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

标签 c++ c opengl ffmpeg gpu

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

我找到了How to set decode pixel format in libavcodec?它解释了如何将 ffmpeg 上的视频解码为特定的像素格式,只要编解码器支持即可。

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

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

最佳答案

  1. 这要看情况。首先,H264只是一个Codec标准。当 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 或 Intel IPP。如果您仍然缺乏性能,那么您可以考虑硬件加速。

关于c++ - 使用 C++ 在 ffmpeg 中解码为特定像素格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57211846/

相关文章:

c++ - 函数指针的模板参数推导(g++ & ICC vs Clang++ & VC++)

c++ - Gtest 和 Gmock - 双重自由或腐败

c - 为指向指针数组的指针赋值

c - C 中的 fread fwrite fseek

c - 在 C 中使用共享内存添加数组元素

opengl - 游戏中的 3D map 渲染

c++ - 从 QTextEdit 中删除空格

c++ - 创建新线程时复制构造函数调用

c++ - OpenGL 和 GLSL : Greyscale texture not showing

c++ - OpenGL 中的淡入淡出场景