正如您从问题标题中推测的那样,我们需要同时解码和显示多个(例如,8个) H.264编码视频(并始终保持它们的同步,但这是另一个问题)。视频通常在25 FPS,分辨率为640x480。
在深入了解问题的症结之前,我将提供一些背景知识。
这个特性需要放入一个相当大的C# 3.5 (WinForms)应用程序中。视频将占用应用程序中的矩形-托管代码需要能够指定每个视频的绘制位置和大小。
我们在H264中获取C#包,并将它们发送到本地H264解码器中,以获取YUV12图像数据。
早期的尝试是将YUV12映像转换为RGB24,BitBlt‘将它们转换为从C#传入本机代码的HWND。虽然功能强大,但所有BitBlt‘’ing都必须发生在UI线程上,这使得它在显示多个视频时(在2.6GHz内核2双上)而陷入困境。
当前的尝试是在启动和加载时,每个cpu核心启动一个线程,在这些线程之间平衡视频的解码/显示。这方面的表现令人印象深刻(我发现观看任务经理比正在显示的视频有趣得多)。就UI而言,它留下了许多有待改进的地方。
我们开始从非UI线程绘制到在UI线程上创建的HWND (例如,停靠在WinForms控件中的面板)的毫秒,由于WinForms的非线程安全性,我们开始获得各种奇怪的行为。这导致我们在本机代码中创建了HWND,并绘制到这些代码中,其中C#提供了应该在屏幕坐标中绘制的矩形。
啊!CanOfWorms.Open()。
问题:当C#应用程序接收到焦点时,它跳到Z顺序的前面,隐藏视频窗口。解决方案:将视频窗口始终放在顶部。
问题:当用户切换到另一个应用程序时,视频窗口仍然在顶部。解决方案:检测C#应用程序的激活和失活,并相应地显示/隐藏视频窗口。
问题:用户说:“我希望我的视频在一个显示器上播放,而我在另一个显示器上编辑一个Word文档!”解决方案:告诉用户闭嘴,这个词无论如何都很糟糕。
问题:我被解雇了。
等等
我想问题的症结在于,我们在一个非UI线程上创建了HWND,我们希望‘模拟’那些嵌入在C#应用程序中的线程。
有什么想法/建议吗?我是不是完全出去吃午饭了?
如果存在,我更愿意采取一种完全不同的方法(这个项目需要大量的学习-中彩票比我在路上的每一步都选择了最好的方法更有可能)。
发布于 2011-05-14 04:25:10
忘掉BitBlt-ing,然后做这个:
此外,我猜您将能够将原始YUV12放入缓冲区,因为VMRenderer能够直接显示它们。
使用DirectShowNet库。
编辑:
是的,BTW,如果视频在相同的“画布”上,你可以使用同样的技术对渲染器,只创建一个大窗口,然后移动解码视频矩形‘手动’,并将它们放入帧缓冲区。
还有另一个编辑:
BitBlts总是序列化的,也就是说它们不能并行运行。
发布于 2011-05-14 00:41:27
我们开始从非UI线程绘制到在UI线程上创建的HWND (例如,停靠在WinForms控件中的面板)的毫秒,由于WinForms的非线程安全性,我们开始获得各种奇怪的行为。这导致我们在本机代码中创建了HWND,并绘制到这些代码中,其中C#提供了应该在屏幕坐标中绘制的矩形。
什么样的古怪行为?如果您的意思是闪烁或绘图延迟,您是否试图锁定面板或任何其他类以进行线程/绘图同步?再次:当您将数据发送到解码器、接收图像、转换图像并使用OnPaint处理程序绘制数据时,具体问题是什么?(设置一个在25 then处循环的不同线程,然后调用thread 1.inValue())
我想问题的症结在于,我们在一个非UI线程上创建了HWND,我们希望‘模拟’那些嵌入在C#应用程序中的线程。
别干那事。尝试在c#应用程序中绘制接收到的数据。通常,我不会重复混合本地代码和c#。在本机代码中使用h264解码器是这里唯一的例外。
使用您的线程解码视频数据包(就像您已经做的那样),然后有一个线程循环并调用无效(如上所述)。然后为每个显示视频的面板设置一个OnPaint处理程序。在这个处理程序中,获取最新的视频图片并绘制它(e.Graphics)。
我希望这有帮助,但也需要更多关于这个问题的信息.
发布于 2011-05-14 04:36:26
我喜欢早些时候发布的DirectShow答案,但我希望包含一个可能更容易实现的额外选项,基于您问题的摘录:
在运行过程中,所有BitBlt‘’ing都必须发生在UI线程上,这使得它在显示多个视频时陷入瘫痪。
我的想法是从这段代码开始,并使用Visual 2010的异步CTP,即目前可用,并包含一个go-live许可证。从这里开始,修改现有代码应该比较简单,以便更好地响应:只需在几个地方添加、等待和异步关键字,其余代码就应该基本不变。
https://stackoverflow.com/questions/5998889
复制相似问题