[vlc-commits] Win32: add --clock-source configuration item

Rémi Denis-Courmont git at videolan.org
Thu Sep 6 18:26:36 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu Sep  6 19:26:37 2012 +0300| [602d9e215b2525665289c9319dd37e5139c7038f] | committer: Rémi Denis-Courmont

Win32: add --clock-source configuration item

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=602d9e215b2525665289c9319dd37e5139c7038f
---

 src/libvlc-module.c |    6 ++
 src/libvlc.c        |    3 +
 src/libvlc.h        |    2 +
 src/win32/thread.c  |  168 +++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 167 insertions(+), 12 deletions(-)

diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 2d86f1a..c065b7b 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -2037,6 +2037,12 @@ vlc_module_begin ()
               HPRIORITY_LONGTEXT, false )
 #endif
 
+#define CLOCK_SOURCE_TEXT N_("Clock source")
+#ifdef WIN32
+    add_string( "clock-source", NULL, CLOCK_SOURCE_TEXT, CLOCK_SOURCE_TEXT, true )
+        change_string_cb( EnumClockSource )
+#endif
+
 /* Playlist options */
     set_category( CAT_PLAYLIST )
     set_subcategory( SUBCAT_PLAYLIST_GENERAL )
diff --git a/src/libvlc.c b/src/libvlc.c
index a335fd7..857960c 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -177,6 +177,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     msg_Dbg( p_libvlc, "%s", COPYRIGHT_MESSAGE );
     msg_Dbg( p_libvlc, "revision %s", psz_vlc_changeset );
     msg_Dbg( p_libvlc, "configured with %s", CONFIGURE_LINE );
+#ifdef WIN32
+    SelectClockSource (VLC_OBJECT(p_libvlc));
+#endif
 
     /* Load the builtins and plugins into the module_bank.
      * We have to do it before config_Load*() because this also gets the
diff --git a/src/libvlc.h b/src/libvlc.h
index 20bde6e..2940bf8 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -43,6 +43,8 @@ void system_Init      ( void );
 void system_Configure ( libvlc_int_t *, int, const char *const [] );
 #ifdef WIN32
 void system_End(void);
+void SelectClockSource( vlc_object_t * );
+size_t EnumClockSource( vlc_object_t *, char ***, char *** );
 #endif
 void vlc_CPU_init(void);
 void vlc_CPU_dump(vlc_object_t *);
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 564a9f6..ced91f9 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -55,9 +55,7 @@ struct vlc_thread
     void          *data;
 };
 
-#if (_WIN32_WINNT < 0x0600)
-static LARGE_INTEGER freq;
-#endif
+static CRITICAL_SECTION clock_lock;
 static vlc_mutex_t super_mutex;
 static vlc_cond_t  super_variable;
 extern vlc_rwlock_t config_lock, msg_lock;
@@ -72,10 +70,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
     switch (fdwReason)
     {
         case DLL_PROCESS_ATTACH:
-#if (_WIN32_WINNT < 0x0600)
-            if (!QueryPerformanceFrequency (&freq))
-                return FALSE;
-#endif
+            InitializeCriticalSection (&clock_lock);
             vlc_mutex_init (&super_mutex);
             vlc_cond_init (&super_variable);
             vlc_threadvar_create (&thread_key, NULL);
@@ -90,6 +85,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
             vlc_threadvar_delete (&thread_key);
             vlc_cond_destroy (&super_variable);
             vlc_mutex_destroy (&super_mutex);
+            DeleteCriticalSection (&clock_lock);
             break;
     }
     return TRUE;
@@ -709,9 +705,21 @@ void vlc_control_cancel (int cmd, ...)
 }
 
 /*** Clock ***/
+static mtime_t mdate_giveup (void)
+{
+    abort ();
+}
+
+static mtime_t (*mdate_selected) (void) = mdate_giveup;
+
 mtime_t mdate (void)
 {
+    return mdate_selected ();
+}
+
 #if (_WIN32_WINNT >= 0x0601)
+static mtime_t mdate_interrupt (void)
+{
     ULONGLONG ts;
 
     if (unlikely(!QueryUnbiasedInterruptTime (&ts)))
@@ -720,15 +728,32 @@ mtime_t mdate (void)
     /* hundreds of nanoseconds */
     static_assert ((10000000 % CLOCK_FREQ) == 0, "Broken frequencies ratio");
     return ts / (10000000 / CLOCK_FREQ);
-
-#elif (_WIN32_WINNT >= 0x0600)
+}
+#endif
+#if (_WIN32_WINNT >= 0x0600)
+static mtime_t mdate_tick (void)
+{
      ULONGLONG ts = GetTickCount64 ();
 
     /* milliseconds */
     static_assert ((CLOCK_FREQ % 1000) == 0, "Broken frequencies ratio");
     return ts * (CLOCK_FREQ / 1000);
+}
+#endif
+#include <mmsystem.h>
+static mtime_t mdate_multimedia (void)
+{
+     DWORD ts = timeGetTime ();
 
-#else
+    /* milliseconds */
+    static_assert ((CLOCK_FREQ % 1000) == 0, "Broken frequencies ratio");
+    return ts * (CLOCK_FREQ / 1000);
+}
+
+static LARGE_INTEGER perf_freq;
+
+static mtime_t mdate_perf (void)
+{
     /* We don't need the real date, just the value of a high precision timer */
     LARGE_INTEGER counter;
     if (!QueryPerformanceCounter (&counter))
@@ -736,10 +761,26 @@ mtime_t mdate (void)
 
     /* Convert to from (1/freq) to microsecond resolution */
     /* We need to split the division to avoid 63-bits overflow */
-    lldiv_t d = lldiv (counter.QuadPart, freq.QuadPart);
+    lldiv_t d = lldiv (counter.QuadPart, perf_freq.QuadPart);
+
+    return (d.quot * 1000000) + ((d.rem * 1000000) / perf_freq.QuadPart);
+}
 
