diff options
Diffstat (limited to 'src/thirdparty/BaseClasses/refclock.h')
-rw-r--r-- | src/thirdparty/BaseClasses/refclock.h | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/thirdparty/BaseClasses/refclock.h b/src/thirdparty/BaseClasses/refclock.h new file mode 100644 index 000000000..2a8d38434 --- /dev/null +++ b/src/thirdparty/BaseClasses/refclock.h @@ -0,0 +1,184 @@ +//------------------------------------------------------------------------------
+// File: RefClock.h
+//
+// Desc: DirectShow base classes - defines the IReferenceClock interface.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __BASEREFCLOCK__
+#define __BASEREFCLOCK__
+
+#include "Schedule.h"
+
+const UINT RESOLUTION = 1; /* High resolution timer */
+const INT ADVISE_CACHE = 4; /* Default cache size */
+const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */
+
+inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
+{
+ /* This converts an arbitrary value representing a reference time
+ into a MILLISECONDS value for use in subsequent system calls */
+
+ return (RT / (UNITS / MILLISECONDS));
+}
+
+/* This class hierarchy will support an IReferenceClock interface so
+ that an audio card (or other externally driven clock) can update the
+ system wide clock that everyone uses.
+
+ The interface will be pretty thin with probably just one update method
+ This interface has not yet been defined.
+ */
+
+/* This abstract base class implements the IReferenceClock
+ * interface. Classes that actually provide clock signals (from
+ * whatever source) have to be derived from this class.
+ *
+ * The abstract class provides implementations for:
+ * CUnknown support
+ * locking support (CCritSec)
+ * client advise code (creates a thread)
+ *
+ * Question: what can we do about quality? Change the timer
+ * resolution to lower the system load? Up the priority of the
+ * timer thread to force more responsive signals?
+ *
+ * During class construction we create a worker thread that is destroyed during
+ * destuction. This thread executes a series of WaitForSingleObject calls,
+ * waking up when a command is given to the thread or the next wake up point
+ * is reached. The wakeup points are determined by clients making Advise
+ * calls.
+ *
+ * Each advise call defines a point in time when they wish to be notified. A
+ * periodic advise is a series of these such events. We maintain a list of
+ * advise links and calculate when the nearest event notification is due for.
+ * We then call WaitForSingleObject with a timeout equal to this time. The
+ * handle we wait on is used by the class to signal that something has changed
+ * and that we must reschedule the next event. This typically happens when
+ * someone comes in and asks for an advise link while we are waiting for an
+ * event to timeout.
+ *
+ * While we are modifying the list of advise requests we
+ * are protected from interference through a critical section. Clients are NOT
+ * advised through callbacks. One shot clients have an event set, while
+ * periodic clients have a semaphore released for each event notification. A
+ * semaphore allows a client to be kept up to date with the number of events
+ * actually triggered and be assured that they can't miss multiple events being
+ * set.
+ *
+ * Keeping track of advises is taken care of by the CAMSchedule class.
+ */
+
+class CBaseReferenceClock
+: public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl
+{
+protected:
+ virtual ~CBaseReferenceClock(); // Don't let me be created on the stack!
+public:
+ CBaseReferenceClock(__in_opt LPCTSTR pName,
+ __inout_opt LPUNKNOWN pUnk,
+ __inout HRESULT *phr,
+ __inout_opt CAMSchedule * pSched = 0 );
+
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+
+ DECLARE_IUNKNOWN
+
+ /* IReferenceClock methods */
+ // Derived classes must implement GetPrivateTime(). All our GetTime
+ // does is call GetPrivateTime and then check so that time does not
+ // go backwards. A return code of S_FALSE implies that the internal
+ // clock has gone backwards and GetTime time has halted until internal
+ // time has caught up. (Don't know if this will be much use to folk,
+ // but it seems odd not to use the return code for something useful.)
+ STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime);
+ // When this is called, it sets m_rtLastGotTime to the time it returns.
+
+ /* Provide standard mechanisms for scheduling events */
+
+ /* Ask for an async notification that a time has elapsed */
+ STDMETHODIMP AdviseTime(
+ REFERENCE_TIME baseTime, // base reference time
+ REFERENCE_TIME streamTime, // stream offset time
+ HEVENT hEvent, // advise via this event
+ __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
+ );
+
+ /* Ask for an asynchronous periodic notification that a time has elapsed */
+ STDMETHODIMP AdvisePeriodic(
+ REFERENCE_TIME StartTime, // starting at this time
+ REFERENCE_TIME PeriodTime, // time between notifications
+ HSEMAPHORE hSemaphore, // advise via a semaphore
+ __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
+ );
+
+ /* Cancel a request for notification(s) - if the notification was
+ * a one shot timer then this function doesn't need to be called
+ * as the advise is automatically cancelled, however it does no
+ * harm to explicitly cancel a one-shot advise. It is REQUIRED that
+ * clients call Unadvise to clear a Periodic advise setting.
+ */
+
+ STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
+
+ /* Methods for the benefit of derived classes or outer objects */
+
+ // GetPrivateTime() is the REAL clock. GetTime is just a cover for
+ // it. Derived classes will probably override this method but not
+ // GetTime() itself.
+ // The important point about GetPrivateTime() is it's allowed to go
+ // backwards. Our GetTime() will keep returning the LastGotTime
+ // until GetPrivateTime() catches up.
+ virtual REFERENCE_TIME GetPrivateTime();
+
+ /* Provide a method for correcting drift */
+ STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
+
+ CAMSchedule * GetSchedule() const { return m_pSchedule; }
+
+ // IReferenceClockTimerControl methods
+ //
+ // Setting a default of 0 disables the default of 1ms
+ STDMETHODIMP SetDefaultTimerResolution(
+ REFERENCE_TIME timerResolution // in 100ns
+ );
+ STDMETHODIMP GetDefaultTimerResolution(
+ __out REFERENCE_TIME* pTimerResolution // in 100ns
+ );
+
+private:
+ REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time
+ DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime
+ REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime
+ REFERENCE_TIME m_rtNextAdvise; // Time of next advise
+ UINT m_TimerResolution;
+
+#ifdef PERF
+ int m_idGetSystemTime;
+#endif
+
+// Thread stuff
+public:
+ void TriggerThread() // Wakes thread up. Need to do this if
+ { // time to next advise needs reevaluating.
+ EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
+ }
+
+
+private:
+ BOOL m_bAbort; // Flag used for thread shutdown
+ HANDLE m_hThread; // Thread handle
+
+ HRESULT AdviseThread(); // Method in which the advise thread runs
+ static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there
+
+protected:
+ CAMSchedule * m_pSchedule;
+
+ void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
+};
+
+#endif
+
|