1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - efines class hierarchy for streams
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
14 /* The following classes are declared in this header: */
16 class CBaseMediaFilter
; // IMediaFilter support
17 class CBaseFilter
; // IBaseFilter,IMediaFilter support
18 class CBasePin
; // Abstract base class for IPin interface
19 class CEnumPins
; // Enumerate input and output pins
20 class CEnumMediaTypes
; // Enumerate the pin's preferred formats
21 class CBaseOutputPin
; // Adds data provider member functions
22 class CBaseInputPin
; // Implements IMemInputPin interface
23 class CMediaSample
; // Basic transport unit for IMemInputPin
24 class CBaseAllocator
; // General list guff for most allocators
25 class CMemAllocator
; // Implements memory buffer allocation
28 //=====================================================================
29 //=====================================================================
31 // QueryFilterInfo and QueryPinInfo AddRef the interface pointers
32 // they return. You can use the macro below to release the interface.
34 //=====================================================================
35 //=====================================================================
37 #define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
39 #define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
41 //=====================================================================
42 //=====================================================================
43 // Defines CBaseMediaFilter
45 // Abstract base class implementing IMediaFilter.
47 // Typically you will derive your filter from CBaseFilter rather than
48 // this, unless you are implementing an object such as a plug-in
49 // distributor that needs to support IMediaFilter but not IBaseFilter.
51 // Note that IMediaFilter is derived from IPersist to allow query of
53 //=====================================================================
54 //=====================================================================
56 class AM_NOVTABLE CBaseMediaFilter
: public CUnknown
,
62 FILTER_STATE m_State
; // current state: running, paused
63 IReferenceClock
*m_pClock
; // this filter's reference clock
64 // note: all filters in a filter graph use the same clock
66 // offset from stream time to reference time
69 CLSID m_clsid
; // This filters clsid
70 // used for serialization
71 CCritSec
*m_pLock
; // Object we use for locking
81 virtual ~CBaseMediaFilter();
85 // override this to say what interfaces we support where
86 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void ** ppv
);
89 // --- IPersist method ---
92 STDMETHODIMP
GetClassID(CLSID
*pClsID
);
94 // --- IMediaFilter methods ---
96 STDMETHODIMP
GetState(DWORD dwMSecs
, FILTER_STATE
*State
);
98 STDMETHODIMP
SetSyncSource(IReferenceClock
*pClock
);
100 STDMETHODIMP
GetSyncSource(IReferenceClock
**pClock
);
102 // default implementation of Stop and Pause just record the
103 // state. Override to activate or de-activate your filter.
104 // Note that Run when called from Stopped state will call Pause
105 // to ensure activation, so if you are a source or transform
106 // you will probably not need to override Run.
108 STDMETHODIMP
Pause();
111 // the start parameter is the difference to be added to the
112 // sample's stream time to get the reference time for
114 STDMETHODIMP
Run(REFERENCE_TIME tStart
);
116 // --- helper methods ---
118 // return the current stream time - ie find out what
119 // stream time should be appearing now
120 virtual HRESULT
StreamTime(CRefTime
& rtStream
);
122 // Is the filter currently active? (running or paused)
124 CAutoLock
cObjectLock(m_pLock
);
125 return ((m_State
== State_Paused
) || (m_State
== State_Running
));
129 //=====================================================================
130 //=====================================================================
131 // Defines CBaseFilter
133 // An abstract class providing basic IBaseFilter support for pin
134 // enumeration and filter information reading.
136 // We cannot derive from CBaseMediaFilter since methods in IMediaFilter
137 // are also in IBaseFilter and would be ambiguous. Since much of the code
138 // assumes that they derive from a class that has m_State and other state
139 // directly available, we duplicate code from CBaseMediaFilter rather than
140 // having a member variable.
142 // Derive your filter from this, or from a derived object such as
144 //=====================================================================
145 //=====================================================================
148 class AM_NOVTABLE CBaseFilter
: public CUnknown
, // Handles an IUnknown
149 public IBaseFilter
, // The Filter Interface
150 public IAMovieSetup
// For un/registration
153 friend class CBasePin
;
156 FILTER_STATE m_State
; // current state: running, paused
157 IReferenceClock
*m_pClock
; // this graph's ref clock
158 CRefTime m_tStart
; // offset from stream time to reference time
159 CLSID m_clsid
; // This filters clsid
160 // used for serialization
161 CCritSec
*m_pLock
; // Object we use for locking
163 WCHAR
*m_pName
; // Full filter name
164 IFilterGraph
*m_pGraph
; // Graph we belong to
165 IMediaEventSink
*m_pSink
; // Called with notify events
166 LONG m_PinVersion
; // Current pin version
171 const TCHAR
*pName
, // Object description
172 LPUNKNOWN pUnk
, // IUnknown of delegating object
173 CCritSec
*pLock
, // Object who maintains lock
174 REFCLSID clsid
); // The clsid to be used to serialize this filter
177 TCHAR
*pName
, // Object description
178 LPUNKNOWN pUnk
, // IUnknown of delegating object
179 CCritSec
*pLock
, // Object who maintains lock
180 REFCLSID clsid
, // The clsid to be used to serialize this filter
181 HRESULT
*phr
); // General OLE return code
184 const CHAR
*pName
, // Object description
185 LPUNKNOWN pUnk
, // IUnknown of delegating object
186 CCritSec
*pLock
, // Object who maintains lock
187 REFCLSID clsid
); // The clsid to be used to serialize this filter
190 CHAR
*pName
, // Object description
191 LPUNKNOWN pUnk
, // IUnknown of delegating object
192 CCritSec
*pLock
, // Object who maintains lock
193 REFCLSID clsid
, // The clsid to be used to serialize this filter
194 HRESULT
*phr
); // General OLE return code
200 // override this to say what interfaces we support where
201 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void ** ppv
);
203 STDMETHODIMP_(ULONG
) NonDelegatingRelease();
207 // --- IPersist method ---
210 STDMETHODIMP
GetClassID(CLSID
*pClsID
);
212 // --- IMediaFilter methods ---
214 STDMETHODIMP
GetState(DWORD dwMSecs
, FILTER_STATE
*State
);
216 STDMETHODIMP
SetSyncSource(IReferenceClock
*pClock
);
218 STDMETHODIMP
GetSyncSource(IReferenceClock
**pClock
);
221 // override Stop and Pause so we can activate the pins.
222 // Note that Run will call Pause first if activation needed.
223 // Override these if you want to activate your filter rather than
226 STDMETHODIMP
Pause();
228 // the start parameter is the difference to be added to the
229 // sample's stream time to get the reference time for
231 STDMETHODIMP
Run(REFERENCE_TIME tStart
);
233 // --- helper methods ---
235 // return the current stream time - ie find out what
236 // stream time should be appearing now
237 virtual HRESULT
StreamTime(CRefTime
& rtStream
);
239 // Is the filter currently active?
241 CAutoLock
cObjectLock(m_pLock
);
242 return ((m_State
== State_Paused
) || (m_State
== State_Running
));
245 // Is this filter stopped (without locking)
247 return (m_State
== State_Stopped
);
251 // --- IBaseFilter methods ---
255 STDMETHODIMP
EnumPins(
256 IEnumPins
** ppEnum
);
259 // default behaviour of FindPin assumes pin ids are their names
260 STDMETHODIMP
FindPin(
265 STDMETHODIMP
QueryFilterInfo(
266 FILTER_INFO
* pInfo
);
268 STDMETHODIMP
JoinFilterGraph(
269 IFilterGraph
* pGraph
,
272 // return a Vendor information string. Optional - may return E_NOTIMPL.
273 // memory returned should be freed using CoTaskMemFree
274 // default implementation returns E_NOTIMPL
275 STDMETHODIMP
QueryVendorInfo(
279 // --- helper methods ---
281 // send an event notification to the filter graph if we know about it.
282 // returns S_OK if delivered, S_FALSE if the filter graph does not sink
283 // events, or an error otherwise.
286 LONG_PTR EventParam1
,
287 LONG_PTR EventParam2
);
289 // return the filter graph we belong to
290 IFilterGraph
*GetFilterGraph() {
295 // pPin is the pin to reconnect
296 // pmt is the type to reconnect with - can be NULL
297 // Calls ReconnectEx on the filter graph
298 HRESULT
ReconnectPin(IPin
*pPin
, AM_MEDIA_TYPE
const *pmt
);
300 // find out the current pin version (used by enumerators)
301 virtual LONG
GetPinVersion();
302 void IncrementPinVersion();
304 // you need to supply these to access the pins from the enumerator
305 // and for default Stop and Pause/Run activation.
306 virtual int GetPinCount() PURE
;
307 virtual CBasePin
*GetPin(int n
) PURE
;
309 // --- IAMovieSetup methods ---
311 STDMETHODIMP
Register(); // ask filter to register itself
312 STDMETHODIMP
Unregister(); // and unregister itself
314 // --- setup helper methods ---
315 // (override to return filters setup data)
317 virtual LPAMOVIESETUP_FILTER
GetSetupData(){ return NULL
; }
322 //=====================================================================
323 //=====================================================================
326 // Abstract class that supports the basics of IPin
327 //=====================================================================
328 //=====================================================================
330 class AM_NOVTABLE CBasePin
: public CUnknown
, public IPin
, public IQualityControl
335 WCHAR
* m_pName
; // This pin's name
336 IPin
*m_Connected
; // Pin we have connected to
337 PIN_DIRECTION m_dir
; // Direction of this pin
338 CCritSec
*m_pLock
; // Object we use for locking
339 bool m_bRunTimeError
; // Run time error generated
340 bool m_bCanReconnectWhenActive
; // OK to reconnect when active
341 bool m_bTryMyTypesFirst
; // When connecting enumerate
342 // this pin's types first
343 CBaseFilter
*m_pFilter
; // Filter we were created by
344 IQualityControl
*m_pQSink
; // Target for Quality messages
345 LONG m_TypeVersion
; // Holds current type version
346 CMediaType m_mt
; // Media type of connection
348 CRefTime m_tStart
; // time from NewSegment call
349 CRefTime m_tStop
; // time from NewSegment
350 double m_dRate
; // rate from NewSegment
353 LONG m_cRef
; // Ref count tracing
356 // displays pin connection information
359 void DisplayPinInfo(IPin
*pReceivePin
);
360 void DisplayTypeInfo(IPin
*pPin
, const CMediaType
*pmt
);
362 void DisplayPinInfo(IPin
*pReceivePin
) {};
363 void DisplayTypeInfo(IPin
*pPin
, const CMediaType
*pmt
) {};
366 // used to agree a media type for a pin connection
368 // given a specific media type, attempt a connection (includes
369 // checking that the type is acceptable to this pin)
372 IPin
* pReceivePin
, // connect to this pin
373 const CMediaType
* pmt
// using this type
376 // try all the media types in this enumerator - for each that
377 // we accept, try to connect using ReceiveConnection.
378 HRESULT
TryMediaTypes(
379 IPin
*pReceivePin
, // connect to this pin
380 const CMediaType
*pmt
, // proposed type from Connect
381 IEnumMediaTypes
*pEnum
); // try this enumerator
383 // establish a connection with a suitable mediatype. Needs to
384 // propose a media type if the pmt pointer is null or partially
385 // specified - use TryMediaTypes on both our and then the other pin's
386 // enumerator until we find one that works.
387 HRESULT
AgreeMediaType(
388 IPin
*pReceivePin
, // connect to this pin
389 const CMediaType
*pmt
); // proposed type from Connect
394 TCHAR
*pObjectName
, // Object description
395 CBaseFilter
*pFilter
, // Owning filter who knows about pins
396 CCritSec
*pLock
, // Object who implements the lock
397 HRESULT
*phr
, // General OLE return code
398 LPCWSTR pName
, // Pin name for us
399 PIN_DIRECTION dir
); // Either PINDIR_INPUT or PINDIR_OUTPUT
402 CHAR
*pObjectName
, // Object description
403 CBaseFilter
*pFilter
, // Owning filter who knows about pins
404 CCritSec
*pLock
, // Object who implements the lock
405 HRESULT
*phr
, // General OLE return code
406 LPCWSTR pName
, // Pin name for us
407 PIN_DIRECTION dir
); // Either PINDIR_INPUT or PINDIR_OUTPUT
413 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void ** ppv
);
414 STDMETHODIMP_(ULONG
) NonDelegatingRelease();
415 STDMETHODIMP_(ULONG
) NonDelegatingAddRef();
417 // --- IPin methods ---
419 // take lead role in establishing a connection. Media type pointer
420 // may be null, or may point to partially-specified mediatype
421 // (subtype or format type may be GUID_NULL).
422 STDMETHODIMP
Connect(
424 const AM_MEDIA_TYPE
*pmt
// optional media type
427 // (passive) accept a connection from another pin
428 STDMETHODIMP
ReceiveConnection(
429 IPin
* pConnector
, // this is the initiating connecting pin
430 const AM_MEDIA_TYPE
*pmt
// this is the media type we will exchange
433 STDMETHODIMP
Disconnect();
435 STDMETHODIMP
ConnectedTo(IPin
**pPin
);
437 STDMETHODIMP
ConnectionMediaType(AM_MEDIA_TYPE
*pmt
);
439 STDMETHODIMP
QueryPinInfo(
443 STDMETHODIMP
QueryDirection(
444 PIN_DIRECTION
* pPinDir
447 STDMETHODIMP
QueryId(
451 // does the pin support this media type
452 STDMETHODIMP
QueryAccept(
453 const AM_MEDIA_TYPE
*pmt
456 // return an enumerator for this pins preferred media types
457 STDMETHODIMP
EnumMediaTypes(
458 IEnumMediaTypes
**ppEnum
461 // return an array of IPin* - the pins that this pin internally connects to
462 // All pins put in the array must be AddReffed (but no others)
463 // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
464 // Default: return E_NOTIMPL
465 // The filter graph will interpret NOT_IMPL as any input pin connects to
466 // all visible output pins and vice versa.
467 // apPin can be NULL if nPin==0 (not otherwise).
468 STDMETHODIMP
QueryInternalConnections(
469 IPin
* *apPin
, // array of IPin*
470 ULONG
*nPin
// on input, the number of slots
471 // on output the number of pins
472 ) { return E_NOTIMPL
; }
474 // Called when no more data will be sent
475 STDMETHODIMP
EndOfStream(void);
477 // Begin/EndFlush still PURE
479 // NewSegment notifies of the start/stop/rate applying to the data
480 // about to be received. Default implementation records data and
482 // Override this to pass downstream.
483 STDMETHODIMP
NewSegment(
484 REFERENCE_TIME tStart
,
485 REFERENCE_TIME tStop
,
488 //================================================================================
489 // IQualityControl methods
490 //================================================================================
492 STDMETHODIMP
Notify(IBaseFilter
* pSender
, Quality q
);
494 STDMETHODIMP
SetSink(IQualityControl
* piqc
);
496 // --- helper methods ---
498 // Returns true if the pin is connected. false otherwise.
499 BOOL
IsConnected(void) {return (m_Connected
!= NULL
); };
500 // Return the pin this is connected to (if any)
501 IPin
* GetConnected() { return m_Connected
; };
503 // Check if our filter is currently stopped
505 return (m_pFilter
->m_State
== State_Stopped
);
508 // find out the current type version (used by enumerators)
509 virtual LONG
GetMediaTypeVersion();
510 void IncrementTypeVersion();
512 // switch the pin to active (paused or running) mode
513 // not an error to call this if already active
514 virtual HRESULT
Active(void);
516 // switch the pin to inactive state - may already be inactive
517 virtual HRESULT
Inactive(void);
519 // Notify of Run() from filter
520 virtual HRESULT
Run(REFERENCE_TIME tStart
);
522 // check if the pin can support this specific proposed type and format
523 virtual HRESULT
CheckMediaType(const CMediaType
*) PURE
;
525 // set the connection to use this format (previously agreed)
526 virtual HRESULT
SetMediaType(const CMediaType
*);
528 // check that the connection is ok before verifying it
529 // can be overridden eg to check what interfaces will be supported.
530 virtual HRESULT
CheckConnect(IPin
*);
532 // Set and release resources required for a connection
533 virtual HRESULT
BreakConnect();
534 virtual HRESULT
CompleteConnect(IPin
*pReceivePin
);
536 // returns the preferred formats for a pin
537 virtual HRESULT
GetMediaType(int iPosition
,CMediaType
*pMediaType
);
539 // access to NewSegment values
540 REFERENCE_TIME
CurrentStopTime() {
543 REFERENCE_TIME
CurrentStartTime() {
546 double CurrentRate() {
551 LPWSTR
Name() { return m_pName
; };
553 // Can reconnectwhen active?
554 void SetReconnectWhenActive(bool bCanReconnect
)
556 m_bCanReconnectWhenActive
= bCanReconnect
;
559 bool CanReconnectWhenActive()
561 return m_bCanReconnectWhenActive
;
565 STDMETHODIMP
DisconnectInternal();
569 //=====================================================================
570 //=====================================================================
573 // Pin enumerator class that works by calling CBaseFilter. This interface
574 // is provided by CBaseFilter::EnumPins and calls GetPinCount() and
575 // GetPin() to enumerate existing pins. Needs to be a separate object so
576 // that it can be cloned (creating an existing object at the same
577 // position in the enumeration)
579 //=====================================================================
580 //=====================================================================
582 class CEnumPins
: public IEnumPins
// The interface we support
584 int m_Position
; // Current ordinal position
585 int m_PinCount
; // Number of pins available
586 CBaseFilter
*m_pFilter
; // The filter who owns us
587 LONG m_Version
; // Pin version information
590 typedef CGenericList
<CBasePin
> CPinList
;
592 CPinList m_PinCache
; // These pointers have not been AddRef'ed and
593 // so they should not be dereferenced. They are
594 // merely kept to ID which pins have been enumerated.
600 /* If while we are retrieving a pin for example from the filter an error
601 occurs we assume that our internal state is stale with respect to the
602 filter (someone may have deleted all the pins). We can check before
603 starting whether or not the operation is likely to fail by asking the
604 filter what it's current version number is. If the filter has not
605 overriden the GetPinVersion method then this will always match */
607 BOOL
AreWeOutOfSync() {
608 return (m_pFilter
->GetPinVersion() == m_Version
? FALSE
: TRUE
);
611 /* This method performs the same operations as Reset, except is does not clear
612 the cache of pins already enumerated. */
614 STDMETHODIMP
Refresh();
619 CBaseFilter
*pFilter
,
620 CEnumPins
*pEnumPins
);
622 virtual ~CEnumPins();
625 STDMETHODIMP
QueryInterface(REFIID riid
, void **ppv
);
626 STDMETHODIMP_(ULONG
) AddRef();
627 STDMETHODIMP_(ULONG
) Release();
631 ULONG cPins
, // place this many pins...
632 IPin
** ppPins
, // ...in this array of IPin*
633 ULONG
* pcFetched
// actual count passed returned here
636 STDMETHODIMP
Skip(ULONG cPins
);
637 STDMETHODIMP
Reset();
638 STDMETHODIMP
Clone(IEnumPins
**ppEnum
);
644 //=====================================================================
645 //=====================================================================
646 // Defines CEnumMediaTypes
648 // Enumerates the preferred formats for input and output pins
649 //=====================================================================
650 //=====================================================================
652 class CEnumMediaTypes
: public IEnumMediaTypes
// The interface we support
654 int m_Position
; // Current ordinal position
655 CBasePin
*m_pPin
; // The pin who owns us
656 LONG m_Version
; // Media type version value
662 /* The media types a filter supports can be quite dynamic so we add to
663 the general IEnumXXXX interface the ability to be signaled when they
664 change via an event handle the connected filter supplies. Until the
665 Reset method is called after the state changes all further calls to
666 the enumerator (except Reset) will return E_UNEXPECTED error code */
668 BOOL
AreWeOutOfSync() {
669 return (m_pPin
->GetMediaTypeVersion() == m_Version
? FALSE
: TRUE
);
676 CEnumMediaTypes
*pEnumMediaTypes
);
678 virtual ~CEnumMediaTypes();
681 STDMETHODIMP
QueryInterface(REFIID riid
, void **ppv
);
682 STDMETHODIMP_(ULONG
) AddRef();
683 STDMETHODIMP_(ULONG
) Release();
687 ULONG cMediaTypes
, // place this many pins...
688 AM_MEDIA_TYPE
** ppMediaTypes
, // ...in this array
689 ULONG
* pcFetched
// actual count passed
692 STDMETHODIMP
Skip(ULONG cMediaTypes
);
693 STDMETHODIMP
Reset();
694 STDMETHODIMP
Clone(IEnumMediaTypes
**ppEnum
);
700 //=====================================================================
701 //=====================================================================
702 // Defines CBaseOutputPin
704 // class derived from CBasePin that can pass buffers to a connected pin
705 // that supports IMemInputPin. Supports IPin.
707 // Derive your output pin from this.
709 //=====================================================================
710 //=====================================================================
712 class AM_NOVTABLE CBaseOutputPin
: public CBasePin
717 IMemAllocator
*m_pAllocator
;
718 IMemInputPin
*m_pInputPin
; // interface on the downstreaminput pin
719 // set up in CheckConnect when we connect.
725 CBaseFilter
*pFilter
,
732 CBaseFilter
*pFilter
,
737 // override CompleteConnect() so we can negotiate an allocator
738 virtual HRESULT
CompleteConnect(IPin
*pReceivePin
);
740 // negotiate the allocator and its buffer size/count and other properties
741 // Calls DecideBufferSize to set properties
742 virtual HRESULT
DecideAllocator(IMemInputPin
* pPin
, IMemAllocator
** pAlloc
);
744 // override this to set the buffer size and count. Return an error
745 // if the size/count is not to your liking.
746 // The allocator properties passed in are those requested by the
747 // input pin - use eg the alignment and prefix members if you have
748 // no preference on these.
749 virtual HRESULT
DecideBufferSize(
750 IMemAllocator
* pAlloc
,
751 ALLOCATOR_PROPERTIES
* ppropInputRequest
754 // returns an empty sample buffer from the allocator
755 virtual HRESULT
GetDeliveryBuffer(IMediaSample
** ppSample
,
756 REFERENCE_TIME
* pStartTime
,
757 REFERENCE_TIME
* pEndTime
,
760 // deliver a filled-in sample to the connected input pin
761 // note - you need to release it after calling this. The receiving
762 // pin will addref the sample if it needs to hold it beyond the
764 virtual HRESULT
Deliver(IMediaSample
*);
766 // override this to control the connection
767 virtual HRESULT
InitAllocator(IMemAllocator
**ppAlloc
);
768 HRESULT
CheckConnect(IPin
*pPin
);
769 HRESULT
BreakConnect();
771 // override to call Commit and Decommit
772 HRESULT
Active(void);
773 HRESULT
Inactive(void);
775 // we have a default handling of EndOfStream which is to return
776 // an error, since this should be called on input pins only
777 STDMETHODIMP
EndOfStream(void);
779 // called from elsewhere in our filter to pass EOS downstream to
780 // our connected input pin
781 virtual HRESULT
DeliverEndOfStream(void);
783 // same for Begin/EndFlush - we handle Begin/EndFlush since it
784 // is an error on an output pin, and we have Deliver methods to
785 // call the methods on the connected pin
786 STDMETHODIMP
BeginFlush(void);
787 STDMETHODIMP
EndFlush(void);
788 virtual HRESULT
DeliverBeginFlush(void);
789 virtual HRESULT
DeliverEndFlush(void);
791 // deliver NewSegment to connected pin - you will need to
792 // override this if you queue any data in your output pin.
793 virtual HRESULT
DeliverNewSegment(
794 REFERENCE_TIME tStart
,
795 REFERENCE_TIME tStop
,
798 //================================================================================
799 // IQualityControl methods
800 //================================================================================
802 // All inherited from CBasePin and not overridden here.
803 // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
804 // STDMETHODIMP SetSink(IQualityControl * piqc);
808 //=====================================================================
809 //=====================================================================
810 // Defines CBaseInputPin
812 // derive your standard input pin from this.
813 // you need to supply GetMediaType and CheckConnect etc (see CBasePin),
814 // and you need to supply Receive to do something more useful.
816 //=====================================================================
817 //=====================================================================
819 class AM_NOVTABLE CBaseInputPin
: public CBasePin
,
825 IMemAllocator
*m_pAllocator
; // Default memory allocator
827 // allocator is read-only, so received samples
828 // cannot be modified (probably only relevant to in-place
832 // in flushing state (between BeginFlush and EndFlush)
833 // if TRUE, all Receives are returned with S_FALSE
836 // Sample properties - initalized in Receive
837 AM_SAMPLE2_PROPERTIES m_SampleProps
;
843 CBaseFilter
*pFilter
,
850 CBaseFilter
*pFilter
,
855 virtual ~CBaseInputPin();
859 // override this to publicise our interfaces
860 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void **ppv
);
862 // return the allocator interface that this input pin
863 // would like the output pin to use
864 STDMETHODIMP
GetAllocator(IMemAllocator
** ppAllocator
);
866 // tell the input pin which allocator the output pin is actually
868 STDMETHODIMP
NotifyAllocator(
869 IMemAllocator
* pAllocator
,
872 // do something with this media sample
873 STDMETHODIMP
Receive(IMediaSample
*pSample
);
875 // do something with these media samples
876 STDMETHODIMP
ReceiveMultiple (
877 IMediaSample
**pSamples
,
879 long *nSamplesProcessed
);
881 // See if Receive() blocks
882 STDMETHODIMP
ReceiveCanBlock();
884 // Default handling for BeginFlush - call at the beginning
885 // of your implementation (makes sure that all Receive calls
886 // fail). After calling this, you need to free any queued data
887 // and then call downstream.
888 STDMETHODIMP
BeginFlush(void);
890 // default handling for EndFlush - call at end of your implementation
891 // - before calling this, ensure that there is no queued data and no thread
892 // pushing any more without a further receive, then call downstream,
893 // then call this method to clear the m_bFlushing flag and re-enable
895 STDMETHODIMP
EndFlush(void);
897 // this method is optional (can return E_NOTIMPL).
898 // default implementation returns E_NOTIMPL. Override if you have
899 // specific alignment or prefix needs, but could use an upstream
901 STDMETHODIMP
GetAllocatorRequirements(ALLOCATOR_PROPERTIES
*pProps
);
903 // Release the pin's allocator.
904 HRESULT
BreakConnect();
906 // helper method to check the read-only flag
911 // helper method to see if we are flushing
916 // Override this for checking whether it's OK to process samples
917 // Also call this from EndOfStream.
918 virtual HRESULT
CheckStreaming();
920 // Pass a Quality notification on to the appropriate sink
921 HRESULT
PassNotify(Quality
& q
);
924 //================================================================================
925 // IQualityControl methods (from CBasePin)
926 //================================================================================
928 STDMETHODIMP
Notify(IBaseFilter
* pSender
, Quality q
);
930 // no need to override:
931 // STDMETHODIMP SetSink(IQualityControl * piqc);
934 // switch the pin to inactive state - may already be inactive
935 virtual HRESULT
Inactive(void);
937 // Return sample properties pointer
938 AM_SAMPLE2_PROPERTIES
* SampleProps() {
939 ASSERT(m_SampleProps
.cbData
!= 0);
940 return &m_SampleProps
;
945 ///////////////////////////////////////////////////////////////////////////
949 class CDynamicOutputPin
: public CBaseOutputPin
,
950 public IPinFlowControl
956 CBaseFilter
*pFilter
,
964 CBaseFilter
*pFilter
,
969 ~CDynamicOutputPin();
973 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void **ppv
);
976 STDMETHODIMP
Disconnect(void);
978 // IPinFlowControl Methods
979 STDMETHODIMP
Block(DWORD dwBlockFlags
, HANDLE hEvent
);
981 // Set graph config info
982 void SetConfigInfo(IGraphConfig
*pGraphConfig
, HANDLE hStopEvent
);
985 virtual HRESULT
Deliver(IMediaSample
*pSample
);
986 virtual HRESULT
DeliverEndOfStream(void);
987 virtual HRESULT
DeliverNewSegment(REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
);
990 HRESULT
DeliverBeginFlush(void);
991 HRESULT
DeliverEndFlush(void);
993 HRESULT
Inactive(void);
994 HRESULT
Active(void);
995 virtual HRESULT
CompleteConnect(IPin
*pReceivePin
);
997 virtual HRESULT
StartUsingOutputPin(void);
998 virtual void StopUsingOutputPin(void);
999 virtual bool StreamingThreadUsingOutputPin(void);
1001 HRESULT ChangeOutputFormat
1003 const AM_MEDIA_TYPE
*pmt
,
1004 REFERENCE_TIME tSegmentStart
,
1005 REFERENCE_TIME tSegmentStop
,
1008 HRESULT
ChangeMediaType(const CMediaType
*pmt
);
1009 HRESULT
DynamicReconnect(const CMediaType
*pmt
);
1012 HRESULT
SynchronousBlockOutputPin(void);
1013 HRESULT
AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent
);
1014 HRESULT
UnblockOutputPin(void);
1016 void BlockOutputPin(void);
1017 void ResetBlockState(void);
1019 static HRESULT
WaitEvent(HANDLE hEvent
);
1028 // This lock should be held when the following class members are
1029 // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
1030 // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
1031 CCritSec m_BlockStateLock
;
1033 // This event should be signaled when the output pin is
1034 // not blocked. This is a manual reset event. For more
1035 // information on events, see the documentation for
1036 // CreateEvent() in the Windows SDK.
1037 HANDLE m_hUnblockOutputPinEvent
;
1039 // This event will be signaled when block operation succeedes or
1040 // when the user cancels the block operation. The block operation
1041 // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
1042 // while the block operation is pending.
1043 HANDLE m_hNotifyCallerPinBlockedEvent
;
1045 // The state of the current block operation.
1046 BLOCK_STATE m_BlockState
;
1048 // The ID of the thread which last called IPinFlowControl::Block().
1049 // For more information on thread IDs, see the documentation for
1050 // GetCurrentThreadID() in the Windows SDK.
1051 DWORD m_dwBlockCallerThreadID
;
1053 // The number of times StartUsingOutputPin() has been sucessfully
1054 // called and a corresponding call to StopUsingOutputPin() has not
1055 // been made. When this variable is greater than 0, the streaming
1056 // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
1057 // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple(). The
1058 // streaming thread could also be calling: DynamicReconnect(),
1059 // ChangeMediaType() or ChangeOutputFormat(). The output pin cannot
1060 // be blocked while the output pin is being used.
1061 DWORD m_dwNumOutstandingOutputPinUsers
;
1063 // This event should be set when the IMediaFilter::Stop() is called.
1064 // This is a manual reset event. It is also set when the output pin
1065 // delivers a flush to the connected input pin.
1066 HANDLE m_hStopEvent
;
1067 IGraphConfig
* m_pGraphConfig
;
1069 // TRUE if the output pin's allocator's samples are read only.
1070 // Otherwise FALSE. For more information, see the documentation
1071 // for IMemInputPin::NotifyAllocator().
1072 BOOL m_bPinUsesReadOnlyAllocator
;
1075 HRESULT
Initialize(void);
1076 HRESULT
ChangeMediaTypeHelper(const CMediaType
*pmt
);
1079 void AssertValid(void);
1083 class CAutoUsingOutputPin
1086 CAutoUsingOutputPin( CDynamicOutputPin
* pOutputPin
, HRESULT
* phr
);
1087 ~CAutoUsingOutputPin();
1090 CDynamicOutputPin
* m_pOutputPin
;
1093 inline CAutoUsingOutputPin::CAutoUsingOutputPin( CDynamicOutputPin
* pOutputPin
, HRESULT
* phr
) :
1096 // The caller should always pass in valid pointers.
1097 ASSERT( NULL
!= pOutputPin
);
1098 ASSERT( NULL
!= phr
);
1100 // Make sure the user initialized phr.
1101 ASSERT( S_OK
== *phr
);
1103 HRESULT hr
= pOutputPin
->StartUsingOutputPin();
1110 m_pOutputPin
= pOutputPin
;
1113 inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
1115 if( NULL
!= m_pOutputPin
)
1117 m_pOutputPin
->StopUsingOutputPin();
1123 inline HRESULT
CDynamicOutputPin::Deliver(IMediaSample
*pSample
)
1125 // The caller should call StartUsingOutputPin() before calling this
1127 ASSERT(StreamingThreadUsingOutputPin());
1129 return CBaseOutputPin::Deliver(pSample
);
1132 inline HRESULT
CDynamicOutputPin::DeliverEndOfStream(void)
1134 // The caller should call StartUsingOutputPin() before calling this
1136 ASSERT( StreamingThreadUsingOutputPin() );
1138 return CBaseOutputPin::DeliverEndOfStream();
1141 inline HRESULT
CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
1143 // The caller should call StartUsingOutputPin() before calling this
1145 ASSERT(StreamingThreadUsingOutputPin());
1147 return CBaseOutputPin::DeliverNewSegment(tStart
, tStop
, dRate
);
1152 //=====================================================================
1153 //=====================================================================
1154 // Memory allocators
1156 // the shared memory transport between pins requires the input pin
1157 // to provide a memory allocator that can provide sample objects. A
1158 // sample object supports the IMediaSample interface.
1160 // CBaseAllocator handles the management of free and busy samples. It
1161 // allocates CMediaSample objects. CBaseAllocator is an abstract class:
1162 // in particular it has no method of initializing the list of free
1163 // samples. CMemAllocator is derived from CBaseAllocator and initializes
1164 // the list of samples using memory from the standard IMalloc interface.
1166 // If you want your buffers to live in some special area of memory,
1167 // derive your allocator object from CBaseAllocator. If you derive your
1168 // IMemInputPin interface object from CBaseMemInputPin, you will get
1169 // CMemAllocator-based allocation etc for free and will just need to
1170 // supply the Receive handling, and media type / format negotiation.
1171 //=====================================================================
1172 //=====================================================================
1175 //=====================================================================
1176 //=====================================================================
1177 // Defines CMediaSample
1179 // an object of this class supports IMediaSample and represents a buffer
1180 // for media data with some associated properties. Releasing it returns
1181 // it to a freelist managed by a CBaseAllocator derived object.
1182 //=====================================================================
1183 //=====================================================================
1185 class CMediaSample
: public IMediaSample2
// The interface we support
1190 friend class CBaseAllocator
;
1192 /* Values for dwFlags - these are used for backward compatiblity
1193 only now - use AM_SAMPLE_xxx
1195 enum { Sample_SyncPoint
= 0x01, /* Is this a sync point */
1196 Sample_Preroll
= 0x02, /* Is this a preroll sample */
1197 Sample_Discontinuity
= 0x04, /* Set if start of new segment */
1198 Sample_TypeChanged
= 0x08, /* Has the type changed */
1199 Sample_TimeValid
= 0x10, /* Set if time is valid */
1200 Sample_MediaTimeValid
= 0x20, /* Is the media time valid */
1201 Sample_TimeDiscontinuity
= 0x40, /* Time discontinuity */
1202 Sample_StopValid
= 0x100, /* Stop time valid */
1203 Sample_ValidFlags
= 0x1FF
1206 /* Properties, the media sample class can be a container for a format
1207 change in which case we take a copy of a type through the SetMediaType
1208 interface function and then return it when GetMediaType is called. As
1209 we do no internal processing on it we leave it as a pointer */
1211 DWORD m_dwFlags
; /* Flags for this sample */
1212 /* Type specific flags are packed
1215 DWORD m_dwTypeSpecificFlags
; /* Media type specific flags */
1216 LPBYTE m_pBuffer
; /* Pointer to the complete buffer */
1217 LONG m_lActual
; /* Length of data in this sample */
1218 LONG m_cbBuffer
; /* Size of the buffer */
1219 CBaseAllocator
*m_pAllocator
; /* The allocator who owns us */
1220 CMediaSample
*m_pNext
; /* Chaining in free list */
1221 REFERENCE_TIME m_Start
; /* Start sample time */
1222 REFERENCE_TIME m_End
; /* End sample time */
1223 LONGLONG m_MediaStart
; /* Real media start position */
1224 LONG m_MediaEnd
; /* A difference to get the end */
1225 AM_MEDIA_TYPE
*m_pMediaType
; /* Media type change data */
1226 DWORD m_dwStreamId
; /* Stream id */
1228 LONG m_cRef
; /* Reference count */
1235 CBaseAllocator
*pAllocator
,
1237 LPBYTE pBuffer
= NULL
,
1242 CBaseAllocator
*pAllocator
,
1244 LPBYTE pBuffer
= NULL
,
1248 virtual ~CMediaSample();
1250 /* Note the media sample does not delegate to its owner */
1252 STDMETHODIMP
QueryInterface(REFIID riid
, void **ppv
);
1253 STDMETHODIMP_(ULONG
) AddRef();
1254 STDMETHODIMP_(ULONG
) Release();
1256 // set the buffer pointer and length. Used by allocators that
1257 // want variable sized pointers or pointers into already-read data.
1258 // This is only available through a CMediaSample* not an IMediaSample*
1259 // and so cannot be changed by clients.
1260 HRESULT
SetPointer(BYTE
* ptr
, LONG cBytes
);
1262 // Get me a read/write pointer to this buffer's memory.
1263 STDMETHODIMP
GetPointer(BYTE
** ppBuffer
);
1265 STDMETHODIMP_(LONG
) GetSize(void);
1267 // get the stream time at which this sample should start and finish.
1268 STDMETHODIMP
GetTime(
1269 REFERENCE_TIME
* pTimeStart
, // put time here
1270 REFERENCE_TIME
* pTimeEnd
1273 // Set the stream time at which this sample should start and finish.
1274 STDMETHODIMP
SetTime(
1275 REFERENCE_TIME
* pTimeStart
, // put time here
1276 REFERENCE_TIME
* pTimeEnd
1278 STDMETHODIMP
IsSyncPoint(void);
1279 STDMETHODIMP
SetSyncPoint(BOOL bIsSyncPoint
);
1280 STDMETHODIMP
IsPreroll(void);
1281 STDMETHODIMP
SetPreroll(BOOL bIsPreroll
);
1283 STDMETHODIMP_(LONG
) GetActualDataLength(void);
1284 STDMETHODIMP
SetActualDataLength(LONG lActual
);
1286 // these allow for limited format changes in band
1288 STDMETHODIMP
GetMediaType(AM_MEDIA_TYPE
**ppMediaType
);
1289 STDMETHODIMP
SetMediaType(AM_MEDIA_TYPE
*pMediaType
);
1291 // returns S_OK if there is a discontinuity in the data (this same is
1292 // not a continuation of the previous stream of data
1293 // - there has been a seek).
1294 STDMETHODIMP
IsDiscontinuity(void);
1295 // set the discontinuity property - TRUE if this sample is not a
1296 // continuation, but a new sample after a seek.
1297 STDMETHODIMP
SetDiscontinuity(BOOL bDiscontinuity
);
1299 // get the media times for this sample
1300 STDMETHODIMP
GetMediaTime(
1301 LONGLONG
* pTimeStart
,
1305 // Set the media times for this sample
1306 STDMETHODIMP
SetMediaTime(
1307 LONGLONG
* pTimeStart
,
1311 // Set and get properties (IMediaSample2)
1312 STDMETHODIMP
GetProperties(
1317 STDMETHODIMP
SetProperties(
1319 const BYTE
* pbProperties
1324 //=====================================================================
1325 //=====================================================================
1326 // Defines CBaseAllocator
1328 // Abstract base class that manages a list of media samples
1330 // This class provides support for getting buffers from the free list,
1331 // including handling of commit and (asynchronous) decommit.
1333 // Derive from this class and override the Alloc and Free functions to
1334 // allocate your CMediaSample (or derived) objects and add them to the
1335 // free list, preparing them as necessary.
1336 //=====================================================================
1337 //=====================================================================
1339 class AM_NOVTABLE CBaseAllocator
: public CUnknown
,// A non delegating IUnknown
1340 public IMemAllocatorCallbackTemp
, // The interface we support
1341 public CCritSec
// Provides object locking
1344 friend class CSampleList
;
1346 /* Trick to get at protected member in CMediaSample */
1347 static CMediaSample
* &NextSample(CMediaSample
*pSample
)
1349 return pSample
->m_pNext
;
1352 /* Mini list class for the free list */
1356 CSampleList() : m_List(NULL
), m_nOnList(0) {};
1360 ASSERT(m_nOnList
== 0);
1363 CMediaSample
*Head() const { return m_List
; };
1364 CMediaSample
*Next(CMediaSample
*pSample
) const { return CBaseAllocator::NextSample(pSample
); };
1365 int GetCount() const { return m_nOnList
; };
1366 void Add(CMediaSample
*pSample
)
1368 ASSERT(pSample
!= NULL
);
1369 CBaseAllocator::NextSample(pSample
) = m_List
;
1373 CMediaSample
*RemoveHead()
1375 CMediaSample
*pSample
= m_List
;
1376 if (pSample
!= NULL
) {
1377 m_List
= CBaseAllocator::NextSample(m_List
);
1382 void Remove(CMediaSample
*pSample
);
1385 CMediaSample
*m_List
;
1390 CSampleList m_lFree
; // Free list
1392 /* Note to overriders of CBaseAllocator.
1394 We use a lazy signalling mechanism for waiting for samples.
1395 This means we don't call the OS if no waits occur.
1397 In order to implement this:
1399 1. When a new sample is added to m_lFree call NotifySample() which
1400 calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
1401 sets m_lWaiting to 0.
1402 This must all be done holding the allocator's critical section.
1404 2. When waiting for a sample call SetWaiting() which increments
1405 m_lWaiting BEFORE leaving the allocator's critical section.
1407 3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
1408 having left the allocator's critical section. The effect of
1409 this is to remove 1 from the semaphore's count. You MUST call
1410 this once having incremented m_lWaiting.
1412 The following are then true when the critical section is not held :
1413 (let nWaiting = number about to wait or waiting)
1415 (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
1416 (2) m_lWaiting + Semaphore count == nWaiting
1418 We would deadlock if
1420 m_lFree.GetCount() != 0 &&
1421 Semaphore count == 0
1423 But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
1424 from (2) Semaphore count == nWaiting (which is non-0) so the
1425 deadlock can't happen.
1428 HANDLE m_hSem
; // For signalling
1429 long m_lWaiting
; // Waiting for a free element
1430 long m_lCount
; // how many buffers we have agreed to provide
1431 long m_lAllocated
; // how many buffers are currently allocated
1432 long m_lSize
; // agreed size of each buffer
1433 long m_lAlignment
; // agreed alignment
1434 long m_lPrefix
; // agreed prefix (preceeds GetPointer() value)
1435 BOOL m_bChanged
; // Have the buffer requirements changed
1437 // if true, we are decommitted and can't allocate memory
1439 // if true, the decommit has happened, but we haven't called Free yet
1440 // as there are still outstanding buffers
1441 BOOL m_bDecommitInProgress
;
1443 // Notification interface
1444 IMemAllocatorNotifyCallbackTemp
*m_pNotify
;
1446 BOOL m_fEnableReleaseCallback
;
1448 // called to decommit the memory when the last buffer is freed
1449 // pure virtual - need to override this
1450 virtual void Free(void) PURE
;
1452 // override to allocate the memory when commit called
1453 virtual HRESULT
Alloc(void);
1458 TCHAR
*, LPUNKNOWN
, HRESULT
*,
1459 BOOL bEvent
= TRUE
, BOOL fEnableReleaseCallback
= FALSE
);
1462 CHAR
*, LPUNKNOWN
, HRESULT
*,
1463 BOOL bEvent
= TRUE
, BOOL fEnableReleaseCallback
= FALSE
);
1465 virtual ~CBaseAllocator();
1469 // override this to publicise our interfaces
1470 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void **ppv
);
1472 STDMETHODIMP
SetProperties(
1473 ALLOCATOR_PROPERTIES
* pRequest
,
1474 ALLOCATOR_PROPERTIES
* pActual
);
1476 // return the properties actually being used on this allocator
1477 STDMETHODIMP
GetProperties(
1478 ALLOCATOR_PROPERTIES
* pProps
);
1480 // override Commit to allocate memory. We handle the GetBuffer
1482 STDMETHODIMP
Commit();
1484 // override this to handle the memory freeing. We handle any outstanding
1486 STDMETHODIMP
Decommit();
1488 // get container for a sample. Blocking, synchronous call to get the
1489 // next free buffer (as represented by an IMediaSample interface).
1490 // on return, the time etc properties will be invalid, but the buffer
1491 // pointer and size will be correct. The two time parameters are
1492 // optional and either may be NULL, they may alternatively be set to
1493 // the start and end times the sample will have attached to it
1494 // bPrevFramesSkipped is not used (used only by the video renderer's
1495 // allocator where it affects quality management in direct draw).
1497 STDMETHODIMP
GetBuffer(IMediaSample
**ppBuffer
,
1498 REFERENCE_TIME
* pStartTime
,
1499 REFERENCE_TIME
* pEndTime
,
1502 // final release of a CMediaSample will call this
1503 STDMETHODIMP
ReleaseBuffer(IMediaSample
*pBuffer
);
1504 // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
1506 STDMETHODIMP
SetNotify(IMemAllocatorNotifyCallbackTemp
*pNotify
);
1508 STDMETHODIMP
GetFreeCount(LONG
*plBuffersFree
);
1510 // Notify that a sample is available
1511 void NotifySample();
1513 // Notify that we're waiting for a sample
1514 void SetWaiting() { m_lWaiting
++; };
1518 //=====================================================================
1519 //=====================================================================
1520 // Defines CMemAllocator
1522 // this is an allocator based on CBaseAllocator that allocates sample
1523 // buffers in main memory (from 'new'). You must call SetProperties
1524 // before calling Commit.
1526 // we don't free the memory when going into Decommit state. The simplest
1527 // way to implement this without complicating CBaseAllocator is to
1528 // have a Free() function, called to go into decommit state, that does
1529 // nothing and a ReallyFree function called from our destructor that
1530 // actually frees the memory.
1531 //=====================================================================
1532 //=====================================================================
1534 // Make me one from quartz.dll
1535 STDAPI
CreateMemoryAllocator(IMemAllocator
**ppAllocator
);
1537 class CMemAllocator
: public CBaseAllocator
1542 LPBYTE m_pBuffer
; // combined memory for all buffers
1544 // override to free the memory when decommit completes
1545 // - we actually do nothing, and save the memory until deletion.
1548 // called from the destructor (and from Alloc if changing size/count) to
1549 // actually free up the memory
1550 void ReallyFree(void);
1552 // overriden to allocate the memory when commit called
1553 HRESULT
Alloc(void);
1556 /* This goes in the factory template table to create new instances */
1557 static CUnknown
*CreateInstance(LPUNKNOWN
, HRESULT
*);
1559 STDMETHODIMP
SetProperties(
1560 ALLOCATOR_PROPERTIES
* pRequest
,
1561 ALLOCATOR_PROPERTIES
* pActual
);
1563 CMemAllocator(TCHAR
*, LPUNKNOWN
, HRESULT
*);
1565 CMemAllocator(CHAR
*, LPUNKNOWN
, HRESULT
*);
1570 // helper used by IAMovieSetup implementation
1572 AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER
* const psetupdata
1573 , IFilterMapper
* pIFM
1577 ///////////////////////////////////////////////////////////////////////////
1578 // ------------------------------------------------------------------------
1579 // ------------------------------------------------------------------------
1580 // ------------------------------------------------------------------------
1581 // ------------------------------------------------------------------------
1582 ///////////////////////////////////////////////////////////////////////////
1584 #endif /* __FILTER__ */