Filter组件开发中的SDK基类分析

DirectShow SDK提供了一套开发Filter的基类源代码。基于这些基类开发Filter将大大简化开发过程。

1、CBaseObject

大部分SDK类都从CBaseObject类(参见combase.h)中继承而来的。

[cpp] view plaincopy

  1. class CBaseObject  
  2. {  
  3.   
  4. private:  
  5.   
  6.     // Disable the copy constructor and assignment by default so you will get  
  7.     //   compiler errors instead of unexpected behaviour if you pass objects  
  8.     //   by value or assign objects.  
  9.     CBaseObject(const CBaseObject& objectSrc);          // no implementation  
  10.     void operator=(const CBaseObject& objectSrc);       // no implementation  
  11.   
  12. private:  
  13.     static LONG m_cObjects;     /* Total number of objects active */  
  14.   
  15. protected:  
  16. #ifdef DEBUG  
  17.     DWORD m_dwCookie;           /* Cookie identifying this object */  
  18. #endif  
  19.   
  20.   
  21. public:  
  22.   
  23.     /* These increment and decrement the number of active objects */  
  24.   
  25.     CBaseObject(const TCHAR *pName);  
  26. #ifdef UNICODE  
  27.     CBaseObject(const char *pName);  
  28. #endif  
  29.     ~CBaseObject();  
  30.   
  31.     /* Call this to find if there are any CUnknown derived objects active */  
  32.   
  33.     static LONG ObjectsActive() {  
  34.         return m_cObjects;  
  35.     };  
  36. };  
2、 CUnknown

作为COM组件(参见combase.cpp文件),最基本的当然是IUnknown接口的实现。SDK提供了CUnknown类,SDK实现了COM接口类都是直接或间接从这个类继承来的。

[cpp] view plaincopy

  1. class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,  
  2.                  public CBaseObject  
  3. {  
  4. private:  
  5.     const LPUNKNOWN m_pUnknown; /* Owner of this object */  
  6.   
  7. protected:                      /* So we can override NonDelegatingRelease() */  
  8.     volatile LONG m_cRef;       /* Number of reference counts */  
  9.   
  10. public:  
  11.   
  12.     CUnknown(const TCHAR *pName, LPUNKNOWN pUnk);  
  13.     virtual ~CUnknown() {};  
  14.   
  15.     // This is redundant, just use the other constructor  
  16.     //   as we never touch the HRESULT in this anyway  
  17.     CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr);  
  18. #ifdef UNICODE  
  19.     CUnknown(const char *pName, LPUNKNOWN pUnk);  
  20.     CUnknown(char *pName, LPUNKNOWN pUnk,HRESULT *phr);  
  21. #endif  
  22.   
  23.     /* Return the owner of this object */  
  24.   
  25.     LPUNKNOWN GetOwner() const {  
  26.         return m_pUnknown;  
  27.     };  
  28.   
  29.     /* Called from the class factory to create a new instance, it is 
  30.        pure virtual so it must be overriden in your derived class */  
  31.   
  32.     /* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */  
  33.   
  34.     /* Non delegating unknown implementation */  
  35.   
  36.     STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);  
  37.     STDMETHODIMP_(ULONG) NonDelegatingAddRef();  
  38.     STDMETHODIMP_(ULONG) NonDelegatingRelease();  
  39. };  

CUnknown类从CBaseObject中继承而来,另外CUnknown类还实现了INonDelegatingUnknown接口,用于支持引用计数、接口查询、COM组件“聚合”等。

CUnknown类的使用方法如下:

(1) 从CUnknown派生一个子类,并在子类的public区加入DECLARE_IUNKNOWN宏;

(2) 重写NonDelegatingQueryInterface函数,用以支持IUnknown外的其他接口;

(3) 在子类的构造函数中调用CUnknown的构造函数。

eg:

[cpp] view plaincopy

  1. class CSeekingPassThru : public ISeekingPassThru, public CUnknown  
  2. {  
  3. public:  
  4.     static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);  
  5.     CSeekingPassThru(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);  
  6.     ~CSeekingPassThru();  
  7.   
  8.     DECLARE_IUNKNOWN;  
  9.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);  
  10.   
  11.     STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);  
  12.   
  13. private:  
  14.     CPosPassThru              *m_pPosPassThru;  
  15. };  

 

[cpp] view plaincopy

  1. CSeekingPassThru::CSeekingPassThru( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr )  
  2.                             : CUnknown(pName, pUnk, phr),  
  3.                             m_pPosPassThru(NULL)  
  4. {  
  5. }  
3、 CBaseFilter

最基本的Filter由CBaseFilter 类(参见amfilter.cpp)实现。

作为Filter的基本特征,CBaseFilter实现了IBaseFilter接口(IbaseFilter从IMediaFilter继承而来)。

同时CBaseFilter还实现了Filter框架(描述了各个Pin组件的情况)。

[cpp] view plaincopy

  1. class AM_NOVTABLE CBaseFilter : public CUnknown,        // Handles an IUnknown  
  2.                     public IBaseFilter,     // The Filter Interface  
  3.                     public IAMovieSetup     // For un/registration  
  4. {  
  5.   
  6. friend class CBasePin;  
  7.   
  8. protected:  
  9.     FILTER_STATE    m_State;            // current state: running, paused  
  10.     IReferenceClock *m_pClock;          // this graph's ref clock  
  11.     CRefTime        m_tStart;           // offset from stream time to reference time  
  12.     CLSID       m_clsid;            // This filters clsid  
  13.                                         // used for serialization  
  14.     CCritSec        *m_pLock;           // Object we use for locking  
  15.   
  16.     WCHAR           *m_pName;           // Full filter name  
  17.     IFilterGraph    *m_pGraph;          // Graph we belong to  
  18.     IMediaEventSink *m_pSink;           // Called with notify events  
  19.     LONG            m_PinVersion;       // Current pin version  
  20.   
  21. public:  
  22.   
  23.     CBaseFilter(  
  24.         const TCHAR *pName,     // Object description  
  25.         LPUNKNOWN pUnk,         // IUnknown of delegating object  
  26.         CCritSec  *pLock,       // Object who maintains lock  
  27.     REFCLSID   clsid);      // The clsid to be used to serialize this filter  
  28.   
  29.     CBaseFilter(  
  30.         TCHAR     *pName,       // Object description  
  31.         LPUNKNOWN pUnk,         // IUnknown of delegating object  
  32.         CCritSec  *pLock,       // Object who maintains lock  
  33.     REFCLSID   clsid,       // The clsid to be used to serialize this filter  
  34.         HRESULT   *phr);        // General OLE return code  
  35. #ifdef UNICODE  
  36.     CBaseFilter(  
  37.         const CHAR *pName,     // Object description  
  38.         LPUNKNOWN pUnk,         // IUnknown of delegating object  
  39.         CCritSec  *pLock,       // Object who maintains lock  
  40.     REFCLSID   clsid);      // The clsid to be used to serialize this filter  
  41.   
  42.     CBaseFilter(  
  43.         CHAR     *pName,       // Object description  
  44.         LPUNKNOWN pUnk,         // IUnknown of delegating object  
  45.         CCritSec  *pLock,       // Object who maintains lock  
  46.     REFCLSID   clsid,       // The clsid to be used to serialize this filter  
  47.         HRESULT   *phr);        // General OLE return code  
  48. #endif  
  49.     ~CBaseFilter();  
  50.   
  51.     DECLARE_IUNKNOWN  
  52.   
  53.     // override this to say what interfaces we support where  
  54.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);  
  55. #ifdef DEBUG  
  56.     STDMETHODIMP_(ULONG) NonDelegatingRelease();  
  57. #endif  
  58.   
  59.     //  
  60.     // --- IPersist method ---  
  61.     //  
  62.   
  63.     STDMETHODIMP GetClassID(CLSID *pClsID);  
  64.   
  65.     // --- IMediaFilter methods ---  
  66.   
  67.     STDMETHODIMP GetState(DWORD dwMSecs, FILTER_STATE *State);  
  68.   
  69.     STDMETHODIMP SetSyncSource(IReferenceClock *pClock);  
  70.   
  71.     STDMETHODIMP GetSyncSource(IReferenceClock **pClock);  
  72.   
  73.   
  74.     // override Stop and Pause so we can activate the pins.  
  75.     // Note that Run will call Pause first if activation needed.  
  76.     // Override these if you want to activate your filter rather than  
  77.     // your pins.  
  78.     STDMETHODIMP Stop();  
  79.     STDMETHODIMP Pause();  
  80.   
  81.     // the start parameter is the difference to be added to the  
  82.     // sample's stream time to get the reference time for  
  83.     // its presentation  
  84.     STDMETHODIMP Run(REFERENCE_TIME tStart);  
  85.   
  86.     // --- helper methods ---  
  87.   
  88.     // return the current stream time - ie find out what  
  89.     // stream time should be appearing now  
  90.     virtual HRESULT StreamTime(CRefTime& rtStream);  
  91.   
  92.     // Is the filter currently active?  
  93.     BOOL IsActive() {  
  94.         CAutoLock cObjectLock(m_pLock);  
  95.         return ((m_State == State_Paused) || (m_State == State_Running));  
  96.     };  
  97.   
  98.     // Is this filter stopped (without locking)  
  99.     BOOL IsStopped() {  
  100.         return (m_State == State_Stopped);  
  101.     };  
  102.   
  103.     //  
  104.     // --- IBaseFilter methods ---  
  105.     //  
  106.   
  107.     // pin enumerator  
  108.     STDMETHODIMP EnumPins(  
  109.                     IEnumPins ** ppEnum);  
  110.   
  111.   
  112.     // default behaviour of FindPin assumes pin ids are their names  
  113.     STDMETHODIMP FindPin(  
  114.         LPCWSTR Id,  
  115.         IPin ** ppPin  
  116.     );  
  117.   
  118.     STDMETHODIMP QueryFilterInfo(  
  119.                     FILTER_INFO * pInfo);  
  120.   
  121.     STDMETHODIMP JoinFilterGraph(  
  122.                     IFilterGraph * pGraph,  
  123.                     LPCWSTR pName);  
  124.   
  125.     // return a Vendor information string. Optional - may return E_NOTIMPL.  
  126.     // memory returned should be freed using CoTaskMemFree  
  127.     // default implementation returns E_NOTIMPL  
  128.     STDMETHODIMP QueryVendorInfo(  
  129.                     LPWSTR* pVendorInfo  
  130.             );  
  131.   
  132.     // --- helper methods ---  
  133.   
  134.     // send an event notification to the filter graph if we know about it.  
  135.     // returns S_OK if delivered, S_FALSE if the filter graph does not sink  
  136.     // events, or an error otherwise.  
  137.     HRESULT NotifyEvent(  
  138.         long EventCode,  
  139.         LONG_PTR EventParam1,  
  140.         LONG_PTR EventParam2);  
  141.   
  142.     // return the filter graph we belong to  
  143.     IFilterGraph *GetFilterGraph() {  
  144.         return m_pGraph;  
  145.     }  
  146.   
  147.     // Request reconnect  
  148.     // pPin is the pin to reconnect  
  149.     // pmt is the type to reconnect with - can be NULL  
  150.     // Calls ReconnectEx on the filter graph  
  151.     HRESULT ReconnectPin(IPin *pPin, AM_MEDIA_TYPE const *pmt);  
  152.   
  153.     // find out the current pin version (used by enumerators)  
  154.     virtual LONG GetPinVersion();  
  155.     void IncrementPinVersion();  
  156.   
  157.     // you need to supply these to access the pins from the enumerator  
  158.     // and for default Stop and Pause/Run activation.  
  159.     virtual int GetPinCount() PURE;  
  160.     virtual CBasePin *GetPin(int n) PURE;  
  161.   
  162.     // --- IAMovieSetup methods ---  
  163.   
  164.     STDMETHODIMP Register();    // ask filter to register itself  
  165.     STDMETHODIMP Unregister();  // and unregister itself  
  166.   
  167.     // --- setup helper methods ---  
  168.     // (override to return filters setup data)  
  169.   
  170.     virtual LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }  
  171.   
  172. };  

