mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 23:32:04 +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-utils.h"
|
||||||
#include "clapper-app-media-item-box.h"
|
#include "clapper-app-media-item-box.h"
|
||||||
|
|
||||||
/* Useful only on Windows */
|
|
||||||
#ifdef G_OS_WIN32
|
#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 *
|
const gchar *const *
|
||||||
clapper_app_utils_get_extensions (void)
|
clapper_app_utils_get_extensions (void)
|
||||||
{
|
{
|
||||||
@@ -45,7 +161,7 @@ clapper_app_utils_get_subtitles_extensions (void)
|
|||||||
|
|
||||||
return subs_extensions;
|
return subs_extensions;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // G_OS_WIN32
|
||||||
|
|
||||||
const gchar *const *
|
const gchar *const *
|
||||||
clapper_app_utils_get_mime_types (void)
|
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);
|
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
|
#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
|
G_GNUC_INTERNAL
|
||||||
const gchar *const * clapper_app_utils_get_extensions (void);
|
const gchar *const * clapper_app_utils_get_extensions (void);
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "clapper-app-application.h"
|
#include "clapper-app-application.h"
|
||||||
#include "clapper-app-types.h"
|
#include "clapper-app-types.h"
|
||||||
|
#include "clapper-app-utils.h"
|
||||||
|
|
||||||
gint
|
gint
|
||||||
main (gint argc, gchar **argv)
|
main (gint argc, gchar **argv)
|
||||||
@@ -34,7 +35,13 @@ main (gint argc, gchar **argv)
|
|||||||
GApplication *application;
|
GApplication *application;
|
||||||
gint status;
|
gint status;
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
guint resolution = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
g_setenv ("GSK_RENDERER", "gl", FALSE);
|
g_setenv ("GSK_RENDERER", "gl", FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
if (!(clapper_ldir = g_getenv ("CLAPPER_APP_OVERRIDE_LOCALEDIR")))
|
if (!(clapper_ldir = g_getenv ("CLAPPER_APP_OVERRIDE_LOCALEDIR")))
|
||||||
@@ -48,13 +55,24 @@ main (gint argc, gchar **argv)
|
|||||||
adw_init ();
|
adw_init ();
|
||||||
|
|
||||||
clapper_app_types_init ();
|
clapper_app_types_init ();
|
||||||
|
clapper_app_utils_debug_init ();
|
||||||
|
|
||||||
g_set_application_name ("Clapper");
|
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 ();
|
application = clapper_app_application_new ();
|
||||||
|
|
||||||
status = g_application_run (application, argc, argv);
|
status = g_application_run (application, argc, argv);
|
||||||
g_object_unref (application);
|
g_object_unref (application);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
if (resolution > 0)
|
||||||
|
clapper_app_utils_win_hi_res_clock_stop (resolution);
|
||||||
|
#endif
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@@ -80,6 +80,22 @@ clapperapp_c_args = [
|
|||||||
'-DGST_USE_UNSTABLE_API',
|
'-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(
|
executable(
|
||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
clapperapp_sources,
|
clapperapp_sources,
|
||||||
@@ -90,7 +106,7 @@ executable(
|
|||||||
install_dir: bindir,
|
install_dir: bindir,
|
||||||
win_subsystem: 'windows',
|
win_subsystem: 'windows',
|
||||||
)
|
)
|
||||||
if ['windows'].contains(host_machine.system())
|
if is_windows
|
||||||
executable(
|
executable(
|
||||||
meson.project_name() + '-console',
|
meson.project_name() + '-console',
|
||||||
clapperapp_sources,
|
clapperapp_sources,
|
||||||
|
Reference in New Issue
Block a user