Directshow 中使用 IGraphBuilder

Directshow 中使用 IGraphBuilder

在使用directShow的过程中,常常会用到IGraphBuilder,很多人都喜欢把它封装成类的方式来使用。在网上有许多版本的封装方式,这个是我在学习过程中使用的一个封装,说不上好,贴出来是自己记录一下,当然,也可以供大家参考学习。

//以下代码仅供参考学习
//Author:古斌亮
//email: [email protected]

//GraphBuilder.h 文件
#ifndef __GRAPHBUILDER__H__
#define __GRAPHBUILDER__H__
////////////////////////////////////////////////////////////////////////////////
//
// File Name : GraphBuilder.h
//
// Description : ....
//
// Creator  : James Gu
//
// Time   : 12/01/2006
//
// Modified  : ........
//     ........
//==============================================================================


////////////////////////////////////////////////////////////////////////////////
//include
////////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN  // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>

#include <stdio.h>
#include <streams.h>

#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>

#include <qedit.h>

#include <Mmsystem.h>
#include <initguid.h>

//#include <vector>

////////////////////////////////////////////////////////////////////////////////
//devfine
////////////////////////////////////////////////////////////////////////////////
#define S_RELEASE(x) {if(x){x->Release();x = NULL;}}

////////////////////////////////////////////////////////////////////////////////
//Initialize COM  
////////////////////////////////////////////////////////////////////////////////
//class CCOMInitialize
//{
//public:
// CCOMInitialize(){::CoInitialize(NULL);}
// ~ CCOMInitialize(){::CoUninitialize();}
//};

////////////////////////////////////////////////////////////////////////////////
//CDeviceFilter -- device filter
////////////////////////////////////////////////////////////////////////////////
class CDeviceFilter
{
public:
 CDeviceFilter();
 virtual ~ CDeviceFilter();

public:
 IBaseFilter*  DeviceFilter(){return m_pFilter;}

public://CLSID_SystemDeviceEnum
 bool CreateEnumor(REFCLSID riid );
 void ReleaseEnumor();

public:
 BOOL GetFirstFilter(const char * szFriendName = NULL);
 BOOL GetNextFilter(const char * szFriendName = NULL);

protected:
 BOOL GetDeviceByFriendName(const char * szFriendName);

protected:
 CComPtr<ICreateDevEnum> m_sysenum;
 IEnumMoniker *   m_pEnumMoniker;
 IBaseFilter *   m_pFilter;
};


////////////////////////////////////////////////////////////////////////////////
//CGraphBuilder -- smart graphbuilder
//
// DxShow应用的基本类:   James gu -- 02/07/2007
// 改类进行对IGraphBuilder进行封装,完成部分IGraphBuilder的功能
// 还可以对改类进行近一步的扩展,使可以完成FilterGraph Objects的更多功能
//
////////////////////////////////////////////////////////////////////////////////
class CGraphBuilder
{
public://Graphbuilder
 HRESULT QueryInterface(REFIID riid,void ** ppvObject);

public://filtergraph && filtergraph2 interface
 HRESULT Connect(IPin *ppinOut,IPin *ppinIn);
 HRESULT Render(IPin *ppinOut);
 HRESULT RenderFile(LPCWSTR lpwstrFile,LPCWSTR lpwstrPlayList);
 HRESULT AddSourceFilter(LPCWSTR lpwstrFileName,
  LPCWSTR lpwstrFilterName,IBaseFilter **ppFilter);

 HRESULT SetLogFile(DWORD_PTR hFile);
 HRESULT Abort(void);
 HRESULT ShouldOperationContinue(void);

 HRESULT AddFilter(IBaseFilter *pFilter,LPCWSTR pName);
 HRESULT RemoveFilter(IBaseFilter *pFilter);
 HRESULT EnumFilters(IEnumFilters **ppEnum);
 HRESULT FindFilterByName(LPCWSTR pName,IBaseFilter **ppFilter);
 HRESULT ConnectDirect(IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt);
 HRESULT Reconnect(IPin *ppin);
 HRESULT Disconnect(IPin *ppin);
 HRESULT SetDefaultSyncSource(void);

public://MediaControl interface(s)
public://MediaEvent interface(s)
public://MediaEventEx interface(s)
public://MediaSeeking interface(s)
public://VideoWindow interface(s)

public://function(s)
 void HandleEvent();
 void DeviceAbort();
 BOOL DisConnectAllPin(IBaseFilter * pFilter);
 HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
 HRESULT ConnectFilters(IBaseFilter *pFirst, IBaseFilter *pSecond);
 void DisConnectFilterNukeDown(IBaseFilter * inFilter,BOOL bRemove = FALSE);
 void DisConnectFilterNukeUp(IBaseFilter * inFilter,BOOL bRemove = FALSE);
 void RemoveFilters();

protected:
 bool OnDeviceAbort();
 bool OnDeviceLost(IUnknown  *punk);

public://control(s)
 BOOL QueryInterface();
 void ReleaseInterface();

public://控制方法
    bool ResizeWindow(const RECT& rect);
 bool ResizeWindow(long left,long top,long width,long height);
 bool SetDisplayWindow(HWND hWnd);
 bool SetNotifyWindow(HWND hWnd, UINT message);