CBaseFilter类的使用方法如下:

(1) 声明一个新类是从CBaseFilter中继承而来;

(2) 在新类中定义Filter上的Pin的实例(Pin从CBasePin类继承而来);

(3) 实现纯虚函数CBaseFilter::GetPin,用于返回Filter上各个Pin的对象指针;

(4) 实现纯虚函数CBaseFilter::GetPinCount,用于返回Filter上Pin 的数量;

(5) 考虑如何处理从输入Pin进来的Sample数据。

eg:

[cpp] view plaincopy

  1. //  
  2. // The filter object itself. Supports IBaseFilter through  
  3. // CBaseFilter and also IFileSourceFilter directly in this object  
  4. // CAsyncReader类实现了一个Filter,它从CBaseFilter派生,实现了仅含一个输出  
  5. // Pin(CAsyncOutputPin类的实例)的Source filter框架。  
  6. class CAsyncReader : public CBaseFilter  
  7. {  
  8.   
  9. protected:  
  10.     // filter-wide lock  
  11.     CCritSec m_csFilter;  
  12.   
  13.     // all i/o done here  
  14.     CAsyncIo m_Io;  
  15.   
  16.     // (2)在新类中定义Filter上的Pin的实例(Pin从CBasePin类继承而来);  
  17.     // our output pin  
  18.     CAsyncOutputPin m_OutputPin;  
  19.   
  20.     // Type we think our data is  
  21.     CMediaType m_mt;  
  22.   
  23. public:  
  24.           
  25.     // construction / destruction  
  26.   
  27.     CAsyncReader(  
  28.         TCHAR *pName,  
  29.         LPUNKNOWN pUnk,  
  30.         CAsyncStream *pStream, // 它是Filter获取数据的源  
  31.         HRESULT *phr);  
  32.   
  33.     ~CAsyncReader();  
  34.   
  35.   
  36.     //(3) 实现纯虚函数CBaseFilter::GetPin,用于返回Filter上各个Pin的对象指针;  
  37.     //(4) 实现纯虚函数CBaseFilter::GetPinCount,用于返回Filter上Pin 的数量;  
  38.     int GetPinCount();  
  39.     CBasePin *GetPin(int n);  
  40.   
  41.     // --- Access our media type  
  42.     const CMediaType *LoadType() const  
  43.     {  
  44.         return &m_mt;  
  45.     }  
  46.   
  47.     virtual HRESULT Connect(  
  48.         IPin * pReceivePin,  
  49.         const AM_MEDIA_TYPE *pmt   // optional media type  
  50.     )  
  51.     {  
  52.         return m_OutputPin.CBasePin::Connect(pReceivePin, pmt);  
  53.     }  
  54. };  

还有SDK类的CSource、CBaseRenderer、 CTracsformFilter都是从CBaseFilter继承来的,实现开发Filter时,

使用这些子类作为Filter类。

4、CBasePin

Filter  上最基本的Pin由CBasePin类(参见 amfilter.h)实现。

作为Pin的基本特征,CBasePin实现了IPin接口。CBasePin设计了Pin 的整个连接过程。

另外,这个类还实现了IQualityControl接口,该接口用于质量控制。

