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