• Filter组件开发中的SDK基类分析 分类: DirectX 2014-10-09 15:50 477人阅读 评论(0) 收藏


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

    1、CBaseObject

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

    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接口类都是直接或间接从这个类继承来的。

    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:

    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. };  


     

    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组件的情况)。

    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:

    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接口,该接口用于质量控制

    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的状态转换相对应

    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函数

    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:

    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内存的释放)

    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. };  


     

     

    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:

    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 上的首选媒体类型。

     

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

    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. };  

     

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

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

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

    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  


     

    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  


     

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

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    【转】《基于MFC的OpenGL编程》Part 5 Transformations Rotations, Translations and Scaling
    【转】 《基于MFC的OpenGL编程》Part 10 Texture Mapping
    【转】 《基于MFC的OpenGL编程》Part 11 Blending, Antialiasing and Fog
    win form 托盘功能的实现(引用CSDN)
    C# win form退出窗体时对话框实用
    智能DNS 笔记
    iis无法启动, 找出占用80端口的罪魁祸首
    gvim for windows的剪贴板操作
    内容交换
    Content Networking 读书笔记
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706502.html
Copyright © 2020-2023  润新知