AJA NTV2 SDK  17.6.0.2675
NTV2 SDK 17.6.0.2675
refclock.h
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // File: RefClock.h
3 //
4 // Desc: DirectShow base classes - defines the IReferenceClock interface.
5 //
6 // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
8 
9 
10 #ifndef __BASEREFCLOCK__
11 #define __BASEREFCLOCK__
12 
13 #include "Schedule.h"
14 
15 const UINT RESOLUTION = 1; /* High resolution timer */
16 const INT ADVISE_CACHE = 4; /* Default cache size */
17 const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */
18 
19 inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
20 {
21  /* This converts an arbitrary value representing a reference time
22  into a MILLISECONDS value for use in subsequent system calls */
23 
24  return (RT / (UNITS / MILLISECONDS));
25 }
26 
27 /* This class hierarchy will support an IReferenceClock interface so
28  that an audio card (or other externally driven clock) can update the
29  system wide clock that everyone uses.
30 
31  The interface will be pretty thin with probably just one update method
32  This interface has not yet been defined.
33  */
34 
35 /* This abstract base class implements the IReferenceClock
36  * interface. Classes that actually provide clock signals (from
37  * whatever source) have to be derived from this class.
38  *
39  * The abstract class provides implementations for:
40  * CUnknown support
41  * locking support (CCritSec)
42  * client advise code (creates a thread)
43  *
44  * Question: what can we do about quality? Change the timer
45  * resolution to lower the system load? Up the priority of the
46  * timer thread to force more responsive signals?
47  *
48  * During class construction we create a worker thread that is destroyed during
49  * destuction. This thread executes a series of WaitForSingleObject calls,
50  * waking up when a command is given to the thread or the next wake up point
51  * is reached. The wakeup points are determined by clients making Advise
52  * calls.
53  *
54  * Each advise call defines a point in time when they wish to be notified. A
55  * periodic advise is a series of these such events. We maintain a list of
56  * advise links and calculate when the nearest event notification is due for.
57  * We then call WaitForSingleObject with a timeout equal to this time. The
58  * handle we wait on is used by the class to signal that something has changed
59  * and that we must reschedule the next event. This typically happens when
60  * someone comes in and asks for an advise link while we are waiting for an
61  * event to timeout.
62  *
63  * While we are modifying the list of advise requests we
64  * are protected from interference through a critical section. Clients are NOT
65  * advised through callbacks. One shot clients have an event set, while
66  * periodic clients have a semaphore released for each event notification. A
67  * semaphore allows a client to be kept up to date with the number of events
68  * actually triggered and be assured that they can't miss multiple events being
69  * set.
70  *
71  * Keeping track of advises is taken care of by the CAMSchedule class.
72  */
73 
75 : public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl
76 {
77 protected:
78  virtual ~CBaseReferenceClock(); // Don't let me be created on the stack!
79 public:
80  CBaseReferenceClock(__in_opt LPCTSTR pName,
81  __inout_opt LPUNKNOWN pUnk,
82  __inout HRESULT *phr,
83  __inout_opt CAMSchedule * pSched = 0 );
84 
85  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
86 
88 
89  /* IReferenceClock methods */
90  // Derived classes must implement GetPrivateTime(). All our GetTime
91  // does is call GetPrivateTime and then check so that time does not
92  // go backwards. A return code of S_FALSE implies that the internal
93  // clock has gone backwards and GetTime time has halted until internal
94  // time has caught up. (Don't know if this will be much use to folk,
95  // but it seems odd not to use the return code for something useful.)
96  STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime);
97  // When this is called, it sets m_rtLastGotTime to the time it returns.
98 
99  /* Provide standard mechanisms for scheduling events */
100 
101  /* Ask for an async notification that a time has elapsed */
102  STDMETHODIMP AdviseTime(
103  REFERENCE_TIME baseTime, // base reference time
104  REFERENCE_TIME streamTime, // stream offset time
105  HEVENT hEvent, // advise via this event
106  __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
107  );
108 
109  /* Ask for an asynchronous periodic notification that a time has elapsed */
110  STDMETHODIMP AdvisePeriodic(
111  REFERENCE_TIME StartTime, // starting at this time
112  REFERENCE_TIME PeriodTime, // time between notifications
113  HSEMAPHORE hSemaphore, // advise via a semaphore
114  __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
115  );
116 
117  /* Cancel a request for notification(s) - if the notification was
118  * a one shot timer then this function doesn't need to be called
119  * as the advise is automatically cancelled, however it does no
120  * harm to explicitly cancel a one-shot advise. It is REQUIRED that
121  * clients call Unadvise to clear a Periodic advise setting.
122  */
123 
124  STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
125 
126  /* Methods for the benefit of derived classes or outer objects */
127 
128  // GetPrivateTime() is the REAL clock. GetTime is just a cover for
129  // it. Derived classes will probably override this method but not
130  // GetTime() itself.
131  // The important point about GetPrivateTime() is it's allowed to go
132  // backwards. Our GetTime() will keep returning the LastGotTime
133  // until GetPrivateTime() catches up.
134  virtual REFERENCE_TIME GetPrivateTime();
135 
136  /* Provide a method for correcting drift */
137  STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
138 
139  CAMSchedule * GetSchedule() const { return m_pSchedule; }
140 
141  // IReferenceClockTimerControl methods
142  //
143  // Setting a default of 0 disables the default of 1ms
144  STDMETHODIMP SetDefaultTimerResolution(
145  REFERENCE_TIME timerResolution // in 100ns
146  );
147  STDMETHODIMP GetDefaultTimerResolution(
148  __out REFERENCE_TIME* pTimerResolution // in 100ns
149  );
150 
151 private:
152  REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time
153  DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime
154  REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime
155  REFERENCE_TIME m_rtNextAdvise; // Time of next advise
156  UINT m_TimerResolution;
157 
158 #ifdef PERF
159  int m_idGetSystemTime;
160 #endif
161 
162 // Thread stuff
163 public:
164  void TriggerThread() // Wakes thread up. Need to do this if
165  { // time to next advise needs reevaluating.
166  EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
167  }
168 
169 
170 private:
171  BOOL m_bAbort; // Flag used for thread shutdown
172  HANDLE m_hThread; // Thread handle
173 
174  HRESULT AdviseThread(); // Method in which the advise thread runs
175  static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there
176 
177 protected:
179 
180  void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
181 };
182 
183 #endif
184 
DECLARE_IUNKNOWN
#define DECLARE_IUNKNOWN
Definition: combase.h:285
CBaseReferenceClock::AdviseTime
STDMETHODIMP AdviseTime(REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HEVENT hEvent, __out DWORD_PTR *pdwAdviseCookie)
Definition: refclock.cpp:175
HANDLE
short HANDLE
Definition: ajatypes.h:318
schedule.h
CBaseReferenceClock::GetPrivateTime
virtual REFERENCE_TIME GetPrivateTime()
Definition: refclock.cpp:232
CAMSchedule::GetEvent
HANDLE GetEvent() const
Definition: schedule.h:34
CBaseReferenceClock::CBaseReferenceClock
CBaseReferenceClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr, __inout_opt CAMSchedule *pSched=0)
Definition: refclock.cpp:71
MAX_TIME
const LONGLONG MAX_TIME
Definition: refclock.h:17
CBaseReferenceClock::Restart
void Restart(IN REFERENCE_TIME rtMinTime=0I64)
Definition: refclock.cpp:135
MILLISECONDS
const LONGLONG MILLISECONDS
Definition: reftime.h:39
RESOLUTION
const UINT RESOLUTION
Definition: refclock.h:15
CBaseReferenceClock::m_pSchedule
CAMSchedule * m_pSchedule
Definition: refclock.h:178
CBaseReferenceClock::SetDefaultTimerResolution
STDMETHODIMP SetDefaultTimerResolution(REFERENCE_TIME timerResolution)
Definition: refclock.cpp:367
CBaseReferenceClock
Definition: refclock.h:74
ConvertToMilliseconds
LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME &RT)
Definition: refclock.h:19
pName
CHAR * pName
Definition: amvideo.cpp:26
ADVISE_CACHE
const INT ADVISE_CACHE
Definition: refclock.h:16
CBaseReferenceClock::~CBaseReferenceClock
virtual ~CBaseReferenceClock()
Definition: refclock.cpp:43
CCritSec
Definition: wxutil.h:18
riid
__in REFIID riid
Definition: dllentry.cpp:192
EXECUTE_ASSERT
#define EXECUTE_ASSERT(_x_)
Definition: wxdebug.h:207
CUnknown
Definition: combase.h:200
CBaseReferenceClock::NonDelegatingQueryInterface
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
Definition: refclock.cpp:22
CBaseReferenceClock::TriggerThread
void TriggerThread()
Definition: refclock.h:164
UNITS
const LONGLONG UNITS
Definition: reftime.h:41
CAMSchedule
Definition: schedule.h:13
CBaseReferenceClock::GetTime
DECLARE_IUNKNOWN STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime)
Definition: refclock.cpp:142
CBaseReferenceClock::GetDefaultTimerResolution
STDMETHODIMP GetDefaultTimerResolution(__out REFERENCE_TIME *pTimerResolution)
Definition: refclock.cpp:392
CBaseReferenceClock::SetTimeDelta
STDMETHODIMP SetTimeDelta(const REFERENCE_TIME &TimeDelta)
Definition: refclock.cpp:264
CBaseReferenceClock::Unadvise
STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie)
Definition: refclock.cpp:226
CBaseReferenceClock::GetSchedule
CAMSchedule * GetSchedule() const
Definition: refclock.h:139
CBaseReferenceClock::AdvisePeriodic
STDMETHODIMP AdvisePeriodic(REFERENCE_TIME StartTime, REFERENCE_TIME PeriodTime, HSEMAPHORE hSemaphore, __out DWORD_PTR *pdwAdviseCookie)
Definition: refclock.cpp:205