wasapi: Set realtime thread priority at runtime

Use LoadLibrary() to set the thread characteristics at runtime so it
works automagically regardless of where or how the plugin was built.
This commit is contained in:
Nirbheek Chauhan 2018-02-14 20:12:07 +05:30
parent 0cb11c15ed
commit f7d0ce2477
4 changed files with 67 additions and 20 deletions

View file

@ -501,14 +501,8 @@ gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK
(self)->ringbuffer, self->positions); (self)->ringbuffer, self->positions);
#if defined(_MSC_VER) || defined(GST_FORCE_WIN_AVRT)
/* Increase the thread priority to reduce glitches */ /* Increase the thread priority to reduce glitches */
{ self->thread_priority_handle = gst_wasapi_util_set_thread_characteristics ();
DWORD taskIndex = 0;
self->thread_priority_handle =
AvSetMmThreadCharacteristics (TEXT ("Pro Audio"), &taskIndex);
}
#endif
res = TRUE; res = TRUE;
@ -530,12 +524,11 @@ gst_wasapi_sink_unprepare (GstAudioSink * asink)
!gst_wasapi_util_have_audioclient3 ()) !gst_wasapi_util_have_audioclient3 ())
CoUninitialize (); CoUninitialize ();
#if defined(_MSC_VER) || defined(GST_FORCE_WIN_AVRT)
if (self->thread_priority_handle != NULL) { if (self->thread_priority_handle != NULL) {
AvRevertMmThreadCharacteristics (self->thread_priority_handle); gst_wasapi_util_revert_thread_characteristics
(self->thread_priority_handle);
self->thread_priority_handle = NULL; self->thread_priority_handle = NULL;
} }
#endif
if (self->client != NULL) { if (self->client != NULL) {
IAudioClient_Stop (self->client); IAudioClient_Stop (self->client);

View file

@ -448,14 +448,8 @@ gst_wasapi_src_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
(self)->ringbuffer, self->positions); (self)->ringbuffer, self->positions);
#if defined(_MSC_VER) || defined(GST_FORCE_WIN_AVRT)
/* Increase the thread priority to reduce glitches */ /* Increase the thread priority to reduce glitches */
{ self->thread_priority_handle = gst_wasapi_util_set_thread_characteristics ();
DWORD taskIndex = 0;
self->thread_priority_handle =
AvSetMmThreadCharacteristics (TEXT ("Pro Audio"), &taskIndex);
}
#endif
res = TRUE; res = TRUE;
beach: beach:
@ -475,12 +469,11 @@ gst_wasapi_src_unprepare (GstAudioSrc * asrc)
if (self->sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) if (self->sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE)
CoUninitialize (); CoUninitialize ();
#if defined(_MSC_VER) || defined(GST_FORCE_WIN_AVRT)
if (self->thread_priority_handle != NULL) { if (self->thread_priority_handle != NULL) {
AvRevertMmThreadCharacteristics (self->thread_priority_handle); gst_wasapi_util_revert_thread_characteristics
(self->thread_priority_handle);
self->thread_priority_handle = NULL; self->thread_priority_handle = NULL;
} }
#endif
if (self->client != NULL) { if (self->client != NULL) {
IAudioClient_Stop (self->client); IAudioClient_Stop (self->client);

View file

@ -104,6 +104,16 @@ static struct
static int windows_major_version = 0; static int windows_major_version = 0;
static struct
{
HMODULE dll;
gboolean tried_loading;
HANDLE (WINAPI * AvSetMmThreadCharacteristics) (LPCSTR, LPDWORD);
BOOL (WINAPI * AvRevertMmThreadCharacteristics) (HANDLE);
} gst_wasapi_avrt_tbl = {
0};
gboolean gboolean
gst_wasapi_util_have_audioclient3 (void) gst_wasapi_util_have_audioclient3 (void)
{ {
@ -938,3 +948,50 @@ gst_wasapi_util_initialize_audioclient3 (GstElement * self,
*ret_devicep_frames = devicep_frames; *ret_devicep_frames = devicep_frames;
return TRUE; return TRUE;
} }
static gboolean
gst_wasapi_util_init_thread_priority (void)
{
if (gst_wasapi_avrt_tbl.tried_loading)
return gst_wasapi_avrt_tbl.dll != NULL;
if (!gst_wasapi_avrt_tbl.dll)
gst_wasapi_avrt_tbl.dll = LoadLibrary (TEXT ("avrt.dll"));
if (!gst_wasapi_avrt_tbl.dll) {
GST_WARNING ("Failed to set thread priority, can't find avrt.dll");
gst_wasapi_avrt_tbl.tried_loading = TRUE;
return FALSE;
}
gst_wasapi_avrt_tbl.AvSetMmThreadCharacteristics =
GetProcAddress (gst_wasapi_avrt_tbl.dll, "AvSetMmThreadCharacteristicsA");
gst_wasapi_avrt_tbl.AvRevertMmThreadCharacteristics =
GetProcAddress (gst_wasapi_avrt_tbl.dll,
"AvRevertMmThreadCharacteristics");
gst_wasapi_avrt_tbl.tried_loading = TRUE;
return TRUE;
}
HANDLE
gst_wasapi_util_set_thread_characteristics (void)
{
DWORD taskIndex = 0;
if (!gst_wasapi_util_init_thread_priority ())
return NULL;
return gst_wasapi_avrt_tbl.AvSetMmThreadCharacteristics (TEXT ("Pro Audio"),
&taskIndex);
}
void
gst_wasapi_util_revert_thread_characteristics (HANDLE handle)
{
if (!gst_wasapi_util_init_thread_priority ())
return;
gst_wasapi_avrt_tbl.AvRevertMmThreadCharacteristics (handle);
}

View file

@ -110,4 +110,8 @@ gboolean gst_wasapi_util_initialize_audioclient3 (GstElement * element,
GstAudioRingBufferSpec * spec, IAudioClient3 * client, GstAudioRingBufferSpec * spec, IAudioClient3 * client,
WAVEFORMATEX * format, gboolean low_latency, guint * ret_devicep_frames); WAVEFORMATEX * format, gboolean low_latency, guint * ret_devicep_frames);
HANDLE gst_wasapi_util_set_thread_characteristics (void);
void gst_wasapi_util_revert_thread_characteristics (HANDLE handle);
#endif /* __GST_WASAPI_UTIL_H__ */ #endif /* __GST_WASAPI_UTIL_H__ */