• 使用ffmpeg解码video模块,支持3种解码:cpu解码、amd64平台的cuda解码和NX平台的Nvmpi解码


    仓库代码:https://gitee.com/liudegui/ffmpeg_decode_video

    ffmpeg_decode_video

    • 使用ffmpeg解码video模块,支持3种解码:cpu解码、amd64平台的cuda解码和NX平台的Nvmpi解码
    • 封装库只依赖ffmpeg,测试程序中用到了OpenCV,可用于将帧送往opencv检测程序

    ref:

    • https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/hw_decode.c
    • ref: https://github.com/chinahbcq/ffmpeg_hw_decode

    概要

    该库希望支持能在一份代码中支持CUDA GPU和CPU模式的切换,也可以选择是否只解码关键帧。主要设计思想如下:

    判断是否支持CUDA GPU解码

    bool support_hwdevice()
    {
        AVHWDeviceType type;
        type = av_hwdevice_find_type_by_name(s_hwdevice_name);
        if (type == AV_HWDEVICE_TYPE_NONE)
        {
            fprintf(stderr, "Device type %s is not supported.\n", s_hwdevice_name);
            fprintf(stderr, "Available device types:");
            while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
                fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
            fprintf(stderr, "\n");
            return false;
        }
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    该方法对有显卡,但不支持硬解加速的机器不适用,比如部分笔记本。

    此时该函数也会返回true,但是解码时候会报 Hardware is lacking required capabilities这样的错误。

    初始化

    init_ctx初始化函数主要是对输入的input_ctx和用于解码的decoder_ctx初始化。

    GPU解码初始化

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C1ezkPzY-1656490229117)(./初始化.png)]
    说明:

    • 深色框为硬件解码与软解解码不一样的地方。

    • av_hwdevice_find_type_by_name()的功能是根据名称查找对应的AVHWDeviceType。

    • AVHWDeviceType表示硬件加速API的类型,比如AV_HWDEVICE_TYPE_CUDA是nvidia提供的加速API.

    • av_hwdevice_find_type_by_name支持的名称如下所示。

    static const char *const hw_type_names[] = {
        [AV_HWDEVICE_TYPE_CUDA]   = "cuda",
        [AV_HWDEVICE_TYPE_DRM]    = "drm",
        [AV_HWDEVICE_TYPE_DXVA2]  = "dxva2",
        [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
        [AV_HWDEVICE_TYPE_OPENCL] = "opencl",
        [AV_HWDEVICE_TYPE_QSV]    = "qsv",
        [AV_HWDEVICE_TYPE_VAAPI]  = "vaapi",
        [AV_HWDEVICE_TYPE_VDPAU]  = "vdpau",
        [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox",
        [AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec",
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • avcodec_get_hw_config:用于获取编解码器支持的硬件配置AVCodecHWConfig。这里用于获取硬件支持的像素格式。
    • av_hwdevice_ctx_create:av_hwdevice_ctx_create创建硬件设备相关的上下文信息AVHWDeviceContext和对硬件设备进行初始化。
    • decoder_ctx->get_format = get_hw_format ,get_hw_format是向AVCodecContext注册的一个函数,用于协商支持的像素格式。

    CPU解码初始化

    • cpu解码初始化与GPU不一样的是,调用avcodec_find_decoder寻找合适的decoder,并给decoder context设置类型、高和宽。

    解码

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eA7nyoOy-1656490229118)(./解码.png)]

    • GPU解码与CPU解码的一个区别是,GPU需要调用av_hwframe_transfer_data,该函数拷贝GPU到CPU。
    • av_hwframe_transfer_data:拷贝数据到一个硬件的surface,或者从一个硬件surface拷贝数据,也就是GPU和CPU之间数据拷贝。这里用于GPU拷贝到CPU。

    格式

    • GPU解码后数据格式默认类型是从硬件读取,CUDA可能是AV_PIX_FMT_NV12;而CPU解码后的数据一般是YUV数据,比如AV_PIX_FMT_YUV420P。

    参考

    // ref:https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/hw_decode.c
    // ref: https://github.com/chinahbcq/ffmpeg_hw_decode
    // ref: https://www.jianshu.com/p/3ea9ef713211
    
    • 1
    • 2
    • 3
  • 相关阅读:
    OpenCV图像处理——目标追踪
    【Nodejs】使用robotjs控制鼠标键盘 自动点击屏幕上指定位置的图标 实现连接wifi等操作
    Docker
    【Git】有人瞎动你代码怎么办?学会git reset、 revert轻松解决
    Apollo 应用与源码分析:Monitor监控-硬件监控-CPU、磁盘、内存资源监控逻辑源码分析
    如何阅读外文文献?文献阅读七步法
    Matryoshka Doll(思维dp)
    对比不同测量矩阵的重构概率
    一站到底,Spring+SpringBoot+SpringCloud全攻略,是真的全面
    华为OD机试 - 单词接龙 - 数据结构map、list (Java 2023 B卷 100分)
  • 原文地址:https://blog.csdn.net/stallion5632/article/details/125524086