glbasefilter: expose finding the local GL context
authorMatthew Waters <matthew@centricular.com>
Thu, 3 May 2018 03:59:07 +0000 (13:59 +1000)
committerMatthew Waters <matthew@centricular.com>
Sat, 5 May 2018 11:24:25 +0000 (21:24 +1000)
And use it to attempt to find the GL context sooner for upload and color
conversion caps transformations.

ext/gl/gstglcolorconvertelement.c
ext/gl/gstglcolorconvertelement.h
ext/gl/gstgluploadelement.c
ext/gl/gstgluploadelement.h
gst-libs/gst/gl/gstglbasefilter.c
gst-libs/gst/gl/gstglbasefilter.h

index 642b494..9cd041d 100644 (file)
@@ -76,9 +76,6 @@ gst_gl_color_convert_element_stop (GstBaseTransform * bt)
     convert->convert = NULL;
   }
 
-  gst_caps_replace (&convert->in_caps, NULL);
-  gst_caps_replace (&convert->out_caps, NULL);
-
   return
       GST_BASE_TRANSFORM_CLASS (gst_gl_color_convert_element_parent_class)->stop
       (bt);
@@ -127,11 +124,8 @@ gst_gl_color_convert_element_set_caps (GstBaseTransform * bt,
 {
   GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt);
 
-  gst_caps_replace (&convert->in_caps, in_caps);
-  gst_caps_replace (&convert->out_caps, out_caps);
-
-  if (convert->convert)
-    gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps);
+  if (!gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps))
+    return FALSE;
 
   return TRUE;
 }
@@ -140,7 +134,17 @@ static GstCaps *
 gst_gl_color_convert_element_transform_caps (GstBaseTransform * bt,
     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
-  GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
+  GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt);
+  GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (bt);
+  GstGLContext *context;
+
+  if (base_filter->display && !gst_gl_base_filter_find_gl_context (base_filter))
+    return NULL;
+
+  context = GST_GL_BASE_FILTER (bt)->context;
+
+  if (!convert->convert && context)
+    convert->convert = gst_gl_color_convert_new (context);
 
   return gst_gl_color_convert_transform_caps (context, direction, caps, filter);
 }
@@ -172,7 +176,6 @@ gst_gl_color_convert_element_decide_allocation (GstBaseTransform * trans,
     GstQuery * query)
 {
   GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (trans);
-  GstGLContext *context;
 
   /* get gl context */
   if (!GST_BASE_TRANSFORM_CLASS
@@ -180,15 +183,6 @@ gst_gl_color_convert_element_decide_allocation (GstBaseTransform * trans,
           query))
     return FALSE;
 
-  context = GST_GL_BASE_FILTER (trans)->context;
-
-  if (!convert->convert)
-    convert->convert = gst_gl_color_convert_new (context);
-
-  if (!gst_gl_color_convert_set_caps (convert->convert, convert->in_caps,
-          convert->out_caps))
-    return FALSE;
-
   if (!gst_gl_color_convert_decide_allocation (convert->convert, query))
     return FALSE;
 
index 2a0dd1d..211871a 100644 (file)
@@ -45,8 +45,6 @@ struct _GstGLColorConvertElement
   GstGLBaseFilter        parent;
 
   GstGLColorConvert *convert;
-  GstCaps *in_caps;
-  GstCaps *out_caps;
 };
 
 struct _GstGLColorConvertElementClass
index f9e52f6..cac11b5 100644 (file)
@@ -124,9 +124,6 @@ gst_gl_upload_element_stop (GstBaseTransform * bt)
     upload->upload = NULL;
   }
 
-  gst_caps_replace (&upload->in_caps, NULL);
-  gst_caps_replace (&upload->out_caps, NULL);
-
   return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt);
 }
 
@@ -148,11 +145,16 @@ static GstCaps *
 _gst_gl_upload_element_transform_caps (GstBaseTransform * bt,
     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
+  GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (bt);
   GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt);
-  GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
+  GstGLContext *context;
 
+  if (base_filter->display && !gst_gl_base_filter_find_gl_context (base_filter))
+    return NULL;
+
+  context = GST_GL_BASE_FILTER (bt)->context;
   if (upload->upload == NULL)
-    upload->upload = gst_gl_upload_new (NULL);
+    upload->upload = gst_gl_upload_new (context);
 
   return gst_gl_upload_transform_caps (upload->upload, context, direction, caps,
       filter);
@@ -171,10 +173,15 @@ _gst_gl_upload_element_propose_allocation (GstBaseTransform * bt,
     GstQuery * decide_query, GstQuery * query)
 {
   GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt);
+  GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
   gboolean ret;
 
   if (!upload->upload)
     return FALSE;
+  if (!context)
+    return FALSE;
+
+  gst_gl_upload_set_context (upload->upload, context);
 
   ret = GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (bt,
       decide_query, query);
@@ -187,23 +194,9 @@ static gboolean
 _gst_gl_upload_element_decide_allocation (GstBaseTransform * trans,
     GstQuery * query)
 {
-  GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (trans);
-  GstGLContext *context;
-  gboolean ret;
-
-  ret =
+  return
       GST_BASE_TRANSFORM_CLASS
       (gst_gl_upload_element_parent_class)->decide_allocation (trans, query);
-  if (!ret)
-    return FALSE;
-
-  /* GstGLBaseFilter populates ->context in ::decide_allocation so now it's the
-   * time to set the ->upload context */
-  context = GST_GL_BASE_FILTER (trans)->context;
-  gst_gl_upload_set_context (upload->upload, context);
-
-  return gst_gl_upload_set_caps (upload->upload, upload->in_caps,
-      upload->out_caps);
 }
 
 static gboolean
@@ -212,13 +205,7 @@ _gst_gl_upload_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps,
 {
   GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt);
 
-  gst_caps_replace (&upload->in_caps, in_caps);
-  gst_caps_replace (&upload->out_caps, out_caps);
-
-  if (upload->upload)
-    return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps);
-
-  return TRUE;
+  return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps);
 }
 
 GstFlowReturn
index 615773c..05f98c3 100644 (file)
@@ -50,8 +50,6 @@ struct _GstGLUploadElement
   GstGLBaseFilter     parent;
 
   GstGLUpload *upload;
-  GstCaps *in_caps;
-  GstCaps *out_caps;
 };
 
 /**
index 3c9eb91..61514ce 100644 (file)
@@ -63,7 +63,8 @@ enum
 #define gst_gl_base_filter_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLBaseFilter, gst_gl_base_filter,
     GST_TYPE_BASE_TRANSFORM, GST_DEBUG_CATEGORY_INIT (gst_gl_base_filter_debug,
-        "glbasefilter", 0, "glbasefilter element"););
+        "glbasefilter", 0, "glbasefilter element");
+    );
 
 static void gst_gl_base_filter_finalize (GObject * object);
 static void gst_gl_base_filter_set_property (GObject * object, guint prop_id,
@@ -180,11 +181,13 @@ gst_gl_base_filter_set_context (GstElement * element, GstContext * context)
   GstGLBaseFilter *filter = GST_GL_BASE_FILTER (element);
   GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter);
 
+  GST_OBJECT_LOCK (filter);
   gst_gl_handle_set_context (element, context, &filter->display,
       &filter->priv->other_context);
   if (filter->display)
     gst_gl_display_filter_gl_api (filter->display,
         filter_class->supported_gl_api);
+  GST_OBJECT_UNLOCK (filter);
 
   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
 }
@@ -220,8 +223,12 @@ gst_gl_base_filter_query (GstBaseTransform * trans, GstPadDirection direction,
     }
     case GST_QUERY_CONTEXT:
     {
-      if (gst_gl_handle_context_query ((GstElement *) filter, query,
-              filter->display, filter->context, filter->priv->other_context))
+      gboolean ret;
+      GST_OBJECT_LOCK (filter);
+      ret = gst_gl_handle_context_query ((GstElement *) filter, query,
+          filter->display, filter->context, filter->priv->other_context);
+      GST_OBJECT_UNLOCK (filter);
+      if (ret)
         return TRUE;
       break;
     }
@@ -319,50 +326,9 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans,
 {
   GstGLBaseFilter *filter = GST_GL_BASE_FILTER (trans);
   GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter);
-  GError *error = NULL;
-  gboolean new_context = FALSE;
-
-  if (!filter->context)
-    new_context = TRUE;
-
-  _find_local_gl_context (filter);
-
-  if (!filter->context) {
-    GST_OBJECT_LOCK (filter->display);
-    do {
-      if (filter->context)
-        gst_object_unref (filter->context);
-      /* just get a GL context.  we don't care */
-      filter->context =
-          gst_gl_display_get_gl_context_for_thread (filter->display, NULL);
-      if (!filter->context) {
-        if (!gst_gl_display_create_context (filter->display,
-                filter->priv->other_context, &filter->context, &error)) {
-          GST_OBJECT_UNLOCK (filter->display);
-          goto context_error;
-        }
-      }
-    } while (!gst_gl_display_add_context (filter->display, filter->context));
-    GST_OBJECT_UNLOCK (filter->display);
-  }
-
-  if (new_context || !filter->priv->gl_started) {
-    if (filter->priv->gl_started)
-      gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_stop,
-          filter);
-
-    {
-      GstGLAPI current_gl_api = gst_gl_context_get_gl_api (filter->context);
-      if ((current_gl_api & filter_class->supported_gl_api) == 0)
-        goto unsupported_gl_api;
-    }
 