-    return (d.quot * 1000000) + ((d.rem * 1000000) / freq.QuadPart);
+static mtime_t mdate_wall (void)
+{
+    FILETIME ts;
+    ULARGE_INTEGER s;
+
+#if (_WIN32_WINNT >= 0x0602)
+    GetSystemTimePreciseAsFileTime (&ts);
+#else
+    GetSystemTimeAsFileTime (&ts);
 #endif
+    s.LowPart = ts.dwLowDateTime;
+    s.HighPart = ts.dwHighDateTime;
+    /* hundreds of nanoseconds */
+    static_assert ((10000000 % CLOCK_FREQ) == 0, "Broken frequencies ratio");
+    return s.QuadPart / (10000000 / CLOCK_FREQ);
 }
 
 #undef mwait
@@ -764,6 +805,109 @@ void msleep (mtime_t delay)
     mwait (mdate () + delay);
 }
 
+void SelectClockSource (vlc_object_t *obj)
+{
+    EnterCriticalSection (&clock_lock);
+    if (mdate_selected != mdate_giveup)
+    {
+        LeaveCriticalSection (&clock_lock);
+        return;
+    }
+
+    const char *name = "perf";
+    char *str = var_InheritString (obj, "clock-source");
+    if (str != NULL)
+        name = str;
+#if (_WIN32_WINNT >= 0x0601)
+    if (!strcmp (name, "interrupt"))
+    {
+        msg_Dbg (obj, "using interrupt time as clock source");
+        mdate_selected = mdate_interrupt;
+    }
+    else
+#endif
+#if (_WIN32_WINNT >= 0x0600)
+    if (!strcmp (name, "tick"))
+    {
+        msg_Dbg (obj, "using Windows time as clock source");
+        mdate_selected = mdate_tick;
+    }
+    else
+#endif
+    if (!strcmp (name, "multimedia"))
+    {
+        TIMECAPS caps;
+
+        msg_Dbg (obj, "using multimedia timers as clock source");
+        if (timeGetDevCaps (&caps, sizeof (caps)) != MMSYSERR_NOERROR)
+            abort ();
+        msg_Dbg (obj, " min period: %u ms, max period: %u ms",
+                 caps.wPeriodMin, caps.wPeriodMax);
+        mdate_selected = mdate_multimedia;
+    }
+    else
+    if (!strcmp (name, "perf"))
+    {
+        msg_Dbg (obj, "using performance counters as clock source");
+        if (!QueryPerformanceFrequency (&perf_freq))
+            abort ();
+        msg_Dbg (obj, " frequency: %llu Hz", perf_freq.QuadPart);
+        mdate_selected = mdate_perf;
+    }
+    else
+    if (!strcmp (name, "wall"))
+    {
+        msg_Dbg (obj, "using system time as clock source");
+        mdate_selected = mdate_wall;
+    }
+    else
+    {
+        msg_Err (obj, "invalid clock source \"%s\"", name);
+        abort ();
+    }
+    LeaveCriticalSection (&clock_lock);
+    free (str);
+}
+
+#define xstrdup(str) (strdup(str) ?: (abort(), NULL))
+
+size_t EnumClockSource (vlc_object_t *obj, char ***vp, char ***np)
+{
+    const size_t max = 6;
+    char **values = xmalloc (sizeof (*values) * max);
+    char **names = xmalloc (sizeof (*names) * max);
+
+    size_t n = 0;
+
+    values[n] = xstrdup ("");
+    names[n] = xstrdup (_("Auto"));
+    n++;
+#if (_WIN32_WINNT >= 0x0601)
+    values[n] = xstrdup ("interrupt");
+    names[n] = xstrdup ("Interrupt time");
+    n++;
+#endif
+#if (_WIN32_WINNT >= 0x0600)
+    values[n] = xstrdup ("tick");
+    names[n] = xstrdup ("Windows time");
+    n++;
+#endif
+    values[n] = xstrdup ("multimedia");
+    names[n] = xstrdup ("Multimedia timers");
+    n++;
+    values[n] = xstrdup ("perf");
+    names[n] = xstrdup ("Performance counters");
+    n++;
+    values[n] = xstrdup ("wall");
+    names[n] = xstrdup ("System time (DANGEROUS!)");
+    n++;
+
+    *vp = values;
+    *np = names;
+    (void) obj;
+    return n;
+}
+
 
 /*** Timers ***/
 struct vlc_timer



More information about the vlc-commits mailing list