mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
[852/906] use GstContext for GstGLDisplay propogation
implements the hooks required in GstElement::set_context and the context query
This commit is contained in:
parent
f15206082a
commit
64fad7a6d2
6 changed files with 335 additions and 32 deletions
|
@ -28,11 +28,13 @@
|
||||||
#include "gl.h"
|
#include "gl.h"
|
||||||
#include "gstgldisplay.h"
|
#include "gstgldisplay.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_context);
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
||||||
#define GST_CAT_DEFAULT gst_gl_display_debug
|
#define GST_CAT_DEFAULT gst_gl_display_debug
|
||||||
|
|
||||||
#define DEBUG_INIT \
|
#define DEBUG_INIT \
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_gl_display_debug, "gldisplay", 0, "opengl display");
|
GST_DEBUG_CATEGORY_INIT (gst_gl_display_debug, "gldisplay", 0, "opengl display"); \
|
||||||
|
GST_DEBUG_CATEGORY_GET (gst_context, "GST_CONTEXT");
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, G_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, G_TYPE_OBJECT,
|
||||||
DEBUG_INIT);
|
DEBUG_INIT);
|
||||||
|
@ -66,6 +68,8 @@ gst_gl_display_init (GstGLDisplay * display)
|
||||||
|
|
||||||
display->gl_api = GST_GL_API_NONE;
|
display->gl_api = GST_GL_API_NONE;
|
||||||
|
|
||||||
|
GST_TRACE ("init %p", display);
|
||||||
|
|
||||||
gst_gl_memory_init ();
|
gst_gl_memory_init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +83,8 @@ gst_gl_display_finalize (GObject * object)
|
||||||
display->context = NULL;
|
display->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_TRACE ("finalize %p", object);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +148,11 @@ gst_context_set_gl_display (GstContext * context, GstGLDisplay * display)
|
||||||
{
|
{
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
|
|
||||||
|
g_return_if_fail (context != NULL);
|
||||||
|
|
||||||
|
GST_CAT_LOG (gst_context, "setting GstGLDisplay(%p) on context(%p)", display,
|
||||||
|
context);
|
||||||
|
|
||||||
s = gst_context_writable_structure (context);
|
s = gst_context_writable_structure (context);
|
||||||
gst_structure_set (s, GST_GL_DISPLAY_CONTEXT_TYPE, GST_TYPE_GL_DISPLAY,
|
gst_structure_set (s, GST_GL_DISPLAY_CONTEXT_TYPE, GST_TYPE_GL_DISPLAY,
|
||||||
display, NULL);
|
display, NULL);
|
||||||
|
@ -151,8 +162,17 @@ gboolean
|
||||||
gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display)
|
gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display)
|
||||||
{
|
{
|
||||||
const GstStructure *s;
|
const GstStructure *s;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (context != NULL, FALSE);
|
||||||
|
|
||||||
s = gst_context_get_structure (context);
|
s = gst_context_get_structure (context);
|
||||||
return gst_structure_get (s, GST_GL_DISPLAY_CONTEXT_TYPE,
|
ret = gst_structure_get (s, GST_GL_DISPLAY_CONTEXT_TYPE,
|
||||||
GST_TYPE_GL_DISPLAY, display, NULL);
|
GST_TYPE_GL_DISPLAY, display, NULL);
|
||||||
|
|
||||||
|
GST_CAT_LOG (gst_context, "got GstGLDisplay(%p) from context(%p)", *display,
|
||||||
|
context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,8 @@ static void gst_gl_filter_set_property (GObject * object, guint prop_id,
|
||||||
static void gst_gl_filter_get_property (GObject * object, guint prop_id,
|
static void gst_gl_filter_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static void gst_gl_filter_set_context (GstElement * element,
|
||||||
|
GstContext * context);
|
||||||
static gboolean gst_gl_filter_query (GstBaseTransform * trans,
|
static gboolean gst_gl_filter_query (GstBaseTransform * trans,
|
||||||
GstPadDirection direction, GstQuery * query);
|
GstPadDirection direction, GstQuery * query);
|
||||||
static GstCaps *gst_gl_filter_transform_caps (GstBaseTransform * bt,
|
static GstCaps *gst_gl_filter_transform_caps (GstBaseTransform * bt,
|
||||||
|
@ -112,6 +114,8 @@ gst_gl_filter_class_init (GstGLFilterClass * klass)
|
||||||
gst_gl_filter_decide_allocation;
|
gst_gl_filter_decide_allocation;
|
||||||
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_filter_get_unit_size;
|
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_filter_get_unit_size;
|
||||||
|
|
||||||
|
element_class->set_context = gst_gl_filter_set_context;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_OTHER_CONTEXT,
|
g_object_class_install_property (gobject_class, PROP_OTHER_CONTEXT,
|
||||||
g_param_spec_object ("other-context",
|
g_param_spec_object ("other-context",
|
||||||
"External OpenGL context",
|
"External OpenGL context",
|
||||||
|
@ -176,6 +180,14 @@ gst_gl_filter_get_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_set_context (GstElement * element, GstContext * context)
|
||||||
|
{
|
||||||
|
GstGLFilter *filter = GST_GL_FILTER (element);
|
||||||
|
|
||||||
|
gst_gl_handle_set_context (element, context, &filter->display);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_filter_query (GstBaseTransform * trans, GstPadDirection direction,
|
gst_gl_filter_query (GstBaseTransform * trans, GstPadDirection direction,
|
||||||
GstQuery * query)
|
GstQuery * query)
|
||||||
|
@ -186,13 +198,19 @@ gst_gl_filter_query (GstBaseTransform * trans, GstPadDirection direction,
|
||||||
filter = GST_GL_FILTER (trans);
|
filter = GST_GL_FILTER (trans);
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_CONTEXT:
|
||||||
|
{
|
||||||
|
res = gst_gl_handle_context_query ((GstElement *) filter, query,
|
||||||
|
&filter->display);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_QUERY_CUSTOM:
|
case GST_QUERY_CUSTOM:
|
||||||
{
|
{
|
||||||
GstStructure *structure = gst_query_writable_structure (query);
|
GstStructure *structure = gst_query_writable_structure (query);
|
||||||
if (direction == GST_PAD_SINK &&
|
if (direction == GST_PAD_SINK &&
|
||||||
gst_structure_has_name (structure, "gstgldisplay")) {
|
gst_structure_has_name (structure, "gstglcontext")) {
|
||||||
gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER,
|
gst_structure_set (structure, "gstglcontext", G_TYPE_POINTER,
|
||||||
filter->display, NULL);
|
filter->context, NULL);
|
||||||
res = TRUE;
|
res = TRUE;
|
||||||
} else
|
} else
|
||||||
res =
|
res =
|
||||||
|
@ -243,6 +261,10 @@ gst_gl_filter_reset (GstGLFilter * filter)
|
||||||
if (filter->other_context)
|
if (filter->other_context)
|
||||||
gst_object_unref (filter->other_context);
|
gst_object_unref (filter->other_context);
|
||||||
filter->other_context = NULL;
|
filter->other_context = NULL;
|
||||||
|
|
||||||
|
if (filter->context)
|
||||||
|
gst_object_unref (filter->context);
|
||||||
|
filter->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -251,28 +273,29 @@ gst_gl_filter_start (GstBaseTransform * bt)
|
||||||
GstGLFilter *filter = GST_GL_FILTER (bt);
|
GstGLFilter *filter = GST_GL_FILTER (bt);
|
||||||
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
GstQuery *display_query;
|
GstQuery *context_query;
|
||||||
const GValue *id_value;
|
const GValue *id_value;
|
||||||
|
|
||||||
structure = gst_structure_new_empty ("gstgldisplay");
|
if (!gst_gl_ensure_display (filter, &filter->display))
|
||||||
display_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
return FALSE;
|
||||||
|
|
||||||
if (!gst_pad_peer_query (bt->srcpad, display_query)) {
|
structure = gst_structure_new_empty ("gstglcontext");
|
||||||
|
context_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||||
|
|
||||||
|
if (!gst_pad_peer_query (bt->srcpad, context_query)) {
|
||||||
GST_WARNING
|
GST_WARNING
|
||||||
("Could not query GstGLDisplay from downstream (peer query failed)");
|
("Could not query GstGLContext from downstream (peer query failed)");
|
||||||
}
|
}
|
||||||
|
|
||||||
id_value = gst_structure_get_value (structure, "gstgldisplay");
|
id_value = gst_structure_get_value (structure, "gstglcontext");
|
||||||
if (G_VALUE_HOLDS_POINTER (id_value)) {
|
if (G_VALUE_HOLDS_POINTER (id_value)) {
|
||||||
/* at least one gl element is after in our gl chain */
|
/* at least one gl element is after in our gl chain */
|
||||||
filter->display =
|
filter->context =
|
||||||
gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
gst_object_ref (GST_GL_CONTEXT (g_value_get_pointer (id_value)));
|
||||||
filter->context = gst_gl_display_get_context (filter->display);
|
|
||||||
} else {
|
} else {
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
GST_INFO ("Creating GstGLDisplay");
|
GST_INFO ("Creating GstGLContext");
|
||||||
filter->display = gst_gl_display_new ();
|
|
||||||
filter->context = gst_gl_context_new (filter->display);
|
filter->context = gst_gl_context_new (filter->display);
|
||||||
|
|
||||||
if (!gst_gl_context_create (filter->context, filter->other_context, &error)) {
|
if (!gst_gl_context_create (filter->context, filter->other_context, &error)) {
|
||||||
|
@ -282,6 +305,8 @@ gst_gl_filter_start (GstBaseTransform * bt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_query_unref (context_query);
|
||||||
|
|
||||||
if (filter_class->onStart)
|
if (filter_class->onStart)
|
||||||
filter_class->onStart (filter);
|
filter_class->onStart (filter);
|
||||||
|
|
||||||
|
@ -1067,6 +1092,9 @@ gst_gl_filter_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
||||||
filter = GST_GL_FILTER (bt);
|
filter = GST_GL_FILTER (bt);
|
||||||
filter_class = GST_GL_FILTER_GET_CLASS (bt);
|
filter_class = GST_GL_FILTER_GET_CLASS (bt);
|
||||||
|
|
||||||
|
if (!gst_gl_ensure_display (filter, &filter->display))
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
|
||||||
g_assert (filter_class->filter || filter_class->filter_texture);
|
g_assert (filter_class->filter || filter_class->filter_texture);
|
||||||
|
|
||||||
if (filter_class->filter)
|
if (filter_class->filter)
|
||||||
|
|
|
@ -65,7 +65,6 @@ struct _GstGLFilter
|
||||||
GstBufferPool *pool;
|
GstBufferPool *pool;
|
||||||
|
|
||||||
GstGLDisplay *display;
|
GstGLDisplay *display;
|
||||||
GstGLContext *context;
|
|
||||||
|
|
||||||
GstVideoInfo in_info;
|
GstVideoInfo in_info;
|
||||||
GstVideoInfo out_info;
|
GstVideoInfo out_info;
|
||||||
|
@ -81,6 +80,7 @@ struct _GstGLFilter
|
||||||
|
|
||||||
GstGLShader *default_shader;
|
GstGLShader *default_shader;
|
||||||
|
|
||||||
|
GstGLContext *context;
|
||||||
GstGLContext *other_context;
|
GstGLContext *other_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ static gboolean gst_gl_mixer_sink_event (GstCollectPads * pads,
|
||||||
GstCollectData * cdata, GstEvent * event, GstGLMixer * mix);
|
GstCollectData * cdata, GstEvent * event, GstGLMixer * mix);
|
||||||
static gboolean gst_gl_mixer_src_setcaps (GstPad * pad, GstGLMixer * mix,
|
static gboolean gst_gl_mixer_src_setcaps (GstPad * pad, GstGLMixer * mix,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
static void gst_gl_mixer_set_context (GstElement * element,
|
||||||
|
GstContext * context);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -346,15 +348,21 @@ gst_gl_mixer_sink_query (GstCollectPads * pads, GstCollectData * data,
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_QUERY_CONTEXT:
|
||||||
|
{
|
||||||
|
ret = gst_gl_handle_context_query ((GstElement *) mix, query,
|
||||||
|
&mix->display);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_QUERY_CUSTOM:
|
case GST_QUERY_CUSTOM:
|
||||||
{
|
{
|
||||||
/* mix is a sink in terms of gl chain, so we are sharing the gldisplay that
|
/* mix is a sink in terms of gl chain, so we are sharing the gldisplay that
|
||||||
* comes from src pad with every display of the sink pads */
|
* comes from src pad with every display of the sink pads */
|
||||||
GstStructure *structure = gst_query_writable_structure (query);
|
GstStructure *structure = gst_query_writable_structure (query);
|
||||||
|
|
||||||
if (gst_structure_has_name (structure, "gstgldisplay")) {
|
if (gst_structure_has_name (structure, "gstglcontext")) {
|
||||||
gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER,
|
gst_structure_set (structure, "gstglcontext", G_TYPE_POINTER,
|
||||||
mix->display, NULL);
|
mix->context, NULL);
|
||||||
} else {
|
} else {
|
||||||
ret = gst_collect_pads_query_default (pads, data, query, FALSE);
|
ret = gst_collect_pads_query_default (pads, data, query, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -513,6 +521,7 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_mixer_request_new_pad);
|
GST_DEBUG_FUNCPTR (gst_gl_mixer_request_new_pad);
|
||||||
element_class->release_pad = GST_DEBUG_FUNCPTR (gst_gl_mixer_release_pad);
|
element_class->release_pad = GST_DEBUG_FUNCPTR (gst_gl_mixer_release_pad);
|
||||||
element_class->change_state = GST_DEBUG_FUNCPTR (gst_gl_mixer_change_state);
|
element_class->change_state = GST_DEBUG_FUNCPTR (gst_gl_mixer_change_state);
|
||||||
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_gl_mixer_set_context);
|
||||||
|
|
||||||
/* Register the pad class */
|
/* Register the pad class */
|
||||||
g_type_class_ref (GST_TYPE_GL_MIXER_PAD);
|
g_type_class_ref (GST_TYPE_GL_MIXER_PAD);
|
||||||
|
@ -845,6 +854,14 @@ gst_gl_mixer_read_qos (GstGLMixer * mix, gdouble * proportion,
|
||||||
GST_OBJECT_UNLOCK (mix);
|
GST_OBJECT_UNLOCK (mix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_mixer_set_context (GstElement * element, GstContext * context)
|
||||||
|
{
|
||||||
|
GstGLMixer *mix = GST_GL_MIXER (element);
|
||||||
|
|
||||||
|
gst_gl_handle_set_context (element, context, &mix->display);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_mixer_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
gst_gl_mixer_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||||
{
|
{
|
||||||
|
@ -852,6 +869,12 @@ gst_gl_mixer_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_CONTEXT:
|
||||||
|
{
|
||||||
|
res = gst_gl_handle_context_query ((GstElement *) mix, query,
|
||||||
|
&mix->display);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_QUERY_POSITION:
|
case GST_QUERY_POSITION:
|
||||||
{
|
{
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
|
@ -918,27 +941,29 @@ gst_gl_mixer_activate (GstGLMixer * mix, gboolean activate)
|
||||||
{
|
{
|
||||||
if (activate) {
|
if (activate) {
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
GstQuery *display_query;
|
GstQuery *context_query;
|
||||||
const GValue *id_value;
|
const GValue *id_value;
|
||||||
|
|
||||||
structure = gst_structure_new_empty ("gstgldisplay");
|
if (!gst_gl_ensure_display (mix, &mix->display)) {
|
||||||
display_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
return FALSE;
|
||||||
|
|
||||||
if (!gst_pad_peer_query (mix->srcpad, display_query)) {
|
|
||||||
GST_WARNING
|
|
||||||
("Could not query GstGLDisplay from downstream (peer query failed)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id_value = gst_structure_get_value (structure, "gstgldisplay");
|
structure = gst_structure_new_empty ("gstglcontext");
|
||||||
|
context_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||||
|
|
||||||
|
if (!gst_pad_peer_query (mix->srcpad, context_query)) {
|
||||||
|
GST_WARNING
|
||||||
|
("Could not query GstGLContext from downstream (peer query failed)");
|
||||||
|
}
|
||||||
|
|
||||||
|
id_value = gst_structure_get_value (structure, "gstglcontext");
|
||||||
if (G_VALUE_HOLDS_POINTER (id_value)) {
|
if (G_VALUE_HOLDS_POINTER (id_value)) {
|
||||||
mix->display =
|
mix->context =
|
||||||
gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
gst_object_ref (GST_GL_CONTEXT (g_value_get_pointer (id_value)));
|
||||||
mix->context = gst_gl_display_get_context (mix->display);
|
|
||||||
} else {
|
} else {
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
GST_INFO ("Creating GstGLDisplay");
|
GST_INFO ("Creating GstGLDisplay");
|
||||||
mix->display = gst_gl_display_new ();
|
|
||||||
mix->context = gst_gl_context_new (mix->display);
|
mix->context = gst_gl_context_new (mix->display);
|
||||||
gst_gl_display_set_context (mix->display, mix->context);
|
gst_gl_display_set_context (mix->display, mix->context);
|
||||||
|
|
||||||
|
|
|
@ -365,3 +365,227 @@ gst_gl_context_del_shader (GstGLContext * context, GstGLShader * shader)
|
||||||
{
|
{
|
||||||
gst_object_unref (shader);
|
gst_object_unref (shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_display_found (GstElement * element, GstGLDisplay * display)
|
||||||
|
{
|
||||||
|
if (display) {
|
||||||
|
GST_INFO_OBJECT (element, "already have a display (%p)", display);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
context_pad_query (const GValue * item, GValue * value, gpointer user_data)
|
||||||
|
{
|
||||||
|
GstPad *pad = g_value_get_object (item);
|
||||||
|
GstQuery *query = user_data;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
res = gst_pad_peer_query (pad, query);
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
g_value_set_boolean (value, TRUE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "context pad peer query failed");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
run_context_query (GstElement * element, GstQuery * query,
|
||||||
|
GstPadDirection direction)
|
||||||
|
{
|
||||||
|
GstIterator *it;
|
||||||
|
GstIteratorFoldFunction func = context_pad_query;
|
||||||
|
GValue res = { 0 };
|
||||||
|
|
||||||
|
g_value_init (&res, G_TYPE_BOOLEAN);
|
||||||
|
g_value_set_boolean (&res, FALSE);
|
||||||
|
|
||||||
|
/* Ask neighbor */
|
||||||
|
if (direction == GST_PAD_SRC)
|
||||||
|
it = gst_element_iterate_src_pads (element);
|
||||||
|
else
|
||||||
|
it = gst_element_iterate_sink_pads (element);
|
||||||
|
|
||||||
|
while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
|
||||||
|
gst_iterator_resync (it);
|
||||||
|
|
||||||
|
gst_iterator_free (it);
|
||||||
|
|
||||||
|
return g_value_get_boolean (&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_display_context_prepare (GstElement * element,
|
||||||
|
GstGLDisplay ** display_ptr)
|
||||||
|
{
|
||||||
|
GstContext *ctxt;
|
||||||
|
GstQuery *query;
|
||||||
|
|
||||||
|
if (!GST_CAT_CONTEXT)
|
||||||
|
GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
|
||||||
|
|
||||||
|
/* 2a) Query downstream with GST_QUERY_CONTEXT for the context and
|
||||||
|
* check if downstream already has a context of the specific type
|
||||||
|
* 2b) Query upstream as above.
|
||||||
|
*/
|
||||||
|
ctxt = NULL;
|
||||||
|
query = gst_query_new_context (GST_GL_DISPLAY_CONTEXT_TYPE);
|
||||||
|
if (run_context_query (element, query, GST_PAD_SRC)) {
|
||||||
|
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||||
|
"found context (%p) in downstream query", ctxt);
|
||||||
|
gst_query_parse_context (query, &ctxt);
|
||||||
|
} else if (run_context_query (element, query, GST_PAD_SINK)) {
|
||||||
|
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||||
|
"found context (%p) in upstream query", ctxt);
|
||||||
|
gst_query_parse_context (query, &ctxt);
|
||||||
|
} else {
|
||||||
|
/* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
|
||||||
|
* the required context type and afterwards check if a
|
||||||
|
* usable context was set now as in 1). The message could
|
||||||
|
* be handled by the parent bins of the element and the
|
||||||
|
* application.
|
||||||
|
*/
|
||||||
|
GstMessage *msg;
|
||||||
|
|
||||||
|
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||||
|
"posting need context message");
|
||||||
|
msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
|
||||||
|
GST_GL_DISPLAY_CONTEXT_TYPE);
|
||||||
|
gst_element_post_message (element, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whomever responds to the need-context message performs a
|
||||||
|
* GstElement::set_context() with the required context in which the element
|
||||||
|
* is required to update the display_ptr or call gst_gl_handle_set_context().
|
||||||
|
*/
|
||||||
|
if (ctxt) {
|
||||||
|
if (gst_context_has_context_type (ctxt, GST_GL_DISPLAY_CONTEXT_TYPE)) {
|
||||||
|
gst_context_get_gl_display (ctxt, display_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_query_unref (query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_gl_display_context_propagate (GstElement * element, GstGLDisplay * display)
|
||||||
|
{
|
||||||
|
GstContext *context;
|
||||||
|
GstMessage *msg;
|
||||||
|
|
||||||
|
if (!display) {
|
||||||
|
GST_ERROR_OBJECT (element, "Could not get GL display connection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
|
||||||
|
gst_context_set_gl_display (context, display);
|
||||||
|
|
||||||
|
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||||
|
"posting have context (%p) message with display (%p)", context, display);
|
||||||
|
msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (element), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_gl_ensure_display (gpointer element, GstGLDisplay ** display_ptr)
|
||||||
|
{
|
||||||
|
GstGLDisplay *display;
|
||||||
|
|
||||||
|
g_return_val_if_fail (element != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (display_ptr != NULL, FALSE);
|
||||||
|
|
||||||
|
/* 1) Check if the element already has a context of the specific
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
display = *display_ptr;
|
||||||
|
if (gst_gl_display_found (element, display))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
gst_gl_display_context_prepare (element, display_ptr);
|
||||||
|
|
||||||
|
/* Neighbour found and it updated the display */
|
||||||
|
if (gst_gl_display_found (element, *display_ptr))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* If no neighboor, or application not interested, use system default */
|
||||||
|
display = gst_gl_display_new ();
|
||||||
|
|
||||||
|
*display_ptr = display;
|
||||||
|
|
||||||
|
gst_gl_display_context_propagate (element, display);
|
||||||
|
|
||||||
|
return display != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_gl_handle_set_context (GstElement * element, GstContext * context,
|
||||||
|
GstGLDisplay ** display)
|
||||||
|
{
|
||||||
|
GstGLDisplay *replacement = NULL;
|
||||||
|
const gchar *context_type;
|
||||||
|
|
||||||
|
g_return_val_if_fail (display, FALSE);
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
context_type = gst_context_get_context_type (context);
|
||||||
|
|
||||||
|
if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
|
||||||
|
if (!gst_context_get_gl_display (context, &replacement)) {
|
||||||
|
GST_WARNING_OBJECT (element, "Failed to get display from context");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replacement)
|
||||||
|
gst_object_replace ((GstObject **) display, (GstObject *) replacement);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_gl_handle_context_query (GstElement * element, GstQuery * query,
|
||||||
|
GstGLDisplay ** display)
|
||||||
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
const gchar *context_type;
|
||||||
|
GstContext *context, *old_context;
|
||||||
|
|
||||||
|
g_return_val_if_fail (element != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (query != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
|
|
||||||
|
gst_query_parse_context_type (query, &context_type);
|
||||||
|
|
||||||
|
if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
|
||||||
|
|
||||||
|
gst_query_parse_context (query, &old_context);
|
||||||
|
|
||||||
|
if (old_context)
|
||||||
|
context = gst_context_copy (old_context);
|
||||||
|
else
|
||||||
|
context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
|
||||||
|
|
||||||
|
gst_context_set_gl_display (context, *display);
|
||||||
|
gst_query_set_context (query, context);
|
||||||
|
gst_context_unref (context);
|
||||||
|
|
||||||
|
res = *display != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -102,4 +102,10 @@ gboolean gst_gl_context_check_framebuffer_status (GstGLContext * context);
|
||||||
void gst_gl_context_set_error (GstGLContext * context, const char * format, ...);
|
void gst_gl_context_set_error (GstGLContext * context, const char * format, ...);
|
||||||
gchar *gst_gl_context_get_error (void);
|
gchar *gst_gl_context_get_error (void);
|
||||||
|
|
||||||
|
gboolean gst_gl_ensure_display (gpointer element, GstGLDisplay **display_ptr);
|
||||||
|
gboolean gst_gl_handle_set_context (GstElement * element, GstContext * context,
|
||||||
|
GstGLDisplay ** display);
|
||||||
|
gboolean gst_gl_handle_context_query (GstElement * element, GstQuery * query,
|
||||||
|
GstGLDisplay ** display);
|
||||||
|
|
||||||
#endif /* __GST_GL_UTILS_H__ */
|
#endif /* __GST_GL_UTILS_H__ */
|
||||||
|
|
Loading…
Reference in a new issue