-    gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_start,
-        filter);
-
-    if (!filter->priv->gl_started)
-      goto error;
-  }
+  if (!gst_gl_base_filter_find_gl_context (filter))
+    return FALSE;
 
   if (filter_class->gl_set_caps) {
     gst_gl_context_thread_add (filter->context,
@@ -374,28 +340,6 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans,
   return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
       query);
 
-
-unsupported_gl_api:
-  {
-    GstGLAPI gl_api = gst_gl_context_get_gl_api (filter->context);
-    gchar *gl_api_str = gst_gl_api_to_string (gl_api);
-    gchar *supported_gl_api_str =
-        gst_gl_api_to_string (filter_class->supported_gl_api);
-    GST_ELEMENT_ERROR (filter, RESOURCE, BUSY,
-        ("GL API's not compatible context: %s supported: %s", gl_api_str,
-            supported_gl_api_str), (NULL));
-
-    g_free (supported_gl_api_str);
-    g_free (gl_api_str);
-    return FALSE;
-  }
-context_error:
-  {
-    GST_ELEMENT_ERROR (trans, RESOURCE, NOT_FOUND, ("%s", error->message),
-        (NULL));
-    g_clear_error (&error);
-    return FALSE;
-  }
 error:
   {
     GST_ELEMENT_ERROR (trans, LIBRARY, INIT,
@@ -431,8 +375,10 @@ gst_gl_base_filter_change_state (GstElement * element,
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       if (!gst_gl_ensure_element_data (element, &filter->display,
-              &filter->priv->other_context))
+              &filter->priv->other_context)) {
+        GST_OBJECT_UNLOCK (filter);
         return GST_STATE_CHANGE_FAILURE;
+      }
 
       gst_gl_display_filter_gl_api (filter->display,
           filter_class->supported_gl_api);
@@ -463,3 +409,90 @@ gst_gl_base_filter_change_state (GstElement * element,
 
   return ret;
 }
+
+/**
+ * gst_gl_base_filter_find_gl_context:
+ * @filter: a #GstGLBaseFilter
+ *
+ * Returns: Whether an OpenGL context could be retrieved or created successfully
+ */
+gboolean
+gst_gl_base_filter_find_gl_context (GstGLBaseFilter * filter)
+{
+  GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter);
+  GError *error = NULL;
+  gboolean new_context = FALSE;
+
+  if (!filter->context)
+    new_context = TRUE;
+
+  _find_local_gl_context (filter);
+
+  if (!filter->context) {
+    GST_OBJECT_LOCK (filter->display);
+    do {
+      if (filter->context)
+        gst_object_unref (filter->context);
+      /* just get a GL context.  we don't care */
+      filter->context =
+          gst_gl_display_get_gl_context_for_thread (filter->display, NULL);
+      if (!filter->context) {
+        if (!gst_gl_display_create_context (filter->display,
+                filter->priv->other_context, &filter->context, &error)) {
+          GST_OBJECT_UNLOCK (filter->display);
+          goto context_error;
+        }
+      }
+    } while (!gst_gl_display_add_context (filter->display, filter->context));
+    GST_OBJECT_UNLOCK (filter->display);
+  }
+
+  if (new_context || !filter->priv->gl_started) {
+    if (filter->priv->gl_started)
+      gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_stop,
+          filter);
+
+    {
+      GstGLAPI current_gl_api = gst_gl_context_get_gl_api (filter->context);
+      if ((current_gl_api & filter_class->supported_gl_api) == 0)
+        goto unsupported_gl_api;
+    }
+
+    gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_start,
+        filter);
+
+    if (!filter->priv->gl_started)
+      goto error;
+  }
+
+  return TRUE;
+
+unsupported_gl_api:
+  {
+    GstGLAPI gl_api = gst_gl_context_get_gl_api (filter->context);
+    gchar *gl_api_str = gst_gl_api_to_string (gl_api);
+    gchar *supported_gl_api_str =
+        gst_gl_api_to_string (filter_class->supported_gl_api);
+
+    GST_ELEMENT_ERROR (filter, RESOURCE, BUSY,
+        ("GL API's not compatible context: %s supported: %s", gl_api_str,
+            supported_gl_api_str), (NULL));
+
+    g_free (supported_gl_api_str);
+    g_free (gl_api_str);
+    return FALSE;
+  }
+context_error:
+  {
+    GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, ("%s", error->message),
+        (NULL));
+    g_clear_error (&error);
+    return FALSE;
+  }
+error:
+  {
+    GST_ELEMENT_ERROR (filter, LIBRARY, INIT,
+        ("Subclass failed to initialize."), (NULL));
+    return FALSE;
+  }
+}
index 16d2b68..48c1311 100644 (file)
@@ -88,6 +88,9 @@ struct _GstGLBaseFilterClass
   gpointer _padding[GST_PADDING];
 };
 
+GST_EXPORT
+gboolean        gst_gl_base_filter_find_gl_context          (GstGLBaseFilter * filter);
+
 G_END_DECLS
 
 #endif /* _GST_GL_BASE_FILTER_H_ */