//------------------------------------------------------------------------------ // File: TransIP.h // // Desc: DirectShow base classes - defines classes from which simple // Transform-In-Place filters may be derived. // // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // The difference between this and Transfrm.h is that Transfrm copies the data. // // It assumes the filter 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 __TRANSIP__ #define __TRANSIP__ // ====================================================================== // This is the com object that represents a simple transform filter. It // supports IBaseFilter, IMediaFilter and two pins through nested interfaces // ====================================================================== class CTransInPlaceFilter; // Several of the pin functions call filter functions to do the work, // so you can often use the pin classes unaltered, just overriding the // functions in CTransInPlaceFilter. If that's not enough and you want // to derive your own pin class, override GetPin in the filter to supply // your own pin classes to the filter. // ================================================== // Implements the input pin // ================================================== class CTransInPlaceInputPin : public CTransformInputPin { protected: CTransInPlaceFilter * const m_pTIPFilter; // our filter BOOL m_bReadOnly; // incoming stream is read only public: CTransInPlaceInputPin( __in_opt LPCTSTR pObjectName, __inout CTransInPlaceFilter *pFilter, __inout HRESULT *phr, __in_opt LPCWSTR pName); // --- IMemInputPin ----- // Provide an enumerator for media types by getting one from downstream STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); // Say whether media type is acceptable. HRESULT CheckMediaType(const CMediaType* pmt); // Return our upstream allocator STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator); // get told which allocator the upstream output pin is actually // going to use. STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator, BOOL bReadOnly); // Allow the filter to see what allocator we have // N.B. This does NOT AddRef __out IMemAllocator * PeekAllocator() const { return m_pAllocator; } // Pass this on downstream if it ever gets called. STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps); HRESULT CompleteConnect(IPin *pReceivePin); inline const BOOL ReadOnly() { return m_bReadOnly ; } }; // CTransInPlaceInputPin // ================================================== // Implements the output pin // ================================================== class CTransInPlaceOutputPin : public CTransformOutputPin { protected: // m_pFilter points to our CBaseFilter CTransInPlaceFilter * const m_pTIPFilter; public: CTransInPlaceOutputPin( __in_opt LPCTSTR pObjectName, __inout CTransInPlaceFilter *pFilter, __inout HRESULT *phr, __in_opt LPCWSTR pName); // --- CBaseOutputPin ------------ // negotiate the allocator and its buffer size/count // Insists on using our own allocator. (Actually the one upstream of us). // We don't override this - instead we just agree the default // then let the upstream filter decide for itself on reconnect // virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc); // Provide a media type enumerator. Get it from upstream. STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); // Say whether media type is acceptable. HRESULT CheckMediaType(const CMediaType* pmt); // This just saves the allocator being used on the output pin // Also called by input pin's GetAllocator() void SetAllocator(IMemAllocator * pAllocator); __out_opt IMemInputPin * ConnectedIMemInputPin() { return m_pInputPin; } // Allow the filter to see what allocator we have // N.B. This does NOT AddRef __out IMemAllocator * PeekAllocator() const { return m_pAllocator; } HRESULT CompleteConnect(IPin *pReceivePin); }; // CTransInPlaceOutputPin class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter { public: // map getpin/getpincount for base enum of pins to owner // override this to return more specialised pin objects virtual CBasePin *GetPin(int n); public: // Set bModifiesData == false if your derived filter does // not modify the data samples (for instance it's just copying // them somewhere else or looking at the timestamps). CTransInPlaceFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, bool bModifiesData = true); #ifdef UNICODE CTransInPlaceFilter(__in_opt LPCSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, bool bModifiesData = true); #endif // The following are defined to avoid undefined pure virtuals. // Even if they are never called, they will give linkage warnings/errors // We override EnumMediaTypes to bypass the transform class enumerator // which would otherwise call this. HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) { DbgBreak("CTransInPlaceFilter::GetMediaType should never be called"); return E_UNEXPECTED; } // This is called when we actually have to provide our own allocator. HRESULT DecideBufferSize(IMemAllocator*, __inout ALLOCATOR_PROPERTIES *); // The functions which call this in CTransform are overridden in this // class to call CheckInputType with the assumption that the type // does not change. In Debug builds some calls will be made and // we just ensure that they do not assert. HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) { return S_OK; }; // ================================================================= // ----- You may want to override this ----------------------------- // ================================================================= HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin); // chance to customize the transform process virtual HRESULT Receive(IMediaSample *pSample); // ================================================================= // ----- You MUST override these ----------------------------------- // ================================================================= virtual HRESULT Transform(IMediaSample *pSample) PURE; // this goes in the factory template table to create new instances // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); #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_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace")); } #endif // PERF // implementation details protected: __out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource); #ifdef PERF int m_idTransInPlace; // performance measuring id #endif // PERF bool m_bModifiesData; // Does this filter change the data? // these hold our input and output pins friend class CTransInPlaceInputPin; friend class CTransInPlaceOutputPin; __out CTransInPlaceInputPin *InputPin() const { return (CTransInPlaceInputPin *)m_pInput; }; __out CTransInPlaceOutputPin *OutputPin() const { return (CTransInPlaceOutputPin *)m_pOutput; }; // Helper to see if the input and output types match BOOL TypesMatch() { return InputPin()->CurrentMediaType() == OutputPin()->CurrentMediaType(); } // Are the input and output allocators different? BOOL UsingDifferentAllocators() const { return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator(); } }; // CTransInPlaceFilter #endif /* __TRANSIP__ */