video: convertframe: Shut down pipeline asynchronously via the thread pool
authorSebastian Dröge <sebastian@centricular.com>
Fri, 30 Nov 2018 10:40:19 +0000 (12:40 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 30 Nov 2018 10:40:19 +0000 (12:40 +0200)
If we use the main loop it might happen that the caller (e.g. our unit
test) already shut down the loop once the result was received and in
that case the pipeline would never ever be shut down (and our unit test
would hang).

gst-libs/gst/video/convertframe.c

index 4b69fa4..47cab8a 100644 (file)
@@ -489,11 +489,10 @@ convert_frame_dispatch_callback (GstVideoConvertSampleContext * ctx)
   return FALSE;
 }
 
-static gboolean
-convert_frame_stop_pipeline (GstElement * element)
+static void
+convert_frame_stop_pipeline (GstElement * element, gpointer user_data)
 {
   gst_element_set_state (element, GST_STATE_NULL);
-  return FALSE;
 }
 
 static void
@@ -525,14 +524,14 @@ convert_frame_finish (GstVideoConvertSampleContext * context,
    * state to NULL and get rid of its last reference, which in turn
    * will get rid of all remaining references to our context and free
    * it too. We can't do this directly here as we might be called from
-   * a streaming thread. */
+   * a streaming thread.
+   *
+   * We don't use the main loop here because the user might shut down it
+   * immediately after getting the result of the conversion above.
+   */
   if (context->pipeline) {
-    source = g_timeout_source_new (0);
-    g_source_set_callback (source,
-        (GSourceFunc) convert_frame_stop_pipeline,
-        context->pipeline, (GDestroyNotify) gst_object_unref);
-    g_source_attach (source, context->context);
-    g_source_unref (source);
+    gst_element_call_async (context->pipeline, convert_frame_stop_pipeline,
+        NULL, NULL);
     context->pipeline = NULL;
   }
 }