home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / system / source / time.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-09-02  |  5.1 KB  |  209 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <new>
  28.  
  29. #include <windows.h>
  30. #include <mmsystem.h>
  31.  
  32. #include <vd2/system/time.h>
  33. #include <vd2/system/thread.h>
  34.  
  35. #ifdef _MSC_VER
  36.     #pragma comment(lib, "winmm")
  37. #endif
  38.  
  39. uint32 VDGetCurrentTick() {
  40.     return (uint32)GetTickCount();
  41. }
  42.  
  43. uint64 VDGetPreciseTick() {
  44.     LARGE_INTEGER li;
  45.     QueryPerformanceCounter(&li);
  46.     return li.QuadPart;
  47. }
  48.  
  49. namespace {
  50.     uint64 VDGetPreciseTicksPerSecondNowI() {
  51.         LARGE_INTEGER freq;
  52.         QueryPerformanceFrequency(&freq);
  53.         return freq.QuadPart;
  54.     }
  55.  
  56.     double VDGetPreciseTicksPerSecondNow() {
  57.         LARGE_INTEGER freq;
  58.         QueryPerformanceFrequency(&freq);
  59.         return (double)freq.QuadPart;
  60.     }
  61. }
  62.  
  63. uint64 VDGetPreciseTicksPerSecondI() {
  64.     static uint64 ticksPerSecond = VDGetPreciseTicksPerSecondNowI();
  65.  
  66.     return ticksPerSecond;
  67. }
  68.  
  69. double VDGetPreciseTicksPerSecond() {
  70.     static double ticksPerSecond = VDGetPreciseTicksPerSecondNow();
  71.  
  72.     return ticksPerSecond;
  73. }
  74.  
  75. double VDGetPreciseSecondsPerTick() {
  76.     static double secondsPerTick = 1.0 / VDGetPreciseTicksPerSecondNow();
  77.  
  78.     return secondsPerTick;
  79. }
  80.  
  81. uint32 VDGetAccurateTick() {
  82.     return timeGetTime();
  83. }
  84.  
  85. ///////////////////////////////////////////////////////////////////////////////
  86. VDCallbackTimer::VDCallbackTimer()
  87.     : mTimerAccuracy(0)
  88. {
  89. }
  90.  
  91. VDCallbackTimer::~VDCallbackTimer() {
  92.     Shutdown();
  93. }
  94.  
  95. bool VDCallbackTimer::Init(IVDTimerCallback *pCB, uint32 period_ms) {
  96.     return Init2(pCB, period_ms * 10000);
  97. }
  98.  
  99. bool VDCallbackTimer::Init2(IVDTimerCallback *pCB, uint32 period_100ns) {
  100.     Shutdown();
  101.  
  102.     mpCB = pCB;
  103.     mbExit = false;
  104.     UINT accuracy = period_100ns / 20000;
  105.     if (accuracy > 10)
  106.         accuracy = 10;
  107.  
  108.     TIMECAPS tc;
  109.     if (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof tc)) {
  110.         if (accuracy < tc.wPeriodMin)
  111.             accuracy = tc.wPeriodMin;
  112.         if (accuracy > tc.wPeriodMax)
  113.             accuracy = tc.wPeriodMax;
  114.     }
  115.  
  116.     if (TIMERR_NOERROR == timeBeginPeriod(accuracy)) {
  117.         mTimerAccuracy = accuracy;
  118.         mTimerPeriod = period_100ns;
  119.         mTimerPeriodAdjustment = 0;
  120.         mTimerPeriodDelta = 0;
  121.  
  122.         if (ThreadStart())
  123.             return true;
  124.     }
  125.  
  126.     Shutdown();
  127.  
  128.     return false;
  129. }
  130.  
  131. void VDCallbackTimer::Shutdown() {
  132.     if (isThreadActive()) {
  133.         mbExit = true;
  134.         msigExit.signal();
  135.         ThreadWait();
  136.     }
  137.  
  138.     if (mTimerAccuracy) {
  139.         timeEndPeriod(mTimerAccuracy);
  140.         mTimerAccuracy = 0;
  141.     }
  142. }
  143.  
  144. void VDCallbackTimer::SetRateDelta(int delta_100ns) {
  145.     mTimerPeriodDelta = delta_100ns;
  146. }
  147.  
  148. void VDCallbackTimer::AdjustRate(int adjustment_100ns) {
  149.     mTimerPeriodAdjustment += adjustment_100ns;
  150. }
  151.  
  152. bool VDCallbackTimer::IsTimerRunning() const {
  153.     return const_cast<VDCallbackTimer *>(this)->isThreadActive();
  154. }
  155.  
  156. void VDCallbackTimer::ThreadRun() {
  157.     uint32 timerPeriod = mTimerPeriod;
  158.     uint32 periodHi = timerPeriod / 10000;
  159.     uint32 periodLo = timerPeriod % 10000;
  160.     uint32 nextTimeHi = VDGetAccurateTick() + periodHi;
  161.     uint32 nextTimeLo = periodLo;
  162.  
  163.     uint32 maxDelay = mTimerPeriod / 2000;
  164.  
  165.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  166.  
  167.     HANDLE hExit = msigExit.getHandle();
  168.  
  169.     while(!mbExit) {
  170.         uint32 currentTime = VDGetAccurateTick();
  171.         sint32 delta = nextTimeHi - currentTime;
  172.  
  173.         if (delta > 0) {
  174.             // safety guard against the clock going nuts
  175.             DWORD res;
  176.             if ((uint32)delta > maxDelay)
  177.                 res = ::WaitForSingleObject(hExit, maxDelay);
  178.             else
  179.                 res = ::WaitForSingleObject(hExit, nextTimeHi - currentTime);
  180.  
  181.             if (res != WAIT_TIMEOUT)
  182.                 break;
  183.         }
  184.  
  185.         if ((uint32)abs(delta) > maxDelay) {
  186.             nextTimeHi = currentTime + periodHi;
  187.             nextTimeLo = periodLo;
  188.         } else {
  189.             nextTimeLo += periodLo;
  190.             nextTimeHi += periodHi;
  191.             if (nextTimeLo >= 10000) {
  192.                 nextTimeLo -= 10000;
  193.                 ++nextTimeHi;
  194.             }
  195.         }
  196.  
  197.         mpCB->TimerCallback();
  198.  
  199.         int adjust = mTimerPeriodAdjustment.xchg(0);
  200.         int perdelta = mTimerPeriodDelta;
  201.  
  202.         if (adjust || perdelta) {
  203.             timerPeriod += adjust;
  204.             periodHi = (timerPeriod+perdelta) / 10000;
  205.             periodLo = (timerPeriod+perdelta) % 10000;
  206.         }
  207.     }
  208. }
  209.