zoukankan      html  css  js  c++  java
  • MFC Filter20191008

    MFC Filter
     Filter并不总是在一个Win32 DLL中实现的。根据实际的需要,我们可能要在Filter
    的实现中用到MFC,更或者我们将Filter实现在一个EXE应用程序中。下面介绍这样一种在
    MFC应用程序中开发Filter的方式。
     在应用程序中定义的Filter,严格来说,已经不能算是标准的COM组件了,它没有独
    立的实现模块,不需要注册,当然也不能通过标准的COM类工厂来创建。创建这种Filter
    的正确方法是,直接在应用程序中new出一个Filter类对象实例来。代码如下:
     m_pFilterObject=new CFilterClass();
     //Make the initial refcount 1 to match COM creation
     m_pFilterObject->AddRef();
     接下去,这个Filter就跟其他标准的通过CoCreateInstance函数创建的Filter一样使用
    了。举例来说,假设我们在播放媒体文件的时候,想要知道一些数据流的信息(比如视频流
    图像的宽、高、帧率等),另外完成一些简单功能(比如抓帧等)。但是,我们又不想使用
    另外的DLL来开发Filter。于是,我们就可以在应用程序中定义一个Transform filter,并
    插入到媒体文件播放的Filter链路中。代码如下:
     class CAppTransform:public CTransInPlaceFilter
     {
      public:
       CAppTransform(LPUNKNOWN pUnkOuter,HRESULT *phr);
       HRESULT CheckInputType(const CMediaType *mtIn);
       HRESULT Transform(IMediaSample *pSample);
     };
     然后,如下实现:
     CAppTransform::CAppTransform(LPUNKNOWN pUnkOuter,HRESULT *phr):
     CTransInPlaceFilter(NAME("App Trans-IP"),pUnkOuter,GUID_NULL,phr)
     {
     }
     HRESULT CAppTransform::Transform(IMediaSample *pSample)
     {
      //Override to do someting inside the application
      //Such as grabbing a poster frame...
      return S_OK;
     }
     //Check if we can support this specific proposed type and format
     HRESULT CAppTransform::CheckInputType(const CMediaType *pmt)
     {
      //We accept a series of raw media types
      if(pmt->majortype==MEDIATYPE_Video &&
       (pmt->subtype==MEDIASUBTYPE_RGB32||
       pmt->subtype==MEDIASUBTYPE_RGB24||
       pmt->subtype==MEDIASUBTYPE_RGB565||
       pmt->subtype==MEDIASUBTYPE_RGB555||
       pmt->subtype==MEDIASUBTYPE_UYVY||
       pmt->subtype==MEDIASUBTYPE_YUY2))
      {
       return NOERROR;
      }
      return E_FAIL;
     }
     为了播放媒体文件,我们另外设计了一个类CAppGraphBuilder,用于Filter Graph的
    构建。我们的思路是,首先使用IGraphBuilder::RenderFile构建一个完整的媒体文件回放
    链路,然后找到Video Renderer(或者Overlay Mixer),在它之前插入我们自己的Transform
    Filter。代码如下:
     //给定一个媒体文件,创建一个回放链路,随后插入我们的Transform Filter
     HRESULT CAppGraphBuilder::BuildFromFile(LPCWSTR pszFile)
     {
      DestroyGraph();
      //创建一个Filter Graph
      HRESULT hr=CoCreateInstance(
         CLSID_FilterGraph,
         NULL,
         CLSCTX_INPROC,
         IID_IGraphBuilder,
         (void**)&m_pGraph);
      if(FAILED(hr))
      {
       return hr;
      }
      AddToObjectTable();
      //首先构建一个源文件的回放Filter Graph
      hr=m_pGraph->RenderFile(pszFile,NULL);
      if(FAILED(hr))
      {
       return hr;
      }
      //通过IVideoWindow接口找到Video Renderer
      IBaseFilter *pVR;
      hr=FindFilterByInterface(IID_IVideoWindow,&pVR);
      if(FAILED(hr))
      {
       return hr;
      }
      //注意,如果Video Renderer的上一级Filter是Overlay Mixer,则将没有实际的
      //数据传送到Video Renderer上,这种情况下,我们的Filter应该插在Overlay
      //Mixer之前
      IPin *pPin=InputPinOf(pVR);  //获取Video Renderer的输入Pin
      AM_MEDIA_TYPE mt;
      pPin->ConnectionMediaType(&mt); //取得连接用的媒体类型
      pPin->Release();
      CMediaType mtIn=mt;
      FreeMediaType(mt);
      if(mtIn.subtype==MEDIASUBTYPE_Overlay)
      {
       //This connection may be a overlay mixer
       //need to move upstream one place
       IBaseFilter *pOvMix=NULL;
       hr=NextUpstream(pVR,&pOvMix);
       pVR->Release();
       if(FAILED(hr))
       {
        return hr;
       }
       pVR=pOvMix;
      }
      //创建我们的Transform Filter
      CreateAppFilter();
      //将我们的Filter插入到已有的Filter链路中
      hr=ConnectUpstreamof(pVR,m_pFilter);
      pVR->Release();
      return hr;
     }
     //创建我们的Transform Filter,注意不是用CoCreateInstance函数
     void CAppGraphBuilder::CreateAppFilter(void)
     {
      if(m_pFilter)
      {
       m_pFilter->Release();
       m_pFilter=NULL;
      }
      HRESULT hr=S_OK;
      //创建Filter对象实例
      m_pFilter=new CAppTransform(NULL,&hr);
      //增加一个引用计数,防止COM的自动销毁
      m_pFilter->AddRef();
      //获取IBaseFilter接口
      IBaseFilter *pFilter=NULL;
      hr=m_pFilter->QueryInterface(IID_IBaseFilter,(void **)&pFilter);
      if(SUCCEEDED(hr))
      {
       hr=m_pGraph->AddFilter(pFilter,L"App Transform");
       pFilter->Release();
      }
     }
     //将pTransform Filter(假设为一进一出)插入到pFilter的前面
     HRESULT CAppGraphBuilder::ConnectUpstreamof(IBaseFilter *pFilter,
     IBaseFilter *pTransform)
     {
      IPin *pPinIn=InputPinOf(pFilter);
      if(!pPinIn)
      {
       return E_FAIL;
      }
      //Get the peer output pin
      IPin *pPinOut=NULL;
      HRESULT hr=pPinIn->ConnectedTo(&pPinOut);
      if(FAILED(hr))
      {
       pPinIn->Release();
       return hr;
      }
      //Disconnect the current connection
      hr=m_pGraph->Disconnect(pPinOut);
      if(SUCCEEDED(hr))
      {
       hr=m_pGraph->Disconnect(pPinIn);
      }
      //Insert pTransform filter by connecting its input pin and output pin
      if(SUCCEEDED(hr))
      {
       IPin *pPinInXfm=InputPinOf(pTransform);
       hr=m_pGraph->Connect(pPinOut,pPinInXfm);
       pPinInXfm->Release();
      }
      if(SUCCEEDED(hr))
      {
       IPin *pPinOutXfm=OutputPinOf(pTransform);
       hr=m_pGraph->Connect(pPinOutXfm,pPinIn);
       pPinOutXfm->Release();
      }
      pPinIn->Release();
      pPinOut->Release();
      return hr;
     }

  • 相关阅读:
    [C++]猜词游戏简版
    [C++]异常处理实例-基础版
    C++Primer Plus习题记录-Chapter12
    C++Primer Plus习题记录-Chapter11
    [C++]MI(多继承)实例-基础版
    Windows下编译libevent及使用
    jquery点击回到顶部
    简体繁体转换
    检测ip和地区
    点击复制到剪切板
  • 原文地址:https://www.cnblogs.com/xiaomi-daming/p/11634332.html
Copyright © 2011-2022 走看看