// 所有原创文章转载请注明作者及链接
// blackboycpp(AT)gmail.com
// QQ群: 135202158
类定义:
//============================================================================= // 名 称 : zp_Gate.h // 功 能 : Filter, 输入Pin, 输出Pin 3个类的类定义 // // 这几个类主要示范了如何从CBaseFilter, CBaseInputPin, CBaseOutputPin这3个 // 类派生出自已需要的Filter及Pin类. 这3个类的实现已经几乎是最简单的了, 只实现了 // 必须实现的方法. 同样地, 这个Filter的功能也相当简单, 对于数据流相当于是透明的, // 只是简单地转发一下sample, 不进行任何操作. 它有2个Pin, 一个输入Pin, 一输出Pin, // 这两个Pin上的数据和媒体类型当然, 也是完全一样的. // // 开发者: [email protected] // 更新于: 2009-11-24 15:34:54 // 备 注 : //============================================================================= #pragma once // the GUID of the filter // {1B0FFB65-DB1A-494f-8748-046970465B86} DEFINE_GUID(CLSID_Gate, 0x1b0ffb65, 0xdb1a, 0x494f, 0x87, 0x48, 0x4, 0x69, 0x70, 0x46, 0x5b, 0x86); class CGate; class CDataOut; // 功 能 : 输入Pin类 // 更新于: 2009-11-24 15:36:13 // 备 注 : class CDataIn : public CBaseInputPin { friend class CDataOut; public: CDataIn(TCHAR* pObjName, CGate* pFilter, HRESULT* phr, LPCWSTR pPinName); virtual ~CDataIn(); public: // 连接时检查媒体类型 HRESULT CheckMediaType(const CMediaType *pmt); STDMETHODIMP EndOfStream(); STDMETHODIMP BeginFlush(); STDMETHODIMP EndFlush(); // 从流中接收下一个Sample STDMETHODIMP Receive(IMediaSample *pSample); private: CGate* m_pGate; // 所在的Filter }; // 功 能 : 输出Pin类 // 更新于: 2009-11-24 15:37:55 // 备 注 : class CDataOut : public CBaseOutputPin { friend class CDataIn; public: CDataOut(TCHAR* pObjName, CGate* pFilter, HRESULT* phr, LPCWSTR pPinName); virtual ~CDataOut(); public: // 枚举首选的媒体类型 STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum); HRESULT CheckMediaType(const CMediaType* pmt); HRESULT DecideBufferSize( IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * ppropInputRequest); HRESULT Active(); HRESULT Inactive(); // 将Sample交到下级输入Pin HRESULT Deliver(IMediaSample* pMediaSample); HRESULT DeliverBeginFlush(); HRESULT DeliverEndFlush(); HRESULT DeliverEndOfStream(); private: CGate* m_pGate; // 所在的Filter COutputQueue* m_pOutQueue; }; class CGate : public CCritSec, public CBaseFilter { friend class CDataIn; friend class CDataOut; public: CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* hr); public: virtual ~CGate(void); public: static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT* phr); CBasePin* GetPin(int n); // 获得指定Pin int GetPinCount(); // 获得Pin数量 private: CDataIn* m_pInputPin; // 输入Pin CDataOut* m_pOutputPin; // 输入Pin };
-----------------------
实现:
//============================================================================= // 名 称 : zp_Gate.cpp // 功 能 : CGate, CDataIn, CDataOut 3个类的实现 // 开发者: [email protected] // 更新于: 2009-11-24 16:02:17 // 备 注 : // //============================================================================= #include "stdafx.h" #include "zp_Gate.h" //#include "zp_utl.h" #ifdef _MANAGED #pragma managed(push, off) #endif #pragma warning(disable:4355 4127) const AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_NULL, // Major type &MEDIASUBTYPE_NULL // Minor type }; const AMOVIESETUP_PIN psudPins[] = { { L"Input", // Pin名字字符串 FALSE, // 是否被render FALSE, // 是否输出 FALSE, // 允许为空 FALSE, // 允许多个 &CLSID_NULL, // 连接到Filter L"Output", // 连接到Pin 1, // 媒体类型数量 &sudPinTypes // Pin信息 }, { L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, L"Input", 1, &sudPinTypes } }; const AMOVIESETUP_FILTER sudGate = { &CLSID_Gate, // Filetr的CLSID L"Gate", // Filter的名字 MERIT_DO_NOT_USE, // Filter的Merit 2, // Pin数量 psudPins // Pin信息 }; CFactoryTemplate g_Templates [1] = { { L"Gate", &CLSID_Gate, CGate::CreateInstance, NULL, &sudGate } }; int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); STDAPI DllRegisterServer() { return AMovieDllRegisterServer2(TRUE); } STDAPI DllUnregisterServer() { return AMovieDllRegisterServer2(FALSE); } extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return DllEntryPoint((HINSTANCE)(hModule), ul_reason_for_call, lpReserved); } ////////////////////////////////////////////////////////////////////////// CDataIn::CDataIn(TCHAR* pObjName, CGate* pFilter, HRESULT* phr, LPCWSTR pPinName) : CBaseInputPin(pObjName, pFilter, pFilter, phr, pPinName), m_pGate(pFilter) { ASSERT(pFilter); } CDataIn::~CDataIn() { } HRESULT CDataIn::CheckMediaType(const CMediaType *pmt) { CAutoLock lockit(m_pLock); // TODO: return NOERROR; } STDMETHODIMP CDataIn::EndOfStream() { CAutoLock lockit(m_pLock); HRESULT hr = NOERROR; CDataOut* pOutPin = m_pGate->m_pOutputPin; if(pOutPin != NULL) { hr = pOutPin->DeliverEndOfStream(); if(FAILED(hr)) return hr; } return NOERROR; } HRESULT CDataIn::BeginFlush() { CAutoLock lockit(m_pLock); // TODO: HRESULT hr = m_pGate->m_pOutputPin->DeliverBeginFlush(); if(FAILED(hr)) return hr; return CBaseInputPin::BeginFlush(); } HRESULT CDataIn::EndFlush() { CAutoLock lockit(m_pLock); // TODO: HRESULT hr = m_pGate->m_pOutputPin->DeliverEndFlush(); if(FAILED(hr)) return hr; return CBaseInputPin::EndFlush(); } HRESULT CDataIn::Receive(IMediaSample *pSample) { ASSERT(pSample); CAutoLock lockit(m_pLock); HRESULT hr = NOERROR; hr = CBaseInputPin::Receive(pSample); if(FAILED(hr)) return hr; // TODO: hr = m_pGate->m_pOutputPin->Deliver(pSample); if(FAILED(hr)) return hr; return NOERROR; } ////////////////////////////////////////////////////////////////////////// CDataOut::CDataOut(TCHAR* pObjName, CGate* pFilter, HRESULT* phr, LPCWSTR pPinName) : CBaseOutputPin(pObjName, pFilter, pFilter, phr, pPinName), m_pGate(pFilter) { ASSERT(pFilter); m_pOutQueue = NULL; } CDataOut::~CDataOut() { } HRESULT CDataOut::CheckMediaType(const CMediaType* pmt) { CAutoLock lockit(m_pLock); // TODO: HRESULT hr = NOERROR; if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED; hr = m_pGate->m_pInputPin->m_Connected->QueryAccept(pmt); if(hr != NOERROR) return VFW_E_TYPE_NOT_ACCEPTED; return NOERROR; } STDMETHODIMP CDataOut::EnumMediaTypes(IEnumMediaTypes **ppEnum) { CAutoLock lockit(m_pLock); ASSERT(ppEnum); if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED; return m_pGate->m_pInputPin->m_Connected->EnumMediaTypes(ppEnum); } HRESULT CDataOut::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * ppropInputRequest) { return NOERROR; } HRESULT CDataOut::Deliver(IMediaSample* pMediaSample) { CheckPointer(pMediaSample, E_POINTER); // TODO: if(m_pOutQueue == NULL) return NOERROR; pMediaSample->AddRef(); // TODO: return m_pOutQueue->Receive(pMediaSample); } HRESULT CDataOut::Active() { CAutoLock lockit(m_pLock); HRESULT hr = NOERROR; if(m_Connected == NULL) return NOERROR; if(m_pOutQueue == NULL) { m_pOutQueue = new COutputQueue(m_Connected, &hr, TRUE, FALSE); if(m_pOutQueue == NULL) return E_OUTOFMEMORY; if(FAILED(hr)) { delete m_pOutQueue; m_pOutQueue = NULL; return hr; } } CBaseOutputPin::Active(); return NOERROR; } HRESULT CDataOut::Inactive() { CAutoLock lockit(m_pLock); if(m_pOutQueue) { delete m_pOutQueue; m_pOutQueue = NULL; } CBaseOutputPin::Inactive(); return NOERROR; } HRESULT CDataOut::DeliverEndOfStream() { if(m_pOutQueue == NULL) return NOERROR; m_pOutQueue->EOS(); return NOERROR; } HRESULT CDataOut::DeliverBeginFlush() { if(m_pOutQueue == NULL) return NOERROR; m_pOutQueue->BeginFlush(); return NOERROR; } HRESULT CDataOut::DeliverEndFlush() { if(m_pOutQueue == NULL) return NOERROR; m_pOutQueue->EndFlush(); return NOERROR; } ////////////////////////////////////////////////////////////////////////// CUnknown* WINAPI CGate::CreateInstance(LPUNKNOWN pUnk, HRESULT* phr) { return new CGate(NAME("Gate"), pUnk, phr); } CGate::CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr) : CBaseFilter(NAME("Gate"), pUnk, this, CLSID_Gate) { m_pInputPin = new CDataIn(NAME("Input Pin"), this, phr, L"Input"); m_pOutputPin = new CDataOut(NAME("Output Pin"), this, phr, L"Output"); } CGate::~CGate() { if(m_pInputPin != NULL) { delete m_pInputPin; } if(m_pOutputPin != NULL) { delete m_pOutputPin; } } CBasePin* CGate::GetPin(int n) { if(n < 0) return NULL; else if(n == 0) return m_pInputPin; else if(n == 1) return m_pOutputPin; else return NULL; } int CGate::GetPinCount() { return 2; } #ifdef _MANAGED #pragma managed(pop) #endif
FilterGraph里测试: