如何使用 GPU 高效地渲染和处理视频流?
Posted
技术标签:
【中文标题】如何使用 GPU 高效地渲染和处理视频流?【英文标题】:How to efficiently render and process video streams using GPU? 【发布时间】:2010-10-03 14:05:54 【问题描述】:我计划开发一个使用 C++、Qt 和 OpenGL 进行实时视频操作的工具。视频叠加不是一个选项,因为着色器应该用于帧处理。目前我想象以下步骤顺序:
-
解码视频 (CPU)
对其进行预处理(可选,CPU)
将其传输到视频内存(使用 DMA 的 GPU)
使用顶点和片段着色器 (GPU) 进一步处理它
渲染它(GPU)
我正在寻找一些一般性建议来解释此处可以使用哪些扩展或技术。是否有充分的理由使用 Direct3D?
【问题讨论】:
【参考方案1】:首先,在 PC 上没有明确的方式来使用 DMA。驱动程序可能使用它,或者可能使用其他东西。
无论如何,第 3 步将是“更改显卡上的纹理数据”。在 OpenGL 中,它是 PBO(像素缓冲区对象)扩展或旧的 glTexSubImage* 函数。在 D3D9 中,它是纹理上的 LockRect 或其他方式(例如,划痕纹理上的 LockRect,然后 blit 到 GPU 纹理中)。其中任何一个都可能使用 DMA,但您不能确定。
然后数据在纹理中。您可以使用一些着色器将其渲染到屏幕上(例如进行 YCbCr 转换),或渲染到其他纹理中以进行更复杂的处理效果(例如模糊/发光/...)。
从某种意义上说,使用 Direct3D 更容易,因为有明确定义的“浪费方式”做事。在 OpenGL 中,有很多选项可以做任何事情,您必须以某种方式找出哪些是快速的(有时不同平台或硬件上的快速路径不同)。
【讨论】:
【参考方案2】:如果您使用 linux,NVIDIA 最新的 180.xx 系列驱动程序通过 VDPAU api(视频解码和演示)增加了对视频解码的支持。 mplayer、vlc、ffmpeg、mythtv等很多大项目都集成了这个api。我不知道所有细节,但它们为许多编解码器提供了 api,包括常见的子操作和比特流操作。
在直接使用 CUDA(我假设 VDPAU 可能会使用)之前,我会先看看这里
【讨论】:
【参考方案3】:为了将帧数据从 cpu 传输到 gpu,您可能需要查看 PBOs。也检查this。
此外,如果您仍然使用着色器,则可以通过在片段着色器中进行色彩空间转换(YCbCr 到 RGB)来减轻 CPU 负担。
“进一步处理”和“渲染”步骤通常几乎相同,在着色器中做一些很酷的事情并将其混合到帧缓冲区中。如果你想混搭视频和不同的效果,FBOs 也很有用。
【讨论】:
【参考方案4】:作为替代方案,您可以查看一些用于执行通用 GPU 编程 (GPGPU) 的不同语言,例如 NVIDIA 的 CUDA 或 ATI 的 Stream SDK。不过,根据您的选择,您可以将自己限制在一个品牌的 GPU 上。使用这些语言的原因是为了在更接近于普通高级编程的抽象级别上工作,而不是使用着色器。
我对你想做的事情没有经验,所以我不能说着色器是否真的更适合这项工作,但你可以考虑看看。不得不说,算法设计与普通代码还是有些不同的,需要花点功夫才能掌握(我只用过CUDA,但它们似乎都使用了类似的抽象)。
我想如果你在着色器工作方面有相当多的经验,那么你可能不值得为学习一个新平台而烦恼。
【讨论】:
【参考方案5】:以下步骤应该可以做到:
将视频解码为 YUV
这通常是解码器库所做的。
作为纹理加载到 OpenGL 中
将 YUV 转换为 RGB
由于您不想使用叠加层,因此您必须手动转换。 Here 是使用着色器的示例。
将转换后的纹理放在四边形上并渲染到屏幕上
【讨论】:
以上是关于如何使用 GPU 高效地渲染和处理视频流?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过优化 Python 中的 GPU 使用率将视频处理速度提高 5 倍(教程含源码)