//------------------------------------------------------------------------------ // 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__ */