[cpp] view plaincopy

  1. class  AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl  
  2. {  
  3.   
  4. protected:  
  5.   
  6.     WCHAR *         m_pName;                // This pin's name  
  7.     IPin            *m_Connected;               // Pin we have connected to  
  8.     PIN_DIRECTION   m_dir;                      // Direction of this pin  
  9.     CCritSec        *m_pLock;                   // Object we use for locking  
  10.     bool            m_bRunTimeError;            // Run time error generated  
  11.     bool            m_bCanReconnectWhenActive;  // OK to reconnect when active  
  12.     bool            m_bTryMyTypesFirst;         // When connecting enumerate  
  13.                                                 // this pin's types first  
  14.     CBaseFilter    *m_pFilter;                  // Filter we were created by  
  15.     IQualityControl *m_pQSink;                  // Target for Quality messages  
  16.     LONG            m_TypeVersion;              // Holds current type version  
  17.     CMediaType      m_mt;                       // Media type of connection  
  18.   
  19.     CRefTime        m_tStart;                   // time from NewSegment call  
  20.     CRefTime        m_tStop;                    // time from NewSegment  
  21.     double          m_dRate;                    // rate from NewSegment  
  22.   
  23. #ifdef DEBUG  
  24.     LONG            m_cRef;                     // Ref count tracing  
  25. #endif  
  26.   
  27.     // displays pin connection information  
  28.   
  29. #ifdef DEBUG  
  30.     void DisplayPinInfo(IPin *pReceivePin);  
  31.     void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);  
  32. #else  
  33.     void DisplayPinInfo(IPin *pReceivePin) {};  
  34.     void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};  
  35. #endif  
  36.   
  37.     // used to agree a media type for a pin connection  
  38.   
  39.     // given a specific media type, attempt a connection (includes  
  40.     // checking that the type is acceptable to this pin)  
  41.     HRESULT  
  42.     AttemptConnection(  
  43.         IPin* pReceivePin,      // connect to this pin  
  44.         const CMediaType* pmt   // using this type  
  45.     );  
  46.   
  47.     // try all the media types in this enumerator - for each that  
  48.     // we accept, try to connect using ReceiveConnection.  
  49.     HRESULT TryMediaTypes(  
  50.                         IPin *pReceivePin,      // connect to this pin  
  51.                         const CMediaType *pmt,        // proposed type from Connect  
  52.                         IEnumMediaTypes *pEnum);    // try this enumerator  
  53.   
  54.     // establish a connection with a suitable mediatype. Needs to  
  55.     // propose a media type if the pmt pointer is null or partially  
  56.     // specified - use TryMediaTypes on both our and then the other pin's  
  57.     // enumerator until we find one that works.  
  58.     HRESULT AgreeMediaType(  
  59.                         IPin *pReceivePin,      // connect to this pin  
  60.                         const CMediaType *pmt);       // proposed type from Connect  
  61.   
  62. public:  
  63.   
  64.     CBasePin(  
  65.         TCHAR *pObjectName,         // Object description  
  66.         CBaseFilter *pFilter,       // Owning filter who knows about pins  
  67.         CCritSec *pLock,            // Object who implements the lock  
  68.         HRESULT *phr,               // General OLE return code  
  69.         LPCWSTR pName,              // Pin name for us  
  70.         PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT  
  71. #ifdef UNICODE  
  72.     CBasePin(  
  73.         CHAR *pObjectName,         // Object description  
  74.         CBaseFilter *pFilter,       // Owning filter who knows about pins  
  75.         CCritSec *pLock,            // Object who implements the lock  
  76.         HRESULT *phr,               // General OLE return code  
  77.         LPCWSTR pName,              // Pin name for us  
  78.         PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT  
  79. #endif  
  80.     virtual ~CBasePin();  
  81.   
  82.     DECLARE_IUNKNOWN  
  83.   
  84.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);  
  85.     STDMETHODIMP_(ULONG) NonDelegatingRelease();  
  86.     STDMETHODIMP_(ULONG) NonDelegatingAddRef();  
  87.   
  88.     // --- IPin methods ---  
  89.   
  90.     // take lead role in establishing a connection. Media type pointer  
  91.     // may be null, or may point to partially-specified mediatype  
  92.     // (subtype or format type may be GUID_NULL).  
  93.     STDMETHODIMP Connect(  
  94.         IPin * pReceivePin,  
  95.         const AM_MEDIA_TYPE *pmt   // optional media type  
  96.     );  
  97.   
  98.     // (passive) accept a connection from another pin  
  99.     STDMETHODIMP ReceiveConnection(  
  100.         IPin * pConnector,      // this is the initiating connecting pin  
  101.         const AM_MEDIA_TYPE *pmt   // this is the media type we will exchange  
  102.     );  
  103.   
  104.     STDMETHODIMP Disconnect();  
  105.   
  106.     STDMETHODIMP ConnectedTo(IPin **pPin);  
  107.   
  108.     STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt);  
  109.   
  110.     STDMETHODIMP QueryPinInfo(  
  111.         PIN_INFO * pInfo  
  112.     );  
  113.   
  114.     STDMETHODIMP QueryDirection(  
  115.         PIN_DIRECTION * pPinDir  
  116.     );  
  117.   
  118.     STDMETHODIMP QueryId(  
  119.         LPWSTR * Id  
  120.     );  
  121.   
  122.     // does the pin support this media type  
  123.     STDMETHODIMP QueryAccept(  
  124.         const AM_MEDIA_TYPE *pmt  
  125.     );  
  126.   
  127.     // return an enumerator for this pins preferred media types  
  128.     STDMETHODIMP EnumMediaTypes(  
  129.         IEnumMediaTypes **ppEnum  
  130.     );  
  131.   
  132.     // return an array of IPin* - the pins that this pin internally connects to  
  133.     // All pins put in the array must be AddReffed (but no others)  
  134.     // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE  
  135.     // Default: return E_NOTIMPL  
  136.     // The filter graph will interpret NOT_IMPL as any input pin connects to  
  137.     // all visible output pins and vice versa.  
  138.     // apPin can be NULL if nPin==0 (not otherwise).  
  139.     STDMETHODIMP QueryInternalConnections(  
  140.         IPin* *apPin,     // array of IPin*  
  141.         ULONG *nPin       // on input, the number of slots  
  142.                           // on output  the number of pins  
  143.     ) { return E_NOTIMPL; }  
  144.   
  145.     // Called when no more data will be sent  
  146.     STDMETHODIMP EndOfStream(void);  
  147.   
  148.     // Begin/EndFlush still PURE  
  149.   
  150.     // NewSegment notifies of the start/stop/rate applying to the data  
  151.     // about to be received. Default implementation records data and  
  152.     // returns S_OK.  
  153.     // Override this to pass downstream.  
  154.     STDMETHODIMP NewSegment(  
  155.                     REFERENCE_TIME tStart,  
  156.                     REFERENCE_TIME tStop,  
  157.                     double dRate);  
  158.   
  159.     //================================================================================  
  160.     // IQualityControl methods  
  161.     //================================================================================  
  162.   
  163.     STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);  
  164.   
  165.     STDMETHODIMP SetSink(IQualityControl * piqc);  
  166.   
  167.     // --- helper methods ---  
  168.   
  169.     // Returns true if the pin is connected. false otherwise.  
  170.     BOOL IsConnected(void) {return (m_Connected != NULL); };  
  171.     // Return the pin this is connected to (if any)  
  172.     IPin * GetConnected() { return m_Connected; };  
  173.   
  174.     // Check if our filter is currently stopped  
  175.     BOOL IsStopped() {  
  176.         return (m_pFilter->m_State == State_Stopped);  
  177.     };  
  178.   
  179.     // find out the current type version (used by enumerators)  
  180.     virtual LONG GetMediaTypeVersion();  
  181.     void IncrementTypeVersion();  
  182.   
  183.     // switch the pin to active (paused or running) mode  
  184.     // not an error to call this if already active  
  185.     virtual HRESULT Active(void);  
  186.   
  187.     // switch the pin to inactive state - may already be inactive  
  188.     virtual HRESULT Inactive(void);  
  189.   
  190.     // Notify of Run() from filter  
  191.     virtual HRESULT Run(REFERENCE_TIME tStart);  
  192.   
  193.     // check if the pin can support this specific proposed type and format  
  194.     virtual HRESULT CheckMediaType(const CMediaType *) PURE;  
  195.   
  196.     // set the connection to use this format (previously agreed)  
  197.     virtual HRESULT SetMediaType(const CMediaType *);  
  198.   
  199.     // check that the connection is ok before verifying it  
  200.     // can be overridden eg to check what interfaces will be supported.  
  201.     virtual HRESULT CheckConnect(IPin *);  
  202.   
  203.     // Set and release resources required for a connection  
  204.     virtual HRESULT BreakConnect();  
  205.     virtual HRESULT CompleteConnect(IPin *pReceivePin);  
  206.   
  207.     // returns the preferred formats for a pin  
  208.     virtual HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);  
  209.   
  210.     // access to NewSegment values  
  211.     REFERENCE_TIME CurrentStopTime() {  
  212.         return m_tStop;  
  213.     }  
  214.     REFERENCE_TIME CurrentStartTime() {  
  215.         return m_tStart;  
  216.     }  
  217.     double CurrentRate() {  
  218.         return m_dRate;  
  219.     }  
  220.   
  221.     //  Access name  
  222.     LPWSTR Name() { return m_pName; };  
  223.   
  224.     //  Can reconnectwhen active?  
  225.     void SetReconnectWhenActive(bool bCanReconnect)  
  226.     {  
  227.         m_bCanReconnectWhenActive = bCanReconnect;  
  228.     }  
  229.   
  230.     bool CanReconnectWhenActive()  
  231.     {  
  232.         return m_bCanReconnectWhenActive;  
  233.     }  
  234.   
  235. protected:  
  236.     STDMETHODIMP DisconnectInternal();  
  237. };  

在CBasePin实现的成员函数中,有3个与Filter的状态转换相对应。

[cpp] view plaincopy

  1. // 转换pin到活动状态(暂停或运行)  
  2.   // not an error to call this if already active  
  3.   virtual HRESULT Active(void);  
  4.   
  5.   // 转换pin到不活动状态 - 可能已经处于非活动状态  
  6.   virtual HRESULT Inactive(void);  
  7.   
  8.   // 通知运行filter 的 Run()  
  9.   virtual HRESULT Run(REFERENCE_TIME tStart);  

 

我们来看一下Filter的Stop的实现,实际上就是调用Filter的所有pin的Inactive函数

