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