使用C++解码为ffmpeg中的特定像素格式

Decoding to specific pixel format in ffmpeg with C++

本文关键字:像素 格式 C++ 解码 ffmpeg 使用      更新时间:2023-10-16

我需要解码视频,但我的视频播放器仅支持 RGB8 像素格式。所以我正在研究如何在 GPU 中进行像素格式转换,最好是在解码过程中,但如果不可能,则在解码过程之后。

我找到了如何在libavcodec中设置解码像素格式?它解释了如何将ffmpeg上的视频解码为特定的像素格式,只要它由编解码器支持。

基本上,get_format()是一个函数,它从编解码器支持的像素格式列表中选择解码视频的像素格式。我的问题是:

  1. 此支持的编解码器输出格式列表是否适用于所有计算机?例如,如果我的编解码器是用于 H264,那么它将始终在所有计算机上为我提供相同的列表?(假设所有计算机的 ffmpeg 版本相同)
  2. 如果我选择这些受支持的像素格式中的任何一种,像素格式转换是否始终在 GPU 中进行?
  3. 如果某些像素格式转换不会在 GPU 中发生,那么我的问题是:sws_scale()函数会在 GPU 或 CPU 中转换吗?
  1. 这取决于。首先,H264只是一个编解码器标准。当libx264或openh264正在实现此标准时,您可以猜测每个实现都支持不同的格式。但是,让我们假设(正如您在问题中所做的那样)您在不同的机器上使用相同的实现,那么是的,可能仍然存在不同机器支持不同格式的情况。以H264_AMF为例。您需要 AMD 显卡才能使用编解码器,支持的格式也取决于您的显卡。
  2. 解码通常会在 CPU 上进行,除非您明确指定硬件解码器。有关硬件解码,请参阅此示例:https://github.com/FFmpeg/FFmpeg/blob/release/4.1/doc/examples/hw_decode.c 使用
    硬件解码时,您严重依赖计算机。每个硬件编码器将输出自己的(专有)帧格式,例如NV12用于NVIDA显卡。现在是棘手的部分。编码的帧将保留在您的 GPU 内存中,这意味着您可以重复使用 avframe 缓冲区来使用 OpenCL/GL 进行像素转换。但是在使用不同的框架时实现 GPU 零拷贝并不是那么容易,我没有足够的知识来帮助你。所以我要做的是通过av_hwframe_transfer_data从GPU下载解码的帧,如示例中所示。 从这一点开始,如果您使用硬件或软件解码,它并没有太大区别。
  3. 据我所知,sws_scale没有使用硬件加速。因为它不接受"hwframes"。如果你想在硬件级别进行颜色转换,你可能想看看OpenCV,你可以在那里使用GPUMat然后上传你的帧,调用cvtColor并再次下载。

一些一般评论:
几乎任何图像操作缩放等在您的 GPU 上都更快,但上传和下载数据可能需要很长时间。对于单个操作,通常不值得使用 GPU。
在您的情况下,我会首先尝试使用 CPU 解码和 CPU 颜色转换。只需确保使用良好的线程化和矢量化算法,如 OpenCV 或英特尔 IPP。如果您仍然缺乏性能,那么您可以考虑硬件加速。