audioutilsprivate: restore thread priority before ending
authorSilvio Lazzeretti <silviola@amazon.com>
Thu, 16 Jul 2020 12:34:51 +0000 (14:34 +0200)
committerSilvio Lazzeretti <silviola@amazon.com>
Sat, 18 Jul 2020 11:00:00 +0000 (13:00 +0200)
The priority of the thread that executes audioringbuffer_thread_func
is incremented on Windows by the usage of the AvSetMmThreadCharacteristics
API. This change has to be restored, as described on the documentation
of the API (https://docs.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avsetmmthreadcharacteristicsw#remarks),
with a call to the AvRevertMmThreadCharacteristics. If this is not done,
a handle will be leaked.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/760>

gst-libs/gst/audio/gstaudiosink.c
gst-libs/gst/audio/gstaudiosrc.c
gst-libs/gst/audio/gstaudioutilsprivate.c
gst-libs/gst/audio/gstaudioutilsprivate.h

index 0aa4433..5103f2d 100644 (file)
@@ -205,6 +205,7 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
   WriteFunc writefunc;
   GstMessage *message;
   GValue val = { 0 };
+  gpointer handle;
 
   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
   csink = GST_AUDIO_SINK_GET_CLASS (sink);
@@ -220,7 +221,7 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
   if (writefunc == NULL)
     goto no_function;
 
-  if (G_UNLIKELY (!__gst_audio_set_thread_priority ()))
+  if (G_UNLIKELY (!__gst_audio_set_thread_priority (&handle)))
     GST_WARNING_OBJECT (sink, "failed to set thread priority");
 
   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
@@ -306,6 +307,9 @@ stop_running:
     g_value_unset (&val);
     GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
     gst_element_post_message (GST_ELEMENT_CAST (sink), message);
+
+    if (G_UNLIKELY (!__gst_audio_restore_thread_priority (handle)))
+      GST_WARNING_OBJECT (sink, "failed to restore thread priority");
     return;
   }
 }
index 77843f4..fccdeac 100644 (file)
@@ -187,6 +187,7 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
   ReadFunc readfunc;
   GstMessage *message;
   GValue val = { 0 };
+  gpointer handle;
 
   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
   csrc = GST_AUDIO_SRC_GET_CLASS (src);
@@ -196,7 +197,7 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
   if ((readfunc = csrc->read) == NULL)
     goto no_function;
 
-  if (G_UNLIKELY (!__gst_audio_set_thread_priority ()))
+  if (G_UNLIKELY (!__gst_audio_set_thread_priority (&handle)))
     GST_WARNING_OBJECT (src, "failed to set thread priority");
 
   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
@@ -281,6 +282,9 @@ stop_running:
     g_value_unset (&val);
     GST_DEBUG_OBJECT (src, "posting LEAVE stream status");
     gst_element_post_message (GST_ELEMENT_CAST (src), message);
+
+    if (G_UNLIKELY (!__gst_audio_restore_thread_priority (handle)))
+      GST_WARNING_OBJECT (src, "failed to restore thread priority");
     return;
   }
 }
index 0ace496..1db4601 100644 (file)
@@ -281,20 +281,54 @@ __gst_audio_init_thread_priority (void)
  * Increases the priority of the thread it's called from
  */
 gboolean
-__gst_audio_set_thread_priority (void)
+__gst_audio_set_thread_priority (gpointer * handle)
 {
 #ifdef G_OS_WIN32
   DWORD taskIndex = 0;
 #endif
 
+  g_return_val_if_fail (handle != NULL, FALSE);
+
+  *handle = NULL;
+
   if (!__gst_audio_init_thread_priority ())
     return FALSE;
 
 #ifdef G_OS_WIN32
-  /* 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) != 0;
+  /* This is only used from ringbuffer thread functions */
+  *handle = (gpointer)
+      _gst_audio_avrt_tbl.AvSetMmThreadCharacteristics (TEXT ("Pro Audio"),
+      &taskIndex);
+  if (*handle == 0) {
+    gchar *errorMsg = g_win32_error_message (GetLastError ());
+
+    GST_WARNING
+        ("Failed to set thread priority, AvSetMmThreadCharacteristics returned: %s",
+        errorMsg);
+    g_free (errorMsg);
+  }
+
+  return *handle != 0;
+#else
+  return TRUE;
+#endif
+}
+
+/*
+ * Restores the priority of the thread that was increased
+ * with __gst_audio_set_thread_priority.
+ * This function must be called from the same thread that called the
+ * __gst_audio_set_thread_priority function.
+ * See https://docs.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avsetmmthreadcharacteristicsw#remarks
+ */
+gboolean
+__gst_audio_restore_thread_priority (gpointer handle)
+{
+#ifdef G_OS_WIN32
+  if (!handle)
+    return FALSE;
+
+  return _gst_audio_avrt_tbl.AvRevertMmThreadCharacteristics ((HANDLE) handle);
 #else
   return TRUE;
 #endif
index 4e2b61a..1c5ecd6 100644 (file)
@@ -43,7 +43,10 @@ gboolean __gst_audio_encoded_audio_convert (GstAudioInfo * fmt, gint64 bytes,
                                             gint64 * dest_value);
 
 G_GNUC_INTERNAL
-gboolean __gst_audio_set_thread_priority   (void);
+gboolean __gst_audio_set_thread_priority   (gpointer * handle);
+
+G_GNUC_INTERNAL
+gboolean __gst_audio_restore_thread_priority (gpointer handle);
 
 G_END_DECLS