plugins: create a GL context on certain conditions
authorVíctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Thu, 26 Jan 2017 11:02:56 +0000 (12:02 +0100)
committerVíctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Fri, 27 Jan 2017 10:27:35 +0000 (11:27 +0100)
If a GstVaapiDisplay is not found in the GStreamer context sharing,
then VAAPI elements look for a local GstGLContext in gst context
sharing mechanism ('gst.gl.local.context').

If this GstGLContext not found either then, only the VAAPI decoders
and the VAAPI post-processor, will try to instantiate a new
GstGLContext.

If a valid GstGLContext is received, then a new GstVaapiDisplay will
be instantiated with the platform, API and windowing specified by the
instantiated GstGLContext.

Original-Patch-By: Matt Fischer <matt.fischer@garmin.com>
https://bugzilla.gnome.org/show_bug.cgi?id=777409

gst/vaapi/gstvaapipluginbase.c
gst/vaapi/gstvaapipluginbase.h
gst/vaapi/gstvaapipluginutil.c

index d37300e..d951aa4 100644 (file)
@@ -30,6 +30,9 @@
 #include "gstvaapivideocontext.h"
 #include "gstvaapivideometa.h"
 #include "gstvaapivideobufferpool.h"
+#if USE_GST_GL_HELPERS
+# include <gst/gl/gl.h>
+#endif
 
 /* Default debug category is from the subclass */
 #define GST_CAT_DEFAULT (plugin->debug_category)
@@ -75,6 +78,12 @@ gst_vaapi_plugin_base_set_context (GstVaapiPluginBase * plugin,
 
   if (gst_vaapi_video_context_get_display (context, &display))
     plugin_set_display (plugin, display);
+
+#if USE_GST_GL_HELPERS
+  gst_gl_handle_set_context (GST_ELEMENT_CAST (plugin), context,
+      (GstGLDisplay **) & plugin->gl_display,
+      (GstGLContext **) & plugin->gl_other_context);
+#endif
 }
 
 void
@@ -215,17 +224,6 @@ plugin_reset_texture_map (GstVaapiPluginBase * plugin)
     gst_vaapi_display_reset_texture_map (plugin->display);
 }
 
-static void
-gst_vaapi_plugin_base_find_gl_context (GstVaapiPluginBase * plugin)
-{
-  GstObject *gl_context;
-
-  if (!gst_vaapi_find_gl_local_context (GST_ELEMENT_CAST (plugin), &gl_context))
-    return;
-  gst_vaapi_plugin_base_set_gl_context (plugin, gl_context);
-  gst_object_unref (gl_context);
-}
-
 void
 gst_vaapi_plugin_base_class_init (GstVaapiPluginBaseClass * klass)
 {
@@ -292,6 +290,8 @@ gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin)
 
   gst_vaapi_display_replace (&plugin->display, NULL);
   gst_object_replace (&plugin->gl_context, NULL);
+  gst_object_replace (&plugin->gl_display, NULL);
+  gst_object_replace (&plugin->gl_other_context, NULL);
 
   gst_caps_replace (&plugin->sinkpad_caps, NULL);
   gst_video_info_init (&plugin->sinkpad_info);
@@ -386,10 +386,6 @@ gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin)
     return TRUE;
   gst_vaapi_display_replace (&plugin->display, NULL);
 
-  /* Query for a local GstGL context. If it's found, it will be used
-   * to create the VA display */
-  gst_vaapi_plugin_base_find_gl_context (plugin);
-
   if (!gst_vaapi_ensure_display (GST_ELEMENT (plugin),
           plugin->display_type_req))
     return FALSE;
@@ -1121,6 +1117,56 @@ gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
 #endif
 }
 