[cpp] view plaincopy

  1. STDMETHODIMP  
  2. CBaseFilter::Stop()  
  3. {  
  4.     CAutoLock cObjectLock(m_pLock);  
  5.     HRESULT hr = NOERROR;  
  6.   
  7.     // 通知所有pin改变状态  
  8.     if (m_State != State_Stopped) {  
  9.         int cPins = GetPinCount();  
  10.         for (int c = 0; c < cPins; c++) {  
  11.   
  12.             CBasePin *pPin = GetPin(c);  
  13.   
  14.             // Disconnected pins are not activated - this saves pins worrying  
  15.             // about this state themselves. We ignore the return code to make  
  16.             // sure everyone is inactivated regardless. The base input pin  
  17.             // class can return an error if it has no allocator but Stop can  
  18.             // be used to resync the graph state after something has gone bad  
  19.             // 仅在完成连接的pin上调用Inactive函数  
  20.             // 如果Inactive函数返回一个错误值,则暂时忽略,  
  21.             // 以便所有Pin都有机会被调用Inactive  
  22.             if (pPin->IsConnected()) {  
  23.                 HRESULT hrTmp = pPin->Inactive();  
  24.                 if (FAILED(hrTmp) && SUCCEEDED(hr)) {  
  25.                     hr = hrTmp;  
  26.                 }  
  27.             }  
  28.         }  
  29.     }  
  30.   
  31.   
  32.     m_State = State_Stopped;  
  33.     return hr;  
  34. }  

 

在实际开发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:

[cpp] view plaincopy

  1. // CAsyncOutputPin实现了一个输出Pin  
  2. // 继承自IAsyncReader、CBasePin,这是对拉模式的Source Filter的基本要求  
  3. /* IAsyncReader接口方法及描述如下: 
  4. BeginFlush  放弃所有正在进行的数据读取 
  5. EndFlush    与BeginFlush配对,标示Flush过程结束 
  6. Length      得到数据总长度和当前可以读取的长度 
  7. RequestAlloctor 要求一个输入Pin上的Sample管理器 
  8. Request     发出一个数据请求 
  9. SyncReadAligned 同步读取数据(边界对齐) 
  10. SyncRead    同步读取数据 
  11. WaitForNext 等待一个请求的完成 
  12. ====================================================================== 
  13. 可以看出CAsyOutputPin类上实现的IAsyncReader的各个接口方法,都“委托” 
  14. 给了CAsyncIo类对象的同名成员函数 
  15. */  
  16. class CAsyncOutputPin  
  17.   : public IAsyncReader,   
  18.     public CBasePin  
  19. {  
  20. protected:  
  21.     CAsyncReader* m_pReader;  
  22.     CAsyncIo * m_pIo;  
  23.   
  24.     //  This is set every time we're asked to return an IAsyncReader  
  25.     //  interface  
  26.     //  This allows us to know if the downstream pin can use  
  27.     //  this transport, otherwise we can hook up to thinks like the  
  28.     //  dump filter and nothing happens  
  29.     BOOL         m_bQueriedForAsyncReader;  
  30.   
  31.     HRESULT InitAllocator(IMemAllocator **ppAlloc);  
  32.   
  33. public:  
  34.     // constructor and destructor  
  35.     CAsyncOutputPin(  
  36.         HRESULT * phr,  
  37.         CAsyncReader *pReader,  
  38.         CAsyncIo *pIo,  
  39.         CCritSec * pLock);  
  40.   
  41.     ~CAsyncOutputPin();  
  42.   
  43.     // --- CUnknown ---  
  44.   
  45.     // need to expose IAsyncReader  
  46.     DECLARE_IUNKNOWN  
  47.     STDMETHODIMP NonDelegatingQueryInterface(REFIID, void**);  
  48.   
  49.     // --- IPin methods ---  
  50.     STDMETHODIMP Connect(  
  51.         IPin * pReceivePin,  
  52.         const AM_MEDIA_TYPE *pmt   // optional media type  
  53.     );  
  54.   
  55.     // --- CBasePin methods ---  
  56.   
  57.     // return the types we prefer - this will return the known  
  58.     // file type  
  59.     HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);  
  60.   
  61.     // can we support this type?  
  62.     HRESULT CheckMediaType(const CMediaType* pType);  
  63.   
  64.     // Clear the flag so we see if IAsyncReader is queried for  
  65.     HRESULT CheckConnect(IPin *pPin)  
  66.     {  
  67.         m_bQueriedForAsyncReader = FALSE;  
  68.         return CBasePin::CheckConnect(pPin);  
  69.     }  
  70.   
  71.     // See if it was asked for  
  72.     HRESULT CompleteConnect(IPin *pReceivePin)  
  73.     {  
  74.         if (m_bQueriedForAsyncReader) {  
  75.             return CBasePin::CompleteConnect(pReceivePin);  
  76.         } else {  
  77.   
  78. #ifdef VFW_E_NO_TRANSPORT  
  79.             return VFW_E_NO_TRANSPORT;  
  80. #else  
  81.             return E_FAIL;  
  82. #endif  
  83.         }  
  84.     }  
  85.   
  86.     //  Remove our connection status  
  87.     HRESULT BreakConnect()  
  88.     {  
  89.         m_bQueriedForAsyncReader = FALSE;  
  90.         return CBasePin::BreakConnect();  
  91.     }  
  92.   
  93.     // --- IAsyncReader methods ---  
  94.     // pass in your preferred allocator and your preferred properties.  
  95.     // method returns the actual allocator to be used. Call GetProperties  
  96.     // on returned allocator to learn alignment and prefix etc chosen.  
  97.     // this allocator will be not be committed and decommitted by  
  98.     // the async reader, only by the consumer.  
  99.     STDMETHODIMP RequestAllocator(  
  100.                       IMemAllocator* pPreferred,  
  101.                       ALLOCATOR_PROPERTIES* pProps,  
  102.                       IMemAllocator ** ppActual);  
  103.   
  104.     // queue a request for data.  
  105.     // media sample start and stop times contain the requested absolute  
  106.     // byte position (start inclusive, stop exclusive).  
  107.     // may fail if sample not obtained from agreed allocator.  
  108.     // may fail if start/stop position does not match agreed alignment.  
  109.     // samples allocated from source pin's allocator may fail  
  110.     // GetPointer until after returning from WaitForNext.  
  111.     STDMETHODIMP Request(  
  112.                      IMediaSample* pSample,  
  113.                      DWORD_PTR dwUser);         // user context  
  114.   
  115.     // block until the next sample is completed or the timeout occurs.  
  116.     // timeout (millisecs) may be 0 or INFINITE. Samples may not  
  117.     // be delivered in order. If there is a read error of any sort, a  
  118.     // notification will already have been sent by the source filter,  
  119.     // and STDMETHODIMP will be an error.  
  120.     STDMETHODIMP WaitForNext(  
  121.                       DWORD dwTimeout,  
  122.                       IMediaSample** ppSample,  // completed sample  
  123.                       DWORD_PTR * pdwUser);     // user context  
  124.   
  125.     // sync read of data. Sample passed in must have been acquired from  
  126.     // the agreed allocator. Start and stop position must be aligned.  
  127.     // equivalent to a Request/WaitForNext pair, but may avoid the  
  128.     // need for a thread on the source filter.  
  129.     STDMETHODIMP SyncReadAligned(  
  130.                       IMediaSample* pSample);  
  131.   
  132.   
  133.     // sync read. works in stopped state as well as run state.  
  134.     // need not be aligned. Will fail if read is beyond actual total  
  135.     // length.  
  136.     STDMETHODIMP SyncRead(  
  137.                       LONGLONG llPosition,  // absolute file position  
  138.                       LONG lLength,         // nr bytes required  
  139.                       BYTE* pBuffer);       // write data here  
  140.   
  141.     // return total length of stream, and currently available length.  
  142.     // reads for beyond the available length but within the total length will  
  143.     // normally succeed but may block for a long period.  
  144.     STDMETHODIMP Length(  
  145.                       LONGLONG* pTotal,  
  146.                       LONGLONG* pAvailable);  
  147.   
  148.     // cause all outstanding reads to return, possibly with a failure code  
  149.     // (VFW_E_TIMEOUT) indicating they were cancelled.  
  150.     // these are defined on IAsyncReader and IPin  
  151.     STDMETHODIMP BeginFlush(void);  
  152.     STDMETHODIMP EndFlush(void);  
  153.   
  154. };  
5、 CBaseInputPin和CBaseOutputPin

 从CBasePin类派生的,也是很基本的输入或输出pin。

它们的实现可参见 amfilter.cpp

CBaseInputPin实现了IMemInputPin(用于推模式的数据传送),

而CBaseOutputPin主要完成了传送数据所使用的Sample管理器(Allocator)的协商,并重写了CBasePin::Active(用于实际的Sample内存分配)

以及CBasePin::Inactive(用于Sample内存的释放)

[cpp] view plaincopy

  1. class AM_NOVTABLE CBaseInputPin : public CBasePin,  
  2.                                   public IMemInputPin  
  3. {  
  4.   
  5. protected:  
  6.   
  7.     IMemAllocator *m_pAllocator;    // Default memory allocator  
  8.   
  9.     // allocator is read-only, so received samples  
  10.     // cannot be modified (probably only relevant to in-place  
  11.     // transforms  
  12.     BYTE m_bReadOnly;  
  13.   
  14.     // in flushing state (between BeginFlush and EndFlush)  
  15.     // if TRUE, all Receives are returned with S_FALSE  
  16.     BYTE m_bFlushing;  
  17.   
  18.     // Sample properties - initalized in Receive  
  19.     AM_SAMPLE2_PROPERTIES m_SampleProps;  
  20.   
  21. public:  
  22.   
  23.     CBaseInputPin(  
  24.         TCHAR *pObjectName,  
  25.         CBaseFilter *pFilter,  
  26.         CCritSec *pLock,  
  27.         HRESULT *phr,  
  28.         LPCWSTR pName);  
  29. #ifdef UNICODE  
  30.     CBaseInputPin(  
  31.         CHAR *pObjectName,  
  32.         CBaseFilter *pFilter,  
  33.         CCritSec *pLock,  
  34.         HRESULT *phr,  
  35.         LPCWSTR pName);  
  36. #endif  
  37.     virtual ~CBaseInputPin();  
  38.   
  39.     DECLARE_IUNKNOWN  
  40.   
  41.     // override this to publicise our interfaces  
  42.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);  
  43.   
  44.     // return the allocator interface that this input pin  
  45.     // would like the output pin to use  
  46.     STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);  
  47.   
  48.     // tell the input pin which allocator the output pin is actually  
  49.     // going to use.  
  50.     STDMETHODIMP NotifyAllocator(  
  51.                     IMemAllocator * pAllocator,  
  52.                     BOOL bReadOnly);  
  53.   
  54.     // do something with this media sample  
  55.     STDMETHODIMP Receive(IMediaSample *pSample);  
  56.   
  57.     // do something with these media samples  
  58.     STDMETHODIMP ReceiveMultiple (  
  59.         IMediaSample **pSamples,  
  60.         long nSamples,  
  61.         long *nSamplesProcessed);  
  62.   
  63.     // See if Receive() blocks  
  64.     STDMETHODIMP ReceiveCanBlock();  
  65.   
  66.     // Default handling for BeginFlush - call at the beginning  
  67.     // of your implementation (makes sure that all Receive calls  
  68.     // fail). After calling this, you need to free any queued data  
  69.     // and then call downstream.  
  70.     STDMETHODIMP BeginFlush(void);  
  71.   
  72.     // default handling for EndFlush - call at end of your implementation  
  73.     // - before calling this, ensure that there is no queued data and no thread  
  74.     // pushing any more without a further receive, then call downstream,  
  75.     // then call this method to clear the m_bFlushing flag and re-enable  
  76.     // receives  
  77.     STDMETHODIMP EndFlush(void);  
  78.   
  79.     // this method is optional (can return E_NOTIMPL).  
  80.     // default implementation returns E_NOTIMPL. Override if you have  
  81.     // specific alignment or prefix needs, but could use an upstream  
  82.     // allocator  
  83.     STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);  
  84.   
  85.     // Release the pin's allocator.  
  86.     HRESULT BreakConnect();  
  87.   
  88.     // helper method to check the read-only flag  
  89.     BOOL IsReadOnly() {  
  90.         return m_bReadOnly;  
  91.     };  
  92.   
  93.     // helper method to see if we are flushing  
  94.     BOOL IsFlushing() {  
  95.         return m_bFlushing;  
  96.     };  
  97.   
  98.     //  Override this for checking whether it's OK to process samples  
  99.     //  Also call this from EndOfStream.  
  100.     virtual HRESULT CheckStreaming();  
  101.   
  102.     // Pass a Quality notification on to the appropriate sink  
  103.     HRESULT PassNotify(Quality& q);  
  104.   
  105.   
  106.     //================================================================================  
  107.     // IQualityControl methods (from CBasePin)  
  108.     //================================================================================  
  109.   
  110.     STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);  
  111.   
  112.     // no need to override:  
  113.     // STDMETHODIMP SetSink(IQualityControl * piqc);  
  114.   
  115.   
  116.     // switch the pin to inactive state - may already be inactive  
  117.     virtual HRESULT Inactive(void);  
  118.   
  119.     // Return sample properties pointer  
  120.     AM_SAMPLE2_PROPERTIES * SampleProps() {  
  121.         ASSERT(m_SampleProps.cbData != 0);  
  122.         return &m_SampleProps;  
  123.     }  
  124.   
  125. };  

 

 

[cpp] view plaincopy

  1. class  AM_NOVTABLE CBaseOutputPin : public CBasePin  
  2. {  
  3.   
  4. protected:  
  5.   
  6.     IMemAllocator *m_pAllocator;  
  7.     IMemInputPin *m_pInputPin;        // interface on the downstreaminput pin  
  8.                                       // set up in CheckConnect when we connect.  
  9.   
  10. public:  
  11.   
  12.     CBaseOutputPin(  
  13.         TCHAR *pObjectName,  
  14.         CBaseFilter *pFilter,  
  15.         CCritSec *pLock,  
  16.         HRESULT *phr,  
  17.         LPCWSTR pName);  
  18. #ifdef UNICODE  
  19.     CBaseOutputPin(  
  20.         CHAR *pObjectName,  
  21.         CBaseFilter *pFilter,  
  22.         CCritSec *pLock,  
  23.         HRESULT *phr,  
  24.         LPCWSTR pName);  
  25. #endif  
  26.     // override CompleteConnect() so we can negotiate an allocator  
  27.     virtual HRESULT CompleteConnect(IPin *pReceivePin);  
  28.   
  29.     // negotiate the allocator and its buffer size/count and other properties  
  30.     // Calls DecideBufferSize to set properties  
  31.     virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);  
  32.   
  33.     // override this to set the buffer size and count. Return an error  
  34.     // if the size/count is not to your liking.  
  35.     // The allocator properties passed in are those requested by the  
  36.     // input pin - use eg the alignment and prefix members if you have  
  37.     // no preference on these.  
  38.     virtual HRESULT DecideBufferSize(  
  39.         IMemAllocator * pAlloc,  
  40.         ALLOCATOR_PROPERTIES * ppropInputRequest  
  41.     ) PURE;  
  42.   
  43.     // returns an empty sample buffer from the allocator  
  44.     virtual HRESULT GetDeliveryBuffer(IMediaSample ** ppSample,  
  45.                                       REFERENCE_TIME * pStartTime,  
  46.                                       REFERENCE_TIME * pEndTime,  
  47.                                       DWORD dwFlags);  
  48.   
  49.     // deliver a filled-in sample to the connected input pin  
  50.     // note - you need to release it after calling this. The receiving  
  51.     // pin will addref the sample if it needs to hold it beyond the  
  52.     // call.  
  53.     virtual HRESULT Deliver(IMediaSample *);  
  54.   
  55.     // override this to control the connection  
  56.     virtual HRESULT InitAllocator(IMemAllocator **ppAlloc);  
  57.     HRESULT CheckConnect(IPin *pPin);  
  58.     HRESULT BreakConnect();  
  59.   
  60.     // override to call Commit and Decommit  
  61.     HRESULT Active(void);  
  62.     HRESULT Inactive(void);  
  63.   
  64.     // we have a default handling of EndOfStream which is to return  
  65.     // an error, since this should be called on input pins only  
  66.     STDMETHODIMP EndOfStream(void);  
  67.   
  68.     // called from elsewhere in our filter to pass EOS downstream to  
  69.     // our connected input pin  
  70.     virtual HRESULT DeliverEndOfStream(void);  
  71.   
  72.     // same for Begin/EndFlush - we handle Begin/EndFlush since it  
  73.     // is an error on an output pin, and we have Deliver methods to  
  74.     // call the methods on the connected pin  
  75.     STDMETHODIMP BeginFlush(void);  
  76.     STDMETHODIMP EndFlush(void);  
  77.     virtual HRESULT DeliverBeginFlush(void);  
  78.     virtual HRESULT DeliverEndFlush(void);  
  79.   
  80.     // deliver NewSegment to connected pin - you will need to  
  81.     // override this if you queue any data in your output pin.  
  82.     virtual HRESULT DeliverNewSegment(  
  83.                         REFERENCE_TIME tStart,  
  84.                         REFERENCE_TIME tStop,  
  85.                         double dRate);  
  86.   
  87.     //================================================================================  
  88.     // IQualityControl methods  
  89.     //================================================================================  
  90.   
  91.     // All inherited from CBasePin and not overridden here.  
  92.     // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);  
  93.     // STDMETHODIMP SetSink(IQualityControl * piqc);  
  94. };  

 CBaseInputPin类的使用方法(派生一个子类,并且至少需要重写以下函数)如下:

(1) CBaseInputPin::BeginFlush

(2) CBaseInputPin::EndFlush

(3) CBaseInputPin::Receive

(4) CBaseInputPin::CheckMediaType

(5) CBaseInputPin::GetMediaType

eg:

[cpp] view plaincopy

  1. class CRendererInputPin : public CBaseInputPin  
  2. {  
  3. protected:  
  4.   
  5.     CBaseRenderer *m_pRenderer;  
  6.   
  7. public:  
  8.   
  9.     CRendererInputPin(CBaseRenderer *pRenderer,  
  10.                       HRESULT *phr,  
  11.                       LPCWSTR Name);  
  12.   
  13.     // Overriden from the base pin classes  
  14.   
  15.     HRESULT BreakConnect();  
  16.     HRESULT CompleteConnect(IPin *pReceivePin);  
  17.     HRESULT SetMediaType(const CMediaType *pmt);  
  18.     HRESULT CheckMediaType(const CMediaType *pmt);  
  19.     HRESULT Active();  
  20.     HRESULT Inactive();  
  21.   
  22.     // Add rendering behaviour to interface functions  
  23.   
  24.     STDMETHODIMP QueryId(LPWSTR *Id);  
  25.     STDMETHODIMP EndOfStream();  
  26.     STDMETHODIMP BeginFlush();  
  27.     STDMETHODIMP EndFlush();  
  28.     STDMETHODIMP Receive(IMediaSample *pMediaSample);  
  29.   
  30.     // Helper  
  31.     IMemAllocator inline *Allocator() const  
  32.     {  
  33.         return m_pAllocator;  
  34.     }  
  35. };  

 

CBaseOutputPin类的使用方法(派生一个子类,并且最少需要重写以下函数)如下:

(1) 重写CBasePin::CheckMediaType进行连接时媒体类型的检查;

(2) 实现纯虚函数CBaseOutputPin::DecideBufferSize,决定Sample内存的大小;

(3) 重写CBasePin::GetMediaType, 提供Pin 上的首选媒体类型。

 

[cpp] view plaincopy

  1. class CTransformOutputPin : public CBaseOutputPin  
  2. {  
  3.     friend class CTransformFilter;  
  4.   
  5. protected:  
  6.     CTransformFilter *m_pTransformFilter;  
  7.   
  8. public:  
  9.   
  10.     // implement IMediaPosition by passing upstream  
  11.     IUnknown * m_pPosition;  
  12.   
  13.     CTransformOutputPin(  
  14.         TCHAR *pObjectName,  
  15.         CTransformFilter *pTransformFilter,  
  16.         HRESULT * phr,  
  17.         LPCWSTR pName);  
  18. #ifdef UNICODE  
  19.     CTransformOutputPin(  
  20.         CHAR *pObjectName,  
  21.         CTransformFilter *pTransformFilter,  
  22.         HRESULT * phr,  
  23.         LPCWSTR pName);  
  24. #endif  
  25.     ~CTransformOutputPin();  
  26.   
  27.     // override to expose IMediaPosition  
  28.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);  
  29.   
  30.     // --- CBaseOutputPin ------------  
  31.   
  32.     STDMETHODIMP QueryId(LPWSTR * Id)  
  33.     {  
  34.         return AMGetWideString(L"Out", Id);  
  35.     }  
  36.   
  37.     // Grab and release extra interfaces if required  
  38.   
  39.     HRESULT CheckConnect(IPin *pPin);  
  40.     HRESULT BreakConnect();  
  41.     HRESULT CompleteConnect(IPin *pReceivePin);  
  42.   
  43.     // check that we can support this output type  
  44.     HRESULT CheckMediaType(const CMediaType* mtOut);  
  45.   
  46.     // set the connection media type  
  47.     HRESULT SetMediaType(const CMediaType *pmt);  
  48.   
  49.     // called from CBaseOutputPin during connection to ask for  
  50.     // the count and size of buffers we need.  
  51.     HRESULT DecideBufferSize(  
  52.                 IMemAllocator * pAlloc,  
  53.                 ALLOCATOR_PROPERTIES *pProp);  
  54.   
  55.     // returns the preferred formats for a pin  
  56.     HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);  
  57.   
  58.     // inherited from IQualityControl via CBasePin  
  59.     STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);  
  60.   
  61.     // Media type  
  62. public:  
  63.     CMediaType& CurrentMediaType() { return m_mt; };  
  64. };  

 ===================================================================

如果开发的是一个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: 参照我的另一篇文章:  

[cpp] view plaincopy

  1. class CPushSourceBitmap : public CSource  
  2. {  
  3.   
  4. private:  
  5.     // Constructor is private because you have to use CreateInstance  
  6.     CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr);  
  7.     ~CPushSourceBitmap();  
  8.   
  9.     CPushPinBitmap *m_pPin;  
  10.   
  11. public:  
  12.     static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);    
  13.   
  14. };  

 

[cpp] view plaincopy

  1. CPushSourceBitmap::CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr)  
  2.            : CSource(NAME("PushSourceBitmap"), pUnk, CLSID_PushSourceBitmap)  
  3. {  
  4.     // The pin magically adds itself to our pin array.  
  5.     m_pPin = new CPushPinBitmap(phr, this);  
  6.   
  7.     if (phr)  
  8.     {  
  9.         if (m_pPin == NULL)  
  10.             *phr = E_OUTOFMEMORY;  
  11.         else  
  12.             *phr = S_OK;  
  13.     }    
  14. }  

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: 参照我的另一篇文章:  

[cpp] view plaincopy

  1. class CPushPinBitmap : public CSourceStream  
  2. {  
  3. protected:  
  4.   
  5.     int m_FramesWritten;                // To track where we are in the file  
  6.     BOOL m_bZeroMemory;                 // Do we need to clear the buffer?  
  7.     CRefTime m_rtSampleTime;            // The time stamp for each sample  
  8.   
  9.     BITMAPINFO *m_pBmi;                 // Pointer to the bitmap header  
  10.     DWORD       m_cbBitmapInfo;         // Size of the bitmap header  
  11.       
  12.     // File opening variables   
  13.     HANDLE m_hFile;                     // Handle returned from CreateFile  
  14.     BYTE * m_pFile;                     // Points to beginning of file buffer  
  15.     BYTE * m_pImage;                    // Points to pixel bits                                        
  16.   
  17.     int m_iFrameNumber;  
  18.     const REFERENCE_TIME m_rtFrameLength;  
  19.   
  20.     CCritSec m_cSharedState;            // Protects our internal state  
  21.     CImageDisplay m_Display;            // Figures out our media type for us  
  22.   
  23. public:  
  24.   
  25.     CPushPinBitmap(HRESULT *phr, CSource *pFilter);  
  26.     ~CPushPinBitmap();  
  27.   
  28.     // Override the version that offers exactly one media type  
  29.     HRESULT GetMediaType(CMediaType *pMediaType);  
  30.     HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);  
  31.     HRESULT FillBuffer(IMediaSample *pSample);  
  32.       
  33.     // Quality control  
  34.     // Not implemented because we aren't going in real time.  
  35.     // If the file-writing filter slows the graph down, we just do nothing, which means  
  36.     // wait until we're unblocked. No frames are ever dropped.  
  37.     STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)  
  38.     {  
  39.         return E_FAIL;  
  40.     }  
  41.   
  42. };  

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 的继承类去实现它们。

[cpp] view plaincopy

  1. class CVideoTransformFilter : public CTransformFilter  
  2. {  
  3.   public:  
  4.   
  5.     CVideoTransformFilter(TCHAR *, LPUNKNOWN, REFCLSID clsid);  
  6.     ~CVideoTransformFilter();  
  7.     HRESULT EndFlush();  
  8.   
  9.     // =================================================================  
  10.     // ----- override these bits ---------------------------------------  
  11.     // =================================================================  
  12.     // The following methods are in CTransformFilter which is inherited.  
  13.     // They are mentioned here for completeness  
  14.     //  
  15.     // These MUST be supplied in a derived class  
  16.     //  
  17.     // NOTE:  
  18.     // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut);  
  19.     // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE;  
  20.     // virtual HRESULT CheckTransform  
  21.     //     (const CMediaType* mtIn, const CMediaType* mtOut) PURE;  
  22.     // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);  
  23.     // virtual HRESULT DecideBufferSize  
  24.     //     (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE;  
  25.     // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE;  
  26.     //  
  27.     // These MAY also be overridden  
  28.     //  
  29.     // virtual HRESULT StopStreaming();  
  30.     // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt);  
  31.     // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin);  
  32.     // virtual HRESULT BreakConnect(PIN_DIRECTION dir);  
  33.     // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin);  
  34.     // virtual HRESULT EndOfStream(void);  
  35.     // virtual HRESULT BeginFlush(void);  
  36.     // virtual HRESULT EndFlush(void);  
  37.     // virtual HRESULT NewSegment  
  38.     //     (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate);  
  39. #ifdef PERF  
  40.   
  41.     // If you override this - ensure that you register all these ids  
  42.     // as well as any of your own,  
  43.     virtual void RegisterPerfId() {  
  44.         m_idSkip        = MSR_REGISTER(TEXT("Video Transform Skip frame"));  
  45.         m_idFrameType   = MSR_REGISTER(TEXT("Video transform frame type"));  
  46.         m_idLate        = MSR_REGISTER(TEXT("Video Transform Lateness"));  
  47.         m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key"));  
  48.         CTransformFilter::RegisterPerfId();  
  49.     }  
  50. #endif  
  51.   
  52.   protected:  
  53.   
  54.     // =========== QUALITY MANAGEMENT IMPLEMENTATION ========================  
  55.     // Frames are assumed to come in three types:  
  56.     // Type 1: an AVI key frame or an MPEG I frame.  
  57.     //        This frame can be decoded with no history.  
  58.     //        Dropping this frame means that no further frame can be decoded  
  59.     //        until the next type 1 frame.  
  60.     //        Type 1 frames are sync points.  
  61.     // Type 2: an AVI non-key frame or an MPEG P frame.  
  62.     //        This frame cannot be decoded unless the previous type 1 frame was  
  63.     //        decoded and all type 2 frames since have been decoded.  
  64.     //        Dropping this frame means that no further frame can be decoded  
  65.     //        until the next type 1 frame.  
  66.     // Type 3: An MPEG B frame.  
  67.     //        This frame cannot be decoded unless the previous type 1 or 2 frame  
  68.     //        has been decoded AND the subsequent type 1 or 2 frame has also  
  69.     //        been decoded.  (This requires decoding the frames out of sequence).  
  70.     //        Dropping this frame affects no other frames.  This implementation  
  71.     //        does not allow for these.  All non-sync-point frames are treated  
  72.     //        as being type 2.  
  73.     //  
  74.     // The spacing of frames of type 1 in a file is not guaranteed.  There MUST  
  75.     // be a type 1 frame at (well, near) the start of the file in order to start  
  76.     // decoding at all.  After that there could be one every half second or so,  
  77.     // there could be one at the start of each scene (aka "cut", "shot") or  
  78.     // there could be no more at all.  
  79.     // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED  
  80.     // without losing all the rest of the movie.  There is no way to tell whether  
  81.     // this is the case, so we find that we are in the gambling business.  
  82.     // To try to improve the odds, we record the greatest interval between type 1s  
  83.     // that we have seen and we bet on things being no worse than this in the  
  84.     // future.  
  85.   
  86.     // You can tell if it's a type 1 frame by calling IsSyncPoint().  
  87.     // there is no architected way to test for a type 3, so you should override  
  88.     // the quality management here if you have B-frames.  
  89.   
  90.     int m_nKeyFramePeriod; // the largest observed interval between type 1 frames  
  91.                            // 1 means every frame is type 1, 2 means every other.  
  92.   
  93.     int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1.  
  94.                                 // becomes the new m_nKeyFramePeriod if greater.  
  95.   
  96.     BOOL m_bSkipping;           // we are skipping to the next type 1 frame  
  97.   
  98. #ifdef PERF  
  99.     int m_idFrameType;          // MSR id Frame type.  1=Key, 2="non-key"  
  100.     int m_idSkip;               // MSR id skipping  
  101.     int m_idLate;               // MSR id lateness  
  102.     int m_idTimeTillKey;        // MSR id for guessed time till next key frame.  
  103. #endif  
  104.   
  105.     virtual HRESULT StartStreaming();  
  106.   
  107.     HRESULT AbortPlayback(HRESULT hr);  // if something bad happens  
  108.   
  109.     HRESULT Receive(IMediaSample *pSample);  
  110.   
  111.     HRESULT AlterQuality(Quality q);  
  112.   
  113.     BOOL ShouldSkipFrame(IMediaSample * pIn);  
  114.   
  115.     int m_itrLate;              // lateness from last Quality message  
  116.                                 // (this overflows at 214 secs late).  
  117.     int m_tDecodeStart;         // timeGetTime when decode started.  
  118.     int m_itrAvgDecode;         // Average decode time in reference units.  
  119.   
  120.     BOOL m_bNoSkip;             // debug - no skipping.  
  121.   
  122.     // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade.  
  123.     // We send one when we start degrading, not one for every frame, this means  
  124.     // we track whether we've sent one yet.  
  125.     BOOL m_bQualityChanged;  
  126.   
  127.     // When non-zero, don't pass anything to renderer until next keyframe  
  128.     // If there are few keys, give up and eventually draw something  
  129.     int m_nWaitForKey;  
  130. };  

 

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的函数实现。代码如下:

[cpp] view plaincopy

  1. // 当输入或输出Pin完成连接时被调用,  
  2. // 经过一个反复重连的过程,来达到输入和输出Pin使用相同的媒体类型的目的  
  3. HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin)  
  4. {  
  5.     UNREFERENCED_PARAMETER(pReceivePin);  
  6.     ASSERT(m_pInput);  
  7.     ASSERT(m_pOutput);  
  8.   
  9.     // if we are not part of a graph, then don't indirect the pointer  
  10.     // this probably prevents use of the filter without a filtergraph  
  11.     if (!m_pGraph) {  
  12.         return VFW_E_NOT_IN_GRAPH;  
  13.     }  
  14.   
  15.     // Always reconnect the input to account for buffering changes  
  16.     //  
  17.     // Because we don't get to suggest a type on ReceiveConnection  
  18.     // we need another way of making sure the right type gets used.  
  19.     //  
  20.     // One way would be to have our EnumMediaTypes return our output  
  21.     // connection type first but more deterministic and simple is to  
  22.     // call ReconnectEx passing the type we want to reconnect with  
  23.     // via the base class ReconeectPin method.  
  24.   
  25.     // 当输出Pin调用该函数(并且此时输入Pin已连上)时,使用输出Pin上的媒体类型对  
  26.     // 输入Pin进行重连接  
  27.     if (dir == PINDIR_OUTPUT) {  
  28.         if( m_pInput->IsConnected() ) {  
  29.             return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );  
  30.         }  
  31.         return NOERROR;  
  32.     }  
  33.   
  34.     ASSERT(dir == PINDIR_INPUT);  
  35.   
  36.     // Reconnect output if necessary  
  37.   
  38.     // 当输入Pin调用该函数(并且此时输出Pin已连上)时,如果输入和输出Pin上使用的  
  39.     // 媒体类型不一致,则使用输入Pin上的媒体类型对输出Pin进行重新连接  
  40.     if( m_pOutput->IsConnected() ) {  
  41.   
  42.         if (  m_pInput->CurrentMediaType()  
  43.            != m_pOutput->CurrentMediaType()  
  44.            ) {  
  45.             return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );  
  46.         }  
  47.     }  
  48.     return NOERROR;  
  49.   
  50. } // ComnpleteConnect  

 

[cpp] view plaincopy

  1. // 当上一级Filter的输出Pin要求我们的输入Pin提供Sample管理器时,  
  2. // 如果我们的输出Pin已连接上,则可以取出输出Pin上的Sample管理器提供给上一级  
  3. // Filter,以此达到我们的输入和输出Pin使用同一个Sample管理器的目的  
  4. STDMETHODIMP CTransInPlaceInputPin::GetAllocator(IMemAllocator ** ppAllocator)  
  5. {  
  6.     CheckPointer(ppAllocator,E_POINTER);  
  7.     ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));  
  8.     CAutoLock cObjectLock(m_pLock);  
  9.   
  10.     HRESULT hr;  
  11.   
  12.     if ( m_pTIPFilter->m_pOutput->IsConnected() ) {  
  13.         //  Store the allocator we got  
  14.         hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()  
  15.                                         ->GetAllocator( ppAllocator );  
  16.         if (SUCCEEDED(hr)) {  
  17.             m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator );  
  18.         }  
  19.     }  
  20.     else {  
  21.         //  Help upstream filter (eg TIP filter which is having to do a copy)  
  22.         //  by providing a temp allocator here - we'll never use  
  23.         //  this allocator because when our output is connected we'll  
  24.         //  reconnect this pin  
  25.         hr = CTransformInputPin::GetAllocator( ppAllocator );  
  26.     }  
  27.     return hr;  
  28.   
  29. } // GetAllocator  

 