 bool Play();
 bool Stop();
 bool Pause();
 bool StopWhenReady();

 bool IsRunning();
 bool IsStop();
 bool IsPause();

public:
 CGraphBuilder();
 CGraphBuilder(IGraphBuilder * builder);
 virtual ~CGraphBuilder();

public:
 bool Attach(IGraphBuilder * builder);

private://
 CGraphBuilder(const CGraphBuilder& builder){}
 CGraphBuilder& operator=(const CGraphBuilder& me){return *this;}

public://interface(s)
 IGraphBuilder *  GraphBuilder(){return m_pGraph;}

private:
 IMediaControl *  MediaControl();
 IMediaEventEx *  MediaEventEx();

protected:
 CComPtr<IGraphBuilder>   m_pGraph;

protected:
 IMediaControl *  m_pMediaControl;

protected:
 HWND   m_hWnd;
};

////////////////////////////////////////////////////////////////////////////////
//CCaptureGraphBuilder -- capture graphbuilder
////////////////////////////////////////////////////////////////////////////////
class CCaptureGraphBuilder
{
public://FilterGraph2 Interface
 STDMETHOD(AllocCapFile)(LPCOLESTR lpwstr, DWORDLONG dwlSize);
 STDMETHOD(ControlStream)(const GUID *pCategory,
      const GUID *pType,
      IBaseFilter *pFilter,
                        REFERENCE_TIME *pstart,
                        REFERENCE_TIME *pstop,
                        WORD wStartCookie,
                        WORD wStopCookie);

 STDMETHOD(CopyCaptureFile)(LPOLESTR lpwstrOld,
      LPOLESTR lpwstrNew,
      int fAllowEscAbort,
                        IAMCopyCaptureFileProgress *pCallback);

 STDMETHOD(FindInterface)(const GUID *pCategory,
      const GUID *pType,
      IBaseFilter *pf,
      REFIID riid,
      void **ppint);

 STDMETHOD(FindPin)(IUnknown *pSource,
      PIN_DIRECTION pindir,
      const GUID *pCategory,
                        const GUID *pType,
      BOOL fUnconnected,
      int num,
      IPin **ppPin);

 STDMETHOD(GetFiltergraph)(IGraphBuilder **ppfg);

 STDMETHOD(RenderStream)(const GUID *pCategory,
      const GUID *pType,
      IUnknown *pSource,
      IBaseFilter *pIntermediate,
      IBaseFilter *pSink);

 STDMETHOD(SetOutputFileName)(const GUID *pType,
      LPCOLESTR lpwstrFile,
      IBaseFilter **ppf,
      IFileSinkFilter **pSink);

 STDMETHOD(SetFiltergraph)(IGraphBuilder *pfg);

protected://stream config
 HRESULT SetGraphBuilder();

public://IAMStreamConfig Interface
 HRESULT GetFormat(AM_MEDIA_TYPE **pmt);
 HRESULT GetNumberOfCapabilities(int *piCount,int *piSize);
 HRESULT GetStreamCaps(int iIndex,AM_MEDIA_TYPE **pmt,BYTE *pSCC);
 HRESULT SetFormat(AM_MEDIA_TYPE *pmt);
 //config(s) 

protected:
 IAMStreamConfig * AMStreamConfig();

public:
 CCaptureGraphBuilder(CGraphBuilder& gf,CDeviceFilter& dev);
 virtual ~CCaptureGraphBuilder();

protected:
 CComPtr<ICaptureGraphBuilder2> m_pGraphBuilder2;
 CGraphBuilder&     m_graphbuilder;
 CDeviceFilter&     m_device;
 IAMStreamConfig *    m_streamconfig;
};

////////////////////////////////////////////////////////////////////////////////
//CDXBaseFilter -- dxbase filter
////////////////////////////////////////////////////////////////////////////////
class CDXBaseFilter
{
public:
 CDXBaseFilter(const GUID& guid);
 virtual ~ CDXBaseFilter();

public:
 IBaseFilter*  BaseFilter(){return m_pFilter;}

public:
 IPin * GetPin(PIN_DIRECTION PinDir = PINDIR_OUTPUT);

protected:
 CComPtr<IBaseFilter> m_pFilter;
 GUID     m_guid;
};

////////////////////////////////////////////////////////////////////////////////
#endif //__GRAPHBUILDER__H__
////////////////////////////////////////////////////////////////////////////////

//GraphBuilder.cpp 文件

///////////////////////////////////////////////////////////////////////////////////
//
// File Name : GraphBuilder.cpp
//
// Description : ....
//
// Author  : James Gu
//
// Time   : 12/01/2006
//
// Modified  : ........
//     ........
//=================================================================================

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
//#include "stdafx.h"

