amfilter.h
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:56k
源码类别:

P2P编程

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // File: AMFilter.h
  3. //
  4. // Desc: DirectShow base classes - efines class hierarchy for streams
  5. //       architecture.
  6. //
  7. // Copyright (c) Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9. #ifndef __FILTER__
  10. #define __FILTER__
  11. /* The following classes are declared in this header: */
  12. class CBaseMediaFilter;     // IMediaFilter support
  13. class CBaseFilter;          // IBaseFilter,IMediaFilter support
  14. class CBasePin;             // Abstract base class for IPin interface
  15. class CEnumPins;            // Enumerate input and output pins
  16. class CEnumMediaTypes;      // Enumerate the pin's preferred formats
  17. class CBaseOutputPin;       // Adds data provider member functions
  18. class CBaseInputPin;        // Implements IMemInputPin interface
  19. class CMediaSample;         // Basic transport unit for IMemInputPin
  20. class CBaseAllocator;       // General list guff for most allocators
  21. class CMemAllocator;        // Implements memory buffer allocation
  22. //=====================================================================
  23. //=====================================================================
  24. //
  25. // QueryFilterInfo and QueryPinInfo AddRef the interface pointers
  26. // they return.  You can use the macro below to release the interface.
  27. //
  28. //=====================================================================
  29. //=====================================================================
  30. #define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
  31. #define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
  32. //=====================================================================
  33. //=====================================================================
  34. // Defines CBaseMediaFilter
  35. //
  36. // Abstract base class implementing IMediaFilter.
  37. //
  38. // Typically you will derive your filter from CBaseFilter rather than
  39. // this,  unless you are implementing an object such as a plug-in
  40. // distributor that needs to support IMediaFilter but not IBaseFilter.
  41. //
  42. // Note that IMediaFilter is derived from IPersist to allow query of
  43. // class id.
  44. //=====================================================================
  45. //=====================================================================
  46. class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
  47.                                      public IMediaFilter
  48. {
  49. protected:
  50.     FILTER_STATE    m_State;            // current state: running, paused
  51.     IReferenceClock *m_pClock;          // this filter's reference clock
  52.     // note: all filters in a filter graph use the same clock
  53.     // offset from stream time to reference time
  54.     CRefTime        m_tStart;
  55.     CLSID     m_clsid;            // This filters clsid
  56.                                         // used for serialization
  57.     CCritSec        *m_pLock;           // Object we use for locking
  58. public:
  59.     CBaseMediaFilter(
  60.         const TCHAR     *pName,
  61.         LPUNKNOWN pUnk,
  62.         CCritSec  *pLock,
  63. REFCLSID   clsid);
  64.     virtual ~CBaseMediaFilter();
  65.     DECLARE_IUNKNOWN
  66.     // override this to say what interfaces we support where
  67.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  68.     //
  69.     // --- IPersist method ---
  70.     //
  71.     STDMETHODIMP GetClassID(CLSID *pClsID);
  72.     // --- IMediaFilter methods ---
  73.     STDMETHODIMP GetState(DWORD dwMSecs, FILTER_STATE *State);
  74.     STDMETHODIMP SetSyncSource(IReferenceClock *pClock);
  75.     STDMETHODIMP GetSyncSource(IReferenceClock **pClock);
  76.     // default implementation of Stop and Pause just record the
  77.     // state. Override to activate or de-activate your filter.
  78.     // Note that Run when called from Stopped state will call Pause
  79.     // to ensure activation, so if you are a source or transform
  80.     // you will probably not need to override Run.
  81.     STDMETHODIMP Stop();
  82.     STDMETHODIMP Pause();
  83.     // the start parameter is the difference to be added to the
  84.     // sample's stream time to get the reference time for
  85.     // its presentation
  86.     STDMETHODIMP Run(REFERENCE_TIME tStart);
  87.     // --- helper methods ---
  88.     // return the current stream time - ie find out what
  89.     // stream time should be appearing now
  90.     virtual HRESULT StreamTime(CRefTime& rtStream);
  91.     // Is the filter currently active? (running or paused)
  92.     BOOL IsActive() {
  93.         CAutoLock cObjectLock(m_pLock);
  94.         return ((m_State == State_Paused) || (m_State == State_Running));
  95.     };
  96. };
  97. //=====================================================================
  98. //=====================================================================
  99. // Defines CBaseFilter
  100. //
  101. // An abstract class providing basic IBaseFilter support for pin
  102. // enumeration and filter information reading.
  103. //
  104. // We cannot derive from CBaseMediaFilter since methods in IMediaFilter
  105. // are also in IBaseFilter and would be ambiguous. Since much of the code
  106. // assumes that they derive from a class that has m_State and other state
  107. // directly available, we duplicate code from CBaseMediaFilter rather than
  108. // having a member variable.
  109. //
  110. // Derive your filter from this, or from a derived object such as
  111. // CTransformFilter.
  112. //=====================================================================
  113. //=====================================================================
  114. class AM_NOVTABLE CBaseFilter : public CUnknown,        // Handles an IUnknown
  115.                     public IBaseFilter,     // The Filter Interface
  116.                     public IAMovieSetup     // For un/registration
  117. {
  118. friend class CBasePin;
  119. protected:
  120.     FILTER_STATE    m_State;            // current state: running, paused
  121.     IReferenceClock *m_pClock;          // this graph's ref clock
  122.     CRefTime        m_tStart;           // offset from stream time to reference time
  123.     CLSID     m_clsid;            // This filters clsid
  124.                                         // used for serialization
  125.     CCritSec        *m_pLock;           // Object we use for locking
  126.     WCHAR           *m_pName;           // Full filter name
  127.     IFilterGraph    *m_pGraph;          // Graph we belong to
  128.     IMediaEventSink *m_pSink;           // Called with notify events
  129.     LONG            m_PinVersion;       // Current pin version
  130. public:
  131.     CBaseFilter(
  132.         const TCHAR *pName,     // Object description
  133.         LPUNKNOWN pUnk,         // IUnknown of delegating object
  134.         CCritSec  *pLock,       // Object who maintains lock
  135. REFCLSID   clsid);      // The clsid to be used to serialize this filter
  136.     CBaseFilter(
  137.         TCHAR     *pName,       // Object description
  138.         LPUNKNOWN pUnk,         // IUnknown of delegating object
  139.         CCritSec  *pLock,       // Object who maintains lock
  140. REFCLSID   clsid,       // The clsid to be used to serialize this filter
  141.         HRESULT   *phr);        // General OLE return code
  142. #ifdef UNICODE
  143.     CBaseFilter(
  144.         const CHAR *pName,     // Object description
  145.         LPUNKNOWN pUnk,         // IUnknown of delegating object
  146.         CCritSec  *pLock,       // Object who maintains lock
  147. REFCLSID   clsid);      // The clsid to be used to serialize this filter
  148.     CBaseFilter(
  149.         CHAR     *pName,       // Object description
  150.         LPUNKNOWN pUnk,         // IUnknown of delegating object
  151.         CCritSec  *pLock,       // Object who maintains lock
  152. REFCLSID   clsid,       // The clsid to be used to serialize this filter
  153.         HRESULT   *phr);        // General OLE return code
  154. #endif
  155.     ~CBaseFilter();
  156.     DECLARE_IUNKNOWN
  157.     // override this to say what interfaces we support where
  158.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  159. #ifdef DEBUG
  160.     STDMETHODIMP_(ULONG) NonDelegatingRelease();
  161. #endif
  162.     //
  163.     // --- IPersist method ---
  164.     //
  165.     STDMETHODIMP GetClassID(CLSID *pClsID);
  166.     // --- IMediaFilter methods ---
  167.     STDMETHODIMP GetState(DWORD dwMSecs, FILTER_STATE *State);
  168.     STDMETHODIMP SetSyncSource(IReferenceClock *pClock);
  169.     STDMETHODIMP GetSyncSource(IReferenceClock **pClock);
  170.     // override Stop and Pause so we can activate the pins.
  171.     // Note that Run will call Pause first if activation needed.
  172.     // Override these if you want to activate your filter rather than
  173.     // your pins.
  174.     STDMETHODIMP Stop();
  175.     STDMETHODIMP Pause();
  176.     // the start parameter is the difference to be added to the
  177.     // sample's stream time to get the reference time for
  178.     // its presentation
  179.     STDMETHODIMP Run(REFERENCE_TIME tStart);
  180.     // --- helper methods ---
  181.     // return the current stream time - ie find out what
  182.     // stream time should be appearing now
  183.     virtual HRESULT StreamTime(CRefTime& rtStream);
  184.     // Is the filter currently active?
  185.     BOOL IsActive() {
  186.         CAutoLock cObjectLock(m_pLock);
  187.         return ((m_State == State_Paused) || (m_State == State_Running));
  188.     };
  189.     // Is this filter stopped (without locking)
  190.     BOOL IsStopped() {
  191.         return (m_State == State_Stopped);
  192.     };
  193.     //
  194.     // --- IBaseFilter methods ---
  195.     //
  196.     // pin enumerator
  197.     STDMETHODIMP EnumPins(
  198.                     IEnumPins ** ppEnum);
  199.     // default behaviour of FindPin assumes pin ids are their names
  200.     STDMETHODIMP FindPin(
  201.         LPCWSTR Id,
  202.         IPin ** ppPin
  203.     );
  204.     STDMETHODIMP QueryFilterInfo(
  205.                     FILTER_INFO * pInfo);
  206.     STDMETHODIMP JoinFilterGraph(
  207.                     IFilterGraph * pGraph,
  208.                     LPCWSTR pName);
  209.     // return a Vendor information string. Optional - may return E_NOTIMPL.
  210.     // memory returned should be freed using CoTaskMemFree
  211.     // default implementation returns E_NOTIMPL
  212.     STDMETHODIMP QueryVendorInfo(
  213.                     LPWSTR* pVendorInfo
  214.             );
  215.     // --- helper methods ---
  216.     // send an event notification to the filter graph if we know about it.
  217.     // returns S_OK if delivered, S_FALSE if the filter graph does not sink
  218.     // events, or an error otherwise.
  219.     HRESULT NotifyEvent(
  220.         long EventCode,
  221.         LONG_PTR EventParam1,
  222.         LONG_PTR EventParam2);
  223.     // return the filter graph we belong to
  224.     IFilterGraph *GetFilterGraph() {
  225.         return m_pGraph;
  226.     }
  227.     // Request reconnect
  228.     // pPin is the pin to reconnect
  229.     // pmt is the type to reconnect with - can be NULL
  230.     // Calls ReconnectEx on the filter graph
  231.     HRESULT ReconnectPin(IPin *pPin, AM_MEDIA_TYPE const *pmt);
  232.     // find out the current pin version (used by enumerators)
  233.     virtual LONG GetPinVersion();
  234.     void IncrementPinVersion();
  235.     // you need to supply these to access the pins from the enumerator
  236.     // and for default Stop and Pause/Run activation.
  237.     virtual int GetPinCount() PURE;
  238.     virtual CBasePin *GetPin(int n) PURE;
  239.     // --- IAMovieSetup methods ---
  240.     STDMETHODIMP Register();    // ask filter to register itself
  241.     STDMETHODIMP Unregister();  // and unregister itself
  242.     // --- setup helper methods ---
  243.     // (override to return filters setup data)
  244.     virtual LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
  245. };
  246. //=====================================================================
  247. //=====================================================================
  248. // Defines CBasePin
  249. //
  250. // Abstract class that supports the basics of IPin
  251. //=====================================================================
  252. //=====================================================================
  253. class  AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
  254. {
  255. protected:
  256.     WCHAR *         m_pName;         // This pin's name
  257.     IPin            *m_Connected;               // Pin we have connected to
  258.     PIN_DIRECTION   m_dir;                      // Direction of this pin
  259.     CCritSec        *m_pLock;                   // Object we use for locking
  260.     bool            m_bRunTimeError;            // Run time error generated
  261.     bool            m_bCanReconnectWhenActive;  // OK to reconnect when active
  262.     bool            m_bTryMyTypesFirst;         // When connecting enumerate
  263.                                                 // this pin's types first
  264.     CBaseFilter    *m_pFilter;                  // Filter we were created by
  265.     IQualityControl *m_pQSink;                  // Target for Quality messages
  266.     LONG            m_TypeVersion;              // Holds current type version
  267.     CMediaType      m_mt;                       // Media type of connection
  268.     CRefTime        m_tStart;                   // time from NewSegment call
  269.     CRefTime        m_tStop;                    // time from NewSegment
  270.     double          m_dRate;                    // rate from NewSegment
  271. #ifdef DEBUG
  272.     LONG            m_cRef;                     // Ref count tracing
  273. #endif
  274.     // displays pin connection information
  275. #ifdef DEBUG
  276.     void DisplayPinInfo(IPin *pReceivePin);
  277.     void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
  278. #else
  279.     void DisplayPinInfo(IPin *pReceivePin) {};
  280.     void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
  281. #endif
  282.     // used to agree a media type for a pin connection
  283.     // given a specific media type, attempt a connection (includes
  284.     // checking that the type is acceptable to this pin)
  285.     HRESULT
  286.     AttemptConnection(
  287.         IPin* pReceivePin,      // connect to this pin
  288.         const CMediaType* pmt   // using this type
  289.     );
  290.     // try all the media types in this enumerator - for each that
  291.     // we accept, try to connect using ReceiveConnection.
  292.     HRESULT TryMediaTypes(
  293.                         IPin *pReceivePin,      // connect to this pin
  294.                         const CMediaType *pmt,        // proposed type from Connect
  295.                         IEnumMediaTypes *pEnum);    // try this enumerator
  296.     // establish a connection with a suitable mediatype. Needs to
  297.     // propose a media type if the pmt pointer is null or partially
  298.     // specified - use TryMediaTypes on both our and then the other pin's
  299.     // enumerator until we find one that works.
  300.     HRESULT AgreeMediaType(
  301.                         IPin *pReceivePin,      // connect to this pin
  302.                         const CMediaType *pmt);       // proposed type from Connect
  303. public:
  304.     CBasePin(
  305.         TCHAR *pObjectName,         // Object description
  306.         CBaseFilter *pFilter,       // Owning filter who knows about pins
  307.         CCritSec *pLock,            // Object who implements the lock
  308.         HRESULT *phr,               // General OLE return code
  309.         LPCWSTR pName,              // Pin name for us
  310.         PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
  311. #ifdef UNICODE
  312.     CBasePin(
  313.         CHAR *pObjectName,         // Object description
  314.         CBaseFilter *pFilter,       // Owning filter who knows about pins
  315.         CCritSec *pLock,            // Object who implements the lock
  316.         HRESULT *phr,               // General OLE return code
  317.         LPCWSTR pName,              // Pin name for us
  318.         PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
  319. #endif
  320.     virtual ~CBasePin();
  321.     DECLARE_IUNKNOWN
  322.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  323.     STDMETHODIMP_(ULONG) NonDelegatingRelease();
  324.     STDMETHODIMP_(ULONG) NonDelegatingAddRef();
  325.     // --- IPin methods ---
  326.     // take lead role in establishing a connection. Media type pointer
  327.     // may be null, or may point to partially-specified mediatype
  328.     // (subtype or format type may be GUID_NULL).
  329.     STDMETHODIMP Connect(
  330.         IPin * pReceivePin,
  331.         const AM_MEDIA_TYPE *pmt   // optional media type
  332.     );
  333.     // (passive) accept a connection from another pin
  334.     STDMETHODIMP ReceiveConnection(
  335.         IPin * pConnector,      // this is the initiating connecting pin
  336.         const AM_MEDIA_TYPE *pmt   // this is the media type we will exchange
  337.     );
  338.     STDMETHODIMP Disconnect();
  339.     STDMETHODIMP ConnectedTo(IPin **pPin);
  340.     STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt);
  341.     STDMETHODIMP QueryPinInfo(
  342.         PIN_INFO * pInfo
  343.     );
  344.     STDMETHODIMP QueryDirection(
  345.      PIN_DIRECTION * pPinDir
  346.     );
  347.     STDMETHODIMP QueryId(
  348.         LPWSTR * Id
  349.     );
  350.     // does the pin support this media type
  351.     STDMETHODIMP QueryAccept(
  352.         const AM_MEDIA_TYPE *pmt
  353.     );
  354.     // return an enumerator for this pins preferred media types
  355.     STDMETHODIMP EnumMediaTypes(
  356.         IEnumMediaTypes **ppEnum
  357.     );
  358.     // return an array of IPin* - the pins that this pin internally connects to
  359.     // All pins put in the array must be AddReffed (but no others)
  360.     // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
  361.     // Default: return E_NOTIMPL
  362.     // The filter graph will interpret NOT_IMPL as any input pin connects to
  363.     // all visible output pins and vice versa.
  364.     // apPin can be NULL if nPin==0 (not otherwise).
  365.     STDMETHODIMP QueryInternalConnections(
  366.         IPin* *apPin,     // array of IPin*
  367.         ULONG *nPin       // on input, the number of slots
  368.                           // on output  the number of pins
  369.     ) { return E_NOTIMPL; }
  370.     // Called when no more data will be sent
  371.     STDMETHODIMP EndOfStream(void);
  372.     // Begin/EndFlush still PURE
  373.     // NewSegment notifies of the start/stop/rate applying to the data
  374.     // about to be received. Default implementation records data and
  375.     // returns S_OK.
  376.     // Override this to pass downstream.
  377.     STDMETHODIMP NewSegment(
  378.                     REFERENCE_TIME tStart,
  379.                     REFERENCE_TIME tStop,
  380.                     double dRate);
  381.     //================================================================================
  382.     // IQualityControl methods
  383.     //================================================================================
  384.     STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
  385.     STDMETHODIMP SetSink(IQualityControl * piqc);
  386.     // --- helper methods ---
  387.     // Returns true if the pin is connected. false otherwise.
  388.     BOOL IsConnected(void) {return (m_Connected != NULL); };
  389.     // Return the pin this is connected to (if any)
  390.     IPin * GetConnected() { return m_Connected; };
  391.     // Check if our filter is currently stopped
  392.     BOOL IsStopped() {
  393.         return (m_pFilter->m_State == State_Stopped);
  394.     };
  395.     // find out the current type version (used by enumerators)
  396.     virtual LONG GetMediaTypeVersion();
  397.     void IncrementTypeVersion();
  398.     // switch the pin to active (paused or running) mode
  399.     // not an error to call this if already active
  400.     virtual HRESULT Active(void);
  401.     // switch the pin to inactive state - may already be inactive
  402.     virtual HRESULT Inactive(void);
  403.     // Notify of Run() from filter
  404.     virtual HRESULT Run(REFERENCE_TIME tStart);
  405.     // check if the pin can support this specific proposed type and format
  406.     virtual HRESULT CheckMediaType(const CMediaType *) PURE;
  407.     // set the connection to use this format (previously agreed)
  408.     virtual HRESULT SetMediaType(const CMediaType *);
  409.     // check that the connection is ok before verifying it
  410.     // can be overridden eg to check what interfaces will be supported.
  411.     virtual HRESULT CheckConnect(IPin *);
  412.     // Set and release resources required for a connection
  413.     virtual HRESULT BreakConnect();
  414.     virtual HRESULT CompleteConnect(IPin *pReceivePin);
  415.     // returns the preferred formats for a pin
  416.     virtual HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);
  417.     // access to NewSegment values
  418.     REFERENCE_TIME CurrentStopTime() {
  419.         return m_tStop;
  420.     }
  421.     REFERENCE_TIME CurrentStartTime() {
  422.         return m_tStart;
  423.     }
  424.     double CurrentRate() {
  425.         return m_dRate;
  426.     }
  427.     //  Access name
  428.     LPWSTR Name() { return m_pName; };
  429.     //  Can reconnectwhen active?
  430.     void SetReconnectWhenActive(bool bCanReconnect)
  431.     {
  432.         m_bCanReconnectWhenActive = bCanReconnect;
  433.     }
  434.     bool CanReconnectWhenActive()
  435.     {
  436.         return m_bCanReconnectWhenActive;
  437.     }
  438. protected:
  439.     STDMETHODIMP DisconnectInternal();
  440. };
  441. //=====================================================================
  442. //=====================================================================
  443. // Defines CEnumPins
  444. //
  445. // Pin enumerator class that works by calling CBaseFilter. This interface
  446. // is provided by CBaseFilter::EnumPins and calls GetPinCount() and
  447. // GetPin() to enumerate existing pins. Needs to be a separate object so
  448. // that it can be cloned (creating an existing object at the same
  449. // position in the enumeration)
  450. //
  451. //=====================================================================
  452. //=====================================================================
  453. class CEnumPins : public IEnumPins      // The interface we support
  454. {
  455.     int m_Position;                 // Current ordinal position
  456.     int m_PinCount;                 // Number of pins available
  457.     CBaseFilter *m_pFilter;         // The filter who owns us
  458.     LONG m_Version;                 // Pin version information
  459.     LONG m_cRef;
  460.     typedef CGenericList<CBasePin> CPinList;
  461.     CPinList m_PinCache;     // These pointers have not been AddRef'ed and
  462.     // so they should not be dereferenced.  They are
  463.     // merely kept to ID which pins have been enumerated.
  464. #ifdef DEBUG
  465.     DWORD m_dwCookie;
  466. #endif
  467.     /* If while we are retrieving a pin for example from the filter an error
  468.        occurs we assume that our internal state is stale with respect to the
  469.        filter (someone may have deleted all the pins). We can check before
  470.        starting whether or not the operation is likely to fail by asking the
  471.        filter what it's current version number is. If the filter has not
  472.        overriden the GetPinVersion method then this will always match */
  473.     BOOL AreWeOutOfSync() {
  474.         return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
  475.     };
  476.     /* This method performs the same operations as Reset, except is does not clear
  477.        the cache of pins already enumerated. */
  478.     STDMETHODIMP Refresh();
  479. public:
  480.     CEnumPins(
  481.         CBaseFilter *pFilter,
  482.         CEnumPins *pEnumPins);
  483.     virtual ~CEnumPins();
  484.     // IUnknown
  485.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  486.     STDMETHODIMP_(ULONG) AddRef();
  487.     STDMETHODIMP_(ULONG) Release();
  488.     // IEnumPins
  489.     STDMETHODIMP Next(
  490.         ULONG cPins,         // place this many pins...
  491.         IPin ** ppPins,      // ...in this array of IPin*
  492.         ULONG * pcFetched    // actual count passed returned here
  493.     );
  494.     STDMETHODIMP Skip(ULONG cPins);
  495.     STDMETHODIMP Reset();
  496.     STDMETHODIMP Clone(IEnumPins **ppEnum);
  497. };
  498. //=====================================================================
  499. //=====================================================================
  500. // Defines CEnumMediaTypes
  501. //
  502. // Enumerates the preferred formats for input and output pins
  503. //=====================================================================
  504. //=====================================================================
  505. class CEnumMediaTypes : public IEnumMediaTypes    // The interface we support
  506. {
  507.     int m_Position;           // Current ordinal position
  508.     CBasePin *m_pPin;         // The pin who owns us
  509.     LONG m_Version;           // Media type version value
  510.     LONG m_cRef;
  511. #ifdef DEBUG
  512.     DWORD m_dwCookie;
  513. #endif
  514.     /* The media types a filter supports can be quite dynamic so we add to
  515.        the general IEnumXXXX interface the ability to be signaled when they
  516.        change via an event handle the connected filter supplies. Until the
  517.        Reset method is called after the state changes all further calls to
  518.        the enumerator (except Reset) will return E_UNEXPECTED error code */
  519.     BOOL AreWeOutOfSync() {
  520.         return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
  521.     };
  522. public:
  523.     CEnumMediaTypes(
  524.         CBasePin *pPin,
  525.         CEnumMediaTypes *pEnumMediaTypes);
  526.     virtual ~CEnumMediaTypes();
  527.     // IUnknown
  528.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  529.     STDMETHODIMP_(ULONG) AddRef();
  530.     STDMETHODIMP_(ULONG) Release();
  531.     // IEnumMediaTypes
  532.     STDMETHODIMP Next(
  533.         ULONG cMediaTypes,          // place this many pins...
  534.         AM_MEDIA_TYPE ** ppMediaTypes,  // ...in this array
  535.         ULONG * pcFetched           // actual count passed
  536.     );
  537.     STDMETHODIMP Skip(ULONG cMediaTypes);
  538.     STDMETHODIMP Reset();
  539.     STDMETHODIMP Clone(IEnumMediaTypes **ppEnum);
  540. };
  541. //=====================================================================
  542. //=====================================================================
  543. // Defines CBaseOutputPin
  544. //
  545. // class derived from CBasePin that can pass buffers to a connected pin
  546. // that supports IMemInputPin. Supports IPin.
  547. //
  548. // Derive your output pin from this.
  549. //
  550. //=====================================================================
  551. //=====================================================================
  552. class  AM_NOVTABLE CBaseOutputPin : public CBasePin
  553. {
  554. protected:
  555.     IMemAllocator *m_pAllocator;
  556.     IMemInputPin *m_pInputPin;        // interface on the downstreaminput pin
  557.                                       // set up in CheckConnect when we connect.
  558. public:
  559.     CBaseOutputPin(
  560.         TCHAR *pObjectName,
  561.         CBaseFilter *pFilter,
  562.         CCritSec *pLock,
  563.         HRESULT *phr,
  564.         LPCWSTR pName);
  565. #ifdef UNICODE
  566.     CBaseOutputPin(
  567.         CHAR *pObjectName,
  568.         CBaseFilter *pFilter,
  569.         CCritSec *pLock,
  570.         HRESULT *phr,
  571.         LPCWSTR pName);
  572. #endif
  573.     // override CompleteConnect() so we can negotiate an allocator
  574.     virtual HRESULT CompleteConnect(IPin *pReceivePin);
  575.     // negotiate the allocator and its buffer size/count and other properties
  576.     // Calls DecideBufferSize to set properties
  577.     virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);
  578.     // override this to set the buffer size and count. Return an error
  579.     // if the size/count is not to your liking.
  580.     // The allocator properties passed in are those requested by the
  581.     // input pin - use eg the alignment and prefix members if you have
  582.     // no preference on these.
  583.     virtual HRESULT DecideBufferSize(
  584.         IMemAllocator * pAlloc,
  585.         ALLOCATOR_PROPERTIES * ppropInputRequest
  586.     ) PURE;
  587.     // returns an empty sample buffer from the allocator
  588.     virtual HRESULT GetDeliveryBuffer(IMediaSample ** ppSample,
  589.                                       REFERENCE_TIME * pStartTime,
  590.                                       REFERENCE_TIME * pEndTime,
  591.                                       DWORD dwFlags);
  592.     // deliver a filled-in sample to the connected input pin
  593.     // note - you need to release it after calling this. The receiving
  594.     // pin will addref the sample if it needs to hold it beyond the
  595.     // call.
  596.     virtual HRESULT Deliver(IMediaSample *);
  597.     // override this to control the connection
  598.     virtual HRESULT InitAllocator(IMemAllocator **ppAlloc);
  599.     HRESULT CheckConnect(IPin *pPin);
  600.     HRESULT BreakConnect();
  601.     // override to call Commit and Decommit
  602.     HRESULT Active(void);
  603.     HRESULT Inactive(void);
  604.     // we have a default handling of EndOfStream which is to return
  605.     // an error, since this should be called on input pins only
  606.     STDMETHODIMP EndOfStream(void);
  607.     // called from elsewhere in our filter to pass EOS downstream to
  608.     // our connected input pin
  609.     virtual HRESULT DeliverEndOfStream(void);
  610.     // same for Begin/EndFlush - we handle Begin/EndFlush since it
  611.     // is an error on an output pin, and we have Deliver methods to
  612.     // call the methods on the connected pin
  613.     STDMETHODIMP BeginFlush(void);
  614.     STDMETHODIMP EndFlush(void);
  615.     virtual HRESULT DeliverBeginFlush(void);
  616.     virtual HRESULT DeliverEndFlush(void);
  617.     // deliver NewSegment to connected pin - you will need to
  618.     // override this if you queue any data in your output pin.
  619.     virtual HRESULT DeliverNewSegment(
  620.                         REFERENCE_TIME tStart,
  621.                         REFERENCE_TIME tStop,
  622.                         double dRate);
  623.     //================================================================================
  624.     // IQualityControl methods
  625.     //================================================================================
  626.     // All inherited from CBasePin and not overridden here.
  627.     // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
  628.     // STDMETHODIMP SetSink(IQualityControl * piqc);
  629. };
  630. //=====================================================================
  631. //=====================================================================
  632. // Defines CBaseInputPin
  633. //
  634. // derive your standard input pin from this.
  635. // you need to supply GetMediaType and CheckConnect etc (see CBasePin),
  636. // and you need to supply Receive to do something more useful.
  637. //
  638. //=====================================================================
  639. //=====================================================================
  640. class AM_NOVTABLE CBaseInputPin : public CBasePin,
  641.                                   public IMemInputPin
  642. {
  643. protected:
  644.     IMemAllocator *m_pAllocator;    // Default memory allocator
  645.     // allocator is read-only, so received samples
  646.     // cannot be modified (probably only relevant to in-place
  647.     // transforms
  648.     BYTE m_bReadOnly;
  649.     // in flushing state (between BeginFlush and EndFlush)
  650.     // if TRUE, all Receives are returned with S_FALSE
  651.     BYTE m_bFlushing;
  652.     // Sample properties - initalized in Receive
  653.     AM_SAMPLE2_PROPERTIES m_SampleProps;
  654. public:
  655.     CBaseInputPin(
  656.         TCHAR *pObjectName,
  657.         CBaseFilter *pFilter,
  658.         CCritSec *pLock,
  659.         HRESULT *phr,
  660.         LPCWSTR pName);
  661. #ifdef UNICODE
  662.     CBaseInputPin(
  663.         CHAR *pObjectName,
  664.         CBaseFilter *pFilter,
  665.         CCritSec *pLock,
  666.         HRESULT *phr,
  667.         LPCWSTR pName);
  668. #endif
  669.     virtual ~CBaseInputPin();
  670.     DECLARE_IUNKNOWN
  671.     // override this to publicise our interfaces
  672.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  673.     // return the allocator interface that this input pin
  674.     // would like the output pin to use
  675.     STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);
  676.     // tell the input pin which allocator the output pin is actually
  677.     // going to use.
  678.     STDMETHODIMP NotifyAllocator(
  679.                     IMemAllocator * pAllocator,
  680.                     BOOL bReadOnly);
  681.     // do something with this media sample
  682.     STDMETHODIMP Receive(IMediaSample *pSample);
  683.     // do something with these media samples
  684.     STDMETHODIMP ReceiveMultiple (
  685.         IMediaSample **pSamples,
  686.         long nSamples,
  687.         long *nSamplesProcessed);
  688.     // See if Receive() blocks
  689.     STDMETHODIMP ReceiveCanBlock();
  690.     // Default handling for BeginFlush - call at the beginning
  691.     // of your implementation (makes sure that all Receive calls
  692.     // fail). After calling this, you need to free any queued data
  693.     // and then call downstream.
  694.     STDMETHODIMP BeginFlush(void);
  695.     // default handling for EndFlush - call at end of your implementation
  696.     // - before calling this, ensure that there is no queued data and no thread
  697.     // pushing any more without a further receive, then call downstream,
  698.     // then call this method to clear the m_bFlushing flag and re-enable
  699.     // receives
  700.     STDMETHODIMP EndFlush(void);
  701.     // this method is optional (can return E_NOTIMPL).
  702.     // default implementation returns E_NOTIMPL. Override if you have
  703.     // specific alignment or prefix needs, but could use an upstream
  704.     // allocator
  705.     STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);
  706.     // Release the pin's allocator.
  707.     HRESULT BreakConnect();
  708.     // helper method to check the read-only flag
  709.     BOOL IsReadOnly() {
  710.         return m_bReadOnly;
  711.     };
  712.     // helper method to see if we are flushing
  713.     BOOL IsFlushing() {
  714.         return m_bFlushing;
  715.     };
  716.     //  Override this for checking whether it's OK to process samples
  717.     //  Also call this from EndOfStream.
  718.     virtual HRESULT CheckStreaming();
  719.     // Pass a Quality notification on to the appropriate sink
  720.     HRESULT PassNotify(Quality& q);
  721.     //================================================================================
  722.     // IQualityControl methods (from CBasePin)
  723.     //================================================================================
  724.     STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
  725.     // no need to override:
  726.     // STDMETHODIMP SetSink(IQualityControl * piqc);
  727.     // switch the pin to inactive state - may already be inactive
  728.     virtual HRESULT Inactive(void);
  729.     // Return sample properties pointer
  730.     AM_SAMPLE2_PROPERTIES * SampleProps() {
  731.         ASSERT(m_SampleProps.cbData != 0);
  732.         return &m_SampleProps;
  733.     }
  734. };
  735. ///////////////////////////////////////////////////////////////////////////
  736. // CDynamicOutputPin
  737. //
  738. class CDynamicOutputPin : public CBaseOutputPin,
  739.                           public IPinFlowControl
  740. {
  741. public:
  742. #ifdef UNICODE
  743.     CDynamicOutputPin(
  744.         CHAR *pObjectName,
  745.         CBaseFilter *pFilter,
  746.         CCritSec *pLock,
  747.         HRESULT *phr,
  748.         LPCWSTR pName);
  749. #endif
  750.     CDynamicOutputPin(
  751.         TCHAR *pObjectName,
  752.         CBaseFilter *pFilter,
  753.         CCritSec *pLock,
  754.         HRESULT *phr,
  755.         LPCWSTR pName);
  756.     ~CDynamicOutputPin();
  757.     // IUnknown Methods
  758.     DECLARE_IUNKNOWN
  759.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  760.     // IPin Methods
  761.     STDMETHODIMP Disconnect(void);
  762.     // IPinFlowControl Methods
  763.     STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
  764.     //  Set graph config info
  765.     void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
  766.     #ifdef DEBUG
  767.     virtual HRESULT Deliver(IMediaSample *pSample);
  768.     virtual HRESULT DeliverEndOfStream(void);
  769.     virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
  770.     #endif // DEBUG
  771.     HRESULT DeliverBeginFlush(void);
  772.     HRESULT DeliverEndFlush(void);
  773.     HRESULT Inactive(void);
  774.     HRESULT Active(void);
  775.     virtual HRESULT CompleteConnect(IPin *pReceivePin);
  776.     virtual HRESULT StartUsingOutputPin(void);
  777.     virtual void StopUsingOutputPin(void);
  778.     virtual bool StreamingThreadUsingOutputPin(void);
  779.     HRESULT ChangeOutputFormat
  780.         (
  781.         const AM_MEDIA_TYPE *pmt,
  782.         REFERENCE_TIME tSegmentStart,
  783.         REFERENCE_TIME tSegmentStop,
  784.         double dSegmentRate
  785.         );
  786.     HRESULT ChangeMediaType(const CMediaType *pmt);
  787.     HRESULT DynamicReconnect(const CMediaType *pmt);
  788. protected:
  789.     HRESULT SynchronousBlockOutputPin(void);
  790.     HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
  791.     HRESULT UnblockOutputPin(void);
  792.     void BlockOutputPin(void);
  793.     void ResetBlockState(void);
  794.     static HRESULT WaitEvent(HANDLE hEvent);
  795.     enum BLOCK_STATE
  796.     {
  797.         NOT_BLOCKED,
  798.         PENDING,
  799.         BLOCKED
  800.     };
  801.     // This lock should be held when the following class members are
  802.     // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
  803.     // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
  804.     CCritSec m_BlockStateLock;
  805.     // This event should be signaled when the output pin is
  806.     // not blocked.  This is a manual reset event.  For more
  807.     // information on events, see the documentation for
  808.     // CreateEvent() in the Windows SDK.
  809.     HANDLE m_hUnblockOutputPinEvent;
  810.     // This event will be signaled when block operation succeedes or
  811.     // when the user cancels the block operation.  The block operation
  812.     // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
  813.     // while the block operation is pending.
  814.     HANDLE m_hNotifyCallerPinBlockedEvent;
  815.     // The state of the current block operation.
  816.     BLOCK_STATE m_BlockState;
  817.     // The ID of the thread which last called IPinFlowControl::Block().
  818.     // For more information on thread IDs, see the documentation for
  819.     // GetCurrentThreadID() in the Windows SDK.
  820.     DWORD m_dwBlockCallerThreadID;
  821.     // The number of times StartUsingOutputPin() has been sucessfully
  822.     // called and a corresponding call to StopUsingOutputPin() has not
  823.     // been made.  When this variable is greater than 0, the streaming
  824.     // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
  825.     // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple().  The
  826.     // streaming thread could also be calling: DynamicReconnect(),
  827.     // ChangeMediaType() or ChangeOutputFormat().  The output pin cannot
  828.     // be blocked while the output pin is being used.
  829.     DWORD m_dwNumOutstandingOutputPinUsers;
  830.     // This event should be set when the IMediaFilter::Stop() is called.
  831.     // This is a manual reset event.  It is also set when the output pin
  832.     // delivers a flush to the connected input pin.
  833.     HANDLE m_hStopEvent;
  834.     IGraphConfig* m_pGraphConfig;
  835.     // TRUE if the output pin's allocator's samples are read only.
  836.     // Otherwise FALSE.  For more information, see the documentation
  837.     // for IMemInputPin::NotifyAllocator().
  838.     BOOL m_bPinUsesReadOnlyAllocator;
  839. private:
  840.     HRESULT Initialize(void);
  841.     HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
  842.     #ifdef DEBUG
  843.     void AssertValid(void);
  844.     #endif // DEBUG
  845. };
  846. class CAutoUsingOutputPin
  847. {
  848. public:
  849.     CAutoUsingOutputPin( CDynamicOutputPin* pOutputPin, HRESULT* phr );
  850.     ~CAutoUsingOutputPin();
  851. private:
  852.     CDynamicOutputPin* m_pOutputPin;
  853. };
  854. inline CAutoUsingOutputPin::CAutoUsingOutputPin( CDynamicOutputPin* pOutputPin, HRESULT* phr ) :
  855.     m_pOutputPin(NULL)
  856. {
  857.     // The caller should always pass in valid pointers.
  858.     ASSERT( NULL != pOutputPin );
  859.     ASSERT( NULL != phr );
  860.     // Make sure the user initialized phr.
  861.     ASSERT( S_OK == *phr );
  862.     HRESULT hr = pOutputPin->StartUsingOutputPin();
  863.     if( FAILED( hr ) )
  864.     {
  865.         *phr = hr;
  866.         return;
  867.     }
  868.     m_pOutputPin = pOutputPin;
  869. }
  870. inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
  871. {
  872.     if( NULL != m_pOutputPin )
  873.     {
  874.         m_pOutputPin->StopUsingOutputPin();
  875.     }
  876. }
  877. #ifdef DEBUG
  878. inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
  879. {
  880.     // The caller should call StartUsingOutputPin() before calling this
  881.     // method.
  882.     ASSERT(StreamingThreadUsingOutputPin());
  883.     return CBaseOutputPin::Deliver(pSample);
  884. }
  885. inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
  886. {
  887.     // The caller should call StartUsingOutputPin() before calling this
  888.     // method.
  889.     ASSERT( StreamingThreadUsingOutputPin() );
  890.     return CBaseOutputPin::DeliverEndOfStream();
  891. }
  892. inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  893. {
  894.     // The caller should call StartUsingOutputPin() before calling this
  895.     // method.
  896.     ASSERT(StreamingThreadUsingOutputPin());
  897.     return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
  898. }
  899. #endif // DEBUG
  900. //=====================================================================
  901. //=====================================================================
  902. // Memory allocators
  903. //
  904. // the shared memory transport between pins requires the input pin
  905. // to provide a memory allocator that can provide sample objects. A
  906. // sample object supports the IMediaSample interface.
  907. //
  908. // CBaseAllocator handles the management of free and busy samples. It
  909. // allocates CMediaSample objects. CBaseAllocator is an abstract class:
  910. // in particular it has no method of initializing the list of free
  911. // samples. CMemAllocator is derived from CBaseAllocator and initializes
  912. // the list of samples using memory from the standard IMalloc interface.
  913. //
  914. // If you want your buffers to live in some special area of memory,
  915. // derive your allocator object from CBaseAllocator. If you derive your
  916. // IMemInputPin interface object from CBaseMemInputPin, you will get
  917. // CMemAllocator-based allocation etc for free and will just need to
  918. // supply the Receive handling, and media type / format negotiation.
  919. //=====================================================================
  920. //=====================================================================
  921. //=====================================================================
  922. //=====================================================================
  923. // Defines CMediaSample
  924. //
  925. // an object of this class supports IMediaSample and represents a buffer
  926. // for media data with some associated properties. Releasing it returns
  927. // it to a freelist managed by a CBaseAllocator derived object.
  928. //=====================================================================
  929. //=====================================================================
  930. class CMediaSample : public IMediaSample2    // The interface we support
  931. {
  932. protected:
  933.     friend class CBaseAllocator;
  934.     /*  Values for dwFlags - these are used for backward compatiblity
  935.         only now - use AM_SAMPLE_xxx
  936.     */
  937.     enum { Sample_SyncPoint       = 0x01,   /* Is this a sync point */
  938.            Sample_Preroll         = 0x02,   /* Is this a preroll sample */
  939.            Sample_Discontinuity   = 0x04,   /* Set if start of new segment */
  940.            Sample_TypeChanged     = 0x08,   /* Has the type changed */
  941.            Sample_TimeValid       = 0x10,   /* Set if time is valid */
  942.            Sample_MediaTimeValid  = 0x20,   /* Is the media time valid */
  943.            Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
  944.            Sample_StopValid       = 0x100,  /* Stop time valid */
  945.            Sample_ValidFlags      = 0x1FF
  946.          };
  947.     /* Properties, the media sample class can be a container for a format
  948.        change in which case we take a copy of a type through the SetMediaType
  949.        interface function and then return it when GetMediaType is called. As
  950.        we do no internal processing on it we leave it as a pointer */
  951.     DWORD            m_dwFlags;         /* Flags for this sample */
  952.                                         /* Type specific flags are packed
  953.                                            into the top word
  954.                                         */
  955.     DWORD            m_dwTypeSpecificFlags; /* Media type specific flags */
  956.     LPBYTE           m_pBuffer;         /* Pointer to the complete buffer */
  957.     LONG             m_lActual;         /* Length of data in this sample */
  958.     LONG             m_cbBuffer;        /* Size of the buffer */
  959.     CBaseAllocator  *m_pAllocator;      /* The allocator who owns us */
  960.     CMediaSample     *m_pNext;          /* Chaining in free list */
  961.     REFERENCE_TIME   m_Start;           /* Start sample time */
  962.     REFERENCE_TIME   m_End;             /* End sample time */
  963.     LONGLONG         m_MediaStart;      /* Real media start position */
  964.     LONG             m_MediaEnd;        /* A difference to get the end */
  965.     AM_MEDIA_TYPE    *m_pMediaType;     /* Media type change data */
  966.     DWORD            m_dwStreamId;      /* Stream id */
  967. public:
  968.     LONG             m_cRef;            /* Reference count */
  969. public:
  970.     CMediaSample(
  971.         TCHAR *pName,
  972.         CBaseAllocator *pAllocator,
  973.         HRESULT *phr,
  974.         LPBYTE pBuffer = NULL,
  975.         LONG length = 0);
  976. #ifdef UNICODE
  977.     CMediaSample(
  978.         CHAR *pName,
  979.         CBaseAllocator *pAllocator,
  980.         HRESULT *phr,
  981.         LPBYTE pBuffer = NULL,
  982.         LONG length = 0);
  983. #endif
  984.     virtual ~CMediaSample();
  985.     /* Note the media sample does not delegate to its owner */
  986.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  987.     STDMETHODIMP_(ULONG) AddRef();
  988.     STDMETHODIMP_(ULONG) Release();
  989.     // set the buffer pointer and length. Used by allocators that
  990.     // want variable sized pointers or pointers into already-read data.
  991.     // This is only available through a CMediaSample* not an IMediaSample*
  992.     // and so cannot be changed by clients.
  993.     HRESULT SetPointer(BYTE * ptr, LONG cBytes);
  994.     // Get me a read/write pointer to this buffer's memory.
  995.     STDMETHODIMP GetPointer(BYTE ** ppBuffer);
  996.     STDMETHODIMP_(LONG) GetSize(void);
  997.     // get the stream time at which this sample should start and finish.
  998.     STDMETHODIMP GetTime(
  999.         REFERENCE_TIME * pTimeStart,     // put time here
  1000.         REFERENCE_TIME * pTimeEnd
  1001.     );
  1002.     // Set the stream time at which this sample should start and finish.
  1003.     STDMETHODIMP SetTime(
  1004.         REFERENCE_TIME * pTimeStart,     // put time here
  1005.         REFERENCE_TIME * pTimeEnd
  1006.     );
  1007.     STDMETHODIMP IsSyncPoint(void);
  1008.     STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
  1009.     STDMETHODIMP IsPreroll(void);
  1010.     STDMETHODIMP SetPreroll(BOOL bIsPreroll);
  1011.     STDMETHODIMP_(LONG) GetActualDataLength(void);
  1012.     STDMETHODIMP SetActualDataLength(LONG lActual);
  1013.     // these allow for limited format changes in band
  1014.     STDMETHODIMP GetMediaType(AM_MEDIA_TYPE **ppMediaType);
  1015.     STDMETHODIMP SetMediaType(AM_MEDIA_TYPE *pMediaType);
  1016.     // returns S_OK if there is a discontinuity in the data (this same is
  1017.     // not a continuation of the previous stream of data
  1018.     // - there has been a seek).
  1019.     STDMETHODIMP IsDiscontinuity(void);
  1020.     // set the discontinuity property - TRUE if this sample is not a
  1021.     // continuation, but a new sample after a seek.
  1022.     STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
  1023.     // get the media times for this sample
  1024.     STDMETHODIMP GetMediaTime(
  1025.      LONGLONG * pTimeStart,
  1026. LONGLONG * pTimeEnd
  1027.     );
  1028.     // Set the media times for this sample
  1029.     STDMETHODIMP SetMediaTime(
  1030.      LONGLONG * pTimeStart,
  1031. LONGLONG * pTimeEnd
  1032.     );
  1033.     // Set and get properties (IMediaSample2)
  1034.     STDMETHODIMP GetProperties(
  1035.         DWORD cbProperties,
  1036.         BYTE * pbProperties
  1037.     );
  1038.     STDMETHODIMP SetProperties(
  1039.         DWORD cbProperties,
  1040.         const BYTE * pbProperties
  1041.     );
  1042. };
  1043. //=====================================================================
  1044. //=====================================================================
  1045. // Defines CBaseAllocator
  1046. //
  1047. // Abstract base class that manages a list of media samples
  1048. //
  1049. // This class provides support for getting buffers from the free list,
  1050. // including handling of commit and (asynchronous) decommit.
  1051. //
  1052. // Derive from this class and override the Alloc and Free functions to
  1053. // allocate your CMediaSample (or derived) objects and add them to the
  1054. // free list, preparing them as necessary.
  1055. //=====================================================================
  1056. //=====================================================================
  1057. class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
  1058.                        public IMemAllocatorCallbackTemp, // The interface we support
  1059.                        public CCritSec             // Provides object locking
  1060. {
  1061.     class CSampleList;
  1062.     friend class CSampleList;
  1063.     /*  Trick to get at protected member in CMediaSample */
  1064.     static CMediaSample * &NextSample(CMediaSample *pSample)
  1065.     {
  1066.         return pSample->m_pNext;
  1067.     };
  1068.     /*  Mini list class for the free list */
  1069.     class CSampleList
  1070.     {
  1071.     public:
  1072.         CSampleList() : m_List(NULL), m_nOnList(0) {};
  1073. #ifdef DEBUG
  1074.         ~CSampleList()
  1075.         {
  1076.             ASSERT(m_nOnList == 0);
  1077.         };
  1078. #endif
  1079.         CMediaSample *Head() const { return m_List; };
  1080.         CMediaSample *Next(CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
  1081.         int GetCount() const { return m_nOnList; };
  1082.         void Add(CMediaSample *pSample)
  1083.         {
  1084.             ASSERT(pSample != NULL);
  1085.             CBaseAllocator::NextSample(pSample) = m_List;
  1086.             m_List = pSample;
  1087.             m_nOnList++;
  1088.         };
  1089.         CMediaSample *RemoveHead()
  1090.         {
  1091.             CMediaSample *pSample = m_List;
  1092.             if (pSample != NULL) {
  1093.                 m_List = CBaseAllocator::NextSample(m_List);
  1094.                 m_nOnList--;
  1095.             }
  1096.             return pSample;
  1097.         };
  1098.         void Remove(CMediaSample *pSample);
  1099.     public:
  1100.         CMediaSample *m_List;
  1101.         int           m_nOnList;
  1102.     };
  1103. protected:
  1104.     CSampleList m_lFree;        // Free list
  1105.     /*  Note to overriders of CBaseAllocator.
  1106.         We use a lazy signalling mechanism for waiting for samples.
  1107.         This means we don't call the OS if no waits occur.
  1108.         In order to implement this:
  1109.         1. When a new sample is added to m_lFree call NotifySample() which
  1110.            calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
  1111.            sets m_lWaiting to 0.
  1112.            This must all be done holding the allocator's critical section.
  1113.         2. When waiting for a sample call SetWaiting() which increments
  1114.            m_lWaiting BEFORE leaving the allocator's critical section.
  1115.         3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
  1116.            having left the allocator's critical section.  The effect of
  1117.            this is to remove 1 from the semaphore's count.  You MUST call
  1118.            this once having incremented m_lWaiting.
  1119.         The following are then true when the critical section is not held :
  1120.             (let nWaiting = number about to wait or waiting)
  1121.             (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
  1122.             (2) m_lWaiting + Semaphore count == nWaiting
  1123.         We would deadlock if
  1124.            nWaiting != 0 &&
  1125.            m_lFree.GetCount() != 0 &&
  1126.            Semaphore count == 0
  1127.            But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
  1128.            from (2) Semaphore count == nWaiting (which is non-0) so the
  1129.            deadlock can't happen.
  1130.     */
  1131.     HANDLE m_hSem;              // For signalling
  1132.     long m_lWaiting;            // Waiting for a free element
  1133.     long m_lCount;              // how many buffers we have agreed to provide
  1134.     long m_lAllocated;          // how many buffers are currently allocated
  1135.     long m_lSize;               // agreed size of each buffer
  1136.     long m_lAlignment;          // agreed alignment
  1137.     long m_lPrefix;             // agreed prefix (preceeds GetPointer() value)
  1138.     BOOL m_bChanged;            // Have the buffer requirements changed
  1139.     // if true, we are decommitted and can't allocate memory
  1140.     BOOL m_bCommitted;
  1141.     // if true, the decommit has happened, but we haven't called Free yet
  1142.     // as there are still outstanding buffers
  1143.     BOOL m_bDecommitInProgress;
  1144.     //  Notification interface
  1145.     IMemAllocatorNotifyCallbackTemp *m_pNotify;
  1146.     BOOL m_fEnableReleaseCallback;
  1147.     // called to decommit the memory when the last buffer is freed
  1148.     // pure virtual - need to override this
  1149.     virtual void Free(void) PURE;
  1150.     // override to allocate the memory when commit called
  1151.     virtual HRESULT Alloc(void);
  1152. public:
  1153.     CBaseAllocator(
  1154.         TCHAR *, LPUNKNOWN, HRESULT *,
  1155.         BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
  1156. #ifdef UNICODE
  1157.     CBaseAllocator(
  1158.         CHAR *, LPUNKNOWN, HRESULT *,
  1159.         BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
  1160. #endif
  1161.     virtual ~CBaseAllocator();
  1162.     DECLARE_IUNKNOWN
  1163.     // override this to publicise our interfaces
  1164.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  1165.     STDMETHODIMP SetProperties(
  1166.     ALLOCATOR_PROPERTIES* pRequest,
  1167.     ALLOCATOR_PROPERTIES* pActual);
  1168.     // return the properties actually being used on this allocator
  1169.     STDMETHODIMP GetProperties(
  1170.     ALLOCATOR_PROPERTIES* pProps);
  1171.     // override Commit to allocate memory. We handle the GetBuffer
  1172.     //state changes
  1173.     STDMETHODIMP Commit();
  1174.     // override this to handle the memory freeing. We handle any outstanding
  1175.     // GetBuffer calls
  1176.     STDMETHODIMP Decommit();
  1177.     // get container for a sample. Blocking, synchronous call to get the
  1178.     // next free buffer (as represented by an IMediaSample interface).
  1179.     // on return, the time etc properties will be invalid, but the buffer
  1180.     // pointer and size will be correct. The two time parameters are
  1181.     // optional and either may be NULL, they may alternatively be set to
  1182.     // the start and end times the sample will have attached to it
  1183.     // bPrevFramesSkipped is not used (used only by the video renderer's
  1184.     // allocator where it affects quality management in direct draw).
  1185.     STDMETHODIMP GetBuffer(IMediaSample **ppBuffer,
  1186.                            REFERENCE_TIME * pStartTime,
  1187.                            REFERENCE_TIME * pEndTime,
  1188.                            DWORD dwFlags);
  1189.     // final release of a CMediaSample will call this
  1190.     STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
  1191.     // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
  1192.     STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
  1193.     STDMETHODIMP GetFreeCount(LONG *plBuffersFree);
  1194.     // Notify that a sample is available
  1195.     void NotifySample();
  1196.     // Notify that we're waiting for a sample
  1197.     void SetWaiting() { m_lWaiting++; };
  1198. };
  1199. //=====================================================================
  1200. //=====================================================================
  1201. // Defines CMemAllocator
  1202. //
  1203. // this is an allocator based on CBaseAllocator that allocates sample
  1204. // buffers in main memory (from 'new'). You must call SetProperties
  1205. // before calling Commit.
  1206. //
  1207. // we don't free the memory when going into Decommit state. The simplest
  1208. // way to implement this without complicating CBaseAllocator is to
  1209. // have a Free() function, called to go into decommit state, that does
  1210. // nothing and a ReallyFree function called from our destructor that
  1211. // actually frees the memory.
  1212. //=====================================================================
  1213. //=====================================================================
  1214. //  Make me one from quartz.dll
  1215. STDAPI CreateMemoryAllocator(IMemAllocator **ppAllocator);
  1216. class CMemAllocator : public CBaseAllocator
  1217. {
  1218. protected:
  1219.     LPBYTE m_pBuffer;   // combined memory for all buffers
  1220.     // override to free the memory when decommit completes
  1221.     // - we actually do nothing, and save the memory until deletion.
  1222.     void Free(void);
  1223.     // called from the destructor (and from Alloc if changing size/count) to
  1224.     // actually free up the memory
  1225.     void ReallyFree(void);
  1226.     // overriden to allocate the memory when commit called
  1227.     HRESULT Alloc(void);
  1228. public:
  1229.     /* This goes in the factory template table to create new instances */
  1230.     static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *);
  1231.     STDMETHODIMP SetProperties(
  1232.     ALLOCATOR_PROPERTIES* pRequest,
  1233.     ALLOCATOR_PROPERTIES* pActual);
  1234.     CMemAllocator(TCHAR *, LPUNKNOWN, HRESULT *);
  1235. #ifdef UNICODE
  1236.     CMemAllocator(CHAR *, LPUNKNOWN, HRESULT *);
  1237. #endif
  1238.     ~CMemAllocator();
  1239. };
  1240. // helper used by IAMovieSetup implementation
  1241. STDAPI
  1242. AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
  1243.                          , IFilterMapper *                  pIFM
  1244.                          , BOOL                             bRegister  );
  1245. ///////////////////////////////////////////////////////////////////////////
  1246. // ------------------------------------------------------------------------
  1247. // ------------------------------------------------------------------------
  1248. // ------------------------------------------------------------------------
  1249. // ------------------------------------------------------------------------
  1250. ///////////////////////////////////////////////////////////////////////////
  1251. #endif /* __FILTER__ */