[cpp] view plaincopy

  1. // 上一级Filter调用该函数,告知输入Pin上到底使用哪一个Sample管理器  
  2. // 如果设置进来的Sample管理器是只读的,而我们在Filter中又想修改数据,  
  3. // 则我们的Filter不得不最终使用不同的Sample管理器  
  4. STDMETHODIMP  
  5. CTransInPlaceInputPin::NotifyAllocator(  
  6.     IMemAllocator * pAllocator,  
  7.     BOOL bReadOnly)  
  8. {  
  9.     HRESULT hr = S_OK;  
  10.     CheckPointer(pAllocator,E_POINTER);  
  11.     ValidateReadPtr(pAllocator,sizeof(IMemAllocator));  
  12.   
  13.     CAutoLock cObjectLock(m_pLock);  
  14.   
  15.     m_bReadOnly = bReadOnly;  
  16.     //  If we modify data then don't accept the allocator if it's  
  17.     //  the same as the output pin's allocator  
  18.   
  19.     //  If our output is not connected just accept the allocator  
  20.     //  We're never going to use this allocator because when our  
  21.     //  output pin is connected we'll reconnect this pin  
  22.     if (!m_pTIPFilter->OutputPin()->IsConnected()) {  
  23.         return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly);  
  24.     }  
  25.   
  26.     //  If the allocator is read-only and we're modifying data  
  27.     //  and the allocator is the same as the output pin's  
  28.     //  then reject  
  29.     if (bReadOnly && m_pTIPFilter->m_bModifiesData) {  
  30.         IMemAllocator *pOutputAllocator =  
  31.             m_pTIPFilter->OutputPin()->PeekAllocator();  
  32.   
  33.         //  Make sure we have an output allocator  
  34.         if (pOutputAllocator == NULL) {  
  35.             hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()->  
  36.                                       GetAllocator(&pOutputAllocator);  
  37.             if(FAILED(hr)) {  
  38.                 hr = CreateMemoryAllocator(&pOutputAllocator);  
  39.             }  
  40.             if (SUCCEEDED(hr)) {  
  41.                 m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator);  
  42.                 pOutputAllocator->Release();  
  43.             }  
  44.         }  
  45.         if (pAllocator == pOutputAllocator) {  
  46.             hr = E_FAIL;  
  47.         } else if(SUCCEEDED(hr)) {  
  48.             //  Must copy so set the allocator properties on the output  
  49.             ALLOCATOR_PROPERTIES Props, Actual;  
  50.             hr = pAllocator->GetProperties(&Props);  
  51.             if (SUCCEEDED(hr)) {  
  52.                 hr = pOutputAllocator->SetProperties(&Props, &Actual);  
  53.             }  
  54.             if (SUCCEEDED(hr)) {  
  55.                 if (  (Props.cBuffers > Actual.cBuffers)  
  56.                    || (Props.cbBuffer > Actual.cbBuffer)  
  57.                    || (Props.cbAlign  > Actual.cbAlign)  
  58.                    ) {  
  59.                     hr =  E_FAIL;  
  60.                 }  
  61.             }  
  62.   
  63.             //  Set the allocator on the output pin  
  64.             if (SUCCEEDED(hr)) {  
  65.                 hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()  
  66.                                        ->NotifyAllocator( pOutputAllocator, FALSE );  
  67.             }  
  68.         }  
  69.     } else {  
  70.         hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()  
  71.                                    ->NotifyAllocator( pAllocator, bReadOnly );  
  72.         if (SUCCEEDED(hr)) {  
  73.             m_pTIPFilter->OutputPin()->SetAllocator( pAllocator );  
  74.         }  
  75.     }  
  76.   
  77.     if (SUCCEEDED(hr)) {  
  78.   
  79.         // It's possible that the old and the new are the same thing.  
  80.         // AddRef before release ensures that we don't unload it.  
  81.         pAllocator->AddRef();  
  82.   
  83.         if( m_pAllocator != NULL )  
  84.             m_pAllocator->Release();  
  85.   
  86.         m_pAllocator = pAllocator;    // We have an allocator for the input pin  
  87.     }  
  88.   
  89.     return hr;  
  90.   
  91. } // NotifyAllocator  

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  等。

时间: 2024-10-31 10:40:24

Filter组件开发中的SDK基类分析的相关文章

J2EE平台WEB组件开发中如何使用定制标签

j2ee|web|组件开发 摘要: J2EE PLATFORM WEB组件开发涉及SERVLET 和JSP技术,SERVLET和JSP各有其优缺点.JVAVABEAN和定制标签对JSP的表示能力提供了很好的扩展,大大提高了JSP的表示能力,同时它们的引入使WEB开发可以很好的进行分工,提高开发效率,降低开发成本,同时提高了JSP页面的可读性.重用性.可维护性.本文将介绍J2EE平台WEB组件开发中如何使用定制标签,主要介绍开发定制标签的意义,原理.步骤.在TOMCAT上的发布并给出一个典型的标签

asp.net控件开发技巧(2)关闭基类不必要的功能

1.关闭容器 Control类有Controls集合属性,即继承Control类的控件都是一个容器控件,asp.net控件内置的有PlaceHolder控件,其只继承自Control类,什么也没做.但所有控件都是继承自Control类的.如一个label控件,照样可以当容器使用. label1.Controls.add(control) 有些控件则不需要这个功能,如Literal控件,只输出纯文字,不允许添加子控件 开发技巧(2)关闭基类不必要的功能-"> 很简单,重写CreateCont

继承-c#中如何把基类的public方法变成private?

问题描述 c#中如何把基类的public方法变成private? 如题,自定义的类默认继承了Equals,GetHashCode,GetType,ToString四个方法,如何把这四个方法隐藏,让自定义的类看不到这四个方法 解决方案 public new string ToString() { return base.ToString(); } 你的父类可以这样写,这样子类使用的只能是父类的ToString,父类重写了父类的父类的ToString方法 解决方案二: 任何C#中的对象都拥有你说的4

C++第13周项目3 - 车辆类多重继承中使用虚基类

课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565,本周题目链接:http://blog.csdn.net/sxhelijian/article/details/8953304 [项目3]在下面一段类的定义中,自行车类的虚基类为车辆类,机动车类的虚基类也为车辆类,摩托车类的基类为自行车类和机动车类,类之间均为公有继承.(1)根据上面各类间关系的描述,补全下面程序段中空缺的代码(2)实现程序中声明的成员函数,注意相应操作中的

iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用

iOS开发中的手势体系--UIGestureRecognizer分析及其子类的使用 一.引言         在iOS系统中,手势是进行用户交互的重要方式,通过UIGestureRecognizer类,我们可以轻松的创建出各种手势应用于app中.关于UIGestureRecognizer类,是对iOS中的事件传递机制面向应用的封装,将手势消息的传递抽象为了对象.有关消息传递的一些讨论,在前面的博客中有提到: iOS事件响应控制:http://my.oschina.net/u/2340880/bl

如何在派生类中的隐藏基类的虚拟重载函数

我创建了一个类,基类中有虚拟重载函数.我想在派生类中改写基类中的虚拟重载函数.代码如下: #include <iostream.h>class B {private: int nNumber;public: virtual void test() { cout << "B::test()\n"; } virtual void test(int x) { nNumber = x; // 将传入的参数赋值给私有成员 cout << "B::te

Android编程开发中ListView的常见用法分析_Android

本文实例讲述了Android编程开发中ListView的常见用法.分享给大家供大家参考,具体如下: 一.ListView的使用步骤 ListView的使用通常有以下三个要素: (1)ListView中每个条目的布局; (2)填充进入ListView中的内容; (3)将内容与页面进行整合的Adapter. 因此,使用ListView也通常有以下三个步骤: (1)创建ListView条目的布局文件(或使用Android SDK提供的布局); (2)创建填充进入ListView中的内容,如字符串.图片

Android编程开发中ListView的常见用法分析

本文实例讲述了Android编程开发中ListView的常见用法.分享给大家供大家参考,具体如下: 一.ListView的使用步骤 ListView的使用通常有以下三个要素: (1)ListView中每个条目的布局; (2)填充进入ListView中的内容; (3)将内容与页面进行整合的Adapter. 因此,使用ListView也通常有以下三个步骤: (1)创建ListView条目的布局文件(或使用Android SDK提供的布局); (2)创建填充进入ListView中的内容,如字符串.图片

Android开发中include控件用法分析_Android

本文实例讲述了Android开发中include控件用法.分享给大家供大家参考,具体如下: 我们知道,基于Android系统的应用程序的开发,界面设计是非常重要的,它关系着用户体验的好坏.一个好的界面设计,不是用一个xml布局就可以搞定的.当一个activity中的控件非常多的时候,所有的布局文件都放在一个xml文件中,很容易想象那是多么糟糕的事情!笔者通过自身的经历,用include控件来解决这个问题,下面是一个小例子,仅仅实现的是布局,没有响应代码的设计. user.xml文件内容如下: <