* #27232: jni: added pjproject checkout as regular git content

We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/.svn/pristine/9f/9fa7bda04dbe84b039b932b9f08a2b7b32671218.svn-base b/jni/pjproject-android/.svn/pristine/9f/9fa7bda04dbe84b039b932b9f08a2b7b32671218.svn-base
new file mode 100644
index 0000000..14f17cd
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/9f/9fa7bda04dbe84b039b932b9f08a2b7b32671218.svn-base
@@ -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__ */

+

+

+