uint32 VDDubPreviewClock::ReadClock() const { uint32 ticks; if (mpTimer) ticks = mpTimer->GetPreviewTime(); else ticks = VDGetAccurateTick() - mBaseTime; return VDRoundToInt32((double)ticks * mTicksToFrames); }
void VDDubPreviewClock::Init(IVDDubPreviewTimer *timer, IVDAsyncBlitter *blitter, double frameRate, double frameMultiplicationFactor) { mpTimer = timer; mpBlitter = blitter; mBaseTime = VDGetAccurateTick(); mTicksToFrames = frameRate / 1000.0 * frameMultiplicationFactor; sint32 resolution; if (frameRate > 100.0) { resolution = VDRoundToInt32(10000000.0 / frameRate); } else { resolution = VDRoundToInt32(10000000.0 / 4.0 / frameRate); if (resolution < 10000) resolution = 10000; } mFrameTimer.Init3(this, resolution, resolution, false); }
void VDLoopThrottle::BeginWait() { if (!mWaitDepth++) { // transitioning active -> wait uint32 currentTime = VDGetAccurateTick(); if (mbLastTimeValid) { sint32 delta = currentTime - mLastTime; // Time shouldn't ever go backwards, but clocks on Windows occasionally have // the habit of doing so due to time adjustments, broken RDTSC, etc. if (delta < 0) delta = 0; mActiveTimeWindowSum -= mActiveTimeWindow[mWindowIndex]; mActiveTimeWindow[mWindowIndex] = delta; mActiveTimeWindowSum += delta; } mLastTime = currentTime; mbLastTimeValid = true; } }
void VDCallbackTimer::ThreadRun() { uint32 timerPeriod = mTimerPeriod; uint32 periodHi = timerPeriod / 10000; uint32 periodLo = timerPeriod % 10000; uint32 nextTimeHi = VDGetAccurateTick() + periodHi; uint32 nextTimeLo = periodLo; uint32 maxDelay = mTimerPeriod / 2000; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); HANDLE hExit = msigExit.getHandle(); if (!mbPrecise) { while(!mbExit) { DWORD res = ::WaitForSingleObject(hExit, periodHi); if (res != WAIT_TIMEOUT) break; mpCB->TimerCallback(); } } else { while(!mbExit) { uint32 currentTime = VDGetAccurateTick(); sint32 delta = nextTimeHi - currentTime; if (delta > 0) { // safety guard against the clock going nuts DWORD res; if ((uint32)delta > maxDelay) res = ::WaitForSingleObject(hExit, maxDelay); else res = ::WaitForSingleObject(hExit, nextTimeHi - currentTime); if (res != WAIT_TIMEOUT) break; } if ((uint32)abs(delta) > maxDelay) { nextTimeHi = currentTime + periodHi; nextTimeLo = periodLo; } else { nextTimeLo += periodLo; nextTimeHi += periodHi; if (nextTimeLo >= 10000) { nextTimeLo -= 10000; ++nextTimeHi; } } mpCB->TimerCallback(); int adjust = mTimerPeriodAdjustment.xchg(0); int perdelta = mTimerPeriodDelta; if (adjust || perdelta) { timerPeriod += adjust; periodHi = (timerPeriod+perdelta) / 10000; periodLo = (timerPeriod+perdelta) % 10000; } } } }