现在的位置: 首页 > 综合 > 正文

DirectShow编程(3.3)- 关于DirectShow – 构建Filter Graph

2013年04月06日 ⁄ 综合 ⁄ 共 5048字 ⁄ 字号 评论关闭

3.3. 构建Filter Graph
3.3.1. 用于构建Graph的组件

    DirectShow提供了一系列用于构建filter graph的组件,包括:
    *Filter Graph Manager。 这个对象用于控制filter graph,支持IGraphBuilder、IMediaControl和IMediaEventEx等许多接口。所有的directshow应用程序 都需要在某些地方用到这个对象,虽然在有些情况下,是其它的对象为应用程序创建了filter graph manager。
    *Capture Graph Builder。这个对象为构建filter graph提供附加的方法。它最初是为构建提供视频采集的graph而设计的(这正是它的名字由来),但是对于构建许多另外类型的filter graph也是很有用的。它支持ICaptureGraphBuilder2接口。
    *Filter Mapper和System Device Enumerator。这些对象用于查找在系统中注册的或代表硬件驱动的filter。
    *DVD Graph Builder。这个对象构建用以回放和导航DVD的filter graph。它支持IDvdGraphBuilder接口。基于脚本的应用程序能够使用MSWebDVD ActiveX控件来控制DVD回放。
    *Video Control。WinXP提供这个ActiveX控件,用于操纵directshow中的数据和模拟电视。
   
    智能连接(Intelligent Connect)
    智能连接这个术语覆盖了一系列Filter Graph Manager用于构建所有或部份filter graph的算法。任何时候,当Filter Graph Manager需要添加filter来完成graph时,它大致做以下几件事情:
    1.如果有一个filter存在于graph中,而且这个filter有至少一个没有连接的input pin,Filter Graph Manager试着去试用这个filter。
    2.否则,Filter Graph Manager在已注册的filter中寻找连接时可以接受合适的媒体类型的filter。每一个filter都注册有一个Merit值,这个值用以标记 哪个filter最容易被Filter Graph Manager选中来完成graph。Filter Graph Manager按Merit值的顺序来选择filter,Merit值越大,被选中的机会越大。对于每种流类型(如音频、视频、MIDI),默认的 renderer具有一个很高的Merit值,解码器同样是,专用filter具有低Merit值。
    如果Filter Graph Manager因选择的filter不合适而被困,它会返回来尝试另外的filter组合。

