FFmpeg4入门系列教程11:CUDA硬解并使用Qt播放视频(YUV420SP转RGB32)

索引地址:系列教程索引地址

上一篇:FFmpeg4入门系列教程10:软解并使用QML播放视频(YUV420P->OpenGL)

之前几篇文章介绍了使用CPU+FFmpeg解码视频并显示在QWidget/QML/QOpenGL上,本文介绍FFmpeg使用硬件解码,主要是使用CUDA。

首先看一下解码流程,主要流程和CPU解码差不多。

flow

硬解解码包括CUDA/QSV/DRM/VAAPI/VDPAU等等,CUDA很好理解,你主要装了NVIDIA显卡就可以使用;QSV是Intel CPU自带的解码器,但是现在大部分CPU不带QSV支持(便宜),而且配置也不方便,所以就忽略了。

那么就先选一个:

1
2
3
4
5
6
7
8
9
type = av_hwdevice_find_type_by_name("cuda");
if (type == AV_HWDEVICE_TYPE_NONE) {
fprintf(stderr, "Device type %s is not supported.\n", "h264_cuvid");
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 -1;
}

查找名为CUDA的硬件设备,如果没有找到,就输出当前使用的FFmpeg支持的硬件名称。

硬件有了,接下来就是解码器。不同的编码格式对应不同的解码器,比如说H264/H265/VP8等等,以h264为例,此编码器可能支持CUDA硬解也可能不支持(比如说编译的时候没有设置CUDA和硬解支持,那么此时的解码器就不可能支持硬解)。我们需要确定一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//获取支持该decoder的hw配置型
for (i = 0;; i++) {
const AVCodecHWConfig *config = avcodec_get_hw_config(videoCodec, i);
if (!config) {
fprintf(stderr, "Decoder %s does not support device type %s.\n",
videoCodec->name, av_hwdevice_get_type_name(type));
return -1;
}
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
config->device_type == type) {
hw_pix_fmt = config->pix_fmt;
break;
}
}

在打开有效解码器之前需要激活硬解:

1
2
3
4
5
6
7
8
9
10
11
12
13
int FFmpegVideo::hw_decoder_init(AVCodecContext *ctx, const AVHWDeviceType type)
{
int err = 0;

if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type,
NULL, NULL, 0)) < 0) {
fprintf(stderr, "Failed to create specified HW device.\n");
return err;
}
ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);

return err;
}

调用hw_decoder_init来创建硬件上下文。

1
2
if (hw_decoder_init(videoCodecCtx, type) < 0)
return -1;

其他的流程代码和软解一样。

QWidget/QML/QOpenGL部分代码和之前的一样,毕竟只是将解码后的数据送往不同的组件显示。

资源占用如下图:

resource

源码在Github11.1video_decode_by_cuda_display_by_qwidget11.2video_decode_by_cuda_display_by_qopengl11.3video_decode_by_cuda_display_by_qml下。

下一篇:FFmpeg4入门系列教程12:本地yuv文件编码为h264