+/**
+ * gst_vaapi_plugin_base_create_gl_context:
+ * @plugin: a #GstVaapiPluginBase
+ *
+ * It queries downstream and upstream for a #GstGLDisplay and a other
+ * #GstGLContext. If not found, a new #GstGLDisplay and #GstGLContext
+ * are created, if it is possible.
+ *
+ * Returns: (transfer full) a new created #GstGLContext or %NULL
+ **/
+GstObject *
+gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin)
+{
+#if USE_GST_GL_HELPERS
+  GstGLContext *gl_other_context, *gl_context = NULL;
+  GstGLDisplay *gl_display;
+
+  gst_gl_ensure_element_data (plugin, (GstGLDisplay **) & plugin->gl_display,
+      (GstGLContext **) & plugin->gl_other_context);
+
+  gl_display = (GstGLDisplay *) plugin->gl_display;
+  if (!gl_display ||
+      gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY) {
+    gst_object_replace (&plugin->gl_display, NULL);
+    gst_object_replace (&plugin->gl_other_context, NULL);
+    return NULL;
+  }
+  gl_other_context = (GstGLContext *) plugin->gl_other_context;
+
+  GST_INFO_OBJECT (plugin, "creating a new GstGL context");
+
+  GST_OBJECT_LOCK (gl_display);
+  do {
+    if (gl_context)
+      gst_object_unref (gl_context);
+    gl_context = gst_gl_display_get_gl_context_for_thread (gl_display, NULL);
+    if (!gl_context) {
+      if (!gst_gl_display_create_context (gl_display, gl_other_context,
+              &gl_context, NULL))
+        break;
+    }
+  } while (!gst_gl_display_add_context (gl_display, gl_context));
+  GST_OBJECT_UNLOCK (gl_display);
+
+  return GST_OBJECT_CAST (gl_context);
+#else
+  return NULL;
+#endif
+}
+
 static gboolean
 ensure_allowed_raw_caps (GstVaapiPluginBase * plugin)
 {
index 9526d8f..e1db5e7 100644 (file)
@@ -140,6 +140,8 @@ struct _GstVaapiPluginBase
   gchar *display_name;
 
   GstObject *gl_context;
+  GstObject *gl_display;
+  GstObject *gl_other_context;
 
   GstCaps *allowed_raw_caps;
   GstAllocator *sinkpad_allocator;
@@ -237,6 +239,10 @@ gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
     GstObject * object);
 
 G_GNUC_INTERNAL
+GstObject *
+gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin);
+
+G_GNUC_INTERNAL
 GstCaps *
 gst_vaapi_plugin_base_get_allowed_raw_caps (GstVaapiPluginBase * plugin);
 
index 2dcfbdb..ec7c36d 100644 (file)
@@ -241,6 +241,29 @@ gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object)
   return NULL;
 }
 
+static void
+gst_vaapi_find_gl_context (GstElement * element)
+{
+  GstObject *gl_context;
+  GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element);
+
+  /* if the element is vaapisink or any vaapi encoder it doesn't need
+   * to know a GstGLContext in order to create an appropriate
+   * GstVaapiDisplay. Let's them to choose their own
+   * GstVaapiDisplay */
+  if (GST_IS_VIDEO_SINK (element) || GST_IS_VIDEO_ENCODER (element))
+    return;
+
+  gl_context = NULL;
+  if (!gst_vaapi_find_gl_local_context (element, &gl_context))
+    gl_context = gst_vaapi_plugin_base_create_gl_context (plugin);
+
+  if (gl_context) {
+    gst_vaapi_plugin_base_set_gl_context (plugin, gl_context);
+    gst_object_unref (gl_context);
+  }
+}
+
 gboolean
 gst_vaapi_ensure_display (GstElement * element, GstVaapiDisplayType type)
 {
@@ -255,6 +278,11 @@ gst_vaapi_ensure_display (GstElement * element, GstVaapiDisplayType type)
       return TRUE;
   }
 
+  /* Query for a local GstGL context. If it's found, it will be used
+   * to create the VA display */
+  if (!plugin->gl_context)
+    gst_vaapi_find_gl_context (element);
+
   /* If no neighboor, or application not interested, use system default */
   if (plugin->gl_context)
     display = gst_vaapi_create_display_from_gl_context (plugin->gl_context);