3.3.2 Grap构建概述
    创建一个filter graph,从创建一个Filter Graph Manager实例开始:

     IGraphBuilder* pIGB;
     HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
     NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder,(void **)&pIGB);

     Filter Graph Manager支持下列Graph构建方法:
    *IFilterGraph::ConnectDirect,在两个pin之间进行直接连接,如果连接失败,则返回失败
    *IFilterGraph::Connect,连接两个Pin,如果可能的话,直接连接它们,否则,在中间加入其它的filter来完成连接。
    *IGraphBuilder::Render,从某个输出Pin处开始完成余下的graph构建。该方法会自动在输出pin后面添加必须的filter,直到renderer filter为止。
    *IGraphBuilder::RenderFile,构建一个完整的文件回放graph。
    *IGraphBuilder::AddFilter, 将一个filter添加到graph中。它不连接filter,并且在调用此方法前,filter必须已经被创建。创建filter可以是用 CoCreateInstance方法或使用Filter Mapper或系统设备枚举器(System Device Enumerator)。
    这些方法提供了三种构建graph的途径:
    1.filter graph manager构建整个graph
    2.filter graph manager构建部分graph
    3.应用程序构建整个graph
   
    Filter Graph Manager构建整个graph
    如果你仅仅是想回放一个已知格式的文件,如AVI、MPEG、WAV或MP3,使用RenderFile方法。
    RenderFile方法首先寻找注册在系统中能分析源文件的filter,它使用协议名(如http://),文件扩展名或文件的头几个字节来决定选择哪一个源filter。
    Filter Graph Manager使用一个迭代过程来完成余下的graph构建。在这个迭代过程中,它逐个列出filter的输出pin上支持的媒体类型,并搜索哪个已注册 的filter的输入Pin接受该媒体类型。它使用一系列的规则来缩小filter的范围并排定优先顺序:
    *filter类别(category)标识的filter的一般功能
    *媒体类型描述filter能在接受或能输出哪种数据类型
    *merit值决定filter被尝试的次序。如果两个filter具有相同的filter类别并且同时支持相同的输入类型,Filter Graph Manager选择merit值大的那一个。一些filter故意给出一个小merit值是因为它是为特殊用途设计的,仅能由应用程序来将其添加到 graph。
    Filter Graph Manager使用Filter Mapper对象来搜索已注册的filter。
    每个filter被添加时,filter graph manager试着将其与前一个filter的输出pin连接。它们协商决定他们是否能连接,如果能,哪一种媒体类型被用来连接。如果新filter不能 连接,filter graph manager丢弃它并尝试别一个,这个过程一直继续到每个流都被render为止。
   
    Filter Graph Manager构建部分graph
    如果不仅仅是播放一个文件,那么你的应用程序就必须做一些graph的构建工作。比如,一个视频采集应用程序必须先选择一个source filter并将其添加到graph中去。如果你需要将数据写入到一个AVI文件中,你必须添加一个AVI Mux和File Write filter。不过,也经常有可能让filter graph manager来完成整个graph,比如,你可以通过Render方法来render一个pin进行预览。
   
    应用程序构建整个graph
    在某些场合,你的应用程序需要添加和连接每个filter来构建graph。在这种情况下,你很可能明确地知道哪些filter需要加到graph中去。 使用这种方式,应用程序通过调用AddFilter方法添加每个filter,然后枚举filter上的pin,调用Connect或 ConnectDirect来连接它们。

3.3.3. 智能连接
    智能连接是filter graph manager用以构建filter graph的机制。它包含了一系列相关的用以选择filter和将它们添加到graph中去的算法。作为应用程序开发者,你并不需要很具体地了解智能连接 的细节。如果你在构建某个filter graph时遇到问题并希望能解决它,或者你正在编写你自己的filter并希望它能自动地被graph构建,请阅读这一节。
    智能连接涉及以下IGraphBuilder方法:
    *IGraphBuilder::Render
    *IGraphBuilder::AddSourceFilter
    *IGraphBuilder::RenderFile
    *IGraphBuilder::Connect
    Render方法构建一部分graph,它从一个尚未连接的输出pin开始顺着数据流的方向往下,添加必要的filter,起始的那个filter必须已 被添加到了graph中。Render方法每一步都搜索一个能够连接到前一个filter的filter,如果新连接上的filter有多个输出pin, 数据流能自动分流,搜索直到每个流都被renderer为止。如果Render方法搜索到的filter无法使用,它会返回去尝试另一个filter。
    要连接每一个输出pin,Render方法做以下工作:
    1.如果pin支持IStreamBuilder接口,Filter Graph Manager让pin的IStreamBuilder::Render方法来完成整过程。通过暴露这个接口,pin承担了构建graph剩余部分的全部 工作。但是,只有很少数的filter支持此接口。
    2.Filter Graph Manager尝试使用任何在缓存中的filter。在智能连接的整个过程中,filter graph manager可以在早期将filter缓存起来。
    3.如果filter graph包含了任何有未连接的输入pin的filter,filter graph manager会将其当作下一个filter来尝试连接。你可以通过在调用Render之前添加特定的filter来强制让Render方法来尝试这个 filter。
    4.最后,filter graph manager使用IFilterMapper2::EnumMatchingFilters方法在所有注册的filter中寻找,依据已注册的媒体类型列表来逐个试着匹配输出pin的各个媒体类型(按优先级高低排列)。
    每个已注册的filter都有一个merit值,这是一个用来表示filter优先级的数字,最大优先级越高,EnumMatchingFilters方 法返回的filter集依据merit值来排列,直至最小的merit值MERIT_DO_NOT_USE+1,它忽略merit为 MERIT_DO_NOT_USR或更小的filter。filter也通过GUID来归类,类别本身也有merit值, EnumMatchingFilters方法忽略任何merit值为MERIT_DO_NOT_USE或更小的类别,即使在那个类别中的filter有较 高的merit值。
    总结一下,Render方法以下列步骤尝试filter
    1.使用IStreamBuilder
    2.尝试被缓存的filter
    3.尝试已添加在graph中的filter
    4.在已注册的filter中寻找
    AddSourceFilter方法添加一个能render特定文件的source filter。首先,它依据协议名(如Http://)、文件扩展名、或文件头在已注册的filter中寻找匹配的那个。如果此方法定位到了一个合适的 source filter,它便立刻创建一个这个filter的实例,并将其添加到graph中,然后调用filter的IFileSourceFilter:: Load方法。
    RenderFile方法依据一个文件名来构建一个默认的回放graph,在其内部,RenderFile方法调用AddSourceFilter来定位source filter,并且用Render来构建Graph的余下部分。
    Connect方法将输出pin连接到输入pin上去,这个方法自动添加必要的中间filter到graph中去,使用在Render方法中描述的那一系列算法:
    1.使用IStreamBuilder
    2.尝试被缓存的filter
    3.尝试已添加在graph中的filter
    4.在已注册的filter中寻找

 

抱歉!评论已关闭.