如何通过屏幕录像机捕获基于DirectShow的视频?

时间:2012-11-08 18:07:11

标签: video directx directshow video-capture

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

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

备注:

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

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

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

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

    • 改编视频:EC_PAUSEDEC_STEP_COMPLETE

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

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

  • 另一个想法是编写alternative video renderer,但MSDN建议在该页面上使用视频混合渲染器或增强视频渲染器。 VMR似乎是基于DirectX的,所以如果我对这个问题的理论是正确的,这可能无济于事,除非我使用类似D3DX的东西将表面数据作为图像(?),而EVR只是Vista及以上。写一个AVR似乎相当复杂,我不是百分之百确定它是否能帮助我实现我需要的东西,我想在写一个之前。

  • 视频目前通过IVideoWindow呈现,而不是IVMRWindowlessControlIVMRWindowlessControl9。我当然可以改变这个,如果有一些关于这些接口/实现的东西可以帮助它工作。

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

我将非常感谢您对此问题的任何建议,并且一个很好的答案将提供一个小代码示例(让某些已知的工作起作用会很好。)

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

谢谢你的帮助!

1 个答案:

答案 0 :(得分:2)

在渲染视频时,请避免使用叠加层。有几种方法可以: