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