mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +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
f230ec14ba
commit
79260ff8f9
8 changed files with 390 additions and 49 deletions
|
@ -28,11 +28,13 @@
|
|||
#include "gl.h"
|
||||
#include "gstgldisplay.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_context);
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
||||
#define GST_CAT_DEFAULT gst_gl_display_debug
|
||||
|
||||
#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,
|
||||
DEBUG_INIT);
|
||||
|
@ -66,6 +68,8 @@ gst_gl_display_init (GstGLDisplay * display)
|
|||
|
||||
display->gl_api = GST_GL_API_NONE;
|
||||
|
||||
GST_TRACE ("init %p", display);
|
||||
|
||||
gst_gl_memory_init ();
|
||||
}
|
||||
|
||||
|
@ -79,6 +83,8 @@ gst_gl_display_finalize (GObject * object)
|
|||
display->context = NULL;
|
||||
}
|
||||
|
||||
GST_TRACE ("finalize %p", 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;
|
||||
|
||||
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);
|
||||
gst_structure_set (s, GST_GL_DISPLAY_CONTEXT_TYPE, GST_TYPE_GL_DISPLAY,
|
||||
display, NULL);
|
||||
|
@ -151,8 +162,17 @@ gboolean
|
|||
gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display)
|
||||
{
|
||||
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);
|
||||
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_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,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_gl_filter_set_context (GstElement * element,
|
||||
GstContext * context);
|
||||
static gboolean gst_gl_filter_query (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstQuery * query);
|
||||
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_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_param_spec_object ("other-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
|
||||
gst_gl_filter_query (GstBaseTransform * trans, GstPadDirection direction,
|
||||
GstQuery * query)
|
||||
|
@ -186,13 +198,19 @@ gst_gl_filter_query (GstBaseTransform * trans, GstPadDirection direction,
|
|||
filter = GST_GL_FILTER (trans);
|
||||
|
||||
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:
|
||||
{
|
||||
GstStructure *structure = gst_query_writable_structure (query);
|
||||
if (direction == GST_PAD_SINK &&
|
||||
gst_structure_has_name (structure, "gstgldisplay")) {
|
||||
gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER,
|
||||
filter->display, NULL);
|
||||
gst_structure_has_name (structure, "gstglcontext")) {
|
||||
gst_structure_set (structure, "gstglcontext", G_TYPE_POINTER,
|
||||
filter->context, NULL);
|
||||
res = TRUE;
|
||||
} else
|
||||
res =
|
||||
|
@ -243,6 +261,10 @@ gst_gl_filter_reset (GstGLFilter * filter)
|
|||
if (filter->other_context)
|
||||
gst_object_unref (filter->other_context);
|
||||
filter->other_context = NULL;
|
||||
|
||||
if (filter->context)
|
||||
gst_object_unref (filter->context);
|
||||
filter->context = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -251,28 +273,29 @@ gst_gl_filter_start (GstBaseTransform * bt)
|
|||
GstGLFilter *filter = GST_GL_FILTER (bt);
|
||||
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
||||
GstStructure *structure;
|
||||
GstQuery *display_query;
|
||||
GstQuery *context_query;
|
||||
const GValue *id_value;
|
||||
|
||||
structure = gst_structure_new_empty ("gstgldisplay");
|
||||
display_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||
if (!gst_gl_ensure_display (filter, &filter->display))
|
||||
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
|
||||
("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)) {
|
||||
/* at least one gl element is after in our gl chain */
|
||||
filter->display =
|
||||
gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
||||
filter->context = gst_gl_display_get_context (filter->display);
|
||||
filter->context =
|
||||
gst_object_ref (GST_GL_CONTEXT (g_value_get_pointer (id_value)));
|
||||
} else {
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
filter->display = gst_gl_display_new ();
|
||||
GST_INFO ("Creating GstGLContext");
|
||||
filter->context = gst_gl_context_new (filter->display);
|
||||
|
||||
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)
|
||||
filter_class->onStart (filter);
|
||||
|
||||
|
@ -1067,6 +1092,9 @@ gst_gl_filter_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
filter = GST_GL_FILTER (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);
|
||||
|
||||
if (filter_class->filter)
|
||||
|
|
|
@ -65,7 +65,6 @@ struct _GstGLFilter
|
|||
GstBufferPool *pool;
|
||||
|
||||
GstGLDisplay *display;
|
||||
GstGLContext *context;
|
||||
|
||||
GstVideoInfo in_info;
|
||||
GstVideoInfo out_info;
|
||||
|
@ -81,6 +80,7 @@ struct _GstGLFilter
|
|||
|
||||
GstGLShader *default_shader;
|
||||
|
||||
GstGLContext *context;
|
||||
GstGLContext *other_context;
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ static gboolean gst_gl_mixer_sink_event (GstCollectPads * pads,
|
|||
GstCollectData * cdata, GstEvent * event, GstGLMixer * mix);
|
||||
static gboolean gst_gl_mixer_src_setcaps (GstPad * pad, GstGLMixer * mix,
|
||||
GstCaps * caps);
|
||||
static void gst_gl_mixer_set_context (GstElement * element,
|
||||
GstContext * context);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -346,15 +348,21 @@ gst_gl_mixer_sink_query (GstCollectPads * pads, GstCollectData * data,
|
|||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CONTEXT:
|
||||
{
|
||||
ret = gst_gl_handle_context_query ((GstElement *) mix, query,
|
||||
&mix->display);
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CUSTOM:
|
||||
{
|
||||
/* 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 */
|
||||
GstStructure *structure = gst_query_writable_structure (query);
|
||||
|
||||
if (gst_structure_has_name (structure, "gstgldisplay")) {
|
||||
gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER,
|
||||
mix->display, NULL);
|
||||
if (gst_structure_has_name (structure, "gstglcontext")) {
|
||||
gst_structure_set (structure, "gstglcontext", G_TYPE_POINTER,
|
||||
mix->context, NULL);
|
||||
} else {
|
||||
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);
|
||||
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->set_context = GST_DEBUG_FUNCPTR (gst_gl_mixer_set_context);
|
||||
|
||||
/* Register the pad class */
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
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:
|
||||
{
|
||||
GstFormat format;
|
||||
|
@ -918,27 +941,29 @@ gst_gl_mixer_activate (GstGLMixer * mix, gboolean activate)
|
|||
{
|
||||
if (activate) {
|
||||
GstStructure *structure;
|
||||
GstQuery *display_query;
|
||||
GstQuery *context_query;
|
||||
const GValue *id_value;
|
||||
|
||||
structure = gst_structure_new_empty ("gstgldisplay");
|
||||
display_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||
|
||||
if (!gst_pad_peer_query (mix->srcpad, display_query)) {
|
||||
GST_WARNING
|
||||
("Could not query GstGLDisplay from downstream (peer query failed)");
|
||||
if (!gst_gl_ensure_display (mix, &mix->display)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)) {
|
||||
mix->display =
|
||||
gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
||||
mix->context = gst_gl_display_get_context (mix->display);
|
||||
mix->context =
|
||||
gst_object_ref (GST_GL_CONTEXT (g_value_get_pointer (id_value)));
|
||||
} else {
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
mix->display = gst_gl_display_new ();
|
||||
mix->context = gst_gl_context_new (mix->display);
|
||||
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);
|
||||
}
|
||||
|
||||
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, ...);
|
||||
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__ */
|
||||
|
|
|
@ -121,6 +121,8 @@ static void gst_glimage_sink_get_property (GObject * object, guint prop_id,
|
|||
static gboolean gst_glimage_sink_stop (GstBaseSink * bsink);
|
||||
|
||||
static gboolean gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query);
|
||||
static void gst_glimage_sink_set_context (GstElement * element,
|
||||
GstContext * context);
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_glimage_sink_change_state (GstElement * element, GstStateChange transition);
|
||||
|
@ -245,7 +247,7 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass)
|
|||
gobject_class->finalize = gst_glimage_sink_finalize;
|
||||
|
||||
gstelement_class->change_state = gst_glimage_sink_change_state;
|
||||
|
||||
gstelement_class->set_context = gst_glimage_sink_set_context;
|
||||
gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_glimage_sink_query);
|
||||
gstbasesink_class->set_caps = gst_glimage_sink_set_caps;
|
||||
gstbasesink_class->get_times = gst_glimage_sink_get_times;
|
||||
|
@ -373,12 +375,18 @@ gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query)
|
|||
gboolean res = FALSE;
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
{
|
||||
return gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
|
||||
&glimage_sink->display);
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CUSTOM:
|
||||
{
|
||||
GstStructure *structure = gst_query_writable_structure (query);
|
||||
if (gst_structure_has_name (structure, "gstgldisplay")) {
|
||||
gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER,
|
||||
glimage_sink->display, NULL);
|
||||
if (gst_structure_has_name (structure, "gstglcontext")) {
|
||||
gst_structure_set (structure, "gstglcontext", G_TYPE_POINTER,
|
||||
glimage_sink->context, NULL);
|
||||
res = TRUE;
|
||||
} else
|
||||
res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
|
||||
|
@ -420,6 +428,14 @@ gst_glimage_sink_stop (GstBaseSink * bsink)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_glimage_sink_set_context (GstElement * element, GstContext * context)
|
||||
{
|
||||
GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (element);
|
||||
|
||||
gst_gl_handle_set_context (element, context, &gl_sink->display);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
|
@ -439,8 +455,9 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
|
|||
GstGLWindow *window;
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
glimage_sink->display = gst_gl_display_new ();
|
||||
if (!gst_gl_ensure_display (glimage_sink, &glimage_sink->display))
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
|
||||
glimage_sink->context = gst_gl_context_new (glimage_sink->display);
|
||||
gst_gl_display_set_context (glimage_sink->display,
|
||||
glimage_sink->context);
|
||||
|
@ -691,6 +708,9 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
if (!gst_gl_ensure_display (bsink, &glimage_sink->display))
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
|
||||
if (!gst_video_frame_map (&frame, &glimage_sink->info, buf,
|
||||
GST_MAP_READ | GST_MAP_GL)) {
|
||||
GST_WARNING ("Failed to map memory");
|
||||
|
|
|
@ -78,6 +78,8 @@ static gboolean gst_gl_test_src_is_seekable (GstBaseSrc * psrc);
|
|||
static gboolean gst_gl_test_src_do_seek (GstBaseSrc * bsrc,
|
||||
GstSegment * segment);
|
||||
static gboolean gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query);
|
||||
static void gst_gl_test_src_set_context (GstElement * element,
|
||||
GstContext * context);
|
||||
|
||||
static void gst_gl_test_src_get_times (GstBaseSrc * basesrc,
|
||||
GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
|
||||
|
@ -160,6 +162,8 @@ gst_gl_test_src_class_init (GstGLTestSrcClass * klass)
|
|||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
gst_caps_from_string (GST_GL_DOWNLOAD_VIDEO_CAPS)));
|
||||
|
||||
element_class->set_context = gst_gl_test_src_set_context;
|
||||
|
||||
gstbasesrc_class->set_caps = gst_gl_test_src_setcaps;
|
||||
gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable;
|
||||
gstbasesrc_class->do_seek = gst_gl_test_src_do_seek;
|
||||
|
@ -336,16 +340,29 @@ context_error:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_test_src_set_context (GstElement * element, GstContext * context)
|
||||
{
|
||||
GstGLTestSrc *src = GST_GL_TEST_SRC (element);
|
||||
|
||||
gst_gl_handle_set_context (element, context, &src->display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query)
|
||||
{
|
||||
gboolean res;
|
||||
gboolean res = FALSE;
|
||||
GstGLTestSrc *src;
|
||||
|
||||
src = GST_GL_TEST_SRC (bsrc);
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
{
|
||||
res = gst_gl_handle_context_query ((GstElement *) src, query,
|
||||
&src->display);
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CONVERT:
|
||||
{
|
||||
GstFormat src_fmt, dest_fmt;
|
||||
|
@ -544,28 +561,29 @@ gst_gl_test_src_start (GstBaseSrc * basesrc)
|
|||
{
|
||||
GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc);
|
||||
GstStructure *structure;
|
||||
GstQuery *display_query;
|
||||
GstQuery *context_query;
|
||||
const GValue *id_value;
|
||||
|
||||
structure = gst_structure_new_empty ("gstgldisplay");
|
||||
display_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||
if (!gst_gl_ensure_display (src, &src->display))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_pad_peer_query (basesrc->srcpad, display_query)) {
|
||||
structure = gst_structure_new_empty ("gstglcontext");
|
||||
context_query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
|
||||
|
||||
if (!gst_pad_peer_query (basesrc->srcpad, context_query)) {
|
||||
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)) {
|
||||
/* at least one gl element is after in our gl chain */
|
||||
src->display =
|
||||
gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
||||
src->context = gst_gl_display_get_context (src->display);
|
||||
src->context =
|
||||
gst_object_ref (GST_GL_CONTEXT (g_value_get_pointer (id_value)));
|
||||
} else {
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
src->display = gst_gl_display_new ();
|
||||
src->context = gst_gl_context_new (src->display);
|
||||
gst_gl_display_set_context (src->display, src->context);
|
||||
|
||||
|
|
Loading…
Reference in a new issue