none
DXshow开发 怎么创建自己的filter Graph manager结构 RRS feed

  • 问题

  • 一个视频文件结构如图,

    有的视频文件我直接用Renderfile方法,播放的时候视频不流畅,会花屏,但是直接用MediaPlayer或者GraphEdit播放就很流畅。是不是在调用RenderFile函数的时候系统选择的Filter不正确?那我要怎么建立LAV Splitter、Mpeg4S Decoder DMO、MP3 Decoder DMO、Video renderer等Filter,并把他们连接起来? 


    
    
    
    
    2014年2月12日 6:56

答案

  • 你好:

    “是不是在调用RenderFile函数的时候系统选择的Filter不正确?”

    根据你的陈述“有的视频文件我直接用Renderfile方法,播放的时候视频不流畅,会花屏”,所以我觉得如果是选择的Filter不正确,产生的结果就不是有的视频文件播放不流畅花屏了。我建议你看下下面的这个链接里的内容:http://bbs.csdn.net/topics/350260945

    如果只需要播放单个媒体文件,可以使用IGraphBuilder::RenderFile方法渲染媒体文件。
    如果针对应用需要,使用特定的Source Filter后,可以使用IGraphBuilder::Render方法实现对GraphBuilder中输出Pin进行渲染。
    如果需要对渲染流程进行高级控的话,那就需要手动添加Filter并进行手动连接。
    注意要实现播放,一个GraphBuilder中到少要有一个Source filter和一个Renderer。

    下面是具体方法简单介绍:
    1、创建GraphBuilder和Filter
       IGraphBuilder *pBuilter;
       IBaseFilter *pFilter;
       hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
        IID_IGraphBuilder, (void **)&m_pGraph );   
       hr = CoCreateInstance( IID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, 
                              IID_IBaseFilter, (void **)&pFilter );
    2、将Filter添加到GraphBuilder
       pBuilder->AddFilter(pFilter);
    3、取得两个Filter的输入输出Pin

    HRESULT GetUnconnectedPin( IBaseFilter *pFilter, // Pointer to the filter.
     PIN_DIRECTION PinDir, // Direction of the pin to find.
     IPin **ppPin ) // Receives a pointer to the pin.
     {
         *ppPin = 0;
    
         IPin *pPin = 0;
         IEnumPins *pEnum = 0;
         HRESULT hr = pFilter->EnumPins(&pEnum);
         if (FAILED(hr))
         {
             return hr;
         }
     hr = pEnum->Reset();
         while ( ( hr = pEnum->Next(1, &pPin, NULL) ) == S_OK)
         {
             PIN_DIRECTION ThisPinDir;
             pPin->QueryDirection(&ThisPinDir);
             if (ThisPinDir == PinDir)
             {
                 IPin *pTmp = 0;
                 hr = pPin->ConnectedTo(&pTmp);
                 if (SUCCEEDED(hr))  // Already connected, not the pin we want.
                 {
                     pTmp->Release();
                 }
                 else  // Unconnected, this is the pin we want.
                 {
                     pEnum->Release();
                     *ppPin = pPin;
                     return S_OK;
                 }
             }
             pPin->Release();
         }
         pEnum->Release();
         // Did not find a matching pin.
         return E_FAIL;
     }

    4、连接两个Filter
       pBuilder->Connect(ppinIn, ppinOut);
    请参照以上代码再次检查下你的代码。如果不是代码的问题的话,我建议你到一般性问题讨论区这个论坛提问。

    谢谢!


    2014年2月13日 5:42
    版主
  • 你好:

    感谢你的反馈!

    具体请参照下面链接的内容,里面详细说明了怎么开发自己的Filter。

    http://www.vckbase.com/index.php/wv/966.html

    2014年2月13日 9:50
    版主

