DirectShow技术介绍(长篇)-4

    技术2022-07-01  77

    3.3. 构建Filter Graph

    3.3.1. 用于构建Graph的组件

         DirectShow提供了一系列用于构建filter graph的组件,包括:

        Filter Graph Manager。这个对象用于控制filter graph,支持IGraphBuilderIMediaControlIMediaEventEx等许多接口。所有的directshow应用程序都需要在某些地方用到这个对象,虽然在有些情况下,是其它的对象为应用程序创建了filter graph manager

        Capture Graph Builder。这个对象为构建filter graph提供附加的方法。它最初是为构建提供视频采集的graph而设计的(这正是它的名字由来),但是对于构建许多另外类型的filter graph也是很有用的。它支持ICaptureGraphBuilder2接口。

        Filter MapperSystem Device Enumerator。这些对象用于查找在系统中注册的或代表硬件驱动的filter

        DVD Graph Builder。这个对象构建用以回放和导航DVDfilter graph。它支持IDvdGraphBuilder接口。基于脚本的应用程序能够使用MSWebDVD ActiveX控件来控制DVD回放。

        Video ControlWinXP提供这个ActiveX控件,用于操纵directshow中的数据和模拟电视。

       

        智能连接(Intelligent Connect

         智能连接这个术语覆盖了一系列Filter Graph Manager用于构建所有或部份filter graph的算法。任何时候,当Filter Graph Manager需要添加filter来完成graph时,它大致做以下几件事情:

         1.如果有一个filter存在于graph中,而且这个filter有至少一个没有连接的input pinFilter Graph Manager试着去试用这个filter

         2.否则,Filter Graph Manager在已注册的filter中寻找连接时可以接受合适的媒体类型的filter。每一个filter都注册有一个Merit值,这个值用以标记哪个filter最容易被Filter Graph Manager选中来完成graphFilter Graph ManagerMerit值的顺序来选择filterMerit值越大,被选中的机会越大。对于每种流类型(如音频、视频、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

         如果你仅仅是想回放一个已知格式的文件,如AVIMPEGWAVMP3,使用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 MuxFile Write filter。不过,也经常有可能让filter graph manager来完成整个graph,比如,你可以通过Render方法来render一个pin进行预览。

       

        应用程序构建整个graph

         在某些场合,你的应用程序需要添加和连接每个filter来构建graph。在这种情况下,你很可能明确地知道哪些filter需要加到graph中去。使用这种方式,应用程序通过调用AddFilter方法添加每个filter,然后枚举filter上的pin,调用ConnectConnectDirect来连接它们。

     

    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方法每一步都搜索一个能够连接到前一个filterfilter,如果新连接上的filter有多个输出pin,数据流能自动分流,搜索直到每个流都被renderer为止。如果Render方法搜索到的filter无法使用,它会返回去尝试另一个filter

         要连接每一个输出pinRender方法做以下工作:

         1.如果pin支持IStreamBuilder接口,Filter Graph ManagerpinIStreamBuilder::Render方法来完成整过程。通过暴露这个接口,pin承担了构建graph剩余部分的全部工作。但是,只有很少数的filter支持此接口。

         2.Filter Graph Manager尝试使用任何在缓存中的filter。在智能连接的整个过程中,filter graph manager可以在早期将filter缓存起来。

         3.如果filter graph包含了任何有未连接的输入pinfilterfilter graph manager会将其当作下一个filter来尝试连接。你可以通过在调用Render之前添加特定的filter来强制让Render方法来尝试这个filter

         4.最后,filter graph manager使用IFilterMapper2::EnumMatchingFilters方法在所有注册的filter中寻找,依据已注册的媒体类型列表来逐个试着匹配输出pin的各个媒体类型(按优先级高低排列)。

         每个已注册的filter都有一个merit值,这是一个用来表示filter优先级的数字,最大优先级越高,EnumMatchingFilters方法返回的filter集依据merit值来排列,直至最小的meritMERIT_DO_NOT_USE+1,它忽略meritMERIT_DO_NOT_USR或更小的filterfilter也通过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中,然后调用filterIFileSourceFilter::Load方法。

         RenderFile方法依据一个文件名来构建一个默认的回放graph,在其内部,RenderFile方法调用AddSourceFilter来定位source filter,并且用Render来构建Graph的余下部分。

         Connect方法将输出pin连接到输入pin上去,这个方法自动添加必要的中间filtergraph中去,使用在Render方法中描述的那一系列算法:

         1.使用IStreamBuilder

         2.尝试被缓存的filter

         3.尝试已添加在graph中的filter

         4.在已注册的filter中寻找


    最新回复(0)