plugins: create a GL context on certain conditions

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
This commit is contained in:
Víctor Manuel Jáquez Leal 2017-01-26 12:02:56 +01:00
parent 43d4f0bfb5
commit 0968ce468d
3 changed files with 95 additions and 15 deletions

View 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)
{

View 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;
@ -236,6 +238,10 @@ void
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);

View 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);