diff options
author | Seungha Yang <seungha@centricular.com> | 2021-05-11 18:54:43 +0300 |
---|---|---|
committer | Seungha Yang <seungha@centricular.com> | 2021-07-28 14:19:10 +0300 |
commit | 110edbc8bd05a0be0a8c08d8d97ecb889a127a77 (patch) | |
tree | 98a6d50ad3c64195278a4128d32e56c0946cc9ef | |
parent | 97601e49cb84bd0bbcbb8b72bbadbee13615a8c7 (diff) |
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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/817>
-rw-r--r-- | tools/gst-launch.c | 65 | ||||
-rw-r--r-- | 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 <locale.h> /* for LC_ALL */ #include "tools.h" +#ifdef HAVE_WINMM +#include <timeapi.h> +#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) |