mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
Merge pull request #515 from Rafostar/win-hi-clock
clapper-app: Support high resolution clock on MS Windows
This commit is contained in:
@@ -23,8 +23,124 @@
|
||||
#include "clapper-app-utils.h"
|
||||
#include "clapper-app-media-item-box.h"
|
||||
|
||||
/* Useful only on Windows */
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#ifdef HAVE_WIN_PROCESS_THREADS_API
|
||||
#include <processthreadsapi.h>
|
||||
#endif
|
||||
#ifdef HAVE_WIN_TIME_API
|
||||
#include <timeapi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_app_utils_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
void
|
||||
clapper_app_utils_debug_init (void)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperapputils", 0,
|
||||
"Clapper App Utils");
|
||||
}
|
||||
|
||||
/* Windows specific functions */
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/*
|
||||
* clapper_app_utils_win_enforce_hi_res_clock:
|
||||
*
|
||||
* Enforce high resolution clock by explicitly disabling Windows
|
||||
* timer resolution power throttling. When disabled, system remembers
|
||||
* and honors any previous timer resolution request by the process.
|
||||
*
|
||||
* By default, Windows 11 may automatically ignore the timer
|
||||
* resolution requests in certain scenarios.
|
||||
*/
|
||||
void
|
||||
clapper_app_utils_win_enforce_hi_res_clock (void)
|
||||
{
|
||||
#ifdef HAVE_WIN_PROCESS_THREADS_API
|
||||
PROCESS_POWER_THROTTLING_STATE PowerThrottling;
|
||||
RtlZeroMemory (&PowerThrottling, sizeof (PowerThrottling));
|
||||
gboolean success;
|
||||
|
||||
PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
|
||||
PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
|
||||
PowerThrottling.StateMask = 0; // Always honor timer resolution requests
|
||||
|
||||
success = (gboolean) SetProcessInformation(
|
||||
GetCurrentProcess (),
|
||||
ProcessPowerThrottling,
|
||||
&PowerThrottling,
|
||||
sizeof (PowerThrottling));
|
||||
|
||||
/* Not an error. Older Windows does not have this functionality, but
|
||||
* also honor hi-res clock by default anyway, so do not print then. */
|
||||
GST_INFO ("Windows hi-res clock support is %senforced",
|
||||
(success) ? "" : "NOT ");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* clapper_app_utils_win_hi_res_clock_start:
|
||||
*
|
||||
* Start Windows high resolution clock which will improve
|
||||
* accuracy of various Windows timer APIs and precision
|
||||
* of #GstSystemClock during playback.
|
||||
*
|
||||
* On Windows 10 version 2004 (and older), this function affects
|
||||
* a global Windows setting. On any other (newer) version this
|
||||
* will only affect a single process.
|
||||
*
|
||||
* Returns: Timer resolution period value.
|
||||
*/
|
||||
guint
|
||||
clapper_app_utils_win_hi_res_clock_start (void)
|
||||
{
|
||||
guint resolution = 0;
|
||||
|
||||
#ifdef HAVE_WIN_TIME_API
|
||||
TIMECAPS time_caps;
|
||||
MMRESULT res;
|
||||
|
||||
if ((res = timeGetDevCaps (&time_caps, sizeof (TIMECAPS))) != TIMERR_NOERROR) {
|
||||
GST_WARNING ("Could not query timer resolution, code: %u", res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
resolution = MIN (MAX (time_caps.wPeriodMin, 1), time_caps.wPeriodMax);
|
||||
|
||||
if ((res = timeBeginPeriod (resolution)) != TIMERR_NOERROR) {
|
||||
GST_WARNING ("Could not request timer resolution, code: %u", res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GST_INFO ("Started Windows hi-res clock, precision: %ums", resolution);
|
||||
#endif
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
||||
/*
|
||||
* clapper_app_utils_win_hi_res_clock_stop:
|
||||
* @resolution: started resolution value (non-zero)
|
||||
*
|
||||
* Stop previously started Microsoft Windows high resolution clock.
|
||||
*/
|
||||
void
|
||||
clapper_app_utils_win_hi_res_clock_stop (guint resolution)
|
||||
{
|
||||
#ifdef HAVE_WIN_TIME_API
|
||||
MMRESULT res;
|
||||
|
||||
if ((res = timeEndPeriod (resolution)) == TIMERR_NOERROR)
|
||||
GST_INFO ("Stopped Windows hi-res clock");
|
||||
else
|
||||
GST_ERROR ("Could not stop hi-res clock, code: %u", res);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Extensions are used only on Windows */
|
||||
const gchar *const *
|
||||
clapper_app_utils_get_extensions (void)
|
||||
{
|
||||
@@ -45,7 +161,7 @@ clapper_app_utils_get_subtitles_extensions (void)
|
||||
|
||||
return subs_extensions;
|
||||
}
|
||||
#endif
|
||||
#endif // G_OS_WIN32
|
||||
|
||||
const gchar *const *
|
||||
clapper_app_utils_get_mime_types (void)
|
||||
|
@@ -26,7 +26,18 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef void (* ClapperAppUtilsIterRanks) (const gchar *feature_name, GstRank rank, gboolean from_env, gpointer user_data);
|
||||
|
||||
void clapper_app_utils_debug_init (void);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_app_utils_win_enforce_hi_res_clock (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
guint clapper_app_utils_win_hi_res_clock_start (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_app_utils_win_hi_res_clock_stop (guint resolution);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
const gchar *const * clapper_app_utils_get_extensions (void);
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "clapper-app-application.h"
|
||||
#include "clapper-app-types.h"
|
||||
#include "clapper-app-utils.h"
|
||||
|
||||
gint
|
||||
main (gint argc, gchar **argv)
|
||||
@@ -34,7 +35,13 @@ main (gint argc, gchar **argv)
|
||||
GApplication *application;
|
||||
gint status;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
guint resolution = 0;
|
||||
#endif
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
g_setenv ("GSK_RENDERER", "gl", FALSE);
|
||||
#endif
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
if (!(clapper_ldir = g_getenv ("CLAPPER_APP_OVERRIDE_LOCALEDIR")))
|
||||
@@ -48,13 +55,24 @@ main (gint argc, gchar **argv)
|
||||
adw_init ();
|
||||
|
||||
clapper_app_types_init ();
|
||||
clapper_app_utils_debug_init ();
|
||||
|
||||
g_set_application_name ("Clapper");
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
clapper_app_utils_win_enforce_hi_res_clock ();
|
||||
resolution = clapper_app_utils_win_hi_res_clock_start ();
|
||||
#endif
|
||||
|
||||
application = clapper_app_application_new ();
|
||||
|
||||
status = g_application_run (application, argc, argv);
|
||||
g_object_unref (application);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
if (resolution > 0)
|
||||
clapper_app_utils_win_hi_res_clock_stop (resolution);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@@ -80,6 +80,22 @@ clapperapp_c_args = [
|
||||
'-DGST_USE_UNSTABLE_API',
|
||||
]
|
||||
|
||||
is_windows = ['windows'].contains(host_machine.system())
|
||||
|
||||
if is_windows
|
||||
clapperapp_c_args += ['-D_WIN32_WINNT=_WIN32_WINNT_WIN8']
|
||||
kernel32_dep = cc.find_library('kernel32', required: false)
|
||||
if kernel32_dep.found() and cc.has_header('processthreadsapi.h')
|
||||
clapperapp_deps += kernel32_dep
|
||||
clapperapp_c_args += ['-DHAVE_WIN_PROCESS_THREADS_API']
|
||||
endif
|
||||
winmm_dep = cc.find_library('winmm', required: false)
|
||||
if winmm_dep.found() and cc.has_header('timeapi.h')
|
||||
clapperapp_deps += winmm_dep
|
||||
clapperapp_c_args += ['-DHAVE_WIN_TIME_API']
|
||||
endif
|
||||
endif
|
||||
|
||||
executable(
|
||||
meson.project_name(),
|
||||
clapperapp_sources,
|
||||
@@ -90,7 +106,7 @@ executable(
|
||||
install_dir: bindir,
|
||||
win_subsystem: 'windows',
|
||||
)
|
||||
if ['windows'].contains(host_machine.system())
|
||||
if is_windows
|
||||
executable(
|
||||
meson.project_name() + '-console',
|
||||
clapperapp_sources,
|
||||
|
Reference in New Issue
Block a user