3

我们软件的一项功能是使用 DirectShow 播放视频。一位用户和我们的内部 QA 发现屏幕捕获实用程序(包括 Captivate、Camstudio 和 AVS4U 的捕获实用程序)无法记录屏幕上播放的视频以及其他屏幕数据。带有视频的区域要么被捕获为黑色矩形,要么只显示第一帧。

如何将 DirectShow 视频渲染到屏幕上,以便视频捕获实用程序可以捕获正在播放的视频以及周围窗口上的所有其他屏幕(正常 GDI 绘制)数据?下面有很多关于这个问题的细节。

笔记:

  • 我无法在我的开发计算机上重现该问题,这使得解决起来有点棘手。我在 OSX 上使用在 VMWare Fusion 3 中运行的 Windows 7,使用截图工具和通过 Print Screen 键捕获静止图像,并使用 CamStudio 和 AVS4U 捕获屏幕视频,一切正常。但是,一名客户和两名 QA 人员都可以在本机运行 Windows 7 时重现该问题。我的 VM 及其 PC 上的所有驱动程序等都是最新的。我没有受影响客户的确切硬件和驱动程序信息,但我可以为内部 QA 人员的计算机获取它。

  • 我的工作理论是视频正在使用覆盖或其他基于视频硬件的机制完全绕过 GDI 进行渲染,因此捕获实用程序永远不会看到视频数据,并且由于某种原因,这不是使用的机制DirectShow 在我的机器上运行。我不确定如何检查。图形管理器不会发送EC_VMR_RENDERDEVICE_SET让我查看正在使用哪种机制(覆盖、视频内存或系统内存)的事件。

  • 解决它的一个想法是侦听每帧发送的事件通知,然后用于IBasicVideo::GetCurrentImage获取当前帧图像(和position)并使用 GDI 将其渲染到屏幕上。但是,似乎没有每帧发送任何事件。具体来说,我看到的唯一事件是:

    • 打开视频窗口并显示暂停的静止视频:EC_VMR_RENDERDEVICE_SET

    • 踩视频:EC_PAUSEDEC_STEP_COMPLETE

    • 播放视频:什么都没有 - 它播放时不会触发任何事件。

  • 另一个想法是插入一个新的图形过滤器项,它捕获每一帧的帧,并使用 GDI 将其绘制到屏幕上。我不知道这是否是一个好方法,或者从哪里开始编写这样的项目。如果这是最好的解决方案,一个很好的答案将有一个简短的代码示例,展示如何编写一个来获取帧数据。(虽然我不知道这是否是最好的解决方案,虽然我想我只需要得到“一个”解决方案,而不是最好的。当然,如果可能的话,我更喜欢“正确的方式”,无论正确的方式是什么。 )

  • 另一个想法是编写替代视频渲染器,尽管 MSDN 在该页面上建议使用视频混合渲染器或增强型视频渲染器。VMR 似乎是基于 DirectX 的,所以如果我关于问题的理论是正确的,那么这样做可能无济于事,除非我使用 D3DX 之类的东西来获取表面数据作为图像(?),并且 EVR 仅适用于 Vista 及更高版本. 编写 AVR 似乎相当复杂,我不能 100% 确定它是否能帮助我实现我所需要的,我想在写之前做到这一点。

  • 视频当前通过IVideoWindow呈现,而不是IVMRWindowlessControlIVMRWindowlessControl9。如果这些接口/实现之一有什么可以帮助它工作的话,我当然可以改变它。

  • 代码是用原生 C++ 编写的,而不是 .Net,尽管任何语言的解决方案都很棒。支持的最低客户端是 Windows XP。

我将不胜感激有关该问题的任何建议,并且一个很好的答案将提供一个小代码示例(最好有一些已知的工作可以使用。)

我还应该指出,抓取视频的屏幕截图是完全合法的。我们的软件是科学可视化和分析软件,我们的用户播放的视频是他们自己的录音。我们的软件可以显示此视频以及从其他来源记录的非视频数据。屏幕捕获工具用于录制演示、演示、有关研究的在线视频等 - 即捕获与屏幕上周围的内容结合播放的视频的正当理由。

谢谢您的帮助!

4

1 回答 1

2

只是在渲染视频时避免使用叠加层。有几种方法:

于 2012-11-09T00:33:24.603 回答