繁体   English   中英

最快的方式解码和同时显示许多H264视频C#

[英]Fastest way to Decode and Display many H264 Videos Simultaneously C#

正如您可能从问题标题中推测的那样,我们需要同时解码和显示多个(例如,8个)H.264编码视频(并保持它们所有时间同步,但这是另一个问题的另一个问题)。 视频通常为25 FPS,分辨率为640x480。

在我解决问题的关键之前,我将提供一些背景知识。

该功能需要融入相当大的C#3.5(WinForms)应用程序。 视频将占用应用程序中的矩形 - 托管代码需要能够指定每个视频的绘制位置以及大小。

我们在C#中获取H264数据包并将其激发到本机H264解码器以获取YUV12图像数据。

早期的尝试包括将YUV12图像转换为RGB24,将BitBlt将它们转换为从C#传递到本机代码的HWND。 功能上,所有BitBlt都必须在UI线程上发生,这导致它在显示多个视频时陷入困境(在2.6 GHZ核心2 duo上)。

当前尝试在启动时旋转每个cpu-core的一个线程并负载平衡跨这些线程的视频解码/显示。 这种表现是令人兴奋的(我发现观看任务管理器比显示的视频更有趣)。 UI方面,它留下了很多不足之处。

我们从非UI线程开始绘制在UI线程(例如,停靠在WinForms控件中的面板)上创建的HWND毫秒,由于WinForms的非线程安全性,我们开始获得各种各样的时髦行为。 这导致我们用本机代码创建HWND并绘制到那些,用C#提供它们应该在屏幕坐标中绘制的矩形。

尔加! CanOfWorms.Open()。

问题:当C#应用程序获得焦点时,它会跳转到Z-Order的前面并隐藏视频窗口。 解决方案:将视频窗口始终放在顶部。

问题:当用户切换到另一个应用程序时,视频窗口仍然位于顶部。 解决方案:检测C#应用程序的激活和停用,并相应地显示/隐藏视频窗口。

问题:用户说:“我希望我在另一台显示器上编辑Word文档时在一台显示器上播放视频!” 解决方案:告诉用户关闭并且Word无论如何都很糟糕。

问题:我被解雇了。

等等

我想问题的关键在于我们在非UI线程上创建了HWND,并且我们想要“模拟”嵌入在C#应用程序中的那些。

有什么想法/建议? 我完全在这里吃午饭吗?

如果存在一个完全不同的方法,我就会采取完全不同的方法(这个项目需要大量的学习 - 赢得彩票的可能性比我在路上的每一步选择最佳方法的可能性更大)。

忘记BitBlt-ing并执行此操作:

  • 对于您希望播放视频的每个窗口,创建一个DirectShow图形并将图形的渲染器附加到该窗口
  • 在图表中的渲染器之前放入samplegrabber过滤器。 它将允许您进行回调,您可以在其中填充缓冲区
  • 而不是blitting,解码到samplegrabber中提供的缓冲区。

另外,我猜你可以将原始YUV12放入缓冲区,因为VMRenderer能够直接显示它们。

使用DirectShowNet库。

编辑:

是的,顺便说一下,如果视频在同一个“画布”上,你可以使用与渲染器相同的技术并只创建一个大窗口,然后“手动”移动解码的视频矩形并将它们放入帧缓冲区缓冲区。

再编辑:

BitBlts总是被序列化,即它们不能并行运行。

我们从非UI线程开始绘制在UI线程(例如,停靠在WinForms控件中的面板)上创建的HWND毫秒,由于WinForms的非线程安全性,我们开始获得各种各样的时髦行为。 这导致我们用本机代码创建HWND并绘制到那些,用C#提供它们应该在屏幕坐标中绘制的矩形。

什么样的时髦行为? 如果你的意思是闪烁或绘制延迟,你是否试图锁定()面板或任何其他类进行线程/绘图同步? 再次:当您将数据发送到解码器,接收图像,转换它然后使用OnPaint处理程序绘制它时,确切的问题是什么。 (设置一个以25fps循环的不同线程,调用panel1.Invalidate()然后)

我想问题的关键在于我们在非UI线程上创建了HWND,并且我们想要“模拟”嵌入在C#应用程序中的那些。

不要那样做。 尝试在c#应用程序中绘制接收的数据。 一般来说,我不会建议混合本机代码和c#。 在本机代码中使用h264解码器是唯一的例外。

使用你的线程解码视频数据包(正如你已经做的那样),然后让一个线程循环并调用Invalidate(如上所述)。 然后为要显示视频的每个面板都有一个OnPaint处理程序。在此处理程序中获取最新的视频图片并绘制它(e.Graphics)。

我希望这有所帮助,但也需要有关该问题的更多信息......

我喜欢之前发布的DirectShow答案,但我希望根据您的问题摘录中包含一个可能更容易实现的附加选项:

功能上,所有BitBlt都必须在UI线程上发生,导致它在显示多个视频时陷入困境

我的想法是从该代码开始,并使用当前可用的 Visual Studio 2010的Async CTP并包含上线许可证。 从那里开始修改现有代码应该是一个相对简单的响应:只需在几个地方添加await和async关键字,其余的代码应该基本保持不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM