forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			924 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			924 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//------------------------------------------------------------------------------
 | 
						|
// File: CtlUtil.h
 | 
						|
//
 | 
						|
// Desc: DirectShow base classes.
 | 
						|
//
 | 
						|
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
 | 
						|
// Base classes implementing IDispatch parsing for the basic control dual
 | 
						|
// interfaces. Derive from these and implement just the custom method and
 | 
						|
// property methods. We also implement CPosPassThru that can be used by
 | 
						|
// renderers and transforms to pass by IMediaPosition and IMediaSeeking
 | 
						|
 | 
						|
#ifndef __CTLUTIL__
 | 
						|
#define __CTLUTIL__
 | 
						|
 | 
						|
// OLE Automation has different ideas of TRUE and FALSE
 | 
						|
 | 
						|
#define OATRUE (-1)
 | 
						|
#define OAFALSE (0)
 | 
						|
 | 
						|
 | 
						|
// It's possible that we could replace this class with CreateStdDispatch
 | 
						|
 | 
						|
class CBaseDispatch
 | 
						|
{
 | 
						|
    ITypeInfo * m_pti;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CBaseDispatch() : m_pti(NULL) {}
 | 
						|
    ~CBaseDispatch();
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      REFIID riid,
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class AM_NOVTABLE CMediaControl :
 | 
						|
    public IMediaControl,
 | 
						|
    public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CMediaControl(const TCHAR *, LPUNKNOWN);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class AM_NOVTABLE CMediaEvent :
 | 
						|
    public IMediaEventEx,
 | 
						|
    public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CMediaEvent(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class AM_NOVTABLE CMediaPosition :
 | 
						|
    public IMediaPosition,
 | 
						|
    public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
 | 
						|
    CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT *phr);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// OA-compatibility means that we must use double as the RefTime value,
 | 
						|
// and REFERENCE_TIME (essentially a LONGLONG) within filters.
 | 
						|
// this class converts between the two
 | 
						|
 | 
						|
class COARefTime : public CRefTime {
 | 
						|
public:
 | 
						|
 | 
						|
    COARefTime() {
 | 
						|
    };
 | 
						|
 | 
						|
    COARefTime(CRefTime t)
 | 
						|
        : CRefTime(t)
 | 
						|
    {
 | 
						|
    };
 | 
						|
 | 
						|
    COARefTime(REFERENCE_TIME t)
 | 
						|
        : CRefTime(t)
 | 
						|
    {
 | 
						|
    };
 | 
						|
 | 
						|
    COARefTime(double d) {
 | 
						|
        m_time = (LONGLONG) (d * 10000000);
 | 
						|
    };
 | 
						|
 | 
						|
    operator double() {
 | 
						|
        return double(m_time) / 10000000;
 | 
						|
    };
 | 
						|
 | 
						|
    operator REFERENCE_TIME() {
 | 
						|
        return m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    COARefTime& operator=(const double& rd)  {
 | 
						|
        m_time = (LONGLONG) (rd * 10000000);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    COARefTime& operator=(const REFERENCE_TIME& rt)  {
 | 
						|
        m_time = rt;
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    inline BOOL operator==(const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time == rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline BOOL operator!=(const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time != rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline BOOL operator < (const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time < rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline BOOL operator > (const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time > rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline BOOL operator >= (const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time >= rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline BOOL operator <= (const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return m_time <= rt.m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    inline COARefTime operator+(const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return COARefTime(m_time + rt.m_time);
 | 
						|
    };
 | 
						|
 | 
						|
    inline COARefTime operator-(const COARefTime& rt)
 | 
						|
    {
 | 
						|
        return COARefTime(m_time - rt.m_time);
 | 
						|
    };
 | 
						|
 | 
						|
    inline COARefTime operator*(LONG l)
 | 
						|
    {
 | 
						|
        return COARefTime(m_time * l);
 | 
						|
    };
 | 
						|
 | 
						|
    inline COARefTime operator/(LONG l)
 | 
						|
    {
 | 
						|
        return COARefTime(m_time / l);
 | 
						|
    };
 | 
						|
 | 
						|
private:
 | 
						|
    //  Prevent bugs from constructing from LONG (which gets
 | 
						|
    //  converted to double and then multiplied by 10000000
 | 
						|
    COARefTime(LONG);
 | 
						|
    LONG operator=(LONG);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// A utility class that handles IMediaPosition and IMediaSeeking on behalf
 | 
						|
// of single-input pin renderers, or transform filters.
 | 
						|
//
 | 
						|
// Renderers will expose this from the filter; transform filters will
 | 
						|
// expose it from the output pin and not the renderer.
 | 
						|
//
 | 
						|
// Create one of these, giving it your IPin* for your input pin, and delegate
 | 
						|
// all IMediaPosition methods to it. It will query the input pin for
 | 
						|
// IMediaPosition and respond appropriately.
 | 
						|
//
 | 
						|
// Call ForceRefresh if the pin connection changes.
 | 
						|
//
 | 
						|
// This class no longer caches the upstream IMediaPosition or IMediaSeeking
 | 
						|
// it acquires it on each method call. This means ForceRefresh is not needed.
 | 
						|
// The method is kept for source compatibility and to minimise the changes
 | 
						|
// if we need to put it back later for performance reasons.
 | 
						|
 | 
						|
class CPosPassThru : public IMediaSeeking, public CMediaPosition
 | 
						|
{
 | 
						|
    IPin *m_pPin;
 | 
						|
 | 
						|
    HRESULT GetPeer(__deref_out IMediaPosition **ppMP);
 | 
						|
    HRESULT GetPeerSeeking(__deref_out IMediaSeeking **ppMS);
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    HRESULT ForceRefresh() {
 | 
						|
        return S_OK;
 | 
						|
    };
 | 
						|
 | 
						|
    // override to return an accurate current position
 | 
						|
    virtual HRESULT GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime) {
 | 
						|
        return E_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
 | 
						|
 | 
						|
    // IMediaSeeking methods
 | 
						|
    STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
 | 
						|
    STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
 | 
						|
    STDMETHODIMP SetTimeFormat(const GUID * pFormat);
 | 
						|
    STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
 | 
						|
    STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
 | 
						|
    STDMETHODIMP IsFormatSupported( const GUID * pFormat);
 | 
						|
    STDMETHODIMP QueryPreferredFormat( __out GUID *pFormat);
 | 
						|
    STDMETHODIMP ConvertTimeFormat(__out LONGLONG * pTarget, 
 | 
						|
                                   __in_opt const GUID * pTargetFormat,
 | 
						|
                                   LONGLONG Source, 
 | 
						|
                                   __in_opt const GUID * pSourceFormat );
 | 
						|
    STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
 | 
						|
                             , __inout_opt LONGLONG * pStop, DWORD StopFlags );
 | 
						|
 | 
						|
    STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
 | 
						|
    STDMETHODIMP GetCurrentPosition( __out LONGLONG * pCurrent );
 | 
						|
    STDMETHODIMP GetStopPosition( __out LONGLONG * pStop );
 | 
						|
    STDMETHODIMP SetRate( double dRate);
 | 
						|
    STDMETHODIMP GetRate( __out double * pdRate);
 | 
						|
    STDMETHODIMP GetDuration( __out LONGLONG *pDuration);
 | 
						|
    STDMETHODIMP GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest );
 | 
						|
    STDMETHODIMP GetPreroll( __out LONGLONG *pllPreroll );
 | 
						|
 | 
						|
    // IMediaPosition properties
 | 
						|
    STDMETHODIMP get_Duration(__out REFTIME * plength);
 | 
						|
    STDMETHODIMP put_CurrentPosition(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
 | 
						|
    STDMETHODIMP put_StopTime(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
 | 
						|
    STDMETHODIMP put_PrerollTime(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_Rate(__out double * pdRate);
 | 
						|
    STDMETHODIMP put_Rate(double dRate);
 | 
						|
    STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime);
 | 
						|
    STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
 | 
						|
    STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
 | 
						|
 | 
						|
private:
 | 
						|
    HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
 | 
						|
                                __out LONGLONG * pll );
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// Adds the ability to return a current position
 | 
						|
 | 
						|
class CRendererPosPassThru : public CPosPassThru
 | 
						|
{
 | 
						|
    CCritSec m_PositionLock;    // Locks access to our position
 | 
						|
    LONGLONG m_StartMedia;      // Start media time last seen
 | 
						|
    LONGLONG m_EndMedia;        // And likewise the end media
 | 
						|
    BOOL m_bReset;              // Have media times been set
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    // Used to help with passing media times through graph
 | 
						|
 | 
						|
    CRendererPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
 | 
						|
    HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
 | 
						|
    HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
 | 
						|
    HRESULT GetMediaTime(__out LONGLONG *pStartTime,__out_opt LONGLONG *pEndTime);
 | 
						|
    HRESULT ResetMediaTime();
 | 
						|
    HRESULT EOS();
 | 
						|
};
 | 
						|
 | 
						|
STDAPI CreatePosPassThru(
 | 
						|
    __in_opt LPUNKNOWN pAgg,
 | 
						|
    BOOL bRenderer,
 | 
						|
    IPin *pPin,
 | 
						|
    __deref_out IUnknown **ppPassThru
 | 
						|
);
 | 
						|
 | 
						|
// A class that handles the IDispatch part of IBasicAudio and leaves the
 | 
						|
// properties and methods themselves pure virtual.
 | 
						|
 | 
						|
class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CBasicAudio(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// A class that handles the IDispatch part of IBasicVideo and leaves the
 | 
						|
// properties and methods themselves pure virtual.
 | 
						|
 | 
						|
class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CBaseBasicVideo(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
 | 
						|
    STDMETHODIMP GetPreferredAspectRatio(
 | 
						|
      __out long *plAspectX,
 | 
						|
      __out long *plAspectY)
 | 
						|
    {
 | 
						|
        return E_NOTIMPL;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// A class that handles the IDispatch part of IVideoWindow and leaves the
 | 
						|
// properties and methods themselves pure virtual.
 | 
						|
 | 
						|
class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
 | 
						|
{
 | 
						|
    CBaseDispatch m_basedisp;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    CBaseVideoWindow(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    /* IDispatch methods */
 | 
						|
    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetTypeInfo(
 | 
						|
      UINT itinfo,
 | 
						|
      LCID lcid,
 | 
						|
      __deref_out ITypeInfo ** pptinfo);
 | 
						|
 | 
						|
    STDMETHODIMP GetIDsOfNames(
 | 
						|
      REFIID riid,
 | 
						|
      __in_ecount(cNames) LPOLESTR * rgszNames,
 | 
						|
      UINT cNames,
 | 
						|
      LCID lcid,
 | 
						|
      __out_ecount(cNames) DISPID * rgdispid);
 | 
						|
 | 
						|
    STDMETHODIMP Invoke(
 | 
						|
      DISPID dispidMember,
 | 
						|
      REFIID riid,
 | 
						|
      LCID lcid,
 | 
						|
      WORD wFlags,
 | 
						|
      __in DISPPARAMS * pdispparams,
 | 
						|
      __out_opt VARIANT * pvarResult,
 | 
						|
      __out_opt EXCEPINFO * pexcepinfo,
 | 
						|
      __out_opt UINT * puArgErr);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// abstract class to help source filters with their implementation
 | 
						|
// of IMediaPosition. Derive from this and set the duration (and stop
 | 
						|
// position). Also override NotifyChange to do something when the properties
 | 
						|
// change.
 | 
						|
 | 
						|
class AM_NOVTABLE CSourcePosition : public CMediaPosition
 | 
						|
{
 | 
						|
 | 
						|
public:
 | 
						|
    CSourcePosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
 | 
						|
 | 
						|
    // IMediaPosition methods
 | 
						|
    STDMETHODIMP get_Duration(__out REFTIME * plength);
 | 
						|
    STDMETHODIMP put_CurrentPosition(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
 | 
						|
    STDMETHODIMP put_StopTime(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
 | 
						|
    STDMETHODIMP put_PrerollTime(REFTIME llTime);
 | 
						|
    STDMETHODIMP get_Rate(__out double * pdRate);
 | 
						|
    STDMETHODIMP put_Rate(double dRate);
 | 
						|
    STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
 | 
						|
    STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
 | 
						|
 | 
						|
    // override if you can return the data you are actually working on
 | 
						|
    STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime) {
 | 
						|
        return E_NOTIMPL;
 | 
						|
    };
 | 
						|
 | 
						|
protected:
 | 
						|
 | 
						|
    // we call this to notify changes. Override to handle them
 | 
						|
    virtual HRESULT ChangeStart() PURE;
 | 
						|
    virtual HRESULT ChangeStop() PURE;
 | 
						|
    virtual HRESULT ChangeRate() PURE;
 | 
						|
 | 
						|
    COARefTime m_Duration;
 | 
						|
    COARefTime m_Start;
 | 
						|
    COARefTime m_Stop;
 | 
						|
    double m_Rate;
 | 
						|
 | 
						|
    CCritSec * m_pLock;
 | 
						|
};
 | 
						|
 | 
						|
class AM_NOVTABLE CSourceSeeking :
 | 
						|
    public IMediaSeeking,
 | 
						|
    public CUnknown
 | 
						|
{
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN;
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 | 
						|
 | 
						|
    // IMediaSeeking methods
 | 
						|
 | 
						|
    STDMETHODIMP IsFormatSupported(const GUID * pFormat);
 | 
						|
    STDMETHODIMP QueryPreferredFormat(__out GUID *pFormat);
 | 
						|
    STDMETHODIMP SetTimeFormat(const GUID * pFormat);
 | 
						|
    STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
 | 
						|
    STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
 | 
						|
    STDMETHODIMP GetDuration(__out LONGLONG *pDuration);
 | 
						|
    STDMETHODIMP GetStopPosition(__out LONGLONG *pStop);
 | 
						|
    STDMETHODIMP GetCurrentPosition(__out LONGLONG *pCurrent);
 | 
						|
    STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
 | 
						|
    STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
 | 
						|
    STDMETHODIMP ConvertTimeFormat( __out LONGLONG * pTarget, 
 | 
						|
                                    __in_opt const GUID * pTargetFormat,
 | 
						|
                                    LONGLONG Source, 
 | 
						|
                                    __in_opt const GUID * pSourceFormat );
 | 
						|
 | 
						|
    STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent,  DWORD CurrentFlags
 | 
						|
			     , __inout_opt LONGLONG * pStop,  DWORD StopFlags );
 | 
						|
 | 
						|
    STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
 | 
						|
 | 
						|
    STDMETHODIMP GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest );
 | 
						|
    STDMETHODIMP SetRate( double dRate);
 | 
						|
    STDMETHODIMP GetRate( __out double * pdRate);
 | 
						|
    STDMETHODIMP GetPreroll(__out LONGLONG *pPreroll);
 | 
						|
 | 
						|
 | 
						|
protected:
 | 
						|
 | 
						|
    // ctor
 | 
						|
    CSourceSeeking(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
 | 
						|
 | 
						|
    // we call this to notify changes. Override to handle them
 | 
						|
    virtual HRESULT ChangeStart() PURE;
 | 
						|
    virtual HRESULT ChangeStop() PURE;
 | 
						|
    virtual HRESULT ChangeRate() PURE;
 | 
						|
 | 
						|
    CRefTime m_rtDuration;      // length of stream
 | 
						|
    CRefTime m_rtStart;         // source will start here
 | 
						|
    CRefTime m_rtStop;          // source will stop here
 | 
						|
    double m_dRateSeeking;
 | 
						|
 | 
						|
    // seeking capabilities
 | 
						|
    DWORD m_dwSeekingCaps;
 | 
						|
 | 
						|
    CCritSec * m_pLock;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// Base classes supporting Deferred commands.
 | 
						|
 | 
						|
// Deferred commands are queued by calls to methods on the IQueueCommand
 | 
						|
// interface, exposed by the filtergraph and by some filters. A successful
 | 
						|
// call to one of these methods will return an IDeferredCommand interface
 | 
						|
// representing the queued command.
 | 
						|
//
 | 
						|
// A CDeferredCommand object represents a single deferred command, and exposes
 | 
						|
// the IDeferredCommand interface as well as other methods permitting time
 | 
						|
// checks and actual execution. It contains a reference to the CCommandQueue
 | 
						|
// object on which it is queued.
 | 
						|
//
 | 
						|
// CCommandQueue is a base class providing a queue of CDeferredCommand
 | 
						|
// objects, and methods to add, remove, check status and invoke the queued
 | 
						|
// commands. A CCommandQueue object would be part of an object that
 | 
						|
// implemented IQueueCommand.
 | 
						|
 | 
						|
class CCmdQueue;
 | 
						|
 | 
						|
// take a copy of the params and store them. Release any allocated
 | 
						|
// memory in destructor
 | 
						|
 | 
						|
class CDispParams : public DISPPARAMS
 | 
						|
{
 | 
						|
public:
 | 
						|
    CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr = NULL);
 | 
						|
    ~CDispParams();
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// CDeferredCommand lifetime is controlled by refcounts. Caller of
 | 
						|
// InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
 | 
						|
// object also holds a refcount on us. Calling Cancel or Invoke takes
 | 
						|
// us off the CCmdQueue and thus reduces the refcount by 1. Once taken
 | 
						|
// off the queue we cannot be put back on the queue.
 | 
						|
 | 
						|
class CDeferredCommand
 | 
						|
    : public CUnknown,
 | 
						|
      public IDeferredCommand
 | 
						|
{
 | 
						|
public:
 | 
						|
 | 
						|
    CDeferredCommand(
 | 
						|
        __inout CCmdQueue * pQ,
 | 
						|
        __in_opt LPUNKNOWN   pUnk,               // aggregation outer unk
 | 
						|
        __inout HRESULT *   phr,
 | 
						|
        __in LPUNKNOWN   pUnkExecutor,       // object that will execute this cmd
 | 
						|
        REFTIME     time,
 | 
						|
        __in GUID*       iid,
 | 
						|
        long        dispidMethod,
 | 
						|
        short       wFlags,
 | 
						|
        long        cArgs,
 | 
						|
        __in_ecount(cArgs) VARIANT*    pDispParams,
 | 
						|
        __out VARIANT*    pvarResult,
 | 
						|
        __out short*      puArgErr,
 | 
						|
        BOOL        bStream
 | 
						|
        );
 | 
						|
 | 
						|
    DECLARE_IUNKNOWN
 | 
						|
 | 
						|
    // override this to publicise our interfaces
 | 
						|
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __out void **ppv);
 | 
						|
 | 
						|
    // IDeferredCommand methods
 | 
						|
    STDMETHODIMP Cancel();
 | 
						|
    STDMETHODIMP Confidence(
 | 
						|
                    __out LONG* pConfidence);
 | 
						|
    STDMETHODIMP Postpone(
 | 
						|
                    REFTIME newtime);
 | 
						|
    STDMETHODIMP GetHResult(
 | 
						|
                    __out HRESULT* phrResult);
 | 
						|
 | 
						|
    // other public methods
 | 
						|
 | 
						|
    HRESULT Invoke();
 | 
						|
 | 
						|
    // access methods
 | 
						|
 | 
						|
    // returns TRUE if streamtime, FALSE if presentation time
 | 
						|
    BOOL IsStreamTime() {
 | 
						|
       return m_bStream;
 | 
						|
    };
 | 
						|
 | 
						|
    CRefTime GetTime() {
 | 
						|
        return m_time;
 | 
						|
    };
 | 
						|
 | 
						|
    REFIID GetIID() {
 | 
						|
        return *m_iid;
 | 
						|
    };
 | 
						|
 | 
						|
    long GetMethod() {
 | 
						|
        return m_dispidMethod;
 | 
						|
    };
 | 
						|
 | 
						|
    short GetFlags() {
 | 
						|
        return m_wFlags;
 | 
						|
    };
 | 
						|
 | 
						|
    DISPPARAMS* GetParams() {
 | 
						|
        return &m_DispParams;
 | 
						|
    };
 | 
						|
 | 
						|
    VARIANT* GetResult() {
 | 
						|
        return m_pvarResult;
 | 
						|
    };
 | 
						|
 | 
						|
protected:
 | 
						|
 | 
						|
    CCmdQueue* m_pQueue;
 | 
						|
 | 
						|
    // pUnk for the interface that we will execute the command on
 | 
						|
    LPUNKNOWN   m_pUnk;
 | 
						|
 | 
						|
    // stored command data
 | 
						|
    REFERENCE_TIME     m_time;
 | 
						|
    GUID*       m_iid;
 | 
						|
    long        m_dispidMethod;
 | 
						|
    short       m_wFlags;
 | 
						|
    VARIANT*    m_pvarResult;
 | 
						|
    BOOL        m_bStream;
 | 
						|
    CDispParams m_DispParams;
 | 
						|
    DISPID      m_DispId;         //  For get and put
 | 
						|
 | 
						|
    // we use this for ITypeInfo access
 | 
						|
    CBaseDispatch   m_Dispatch;
 | 
						|
 | 
						|
    // save retval here
 | 
						|
    HRESULT     m_hrResult;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// a list of CDeferredCommand objects. this is a base class providing
 | 
						|
// the basics of access to the list. If you want to use CDeferredCommand
 | 
						|
// objects then your queue needs to be derived from this class.
 | 
						|
 | 
						|
class AM_NOVTABLE CCmdQueue
 | 
						|
{
 | 
						|
public:
 | 
						|
    CCmdQueue(__inout_opt HRESULT *phr = NULL);
 | 
						|
    virtual ~CCmdQueue();
 | 
						|
 | 
						|
    // returns a new CDeferredCommand object that will be initialised with
 | 
						|
    // the parameters and will be added to the queue during construction.
 | 
						|
    // returns S_OK if successfully created otherwise an error and
 | 
						|
    // no object has been queued.
 | 
						|
    virtual HRESULT  New(
 | 
						|
        __out CDeferredCommand **ppCmd,
 | 
						|
        __in LPUNKNOWN   pUnk,
 | 
						|
        REFTIME     time,
 | 
						|
        __in GUID*       iid,
 | 
						|
        long        dispidMethod,
 | 
						|
        short       wFlags,
 | 
						|
        long        cArgs,
 | 
						|
        __in_ecount(cArgs) VARIANT*    pDispParams,
 | 
						|
        __out VARIANT*    pvarResult,
 | 
						|
        __out short*      puArgErr,
 | 
						|
        BOOL        bStream
 | 
						|
    );
 | 
						|
 | 
						|
    // called by the CDeferredCommand object to add and remove itself
 | 
						|
    // from the queue
 | 
						|
    virtual HRESULT Insert(__in CDeferredCommand* pCmd);
 | 
						|
    virtual HRESULT Remove(__in CDeferredCommand* pCmd);
 | 
						|
 | 
						|
    // Command-Due Checking
 | 
						|
    //
 | 
						|
    // There are two schemes of synchronisation: coarse and accurate. In
 | 
						|
    // coarse mode, you wait till the time arrives and then execute the cmd.
 | 
						|
    // In accurate mode, you wait until you are processing the sample that
 | 
						|
    // will appear at the time, and then execute the command. It's up to the
 | 
						|
    // filter which one it will implement. The filtergraph will always
 | 
						|
    // implement coarse mode for commands queued at the filtergraph.
 | 
						|
    //
 | 
						|
    // If you want coarse sync, you probably want to wait until there is a
 | 
						|
    // command due, and then execute it. You can do this by calling
 | 
						|
    // GetDueCommand. If you have several things to wait for, get the
 | 
						|
    // event handle from GetDueHandle() and when this is signalled then call
 | 
						|
    // GetDueCommand. Stream time will only advance between calls to Run and
 | 
						|
    // EndRun. Note that to avoid an extra thread there is no guarantee that
 | 
						|
    // if the handle is set there will be a command ready. Each time the
 | 
						|
    // event is signalled, call GetDueCommand (probably with a 0 timeout);
 | 
						|
    // This may return E_ABORT.
 | 
						|
    //
 | 
						|
    // If you want accurate sync, you must call GetCommandDueFor, passing
 | 
						|
    // as a parameter the stream time of the samples you are about to process.
 | 
						|
    // This will return:
 | 
						|
    //   -- a stream-time command due at or before that stream time
 | 
						|
    //   -- a presentation-time command due at or before the
 | 
						|
    //      time that stream time will be presented (only between Run
 | 
						|
    //      and EndRun calls, since outside of this, the mapping from
 | 
						|
    //      stream time to presentation time is not known.
 | 
						|
    //   -- any presentation-time command due now.
 | 
						|
    // This means that if you want accurate synchronisation on samples that
 | 
						|
    // might be processed during Paused mode, you need to use
 | 
						|
    // stream-time commands.
 | 
						|
    //
 | 
						|
    // In all cases, commands remain queued until Invoked or Cancelled. The
 | 
						|
    // setting and resetting of the event handle is managed entirely by this
 | 
						|
    // queue object.
 | 
						|
 | 
						|
    // set the clock used for timing
 | 
						|
    virtual HRESULT SetSyncSource(__in_opt IReferenceClock*);
 | 
						|
 | 
						|
    // switch to run mode. Streamtime to Presentation time mapping known.
 | 
						|
    virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
 | 
						|
 | 
						|
    // switch to Stopped or Paused mode. Time mapping not known.
 | 
						|
    virtual HRESULT EndRun();
 | 
						|
 | 
						|
    // return a pointer to the next due command. Blocks for msTimeout
 | 
						|
    // milliseconds until there is a due command.
 | 
						|
    // Stream-time commands will only become due between Run and Endrun calls.
 | 
						|
    // The command remains queued until invoked or cancelled.
 | 
						|
    // Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
 | 
						|
    // Returns an AddRef-ed object
 | 
						|
    virtual HRESULT GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout);
 | 
						|
 | 
						|
    // return the event handle that will be signalled whenever
 | 
						|
    // there are deferred commands due for execution (when GetDueCommand
 | 
						|
    // will not block).
 | 
						|
    HANDLE GetDueHandle() {
 | 
						|
        return HANDLE(m_evDue);
 | 
						|
    };
 | 
						|
 | 
						|
    // return a pointer to a command that will be due for a given time.
 | 
						|
    // Pass in a stream time here. The stream time offset will be passed
 | 
						|
    // in via the Run method.
 | 
						|
    // Commands remain queued until invoked or cancelled.
 | 
						|
    // This method will not block. It will report VFW_E_NOT_FOUND if there
 | 
						|
    // are no commands due yet.
 | 
						|
    // Returns an AddRef-ed object
 | 
						|
    virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, __out CDeferredCommand**ppCmd);
 | 
						|
 | 
						|
    // check if a given time is due (TRUE if it is due yet)
 | 
						|
    BOOL CheckTime(CRefTime time, BOOL bStream) {
 | 
						|
 | 
						|
        // if no clock, nothing is due!
 | 
						|
        if (!m_pClock) {
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        // stream time
 | 
						|
        if (bStream) {
 | 
						|
 | 
						|
            // not valid if not running
 | 
						|
            if (!m_bRunning) {
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
            // add on known stream time offset to get presentation time
 | 
						|
            time += m_StreamTimeOffset;
 | 
						|
        }
 | 
						|
 | 
						|
        CRefTime Now;
 | 
						|
        m_pClock->GetTime((REFERENCE_TIME*)&Now);
 | 
						|
        return (time <= Now);
 | 
						|
    };
 | 
						|
 | 
						|
protected:
 | 
						|
 | 
						|
    // protect access to lists etc
 | 
						|
    CCritSec m_Lock;
 | 
						|
 | 
						|
    // commands queued in presentation time are stored here
 | 
						|
    CGenericList<CDeferredCommand> m_listPresentation;
 | 
						|
 | 
						|
    // commands queued in stream time are stored here
 | 
						|
    CGenericList<CDeferredCommand> m_listStream;
 | 
						|
 | 
						|
    // set when any commands are due
 | 
						|
    CAMEvent m_evDue;
 | 
						|
 | 
						|
    // creates an advise for the earliest time required, if any
 | 
						|
    void SetTimeAdvise(void);
 | 
						|
 | 
						|
    // advise id from reference clock (0 if no outstanding advise)
 | 
						|
    DWORD_PTR m_dwAdvise;
 | 
						|
 | 
						|
    // advise time is for this presentation time
 | 
						|
    CRefTime m_tCurrentAdvise;
 | 
						|
 | 
						|
    // the reference clock we are using (addrefed)
 | 
						|
    IReferenceClock* m_pClock;
 | 
						|
 | 
						|
    // true when running
 | 
						|
    BOOL m_bRunning;
 | 
						|
 | 
						|
    // contains stream time offset when m_bRunning is true
 | 
						|
    CRefTime m_StreamTimeOffset;
 | 
						|
};
 | 
						|
 | 
						|
#endif // __CTLUTIL__
 |