转载:https://www.pudn.com/news/62bc096d405aad31f717648e.html
- 使用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;
}
该方法对有显卡,但不支持硬解加速的机器不适用,比如部分笔记本。
此时该函数也会返回true
,但是解码时候会报 Hardware is lacking required capabilities
这样的错误。
初始化
init_ctx初始化函数主要是对输入的input_ctx和用于解码的decoder_ctx初始化。
GPU解码初始化
说明:
-
深色框为硬件解码与软解解码不一样的地方。
-
av_hwdevice_find_type_by_name()的功能是根据名称查找对应的AVHWDeviceType。
-
AVHWDeviceType表示硬件加速API的类型,比如AV_HWDEVICE_TYPE_CUDA是nvidia提供的加速API.
-
av_hwdevice_find_type_by_name支持的名称如下所示。文章来源:https://www.toymoban.com/news/detail-404639.html
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",
};
- 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设置类型、高和宽。
解码
文章来源地址https://www.toymoban.com/news/detail-404639.html
- 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
到了这里,关于C++使用ffmpeg硬解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!