标签:des style blog http color io os 使用 ar
DirectShow SDK提供了一套开发Filter的基类源代码。基于这些基类开发Filter将大大简化开发过程。
1、CBaseObject
大部分SDK类都从CBaseObject类(参见combase.h)中继承而来的。
- class CBaseObject
- {
-
- private:
-
-
-
-
- CBaseObject(const CBaseObject& objectSrc);
- void operator=(const CBaseObject& objectSrc);
-
- private:
- static LONG m_cObjects;
-
- protected:
- #ifdef DEBUG
- DWORD m_dwCookie;
- #endif
-
-
- public:
-
-
-
- CBaseObject(const TCHAR *pName);
- #ifdef UNICODE
- CBaseObject(const char *pName);
- #endif
- ~CBaseObject();
-
-
-
- static LONG ObjectsActive() {
- return m_cObjects;
- };
- };
2、 CUnknown
作为COM组件(参见combase.cpp文件),最基本的当然是IUnknown接口的实现。SDK提供了CUnknown类,SDK实现了COM接口类都是直接或间接从这个类继承来的。
- class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
- public CBaseObject
- {
- private:
- const LPUNKNOWN m_pUnknown;
-
- protected:
- volatile LONG m_cRef;
-
- public:
-
- CUnknown(const TCHAR *pName, LPUNKNOWN pUnk);
- virtual ~CUnknown() {};
-
-
-
- CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr);
- #ifdef UNICODE
- CUnknown(const char *pName, LPUNKNOWN pUnk);
- CUnknown(char *pName, LPUNKNOWN pUnk,HRESULT *phr);
- #endif
-
-
-
- LPUNKNOWN GetOwner() const {
- return m_pUnknown;
- };
-
-
-
-
-
-
-
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- };
CUnknown类从CBaseObject中继承而来,另外CUnknown类还实现了INonDelegatingUnknown接口,用于支持引用计数、接口查询、COM组件“聚合”等。
CUnknown类的使用方法如下:
(1) 从CUnknown派生一个子类,并在子类的public区加入DECLARE_IUNKNOWN宏;
(2) 重写NonDelegatingQueryInterface函数,用以支持IUnknown外的其他接口;
(3) 在子类的构造函数中调用CUnknown的构造函数。
eg:
- class CSeekingPassThru : public ISeekingPassThru, public CUnknown
- {
- public:
- static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
- CSeekingPassThru(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
- ~CSeekingPassThru();
-
- DECLARE_IUNKNOWN;
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
-
- STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);
-
- private:
- CPosPassThru *m_pPosPassThru;
- };
- CSeekingPassThru::CSeekingPassThru( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr )
- : CUnknown(pName, pUnk, phr),
- m_pPosPassThru(NULL)
- {
- }
3、 CBaseFilter
最基本的Filter由CBaseFilter 类(参见amfilter.cpp)实现。
作为Filter的基本特征,CBaseFilter实现了IBaseFilter接口(IbaseFilter从IMediaFilter继承而来)。
同时CBaseFilter还实现了Filter框架(描述了各个Pin组件的情况)。
- class AM_NOVTABLE CBaseFilter : public CUnknown,
- public IBaseFilter,
- public IAMovieSetup
- {
-
- friend class CBasePin;
-
- protected:
- FILTER_STATE m_State;
- IReferenceClock *m_pClock;
- CRefTime m_tStart;
- CLSID m_clsid;
-
- CCritSec *m_pLock;
-
- WCHAR *m_pName;
- IFilterGraph *m_pGraph;
- IMediaEventSink *m_pSink;
- LONG m_PinVersion;
-
- public:
-
- CBaseFilter(
- const TCHAR *pName,
- LPUNKNOWN pUnk,
- CCritSec *pLock,
- REFCLSID clsid);
-
- CBaseFilter(
- TCHAR *pName,
- LPUNKNOWN pUnk,
- CCritSec *pLock,
- REFCLSID clsid,
- HRESULT *phr);
- #ifdef UNICODE
- CBaseFilter(
- const CHAR *pName,
- LPUNKNOWN pUnk,
- CCritSec *pLock,
- REFCLSID clsid);
-
- CBaseFilter(
- CHAR *pName,
- LPUNKNOWN pUnk,
- CCritSec *pLock,
- REFCLSID clsid,
- HRESULT *phr);
- #endif
- ~CBaseFilter();
-
- DECLARE_IUNKNOWN
-
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
- #ifdef DEBUG
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- #endif
-
-
-
-
-
- STDMETHODIMP GetClassID(CLSID *pClsID);
-
-
-
- STDMETHODIMP GetState(DWORD dwMSecs, FILTER_STATE *State);
-
- STDMETHODIMP SetSyncSource(IReferenceClock *pClock);
-
- STDMETHODIMP GetSyncSource(IReferenceClock **pClock);
-
-
-
-
-
-
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
-
-
-
-
- STDMETHODIMP Run(REFERENCE_TIME tStart);
-
-
-
-
-
- virtual HRESULT StreamTime(CRefTime& rtStream);
-
-
- BOOL IsActive() {
- CAutoLock cObjectLock(m_pLock);
- return ((m_State == State_Paused) || (m_State == State_Running));
- };
-
-
- BOOL IsStopped() {
- return (m_State == State_Stopped);
- };
-
-
-
-
-
-
- STDMETHODIMP EnumPins(
- IEnumPins ** ppEnum);
-
-
-
- STDMETHODIMP FindPin(
- LPCWSTR Id,
- IPin ** ppPin
- );
-
- STDMETHODIMP QueryFilterInfo(
- FILTER_INFO * pInfo);
-
- STDMETHODIMP JoinFilterGraph(
- IFilterGraph * pGraph,
- LPCWSTR pName);
-
-
-
-
- STDMETHODIMP QueryVendorInfo(
- LPWSTR* pVendorInfo
- );
-
-
-
-
-
-
- HRESULT NotifyEvent(
- long EventCode,
- LONG_PTR EventParam1,
- LONG_PTR EventParam2);
-
-
- IFilterGraph *GetFilterGraph() {
- return m_pGraph;
- }
-
-
-
-
-
- HRESULT ReconnectPin(IPin *pPin, AM_MEDIA_TYPE const *pmt);
-
-
- virtual LONG GetPinVersion();
- void IncrementPinVersion();
-
-
-
- virtual int GetPinCount() PURE;
- virtual CBasePin *GetPin(int n) PURE;
-
-
-
- STDMETHODIMP Register();
- STDMETHODIMP Unregister();
-
-
-
-
- virtual LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
-
- };
CBaseFilter类的使用方法如下:
(1) 声明一个新类是从CBaseFilter中继承而来;
(2) 在新类中定义Filter上的Pin的实例(Pin从CBasePin类继承而来);
(3) 实现纯虚函数CBaseFilter::GetPin,用于返回Filter上各个Pin的对象指针;
(4) 实现纯虚函数CBaseFilter::GetPinCount,用于返回Filter上Pin 的数量;
(5) 考虑如何处理从输入Pin进来的Sample数据。
eg:
-
-
-
-
-
- class CAsyncReader : public CBaseFilter
- {
-
- protected:
-
- CCritSec m_csFilter;
-
-
- CAsyncIo m_Io;
-
-
-
- CAsyncOutputPin m_OutputPin;
-
-
- CMediaType m_mt;
-
- public:
-
-
-
- CAsyncReader(
- TCHAR *pName,
- LPUNKNOWN pUnk,
- CAsyncStream *pStream,
- HRESULT *phr);
-
- ~CAsyncReader();
-
-
-
-
- int GetPinCount();
- CBasePin *GetPin(int n);
-
-
- const CMediaType *LoadType() const
- {
- return &m_mt;
- }
-
- virtual HRESULT Connect(
- IPin * pReceivePin,
- const AM_MEDIA_TYPE *pmt
- )
- {
- return m_OutputPin.CBasePin::Connect(pReceivePin, pmt);
- }
- };
还有SDK类的CSource、CBaseRenderer、 CTracsformFilter都是从CBaseFilter继承来的,实现开发Filter时,
使用这些子类作为Filter类。
4、CBasePin
Filter 上最基本的Pin由CBasePin类(参见 amfilter.h)实现。
作为Pin的基本特征,CBasePin实现了IPin接口。CBasePin设计了Pin 的整个连接过程。
另外,这个类还实现了IQualityControl接口,该接口用于质量控制。
- class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
- {
-
- protected:
-
- WCHAR * m_pName;
- IPin *m_Connected;
- PIN_DIRECTION m_dir;
- CCritSec *m_pLock;
- bool m_bRunTimeError;
- bool m_bCanReconnectWhenActive;
- bool m_bTryMyTypesFirst;
-
- CBaseFilter *m_pFilter;
- IQualityControl *m_pQSink;
- LONG m_TypeVersion;
- CMediaType m_mt;
-
- CRefTime m_tStart;
- CRefTime m_tStop;
- double m_dRate;
-
- #ifdef DEBUG
- LONG m_cRef;
- #endif
-
-
-
- #ifdef DEBUG
- void DisplayPinInfo(IPin *pReceivePin);
- void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
- #else
- void DisplayPinInfo(IPin *pReceivePin) {};
- void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
- #endif
-
-
-
-
-
- HRESULT
- AttemptConnection(
- IPin* pReceivePin,
- const CMediaType* pmt
- );
-
-
-
- HRESULT TryMediaTypes(
- IPin *pReceivePin,
- const CMediaType *pmt,
- IEnumMediaTypes *pEnum);
-
-
-
-
-
- HRESULT AgreeMediaType(
- IPin *pReceivePin,
- const CMediaType *pmt);
-
- public:
-
- CBasePin(
- TCHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName,
- PIN_DIRECTION dir);
- #ifdef UNICODE
- CBasePin(
- CHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName,
- PIN_DIRECTION dir);
- #endif
- virtual ~CBasePin();
-
- DECLARE_IUNKNOWN
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
-
-
-
-
-
-
- STDMETHODIMP Connect(
- IPin * pReceivePin,
- const AM_MEDIA_TYPE *pmt
- );
-
-
- STDMETHODIMP ReceiveConnection(
- IPin * pConnector,
- const AM_MEDIA_TYPE *pmt
- );
-
- STDMETHODIMP Disconnect();
-
- STDMETHODIMP ConnectedTo(IPin **pPin);
-
- STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt);
-
- STDMETHODIMP QueryPinInfo(
- PIN_INFO * pInfo
- );
-
- STDMETHODIMP QueryDirection(
- PIN_DIRECTION * pPinDir
- );
-
- STDMETHODIMP QueryId(
- LPWSTR * Id
- );
-
-
- STDMETHODIMP QueryAccept(
- const AM_MEDIA_TYPE *pmt
- );
-
-
- STDMETHODIMP EnumMediaTypes(
- IEnumMediaTypes **ppEnum
- );
-
-
-
-
-
-
-
-
- STDMETHODIMP QueryInternalConnections(
- IPin* *apPin,
- ULONG *nPin
-
- ) { return E_NOTIMPL; }
-
-
- STDMETHODIMP EndOfStream(void);
-
-
-
-
-
-
-
- STDMETHODIMP NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
-
-
-
-
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
- STDMETHODIMP SetSink(IQualityControl * piqc);
-
-
-
-
- BOOL IsConnected(void) {return (m_Connected != NULL); };
-
- IPin * GetConnected() { return m_Connected; };
-
-
- BOOL IsStopped() {
- return (m_pFilter->m_State == State_Stopped);
- };
-
-
- virtual LONG GetMediaTypeVersion();
- void IncrementTypeVersion();
-
-
-
- virtual HRESULT Active(void);
-
-
- virtual HRESULT Inactive(void);
-
-
- virtual HRESULT Run(REFERENCE_TIME tStart);
-
-
- virtual HRESULT CheckMediaType(const CMediaType *) PURE;
-
-
- virtual HRESULT SetMediaType(const CMediaType *);
-
-
-
- virtual HRESULT CheckConnect(IPin *);
-
-
- virtual HRESULT BreakConnect();
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
-
- virtual HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);
-
-
- REFERENCE_TIME CurrentStopTime() {
- return m_tStop;
- }
- REFERENCE_TIME CurrentStartTime() {
- return m_tStart;
- }
- double CurrentRate() {
- return m_dRate;
- }
-
-
- LPWSTR Name() { return m_pName; };
-
-
- void SetReconnectWhenActive(bool bCanReconnect)
- {
- m_bCanReconnectWhenActive = bCanReconnect;
- }
-
- bool CanReconnectWhenActive()
- {
- return m_bCanReconnectWhenActive;
- }
-
- protected:
- STDMETHODIMP DisconnectInternal();
- };
在CBasePin实现的成员函数中,有3个与Filter的状态转换相对应。
-
-
- virtual HRESULT Active(void);
-
-
- virtual HRESULT Inactive(void);
-
-
- virtual HRESULT Run(REFERENCE_TIME tStart);
我们来看一下Filter的Stop的实现,实际上就是调用Filter的所有pin的Inactive函数
- STDMETHODIMP
- CBaseFilter::Stop()
- {
- CAutoLock cObjectLock(m_pLock);
- HRESULT hr = NOERROR;
-
-
- if (m_State != State_Stopped) {
- int cPins = GetPinCount();
- for (int c = 0; c < cPins; c++) {
-
- CBasePin *pPin = GetPin(c);
-
-
-
-
-
-
-
-
-
- if (pPin->IsConnected()) {
- HRESULT hrTmp = pPin->Inactive();
- if (FAILED(hrTmp) && SUCCEEDED(hr)) {
- hr = hrTmp;
- }
- }
- }
- }
-
-
- m_State = State_Stopped;
- return hr;
- }
在实际开发Filter的过程中,很有可能重写CBasePin::Inactive、 CBasePin::Active和CBasePin::Run这3个函数,以进行必要的初始化、释放资源等。
CBasePin类的使用方法如下:
(1) 从CBasePin派生一个子类;
(2) 实现纯虚函数CBasePIn::CheckMediaType,进行Pin连接时的媒体类型检查;
(3) 实现纯虚函数CBasePin::GetMediaType,提供Pin上的首选媒体类型。
(4) 实现IPin::BeginFlush和IPin::EndFlush两个函数。
(5) 可能需要重写的函数包括
CBasePin::Active() 实现资源分配
CBasePin::Inactive 实现资源释放
CBasePin::Run 在Filter运行前进行一些初始化
CBasePin::CheckConnect 连接时检查,如查询对方Pin上是否支持某个特殊接口
CBasePin::BreakConnect 断开连接,并进行必要的资源释放
CBasePin::CompleteConnect 完成连接时被调用,可以在这个函数中获得当前连接的媒体类型参数
CBasePin::EndOfStream 当上流数据全部传送完毕后被调用。
如果这个是Transform Filter,则将EndOfStream继续入下传送;
如果是Renderer Filter,需要向Filter Graph Manager发送一个EC_COMPLETE事件
CBasePin::Noftify 直接响应质量控制。
eg:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- class CAsyncOutputPin
- : public IAsyncReader,
- public CBasePin
- {
- protected:
- CAsyncReader* m_pReader;
- CAsyncIo * m_pIo;
-
-
-
-
-
-
- BOOL m_bQueriedForAsyncReader;
-
- HRESULT InitAllocator(IMemAllocator **ppAlloc);
-
- public:
-
- CAsyncOutputPin(
- HRESULT * phr,
- CAsyncReader *pReader,
- CAsyncIo *pIo,
- CCritSec * pLock);
-
- ~CAsyncOutputPin();
-
-
-
-
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID, void**);
-
-
- STDMETHODIMP Connect(
- IPin * pReceivePin,
- const AM_MEDIA_TYPE *pmt
- );
-
-
-
-
-
- HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
-
-
- HRESULT CheckMediaType(const CMediaType* pType);
-
-
- HRESULT CheckConnect(IPin *pPin)
- {
- m_bQueriedForAsyncReader = FALSE;
- return CBasePin::CheckConnect(pPin);
- }
-
-
- HRESULT CompleteConnect(IPin *pReceivePin)
- {
- if (m_bQueriedForAsyncReader) {
- return CBasePin::CompleteConnect(pReceivePin);
- } else {
-
- #ifdef VFW_E_NO_TRANSPORT
- return VFW_E_NO_TRANSPORT;
- #else
- return E_FAIL;
- #endif
- }
- }
-
-
- HRESULT BreakConnect()
- {
- m_bQueriedForAsyncReader = FALSE;
- return CBasePin::BreakConnect();
- }
-
-
-
-
-
-
-
- STDMETHODIMP RequestAllocator(
- IMemAllocator* pPreferred,
- ALLOCATOR_PROPERTIES* pProps,
- IMemAllocator ** ppActual);
-
-
-
-
-
-
-
-
- STDMETHODIMP Request(
- IMediaSample* pSample,
- DWORD_PTR dwUser);
-
-
-
-
-
-
- STDMETHODIMP WaitForNext(
- DWORD dwTimeout,
- IMediaSample** ppSample,
- DWORD_PTR * pdwUser);
-
-
-
-
-
- STDMETHODIMP SyncReadAligned(
- IMediaSample* pSample);
-
-
-
-
-
- STDMETHODIMP SyncRead(
- LONGLONG llPosition,
- LONG lLength,
- BYTE* pBuffer);
-
-
-
-
- STDMETHODIMP Length(
- LONGLONG* pTotal,
- LONGLONG* pAvailable);
-
-
-
-
- STDMETHODIMP BeginFlush(void);
- STDMETHODIMP EndFlush(void);
-
- };
5、 CBaseInputPin和CBaseOutputPin
从CBasePin类派生的,也是很基本的输入或输出pin。
它们的实现可参见 amfilter.cpp
CBaseInputPin实现了IMemInputPin(用于推模式的数据传送),
而CBaseOutputPin主要完成了传送数据所使用的Sample管理器(Allocator)的协商,并重写了CBasePin::Active(用于实际的Sample内存分配)
以及CBasePin::Inactive(用于Sample内存的释放)
- class AM_NOVTABLE CBaseInputPin : public CBasePin,
- public IMemInputPin
- {
-
- protected:
-
- IMemAllocator *m_pAllocator;
-
-
-
-
- BYTE m_bReadOnly;
-
-
-
- BYTE m_bFlushing;
-
-
- AM_SAMPLE2_PROPERTIES m_SampleProps;
-
- public:
-
- CBaseInputPin(
- TCHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName);
- #ifdef UNICODE
- CBaseInputPin(
- CHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName);
- #endif
- virtual ~CBaseInputPin();
-
- DECLARE_IUNKNOWN
-
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
-
-
-
- STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);
-
-
-
- STDMETHODIMP NotifyAllocator(
- IMemAllocator * pAllocator,
- BOOL bReadOnly);
-
-
- STDMETHODIMP Receive(IMediaSample *pSample);
-
-
- STDMETHODIMP ReceiveMultiple (
- IMediaSample **pSamples,
- long nSamples,
- long *nSamplesProcessed);
-
-
- STDMETHODIMP ReceiveCanBlock();
-
-
-
-
-
- STDMETHODIMP BeginFlush(void);
-
-
-
-
-
-
- STDMETHODIMP EndFlush(void);
-
-
-
-
-
- STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);
-
-
- HRESULT BreakConnect();
-
-
- BOOL IsReadOnly() {
- return m_bReadOnly;
- };
-
-
- BOOL IsFlushing() {
- return m_bFlushing;
- };
-
-
-
- virtual HRESULT CheckStreaming();
-
-
- HRESULT PassNotify(Quality& q);
-
-
-
-
-
-
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
-
-
-
-
-
- virtual HRESULT Inactive(void);
-
-
- AM_SAMPLE2_PROPERTIES * SampleProps() {
- ASSERT(m_SampleProps.cbData != 0);
- return &m_SampleProps;
- }
-
- };
- class AM_NOVTABLE CBaseOutputPin : public CBasePin
- {
-
- protected:
-
- IMemAllocator *m_pAllocator;
- IMemInputPin *m_pInputPin;
-
-
- public:
-
- CBaseOutputPin(
- TCHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName);
- #ifdef UNICODE
- CBaseOutputPin(
- CHAR *pObjectName,
- CBaseFilter *pFilter,
- CCritSec *pLock,
- HRESULT *phr,
- LPCWSTR pName);
- #endif
-
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
-
-
- virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);
-
-
-
-
-
-
- virtual HRESULT DecideBufferSize(
- IMemAllocator * pAlloc,
- ALLOCATOR_PROPERTIES * ppropInputRequest
- ) PURE;
-
-
- virtual HRESULT GetDeliveryBuffer(IMediaSample ** ppSample,
- REFERENCE_TIME * pStartTime,
- REFERENCE_TIME * pEndTime,
- DWORD dwFlags);
-
-
-
-
-
- virtual HRESULT Deliver(IMediaSample *);
-
-
- virtual HRESULT InitAllocator(IMemAllocator **ppAlloc);
- HRESULT CheckConnect(IPin *pPin);
- HRESULT BreakConnect();
-
-
- HRESULT Active(void);
- HRESULT Inactive(void);
-
-
-
- STDMETHODIMP EndOfStream(void);
-
-
-
- virtual HRESULT DeliverEndOfStream(void);
-
-
-
-
- STDMETHODIMP BeginFlush(void);
- STDMETHODIMP EndFlush(void);
- virtual HRESULT DeliverBeginFlush(void);
- virtual HRESULT DeliverEndFlush(void);
-
-
-
- virtual HRESULT DeliverNewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
-
-
-
-
-
-
-
- };
CBaseInputPin类的使用方法(派生一个子类,并且至少需要重写以下函数)如下:
(1) CBaseInputPin::BeginFlush
(2) CBaseInputPin::EndFlush
(3) CBaseInputPin::Receive
(4) CBaseInputPin::CheckMediaType
(5) CBaseInputPin::GetMediaType
eg:
- class CRendererInputPin : public CBaseInputPin
- {
- protected:
-
- CBaseRenderer *m_pRenderer;
-
- public:
-
- CRendererInputPin(CBaseRenderer *pRenderer,
- HRESULT *phr,
- LPCWSTR Name);
-
-
-
- HRESULT BreakConnect();
- HRESULT CompleteConnect(IPin *pReceivePin);
- HRESULT SetMediaType(const CMediaType *pmt);
- HRESULT CheckMediaType(const CMediaType *pmt);
- HRESULT Active();
- HRESULT Inactive();
-
-
-
- STDMETHODIMP QueryId(LPWSTR *Id);
- STDMETHODIMP EndOfStream();
- STDMETHODIMP BeginFlush();
- STDMETHODIMP EndFlush();
- STDMETHODIMP Receive(IMediaSample *pMediaSample);
-
-
- IMemAllocator inline *Allocator() const
- {
- return m_pAllocator;
- }
- };
CBaseOutputPin类的使用方法(派生一个子类,并且最少需要重写以下函数)如下:
(1) 重写CBasePin::CheckMediaType进行连接时媒体类型的检查;
(2) 实现纯虚函数CBaseOutputPin::DecideBufferSize,决定Sample内存的大小;
(3) 重写CBasePin::GetMediaType, 提供Pin 上的首选媒体类型。
- class CTransformOutputPin : public CBaseOutputPin
- {
- friend class CTransformFilter;
-
- protected:
- CTransformFilter *m_pTransformFilter;
-
- public:
-
-
- IUnknown * m_pPosition;
-
- CTransformOutputPin(
- TCHAR *pObjectName,
- CTransformFilter *pTransformFilter,
- HRESULT * phr,
- LPCWSTR pName);
- #ifdef UNICODE
- CTransformOutputPin(
- CHAR *pObjectName,
- CTransformFilter *pTransformFilter,
- HRESULT * phr,
- LPCWSTR pName);
- #endif
- ~CTransformOutputPin();
-
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
-
-
-
- STDMETHODIMP QueryId(LPWSTR * Id)
- {
- return AMGetWideString(L"Out", Id);
- }
-
-
-
- HRESULT CheckConnect(IPin *pPin);
- HRESULT BreakConnect();
- HRESULT CompleteConnect(IPin *pReceivePin);
-
-
- HRESULT CheckMediaType(const CMediaType* mtOut);
-
-
- HRESULT SetMediaType(const CMediaType *pmt);
-
-
-
- HRESULT DecideBufferSize(
- IMemAllocator * pAlloc,
- ALLOCATOR_PROPERTIES *pProp);
-
-
- HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);
-
-
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
-
- public:
- CMediaType& CurrentMediaType() { return m_mt; };
- };
===================================================================
如果开发的是一个Transform Filter,Filter的父类很多时候都是选择CTransformFilter或CTransInPlaceFilter,这种Filter的开发相对简单。
但有时,Filter框架不得不选择CBaseFilter、 CBaseInputPin、CBaseOutputFilter等类来实现,这就有点麻烦了。
这时候可以参考CTransformFilter、CTransformInputPin、CTransformOutputPin对上述3上基类的使用,以此来指导Filter的开发。
===================================================================
6、 CSource
DirectShow SDK还提供了其他更加实用的Filter类,如:
CSource、CTransformFilter、CTransInPlaceFilter、CVideoTransformFilter、 CBaseRender、CBase Video Render等。
它们的继承关系如图:
如上图所示,CSource类(参见source.cpp的实现)直接从CaseFilter中继承而来,一般作为推模式Source Filter的父类。
CSource类的使用方法如下:
(1)从CSource类中派生一个新的Filter类;
(2)在新的Filter类的构造函数中创建各个CSourceStream类实例(CSourceStream类的构造函数会自动将该Pin加入Filter中,并在析构函数中自动删除);
(3)使用CSource::pStateLock函数返回的同步对象进行Filter对象上的多线程同步。
注意: 使用CSource作为Filter父类的Filter未必就是Source Filter。在有些开发Transform Filter的应用中,输出Pin需要使用独立的线程。(即与输入Pin上传送数据
不同的线程)传关,也可以考虑使用CSource。
eg: 参照我的另一篇文章:
- class CPushSourceBitmap : public CSource
- {
-
- private:
-
- CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr);
- ~CPushSourceBitmap();
-
- CPushPinBitmap *m_pPin;
-
- public:
- static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
-
- };
- CPushSourceBitmap::CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr)
- : CSource(NAME("PushSourceBitmap"), pUnk, CLSID_PushSourceBitmap)
- {
-
- m_pPin = new CPushPinBitmap(phr, this);
-
- if (phr)
- {
- if (m_pPin == NULL)
- *phr = E_OUTOFMEMORY;
- else
- *phr = S_OK;
- }
- }
7 、 CSourceStream
CSource实际上继承自CBaseFilter,提供了一个“推”数据的能力,这种Filter至少有一个输出
Pin采用了CSourecStream类(或CSourceStream的子类)。如下图所示:
CSourceStream上实现了一个线程(CSourceStream从CAMThread类继承而来),Sample数据就是靠这个线程向一线Filter发送的。
CSourceStream类的使用方法如下:
(1)从CSourceStream派生一个输出Pin类;
(2)重写CSourceStream::GetMediaType,提供输出Pin上的首选媒体类型;
(3)重写CSourceStream::CheckMediaType,进行连续时媒体类型的检查;(可选)
(4)实现CBaseOutPin::DecideBufferSize,决定Sample内存的大小;
(5)实现CSourceStream::FillBuffer,为即将传送出去的Sample 填充数据;
(6)可选地实现CSourceStream::OnThreadCreate、CSourceSream::OnThreadDestroy、CSourceStream::OnThreadStartPlay等函数,
进行适当时节的初始化、资源管理等操作。
eg: 参照我的另一篇文章:
- class CPushPinBitmap : public CSourceStream
- {
- protected:
-
- int m_FramesWritten;
- BOOL m_bZeroMemory;
- CRefTime m_rtSampleTime;
-
- BITMAPINFO *m_pBmi;
- DWORD m_cbBitmapInfo;
-
-
- HANDLE m_hFile;
- BYTE * m_pFile;
- BYTE * m_pImage;
-
- int m_iFrameNumber;
- const REFERENCE_TIME m_rtFrameLength;
-
- CCritSec m_cSharedState;
- CImageDisplay m_Display;
-
- public:
-
- CPushPinBitmap(HRESULT *phr, CSource *pFilter);
- ~CPushPinBitmap();
-
-
- HRESULT GetMediaType(CMediaType *pMediaType);
- HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
- HRESULT FillBuffer(IMediaSample *pSample);
-
-
-
-
-
- STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
- {
- return E_FAIL;
- }
-
- };
8、 CTransformFilter
CTransformFilter类是开发Transform Filter最基本的类,也是最常用到的类。结构如下:
它有一个输入Pin和一个输出Pin,分别使用CTransformInputPin类和CTransformOutputPin类。
从图4.8和图4.9可以看出,
CTransformFilter从CBaseFilter继承而来,
CTransformInputPin从CBaseInputPin继承而来,
CTransformOutputPin从CBaseOutputPin继承而来。另个,在CTransformOutputPin上还实现了IMdiaSeeking 和 IMediaPosition接口。
(其实,CTransformOutputPin并没有真正实现各个Seek操作。在实际的Seek操作请发生时,CTransformOutpPin会将这些操作请求转发给上一级Filter的输出Pin)。
CTransformFilter实现的最大特征是,它将Pin上必须实现的函数都“委托”到了Filter上(Pin上必须实现的函数在Filter上有类似的函数定义)。
一般无须重写输入和输出Pin类,而只须在Filter上实现相应的函数就行了)。
提示:CTransformFilter默认在GetPin函数实现中创建输入和输出Pin。因此,如果重写了自己的输入或输出Pin类,需要重写GetPin函数。
CTransformFilter类的使用方法(派生一个Filter子类,且最少需要重写以下函数):
(1)CTransformFilter::CheckInputType
(2)CTransformFilter::CheckTransform
(3)CTransformFilter::DecideBufferSize
(4)CTransformFilter::GetMeiaType
(5)CTransformFilter::Transform
eg:CVideoTransformFilter虽然没有实现上面五个函数,但CVideoTransformFilter 的继承类去实现它们。
9、 CTransInPlaceFilter
CTransInPlaceFilter是一个“就地”处理的Transform Filter类。结构如下:
与CTransformFilter,CTransInPlaceFilter也有一个输入Pin和一个输出Pin,但使用CTransInPlaceOutputPin类。
CTransInPlaceFilter的输入和输出Pin上一般使用相同的媒体类型进行连接,并且使用同一个Sample管理器(如果Filter实现时要修改Sample数据,
而协商达成一致的Sample管理器只读的,那么CTransInPlaceFilter的输入和输出Pin将不得不使用各自的Sample管理器)。
CTransInPlaceFilter类要实现上述的目标,主要依赖于CTransInPlaceFilter::CompleteConnect、CTransInPlaceInputPin::GetAllocator和
CTransInPlaceInputPin::NotifyAlocator的函数实现。代码如下:
-
-
- HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin)
- {
- UNREFERENCED_PARAMETER(pReceivePin);
- ASSERT(m_pInput);
- ASSERT(m_pOutput);
-
-
-
- if (!m_pGraph) {
- return VFW_E_NOT_IN_GRAPH;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (dir == PINDIR_OUTPUT) {
- if( m_pInput->IsConnected() ) {
- return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );
- }
- return NOERROR;
- }
-
- ASSERT(dir == PINDIR_INPUT);
-
-
-
-
-
- if( m_pOutput->IsConnected() ) {
-
- if ( m_pInput->CurrentMediaType()
- != m_pOutput->CurrentMediaType()
- ) {
- return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );
- }
- }
- return NOERROR;
-
- }
-
-
-
- STDMETHODIMP CTransInPlaceInputPin::GetAllocator(IMemAllocator ** ppAllocator)
- {
- CheckPointer(ppAllocator,E_POINTER);
- ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
- CAutoLock cObjectLock(m_pLock);
-
- HRESULT hr;
-
- if ( m_pTIPFilter->m_pOutput->IsConnected() ) {
-
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->GetAllocator( ppAllocator );
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator );
- }
- }
- else {
-
-
-
-
- hr = CTransformInputPin::GetAllocator( ppAllocator );
- }
- return hr;
-
- }
-
-
-
- STDMETHODIMP
- CTransInPlaceInputPin::NotifyAllocator(
- IMemAllocator * pAllocator,
- BOOL bReadOnly)
- {
- HRESULT hr = S_OK;
- CheckPointer(pAllocator,E_POINTER);
- ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
-
- CAutoLock cObjectLock(m_pLock);
-
- m_bReadOnly = bReadOnly;
-
-
-
-
-
-
- if (!m_pTIPFilter->OutputPin()->IsConnected()) {
- return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly);
- }
-
-
-
-
- if (bReadOnly && m_pTIPFilter->m_bModifiesData) {
- IMemAllocator *pOutputAllocator =
- m_pTIPFilter->OutputPin()->PeekAllocator();
-
-
- if (pOutputAllocator == NULL) {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()->
- GetAllocator(&pOutputAllocator);
- if(FAILED(hr)) {
- hr = CreateMemoryAllocator(&pOutputAllocator);
- }
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator);
- pOutputAllocator->Release();
- }
- }
- if (pAllocator == pOutputAllocator) {
- hr = E_FAIL;
- } else if(SUCCEEDED(hr)) {
-
- ALLOCATOR_PROPERTIES Props, Actual;
- hr = pAllocator->GetProperties(&Props);
- if (SUCCEEDED(hr)) {
- hr = pOutputAllocator->SetProperties(&Props, &Actual);
- }
- if (SUCCEEDED(hr)) {
- if ( (Props.cBuffers > Actual.cBuffers)
- || (Props.cbBuffer > Actual.cbBuffer)
- || (Props.cbAlign > Actual.cbAlign)
- ) {
- hr = E_FAIL;
- }
- }
-
-
- if (SUCCEEDED(hr)) {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->NotifyAllocator( pOutputAllocator, FALSE );
- }
- }
- } else {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->NotifyAllocator( pAllocator, bReadOnly );
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator( pAllocator );
- }
- }
-
- if (SUCCEEDED(hr)) {
-
-
-
- pAllocator->AddRef();
-
- if( m_pAllocator != NULL )
- m_pAllocator->Release();
-
- m_pAllocator = pAllocator;
- }
-
- return hr;
-
- }
CTransInPlaceFilter类定义了一个成员变量m_bModifiesData ,用于指示我们在Filter中是否会修改Saple 数据。
这个变量在CTransInPlaceFilter构造函数调用时被默认初始化为true。如果我们确定不会在Filter中修改Sample数据,
那么,将m_bModifiesData设置为false, 可以保证输入和输出Pin连接完成后使用同一个Sample管理器。
10、 CVideoTransformFilter
CVieoTransformFilter是一个实现了视频的质量控制的Transform Filter类。其结构如下:
CVieoTransformFilter通过输入Pin上的Receive 函数接收Sample时,能够根据质量消息决定是否丢帧。这个类主要是为开发AVI解码Filter而设计的。
CVieoTransformFilter类的使用基本上与CTransformFilter相同。
11、 CBaseRenderer
CBaseRender是最基本的实现Renderer Filter的类。它默认实现了一个使用CRendererInputPin类的输入Pin(Renderer Filter没有输出Pin)。
这两个类的结构如下:
从图中可以看出,CBaseRenderer从CBaseFilter继承而来。另外,CBaseRenderer上还实现了IMediaSeekin和IMediaPosition接口。
CRendererInputPin从CBaseInputPin 继承而来,它把各个主要函数调用都“委托”到Filter上。值得注意的是,当输入Pin接收到EndOfStream调用时,
Renderer Filter 有责任向Filter Graph Manager发送一个EC_COMPLETE事件。
CBaseRenderer类的使用方法(派生一个子类,并至少实现如下函数)如下:
(1)CBaseRenderer::CheckMediaType,用于检查输入Pin连接用的媒体类型;
(2)CBaseRenderer::DoRenderSample,处理当前的Sample。
提示:CBaseRenderer实际上是为了用于播放的Render Filter设计的,对于Sample的安排比较复杂。
如果我们要开发Renderer Filter不播放Sample(比如写文件的Filter、或者负责网络的Filter),Fitler的基类可以选择CBaseFilter,而此时输入Pin最
好选择CRenderedInputPin类派生。
12、CBaseVideoRenderer
CBaseVideoRenderer是一个实现Video Renderer类的基类,结构如下:
CBaseVideoRenderer在CBaseRenderer的基础上增加了IQualityControl和IQualProp接口的实现。
其中IQualityControl用于视频质量控制,IQualProp用于在Filter属性页显示一些实时性能参数。CBaseVideoRenderer类的使用方法基本上与CBaseRenderer相同。
在DirectShow SDK基类库中,除了上述Filter和Pin类外,还有很多工具类,有了这些类的支持,我们开发Fitler或DirectShow应用程序会更加轻松。
这些类包括: CPullPin、 COutputQueue、 CSourceSeeking 、CEnumPins、 CEnumMediaTypes 、CMemAllocator 、 CMediaSample 、
CBaseReferenceClock 、CMediaType、 CBasePropertyPage 等。
Filter组件开发中的SDK基类分析
标签:des style blog http color io os 使用 ar
原文地址:http://blog.csdn.net/mao0514/article/details/39932365