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>
This commit is contained in:
Seungha Yang 2021-05-12 00:54:43 +09:00
parent 97601e49cb
commit 110edbc8bd
2 changed files with 85 additions and 2 deletions

View file

@ -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"));

View file

@ -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)