My Project
ctlutil.h
1 //------------------------------------------------------------------------------
2 // File: CtlUtil.h
3 //
4 // Desc: DirectShow base classes.
5 //
6 // Copyright (c) Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
8 
9 
10 // Base classes implementing IDispatch parsing for the basic control dual
11 // interfaces. Derive from these and implement just the custom method and
12 // property methods. We also implement CPosPassThru that can be used by
13 // renderers and transforms to pass by IMediaPosition and IMediaSeeking
14 #pragma once
15 
16 #ifndef __CTLUTIL__
17 #define __CTLUTIL__
18 
19 // OLE Automation has different ideas of TRUE and FALSE
20 
21 #define OATRUE (-1)
22 #define OAFALSE (0)
23 
24 
25 // It's possible that we could replace this class with CreateStdDispatch
26 
28 {
29  ITypeInfo * m_pti;
30 
31 public:
32 
33  CBaseDispatch() : m_pti(NULL) {}
34  ~CBaseDispatch();
35 
36  /* IDispatch methods */
37  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
38 
39  STDMETHODIMP GetTypeInfo(
40  REFIID riid,
41  UINT itinfo,
42  LCID lcid,
43  ITypeInfo ** pptinfo);
44 
45  STDMETHODIMP GetIDsOfNames(
46  REFIID riid,
47  OLECHAR ** rgszNames,
48  UINT cNames,
49  LCID lcid,
50  DISPID * rgdispid);
51 };
52 
53 
54 class AM_NOVTABLE CMediaControl :
55  public IMediaControl,
56  public CUnknown
57 {
58  CBaseDispatch m_basedisp;
59 
60 public:
61 
62  CMediaControl(const TCHAR *, LPUNKNOWN);
63 
64  DECLARE_IUNKNOWN
65 
66  // override this to publicise our interfaces
67  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
68 
69  /* IDispatch methods */
70  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
71 
72  STDMETHODIMP GetTypeInfo(
73  UINT itinfo,
74  LCID lcid,
75  ITypeInfo ** pptinfo);
76 
77  STDMETHODIMP GetIDsOfNames(
78  REFIID riid,
79  OLECHAR ** rgszNames,
80  UINT cNames,
81  LCID lcid,
82  DISPID * rgdispid);
83 
84  STDMETHODIMP Invoke(
85  DISPID dispidMember,
86  REFIID riid,
87  LCID lcid,
88  WORD wFlags,
89  DISPPARAMS * pdispparams,
90  VARIANT * pvarResult,
91  EXCEPINFO * pexcepinfo,
92  UINT * puArgErr);
93 };
94 
95 
96 class AM_NOVTABLE CMediaEvent :
97  public IMediaEventEx,
98  public CUnknown
99 {
100  CBaseDispatch m_basedisp;
101 
102 public:
103 
104  CMediaEvent(const TCHAR *, LPUNKNOWN);
105 
106  DECLARE_IUNKNOWN
107 
108  // override this to publicise our interfaces
109  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
110 
111  /* IDispatch methods */
112  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
113 
114  STDMETHODIMP GetTypeInfo(
115  UINT itinfo,
116  LCID lcid,
117  ITypeInfo ** pptinfo);
118 
119  STDMETHODIMP GetIDsOfNames(
120  REFIID riid,
121  OLECHAR ** rgszNames,
122  UINT cNames,
123  LCID lcid,
124  DISPID * rgdispid);
125 
126  STDMETHODIMP Invoke(
127  DISPID dispidMember,
128  REFIID riid,
129  LCID lcid,
130  WORD wFlags,
131  DISPPARAMS * pdispparams,
132  VARIANT * pvarResult,
133  EXCEPINFO * pexcepinfo,
134  UINT * puArgErr);
135 };
136 
137 
138 class AM_NOVTABLE CMediaPosition :
139  public IMediaPosition,
140  public CUnknown
141 {
142  CBaseDispatch m_basedisp;
143 
144 
145 public:
146 
147  CMediaPosition(const TCHAR *, LPUNKNOWN);
148  CMediaPosition(const TCHAR *, LPUNKNOWN, HRESULT *phr);
149 
150  DECLARE_IUNKNOWN
151 
152  // override this to publicise our interfaces
153  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
154 
155  /* IDispatch methods */
156  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
157 
158  STDMETHODIMP GetTypeInfo(
159  UINT itinfo,
160  LCID lcid,
161  ITypeInfo ** pptinfo);
162 
163  STDMETHODIMP GetIDsOfNames(
164  REFIID riid,
165  OLECHAR ** rgszNames,
166  UINT cNames,
167  LCID lcid,
168  DISPID * rgdispid);
169 
170  STDMETHODIMP Invoke(
171  DISPID dispidMember,
172  REFIID riid,
173  LCID lcid,
174  WORD wFlags,
175  DISPPARAMS * pdispparams,
176  VARIANT * pvarResult,
177  EXCEPINFO * pexcepinfo,
178  UINT * puArgErr);
179 
180 };
181 
182 
183 // OA-compatibility means that we must use double as the RefTime value,
184 // and REFERENCE_TIME (essentially a LONGLONG) within filters.
185 // this class converts between the two
186 
187 class COARefTime : public CRefTime {
188 public:
189 
190  COARefTime() {
191  };
192 
194  : CRefTime(t)
195  {
196  };
197 
198  COARefTime(REFERENCE_TIME t)
199  : CRefTime(t)
200  {
201  };
202 
203  COARefTime(double d) {
204  m_time = (LONGLONG) (d * 10000000);
205  };
206 
207  operator double() {
208  return double(m_time) / 10000000;
209  };
210 
211  operator REFERENCE_TIME() {
212  return m_time;
213  };
214 
215  COARefTime& operator=(const double& rd) {
216  m_time = (LONGLONG) (rd * 10000000);
217  return *this;
218  }
219 
220  COARefTime& operator=(const REFERENCE_TIME& rt) {
221  m_time = rt;
222  return *this;
223  }
224 
225  inline BOOL operator==(const COARefTime& rt)
226  {
227  return m_time == rt.m_time;
228  };
229 
230  inline BOOL operator!=(const COARefTime& rt)
231  {
232  return m_time != rt.m_time;
233  };
234 
235  inline BOOL operator < (const COARefTime& rt)
236  {
237  return m_time < rt.m_time;
238  };
239 
240  inline BOOL operator > (const COARefTime& rt)
241  {
242  return m_time > rt.m_time;
243  };
244 
245  inline BOOL operator >= (const COARefTime& rt)
246  {
247  return m_time >= rt.m_time;
248  };
249 
250  inline BOOL operator <= (const COARefTime& rt)
251  {
252  return m_time <= rt.m_time;
253  };
254 
255  inline COARefTime operator+(const COARefTime& rt)
256  {
257  return COARefTime(m_time + rt.m_time);
258  };
259 
260  inline COARefTime operator-(const COARefTime& rt)
261  {
262  return COARefTime(m_time - rt.m_time);
263  };
264 
265  inline COARefTime operator*(LONG l)
266  {
267  return COARefTime(m_time * l);
268  };
269 
270  inline COARefTime operator/(LONG l)
271  {
272  return COARefTime(m_time / l);
273  };
274 
275 private:
276  // Prevent bugs from constructing from LONG (which gets
277  // converted to double and then multiplied by 10000000
278  COARefTime(LONG l);
279  COARefTime& operator=(LONG l);
280 };
281 
282 
283 // A utility class that handles IMediaPosition and IMediaSeeking on behalf
284 // of single-input pin renderers, or transform filters.
285 //
286 // Renderers will expose this from the filter; transform filters will
287 // expose it from the output pin and not the renderer.
288 //
289 // Create one of these, giving it your IPin* for your input pin, and delegate
290 // all IMediaPosition methods to it. It will query the input pin for
291 // IMediaPosition and respond appropriately.
292 //
293 // Call ForceRefresh if the pin connection changes.
294 //
295 // This class no longer caches the upstream IMediaPosition or IMediaSeeking
296 // it acquires it on each method call. This means ForceRefresh is not needed.
297 // The method is kept for source compatibility and to minimise the changes
298 // if we need to put it back later for performance reasons.
299 
300 class CPosPassThru : public IMediaSeeking, public CMediaPosition
301 {
302  IPin *m_pPin;
303 
304  HRESULT GetPeer(IMediaPosition **ppMP);
305  HRESULT GetPeerSeeking(IMediaSeeking **ppMS);
306 
307 public:
308 
309  CPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
310  DECLARE_IUNKNOWN
311 
312  HRESULT ForceRefresh() {
313  return S_OK;
314  };
315 
316  // override to return an accurate current position
317  virtual HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime) {
318  return E_FAIL;
319  }
320 
321  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv);
322 
323  // IMediaSeeking methods
324  STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
325  STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
326  STDMETHODIMP SetTimeFormat(const GUID * pFormat);
327  STDMETHODIMP GetTimeFormat(GUID *pFormat);
328  STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
329  STDMETHODIMP IsFormatSupported( const GUID * pFormat);
330  STDMETHODIMP QueryPreferredFormat( GUID *pFormat);
331  STDMETHODIMP ConvertTimeFormat(LONGLONG * pTarget, const GUID * pTargetFormat,
332  LONGLONG Source, const GUID * pSourceFormat );
333  STDMETHODIMP SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
334  , LONGLONG * pStop, DWORD StopFlags );
335 
336  STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
337  STDMETHODIMP GetCurrentPosition( LONGLONG * pCurrent );
338  STDMETHODIMP GetStopPosition( LONGLONG * pStop );
339  STDMETHODIMP SetRate( double dRate);
340  STDMETHODIMP GetRate( double * pdRate);
341  STDMETHODIMP GetDuration( LONGLONG *pDuration);
342  STDMETHODIMP GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest );
343  STDMETHODIMP GetPreroll( LONGLONG *pllPreroll );
344 
345  // IMediaPosition properties
346  STDMETHODIMP get_Duration(REFTIME * plength);
347  STDMETHODIMP put_CurrentPosition(REFTIME llTime);
348  STDMETHODIMP get_StopTime(REFTIME * pllTime);
349  STDMETHODIMP put_StopTime(REFTIME llTime);
350  STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
351  STDMETHODIMP put_PrerollTime(REFTIME llTime);
352  STDMETHODIMP get_Rate(double * pdRate);
353  STDMETHODIMP put_Rate(double dRate);
354  STDMETHODIMP get_CurrentPosition(REFTIME * pllTime);
355  STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
356  STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
357 
358 private:
359  HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
360  LONGLONG * pll );
361 };
362 
363 
364 // Adds the ability to return a current position
365 
367 {
368  CCritSec m_PositionLock; // Locks access to our position
369  LONGLONG m_StartMedia; // Start media time last seen
370  LONGLONG m_EndMedia; // And likewise the end media
371  BOOL m_bReset; // Have media times been set
372 
373 public:
374 
375  // Used to help with passing media times through graph
376 
377  CRendererPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
378  HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
379  HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
380  HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime);
381  HRESULT ResetMediaTime();
382  HRESULT EOS();
383 };
384 
385 STDAPI CreatePosPassThru(
386  LPUNKNOWN pAgg,
387  BOOL bRenderer,
388  IPin *pPin,
389  IUnknown **ppPassThru
390 );
391 
392 // A class that handles the IDispatch part of IBasicAudio and leaves the
393 // properties and methods themselves pure virtual.
394 
395 class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
396 {
397  CBaseDispatch m_basedisp;
398 
399 public:
400 
401  CBasicAudio(const TCHAR *, LPUNKNOWN);
402 
403  DECLARE_IUNKNOWN
404 
405  // override this to publicise our interfaces
406  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
407 
408  /* IDispatch methods */
409  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
410 
411  STDMETHODIMP GetTypeInfo(
412  UINT itinfo,
413  LCID lcid,
414  ITypeInfo ** pptinfo);
415 
416  STDMETHODIMP GetIDsOfNames(
417  REFIID riid,
418  OLECHAR ** rgszNames,
419  UINT cNames,
420  LCID lcid,
421  DISPID * rgdispid);
422 
423  STDMETHODIMP Invoke(
424  DISPID dispidMember,
425  REFIID riid,
426  LCID lcid,
427  WORD wFlags,
428  DISPPARAMS * pdispparams,
429  VARIANT * pvarResult,
430  EXCEPINFO * pexcepinfo,
431  UINT * puArgErr);
432 };
433 
434 
435 // A class that handles the IDispatch part of IBasicVideo and leaves the
436 // properties and methods themselves pure virtual.
437 
438 class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
439 {
440  CBaseDispatch m_basedisp;
441 
442 public:
443 
444  CBaseBasicVideo(const TCHAR *, LPUNKNOWN);
445 
446  DECLARE_IUNKNOWN
447 
448  // override this to publicise our interfaces
449  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
450 
451  /* IDispatch methods */
452  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
453 
454  STDMETHODIMP GetTypeInfo(
455  UINT itinfo,
456  LCID lcid,
457  ITypeInfo ** pptinfo);
458 
459  STDMETHODIMP GetIDsOfNames(
460  REFIID riid,
461  OLECHAR ** rgszNames,
462  UINT cNames,
463  LCID lcid,
464  DISPID * rgdispid);
465 
466  STDMETHODIMP Invoke(
467  DISPID dispidMember,
468  REFIID riid,
469  LCID lcid,
470  WORD wFlags,
471  DISPPARAMS * pdispparams,
472  VARIANT * pvarResult,
473  EXCEPINFO * pexcepinfo,
474  UINT * puArgErr);
475 
476  STDMETHODIMP GetPreferredAspectRatio(
477  long *plAspectX,
478  long *plAspectY)
479  {
480  return E_NOTIMPL;
481  }
482 };
483 
484 
485 // A class that handles the IDispatch part of IVideoWindow and leaves the
486 // properties and methods themselves pure virtual.
487 
488 class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
489 {
490  CBaseDispatch m_basedisp;
491 
492 public:
493 
494  CBaseVideoWindow(const TCHAR *, LPUNKNOWN);
495 
496  DECLARE_IUNKNOWN
497 
498  // override this to publicise our interfaces
499  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
500 
501  /* IDispatch methods */
502  STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
503 
504  STDMETHODIMP GetTypeInfo(
505  UINT itinfo,
506  LCID lcid,
507  ITypeInfo ** pptinfo);
508 
509  STDMETHODIMP GetIDsOfNames(
510  REFIID riid,
511  OLECHAR ** rgszNames,
512  UINT cNames,
513  LCID lcid,
514  DISPID * rgdispid);
515 
516  STDMETHODIMP Invoke(
517  DISPID dispidMember,
518  REFIID riid,
519  LCID lcid,
520  WORD wFlags,
521  DISPPARAMS * pdispparams,
522  VARIANT * pvarResult,
523  EXCEPINFO * pexcepinfo,
524  UINT * puArgErr);
525 };
526 
527 
528 // abstract class to help source filters with their implementation
529 // of IMediaPosition. Derive from this and set the duration (and stop
530 // position). Also override NotifyChange to do something when the properties
531 // change.
532 
533 class AM_NOVTABLE CSourcePosition : public CMediaPosition
534 {
535 
536 public:
537  CSourcePosition(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
538 
539  // IMediaPosition methods
540  STDMETHODIMP get_Duration(REFTIME * plength);
541  STDMETHODIMP put_CurrentPosition(REFTIME llTime);
542  STDMETHODIMP get_StopTime(REFTIME * pllTime);
543  STDMETHODIMP put_StopTime(REFTIME llTime);
544  STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
545  STDMETHODIMP put_PrerollTime(REFTIME llTime);
546  STDMETHODIMP get_Rate(double * pdRate);
547  STDMETHODIMP put_Rate(double dRate);
548  STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
549  STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
550 
551  // override if you can return the data you are actually working on
552  STDMETHODIMP get_CurrentPosition(REFTIME * pllTime) {
553  return E_NOTIMPL;
554  };
555 
556 protected:
557 
558  // we call this to notify changes. Override to handle them
559  virtual HRESULT ChangeStart() PURE;
560  virtual HRESULT ChangeStop() PURE;
561  virtual HRESULT ChangeRate() PURE;
562 
563  COARefTime m_Duration;
564  COARefTime m_Start;
565  COARefTime m_Stop;
566  double m_Rate;
567 
568  CCritSec * m_pLock;
569 };
570 
571 class AM_NOVTABLE CSourceSeeking :
572  public IMediaSeeking,
573  public CUnknown
574 {
575 
576 public:
577 
578  DECLARE_IUNKNOWN;
579  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
580 
581  // IMediaSeeking methods
582 
583  STDMETHODIMP IsFormatSupported(const GUID * pFormat);
584  STDMETHODIMP QueryPreferredFormat(GUID *pFormat);
585  STDMETHODIMP SetTimeFormat(const GUID * pFormat);
586  STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
587  STDMETHODIMP GetTimeFormat(GUID *pFormat);
588  STDMETHODIMP GetDuration(LONGLONG *pDuration);
589  STDMETHODIMP GetStopPosition(LONGLONG *pStop);
590  STDMETHODIMP GetCurrentPosition(LONGLONG *pCurrent);
591  STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
592  STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
593  STDMETHODIMP ConvertTimeFormat( LONGLONG * pTarget, const GUID * pTargetFormat,
594  LONGLONG Source, const GUID * pSourceFormat );
595 
596  STDMETHODIMP SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
597  , LONGLONG * pStop, DWORD StopFlags );
598 
599  STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
600 
601  STDMETHODIMP GetAvailable( LONGLONG * pEarliest, LONGLONG * pLatest );
602  STDMETHODIMP SetRate( double dRate);
603  STDMETHODIMP GetRate( double * pdRate);
604  STDMETHODIMP GetPreroll(LONGLONG *pPreroll);
605 
606 
607 protected:
608 
609  // ctor
610  CSourceSeeking(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
611 
612  // we call this to notify changes. Override to handle them
613  virtual HRESULT ChangeStart() PURE;
614  virtual HRESULT ChangeStop() PURE;
615  virtual HRESULT ChangeRate() PURE;
616 
617  CRefTime m_rtDuration; // length of stream
618  CRefTime m_rtStart; // source will start here
619  CRefTime m_rtStop; // source will stop here
620  double m_dRateSeeking;
621 
622  // seeking capabilities
623  DWORD m_dwSeekingCaps;
624 
625  CCritSec * m_pLock;
626 };
627 
628 
629 // Base classes supporting Deferred commands.
630 
631 // Deferred commands are queued by calls to methods on the IQueueCommand
632 // interface, exposed by the filtergraph and by some filters. A successful
633 // call to one of these methods will return an IDeferredCommand interface
634 // representing the queued command.
635 //
636 // A CDeferredCommand object represents a single deferred command, and exposes
637 // the IDeferredCommand interface as well as other methods permitting time
638 // checks and actual execution. It contains a reference to the CCommandQueue
639 // object on which it is queued.
640 //
641 // CCommandQueue is a base class providing a queue of CDeferredCommand
642 // objects, and methods to add, remove, check status and invoke the queued
643 // commands. A CCommandQueue object would be part of an object that
644 // implemented IQueueCommand.
645 
646 class CCmdQueue;
647 
648 // take a copy of the params and store them. Release any allocated
649 // memory in destructor
650 
651 class CDispParams : public DISPPARAMS
652 {
653 public:
654  CDispParams(UINT nArgs, VARIANT* pArgs, HRESULT *phr = NULL);
655  ~CDispParams();
656 };
657 
658 
659 // CDeferredCommand lifetime is controlled by refcounts. Caller of
660 // InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
661 // object also holds a refcount on us. Calling Cancel or Invoke takes
662 // us off the CCmdQueue and thus reduces the refcount by 1. Once taken
663 // off the queue we cannot be put back on the queue.
664 
666  : public CUnknown,
667  public IDeferredCommand
668 {
669 public:
670 
672  CCmdQueue * pQ,
673  LPUNKNOWN pUnk, // aggregation outer unk
674  HRESULT * phr,
675  LPUNKNOWN pUnkExecutor, // object that will execute this cmd
676  REFTIME time,
677  GUID* iid,
678  long dispidMethod,
679  short wFlags,
680  long cArgs,
681  VARIANT* pDispParams,
682  VARIANT* pvarResult,
683  short* puArgErr,
684  BOOL bStream
685  );
686 
687  DECLARE_IUNKNOWN
688 
689  // override this to publicise our interfaces
690  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
691 
692  // IDeferredCommand methods
693  STDMETHODIMP Cancel();
694  STDMETHODIMP Confidence(
695  LONG* pConfidence);
696  STDMETHODIMP Postpone(
697  REFTIME newtime);
698  STDMETHODIMP GetHResult(
699  HRESULT* phrResult);
700 
701  // other public methods
702 
703  HRESULT Invoke();
704 
705  // access methods
706 
707  // returns TRUE if streamtime, FALSE if presentation time
708  BOOL IsStreamTime() {
709  return m_bStream;
710  };
711 
712  CRefTime GetTime() {
713  return m_time;
714  };
715 
716  REFIID GetIID() {
717  return *m_iid;
718  };
719 
720  long GetMethod() {
721  return m_dispidMethod;
722  };
723 
724  short GetFlags() {
725  return m_wFlags;
726  };
727 
728  DISPPARAMS* GetParams() {
729  return &m_DispParams;
730  };
731 
732  VARIANT* GetResult() {
733  return m_pvarResult;
734  };
735 
736 protected:
737 
738  CCmdQueue* m_pQueue;
739 
740  // pUnk for the interface that we will execute the command on
741  LPUNKNOWN m_pUnk;
742 
743  // stored command data
744  REFERENCE_TIME m_time;
745  GUID* m_iid;
746  long m_dispidMethod;
747  short m_wFlags;
748  VARIANT* m_pvarResult;
749  BOOL m_bStream;
750  CDispParams m_DispParams;
751  DISPID m_DispId; // For get and put
752 
753  // we use this for ITypeInfo access
754  CBaseDispatch m_Dispatch;
755 
756  // save retval here
757  HRESULT m_hrResult;
758 };
759 
760 
761 // a list of CDeferredCommand objects. this is a base class providing
762 // the basics of access to the list. If you want to use CDeferredCommand
763 // objects then your queue needs to be derived from this class.
764 
765 class AM_NOVTABLE CCmdQueue
766 {
767 public:
768  CCmdQueue();
769  virtual ~CCmdQueue();
770 
771  // returns a new CDeferredCommand object that will be initialised with
772  // the parameters and will be added to the queue during construction.
773  // returns S_OK if successfully created otherwise an error and
774  // no object has been queued.
775  virtual HRESULT New(
776  CDeferredCommand **ppCmd,
777  LPUNKNOWN pUnk,
778  REFTIME time,
779  GUID* iid,
780  long dispidMethod,
781  short wFlags,
782  long cArgs,
783  VARIANT* pDispParams,
784  VARIANT* pvarResult,
785  short* puArgErr,
786  BOOL bStream
787  );
788 
789  // called by the CDeferredCommand object to add and remove itself
790  // from the queue
791  virtual HRESULT Insert(CDeferredCommand* pCmd);
792  virtual HRESULT Remove(CDeferredCommand* pCmd);
793 
794  // Command-Due Checking
795  //
796  // There are two schemes of synchronisation: coarse and accurate. In
797  // coarse mode, you wait till the time arrives and then execute the cmd.
798  // In accurate mode, you wait until you are processing the sample that
799  // will appear at the time, and then execute the command. It's up to the
800  // filter which one it will implement. The filtergraph will always
801  // implement coarse mode for commands queued at the filtergraph.
802  //
803  // If you want coarse sync, you probably want to wait until there is a
804  // command due, and then execute it. You can do this by calling
805  // GetDueCommand. If you have several things to wait for, get the
806  // event handle from GetDueHandle() and when this is signalled then call
807  // GetDueCommand. Stream time will only advance between calls to Run and
808  // EndRun. Note that to avoid an extra thread there is no guarantee that
809  // if the handle is set there will be a command ready. Each time the
810  // event is signalled, call GetDueCommand (probably with a 0 timeout);
811  // This may return E_ABORT.
812  //
813  // If you want accurate sync, you must call GetCommandDueFor, passing
814  // as a parameter the stream time of the samples you are about to process.
815  // This will return:
816  // -- a stream-time command due at or before that stream time
817  // -- a presentation-time command due at or before the
818  // time that stream time will be presented (only between Run
819  // and EndRun calls, since outside of this, the mapping from
820  // stream time to presentation time is not known.
821  // -- any presentation-time command due now.
822  // This means that if you want accurate synchronisation on samples that
823  // might be processed during Paused mode, you need to use
824  // stream-time commands.
825  //
826  // In all cases, commands remain queued until Invoked or Cancelled. The
827  // setting and resetting of the event handle is managed entirely by this
828  // queue object.
829 
830  // set the clock used for timing
831  virtual HRESULT SetSyncSource(IReferenceClock*);
832 
833  // switch to run mode. Streamtime to Presentation time mapping known.
834  virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
835 
836  // switch to Stopped or Paused mode. Time mapping not known.
837  virtual HRESULT EndRun();
838 
839  // return a pointer to the next due command. Blocks for msTimeout
840  // milliseconds until there is a due command.
841  // Stream-time commands will only become due between Run and Endrun calls.
842  // The command remains queued until invoked or cancelled.
843  // Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
844  // Returns an AddRef-ed object
845  virtual HRESULT GetDueCommand(CDeferredCommand ** ppCmd, long msTimeout);
846 
847  // return the event handle that will be signalled whenever
848  // there are deferred commands due for execution (when GetDueCommand
849  // will not block).
850  HANDLE GetDueHandle() {
851  return HANDLE(m_evDue);
852  };
853 
854  // return a pointer to a command that will be due for a given time.
855  // Pass in a stream time here. The stream time offset will be passed
856  // in via the Run method.
857  // Commands remain queued until invoked or cancelled.
858  // This method will not block. It will report VFW_E_NOT_FOUND if there
859  // are no commands due yet.
860  // Returns an AddRef-ed object
861  virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, CDeferredCommand**ppCmd);
862 
863  // check if a given time is due (TRUE if it is due yet)
864  BOOL CheckTime(CRefTime time, BOOL bStream) {
865 
866  // if no clock, nothing is due!
867  if (!m_pClock) {
868  return FALSE;
869  }
870 
871  // stream time
872  if (bStream) {
873 
874  // not valid if not running
875  if (!m_bRunning) {
876  return FALSE;
877  }
878  // add on known stream time offset to get presentation time
879  time += m_StreamTimeOffset;
880  }
881 
882  CRefTime Now;
883  m_pClock->GetTime((REFERENCE_TIME*)&Now);
884  return (time <= Now);
885  };
886 
887 protected:
888 
889  // protect access to lists etc
890  CCritSec m_Lock;
891 
892  // commands queued in presentation time are stored here
893  CGenericList<CDeferredCommand> m_listPresentation;
894 
895  // commands queued in stream time are stored here
896  CGenericList<CDeferredCommand> m_listStream;
897 
898  // set when any commands are due
899  CAMEvent m_evDue;
900 
901  // creates an advise for the earliest time required, if any
902  void SetTimeAdvise(void);
903 
904  // advise id from reference clock (0 if no outstanding advise)
905  DWORD_PTR m_dwAdvise;
906 
907  // advise time is for this presentation time
908  CRefTime m_tCurrentAdvise;
909 
910  // the reference clock we are using (addrefed)
911  IReferenceClock* m_pClock;
912 
913  // true when running
914  BOOL m_bRunning;
915 
916  // contains stream time offset when m_bRunning is true
917  CRefTime m_StreamTimeOffset;
918 };
919 
920 #endif // __CTLUTIL__
Definition: ctlutil.h:665
Definition: combase.h:201
Definition: ctlutil.h:395
Definition: ctlutil.h:54
Definition: ctlutil.h:533
Definition: ctlutil.h:300
Definition: ctlutil.h:651
Definition: ctlutil.h:366
Definition: ctlutil.h:765
Definition: wxutil.h:19
Definition: ctlutil.h:138
Definition: ctlutil.h:571
Definition: ctlutil.h:27
Definition: ctlutil.h:488
Definition: ctlutil.h:96
Definition: wxutil.h:109
Definition: ctlutil.h:187
Definition: reftime.h:50
Definition: ctlutil.h:438