使用C++解码为ffmpeg中的特定像素格式
Decoding to specific pixel format in ffmpeg with C++
我需要解码视频,但我的视频播放器仅支持 RGB8 像素格式。所以我正在研究如何在 GPU 中进行像素格式转换,最好是在解码过程中,但如果不可能,则在解码过程之后。
我找到了如何在libavcodec中设置解码像素格式?它解释了如何将ffmpeg上的视频解码为特定的像素格式,只要它由编解码器支持。
基本上,get_format()
是一个函数,它从编解码器支持的像素格式列表中选择解码视频的像素格式。我的问题是:
- 此支持的编解码器输出格式列表是否适用于所有计算机?例如,如果我的编解码器是用于 H264,那么它将始终在所有计算机上为我提供相同的列表?(假设所有计算机的 ffmpeg 版本相同)
- 如果我选择这些受支持的像素格式中的任何一种,像素格式转换是否始终在 GPU 中进行?
- 如果某些像素格式转换不会在 GPU 中发生,那么我的问题是:
sws_scale()
函数会在 GPU 或 CPU 中转换吗?
- 这取决于。首先,H264只是一个编解码器标准。当libx264或openh264正在实现此标准时,您可以猜测每个实现都支持不同的格式。但是,让我们假设(正如您在问题中所做的那样)您在不同的机器上使用相同的实现,那么是的,可能仍然存在不同机器支持不同格式的情况。以H264_AMF为例。您需要 AMD 显卡才能使用编解码器,支持的格式也取决于您的显卡。
- 解码通常会在 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下载解码的帧,如示例中所示。 从这一点开始,如果您使用硬件或软件解码,它并没有太大区别。 - 据我所知,
sws_scale
没有使用硬件加速。因为它不接受"hwframes"。如果你想在硬件级别进行颜色转换,你可能想看看OpenCV,你可以在那里使用GPUMat
然后上传你的帧,调用cvtColor
并再次下载。
一些一般评论:
几乎任何图像操作缩放等在您的 GPU 上都更快,但上传和下载数据可能需要很长时间。对于单个操作,通常不值得使用 GPU。
在您的情况下,我会首先尝试使用 CPU 解码和 CPU 颜色转换。只需确保使用良好的线程化和矢量化算法,如 OpenCV 或英特尔 IPP。如果您仍然缺乏性能,那么您可以考虑硬件加速。
相关文章:
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何在24位SDL_Surface上设置像素的颜色
- 如何从SDL_Surface获取特定像素的颜色
- 为什么更改视频格式会更改其像素值?
- 使用C++解码为ffmpeg中的特定像素格式
- 图像的像素格式始终返回 32 位
- glew和glut您如何激活像素格式
- 未知像素格式错误SDL2
- 如何选择DirectX像素格式
- 如何使用 Windows API 获取像素格式布局
- OpenGL从4*浮点格式(C++)上传像素数据
- 通过 C/C++ 使用 JPEG 像素格式在 v4l2 中设置/获取相机 JPEG 压缩质量
- 将用于绘制为位图的像素格式更改
- 以在编译时和运行时都可用的方式描述C++像素格式信息
- 奇怪的SDL_Surface->格式->字节每像素值
- 如何在libavcodec中设置解码像素格式
- SDL2 纹理的像素格式和表面颜色遮罩
- 将 QImage 转换为YUV420P像素格式
- OpenGL上下文创建从不选择像素格式