You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FFmpeg.AutoGen C# GPU解码10路以上视频出现异常问题求助

问题成因

  • 硬件限制:AMD Radeon R7 430是入门级显卡,D3D11VA硬解会话上限本身就只有10路左右,超过上限就会触发解码器创建失败错误。
  • 代码资源浪费:现有代码每一路解码线程都单独创建独立的硬件设备上下文,重复占用显卡资源,进一步降低了可支持的并发路数。
  • 资源泄漏:VideoStreamDecoder的Dispose方法没有释放硬件设备上下文的引用,长时间运行会导致显卡资源泄漏,加重资源不足的问题。
  • 代码逻辑漏洞:Main函数中存在C#经典闭包问题,循环变量直接传入线程委托,可能导致多个线程读取到同一个错误的文件路径。
  • 无容错处理:硬件解码器创建失败后没有降级逻辑,代码继续访问空指针直接触发内存访问异常。

修复方案

1. 共享全局硬件设备上下文

整个程序只初始化一次硬件设备上下文,所有解码线程共享该上下文,仅通过增加引用计数的方式关联到每个解码上下文,避免重复创建资源。

2. 补全资源释放逻辑

在解码器销毁时主动释放硬件上下文的引用,避免资源泄漏。

3. 修复闭包问题

循环内部声明临时变量存储每个线程的视频路径,避免多线程读取变量冲突。

4. 增加降级容错逻辑

硬解初始化失败时自动切换为CPU软解,避免程序直接崩溃。

核心修改代码示例

全局硬件上下文初始化

// 全局共享硬件设备缓冲区
private static AVBufferRef* _hwDeviceCtx = null;

// 程序启动时仅调用一次
private static unsafe void InitHardwareDevice(AVHWDeviceType type)
{
    ffmpeg.av_hwdevice_ctx_create(&_hwDeviceCtx, type, null, null, 0).ThrowExceptionIfError();
}

修改VideoStreamDecoder构造函数的硬件关联逻辑

if (HWDeviceType != AVHWDeviceType.AV_HWDEVICE_TYPE_NONE)
{
    // 复用全局硬件上下文,仅增加引用计数
    _pCodecContext->hw_device_ctx = ffmpeg.av_buffer_ref(_hwDeviceCtx);
    if(_pCodecContext->hw_device_ctx == null)
    {
        // 引用失败自动降级为软解
        HWDeviceType = AVHWDeviceType.AV_HWDEVICE_TYPE_NONE;
    }
}

补全Dispose方法的资源释放

public void Dispose()
{
    ffmpeg.av_frame_unref(_pFrame);
    ffmpeg.av_free(_pFrame);

    ffmpeg.av_frame_unref(_receivedFrame);
    ffmpeg.av_free(_receivedFrame);

    ffmpeg.av_packet_unref(_pPacket);
    ffmpeg.av_free(_pPacket);

    // 新增:释放硬件上下文引用
    if (_pCodecContext->hw_device_ctx != null)
    {
        ffmpeg.av_buffer_unref(&_pCodecContext->hw_device_ctx);
    }

    ffmpeg.avcodec_close(_pCodecContext);
    var pFormatContext = _pFormatContext;
    ffmpeg.avformat_close_input(&pFormatContext);
}

修复Main函数的闭包和容错逻辑

private static void Main(string[] args)
{
    // 先初始化全局硬件设备
    InitHardwareDevice(AVHWDeviceType.AV_HWDEVICE_TYPE_D3D11VA);
    
    for (int i = 0; i < 11; i++)
    {
        // 循环内声明临时变量,避免闭包问题
        string threadUrl = @"D:\video\abc" + i + ".mp4";
        new Thread(() =>
        {
            try
            {
                DecodeAllFramesToImages(AVHWDeviceType.AV_HWDEVICE_TYPE_D3D11VA, threadUrl);
            }
            catch(Exception ex)
            {
                Console.WriteLine($"硬解{threadUrl}失败,切换软解:{ex.Message}");
                DecodeAllFramesToImages(AVHWDeviceType.AV_HWDEVICE_TYPE_NONE, threadUrl);
            }
        }).Start();
    }
    
    // 程序退出时释放全局硬件上下文
    ffmpeg.av_buffer_unref(&_hwDeviceCtx);
}

内容的提问来源于stack exchange,提问作者Sang Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:54:02