Commit 602d9e21 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Win32: add --clock-source configuration item

parent fa51c993
...@@ -2037,6 +2037,12 @@ vlc_module_begin () ...@@ -2037,6 +2037,12 @@ vlc_module_begin ()
HPRIORITY_LONGTEXT, false ) HPRIORITY_LONGTEXT, false )
#endif #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 */ /* Playlist options */
set_category( CAT_PLAYLIST ) set_category( CAT_PLAYLIST )
set_subcategory( SUBCAT_PLAYLIST_GENERAL ) set_subcategory( SUBCAT_PLAYLIST_GENERAL )
......
...@@ -177,6 +177,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, ...@@ -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, "%s", COPYRIGHT_MESSAGE );
msg_Dbg( p_libvlc, "revision %s", psz_vlc_changeset ); msg_Dbg( p_libvlc, "revision %s", psz_vlc_changeset );
msg_Dbg( p_libvlc, "configured with %s", CONFIGURE_LINE ); 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. /* Load the builtins and plugins into the module_bank.
* We have to do it before config_Load*() because this also gets the * We have to do it before config_Load*() because this also gets the
......
...@@ -43,6 +43,8 @@ void system_Init ( void ); ...@@ -43,6 +43,8 @@ void system_Init ( void );
void system_Configure ( libvlc_int_t *, int, const char *const [] ); void system_Configure ( libvlc_int_t *, int, const char *const [] );
#ifdef WIN32 #ifdef WIN32
void system_End(void); void system_End(void);
void SelectClockSource( vlc_object_t * );
size_t EnumClockSource( vlc_object_t *, char ***, char *** );
#endif #endif
void vlc_CPU_init(void); void vlc_CPU_init(void);
void vlc_CPU_dump(vlc_object_t *); void vlc_CPU_dump(vlc_object_t *);
......
...@@ -55,9 +55,7 @@ struct vlc_thread ...@@ -55,9 +55,7 @@ struct vlc_thread
void *data; void *data;
}; };
#if (_WIN32_WINNT < 0x0600) static CRITICAL_SECTION clock_lock;
static LARGE_INTEGER freq;
#endif
static vlc_mutex_t super_mutex; static vlc_mutex_t super_mutex;
static vlc_cond_t super_variable; static vlc_cond_t super_variable;
extern vlc_rwlock_t config_lock, msg_lock; extern vlc_rwlock_t config_lock, msg_lock;
...@@ -72,10 +70,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) ...@@ -72,10 +70,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
switch (fdwReason) switch (fdwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
#if (_WIN32_WINNT < 0x0600) InitializeCriticalSection (&clock_lock);
if (!QueryPerformanceFrequency (&freq))
return FALSE;
#endif
vlc_mutex_init (&super_mutex); vlc_mutex_init (&super_mutex);
vlc_cond_init (&super_variable); vlc_cond_init (&super_variable);
vlc_threadvar_create (&thread_key, NULL); vlc_threadvar_create (&thread_key, NULL);
...@@ -90,6 +85,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) ...@@ -90,6 +85,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
vlc_threadvar_delete (&thread_key); vlc_threadvar_delete (&thread_key);
vlc_cond_destroy (&super_variable); vlc_cond_destroy (&super_variable);
vlc_mutex_destroy (&super_mutex); vlc_mutex_destroy (&super_mutex);
DeleteCriticalSection (&clock_lock);
break; break;
} }
return TRUE; return TRUE;
...@@ -709,9 +705,21 @@ void vlc_control_cancel (int cmd, ...) ...@@ -709,9 +705,21 @@ void vlc_control_cancel (int cmd, ...)
} }
/*** Clock ***/ /*** Clock ***/
static mtime_t mdate_giveup (void)
{
abort ();
}
static mtime_t (*mdate_selected) (void) = mdate_giveup;
mtime_t mdate (void) mtime_t mdate (void)
{ {
return mdate_selected ();
}
#if (_WIN32_WINNT >= 0x0601) #if (_WIN32_WINNT >= 0x0601)
static mtime_t mdate_interrupt (void)
{
ULONGLONG ts; ULONGLONG ts;
if (unlikely(!QueryUnbiasedInterruptTime (&ts))) if (unlikely(!QueryUnbiasedInterruptTime (&ts)))
...@@ -720,15 +728,32 @@ mtime_t mdate (void) ...@@ -720,15 +728,32 @@ mtime_t mdate (void)
/* hundreds of nanoseconds */ /* hundreds of nanoseconds */
static_assert ((10000000 % CLOCK_FREQ) == 0, "Broken frequencies ratio"); static_assert ((10000000 % CLOCK_FREQ) == 0, "Broken frequencies ratio");
return ts / (10000000 / CLOCK_FREQ); return ts / (10000000 / CLOCK_FREQ);
}
#elif (_WIN32_WINNT >= 0x0600) #endif
#if (_WIN32_WINNT >= 0x0600)
static mtime_t mdate_tick (void)
{
ULONGLONG ts = GetTickCount64 (); ULONGLONG ts = GetTickCount64 ();
/* milliseconds */ /* milliseconds */
static_assert ((CLOCK_FREQ % 1000) == 0, "Broken frequencies ratio"); static_assert ((CLOCK_FREQ % 1000) == 0, "Broken frequencies ratio");
return ts * (CLOCK_FREQ / 1000); 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 */ /* We don't need the real date, just the value of a high precision timer */
LARGE_INTEGER counter; LARGE_INTEGER counter;
if (!QueryPerformanceCounter (&counter)) if (!QueryPerformanceCounter (&counter))
...@@ -736,10 +761,26 @@ mtime_t mdate (void) ...@@ -736,10 +761,26 @@ mtime_t mdate (void)
/* Convert to from (1/freq) to microsecond resolution */ /* Convert to from (1/freq) to microsecond resolution */
/* We need to split the division to avoid 63-bits overflow */ /* 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 #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 #undef mwait
...@@ -764,6 +805,109 @@ void msleep (mtime_t delay) ...@@ -764,6 +805,109 @@ void msleep (mtime_t delay)
mwait (mdate () + 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 ***/ /*** Timers ***/
struct vlc_timer struct vlc_timer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment