From 5bccbdc02fa25f99c7266a6cfccd6251d1455b00 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 20 Jan 2022 03:17:58 +0900 Subject: [PATCH] tools: gst-play: Enable Windows high-resolution clock Apply https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/817 to gst-play as well, especially for better high-framerate (60fps or higher) video support, because 15ms default clock precision (actual value is system dependent) is not sufficient for such scenario. Part-of: --- subprojects/gst-plugins-base/tools/gst-play.c | 67 ++++++++++++++++++++++++++ subprojects/gst-plugins-base/tools/meson.build | 29 ++++++++++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-base/tools/gst-play.c b/subprojects/gst-plugins-base/tools/gst-play.c index d02b421..508800a 100644 --- a/subprojects/gst-plugins-base/tools/gst-play.c +++ b/subprojects/gst-plugins-base/tools/gst-play.c @@ -39,6 +39,12 @@ #include +#ifdef HAVE_WINMM +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + #include "gst-play-kb.h" #define VOLUME_STEPS 20 @@ -1491,6 +1497,43 @@ keyboard_cb (const gchar * key_input, gpointer user_data) } } +#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; + } + + gst_println (_("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) { @@ -1513,6 +1556,9 @@ main (int argc, char **argv) GOptionContext *ctx; gchar *playlist_file = NULL; gboolean use_playbin3 = FALSE; +#ifdef HAVE_WINMM + guint winmm_timer_resolution = 0; +#endif GOptionEntry options[] = { {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, N_("Output status information and property notifications"), NULL}, @@ -1669,6 +1715,22 @@ main (int argc, char **argv) ("Failed to create 'playbin' element. Check your GStreamer installation.\n"); return EXIT_FAILURE; } +#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 (interactive) { if (gst_play_kb_set_key_handler (keyboard_cb, play)) { @@ -1682,6 +1744,11 @@ main (int argc, char **argv) /* play */ do_play (play); +#ifdef HAVE_WINMM + /* Undo timeBeginPeriod() if required */ + clear_winmm_timer_resolution (winmm_timer_resolution); +#endif + /* clean up */ play_free (play); diff --git a/subprojects/gst-plugins-base/tools/meson.build b/subprojects/gst-plugins-base/tools/meson.build index 612d6b0..6f96b23 100644 --- a/subprojects/gst-plugins-base/tools/meson.build +++ b/subprojects/gst-plugins-base/tools/meson.build @@ -1,5 +1,30 @@ tool_deps = glib_deps + [pbutils_dep, audio_dep, video_dep, tag_dep, gst_dep, gst_base_dep, gmodule_dep] +extra_args = [] +extra_deps = [] + +if host_system == 'windows' + # Check whether we're building for UWP apps, and if so, will not link winmm + # of which APIs are for WIN32 desktop + building_for_uwp = false + code = ''' + #include + #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) + #error "Not building for UWP" + #endif''' + if cc.compiles(code, name : 'building for UWP') + building_for_uwp = true + endif + + if not building_for_uwp + winmm_lib = cc.find_library('winmm', required: false) + if winmm_lib.found() and cc.has_header('timeapi.h') + extra_args += ['-DHAVE_WINMM'] + extra_deps += [winmm_lib] + endif + endif +endif + executable('gst-device-monitor-@0@'.format(api_version), 'gst-device-monitor.c', install: true, @@ -21,8 +46,8 @@ install_man('gst-discoverer-@0@.1'.format(api_version)) executable('gst-play-@0@'.format(api_version), 'gst-play.c', 'gst-play-kb.c', install: true, - c_args : gst_plugins_base_args + ['-DG_LOG_DOMAIN="gst-play-@0@"'.format(api_version)], + c_args : gst_plugins_base_args + ['-DG_LOG_DOMAIN="gst-play-@0@"'.format(api_version)] + extra_args, include_directories: [configinc], - dependencies : tool_deps + [libm], + dependencies : tool_deps + [libm] + extra_deps, ) install_man('gst-play-@0@.1'.format(api_version)) -- 2.7.4