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*)¶m1, (LONG_PTR*)¶m2, 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
///////////////////////////////////////////////////////////////////////////////////