| //------------------------------------------------------------------------------ | |
| // File: Transfrm.h | |
| // | |
| // Desc: DirectShow base classes - defines classes from which simple | |
| // transform codecs may be derived. | |
| // | |
| // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. | |
| //------------------------------------------------------------------------------ | |
| // It assumes the codec has one input and one output stream, and has no | |
| // interest in memory management, interface negotiation or anything else. | |
| // | |
| // derive your class from this, and supply Transform and the media type/format | |
| // negotiation functions. Implement that class, compile and link and | |
| // you're done. | |
| #ifndef __TRANSFRM__ | |
| #define __TRANSFRM__ | |
| // ====================================================================== | |
| // This is the com object that represents a simple transform filter. It | |
| // supports IBaseFilter, IMediaFilter and two pins through nested interfaces | |
| // ====================================================================== | |
| class CTransformFilter; | |
| // ================================================== | |
| // Implements the input pin | |
| // ================================================== | |
| class CTransformInputPin : public CBaseInputPin | |
| { | |
| friend class CTransformFilter; | |
| protected: | |
| CTransformFilter *m_pTransformFilter; | |
| public: | |
| CTransformInputPin( | |
| __in_opt LPCTSTR pObjectName, | |
| __inout CTransformFilter *pTransformFilter, | |
| __inout HRESULT * phr, | |
| __in_opt LPCWSTR pName); | |
| #ifdef UNICODE | |
| CTransformInputPin( | |
| __in_opt LPCSTR pObjectName, | |
| __inout CTransformFilter *pTransformFilter, | |
| __inout HRESULT * phr, | |
| __in_opt LPCWSTR pName); | |
| #endif | |
| STDMETHODIMP QueryId(__deref_out LPWSTR * Id) | |
| { | |
| return AMGetWideString(L"In", Id); | |
| } | |
| // Grab and release extra interfaces if required | |
| HRESULT CheckConnect(IPin *pPin); | |
| HRESULT BreakConnect(); | |
| HRESULT CompleteConnect(IPin *pReceivePin); | |
| // check that we can support this output type | |
| HRESULT CheckMediaType(const CMediaType* mtIn); | |
| // set the connection media type | |
| HRESULT SetMediaType(const CMediaType* mt); | |
| // --- IMemInputPin ----- | |
| // here's the next block of data from the stream. | |
| // AddRef it yourself if you need to hold it beyond the end | |
| // of this call. | |
| STDMETHODIMP Receive(IMediaSample * pSample); | |
| // provide EndOfStream that passes straight downstream | |
| // (there is no queued data) | |
| STDMETHODIMP EndOfStream(void); | |
| // passes it to CTransformFilter::BeginFlush | |
| STDMETHODIMP BeginFlush(void); | |
| // passes it to CTransformFilter::EndFlush | |
| STDMETHODIMP EndFlush(void); | |
| STDMETHODIMP NewSegment( | |
| REFERENCE_TIME tStart, | |
| REFERENCE_TIME tStop, | |
| double dRate); | |
| // Check if it's OK to process samples | |
| virtual HRESULT CheckStreaming(); | |
| // Media type | |
| public: | |
| CMediaType& CurrentMediaType() { return m_mt; }; | |
| }; | |
| // ================================================== | |
| // Implements the output pin | |
| // ================================================== | |
| class CTransformOutputPin : public CBaseOutputPin | |
| { | |
| friend class CTransformFilter; | |
| protected: | |
| CTransformFilter *m_pTransformFilter; | |
| public: | |
| // implement IMediaPosition by passing upstream | |
| IUnknown * m_pPosition; | |
| CTransformOutputPin( | |
| __in_opt LPCTSTR pObjectName, | |
| __inout CTransformFilter *pTransformFilter, | |
| __inout HRESULT * phr, | |
| __in_opt LPCWSTR pName); | |
| #ifdef UNICODE | |
| CTransformOutputPin( | |
| __in_opt LPCSTR pObjectName, | |
| __inout CTransformFilter *pTransformFilter, | |
| __inout HRESULT * phr, | |
| __in_opt LPCWSTR pName); | |
| #endif | |
| ~CTransformOutputPin(); | |
| // override to expose IMediaPosition | |
| STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv); | |
| // --- CBaseOutputPin ------------ | |
| STDMETHODIMP QueryId(__deref_out LPWSTR * Id) | |
| { | |
| return AMGetWideString(L"Out", Id); | |
| } | |
| // Grab and release extra interfaces if required | |
| HRESULT CheckConnect(IPin *pPin); | |
| HRESULT BreakConnect(); | |
| HRESULT CompleteConnect(IPin *pReceivePin); | |
| // check that we can support this output type | |
| HRESULT CheckMediaType(const CMediaType* mtOut); | |
| // set the connection media type | |
| HRESULT SetMediaType(const CMediaType *pmt); | |
| // called from CBaseOutputPin during connection to ask for | |
| // the count and size of buffers we need. | |
| HRESULT DecideBufferSize( | |
| IMemAllocator * pAlloc, | |
| __inout ALLOCATOR_PROPERTIES *pProp); | |
| // returns the preferred formats for a pin | |
| HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); | |
| // inherited from IQualityControl via CBasePin | |
| STDMETHODIMP Notify(IBaseFilter * pSender, Quality q); | |
| // Media type | |
| public: | |
| CMediaType& CurrentMediaType() { return m_mt; }; | |
| }; | |
| class AM_NOVTABLE CTransformFilter : public CBaseFilter | |
| { | |
| public: | |
| // map getpin/getpincount for base enum of pins to owner | |
| // override this to return more specialised pin objects | |
| virtual int GetPinCount(); | |
| virtual CBasePin * GetPin(int n); | |
| STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin); | |
| // override state changes to allow derived transform filter | |
| // to control streaming start/stop | |
| STDMETHODIMP Stop(); | |
| STDMETHODIMP Pause(); | |
| public: | |
| CTransformFilter(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); | |
| #ifdef UNICODE | |
| CTransformFilter(__in_opt LPCSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); | |
| #endif | |
| ~CTransformFilter(); | |
| // ================================================================= | |
| // ----- override these bits --------------------------------------- | |
| // ================================================================= | |
| // These must be supplied in a derived class | |
| virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); | |
| // check if you can support mtIn | |
| virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; | |
| // check if you can support the transform from this input to this output | |
| virtual HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut) PURE; | |
| // this goes in the factory template table to create new instances | |
| // static CCOMObject * CreateInstance(__inout_opt LPUNKNOWN, HRESULT *); | |
| // call the SetProperties function with appropriate arguments | |
| virtual HRESULT DecideBufferSize( | |
| IMemAllocator * pAllocator, | |
| __inout ALLOCATOR_PROPERTIES *pprop) PURE; | |
| // override to suggest OUTPUT pin media types | |
| virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) PURE; | |
| // ================================================================= | |
| // ----- Optional Override Methods ----------------------- | |
| // ================================================================= | |
| // you can also override these if you want to know about streaming | |
| virtual HRESULT StartStreaming(); | |
| virtual HRESULT StopStreaming(); | |
| // override if you can do anything constructive with quality notifications | |
| virtual HRESULT AlterQuality(Quality q); | |
| // override this to know when the media type is actually set | |
| virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); | |
| // chance to grab extra interfaces on connection | |
| virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); | |
| virtual HRESULT BreakConnect(PIN_DIRECTION dir); | |
| virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); | |
| // chance to customize the transform process | |
| virtual HRESULT Receive(IMediaSample *pSample); | |
| // Standard setup for output sample | |
| HRESULT InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample); | |
| // if you override Receive, you may need to override these three too | |
| virtual HRESULT EndOfStream(void); | |
| virtual HRESULT BeginFlush(void); | |
| virtual HRESULT EndFlush(void); | |
| virtual HRESULT NewSegment( | |
| REFERENCE_TIME tStart, | |
| REFERENCE_TIME tStop, | |
| double dRate); | |
| #ifdef PERF | |
| // Override to register performance measurement with a less generic string | |
| // You should do this to avoid confusion with other filters | |
| virtual void RegisterPerfId() | |
| {m_idTransform = MSR_REGISTER(TEXT("Transform"));} | |
| #endif // PERF | |
| // implementation details | |
| protected: | |
| #ifdef PERF | |
| int m_idTransform; // performance measuring id | |
| #endif | |
| BOOL m_bEOSDelivered; // have we sent EndOfStream | |
| BOOL m_bSampleSkipped; // Did we just skip a frame | |
| BOOL m_bQualityChanged; // Have we degraded? | |
| // critical section protecting filter state. | |
| CCritSec m_csFilter; | |
| // critical section stopping state changes (ie Stop) while we're | |
| // processing a sample. | |
| // | |
| // This critical section is held when processing | |
| // events that occur on the receive thread - Receive() and EndOfStream(). | |
| // | |
| // If you want to hold both m_csReceive and m_csFilter then grab | |
| // m_csFilter FIRST - like CTransformFilter::Stop() does. | |
| CCritSec m_csReceive; | |
| // these hold our input and output pins | |
| friend class CTransformInputPin; | |
| friend class CTransformOutputPin; | |
| CTransformInputPin *m_pInput; | |
| CTransformOutputPin *m_pOutput; | |
| }; | |
| #endif /* __TRANSFRM__ */ | |