我有一个简单的 C++ 应用程序,它使用 FFmpeg 3.2 接收 H264 RTP 流。为了节省 CPU,我使用编解码器 h264_cuvid 进行解码部分。我的 FFmpeg 3.2 是在启用硬件加速的情况下编译的。事实上,如果我执行以下命令:
ffmpeg -hwaccels
我明白了
cuvid
这意味着我的 FFmpeg 设置可以与我的 NVIDIA 卡“对话”。函数 avcodec_decode_video2
提供给我的帧具有像素格式 AV_PIX_FMT_CUDA
。我需要使用 AV_PIX_FMT_RGB
将这些帧转换为新帧。不幸的是,我无法使用众所周知的函数 sws_getContext
和 sws_scale
进行转换,因为不支持像素格式 AV_PIX_FMT_CUDA
。如果我尝试使用 swscale,则会收到错误消息:
“不支持 cuda 作为输入像素格式”
您知道如何将 FFmpeg AVFrame
从 AV_PIX_FMT_CUDA
转换为 AV_PIX_FMT_RGB
吗? (代码片段将不胜感激)
原文由 costef 发布,翻译遵循 CC BY-SA 4.0 许可协议
这是我对最新FFMPeg 4.1版本的硬件解码的理解。以下是我研究源代码后的结论。
首先,我建议从 hw_decode 示例中启发自己:
https://github.com/FFmpeg/FFmpeg/blob/release/4.1/doc/examples/hw_decode.c
使用新的 API,当您使用 avcodec_send_packet() 将数据包发送到编码器时,然后使用 avcodec_receive_frame() 检索解码的帧。
有两种不同的
AVFrame
:一种存储在“CPU”内存(又名 RAM)中的 _软件_,另一种存储在显卡内存中的 _硬件_。从硬件获取 AVFrame
要检索硬件帧并将其转换为可读的、可转换的(使用 swscaler)
AVFrame
,需要使用 av_hwframe_transfer_data() 从图形卡中检索数据。然后看检索帧的像素格式,使用nVidia解码时通常是NV12格式。列出支持的“软件”像素格式
如果要选择像素格式,请注意此处,并非所有 AVPixelFormat 都受支持。 AVHWFramesConstraints 是你的朋友:
最后,一种更快的方法可能是 av_hwframe_transfer_get_formats() 函数,但您至少需要解码一帧。
希望这会有所帮助!