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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1541>
This commit is contained in:
Seungha Yang 2022-01-20 03:17:58 +09:00
parent 614a213e6a
commit 5bccbdc02f
2 changed files with 94 additions and 2 deletions

View file

@ -39,6 +39,12 @@
#include <glib/gprintf.h> #include <glib/gprintf.h>
#ifdef HAVE_WINMM
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <timeapi.h>
#endif
#include "gst-play-kb.h" #include "gst-play-kb.h"
#define VOLUME_STEPS 20 #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 int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -1513,6 +1556,9 @@ main (int argc, char **argv)
GOptionContext *ctx; GOptionContext *ctx;
gchar *playlist_file = NULL; gchar *playlist_file = NULL;
gboolean use_playbin3 = FALSE; gboolean use_playbin3 = FALSE;
#ifdef HAVE_WINMM
guint winmm_timer_resolution = 0;
#endif
GOptionEntry options[] = { GOptionEntry options[] = {
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
N_("Output status information and property notifications"), NULL}, 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"); ("Failed to create 'playbin' element. Check your GStreamer installation.\n");
return EXIT_FAILURE; 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 (interactive) {
if (gst_play_kb_set_key_handler (keyboard_cb, play)) { if (gst_play_kb_set_key_handler (keyboard_cb, play)) {
@ -1682,6 +1744,11 @@ main (int argc, char **argv)
/* play */ /* play */
do_play (play); do_play (play);
#ifdef HAVE_WINMM
/* Undo timeBeginPeriod() if required */
clear_winmm_timer_resolution (winmm_timer_resolution);
#endif
/* clean up */ /* clean up */
play_free (play); play_free (play);

View file

@ -1,5 +1,30 @@
tool_deps = glib_deps + [pbutils_dep, audio_dep, video_dep, tag_dep, gst_dep, gst_base_dep, gmodule_dep] 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 <windows.h>
#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), executable('gst-device-monitor-@0@'.format(api_version),
'gst-device-monitor.c', 'gst-device-monitor.c',
install: true, install: true,
@ -21,8 +46,8 @@ install_man('gst-discoverer-@0@.1'.format(api_version))
executable('gst-play-@0@'.format(api_version), executable('gst-play-@0@'.format(api_version),
'gst-play.c', 'gst-play-kb.c', 'gst-play.c', 'gst-play-kb.c',
install: true, 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], include_directories: [configinc],
dependencies : tool_deps + [libm], dependencies : tool_deps + [libm] + extra_deps,
) )
install_man('gst-play-@0@.1'.format(api_version)) install_man('gst-play-@0@.1'.format(api_version))