gldisplay: synchronize the searching and creation of GstGLContext's
authorMatthew Waters <matthew@centricular.com>
Tue, 21 Apr 2015 02:19:46 +0000 (12:19 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:59 +0000 (19:31 +0000)
Ootherwise we could end up with multiple elements in different chains
each creating a context.  Fixes context creation with glvideomixer.

ext/gl/gstglbasemixer.c
ext/gl/gstglimagesink.c
ext/gl/gstgltestsrc.c
gst-libs/gst/gl/gstglbasefilter.c
gst-libs/gst/gl/gstglcontext.c
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h

index 64c019c..448c6a6 100644 (file)
@@ -484,6 +484,7 @@ gst_gl_base_mixer_decide_allocation (GstGLBaseMixer * mix, GstQuery * query)
   _find_local_gl_context (mix);
 
   if (!mix->context) {
+    GST_OBJECT_LOCK (mix->display);
     do {
       if (mix->context)
         gst_object_unref (mix->context);
@@ -497,6 +498,7 @@ gst_gl_base_mixer_decide_allocation (GstGLBaseMixer * mix, GstQuery * query)
           goto context_error;
       }
     } while (!gst_gl_display_add_context (mix->display, mix->context));
+    GST_OBJECT_UNLOCK (mix->display);
   }
 
   if (mix_class->decide_allocation)
index a7347fd..1047616 100644 (file)
@@ -698,6 +698,7 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
   GST_DEBUG_OBJECT (gl_sink, "Ensuring setup");
 
   if (!gl_sink->context) {
+    GST_OBJECT_LOCK (gl_sink->display);
     do {
       GstGLContext *other_context;
       GstGLWindow *window;
@@ -770,6 +771,7 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
         gst_object_unref (other_context);
       gst_object_unref (window);
     } while (!gst_gl_display_add_context (gl_sink->display, gl_sink->context));
+    GST_OBJECT_UNLOCK (gl_sink->display);
   } else
     GST_DEBUG_OBJECT (gl_sink, "Already have a context");
 
@@ -908,6 +910,9 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
       gst_gl_display_filter_gl_api (glimage_sink->display, SUPPORTED_GL_APIS);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      if (!_ensure_gl_setup (glimage_sink))
+        return GST_STATE_CHANGE_FAILURE;
+
       g_atomic_int_set (&glimage_sink->to_quit, 0);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
index dbd5610..788fd86 100644 (file)
@@ -816,6 +816,7 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
   _find_local_gl_context (src);
 
   if (!src->context) {
+    GST_OBJECT_LOCK (src->display);
     do {
       if (src->context)
         gst_object_unref (src->context);
@@ -828,6 +829,7 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
           goto context_error;
       }
     } while (!gst_gl_display_add_context (src->display, src->context));
+    GST_OBJECT_UNLOCK (src->display);
   }
 
   out_width = GST_VIDEO_INFO_WIDTH (&src->out_info);
index 838842d..628de3d 100644 (file)
@@ -334,6 +334,7 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans,
   _find_local_gl_context (filter);
 
   if (!filter->context) {
+    GST_OBJECT_LOCK (filter->display);
     do {
       if (filter->context)
         gst_object_unref (filter->context);
@@ -350,6 +351,7 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans,
           goto context_error;
       }
     } while (!gst_gl_display_add_context (filter->display, filter->context));
+    GST_OBJECT_UNLOCK (filter->display);
   }
 
   gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_start,
index b578a16..18e527e 100644 (file)
@@ -1216,7 +1216,7 @@ gst_gl_context_create_thread (GstGLContext * context)
   context_class = GST_GL_CONTEXT_GET_CLASS (context);
   window_class = GST_GL_WINDOW_GET_CLASS (context->window);
 
-  display_api = gst_gl_display_get_gl_api (context->priv->display);
+  display_api = gst_gl_display_get_gl_api_unlocked (context->priv->display);
   if (display_api == GST_GL_API_NONE) {
     g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
         "Cannot create context with satisfying requested apis "
index 50d53cc..a049af4 100644 (file)
@@ -237,6 +237,14 @@ gst_gl_display_filter_gl_api (GstGLDisplay * display, GstGLAPI gl_api)
   GST_OBJECT_UNLOCK (display);
 }
 
+GstGLAPI
+gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display)
+{
+  g_return_val_if_fail (GST_IS_GL_DISPLAY (display), GST_GL_API_NONE);
+
+  return display->priv->gl_api;
+}
+
 /**
  * gst_gl_display_get_gl_api:
  * @display: a #GstGLDisplay
@@ -372,6 +380,8 @@ _get_gl_context_for_thread_unlocked (GstGLDisplay * display, GThread * thread)
  *
  * Returns: (transfer full): the #GstGLContext current on @thread or %NULL
  *
+ * Must be called with the object lock held.
+ *
  * Since: 1.6
  */
 GstGLContext *
@@ -382,11 +392,9 @@ gst_gl_display_get_gl_context_for_thread (GstGLDisplay * display,
 
   g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
 
-  GST_OBJECT_LOCK (display);
   context = _get_gl_context_for_thread_unlocked (display, thread);
   GST_DEBUG_OBJECT (display, "returning context %" GST_PTR_FORMAT " for thread "
       "%p", context, thread);
-  GST_OBJECT_UNLOCK (display);
 
   return context;
 }
@@ -430,6 +438,8 @@ out:
  * Returns: whether @context was successfully added. %FALSE may be returned
  * if there already exists another context for @context's active thread.
  *
+ * Must be called with the object lock held.
+ *
  * Since: 1.6
  */
 gboolean
@@ -448,8 +458,6 @@ gst_gl_display_add_context (GstGLDisplay * display, GstGLContext * context)
   g_assert (context_display == display);
   gst_object_unref (context_display);
 
-  GST_OBJECT_LOCK (display);
-
   thread = gst_gl_context_get_thread (context);
   if (thread) {
     collision = _get_gl_context_for_thread_unlocked (display, thread);
@@ -471,7 +479,6 @@ out:
 
   GST_DEBUG_OBJECT (display, "%ssuccessfully inserted context %" GST_PTR_FORMAT,
       ret ? "" : "un", context);
-  GST_OBJECT_UNLOCK (display);
 
   return ret;
 }
index d50b463..a9c1433 100644 (file)
@@ -86,6 +86,7 @@ GstGLDisplayType gst_gl_display_get_handle_type        (GstGLDisplay * display);
 void             gst_gl_display_filter_gl_api          (GstGLDisplay * display,
                                                         GstGLAPI api);
 GstGLAPI         gst_gl_display_get_gl_api             (GstGLDisplay * display);
+GstGLAPI         gst_gl_display_get_gl_api_unlocked    (GstGLDisplay * display);
 
 #define GST_GL_DISPLAY_CONTEXT_TYPE "gst.gl.GLDisplay"
 void     gst_context_set_gl_display (GstContext * context, GstGLDisplay * display);