ctlutil.h
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:26k
源码类别:

P2P编程

开发平台:

Visual C++

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