正如您可能从问题标题中推测的那样,我们需要同时解码和显示多个(例如八个)H.264 编码视频(并使它们始终保持同步,但这是另一个问题) .视频通常为 25 FPS,分辨率为 640x480。
在触及问题的症结之前,我将提供一些背景知识。
该功能需要嵌入到相当大的 C# 3.5 (WinForms) 应用程序中。视频将占据应用程序中的矩形 - 托管代码需要能够指定每个视频的绘制位置及其大小。
我们在 C# 中获取 H264 数据包并将它们发送到本地 H264 解码器以获取 YUV12 图像数据。
早期的尝试包括将 YUV12 图像转换为 RGB24 并将它们转换为从 C# 传递到 native 代码的 HWND。虽然功能正常,但所有 BitBlt'ing 都必须在 UI 线程上发生,这导致它在显示多个视频时陷入困境(在 2.6 GHZ core 2 duo 上)。
当前的尝试是在启动时启动每个 CPU 核心一个线程,并在这些线程之间平衡视频解码/显示的负载。其性能令人惊叹(我发现观看任务管理器比正在显示的视频有趣得多)。在 UI 方面,它还有很多不足之处。
我们开始从非 UI 线程绘制到在 UI 线程上创建的 HWND(例如,停靠在 WinForms 控件中的面板)的毫秒数后,由于非线程安全性,我们开始出现各种奇怪的行为的WinForms。这导致我们在 native 代码中创建 HWND 并绘制到这些代码,C# 提供了它们应该在屏幕坐标中绘制到的矩形。
啊! CanOfWorms.Open()。
问题:当 C# 应用程序获得焦点时,它会跳到 Z 顺序的前面并隐藏视频窗口。 解决方案:将视频窗口始终放在最前面。
问题:当用户切换到另一个应用程序时,视频窗口仍在顶部。 解决方案:检测 C# 应用程序的激活和停用,并相应地显示/隐藏视频窗口。
问题:用户说,“我希望我的视频在一台显示器上播放,而我在另一台显示器上编辑 Word 文档!” 解决方案:告诉用户闭嘴,反正 Word 很烂。
问题:我被解雇了。
等等
我想问题的症结在于我们在非 UI 线程上创建了 HWND,并且我们想要“模拟”那些嵌入到 C# 应用程序中的内容。
有什么想法/建议吗?我完全出去吃午饭了吗?
如果存在的话,我非常愿意采用完全不同的方法(这个项目需要大量学习 - 中彩票的可能性比我在道路上的每一步都选择最佳方法的可能性更大)。
最佳答案
忘记 BitBlt-ing 并执行此操作:
- 对于您希望播放视频的每个窗口,创建一个 DirectShow 图形并将图形的渲染器附加到该窗口
- 在图中的渲染器之前放置样本采集器过滤器。它将允许您进行回调,您可以在其中填充缓冲区
- 不是 blitting,而是解码到 samplegrabber 中提供的缓冲区。
此外,我想您可以将原始 YUV12 放入缓冲区,因为 VMRenderer 可以直接显示它们。
使用DirectShowNet图书馆。
编辑:
是的,顺便说一句,如果视频在同一个“ Canvas ”上,您可以对渲染器使用相同的技术并只创建一个大窗口,然后“手动”移动解码的视频矩形并将它们放入帧缓冲区缓冲区。
另一个编辑:
BitBlts 总是序列化的,即它们不能并行运行。
关于c# - 同时解码和显示多个 H264 视频的最快方法 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5998889/