From 110edbc8bd05a0be0a8c08d8d97ecb889a127a77 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 12 May 2021 00:54:43 +0900 Subject: [PATCH] gst-launch: Enable Windows high-resolution clock Default timer precision of Windows is dependent on system, but usually it's known to be about 15ms in worst case. That's not an enough precision for multimedia application. Enable high-resolution clock in gst-launch to demonstrate the usage of Windows high-precision clock for application developers. Part-of: --- tools/gst-launch.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ tools/meson.build | 22 ++++++++++++++-- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/tools/gst-launch.c b/tools/gst-launch.c index 2e8efa5cf6..d38ea9f612 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -46,6 +46,9 @@ #endif #include /* for LC_ALL */ #include "tools.h" +#ifdef HAVE_WINMM +#include +#endif extern volatile gboolean glib_on_error_halt; @@ -1030,6 +1033,43 @@ query_pipeline_position (gpointer user_data) return G_SOURCE_CONTINUE; } +#ifdef HAVE_WINMM +static guint +enable_winmm_timer_resolution (void) +{ + TIMECAPS time_caps; + guint resolution = 0; + MMRESULT res; + + res = timeGetDevCaps (&time_caps, sizeof (TIMECAPS)); + if (res != TIMERR_NOERROR) { + g_warning ("timeGetDevCaps() returned non-zero code %d", res); + return 0; + } + + resolution = MIN (MAX (time_caps.wPeriodMin, 1), time_caps.wPeriodMax); + res = timeBeginPeriod (resolution); + if (res != TIMERR_NOERROR) { + g_warning ("timeBeginPeriod() returned non-zero code %d", res); + return 0; + } + + PRINT (_("Use Windows high-resolution clock, precision: %u ms\n"), + resolution); + + return resolution; +} + +static void +clear_winmm_timer_resolution (guint resolution) +{ + if (resolution == 0) + return; + + timeEndPeriod (resolution); +} +#endif + int main (int argc, char *argv[]) { @@ -1092,6 +1132,9 @@ main (int argc, char *argv[]) gulong deep_notify_id = 0; guint bus_watch_id = 0; GSource *position_source = NULL; +#ifdef HAVE_WINMM + guint winmm_timer_resolution = 0; +#endif free (malloc (8)); /* -lefence */ @@ -1174,6 +1217,23 @@ main (int argc, char *argv[]) gst_bin_add (GST_BIN (real_pipeline), pipeline); pipeline = real_pipeline; } +#ifdef HAVE_WINMM + /* Enable high-precision clock which will improve accuracy of various + * Windows timer APIs (e.g., Sleep()), and it will increase the precision + * of GstSystemClock as well + */ + + /* NOTE: Once timer resolution is updated via timeBeginPeriod(), + * application should undo it by calling timeEndPeriod() + * + * Prior to Windows 10, version 2004, timeBeginPeriod() affects global + * Windows setting (meaning that it will affect other processes), + * but starting with Windows 10, version 2004, this function no longer + * affects global timer resolution + */ + winmm_timer_resolution = enable_winmm_timer_resolution (); +#endif + if (verbose) { deep_notify_id = gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE); @@ -1285,6 +1345,11 @@ main (int argc, char *argv[]) #endif g_source_remove (bus_watch_id); g_main_loop_unref (loop); + +#ifdef HAVE_WINMM + /* Undo timeBeginPeriod() if required */ + clear_winmm_timer_resolution (winmm_timer_resolution); +#endif } PRINT (_("Freeing pipeline ...\n")); diff --git a/tools/meson.build b/tools/meson.build index 1e33811790..e22721d9db 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -1,19 +1,37 @@ tools = ['gst-inspect', 'gst-stats', 'gst-typefind'] +extra_launch_dep = [] +extra_launch_arg = [] + if gst_parse + if host_system == 'windows' + winmm_lib = cc.find_library('winmm', required: false) + if winmm_lib.found() and cc.has_header('timeapi.h') + extra_launch_dep += [winmm_lib] + extra_launch_arg += ['-DHAVE_WINMM'] + endif + endif + tools += ['gst-launch'] endif foreach tool : tools exe_name = '@0@-@1@'.format(tool, apiversion) src_file = '@0@.c'.format(tool) + extra_deps = [] + extra_c_args = [] + + if tool == 'gst-launch' + extra_deps += extra_launch_dep + extra_c_args += extra_launch_arg + endif executable(exe_name, src_file, install: true, include_directories : [configinc], - dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], - c_args: gst_c_args, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep] + extra_deps, + c_args: gst_c_args + extra_c_args, ) man_page = '@0@-1.0.1'.format(tool)