305 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			305 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // 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__ */
 | |
| 
 | |
| 
 |