#include <assert.h>
#include "graphbuilder.h"

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
//linker library
//#if _DEBUG
//#pragma comment(lib,"strmbasd.lib")
//#else //_DEBUG
//#pragma comment(lib,"STRMBASE.lib")
//#endif //_DEBUG
//
//#pragma comment(lib,"strmiids.lib")
//#pragma comment(lib,"winmm.lib")
//#pragma comment(lib,"quartz.lib")
//#pragma comment(lib,"uuid.lib")

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
#define WriteLog TRACE

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
//static const CCOMInitialize com_initialized = CCOMInitialize();

/////////////////////////////////////////////////////////////////////////////////
//class CDeviceFilter
//
/////////////////////////////////////////////////////////////////////////////////
CDeviceFilter::CDeviceFilter()
{
 m_pEnumMoniker = NULL;
 m_pFilter  = NULL;
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
CDeviceFilter::~CDeviceFilter()
{
 if(m_pFilter)
 {
  m_pFilter->Release();
  m_pFilter = NULL;
 }

 if(m_pEnumMoniker)
 {
  m_pEnumMoniker->Release();
  m_pEnumMoniker = NULL;
 }
 m_sysenum.Release();
}


/////////////////////////////////////////////////////////////////////////////////
//CLSID_SystemDeviceEnum
/////////////////////////////////////////////////////////////////////////////////
bool CDeviceFilter::CreateEnumor(REFCLSID riid )
{
 HRESULT hr = -1;

 if(m_pEnumMoniker)
 {
  m_pEnumMoniker->Release();
  m_pEnumMoniker = NULL;
 }

 m_sysenum.Release();

 hr = m_sysenum.CoCreateInstance(CLSID_SystemDeviceEnum);
 if(FAILED(hr))
 {
  return false;
 }

 hr = m_sysenum->CreateClassEnumerator(riid,&m_pEnumMoniker,0);

 if(SUCCEEDED(hr))
 {
  hr = m_pEnumMoniker->Reset();
 }

 return (SUCCEEDED(hr))?(true):(false);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
void CDeviceFilter::ReleaseEnumor()
{
 if(m_pEnumMoniker)
 {
  m_pEnumMoniker->Release();
  m_pEnumMoniker = NULL;
 }

 m_sysenum.Release();
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
BOOL CDeviceFilter::GetFirstFilter(const char * szFriendName)
{
 return GetNextFilter(szFriendName);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
BOOL CDeviceFilter::GetNextFilter(const char * szFriendName)
{
 HRESULT   hr   = -1;
 IMoniker *  pmoniker = NULL;
 
 if(m_pEnumMoniker)
 {
  S_RELEASE(m_pFilter);

  if(szFriendName)
  {
   return GetDeviceByFriendName(szFriendName);
  }
  else
  {
   hr = m_pEnumMoniker->Next(1,&pmoniker,NULL);
   if(SUCCEEDED(hr))
   {
    hr = pmoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)&m_pFilter);
    S_RELEASE(pmoniker);
   }
  }
 }
 return (SUCCEEDED(hr))?(TRUE):(FALSE);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
BOOL CDeviceFilter::GetDeviceByFriendName(const char * szFriendName)
{
 HRESULT    hr  = -1;
 IMoniker *  pmoniker = NULL;
 IPropertyBag * pbag  = NULL;

 const CComVariant tarName = szFriendName;
 CComVariant   vname;
 
 while(SUCCEEDED(m_pEnumMoniker->Next(1,&pmoniker,NULL)))
 {
  hr = pmoniker->BindToStorage(NULL,NULL,IID_IPropertyBag,(void**)&pbag);
  if(SUCCEEDED(hr))
  {
   hr = pbag->Read(L"FriendlyName",&vname,NULL);
   if(SUCCEEDED(hr) && (vname == tarName))
   {
    hr = pmoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)&m_pFilter);      
    if(SUCCEEDED(hr))
    {
     S_RELEASE(pbag);
     S_RELEASE(pmoniker);
     break;
    }
   }
   S_RELEASE(pbag);
  }
  S_RELEASE(pmoniker);
 };//while()

 return (SUCCEEDED(hr))?(TRUE):(FALSE);
}

/////////////////////////////////////////////////////////////////////////////////
//class CGraphBuilder
/////////////////////////////////////////////////////////////////////////////////
CGraphBuilder::CGraphBuilder()
{
 m_pMediaControl  = NULL;

 if( FAILED(m_pGraph.CoCreateInstance(CLSID_FilterGraph)) )
 {
  throw "Cann't create graph builder object!";
 }
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
CGraphBuilder::CGraphBuilder(IGraphBuilder * builder)
{
 m_pMediaControl = NULL;

 if(builder)
 {
  Attach(builder);
 }
}

/////////////////////////////////////////////////////////////////////////////////
//CGraphBuilder
/////////////////////////////////////////////////////////////////////////////////
CGraphBuilder::~CGraphBuilder()
{
 if(IsRunning())
 {
  Stop();
 }

 ReleaseInterface();

 RemoveFilters();

 m_pGraph.Release();
}

/////////////////////////////////////////////////////////////////////////////////
//Attach
/////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::Attach(IGraphBuilder * builder)
{
 return false;
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
//QueryInterface
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::QueryInterface(REFIID riid,void ** ppvObject)
{
 return m_pGraph->QueryInterface(riid,ppvObject);
}


///////////////////////////////////////////////////////////////////////////////////
//建立GraphBuilder并取得IMediaControl
///////////////////////////////////////////////////////////////////////////////////
BOOL CGraphBuilder::QueryInterface()
{
 HRESULT hr = -1;
 if(m_pGraph)
 {
  S_RELEASE(m_pMediaControl);
  hr = m_pGraph->QueryInterface(IID_IMediaControl,(void**)&m_pMediaControl);
  //hr |= m_pGraph->QueryInterface(IID_IMediaEvent,(void**)&m_pMediaEvent);
  //hr |= m_pGraph->QueryInterface(IID_IMediaEventEx,(void**)&m_pMediaEventEx);
  //hr |= m_pGraph->QueryInterface(IID_IMediaSeeking,(void**)&m_pMediaSeeking);
  //hr |= m_pGraph->QueryInterface(IID_IVideoWindow,(void**)&m_pVideoWindow);
 }
 return (SUCCEEDED(hr))?(TRUE):(FALSE);
}

///////////////////////////////////////////////////////////////////////////////////
//释放GraphBuilder
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::ReleaseInterface()
{
 SetDisplayWindow(NULL);
 SetNotifyWindow(NULL,0);

 S_RELEASE(m_pMediaControl);
 //S_RELEASE(m_pVideoWindow);
 //S_RELEASE(m_pMediaEvent);
 //S_RELEASE(m_pMediaEventEx);
 //S_RELEASE(m_pMediaSeeking);
}

///////////////////////////////////////////////////////////////////////////////////
//IGraphBuilder interface
///////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::Connect(IPin *ppinOut,IPin *ppinIn)
{
 return m_pGraph->Connect(ppinOut,ppinIn);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::Render(IPin *ppinOut)
{
 return m_pGraph->Render(ppinOut);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::RenderFile(LPCWSTR lpwstrFile,LPCWSTR lpwstrPlayList)
{
 return m_pGraph->RenderFile(lpwstrFile,lpwstrPlayList);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::AddSourceFilter(LPCWSTR lpwstrFileName,
 LPCWSTR lpwstrFilterName,IBaseFilter **ppFilter)
{
 return m_pGraph->AddSourceFilter(lpwstrFileName,lpwstrFilterName,ppFilter);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::SetLogFile(DWORD_PTR hFile)
{
 return m_pGraph->SetLogFile(hFile);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::Abort()
{
 return m_pGraph->Abort();
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::ShouldOperationContinue()
{
 return m_pGraph->ShouldOperationContinue();
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::AddFilter(IBaseFilter *pFilter,LPCWSTR pName)
{
 return m_pGraph->AddFilter(pFilter,pName);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::RemoveFilter(IBaseFilter *pFilter)
{
 return m_pGraph->RemoveFilter(pFilter);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::EnumFilters(IEnumFilters **ppEnum)
{
 return m_pGraph->EnumFilters(ppEnum);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::FindFilterByName(LPCWSTR pName,IBaseFilter **ppFilter)
{
 return m_pGraph->FindFilterByName(pName,ppFilter);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::ConnectDirect(IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt)
{
 return m_pGraph->ConnectDirect(ppinOut,ppinIn,pmt);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::Reconnect(IPin *ppin)
{
 return m_pGraph->Reconnect(ppin);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::Disconnect(IPin *ppin)
{
 return m_pGraph->Disconnect(ppin);
}

/////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::SetDefaultSyncSource()
{
 return m_pGraph->SetDefaultSyncSource();
}
///////////////////////////////////////////////////////////////////////////////////
//IGraphBuilder interface --- end!!
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
IMediaControl * CGraphBuilder::MediaControl()
{
 if(m_pMediaControl == NULL)
 {
  m_pGraph->QueryInterface(IID_IMediaControl,(void**)&m_pMediaControl);
 }
 return m_pMediaControl;
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
IMediaEventEx * CGraphBuilder::MediaEventEx()
{
 IMediaEventEx * pe = NULL;
 if(SUCCEEDED(QueryInterface(IID_IMediaEventEx,(void**)&pe)))
 {
  return pe;
 }
 return NULL;
}

///////////////////////////////////////////////////////////////////////////////////
//取得一个filter 的 pin(PINDIR_INPUT/PINDIR_OUTPUT)
///////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
{
 if(pFilter)
 {
  IEnumPins  *pEnum = NULL;
  IPin       *pPin = NULL;

  pFilter->EnumPins(&pEnum);

  while(pEnum->Next(1, &pPin, 0) == S_OK)
  {
   PIN_DIRECTION PinDirThis;
   pPin->QueryDirection(&PinDirThis);
   if (PinDir == PinDirThis)
   {
    S_RELEASE(pEnum);
    //pEnum->Release();
    *ppPin = pPin;
    return S_OK;
   }
   //pPin->Release();
   S_RELEASE(pPin);
  }
  //pEnum->Release();
  S_RELEASE(pEnum);
 }

    return E_FAIL; 
}

///////////////////////////////////////////////////////////////////////////////////
//断开一个filter上连接的所有filter
///////////////////////////////////////////////////////////////////////////////////
BOOL CGraphBuilder::DisConnectAllPin(IBaseFilter * pFilter)
{
 HRESULT  hr   = S_OK;

 if(pFilter)
 {
  IEnumPins * pEnum = NULL;
  IPin *  pin   = NULL;

  if(SUCCEEDED(pFilter->EnumPins(&pEnum)))
  {
   while(SUCCEEDED(pEnum->Next(1,&pin,0)))
   {
    hr |= m_pGraph->Disconnect(pin);
   };
   S_RELEASE(pEnum);
  }
 }

 return (SUCCEEDED(hr))?(TRUE):(FALSE);
}

///////////////////////////////////////////////////////////////////////////////////
//连接两个filter
///////////////////////////////////////////////////////////////////////////////////
HRESULT CGraphBuilder::ConnectFilters(IBaseFilter *pFirst, IBaseFilter *pSecond)
{
    IPin *pOut = NULL;
 IPin *pIn = NULL;

    HRESULT hr = -1;
 
 if(SUCCEEDED(GetPin(pFirst, PINDIR_OUTPUT, &pOut)) &&
  SUCCEEDED(GetPin(pSecond, PINDIR_INPUT, &pIn)))
 {
  hr = this->Connect(pOut,pIn);
 }

 S_RELEASE(pIn);
 S_RELEASE(pOut);

    return hr;
}

///////////////////////////////////////////////////////////////////////////////////
//给定一个Filter,断开这个Filter上面连着的所有Filter
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::DisConnectFilterNukeDown(IBaseFilter * inFilter,BOOL bRemove)
{
 if(inFilter)
 {
  IEnumPins * pinEnum = NULL;
  if(SUCCEEDED(inFilter->EnumPins(&pinEnum)))
  {
   pinEnum->Reset();

   IPin * pin = NULL;
   ULONG cFetched = 0;
   bool pass = true;
   
   while(pass && SUCCEEDED(pinEnum->Next(1, &pin, &cFetched)))
   {
    if(pin && cFetched)
    {
     IPin * connectedPin = NULL;
     
     pin->ConnectedTo(&connectedPin);
     
     if(connectedPin)
     {
      PIN_INFO pininfo;
      
      if(SUCCEEDED(connectedPin->QueryPinInfo(&pininfo)))
      {
       if(pininfo.dir == PINDIR_INPUT)
       {
        DisConnectFilterNukeDown(pininfo.pFilter);
        m_pGraph->Disconnect(connectedPin);
        m_pGraph->Disconnect(pin);
        
        if(bRemove)m_pGraph->RemoveFilter(pininfo.pFilter);
       }
       pininfo.pFilter->Release();
      }
      connectedPin->Release();
     }
     pin->Release();
    }
    else
    {
     pass = false;
    }
   }
   pinEnum->Release();
  }
 }
}

///////////////////////////////////////////////////////////////////////////////////
//给定一个Filter,断开这个Filter下面连着的所有Filter
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::DisConnectFilterNukeUp(IBaseFilter * inFilter,BOOL bRemove)
{
 if(inFilter)
 {
  IEnumPins * pinEnum = NULL;
  
  if(SUCCEEDED(inFilter->EnumPins(&pinEnum)))
  {
   pinEnum->Reset();
   
   IPin * pin = NULL;
   ULONG cFetched = 0;
   bool pass = true;
   
   while(pass && SUCCEEDED(pinEnum->Next(1, &pin, &cFetched)))
   {
    if(pin && cFetched)
    {
     IPin * connectedPin = NULL;

     pin->ConnectedTo(&connectedPin);
     
     if(connectedPin)
     {
      PIN_INFO pininfo;
      
      if(SUCCEEDED(connectedPin->QueryPinInfo(&pininfo)))
      {
       if(pininfo.dir == PINDIR_OUTPUT)
       {
        DisConnectFilterNukeUp(pininfo.pFilter);
        m_pGraph->Disconnect(connectedPin);
        m_pGraph->Disconnect(pin);
        if(bRemove)m_pGraph->RemoveFilter(pininfo.pFilter);
       }
       pininfo.pFilter->Release();
      }
      connectedPin->Release();
     }
     pin->Release();
    }
    else
    {
     pass = false;
    }
   };
   pinEnum->Release();
  }
 }
}

///////////////////////////////////////////////////////////////////////////////////
//清除图表上的所有Filters
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::RemoveFilters()
{
 IEnumFilters * pEnumFilters = NULL;
 HRESULT hr = m_pGraph->EnumFilters(&pEnumFilters);
 if(SUCCEEDED(hr) && (pEnumFilters))
 {
  //ULONG fet = 0;
  IBaseFilter * pf = NULL;
  while(SUCCEEDED(pEnumFilters->Next(1,&pf,0/*&fet*/)))
  {
   if(FAILED(m_pGraph->RemoveFilter(pf)))
   {
    break;
   }
   S_RELEASE(pf);
  };
  S_RELEASE(pEnumFilters);
 }
}

///////////////////////////////////////////////////////////////////////////////////
//事件处理
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::HandleEvent()
{
 LONG event  = 0 ;
 LONG param1 = 0 ;
 LONG param2 = 0 ;

 IMediaEventEx  *pEvent = MediaEventEx();
 if(pEvent)
 {
  while(SUCCEEDED(pEvent->GetEvent(&event, (LONG_PTR*)&param1, (LONG_PTR*)&param2, 0)))
  {
   pEvent->FreeEventParams(event, param1, param2);
   if( event == EC_ERRORABORT )
   {
    OnDeviceAbort();               
    break;
   }
   else if(event == EC_DEVICE_LOST)
   {
    //the device is remove
    if(param2 == 0)
    {
     IUnknown  *punk = (IUnknown*)(LONG_PTR)param1;
     if(OnDeviceLost(punk))
     {
      OnDeviceAbort();
      Stop();
      ReleaseInterface();
      RemoveFilters();
      m_pGraph.Release();
     }
    }
    //the device is add
    else if( param2 == 1 )
    {
     //
    }
   }
  }//while()
  S_RELEASE(pEvent);
 }//if(pEvent)
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
void CGraphBuilder::DeviceAbort()
{
 OnDeviceAbort();
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::OnDeviceLost(IUnknown  *punk)
{
 HRESULT hr = S_OK;
 IBaseFilter * pf = NULL;

 if(punk)
 {
  hr = punk->QueryInterface(IID_IBaseFilter,(void**)&pf);
  if(SUCCEEDED(hr))
  {
   IBaseFilter * pb = NULL;
   hr = m_pGraph->QueryInterface(IID_IBaseFilter,(void**)&pb);
   if(SUCCEEDED(hr))
   {
    if(IsEqualObject(pb,pf))
    {
     pb->Release();
     pf->Release();
     return true;
    }
    pb->Release();
   }
   pf->Release();
  }
 }
 return false;
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::OnDeviceAbort()
{
 return SetDisplayWindow(NULL);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::ResizeWindow(const RECT& rect)
{
 return ResizeWindow(rect.left,rect.top,
     rect.right - rect.left,rect.bottom - rect.top);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::ResizeWindow(long left,long top,long width,long height)
{
 HRESULT hr = -1;

 if(m_pGraph)
 {
  IVideoWindow * pvw = NULL;
  hr = m_pGraph->QueryInterface(IID_IVideoWindow,(void**)&pvw);
  if(SUCCEEDED(hr))
  {
   hr = pvw->SetWindowPosition(left,top,width,height);
   S_RELEASE(pvw);
  }
 }

 return (SUCCEEDED(hr))?(true):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::SetDisplayWindow(HWND hWnd)
{
 HRESULT hr = -1;

 //if(m_pGraph)
 //{
 IVideoWindow * pvw = NULL;
 hr = m_pGraph->QueryInterface(IID_IVideoWindow,(void**)&pvw);
 
 if(SUCCEEDED(hr))
 {
  hr = pvw->put_Visible(OAFALSE);
  hr |= pvw->put_MessageDrain(OAHWND(0));
  hr |= pvw->put_Owner(OAHWND(0));

  if(hWnd && ::IsWindow(hWnd))
  {
   hr = pvw->put_Owner((OAHWND)hWnd);
   hr |= pvw->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS);
   hr |= pvw->put_MessageDrain((OAHWND)hWnd);
   hr |= pvw->put_AutoShow(OATRUE);

   hr |= pvw->put_Visible(OATRUE);
  }
  S_RELEASE(pvw);
 }
 //}//if(m_pGraph)

 return (SUCCEEDED(hr))?(true):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::SetNotifyWindow(HWND hWnd, UINT message)
{
 HRESULT hr = -1;
 IMediaEventEx * pe = MediaEventEx();

 if(pe)
 {
  hr = pe->SetNotifyWindow((OAHWND)hWnd, message, 0);
 }
 return (SUCCEEDED(hr))?(true):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::Play()
{
 return (m_pGraph)?((m_pMediaControl == NULL)?
    (SUCCEEDED(MediaControl()->Run())?(true):(false)):
     ((SUCCEEDED(m_pMediaControl->Run()))?(true):(false))):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::Stop()
{
 return (m_pGraph)?((m_pMediaControl == NULL)?
    (SUCCEEDED(MediaControl()->Stop())?(true):(false)):
     ((SUCCEEDED(m_pMediaControl->Stop()))?(true):(false))):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::StopWhenReady()
{
 return (m_pGraph)?((m_pMediaControl == NULL)?
    (SUCCEEDED(MediaControl()->StopWhenReady())?(true):(false)):
     ((SUCCEEDED(m_pMediaControl->StopWhenReady()))?(true):(false))):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::Pause()
{
 return (m_pGraph)?((m_pMediaControl == NULL)?
    (SUCCEEDED(MediaControl()->Pause())?(true):(false)):
     ((SUCCEEDED(m_pMediaControl->Pause()))?(true):(false))):(false);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::IsRunning()
{
 HRESULT hr = S_OK;

 if(m_pMediaControl==NULL) m_pMediaControl = this->MediaControl();

 if(m_pMediaControl)
 {
  OAFilterState fs = 0;
  hr = m_pMediaControl->GetState(10,&fs);//INFINITE
  if(SUCCEEDED(hr))
  {
   if(fs == State_Running)return true;
  }
 }

 return false;
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::IsStop()
{
 HRESULT hr = S_OK;

 if(m_pMediaControl==NULL) m_pMediaControl = this->MediaControl();

 if(m_pMediaControl)
 {
  OAFilterState fs = 0;
  hr = m_pMediaControl->GetState(10,&fs);//INFINITE
  if(SUCCEEDED(hr))
  {
   if(fs == State_Stopped)return true;
  }
 }

  return false;
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
bool CGraphBuilder::IsPause()
{
 HRESULT hr = S_OK;

 if(m_pMediaControl==NULL) m_pMediaControl = this->MediaControl();

 if(m_pMediaControl)
 {
  OAFilterState fs = 0;
  hr = m_pMediaControl->GetState(10,&fs);//INFINITE
  if(SUCCEEDED(hr))
  {
   if(fs == State_Paused)return true;
  }
 }

 return false;
}
///////////////////////////////////////////////////////////////////////////////////
//End--class CGraphBuilder
///////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////
//class CCaptureGraphBuilder
///////////////////////////////////////////////////////////////////////////////////
CCaptureGraphBuilder::CCaptureGraphBuilder(CGraphBuilder& gf,CDeviceFilter& dev)
 :m_graphbuilder(gf),m_device(dev)
{
 m_streamconfig = NULL;

 if(FAILED(m_pGraphBuilder2.CoCreateInstance(CLSID_CaptureGraphBuilder2)))
 {
  throw "cann't create capture graph builder object!";
 }

 if(FAILED(m_pGraphBuilder2->SetFiltergraph(m_graphbuilder.GraphBuilder())))
 {
  m_pGraphBuilder2.Release();
  throw "cann't add object into graph builder.";
 }
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
CCaptureGraphBuilder::~CCaptureGraphBuilder()
{
 S_RELEASE(m_streamconfig);
 m_pGraphBuilder2.Release();
}

///////////////////////////////////////////////////////////////////////////////////
// interface
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::AllocCapFile(LPCOLESTR lpwstr, DWORDLONG dwlSize)
{
 return m_pGraphBuilder2->AllocCapFile(lpwstr, dwlSize);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::ControlStream(const GUID *pCategory,
      const GUID *pType,
      IBaseFilter *pFilter,
                        REFERENCE_TIME *pstart,
                        REFERENCE_TIME *pstop,
                        WORD wStartCookie,
                        WORD wStopCookie)
{
 return m_pGraphBuilder2->ControlStream(pCategory, pType,
   pFilter, pstart, pstop, wStartCookie, wStopCookie);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::CopyCaptureFile(LPOLESTR lpwstrOld,
      LPOLESTR lpwstrNew,
      int fAllowEscAbort,
                        IAMCopyCaptureFileProgress *pCallback)
{
 return m_pGraphBuilder2->CopyCaptureFile(lpwstrOld,
      lpwstrNew, fAllowEscAbort, pCallback);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::FindInterface(const GUID *pCategory,
      const GUID *pType,
      IBaseFilter *pf,
      REFIID riid,
      void **ppint)
{
 return m_pGraphBuilder2->FindInterface(pCategory, pType, pf, riid, ppint);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::FindPin(IUnknown *pSource,
      PIN_DIRECTION pindir,
      const GUID *pCategory,
                        const GUID *pType,
      BOOL fUnconnected,
      int num,
      IPin **ppPin)
{
 return m_pGraphBuilder2->FindPin(pSource,
    pindir, pCategory, pType, fUnconnected, num, ppPin);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::GetFiltergraph(IGraphBuilder **ppfg)
{
 return m_pGraphBuilder2->GetFiltergraph(ppfg);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::RenderStream(const GUID *pCategory,
      const GUID *pType,
      IUnknown *pSource,
      IBaseFilter *pIntermediate,
      IBaseFilter *pSink)
{
 return m_pGraphBuilder2->RenderStream(pCategory,
     pType, pSource, pIntermediate, pSink);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::SetFiltergraph(IGraphBuilder *pfg)
{
 return m_pGraphBuilder2->SetFiltergraph(pfg);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::SetOutputFileName(const GUID *pType,
      LPCOLESTR lpwstrFile,
      IBaseFilter **ppf,
      IFileSinkFilter **pSink)
{
 return m_pGraphBuilder2->SetOutputFileName(pType, lpwstrFile, ppf, pSink);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::SetGraphBuilder()
{
 return m_pGraphBuilder2->SetFiltergraph(m_graphbuilder.GraphBuilder());
}

///////////////////////////////////////////////////////////////////////////////////
//IAMStreamConfig Interface
///////////////////////////////////////////////////////////////////////////////////
IAMStreamConfig * CCaptureGraphBuilder::AMStreamConfig()
{
 S_RELEASE(m_streamconfig);

 HRESULT hr = -1;

 if(m_device.DeviceFilter())
 {
  hr = m_pGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,
      m_device.DeviceFilter(),IID_IAMStreamConfig,(void**)&m_streamconfig);
  if(FAILED(hr))
  {
   hr = m_pGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,
      m_device.DeviceFilter(),IID_IAMStreamConfig,(void**)&m_streamconfig); 
  }
 }

 return (SUCCEEDED(hr))?(m_streamconfig):(NULL);
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::GetFormat(AM_MEDIA_TYPE **pmt)
{
 return (m_streamconfig == NULL)?
  ((AMStreamConfig())?(m_streamconfig->GetFormat(pmt)):(-1))
    :(m_streamconfig->GetFormat(pmt));
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::GetNumberOfCapabilities(int *piCount,int *piSize)
{
 return (m_streamconfig == NULL)?
  ((AMStreamConfig())?(m_streamconfig->GetNumberOfCapabilities(piCount,piSize)):(-1))
    :(m_streamconfig->GetNumberOfCapabilities(piCount,piSize));
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::GetStreamCaps(int iIndex,AM_MEDIA_TYPE **pmt,BYTE *pSCC)
{
 return (m_streamconfig == NULL)?
  ((AMStreamConfig())?(m_streamconfig->GetStreamCaps(iIndex,pmt,pSCC)):(-1))
    :(m_streamconfig->GetStreamCaps(iIndex,pmt,pSCC));
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
HRESULT CCaptureGraphBuilder::SetFormat(AM_MEDIA_TYPE *pmt)
{
 HRESULT hr = -1;

 if(m_streamconfig == NULL)
 {
  AMStreamConfig();
 }

 if(m_streamconfig)
 {
  hr = m_streamconfig->SetFormat(pmt);

 #if _DEBUG
  if( hr == E_OUTOFMEMORY )
  {
   ::OutputDebugString("AMStreamConfig ... E_OUTOFMEMORY!/n");
  }
  else if( hr == E_POINTER )
  {
   OutputDebugString("AMStreamConfig ... E_POINTER!/n");
  }
  else if( hr == VFW_E_INVALIDMEDIATYPE )
  {
   OutputDebugString("AMStreamConfig .....VFW_E_INVALIDMEDIATYPE!/n");
  }
  else if( hr == VFW_E_NOT_CONNECTED )
  {
   OutputDebugString("AMStreamConfig .....VFW_E_NOT_CONNECTED!/n");
  }
  else if( hr == VFW_E_NOT_STOPPED )
  {
   OutputDebugString("AMStreamConfig ....VFW_E_NOT_STOPPED!/n");
  }
  else if( hr == VFW_E_WRONG_STATE )
  {
   OutputDebugString("AMStreamConfig .....VFW_E_WRONG_STATE!/n");
  }

  if( SUCCEEDED(hr))
  {
   OutputDebugString("AMStreamConfig .....ok/n");
  }
  else
  {
   OutputDebugString("AMStreamConfig ....faild!/n");
  }
 #endif //_DEBUG

  S_RELEASE(this->m_streamconfig);
 }

 return hr;
}
///////////////////////////////////////////////////////////////////////////////////
//End----class CCaptureGraphBuilder
///////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////
//class CDXBaseFilter
///////////////////////////////////////////////////////////////////////////////////
CDXBaseFilter::CDXBaseFilter(const GUID& guid):m_guid(guid)
{
 if(FAILED(m_pFilter.CoCreateInstance(m_guid)))
 {
  throw "cann't create dxobject.";
 }
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
CDXBaseFilter::~CDXBaseFilter()
{
 m_pFilter.Release();
}

///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
IPin * CDXBaseFilter::GetPin(PIN_DIRECTION PinDir)
{
 //PIN_DIRECTION PinDir = inInput ? PINDIR_INPUT : PINDIR_OUTPUT;
    IEnumPins  *pEnum = NULL;
    IPin       *pPin = NULL;

    m_pFilter->EnumPins(&pEnum);

    while(pEnum->Next(1, &pPin, 0) == S_OK)
    {
        PIN_DIRECTION PinDirThis;
        pPin->QueryDirection(&PinDirThis);
        if(PinDir == PinDirThis)
        {
            pEnum->Release();
   return pPin;
        }
        pPin->Release();
    }
    return NULL;
}
///////////////////////////////////////////////////////////////////////////////////
//End--class CDXBaseFilter
///////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////

 

///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
//End File
///////////////////////////////////////////////////////////////////////////////////
 

你可能感兴趣的:(filter,null,Graph,interface,reference,output)