全部回复

  • 你好:

    “是不是在调用RenderFile函数的时候系统选择的Filter不正确?”

    根据你的陈述“有的视频文件我直接用Renderfile方法,播放的时候视频不流畅,会花屏”,所以我觉得如果是选择的Filter不正确,产生的结果就不是有的视频文件播放不流畅花屏了。我建议你看下下面的这个链接里的内容:http://bbs.csdn.net/topics/350260945

    如果只需要播放单个媒体文件,可以使用IGraphBuilder::RenderFile方法渲染媒体文件。
    如果针对应用需要,使用特定的Source Filter后,可以使用IGraphBuilder::Render方法实现对GraphBuilder中输出Pin进行渲染。
    如果需要对渲染流程进行高级控的话,那就需要手动添加Filter并进行手动连接。
    注意要实现播放,一个GraphBuilder中到少要有一个Source filter和一个Renderer。

    下面是具体方法简单介绍:
    1、创建GraphBuilder和Filter
       IGraphBuilder *pBuilter;
       IBaseFilter *pFilter;
       hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
        IID_IGraphBuilder, (void **)&m_pGraph );   
       hr = CoCreateInstance( IID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, 
                              IID_IBaseFilter, (void **)&pFilter );
    2、将Filter添加到GraphBuilder
       pBuilder->AddFilter(pFilter);
    3、取得两个Filter的输入输出Pin

    HRESULT GetUnconnectedPin( IBaseFilter *pFilter, // Pointer to the filter.
     PIN_DIRECTION PinDir, // Direction of the pin to find.
     IPin **ppPin ) // Receives a pointer to the pin.
     {
         *ppPin = 0;
    
         IPin *pPin = 0;
         IEnumPins *pEnum = 0;
         HRESULT hr = pFilter->EnumPins(&pEnum);
         if (FAILED(hr))
         {
             return hr;
         }
     hr = pEnum->Reset();
         while ( ( hr = pEnum->Next(1, &pPin, NULL) ) == S_OK)
         {
             PIN_DIRECTION ThisPinDir;
             pPin->QueryDirection(&ThisPinDir);
             if (ThisPinDir == PinDir)
             {
                 IPin *pTmp = 0;
                 hr = pPin->ConnectedTo(&pTmp);
                 if (SUCCEEDED(hr))  // Already connected, not the pin we want.
                 {
                     pTmp->Release();
                 }
                 else  // Unconnected, this is the pin we want.
                 {
                     pEnum->Release();
                     *ppPin = pPin;
                     return S_OK;
                 }
             }
             pPin->Release();
         }
         pEnum->Release();
         // Did not find a matching pin.
         return E_FAIL;
     }

    4、连接两个Filter
       pBuilder->Connect(ppinIn, ppinOut);
    请参照以上代码再次检查下你的代码。如果不是代码的问题的话,我建议你到一般性问题讨论区这个论坛提问。

    谢谢!


    2014年2月13日 5:42
    版主
  • 谢谢你的回答,对我很有帮助!我还有一点不明白,就是创建那个Filter的类型是通过CoCreateInstance()这个函数中的第一个参数指定的(如CLSID_FilterGraph,CLSID_VideoRenderer等是一个GUID值)但是我查看了定义这个类型的文件,并没有发现有Mpeg4s 或者MP3 Decoder DMO等的Filter,也就是并不是所有的GrapEdit里的Filter,VS定义的文件里都有,那么现在我要怎么创建这些(如Mpeg4s)Filters?
    2014年2月13日 7:12
  • 你好:

    感谢你的反馈!

    具体请参照下面链接的内容,里面详细说明了怎么开发自己的Filter。

    http://www.vckbase.com/index.php/wv/966.html

    2014年2月13日 9:50
    版主
  • 我查看了你给的链接和代码,收获不少。如你所说:要实现播放,一个GraphBuilder中到少要有一个Source filter和一个Renderer。但是我在向GraphBuilder中添加Source filter的时候遇到了问题:IGraphBuilde::AddFilter和AddSourceFilter的参数都是IbaseFilter类型的,不是IFileSourceFilter类型的啊。我尝试转换也转换不成功。

    怎么才能把sourceFilter添加进IGraphBuilder?
    如果是只能添加IBaseFilter类型的filter,那这个IBaseFilter怎么指定播放文件的路径?

    2014年3月5日 7:28
  • 我想问一下,如果一个filter有多个输入针,怎么得到某一个指定的输入针呢?

    我尝试把列举出来的针的id和graph.exe里显示的id比较,有的能得到结果,有的返回错误。

    2014年4月14日 3:42