123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #include <streams.h>
- #include <limits.h>
- #ifdef DXMPERF
- #include "dxmperf.h"
- #endif
- #pragma warning(disable:4355)
- STDMETHODIMP CBaseReferenceClock::NonDelegatingQueryInterface(
- REFIID riid,
- __deref_out void ** ppv)
- {
- HRESULT hr;
- if (riid == IID_IReferenceClock)
- {
- hr = GetInterface((IReferenceClock *) this, ppv);
- }
- else if (riid == IID_IReferenceClockTimerControl)
- {
- hr = GetInterface((IReferenceClockTimerControl *) this, ppv);
- }
- else
- {
- hr = CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
- return hr;
- }
- CBaseReferenceClock::~CBaseReferenceClock()
- {
- #ifdef DXMPERF
- PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this );
- #endif
- if (m_TimerResolution) timeEndPeriod(m_TimerResolution);
- if (m_pSchedule)
- {
- m_pSchedule->DumpLinkedList();
- }
- if (m_hThread)
- {
- m_bAbort = TRUE;
- TriggerThread();
- WaitForSingleObject( m_hThread, INFINITE );
- EXECUTE_ASSERT( CloseHandle(m_hThread) );
- m_hThread = 0;
- EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
- delete m_pSchedule;
- }
- }
- CBaseReferenceClock::CBaseReferenceClock( __in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- __inout_opt CAMSchedule * pShed )
- : CUnknown( pName, pUnk )
- , m_rtLastGotTime(0)
- , m_TimerResolution(0)
- , m_bAbort( FALSE )
- , m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) )
- , m_hThread(0)
- {
- #ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBaseReferenceClock", (IReferenceClock *) this );
- #endif
- ASSERT(m_pSchedule);
- if (!m_pSchedule)
- {
- *phr = E_OUTOFMEMORY;
- }
- else
- {
-
- TIMECAPS tc;
- m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
- ? tc.wPeriodMin
- : 1;
- timeBeginPeriod(m_TimerResolution);
-
- m_dwPrevSystemTime = timeGetTime();
- m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime;
- #ifdef PERF
- m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime"));
- #endif
- if ( !pShed )
- {
- DWORD ThreadID;
- m_hThread = ::CreateThread(NULL,
- (DWORD) 0,
- AdviseThreadFunction,
- (LPVOID) this,
- (DWORD) 0,
- &ThreadID);
- if (m_hThread)
- {
- SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL );
- }
- else
- {
- *phr = E_FAIL;
- EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
- delete m_pSchedule;
- m_pSchedule = NULL;
- }
- }
- }
- }
- void CBaseReferenceClock::Restart (IN REFERENCE_TIME rtMinTime)
- {
- Lock();
- m_rtLastGotTime = rtMinTime ;
- Unlock();
- }
- STDMETHODIMP CBaseReferenceClock::GetTime(__out REFERENCE_TIME *pTime)
- {
- HRESULT hr;
- if (pTime)
- {
- REFERENCE_TIME rtNow;
- Lock();
- rtNow = GetPrivateTime();
- if (rtNow > m_rtLastGotTime)
- {
- m_rtLastGotTime = rtNow;
- hr = S_OK;
- }
- else
- {
- hr = S_FALSE;
- }
- *pTime = m_rtLastGotTime;
- Unlock();
- MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) );
- #ifdef DXMPERF
- PERFLOG_GETTIME( (IReferenceClock *) this, *pTime );
- #endif
- }
- else hr = E_POINTER;
- return hr;
- }
- STDMETHODIMP CBaseReferenceClock::AdviseTime(
- REFERENCE_TIME baseTime,
- REFERENCE_TIME streamTime,
- HEVENT hEvent,
- __out DWORD_PTR *pdwAdviseCookie)
- {
- CheckPointer(pdwAdviseCookie, E_POINTER);
- *pdwAdviseCookie = 0;
-
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0));
- HRESULT hr;
- const REFERENCE_TIME lRefTime = baseTime + streamTime;
- if ( lRefTime <= 0 || lRefTime == MAX_TIME )
- {
- hr = E_INVALIDARG;
- }
- else
- {
- *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE );
- hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
- }
- return hr;
- }
- STDMETHODIMP CBaseReferenceClock::AdvisePeriodic(
- REFERENCE_TIME StartTime,
- REFERENCE_TIME PeriodTime,
- HSEMAPHORE hSemaphore,
- __out DWORD_PTR *pdwAdviseCookie)
- {
- CheckPointer(pdwAdviseCookie, E_POINTER);
- *pdwAdviseCookie = 0;
- HRESULT hr;
- if (StartTime > 0 && PeriodTime > 0 && StartTime != MAX_TIME )
- {
- *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE );
- hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
- }
- else hr = E_INVALIDARG;
- return hr;
- }
- STDMETHODIMP CBaseReferenceClock::Unadvise(DWORD_PTR dwAdviseCookie)
- {
- return m_pSchedule->Unadvise(dwAdviseCookie);
- }
- REFERENCE_TIME CBaseReferenceClock::GetPrivateTime()
- {
- CAutoLock cObjectLock(this);
-
- DWORD dwTime = timeGetTime();
- {
- m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime));
- m_dwPrevSystemTime = dwTime;
- }
- return m_rtPrivateTime;
- }
- STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta)
- {
- #ifdef DEBUG
-
- LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta;
- if (llDelta > UNITS * 1000) {
- DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta")));
-
- }
-
-
-
- const LONG usDelta = LONG(TimeDelta/10);
- DWORD delta = abs(usDelta);
-
- int Severity = 8;
- while ( delta > 0 )
- {
- delta >>= 3;
- Severity--;
- }
-
- DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity,
- TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."),
- Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)),
- DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) ));
-
- #ifdef BREAK_ON_SEVERE_TIME_DELTA
- if (Severity < 0)
- DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"),
- TEXT(__FILE__),__LINE__);
- #endif
- #endif
- CAutoLock cObjectLock(this);
- m_rtPrivateTime += TimeDelta;
-
-
-
-
-
-
-
- if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread();
- return NOERROR;
- }
- DWORD __stdcall CBaseReferenceClock::AdviseThreadFunction(__in LPVOID p)
- {
- return DWORD(reinterpret_cast<CBaseReferenceClock*>(p)->AdviseThread());
- }
- HRESULT CBaseReferenceClock::AdviseThread()
- {
- DWORD dwWait = INFINITE;
-
-
-
-
-
- while ( !m_bAbort )
- {
-
- DbgLog((LOG_TIMING, 3, TEXT("CBaseRefClock::AdviseThread() Delay: %lu ms"), dwWait ));
- WaitForSingleObject(m_pSchedule->GetEvent(), dwWait);
- if (m_bAbort) break;
-
-
-
-
-
- const REFERENCE_TIME rtNow = GetPrivateTime();
- DbgLog((LOG_TIMING, 3,
- TEXT("CBaseRefClock::AdviseThread() Woke at = %lu ms"),
- ConvertToMilliseconds(rtNow) ));
-
-
-
- m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow );
- LONGLONG llWait = m_rtNextAdvise - rtNow;
- ASSERT( llWait > 0 );
- llWait = ConvertToMilliseconds(llWait);
-
- dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait);
- };
- return NOERROR;
- }
- HRESULT CBaseReferenceClock::SetDefaultTimerResolution(
- REFERENCE_TIME timerResolution
- )
- {
- CAutoLock cObjectLock(this);
- if( 0 == timerResolution ) {
- if( m_TimerResolution ) {
- timeEndPeriod( m_TimerResolution );
- m_TimerResolution = 0;
- }
- } else {
- TIMECAPS tc;
- DWORD dwMinResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
- ? tc.wPeriodMin
- : 1;
- DWORD dwResolution = max( dwMinResolution, DWORD(timerResolution / 10000) );
- if( dwResolution != m_TimerResolution ) {
- timeEndPeriod(m_TimerResolution);
- m_TimerResolution = dwResolution;
- timeBeginPeriod( m_TimerResolution );
- }
- }
- return S_OK;
- }
- HRESULT CBaseReferenceClock::GetDefaultTimerResolution(
- __out REFERENCE_TIME* pTimerResolution
- )
- {
- if( !pTimerResolution ) {
- return E_POINTER;
- }
- CAutoLock cObjectLock(this);
- *pTimerResolution = m_TimerResolution * 10000;
- return S_OK;
- }
|