梁志斌的专栏

游戏开发 DirectX技术

 
首页>>
关于作者

作  者:梁  志  斌

QQ   :3055720

QQ群:14739153

友情链接
搜索日志
访问计数
最新评论

DirectShow翻译2005--3.8. 插件发布者(Plug-in Distributors)

   DirectX开发2006-9-25 13:38

3.8. 插件发布者(Plug-in Distributors

Plug-in Distributors(PIDs)是扩展filter graph manager的一种方法。一个PIDfilter graph manager在运行时聚合的一个COM对象。应用程序通过filter graph manager来进入PID
filter graph manager被要求查询一个它不支持的接口时,它会搜索注册表项:
HKEY_CLASSES_ROOT\\Interface\\IID\\Distributor
IID
是接口的GUID,如果注册项存在,那么键值便是支持该接口的PID类标识(CLSID)filter graph manager聚合了PID并返回接口指针,应用程序调用这个指针时实际上就是在调用PID,但是这对于应用程序来说是透明的,对于应用程序来说,它就是在filter graph manager上调用这个接口一样。
PID
为应用程序提供了一种简单的控制filter的方法,如通过调用IFilterGraph::EnumFilters方法,PID可以枚举graph中的所有filter并调用这些filter上的方法。
filter graph manager聚合了一个PID时,它查询PIDIDistributorNotify接口,如果PID支持这个接口,filter graph manager用它来通知PID有关graph的状态变化:
*
filter graphrunpausestop状态之间切换时,它调用IDistributorNotify::Run, IDistributorNotify::PauseIDistributorNotify::Stop
*
如果调置了参考时钟,filter graph manager调用IDistributorNotify::SetSyncSource
*
当有filter添加或移除,或pin连接有变化时,filter graph manager调用IDistributorNotify::NotifyGraphChange

当自己定制PID时,自己所创建的COM对象必须支持聚合,并且它所支持的接口是filter graph manager本身所没有的。IDistributorNotify接口是可选的。
如果PIDfilter graph manager上获得一个接口,那它必须立即release这个接口,否则会在COM对象上出现循环引用的参考计数,使得filter graph manager无法被销毁。在filter graph manager上保持一个参考计数是多余的,因为PID的生命期是由filter graph manager控制的。
因为PID是明确指定是被filter graph manager聚合使用的,因此你应该在PID的构造函数中强行检查IUnknown指针是否为NULL,如果为NULL,则返回错误码VFW_E_NEED_OWNER。同时,为了防止其它对象聚合PID,你可以在IUnknown上查询IGraphBuilder接口,如果不行则返回错误。

--奇妙Merit(玩死Media Player

运行GraphEdit,插入Filter,我们可以看到:每个Filter的信息一般包括DisplaynameFilenameMerit、各个Pin以及Pin支持的Mediatype,还有Version等。我们今天就来看一看这个Merit(其他的一些Filter信息大家从它的名字上就可以猜到它的意义)。

要说Merit,肯定要先说Filter Graph Manager使用的智能连接(Intelligent Connect)机制。我们在Filter GraphRender一个Pin,或者Render一个File,然后看到一条自动的“解码”Filter链路就完成了——这就是智能连接机制。执行这个机制的调用方法为:IGraphBuilder::RenderFile, IGraphBuilder::Render, IGraphBuilder::Connect。下面分别对这三个调用方法进行阐述。

RenderFile
:给出一个文件名,首先要找到正确的Source FilterFilter Graph Manager通过查找注册表来决定使用什么Source Filter。在注册表中,一般会有文件扩展名或者特征字节与使用的Source Filter的对应信息。找到Source Filter之后,就从该Source Filter的各个Output pin开始,进行剩下的职能连接过程。这是一个“递归”过程,直到所有的分支都连到一个Renderer Filter上。步骤大致为:
1.
如果Output pin支持IStreamBuilder接口,则把剩下的工作交给IStreamBuilder::Render
2.
使用在内存中缓冲的Filter进行是试连接。
3.
使用在当前Filter Graph中还没有完全连接的Filter进行试连接。(如果你想智能连接使用特定的你想使用的Filter,一种方法是,在开始智能连接之前先把该Filter加入到Filter Graph中。)
4.
使用IFilterMapper2::EnumMatchingFilters搜索注册表。Filter Graph Manager使用Merit值大于MERIT_DO_NOT_USE的所有FilterFilter所在的目录Merit值也应该大于MERIT_DO_NOT_USE)进行试连接。在匹配Mediatype的前提下,Merit值越高,该Filter被使用的概率越高。

Render
这个方法从当前Filter Graph的某个Filter的指定Output pin开始,进行从这个Pin往下的一条支路的智能连接。智能连接的算法与上述RenderFile的类似。

Connect这个方法调用,以欲连接的一对Input pinOutput pin作为参数。首先进行这两个Pin之间的直接连接。如果不能成功连接,则要插入“中介”Filter。这个“中介”Filter的插入过程就是一个智能连接过程,算法与上述的RenderFile类似。

现在我们知道了智能连接是怎么回事。DirectShow的这个机制,很“聪明”,可以方便地使用第三方(非Microsoft公司)开发的Filter。但是,有一个问题,就是如果系统中存在一些“恶意”的Filter,那么这个智能连接机制就会受到严峻的考验。因为这个原因,基于智能连接机制的应用程序(比如Windows Media Player)也会变得不稳定。(笔者并不赞成直接使用DirectShow Editing Services API进行非线性编辑,就是出于这方面的考虑。)

大家可以下载我写的这个测试Filter源代码(http://hqtech.nease.net/Document.htm)其实这是一个CTransFormFilter的空架子,只是这个FilterMerit值非常高(0x8800000),而且支持所有的Mediatype。注册这个Filter后,当有DirectShow应用程序使用智能连接机制时,就会反反复复地使用这个Filter进行试连接,没有休止。如果你使用Windows Media Player播放媒体文件(AVIMPEGWMV等等),应用程序就会阻塞住;即使是RealOne Player,在播放微软格式的文件时也会出现这种现象。

好了,不玩了,别把Media Player弄得太惨,毕竟对我们也没什么好处!:)期望大家已经对这个Merit有了更深的认识。接下去,把这个Filter从你的系统注销吧:regsvr32 /u yourlocalpath\\HQMPKiller.ax

标签集:TAGS:
回复Comments()点击Count()

回复Comments

{commenttime}{commentauthor}

{CommentUrl}
{commentcontent}
 

 Copyright  @  好想~~~~好想 2005.03