summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2018-09-11 00:41:59 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2018-09-11 00:44:18 +0530
commit118338a72532b051ab8930b43d9c494335a290f5 (patch)
tree4dc00398e4749a889e6239f55a12e04e41c81489
parentda8f9afd8879f24a754b50b09d8373822f7b7555 (diff)
downloadgstreamer-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.c4
-rw-r--r--gst-libs/gst/audio/gstaudiosrc.c4
-rw-r--r--gst-libs/gst/audio/gstaudioutilsprivate.c65
-rw-r--r--gst-libs/gst/audio/gstaudioutilsprivate.h3
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