Update UNRAR.H
[xy_vsfilter.git] / src / filters / BaseClasses / amfilter.h
blob6d8267a69c24c85f88067d378fc675bf687521f1
1 //------------------------------------------------------------------------------
2 // File: AMFilter.h
3 //
4 // Desc: DirectShow base classes - efines class hierarchy for streams
5 // architecture.
6 //
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
11 #ifndef __FILTER__
12 #define __FILTER__
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
52 // class id.
53 //=====================================================================
54 //=====================================================================
56 class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
57 public IMediaFilter
60 protected:
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
67 CRefTime m_tStart;
69 CLSID m_clsid; // This filters clsid
70 // used for serialization
71 CCritSec *m_pLock; // Object we use for locking
73 public:
75 CBaseMediaFilter(
76 const TCHAR *pName,
77 LPUNKNOWN pUnk,
78 CCritSec *pLock,
79 REFCLSID clsid);
81 virtual ~CBaseMediaFilter();
83 DECLARE_IUNKNOWN
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.
107 STDMETHODIMP Stop();
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
113 // its presentation
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)
123 BOOL IsActive() {
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
143 // CTransformFilter.
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;
155 protected:
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
168 public:
170 CBaseFilter(
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
176 CBaseFilter(
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
182 #ifdef UNICODE
183 CBaseFilter(
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
189 CBaseFilter(
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
195 #endif
196 ~CBaseFilter();
198 DECLARE_IUNKNOWN
200 // override this to say what interfaces we support where
201 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
202 #ifdef DEBUG
203 STDMETHODIMP_(ULONG) NonDelegatingRelease();
204 #endif
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
224 // your pins.
225 STDMETHODIMP Stop();
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
230 // its presentation
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?
240 BOOL IsActive() {
241 CAutoLock cObjectLock(m_pLock);
242 return ((m_State == State_Paused) || (m_State == State_Running));
245 // Is this filter stopped (without locking)
246 BOOL IsStopped() {
247 return (m_State == State_Stopped);
251 // --- IBaseFilter methods ---
254 // pin enumerator
255 STDMETHODIMP EnumPins(
256 IEnumPins ** ppEnum);
259 // default behaviour of FindPin assumes pin ids are their names
260 STDMETHODIMP FindPin(
261 LPCWSTR Id,
262 IPin ** ppPin
265 STDMETHODIMP QueryFilterInfo(
266 FILTER_INFO * pInfo);
268 STDMETHODIMP JoinFilterGraph(
269 IFilterGraph * pGraph,
270 LPCWSTR pName);
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(
276 LPWSTR* pVendorInfo
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.
284 HRESULT NotifyEvent(
285 long EventCode,
286 LONG_PTR EventParam1,
287 LONG_PTR EventParam2);
289 // return the filter graph we belong to
290 IFilterGraph *GetFilterGraph() {
291 return m_pGraph;
294 // Request reconnect
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 //=====================================================================
324 // Defines CBasePin
326 // Abstract class that supports the basics of IPin
327 //=====================================================================
328 //=====================================================================
330 class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
333 protected:
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
352 #ifdef DEBUG
353 LONG m_cRef; // Ref count tracing
354 #endif
356 // displays pin connection information
358 #ifdef DEBUG
359 void DisplayPinInfo(IPin *pReceivePin);
360 void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
361 #else
362 void DisplayPinInfo(IPin *pReceivePin) {};
363 void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
364 #endif
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)
370 HRESULT
371 AttemptConnection(
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
391 public:
393 CBasePin(
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
400 #ifdef UNICODE
401 CBasePin(
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
408 #endif
409 virtual ~CBasePin();
411 DECLARE_IUNKNOWN
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(
423 IPin * pReceivePin,
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(
440 PIN_INFO * pInfo
443 STDMETHODIMP QueryDirection(
444 PIN_DIRECTION * pPinDir
447 STDMETHODIMP QueryId(
448 LPWSTR * Id
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
481 // returns S_OK.
482 // Override this to pass downstream.
483 STDMETHODIMP NewSegment(
484 REFERENCE_TIME tStart,
485 REFERENCE_TIME tStop,
486 double dRate);
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
504 BOOL IsStopped() {
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() {
541 return m_tStop;
543 REFERENCE_TIME CurrentStartTime() {
544 return m_tStart;
546 double CurrentRate() {
547 return m_dRate;
550 // Access name
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;
564 protected:
565 STDMETHODIMP DisconnectInternal();
569 //=====================================================================
570 //=====================================================================
571 // Defines CEnumPins
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
588 LONG m_cRef;
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.
596 #ifdef DEBUG
597 DWORD m_dwCookie;
598 #endif
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();
616 public:
618 CEnumPins(
619 CBaseFilter *pFilter,
620 CEnumPins *pEnumPins);
622 virtual ~CEnumPins();
624 // IUnknown
625 STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
626 STDMETHODIMP_(ULONG) AddRef();
627 STDMETHODIMP_(ULONG) Release();
629 // IEnumPins
630 STDMETHODIMP Next(
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
657 LONG m_cRef;
658 #ifdef DEBUG
659 DWORD m_dwCookie;
660 #endif
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);
672 public:
674 CEnumMediaTypes(
675 CBasePin *pPin,
676 CEnumMediaTypes *pEnumMediaTypes);
678 virtual ~CEnumMediaTypes();
680 // IUnknown
681 STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
682 STDMETHODIMP_(ULONG) AddRef();
683 STDMETHODIMP_(ULONG) Release();
685 // IEnumMediaTypes
686 STDMETHODIMP Next(
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
715 protected:
717 IMemAllocator *m_pAllocator;
718 IMemInputPin *m_pInputPin; // interface on the downstreaminput pin
719 // set up in CheckConnect when we connect.
721 public:
723 CBaseOutputPin(
724 TCHAR *pObjectName,
725 CBaseFilter *pFilter,
726 CCritSec *pLock,
727 HRESULT *phr,
728 LPCWSTR pName);
729 #ifdef UNICODE
730 CBaseOutputPin(
731 CHAR *pObjectName,
732 CBaseFilter *pFilter,
733 CCritSec *pLock,
734 HRESULT *phr,
735 LPCWSTR pName);
736 #endif
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
752 ) PURE;
754 // returns an empty sample buffer from the allocator
755 virtual HRESULT GetDeliveryBuffer(IMediaSample ** ppSample,
756 REFERENCE_TIME * pStartTime,
757 REFERENCE_TIME * pEndTime,
758 DWORD dwFlags);
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
763 // call.
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,
796 double dRate);
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,
820 public IMemInputPin
823 protected:
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
829 // transforms
830 BYTE m_bReadOnly;
832 // in flushing state (between BeginFlush and EndFlush)
833 // if TRUE, all Receives are returned with S_FALSE
834 BYTE m_bFlushing;
836 // Sample properties - initalized in Receive
837 AM_SAMPLE2_PROPERTIES m_SampleProps;
839 public:
841 CBaseInputPin(
842 TCHAR *pObjectName,
843 CBaseFilter *pFilter,
844 CCritSec *pLock,
845 HRESULT *phr,
846 LPCWSTR pName);
847 #ifdef UNICODE
848 CBaseInputPin(
849 CHAR *pObjectName,
850 CBaseFilter *pFilter,
851 CCritSec *pLock,
852 HRESULT *phr,
853 LPCWSTR pName);
854 #endif
855 virtual ~CBaseInputPin();
857 DECLARE_IUNKNOWN
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
867 // going to use.
868 STDMETHODIMP NotifyAllocator(
869 IMemAllocator * pAllocator,
870 BOOL bReadOnly);
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,
878 long nSamples,
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
894 // receives
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
900 // allocator
901 STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);
903 // Release the pin's allocator.
904 HRESULT BreakConnect();
906 // helper method to check the read-only flag
907 BOOL IsReadOnly() {
908 return m_bReadOnly;
911 // helper method to see if we are flushing
912 BOOL IsFlushing() {
913 return m_bFlushing;
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 ///////////////////////////////////////////////////////////////////////////
946 // CDynamicOutputPin
949 class CDynamicOutputPin : public CBaseOutputPin,
950 public IPinFlowControl
952 public:
953 #ifdef UNICODE
954 CDynamicOutputPin(
955 CHAR *pObjectName,
956 CBaseFilter *pFilter,
957 CCritSec *pLock,
958 HRESULT *phr,
959 LPCWSTR pName);
960 #endif
962 CDynamicOutputPin(
963 TCHAR *pObjectName,
964 CBaseFilter *pFilter,
965 CCritSec *pLock,
966 HRESULT *phr,
967 LPCWSTR pName);
969 ~CDynamicOutputPin();
971 // IUnknown Methods
972 DECLARE_IUNKNOWN
973 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
975 // IPin Methods
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);
984 #ifdef DEBUG
985 virtual HRESULT Deliver(IMediaSample *pSample);
986 virtual HRESULT DeliverEndOfStream(void);
987 virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
988 #endif // DEBUG
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,
1006 double dSegmentRate
1008 HRESULT ChangeMediaType(const CMediaType *pmt);
1009 HRESULT DynamicReconnect(const CMediaType *pmt);
1011 protected:
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);
1021 enum BLOCK_STATE
1023 NOT_BLOCKED,
1024 PENDING,
1025 BLOCKED
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;
1074 private:
1075 HRESULT Initialize(void);
1076 HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
1078 #ifdef DEBUG
1079 void AssertValid(void);
1080 #endif // DEBUG
1083 class CAutoUsingOutputPin
1085 public:
1086 CAutoUsingOutputPin( CDynamicOutputPin* pOutputPin, HRESULT* phr );
1087 ~CAutoUsingOutputPin();
1089 private:
1090 CDynamicOutputPin* m_pOutputPin;
1093 inline CAutoUsingOutputPin::CAutoUsingOutputPin( CDynamicOutputPin* pOutputPin, HRESULT* phr ) :
1094 m_pOutputPin(NULL)
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();
1104 if( FAILED( hr ) )
1106 *phr = hr;
1107 return;
1110 m_pOutputPin = pOutputPin;
1113 inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
1115 if( NULL != m_pOutputPin )
1117 m_pOutputPin->StopUsingOutputPin();
1121 #ifdef DEBUG
1123 inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
1125 // The caller should call StartUsingOutputPin() before calling this
1126 // method.
1127 ASSERT(StreamingThreadUsingOutputPin());
1129 return CBaseOutputPin::Deliver(pSample);
1132 inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
1134 // The caller should call StartUsingOutputPin() before calling this
1135 // method.
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
1144 // method.
1145 ASSERT(StreamingThreadUsingOutputPin());
1147 return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
1150 #endif // DEBUG
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
1188 protected:
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
1213 into the top word
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 */
1227 public:
1228 LONG m_cRef; /* Reference count */
1231 public:
1233 CMediaSample(
1234 TCHAR *pName,
1235 CBaseAllocator *pAllocator,
1236 HRESULT *phr,
1237 LPBYTE pBuffer = NULL,
1238 LONG length = 0);
1239 #ifdef UNICODE
1240 CMediaSample(
1241 CHAR *pName,
1242 CBaseAllocator *pAllocator,
1243 HRESULT *phr,
1244 LPBYTE pBuffer = NULL,
1245 LONG length = 0);
1246 #endif
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,
1302 LONGLONG * pTimeEnd
1305 // Set the media times for this sample
1306 STDMETHODIMP SetMediaTime(
1307 LONGLONG * pTimeStart,
1308 LONGLONG * pTimeEnd
1311 // Set and get properties (IMediaSample2)
1312 STDMETHODIMP GetProperties(
1313 DWORD cbProperties,
1314 BYTE * pbProperties
1317 STDMETHODIMP SetProperties(
1318 DWORD cbProperties,
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
1343 class CSampleList;
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 */
1353 class CSampleList
1355 public:
1356 CSampleList() : m_List(NULL), m_nOnList(0) {};
1357 #ifdef DEBUG
1358 ~CSampleList()
1360 ASSERT(m_nOnList == 0);
1362 #endif
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;
1370 m_List = pSample;
1371 m_nOnList++;
1373 CMediaSample *RemoveHead()
1375 CMediaSample *pSample = m_List;
1376 if (pSample != NULL) {
1377 m_List = CBaseAllocator::NextSample(m_List);
1378 m_nOnList--;
1380 return pSample;
1382 void Remove(CMediaSample *pSample);
1384 public:
1385 CMediaSample *m_List;
1386 int m_nOnList;
1388 protected:
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
1419 nWaiting != 0 &&
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
1438 BOOL m_bCommitted;
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);
1455 public:
1457 CBaseAllocator(
1458 TCHAR *, LPUNKNOWN, HRESULT *,
1459 BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
1460 #ifdef UNICODE
1461 CBaseAllocator(
1462 CHAR *, LPUNKNOWN, HRESULT *,
1463 BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
1464 #endif
1465 virtual ~CBaseAllocator();
1467 DECLARE_IUNKNOWN
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
1481 //state changes
1482 STDMETHODIMP Commit();
1484 // override this to handle the memory freeing. We handle any outstanding
1485 // GetBuffer calls
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,
1500 DWORD dwFlags);
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
1540 protected:
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.
1546 void Free(void);
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);
1555 public:
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 *);
1564 #ifdef UNICODE
1565 CMemAllocator(CHAR *, LPUNKNOWN, HRESULT *);
1566 #endif
1567 ~CMemAllocator();
1570 // helper used by IAMovieSetup implementation
1571 STDAPI
1572 AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
1573 , IFilterMapper * pIFM
1574 , BOOL bRegister );
1577 ///////////////////////////////////////////////////////////////////////////
1578 // ------------------------------------------------------------------------
1579 // ------------------------------------------------------------------------
1580 // ------------------------------------------------------------------------
1581 // ------------------------------------------------------------------------
1582 ///////////////////////////////////////////////////////////////////////////
1584 #endif /* __FILTER__ */