diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2018-09-11 00:41:59 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2018-09-11 00:44:18 +0530 |
commit | 118338a72532b051ab8930b43d9c494335a290f5 (patch) | |
tree | 4dc00398e4749a889e6239f55a12e04e41c81489 | |
parent | da8f9afd8879f24a754b50b09d8373822f7b7555 (diff) | |
download | gstreamer-plugins-base-118338a72532b051ab8930b43d9c494335a290f5.tar.gz |
gstaudiosrc/sink: Set audio ringbuffer thread priority
On Windows, the ringbuffer thread function must have the "Pro Audio"
priority set, otherwise it sometimes doesn't get scheduled for
200-300ms, which will immediately cause an underrun unless you set
a very high latency-time and buffer-time.
This has no compile-time deps since it tries to load avrt.dll at
runtime to set the thread priority.
-rw-r--r-- | gst-libs/gst/audio/gstaudiosink.c | 4 | ||||
-rw-r--r-- | gst-libs/gst/audio/gstaudiosrc.c | 4 | ||||
-rw-r--r-- | gst-libs/gst/audio/gstaudioutilsprivate.c | 65 | ||||
-rw-r--r-- | gst-libs/gst/audio/gstaudioutilsprivate.h | 3 |
4 files changed, 76 insertions, 0 deletions
diff --git a/gst-libs/gst/audio/gstaudiosink.c b/gst-libs/gst/audio/gstaudiosink.c index cc48f7dbe..cc7b791ba 100644 --- a/gst-libs/gst/audio/gstaudiosink.c +++ b/gst-libs/gst/audio/gstaudiosink.c @@ -53,6 +53,7 @@ #include <gst/audio/audio.h> #include "gstaudiosink.h" +#include "gstaudioutilsprivate.h" GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug); #define GST_CAT_DEFAULT gst_audio_sink_debug @@ -213,6 +214,9 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf) if (writefunc == NULL) goto no_function; + if (G_UNLIKELY (!__gst_audio_set_thread_priority ())) + GST_WARNING_OBJECT (sink, "failed to set thread priority"); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink)); g_value_init (&val, GST_TYPE_G_THREAD); diff --git a/gst-libs/gst/audio/gstaudiosrc.c b/gst-libs/gst/audio/gstaudiosrc.c index c3faf8fff..008921fa9 100644 --- a/gst-libs/gst/audio/gstaudiosrc.c +++ b/gst-libs/gst/audio/gstaudiosrc.c @@ -46,6 +46,7 @@ #include <gst/audio/audio.h> #include "gstaudiosrc.h" +#include "gstaudioutilsprivate.h" GST_DEBUG_CATEGORY_STATIC (gst_audio_src_debug); #define GST_CAT_DEFAULT gst_audio_src_debug @@ -192,6 +193,9 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf) if ((readfunc = csrc->read) == NULL) goto no_function; + if (G_UNLIKELY (!__gst_audio_set_thread_priority ())) + GST_WARNING_OBJECT (src, "failed to set thread priority"); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (src)); g_value_init (&val, GST_TYPE_G_THREAD); diff --git a/gst-libs/gst/audio/gstaudioutilsprivate.c b/gst-libs/gst/audio/gstaudioutilsprivate.c index 27b056bcb..cb3935c3c 100644 --- a/gst-libs/gst/audio/gstaudioutilsprivate.c +++ b/gst-libs/gst/audio/gstaudioutilsprivate.c @@ -23,6 +23,10 @@ #include "config.h" #endif +#ifdef _WIN32 +#include <windows.h> +#endif + #include <gst/audio/audio.h> #include "gstaudioutilsprivate.h" @@ -212,3 +216,64 @@ __gst_audio_encoded_audio_convert (GstAudioInfo * fmt, exit: return res; } + +#ifdef _WIN32 +/* *INDENT-OFF* */ +static struct +{ + HMODULE dll; + gboolean tried_loading; + + HANDLE (WINAPI * AvSetMmThreadCharacteristics) (LPCSTR, LPDWORD); + BOOL (WINAPI * AvRevertMmThreadCharacteristics) (HANDLE); +} _gst_audio_avrt_tbl = { 0 }; +/* *INDENT-ON* */ +#endif + +static gboolean +__gst_audio_init_thread_priority (void) +{ +#ifdef _WIN32 + if (_gst_audio_avrt_tbl.tried_loading) + return _gst_audio_avrt_tbl.dll != NULL; + + if (!_gst_audio_avrt_tbl.dll) + _gst_audio_avrt_tbl.dll = LoadLibrary (TEXT ("avrt.dll")); + + if (!_gst_audio_avrt_tbl.dll) { + GST_WARNING ("Failed to set thread priority, can't find avrt.dll"); + _gst_audio_avrt_tbl.tried_loading = TRUE; + return FALSE; + } + + _gst_audio_avrt_tbl.AvSetMmThreadCharacteristics = + GetProcAddress (_gst_audio_avrt_tbl.dll, "AvSetMmThreadCharacteristicsA"); + _gst_audio_avrt_tbl.AvRevertMmThreadCharacteristics = + GetProcAddress (_gst_audio_avrt_tbl.dll, + "AvRevertMmThreadCharacteristics"); + + _gst_audio_avrt_tbl.tried_loading = TRUE; +#endif + + return TRUE; +} + +/* + * Increases the priority of the thread it's called from + */ +gpointer +__gst_audio_set_thread_priority (void) +{ + if (!__gst_audio_init_thread_priority ()) + return NULL; + +#ifdef _WIN32 + DWORD taskIndex = 0; + /* This is only used from ringbuffer thread functions, so we don't need to + * ever need to revert the thread priorities. */ + return _gst_audio_avrt_tbl.AvSetMmThreadCharacteristics (TEXT ("Pro Audio"), + &taskIndex); +#else + return NULL; +#endif +} diff --git a/gst-libs/gst/audio/gstaudioutilsprivate.h b/gst-libs/gst/audio/gstaudioutilsprivate.h index 976765fa0..b9db8d802 100644 --- a/gst-libs/gst/audio/gstaudioutilsprivate.h +++ b/gst-libs/gst/audio/gstaudioutilsprivate.h @@ -42,6 +42,9 @@ gboolean __gst_audio_encoded_audio_convert (GstAudioInfo * fmt, gint64 bytes, gint64 src_value, GstFormat * dest_format, gint64 * dest_value); +G_GNUC_INTERNAL +gpointer __gst_audio_set_thread_priority (void); + G_END_DECLS #endif |