mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-08 05:42:54 +02:00
Update it to the version found at https://github.com/Microsoft/Windows-classic-samples , which is in an MIT licensed repo, and add the LICENSE file (edited to remove the SIL Open Font LICENSE part since that doesn't apply). Some modifications have been made to reduce the diff/stop git complaining (not including any file that wasn't in the previous version and removing the related header includes in streams.h, and fixing some but not all of the whitespace issues).
924 lines
27 KiB
C++
924 lines
27 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__
|