From e54e5eb9bb70b4e1fe2fbf93dcefd8eabcbe7efa Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 28 Aug 2009 17:02:30 +0200 Subject: [PATCH] systemclock: use preformance counters on windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on clock implementation by HÃ¥vard Graff Try to get the time on windows using the performance counters. These have a much higher resolution and accuracy than the regular getcurrenttime(). Be careful to fall back to regular getcurrenttime() or posix clocks when performance counters are not available. --- gst/gstsystemclock.c | 82 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 2a74fed494..2b2ef0b8d5 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -46,6 +46,12 @@ #include +#ifdef G_OS_WIN32 +# define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ +# include /* QueryPerformance* stuff */ +# undef WIN32_LEAN_AND_MEAN +#endif /* G_OS_WIN32 */ + /* Define this to get some extra debug about jitter from each clock_wait */ #undef WAIT_DEBUGGING @@ -55,6 +61,11 @@ struct _GstSystemClockPrivate GstPoll *timer; gint wakeup_count; /* the number of entries with a pending wakeup */ gboolean async_wakeup; /* if the wakeup was because of a async list change */ + +#ifdef G_OS_WIN32 + LARGE_INTEGER start; + LARGE_INTEGER frequency; +#endif /* G_OS_WIN32 */ }; #define GST_SYSTEM_CLOCK_GET_PRIVATE(obj) \ @@ -155,6 +166,14 @@ gst_system_clock_init (GstSystemClock * clock) clock->priv->clock_type = DEFAULT_CLOCK_TYPE; clock->priv->timer = gst_poll_new_timer (); +#ifdef G_OS_WIN32 + QueryPerformanceFrequency (&clock->priv->frequency); + /* can be 0 if the hardware does not have hardware support */ + if (clock->priv->frequency.QuadPart != 0) + /* we take a base time so that time starts from 0 to ease debugging */ + QueryPerformanceCounter (&clock->priv->start); +#endif /* G_OS_WIN32 */ + #if 0 /* Uncomment this to start the async clock thread straight away */ GST_OBJECT_LOCK (clock); @@ -459,42 +478,67 @@ clock_type_to_posix_id (GstClockType clock_type) static GstClockTime gst_system_clock_get_internal_time (GstClock * clock) { -#ifdef HAVE_POSIX_TIMERS - GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); - clockid_t ptype; - struct timespec ts; +#ifdef G_OS_WIN32 + if (clock->priv->frequency.QuadPart != 0) { + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + LARGE_INTEGER now; - ptype = clock_type_to_posix_id (sysclock->priv->clock_type); + /* we prefer the highly accurate performance counters on windows */ + QueryPerformanceCounter (&now); - if (G_UNLIKELY (clock_gettime (ptype, &ts))) - return GST_CLOCK_TIME_NONE; + return gst_util_uint64_scale (now.QuadPart - sysclock->priv->start.QuadPart, + GST_SECOND, sysclock->priv->frequency.QuadPart); + } else +#endif /* G_OS_WIN32 */ +#if !defined HAVE_POSIX_TIMERS + { + GTimeVal timeval; - return GST_TIMESPEC_TO_TIME (ts); + g_get_current_time (&timeval); + + return GST_TIMEVAL_TO_TIME (timeval); + } #else - GTimeVal timeval; + { + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + clockid_t ptype; + struct timespec ts; - g_get_current_time (&timeval); + ptype = clock_type_to_posix_id (sysclock->priv->clock_type); - return GST_TIMEVAL_TO_TIME (timeval); + if (G_UNLIKELY (clock_gettime (ptype, &ts))) + return GST_CLOCK_TIME_NONE; + + return GST_TIMESPEC_TO_TIME (ts); + } #endif } static guint64 gst_system_clock_get_resolution (GstClock * clock) { +#ifdef G_OS_WIN32 + if (clock->priv->frequency.QuadPart != 0) { + return GST_SECOND / sysclock->priv->frequency.QuadPart; + } else +#endif /* G_OS_WIN32 */ #ifdef HAVE_POSIX_TIMERS - GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); - clockid_t ptype; - struct timespec ts; + { + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + clockid_t ptype; + struct timespec ts; - ptype = clock_type_to_posix_id (sysclock->priv->clock_type); + ptype = clock_type_to_posix_id (sysclock->priv->clock_type); - if (G_UNLIKELY (clock_getres (ptype, &ts))) - return GST_CLOCK_TIME_NONE; + if (G_UNLIKELY (clock_getres (ptype, &ts))) + return GST_CLOCK_TIME_NONE; - return GST_TIMESPEC_TO_TIME (ts); + return GST_TIMESPEC_TO_TIME (ts); + } #else - return 1 * GST_USECOND; + { + return 1 * GST_USECOND; + } #endif }