summaryrefslogtreecommitdiffstats
path: root/thirdparties/win32/include/directshow/amfilter.h
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparties/win32/include/directshow/amfilter.h')
-rw-r--r--thirdparties/win32/include/directshow/amfilter.h1587
1 files changed, 1587 insertions, 0 deletions
diff --git a/thirdparties/win32/include/directshow/amfilter.h b/thirdparties/win32/include/directshow/amfilter.h
new file mode 100644
index 0000000..8646bc0
--- /dev/null
+++ b/thirdparties/win32/include/directshow/amfilter.h
@@ -0,0 +1,1587 @@
+//------------------------------------------------------------------------------
+// File: AMFilter.h
+//
+// Desc: DirectShow base classes - efines class hierarchy for streams
+// architecture.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __FILTER__
+#define __FILTER__
+
+/* The following classes are declared in this header: */
+
+class CBaseMediaFilter; // IMediaFilter support
+class CBaseFilter; // IBaseFilter,IMediaFilter support
+class CBasePin; // Abstract base class for IPin interface
+class CEnumPins; // Enumerate input and output pins
+class CEnumMediaTypes; // Enumerate the pin's preferred formats
+class CBaseOutputPin; // Adds data provider member functions
+class CBaseInputPin; // Implements IMemInputPin interface
+class CMediaSample; // Basic transport unit for IMemInputPin
+class CBaseAllocator; // General list guff for most allocators
+class CMemAllocator; // Implements memory buffer allocation
+
+
+//=====================================================================
+//=====================================================================
+//
+// QueryFilterInfo and QueryPinInfo AddRef the interface pointers
+// they return. You can use the macro below to release the interface.
+//
+//=====================================================================
+//=====================================================================
+
+#define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
+
+#define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseMediaFilter
+//
+// Abstract base class implementing IMediaFilter.
+//
+// Typically you will derive your filter from CBaseFilter rather than
+// this, unless you are implementing an object such as a plug-in
+// distributor that needs to support IMediaFilter but not IBaseFilter.
+//
+// Note that IMediaFilter is derived from IPersist to allow query of
+// class id.
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
+ public IMediaFilter
+{
+
+protected:
+
+ FILTER_STATE m_State; // current state: running, paused
+ IReferenceClock *m_pClock; // this filter's reference clock
+ // note: all filters in a filter graph use the same clock
+
+ // offset from stream time to reference time
+ CRefTime m_tStart;
+
+ CLSID m_clsid; // This filters clsid
+ // used for serialization
+ CCritSec *m_pLock; // Object we use for locking
+
+public:
+
+ CBaseMediaFilter(
+ __in_opt LPCTSTR pName,
+ __inout_opt LPUNKNOWN pUnk,
+ __in CCritSec *pLock,
+ REFCLSID clsid);
+
+ virtual ~CBaseMediaFilter();
+
+ DECLARE_IUNKNOWN
+
+ // override this to say what interfaces we support where
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+
+ //
+ // --- IPersist method ---
+ //
+
+ STDMETHODIMP GetClassID(__out CLSID *pClsID);
+
+ // --- IMediaFilter methods ---
+
+ STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
+
+ STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
+
+ STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
+
+ // default implementation of Stop and Pause just record the
+ // state. Override to activate or de-activate your filter.
+ // Note that Run when called from Stopped state will call Pause
+ // to ensure activation, so if you are a source or transform
+ // you will probably not need to override Run.
+ STDMETHODIMP Stop();
+ STDMETHODIMP Pause();
+
+
+ // the start parameter is the difference to be added to the
+ // sample's stream time to get the reference time for
+ // its presentation
+ STDMETHODIMP Run(REFERENCE_TIME tStart);
+
+ // --- helper methods ---
+
+ // return the current stream time - ie find out what
+ // stream time should be appearing now
+ virtual HRESULT StreamTime(CRefTime& rtStream);
+
+ // Is the filter currently active? (running or paused)
+ BOOL IsActive() {
+ CAutoLock cObjectLock(m_pLock);
+ return ((m_State == State_Paused) || (m_State == State_Running));
+ };
+};
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseFilter
+//
+// An abstract class providing basic IBaseFilter support for pin
+// enumeration and filter information reading.
+//
+// We cannot derive from CBaseMediaFilter since methods in IMediaFilter
+// are also in IBaseFilter and would be ambiguous. Since much of the code
+// assumes that they derive from a class that has m_State and other state
+// directly available, we duplicate code from CBaseMediaFilter rather than
+// having a member variable.
+//
+// Derive your filter from this, or from a derived object such as
+// CTransformFilter.
+//=====================================================================
+//=====================================================================
+
+
+class AM_NOVTABLE CBaseFilter : public CUnknown, // Handles an IUnknown
+ public IBaseFilter, // The Filter Interface
+ public IAMovieSetup // For un/registration
+{
+
+friend class CBasePin;
+
+protected:
+ FILTER_STATE m_State; // current state: running, paused
+ IReferenceClock *m_pClock; // this graph's ref clock
+ CRefTime m_tStart; // offset from stream time to reference time
+ CLSID m_clsid; // This filters clsid
+ // used for serialization
+ CCritSec *m_pLock; // Object we use for locking
+
+ WCHAR *m_pName; // Full filter name
+ IFilterGraph *m_pGraph; // Graph we belong to
+ IMediaEventSink *m_pSink; // Called with notify events
+ LONG m_PinVersion; // Current pin version
+
+public:
+
+ CBaseFilter(
+ __in_opt LPCTSTR pName, // Object description
+ __inout_opt LPUNKNOWN pUnk, // IUnknown of delegating object
+ __in CCritSec *pLock, // Object who maintains lock
+ REFCLSID clsid); // The clsid to be used to serialize this filter
+
+ CBaseFilter(
+ __in_opt LPCTSTR pName, // Object description
+ __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
+ __in CCritSec *pLock, // Object who maintains lock
+ REFCLSID clsid, // The clsid to be used to serialize this filter
+ __inout HRESULT *phr); // General OLE return code
+#ifdef UNICODE
+ CBaseFilter(
+ __in_opt LPCSTR pName, // Object description
+ __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
+ __in CCritSec *pLock, // Object who maintains lock
+ REFCLSID clsid); // The clsid to be used to serialize this filter
+
+ CBaseFilter(
+ __in_opt LPCSTR pName, // Object description
+ __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
+ __in CCritSec *pLock, // Object who maintains lock
+ REFCLSID clsid, // The clsid to be used to serialize this filter
+ __inout HRESULT *phr); // General OLE return code
+#endif
+ ~CBaseFilter();
+
+ DECLARE_IUNKNOWN
+
+ // override this to say what interfaces we support where
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+#ifdef DEBUG
+ STDMETHODIMP_(ULONG) NonDelegatingRelease();
+#endif
+
+ //
+ // --- IPersist method ---
+ //
+
+ STDMETHODIMP GetClassID(__out CLSID *pClsID);
+
+ // --- IMediaFilter methods ---
+
+ STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
+
+ STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
+
+ STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
+
+
+ // override Stop and Pause so we can activate the pins.
+ // Note that Run will call Pause first if activation needed.
+ // Override these if you want to activate your filter rather than
+ // your pins.
+ STDMETHODIMP Stop();
+ STDMETHODIMP Pause();
+
+ // the start parameter is the difference to be added to the
+ // sample's stream time to get the reference time for
+ // its presentation
+ STDMETHODIMP Run(REFERENCE_TIME tStart);
+
+ // --- helper methods ---
+
+ // return the current stream time - ie find out what
+ // stream time should be appearing now
+ virtual HRESULT StreamTime(CRefTime& rtStream);
+
+ // Is the filter currently active?
+ BOOL IsActive() {
+ CAutoLock cObjectLock(m_pLock);
+ return ((m_State == State_Paused) || (m_State == State_Running));
+ };
+
+ // Is this filter stopped (without locking)
+ BOOL IsStopped() {
+ return (m_State == State_Stopped);
+ };
+
+ //
+ // --- IBaseFilter methods ---
+ //
+
+ // pin enumerator
+ STDMETHODIMP EnumPins(
+ __deref_out IEnumPins ** ppEnum);
+
+
+ // default behaviour of FindPin assumes pin ids are their names
+ STDMETHODIMP FindPin(
+ LPCWSTR Id,
+ __deref_out IPin ** ppPin
+ );
+
+ STDMETHODIMP QueryFilterInfo(
+ __out FILTER_INFO * pInfo);
+
+ STDMETHODIMP JoinFilterGraph(
+ __inout_opt IFilterGraph * pGraph,
+ __in_opt LPCWSTR pName);
+
+ // return a Vendor information string. Optional - may return E_NOTIMPL.
+ // memory returned should be freed using CoTaskMemFree
+ // default implementation returns E_NOTIMPL
+ STDMETHODIMP QueryVendorInfo(
+ __deref_out LPWSTR* pVendorInfo
+ );
+
+ // --- helper methods ---
+
+ // send an event notification to the filter graph if we know about it.
+ // returns S_OK if delivered, S_FALSE if the filter graph does not sink
+ // events, or an error otherwise.
+ HRESULT NotifyEvent(
+ long EventCode,
+ LONG_PTR EventParam1,
+ LONG_PTR EventParam2);
+
+ // return the filter graph we belong to
+ __out_opt IFilterGraph *GetFilterGraph() {
+ return m_pGraph;
+ }
+
+ // Request reconnect
+ // pPin is the pin to reconnect
+ // pmt is the type to reconnect with - can be NULL
+ // Calls ReconnectEx on the filter graph
+ HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
+
+ // find out the current pin version (used by enumerators)
+ virtual LONG GetPinVersion();
+ void IncrementPinVersion();
+
+ // you need to supply these to access the pins from the enumerator
+ // and for default Stop and Pause/Run activation.
+ virtual int GetPinCount() PURE;
+ virtual CBasePin *GetPin(int n) PURE;
+
+ // --- IAMovieSetup methods ---
+
+ STDMETHODIMP Register(); // ask filter to register itself
+ STDMETHODIMP Unregister(); // and unregister itself
+
+ // --- setup helper methods ---
+ // (override to return filters setup data)
+
+ virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
+
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBasePin
+//
+// Abstract class that supports the basics of IPin
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
+{
+
+protected:
+
+ WCHAR * m_pName; // This pin's name
+ IPin *m_Connected; // Pin we have connected to
+ PIN_DIRECTION m_dir; // Direction of this pin
+ CCritSec *m_pLock; // Object we use for locking
+ bool m_bRunTimeError; // Run time error generated
+ bool m_bCanReconnectWhenActive; // OK to reconnect when active
+ bool m_bTryMyTypesFirst; // When connecting enumerate
+ // this pin's types first
+ CBaseFilter *m_pFilter; // Filter we were created by
+ IQualityControl *m_pQSink; // Target for Quality messages
+ LONG m_TypeVersion; // Holds current type version
+ CMediaType m_mt; // Media type of connection
+
+ CRefTime m_tStart; // time from NewSegment call
+ CRefTime m_tStop; // time from NewSegment
+ double m_dRate; // rate from NewSegment
+
+#ifdef DEBUG
+ LONG m_cRef; // Ref count tracing
+#endif
+
+ // displays pin connection information
+
+#ifdef DEBUG
+ void DisplayPinInfo(IPin *pReceivePin);
+ void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
+#else
+ void DisplayPinInfo(IPin *pReceivePin) {};
+ void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
+#endif
+
+ // used to agree a media type for a pin connection
+
+ // given a specific media type, attempt a connection (includes
+ // checking that the type is acceptable to this pin)
+ HRESULT
+ AttemptConnection(
+ IPin* pReceivePin, // connect to this pin
+ const CMediaType* pmt // using this type
+ );
+
+ // try all the media types in this enumerator - for each that
+ // we accept, try to connect using ReceiveConnection.
+ HRESULT TryMediaTypes(
+ IPin *pReceivePin, // connect to this pin
+ __in_opt const CMediaType *pmt, // proposed type from Connect
+ IEnumMediaTypes *pEnum); // try this enumerator
+
+ // establish a connection with a suitable mediatype. Needs to
+ // propose a media type if the pmt pointer is null or partially
+ // specified - use TryMediaTypes on both our and then the other pin's
+ // enumerator until we find one that works.
+ HRESULT AgreeMediaType(
+ IPin *pReceivePin, // connect to this pin
+ const CMediaType *pmt); // proposed type from Connect
+
+public:
+
+ CBasePin(
+ __in_opt LPCTSTR pObjectName, // Object description
+ __in CBaseFilter *pFilter, // Owning filter who knows about pins
+ __in CCritSec *pLock, // Object who implements the lock
+ __inout HRESULT *phr, // General OLE return code
+ __in_opt LPCWSTR pName, // Pin name for us
+ PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
+#ifdef UNICODE
+ CBasePin(
+ __in_opt LPCSTR pObjectName, // Object description
+ __in CBaseFilter *pFilter, // Owning filter who knows about pins
+ __in CCritSec *pLock, // Object who implements the lock
+ __inout HRESULT *phr, // General OLE return code
+ __in_opt LPCWSTR pName, // Pin name for us
+ PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
+#endif
+ virtual ~CBasePin();
+
+ DECLARE_IUNKNOWN
+
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+ STDMETHODIMP_(ULONG) NonDelegatingRelease();
+ STDMETHODIMP_(ULONG) NonDelegatingAddRef();
+
+ // --- IPin methods ---
+
+ // take lead role in establishing a connection. Media type pointer
+ // may be null, or may point to partially-specified mediatype
+ // (subtype or format type may be GUID_NULL).
+ STDMETHODIMP Connect(
+ IPin * pReceivePin,
+ __in_opt const AM_MEDIA_TYPE *pmt // optional media type
+ );
+
+ // (passive) accept a connection from another pin
+ STDMETHODIMP ReceiveConnection(
+ IPin * pConnector, // this is the initiating connecting pin
+ const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
+ );
+
+ STDMETHODIMP Disconnect();
+
+ STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
+
+ STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
+
+ STDMETHODIMP QueryPinInfo(
+ __out PIN_INFO * pInfo
+ );
+
+ STDMETHODIMP QueryDirection(
+ __out PIN_DIRECTION * pPinDir
+ );
+
+ STDMETHODIMP QueryId(
+ __deref_out LPWSTR * Id
+ );
+
+ // does the pin support this media type
+ STDMETHODIMP QueryAccept(
+ const AM_MEDIA_TYPE *pmt
+ );
+
+ // return an enumerator for this pins preferred media types
+ STDMETHODIMP EnumMediaTypes(
+ __deref_out IEnumMediaTypes **ppEnum
+ );
+
+ // return an array of IPin* - the pins that this pin internally connects to
+ // All pins put in the array must be AddReffed (but no others)
+ // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
+ // Default: return E_NOTIMPL
+ // The filter graph will interpret NOT_IMPL as any input pin connects to
+ // all visible output pins and vice versa.
+ // apPin can be NULL if nPin==0 (not otherwise).
+ STDMETHODIMP QueryInternalConnections(
+ __out_ecount_part(*nPin,*nPin) IPin* *apPin, // array of IPin*
+ __inout ULONG *nPin // on input, the number of slots
+ // on output the number of pins
+ ) { return E_NOTIMPL; }
+
+ // Called when no more data will be sent
+ STDMETHODIMP EndOfStream(void);
+
+ // Begin/EndFlush still PURE
+
+ // NewSegment notifies of the start/stop/rate applying to the data
+ // about to be received. Default implementation records data and
+ // returns S_OK.
+ // Override this to pass downstream.
+ STDMETHODIMP NewSegment(
+ REFERENCE_TIME tStart,
+ REFERENCE_TIME tStop,
+ double dRate);
+
+ //================================================================================
+ // IQualityControl methods
+ //================================================================================
+
+ STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+
+ STDMETHODIMP SetSink(IQualityControl * piqc);
+
+ // --- helper methods ---
+
+ // Returns true if the pin is connected. false otherwise.
+ BOOL IsConnected(void) {return (m_Connected != NULL); };
+ // Return the pin this is connected to (if any)
+ IPin * GetConnected() { return m_Connected; };
+
+ // Check if our filter is currently stopped
+ BOOL IsStopped() {
+ return (m_pFilter->m_State == State_Stopped);
+ };
+
+ // find out the current type version (used by enumerators)
+ virtual LONG GetMediaTypeVersion();
+ void IncrementTypeVersion();
+
+ // switch the pin to active (paused or running) mode
+ // not an error to call this if already active
+ virtual HRESULT Active(void);
+
+ // switch the pin to inactive state - may already be inactive
+ virtual HRESULT Inactive(void);
+
+ // Notify of Run() from filter
+ virtual HRESULT Run(REFERENCE_TIME tStart);
+
+ // check if the pin can support this specific proposed type and format
+ virtual HRESULT CheckMediaType(const CMediaType *) PURE;
+
+ // set the connection to use this format (previously agreed)
+ virtual HRESULT SetMediaType(const CMediaType *);
+
+ // check that the connection is ok before verifying it
+ // can be overridden eg to check what interfaces will be supported.
+ virtual HRESULT CheckConnect(IPin *);
+
+ // Set and release resources required for a connection
+ virtual HRESULT BreakConnect();
+ virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+ // returns the preferred formats for a pin
+ virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
+
+ // access to NewSegment values
+ REFERENCE_TIME CurrentStopTime() {
+ return m_tStop;
+ }
+ REFERENCE_TIME CurrentStartTime() {
+ return m_tStart;
+ }
+ double CurrentRate() {
+ return m_dRate;
+ }
+
+ // Access name
+ LPWSTR Name() { return m_pName; };
+
+ // Can reconnectwhen active?
+ void SetReconnectWhenActive(bool bCanReconnect)
+ {
+ m_bCanReconnectWhenActive = bCanReconnect;
+ }
+
+ bool CanReconnectWhenActive()
+ {
+ return m_bCanReconnectWhenActive;
+ }
+
+protected:
+ STDMETHODIMP DisconnectInternal();
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CEnumPins
+//
+// Pin enumerator class that works by calling CBaseFilter. This interface
+// is provided by CBaseFilter::EnumPins and calls GetPinCount() and
+// GetPin() to enumerate existing pins. Needs to be a separate object so
+// that it can be cloned (creating an existing object at the same
+// position in the enumeration)
+//
+//=====================================================================
+//=====================================================================
+
+class CEnumPins : public IEnumPins // The interface we support
+{
+ int m_Position; // Current ordinal position
+ int m_PinCount; // Number of pins available
+ CBaseFilter *m_pFilter; // The filter who owns us
+ LONG m_Version; // Pin version information
+ LONG m_cRef;
+
+ typedef CGenericList<CBasePin> CPinList;
+
+ CPinList m_PinCache; // These pointers have not been AddRef'ed and
+ // so they should not be dereferenced. They are
+ // merely kept to ID which pins have been enumerated.
+
+#ifdef DEBUG
+ DWORD m_dwCookie;
+#endif
+
+ /* If while we are retrieving a pin for example from the filter an error
+ occurs we assume that our internal state is stale with respect to the
+ filter (someone may have deleted all the pins). We can check before
+ starting whether or not the operation is likely to fail by asking the
+ filter what it's current version number is. If the filter has not
+ overriden the GetPinVersion method then this will always match */
+
+ BOOL AreWeOutOfSync() {
+ return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
+ };
+
+ /* This method performs the same operations as Reset, except is does not clear
+ the cache of pins already enumerated. */
+
+ STDMETHODIMP Refresh();
+
+public:
+
+ CEnumPins(
+ __in CBaseFilter *pFilter,
+ __in_opt CEnumPins *pEnumPins);
+
+ virtual ~CEnumPins();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IEnumPins
+ STDMETHODIMP Next(
+ ULONG cPins, // place this many pins...
+ __out_ecount(cPins) IPin ** ppPins, // ...in this array of IPin*
+ __out_opt ULONG * pcFetched // actual count passed returned here
+ );
+
+ STDMETHODIMP Skip(ULONG cPins);
+ STDMETHODIMP Reset();
+ STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
+
+
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CEnumMediaTypes
+//
+// Enumerates the preferred formats for input and output pins
+//=====================================================================
+//=====================================================================
+
+class CEnumMediaTypes : public IEnumMediaTypes // The interface we support
+{
+ int m_Position; // Current ordinal position
+ CBasePin *m_pPin; // The pin who owns us
+ LONG m_Version; // Media type version value
+ LONG m_cRef;
+#ifdef DEBUG
+ DWORD m_dwCookie;
+#endif
+
+ /* The media types a filter supports can be quite dynamic so we add to
+ the general IEnumXXXX interface the ability to be signaled when they
+ change via an event handle the connected filter supplies. Until the
+ Reset method is called after the state changes all further calls to
+ the enumerator (except Reset) will return E_UNEXPECTED error code */
+
+ BOOL AreWeOutOfSync() {
+ return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
+ };
+
+public:
+
+ CEnumMediaTypes(
+ __in CBasePin *pPin,
+ __in_opt CEnumMediaTypes *pEnumMediaTypes);
+
+ virtual ~CEnumMediaTypes();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IEnumMediaTypes
+ STDMETHODIMP Next(
+ ULONG cMediaTypes, // place this many pins...
+ __out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes, // ...in this array
+ __out_opt ULONG * pcFetched // actual count passed
+ );
+
+ STDMETHODIMP Skip(ULONG cMediaTypes);
+ STDMETHODIMP Reset();
+ STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
+};
+
+
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseOutputPin
+//
+// class derived from CBasePin that can pass buffers to a connected pin
+// that supports IMemInputPin. Supports IPin.
+//
+// Derive your output pin from this.
+//
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseOutputPin : public CBasePin
+{
+
+protected:
+
+ IMemAllocator *m_pAllocator;
+ IMemInputPin *m_pInputPin; // interface on the downstreaminput pin
+ // set up in CheckConnect when we connect.
+
+public:
+
+ CBaseOutputPin(
+ __in_opt LPCTSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+#ifdef UNICODE
+ CBaseOutputPin(
+ __in_opt LPCSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+#endif
+ // override CompleteConnect() so we can negotiate an allocator
+ virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+ // negotiate the allocator and its buffer size/count and other properties
+ // Calls DecideBufferSize to set properties
+ virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
+
+ // override this to set the buffer size and count. Return an error
+ // if the size/count is not to your liking.
+ // The allocator properties passed in are those requested by the
+ // input pin - use eg the alignment and prefix members if you have
+ // no preference on these.
+ virtual HRESULT DecideBufferSize(
+ IMemAllocator * pAlloc,
+ __inout ALLOCATOR_PROPERTIES * ppropInputRequest
+ ) PURE;
+
+ // returns an empty sample buffer from the allocator
+ virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
+ __in_opt REFERENCE_TIME * pStartTime,
+ __in_opt REFERENCE_TIME * pEndTime,
+ DWORD dwFlags);
+
+ // deliver a filled-in sample to the connected input pin
+ // note - you need to release it after calling this. The receiving
+ // pin will addref the sample if it needs to hold it beyond the
+ // call.
+ virtual HRESULT Deliver(IMediaSample *);
+
+ // override this to control the connection
+ virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
+ HRESULT CheckConnect(IPin *pPin);
+ HRESULT BreakConnect();
+
+ // override to call Commit and Decommit
+ HRESULT Active(void);
+ HRESULT Inactive(void);
+
+ // we have a default handling of EndOfStream which is to return
+ // an error, since this should be called on input pins only
+ STDMETHODIMP EndOfStream(void);
+
+ // called from elsewhere in our filter to pass EOS downstream to
+ // our connected input pin
+ virtual HRESULT DeliverEndOfStream(void);
+
+ // same for Begin/EndFlush - we handle Begin/EndFlush since it
+ // is an error on an output pin, and we have Deliver methods to
+ // call the methods on the connected pin
+ STDMETHODIMP BeginFlush(void);
+ STDMETHODIMP EndFlush(void);
+ virtual HRESULT DeliverBeginFlush(void);
+ virtual HRESULT DeliverEndFlush(void);
+
+ // deliver NewSegment to connected pin - you will need to
+ // override this if you queue any data in your output pin.
+ virtual HRESULT DeliverNewSegment(
+ REFERENCE_TIME tStart,
+ REFERENCE_TIME tStop,
+ double dRate);
+
+ //================================================================================
+ // IQualityControl methods
+ //================================================================================
+
+ // All inherited from CBasePin and not overridden here.
+ // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+ // STDMETHODIMP SetSink(IQualityControl * piqc);
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseInputPin
+//
+// derive your standard input pin from this.
+// you need to supply GetMediaType and CheckConnect etc (see CBasePin),
+// and you need to supply Receive to do something more useful.
+//
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseInputPin : public CBasePin,
+ public IMemInputPin
+{
+
+protected:
+
+ IMemAllocator *m_pAllocator; // Default memory allocator
+
+ // allocator is read-only, so received samples
+ // cannot be modified (probably only relevant to in-place
+ // transforms
+ BYTE m_bReadOnly;
+
+ // in flushing state (between BeginFlush and EndFlush)
+ // if TRUE, all Receives are returned with S_FALSE
+ BYTE m_bFlushing;
+
+ // Sample properties - initalized in Receive
+ AM_SAMPLE2_PROPERTIES m_SampleProps;
+
+public:
+
+ CBaseInputPin(
+ __in_opt LPCTSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+#ifdef UNICODE
+ CBaseInputPin(
+ __in_opt LPCSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+#endif
+ virtual ~CBaseInputPin();
+
+ DECLARE_IUNKNOWN
+
+ // override this to publicise our interfaces
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+ // return the allocator interface that this input pin
+ // would like the output pin to use
+ STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
+
+ // tell the input pin which allocator the output pin is actually
+ // going to use.
+ STDMETHODIMP NotifyAllocator(
+ IMemAllocator * pAllocator,
+ BOOL bReadOnly);
+
+ // do something with this media sample
+ STDMETHODIMP Receive(IMediaSample *pSample);
+
+ // do something with these media samples
+ STDMETHODIMP ReceiveMultiple (
+ __in_ecount(nSamples) IMediaSample **pSamples,
+ long nSamples,
+ __out long *nSamplesProcessed);
+
+ // See if Receive() blocks
+ STDMETHODIMP ReceiveCanBlock();
+
+ // Default handling for BeginFlush - call at the beginning
+ // of your implementation (makes sure that all Receive calls
+ // fail). After calling this, you need to free any queued data
+ // and then call downstream.
+ STDMETHODIMP BeginFlush(void);
+
+ // default handling for EndFlush - call at end of your implementation
+ // - before calling this, ensure that there is no queued data and no thread
+ // pushing any more without a further receive, then call downstream,
+ // then call this method to clear the m_bFlushing flag and re-enable
+ // receives
+ STDMETHODIMP EndFlush(void);
+
+ // this method is optional (can return E_NOTIMPL).
+ // default implementation returns E_NOTIMPL. Override if you have
+ // specific alignment or prefix needs, but could use an upstream
+ // allocator
+ STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
+
+ // Release the pin's allocator.
+ HRESULT BreakConnect();
+
+ // helper method to check the read-only flag
+ BOOL IsReadOnly() {
+ return m_bReadOnly;
+ };
+
+ // helper method to see if we are flushing
+ BOOL IsFlushing() {
+ return m_bFlushing;
+ };
+
+ // Override this for checking whether it's OK to process samples
+ // Also call this from EndOfStream.
+ virtual HRESULT CheckStreaming();
+
+ // Pass a Quality notification on to the appropriate sink
+ HRESULT PassNotify(Quality& q);
+
+
+ //================================================================================
+ // IQualityControl methods (from CBasePin)
+ //================================================================================
+
+ STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+
+ // no need to override:
+ // STDMETHODIMP SetSink(IQualityControl * piqc);
+
+
+ // switch the pin to inactive state - may already be inactive
+ virtual HRESULT Inactive(void);
+
+ // Return sample properties pointer
+ AM_SAMPLE2_PROPERTIES * SampleProps() {
+ ASSERT(m_SampleProps.cbData != 0);
+ return &m_SampleProps;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////
+// CDynamicOutputPin
+//
+
+class CDynamicOutputPin : public CBaseOutputPin,
+ public IPinFlowControl
+{
+public:
+#ifdef UNICODE
+ CDynamicOutputPin(
+ __in_opt LPCSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+#endif
+
+ CDynamicOutputPin(
+ __in_opt LPCTSTR pObjectName,
+ __in CBaseFilter *pFilter,
+ __in CCritSec *pLock,
+ __inout HRESULT *phr,
+ __in_opt LPCWSTR pName);
+
+ ~CDynamicOutputPin();
+
+ // IUnknown Methods
+ DECLARE_IUNKNOWN
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+ // IPin Methods
+ STDMETHODIMP Disconnect(void);
+
+ // IPinFlowControl Methods
+ STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
+
+ // Set graph config info
+ void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
+
+ #ifdef DEBUG
+ virtual HRESULT Deliver(IMediaSample *pSample);
+ virtual HRESULT DeliverEndOfStream(void);
+ virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+ #endif // DEBUG
+
+ HRESULT DeliverBeginFlush(void);
+ HRESULT DeliverEndFlush(void);
+
+ HRESULT Inactive(void);
+ HRESULT Active(void);
+ virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+ virtual HRESULT StartUsingOutputPin(void);
+ virtual void StopUsingOutputPin(void);
+ virtual bool StreamingThreadUsingOutputPin(void);
+
+ HRESULT ChangeOutputFormat
+ (
+ const AM_MEDIA_TYPE *pmt,
+ REFERENCE_TIME tSegmentStart,
+ REFERENCE_TIME tSegmentStop,
+ double dSegmentRate
+ );
+ HRESULT ChangeMediaType(const CMediaType *pmt);
+ HRESULT DynamicReconnect(const CMediaType *pmt);
+
+protected:
+ HRESULT SynchronousBlockOutputPin(void);
+ HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
+ HRESULT UnblockOutputPin(void);
+
+ void BlockOutputPin(void);
+ void ResetBlockState(void);
+
+ static HRESULT WaitEvent(HANDLE hEvent);
+
+ enum BLOCK_STATE
+ {
+ NOT_BLOCKED,
+ PENDING,
+ BLOCKED
+ };
+
+ // This lock should be held when the following class members are
+ // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
+ // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
+ CCritSec m_BlockStateLock;
+
+ // This event should be signaled when the output pin is
+ // not blocked. This is a manual reset event. For more
+ // information on events, see the documentation for
+ // CreateEvent() in the Windows SDK.
+ HANDLE m_hUnblockOutputPinEvent;
+
+ // This event will be signaled when block operation succeedes or
+ // when the user cancels the block operation. The block operation
+ // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
+ // while the block operation is pending.
+ HANDLE m_hNotifyCallerPinBlockedEvent;
+
+ // The state of the current block operation.
+ BLOCK_STATE m_BlockState;
+
+ // The ID of the thread which last called IPinFlowControl::Block().
+ // For more information on thread IDs, see the documentation for
+ // GetCurrentThreadID() in the Windows SDK.
+ DWORD m_dwBlockCallerThreadID;
+
+ // The number of times StartUsingOutputPin() has been sucessfully
+ // called and a corresponding call to StopUsingOutputPin() has not
+ // been made. When this variable is greater than 0, the streaming
+ // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
+ // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple(). The
+ // streaming thread could also be calling: DynamicReconnect(),
+ // ChangeMediaType() or ChangeOutputFormat(). The output pin cannot
+ // be blocked while the output pin is being used.
+ DWORD m_dwNumOutstandingOutputPinUsers;
+
+ // This event should be set when the IMediaFilter::Stop() is called.
+ // This is a manual reset event. It is also set when the output pin
+ // delivers a flush to the connected input pin.
+ HANDLE m_hStopEvent;
+ IGraphConfig* m_pGraphConfig;
+
+ // TRUE if the output pin's allocator's samples are read only.
+ // Otherwise FALSE. For more information, see the documentation
+ // for IMemInputPin::NotifyAllocator().
+ BOOL m_bPinUsesReadOnlyAllocator;
+
+private:
+ HRESULT Initialize(void);
+ HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
+
+ #ifdef DEBUG
+ void AssertValid(void);
+ #endif // DEBUG
+};
+
+class CAutoUsingOutputPin
+{
+public:
+ CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr );
+ ~CAutoUsingOutputPin();
+
+private:
+ CDynamicOutputPin* m_pOutputPin;
+};
+
+inline CAutoUsingOutputPin::CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr ) :
+ m_pOutputPin(NULL)
+{
+ // The caller should always pass in valid pointers.
+ ASSERT( NULL != pOutputPin );
+ ASSERT( NULL != phr );
+
+ // Make sure the user initialized phr.
+ ASSERT( S_OK == *phr );
+
+ HRESULT hr = pOutputPin->StartUsingOutputPin();
+ if( FAILED( hr ) )
+ {
+ *phr = hr;
+ return;
+ }
+
+ m_pOutputPin = pOutputPin;
+}
+
+inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
+{
+ if( NULL != m_pOutputPin )
+ {
+ m_pOutputPin->StopUsingOutputPin();
+ }
+}
+
+#ifdef DEBUG
+
+inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
+{
+ // The caller should call StartUsingOutputPin() before calling this
+ // method.
+ ASSERT(StreamingThreadUsingOutputPin());
+
+ return CBaseOutputPin::Deliver(pSample);
+}
+
+inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
+{
+ // The caller should call StartUsingOutputPin() before calling this
+ // method.
+ ASSERT( StreamingThreadUsingOutputPin() );
+
+ return CBaseOutputPin::DeliverEndOfStream();
+}
+
+inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+ // The caller should call StartUsingOutputPin() before calling this
+ // method.
+ ASSERT(StreamingThreadUsingOutputPin());
+
+ return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
+}
+
+#endif // DEBUG
+
+//=====================================================================
+//=====================================================================
+// Memory allocators
+//
+// the shared memory transport between pins requires the input pin
+// to provide a memory allocator that can provide sample objects. A
+// sample object supports the IMediaSample interface.
+//
+// CBaseAllocator handles the management of free and busy samples. It
+// allocates CMediaSample objects. CBaseAllocator is an abstract class:
+// in particular it has no method of initializing the list of free
+// samples. CMemAllocator is derived from CBaseAllocator and initializes
+// the list of samples using memory from the standard IMalloc interface.
+//
+// If you want your buffers to live in some special area of memory,
+// derive your allocator object from CBaseAllocator. If you derive your
+// IMemInputPin interface object from CBaseMemInputPin, you will get
+// CMemAllocator-based allocation etc for free and will just need to
+// supply the Receive handling, and media type / format negotiation.
+//=====================================================================
+//=====================================================================
+
+
+//=====================================================================
+//=====================================================================
+// Defines CMediaSample
+//
+// an object of this class supports IMediaSample and represents a buffer
+// for media data with some associated properties. Releasing it returns
+// it to a freelist managed by a CBaseAllocator derived object.
+//=====================================================================
+//=====================================================================
+
+class CMediaSample : public IMediaSample2 // The interface we support
+{
+
+protected:
+
+ friend class CBaseAllocator;
+
+ /* Values for dwFlags - these are used for backward compatiblity
+ only now - use AM_SAMPLE_xxx
+ */
+ enum { Sample_SyncPoint = 0x01, /* Is this a sync point */
+ Sample_Preroll = 0x02, /* Is this a preroll sample */
+ Sample_Discontinuity = 0x04, /* Set if start of new segment */
+ Sample_TypeChanged = 0x08, /* Has the type changed */
+ Sample_TimeValid = 0x10, /* Set if time is valid */
+ Sample_MediaTimeValid = 0x20, /* Is the media time valid */
+ Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
+ Sample_StopValid = 0x100, /* Stop time valid */
+ Sample_ValidFlags = 0x1FF
+ };
+
+ /* Properties, the media sample class can be a container for a format
+ change in which case we take a copy of a type through the SetMediaType
+ interface function and then return it when GetMediaType is called. As
+ we do no internal processing on it we leave it as a pointer */
+
+ DWORD m_dwFlags; /* Flags for this sample */
+ /* Type specific flags are packed
+ into the top word
+ */
+ DWORD m_dwTypeSpecificFlags; /* Media type specific flags */
+ __field_ecount_opt(m_cbBuffer) LPBYTE m_pBuffer; /* Pointer to the complete buffer */
+ LONG m_lActual; /* Length of data in this sample */
+ LONG m_cbBuffer; /* Size of the buffer */
+ CBaseAllocator *m_pAllocator; /* The allocator who owns us */
+ CMediaSample *m_pNext; /* Chaining in free list */
+ REFERENCE_TIME m_Start; /* Start sample time */
+ REFERENCE_TIME m_End; /* End sample time */
+ LONGLONG m_MediaStart; /* Real media start position */
+ LONG m_MediaEnd; /* A difference to get the end */
+ AM_MEDIA_TYPE *m_pMediaType; /* Media type change data */
+ DWORD m_dwStreamId; /* Stream id */
+public:
+ LONG m_cRef; /* Reference count */
+
+
+public:
+
+ CMediaSample(
+ __in_opt LPCTSTR pName,
+ __in_opt CBaseAllocator *pAllocator,
+ __inout_opt HRESULT *phr,
+ __in_bcount_opt(length) LPBYTE pBuffer = NULL,
+ LONG length = 0);
+#ifdef UNICODE
+ CMediaSample(
+ __in_opt LPCSTR pName,
+ __in_opt CBaseAllocator *pAllocator,
+ __inout_opt HRESULT *phr,
+ __in_bcount_opt(length) LPBYTE pBuffer = NULL,
+ LONG length = 0);
+#endif
+
+ virtual ~CMediaSample();
+
+ /* Note the media sample does not delegate to its owner */
+
+ STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // set the buffer pointer and length. Used by allocators that
+ // want variable sized pointers or pointers into already-read data.
+ // This is only available through a CMediaSample* not an IMediaSample*
+ // and so cannot be changed by clients.
+ HRESULT SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes);
+
+ // Get me a read/write pointer to this buffer's memory.
+ STDMETHODIMP GetPointer(__deref_out BYTE ** ppBuffer);
+
+ STDMETHODIMP_(LONG) GetSize(void);
+
+ // get the stream time at which this sample should start and finish.
+ STDMETHODIMP GetTime(
+ __out REFERENCE_TIME * pTimeStart, // put time here
+ __out REFERENCE_TIME * pTimeEnd
+ );
+
+ // Set the stream time at which this sample should start and finish.
+ STDMETHODIMP SetTime(
+ __in_opt REFERENCE_TIME * pTimeStart, // put time here
+ __in_opt REFERENCE_TIME * pTimeEnd
+ );
+ STDMETHODIMP IsSyncPoint(void);
+ STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
+ STDMETHODIMP IsPreroll(void);
+ STDMETHODIMP SetPreroll(BOOL bIsPreroll);
+
+ STDMETHODIMP_(LONG) GetActualDataLength(void);
+ STDMETHODIMP SetActualDataLength(LONG lActual);
+
+ // these allow for limited format changes in band
+
+ STDMETHODIMP GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType);
+ STDMETHODIMP SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType);
+
+ // returns S_OK if there is a discontinuity in the data (this same is
+ // not a continuation of the previous stream of data
+ // - there has been a seek).
+ STDMETHODIMP IsDiscontinuity(void);
+ // set the discontinuity property - TRUE if this sample is not a
+ // continuation, but a new sample after a seek.
+ STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
+
+ // get the media times for this sample
+ STDMETHODIMP GetMediaTime(
+ __out LONGLONG * pTimeStart,
+ __out LONGLONG * pTimeEnd
+ );
+
+ // Set the media times for this sample
+ STDMETHODIMP SetMediaTime(
+ __in_opt LONGLONG * pTimeStart,
+ __in_opt LONGLONG * pTimeEnd
+ );
+
+ // Set and get properties (IMediaSample2)
+ STDMETHODIMP GetProperties(
+ DWORD cbProperties,
+ __out_bcount(cbProperties) BYTE * pbProperties
+ );
+
+ STDMETHODIMP SetProperties(
+ DWORD cbProperties,
+ __in_bcount(cbProperties) const BYTE * pbProperties
+ );
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseAllocator
+//
+// Abstract base class that manages a list of media samples
+//
+// This class provides support for getting buffers from the free list,
+// including handling of commit and (asynchronous) decommit.
+//
+// Derive from this class and override the Alloc and Free functions to
+// allocate your CMediaSample (or derived) objects and add them to the
+// free list, preparing them as necessary.
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
+ public IMemAllocatorCallbackTemp, // The interface we support
+ public CCritSec // Provides object locking
+{
+ class CSampleList;
+ friend class CSampleList;
+
+ /* Trick to get at protected member in CMediaSample */
+ static CMediaSample * &NextSample(__in CMediaSample *pSample)
+ {
+ return pSample->m_pNext;
+ };
+
+ /* Mini list class for the free list */
+ class CSampleList
+ {
+ public:
+ CSampleList() : m_List(NULL), m_nOnList(0) {};
+#ifdef DEBUG
+ ~CSampleList()
+ {
+ ASSERT(m_nOnList == 0);
+ };
+#endif
+ CMediaSample *Head() const { return m_List; };
+ CMediaSample *Next(__in CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
+ int GetCount() const { return m_nOnList; };
+ void Add(__inout CMediaSample *pSample)
+ {
+ ASSERT(pSample != NULL);
+ CBaseAllocator::NextSample(pSample) = m_List;
+ m_List = pSample;
+ m_nOnList++;
+ };
+ CMediaSample *RemoveHead()
+ {
+ CMediaSample *pSample = m_List;
+ if (pSample != NULL) {
+ m_List = CBaseAllocator::NextSample(m_List);
+ m_nOnList--;
+ }
+ return pSample;
+ };
+ void Remove(__inout CMediaSample *pSample);
+
+ public:
+ CMediaSample *m_List;
+ int m_nOnList;
+ };
+protected:
+
+ CSampleList m_lFree; // Free list
+
+ /* Note to overriders of CBaseAllocator.
+
+ We use a lazy signalling mechanism for waiting for samples.
+ This means we don't call the OS if no waits occur.
+
+ In order to implement this:
+
+ 1. When a new sample is added to m_lFree call NotifySample() which
+ calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
+ sets m_lWaiting to 0.
+ This must all be done holding the allocator's critical section.
+
+ 2. When waiting for a sample call SetWaiting() which increments
+ m_lWaiting BEFORE leaving the allocator's critical section.
+
+ 3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
+ having left the allocator's critical section. The effect of
+ this is to remove 1 from the semaphore's count. You MUST call
+ this once having incremented m_lWaiting.
+
+ The following are then true when the critical section is not held :
+ (let nWaiting = number about to wait or waiting)
+
+ (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
+ (2) m_lWaiting + Semaphore count == nWaiting
+
+ We would deadlock if
+ nWaiting != 0 &&
+ m_lFree.GetCount() != 0 &&
+ Semaphore count == 0
+
+ But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
+ from (2) Semaphore count == nWaiting (which is non-0) so the
+ deadlock can't happen.
+ */
+
+ HANDLE m_hSem; // For signalling
+ long m_lWaiting; // Waiting for a free element
+ long m_lCount; // how many buffers we have agreed to provide
+ long m_lAllocated; // how many buffers are currently allocated
+ long m_lSize; // agreed size of each buffer
+ long m_lAlignment; // agreed alignment
+ long m_lPrefix; // agreed prefix (preceeds GetPointer() value)
+ BOOL m_bChanged; // Have the buffer requirements changed
+
+ // if true, we are decommitted and can't allocate memory
+ BOOL m_bCommitted;
+ // if true, the decommit has happened, but we haven't called Free yet
+ // as there are still outstanding buffers
+ BOOL m_bDecommitInProgress;
+
+ // Notification interface
+ IMemAllocatorNotifyCallbackTemp *m_pNotify;
+
+ BOOL m_fEnableReleaseCallback;
+
+ // called to decommit the memory when the last buffer is freed
+ // pure virtual - need to override this
+ virtual void Free(void) PURE;
+
+ // override to allocate the memory when commit called
+ virtual HRESULT Alloc(void);
+
+public:
+
+ CBaseAllocator(
+ __in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
+ BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
+#ifdef UNICODE
+ CBaseAllocator(
+ __in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
+ BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
+#endif
+ virtual ~CBaseAllocator();
+
+ DECLARE_IUNKNOWN
+
+ // override this to publicise our interfaces
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+ STDMETHODIMP SetProperties(
+ __in ALLOCATOR_PROPERTIES* pRequest,
+ __out ALLOCATOR_PROPERTIES* pActual);
+
+ // return the properties actually being used on this allocator
+ STDMETHODIMP GetProperties(
+ __out ALLOCATOR_PROPERTIES* pProps);
+
+ // override Commit to allocate memory. We handle the GetBuffer
+ //state changes
+ STDMETHODIMP Commit();
+
+ // override this to handle the memory freeing. We handle any outstanding
+ // GetBuffer calls
+ STDMETHODIMP Decommit();
+
+ // get container for a sample. Blocking, synchronous call to get the
+ // next free buffer (as represented by an IMediaSample interface).
+ // on return, the time etc properties will be invalid, but the buffer
+ // pointer and size will be correct. The two time parameters are
+ // optional and either may be NULL, they may alternatively be set to
+ // the start and end times the sample will have attached to it
+ // bPrevFramesSkipped is not used (used only by the video renderer's
+ // allocator where it affects quality management in direct draw).
+
+ STDMETHODIMP GetBuffer(__deref_out IMediaSample **ppBuffer,
+ __in_opt REFERENCE_TIME * pStartTime,
+ __in_opt REFERENCE_TIME * pEndTime,
+ DWORD dwFlags);
+
+ // final release of a CMediaSample will call this
+ STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
+ // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
+
+ STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
+
+ STDMETHODIMP GetFreeCount(__out LONG *plBuffersFree);
+
+ // Notify that a sample is available
+ void NotifySample();
+
+ // Notify that we're waiting for a sample
+ void SetWaiting() { m_lWaiting++; };
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CMemAllocator
+//
+// this is an allocator based on CBaseAllocator that allocates sample
+// buffers in main memory (from 'new'). You must call SetProperties
+// before calling Commit.
+//
+// we don't free the memory when going into Decommit state. The simplest
+// way to implement this without complicating CBaseAllocator is to
+// have a Free() function, called to go into decommit state, that does
+// nothing and a ReallyFree function called from our destructor that
+// actually frees the memory.
+//=====================================================================
+//=====================================================================
+
+// Make me one from quartz.dll
+STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator);
+
+class CMemAllocator : public CBaseAllocator
+{
+
+protected:
+
+ LPBYTE m_pBuffer; // combined memory for all buffers
+
+ // override to free the memory when decommit completes
+ // - we actually do nothing, and save the memory until deletion.
+ void Free(void);
+
+ // called from the destructor (and from Alloc if changing size/count) to
+ // actually free up the memory
+ void ReallyFree(void);
+
+ // overriden to allocate the memory when commit called
+ HRESULT Alloc(void);
+
+public:
+ /* This goes in the factory template table to create new instances */
+ static CUnknown *CreateInstance(__inout_opt LPUNKNOWN, __inout HRESULT *);
+
+ STDMETHODIMP SetProperties(
+ __in ALLOCATOR_PROPERTIES* pRequest,
+ __out ALLOCATOR_PROPERTIES* pActual);
+
+ CMemAllocator(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
+#ifdef UNICODE
+ CMemAllocator(__in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
+#endif
+ ~CMemAllocator();
+};
+
+// helper used by IAMovieSetup implementation
+STDAPI
+AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
+ , IFilterMapper * pIFM
+ , BOOL bRegister );
+
+
+///////////////////////////////////////////////////////////////////////////
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+///////////////////////////////////////////////////////////////////////////
+
+#endif /* __FILTER__ */
+
+
+
OpenPOWER on IntegriCloud