VMR9的定制AP

转载 2011年02月22日 11:06:00

http://blog.csdn.net/foruok/archive/2008/07/27/2719724.aspx

 

我要在3D场景中播放电影,或者把电影作为纹理来使用。
    有两个办法,一个是写一个video render,用它来接管filter graph的最终输出,将视频数据拷贝到我们的私有纹理上,然后在合适的时候来使用它(主要是在D3D相关的主循环中)。
    另一个是利用VMR9。VMR9允许我们自己提供Allocator-Presenter,以便完成一些特殊的需要。我们提供自己的A/P,VMR9会调用AP的PresentImage函数来做实际的渲染。我们可以在这里把视频数据旁路到私有纹理中。
    第一个办法比较麻烦,因为视频解码后的格式多种多样,这些你都要自己处理。比如YUV、RGB565、RGB32、YUY2等等,乱七八糟。当我播放输出为YUY2的电影时由于我的video render只接收RGB格式,ActiveMovie窗口弹了出来,大煞风景。
    而用后一种办法,上面这些东西VMR9都帮你处理好了,你所要的只是一个StretchRect调用而已!
    SDK中有个MultiVMR9(Samples/cpp/DirectShow/VMR9/MultiVMR9/MultiPlayer)和GamePlayer(Samples/cpp/DirectShow/VMR9/MultiVMR9/MultiPlayer)的例子,还有一个VMR9Allocator(Samples/C++/DirectShow/VMR9/VMR9Allocator),这几个例子相当有用。GamePlayer构造了一面电影墙,效果很酷。
    不过在这些例子中,D3D是作为视频播放流程的附属而存在。我们现在想反过来,D3D为主,视频播放为副,平常主要是3D渲染,视频播放可以没事儿一边自我娱乐,把解码好的视频拷贝到一个纹理上,当3D场景想起它了,直接拿来用。
    OK,研究一下VMR9Allocator。似乎修改下面几点就可以完成了。
    1. 构造CAllocator时传递D3D和D3DDEVICE给它
    2. 在InitializeDevice函数中,调用AllocateSurfaceHelper 创建文理后再创建一个私有纹理
    3. 在PresentImage中把视频拷贝到私有文理
    4. 提高GetVideoTexture接口,允许D3D部分获取视频纹理用作渲染
    
    确实是这么回事,但是在实际操作时我遇到了一些问题,怎么都解决不了,花了我两天时间!
    1. AllocateSurfaceHelper总是失败
    2. 旁路的视频断断续续
    
    第一个问题,我不需要分配带有VMR9AllocFlag_TextureSurface标记的纹理表面,只需要分配offscreen surfaces。于是我这样做:lpAllocInfo->dwFlags = VMR9AllocFlag_OffscreenSurface;(GamePlayer中也是这么做的,而且没问题),然后调用AllocateSurfaceHelper ,结果总是失败!
    第二个问题更严重,我只能得到有限的几桢图象。

    后来在网上(http://www.gamedev.net/community/forums/topic.asp?topic_id=380264,http://www.gamedev.net/community/forums/topic.asp?topic_id=455515)查到需要用IVMRMixerControl9接口的SetMixingPrefs方法来设置MixerPref9_RenderTargetYUV标记。这样VMR9就不再需要纹理表面而可以只需要离乒表面,同时也不会切换render target。于是我们可以得到完整且连续的视频。不过必须是windows xp sp2以上的系统才可以(http://msdn.microsoft.com/en-us/library/ms788177.aspx)。
    我实验了一下,没有结果,后来发现SetMixingPrefs的调用顺序非常关键!一旦你放错了位置,不但达不到你要的效果,可能会更糟。我遇到了这么几个问题:
    1. 查询不到接口,返回E_NOTIMPL
    2. 得到了接口,设置了MixerPref9_RenderTargetYUV,没什么效果
    3. 设置MixerPref9_RenderTargetYUV后以VMR9AllocFlag_TextureSurface为标记调用AllocateSurfaceHelper 会失败
    
    一头雾水,后来把这个调用放到RenderFile之前,AdviseSurfaceAllocator和AdviseNotify调用之后,这样才可以了。不过在播放rmvb文件时出了莫名其妙的错误(待查)。我现在担心这么做之后,会有一些编码格式在播放时出现问题(假如它的解码filter只输出RGB格式?),这里说明了它的一些限制http://msdn.microsoft.com/en-us/library/ms788177.aspx。
    在我查看GamePlayer及MultVMR9 DLL的源码时,发现它并没有像上面那样做,但依然可以正常使用。可见很有可能是我的一些用法不太正确。

    这里提一下使用VMR9定制A/P的步骤,因为WINDOWS XP默认使用VMR7,我们要自己把VMR9加到filter  graph中。SDK中有相关的文档可以看,按那个办法是可以的,不过比较麻烦。上面提到的几个例子是这么做的:
    1. 创建filter graph
    2. 创建VMR9实例并加入到graph中
    3. 配置VMR9为renderless模式
    4. 查询IVMRSurfaceAllocatorNotify9接口
    5. 创建定制的A/P 
    6. 建议VMR9使用你的A/P(调用IVMRSurfaceAllocatorNotify9::AdviseSurfaceAllocator)
    7. 把allocator notifier提供给你的A/P(AdviseNotify)
    8. 调用RenderFile或者其他方法,让graph智能建立剩余的graph
    9. 查询IMediaControl,IMediaEvent等等接口供后续使用
    10. 删除filter graph时,先停止graph,再断开VMR9的所有pin并将其A/P设为NULL 

    文档在Samples/C++/DirectShow/VMR9/MultiVMR9下面VMR9Multi_Help.htm。我感觉这个文档比directshow的SDK中说的要明白。

相关文章推荐

D3D下使用VMR9播放视频(2)

program VmrAlloc; uses   Windows,   Messages,   untVideo in 'untVideo.pas';const   AppName = 'VmrAll...

Directshow VMR9播放器

  • 2011年02月22日 15:28
  • 54KB
  • 下载

D3D下使用VMR9播放视频文件

随着DX开发包的不断升级,其提供给媒体程序开发人员的接口功能也空前强大起来。本文就D3D下使用VMR9播放视频向初学者谈谈心得。高手请止步(不想让你看了吐血^_^)。        早在DX8时代,...

vmr9例子一看就懂

  • 2012年05月08日 17:31
  • 142KB
  • 下载

cisco无线配置:AIR-AP1242G-E-K9修复与设置手册

AIR-AP1242G-E-K9修复与设置手册 由于本网站上传图片实在太慢。因此,在百度有一篇备份。如果有问题,则去那边:http://hi.baidu.com/lehear/item/901d0f...
  • lehear
  • lehear
  • 2012年08月28日 19:54
  • 3781

the old Video Renderer, the Overlay Mixer, the VMR-7 and the VMR-9 区别!

VMR (Video Mixing Renderer) In terms of both performance and breadth of features, the Video Mixing R...

ap3g1-k9w7-tar.153-3.JD4.tar

  • 2017年05月03日 16:39
  • 10.24MB
  • 下载

ap3g2-k9w8-tar.153-3.JF1.tar

  • 2017年11月08日 10:24
  • 15.02MB
  • 下载

【cocos2dx开发技巧9】自定义控件-定制字体工具

在Cocos2dx中已经有三种字体工具了,几本上能够满足游戏中对字体的要求。其中CCLabelTTF使用系统的ttf文件,CCLabelBMFont字体工具制作,CCLabelAtlas使用贴图,不过...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VMR9的定制AP
举报原因:
原因补充:

(最多只允许输入30个字)