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

时间:2019-07-26 01:01:26

标签: c++ c opengl ffmpeg gpu

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

我发现Angular's upgrade guide解释了如何将ffmpeg上的视频解码为特定的像素格式,只要它受编解码器支持即可。

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

  1. 此受支持的编解码器输出格式列表是否对所有计算机都相同?例如,如果我的编解码器适用于H264,那么它将在所有计算机上始终显示相同的列表吗? (假设所有计算机的ffmpeg版本相同)
  2. 如果我选择这些受支持的像素格式中的任何一种,像素格式转换是否将始终在GPU中进行?
  3. 如果某些像素格式转换不会在GPU中发生,那么我的问题是:sws_scale()函数是否在GPU或CPU中进行转换?

1 个答案:

答案 0 :(得分:0)

  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没有使用硬件加速。由于它不接受“ hwframe”。如果您想在硬件级别上进行颜色转换,则可能想看一下OpenCV,您可以在那里使用GPUMat,然后上传您的框架,调用cvtColor,然后再次下载。

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