void gst_vulkan_global_context_query (GstElement * element, const gchar * context_type) { GstQuery *query; GstMessage *msg; if ((query = gst_vulkan_local_context_query (element, context_type, TRUE))) { gst_query_unref (query); return; } /* 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. */ GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "posting need context message"); msg = gst_message_new_need_context (GST_OBJECT_CAST (element), 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_vulkan_handle_set_context(). */ }
static gboolean gst_wayland_sink_find_display (GstWaylandSink * sink) { GstQuery *query; GstMessage *msg; GstContext *context = NULL; GError *error = NULL; gboolean ret = TRUE; g_mutex_lock (&sink->display_lock); if (!sink->display) { /* first query upstream for the needed display handle */ query = gst_query_new_context (GST_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE); if (gst_pad_peer_query (GST_VIDEO_SINK_PAD (sink), query)) { gst_query_parse_context (query, &context); gst_wayland_sink_set_display_from_context (sink, context); } gst_query_unref (query); if (G_LIKELY (!sink->display)) { /* now ask the application to set the display handle */ msg = gst_message_new_need_context (GST_OBJECT_CAST (sink), GST_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE); g_mutex_unlock (&sink->display_lock); gst_element_post_message (GST_ELEMENT_CAST (sink), msg); /* at this point we expect gst_wayland_sink_set_context * to get called and fill sink->display */ g_mutex_lock (&sink->display_lock); if (!sink->display) { /* if the application didn't set a display, let's create it ourselves */ GST_OBJECT_LOCK (sink); sink->display = gst_wl_display_new (sink->display_name, &error); GST_OBJECT_UNLOCK (sink); if (error) { GST_ELEMENT_WARNING (sink, RESOURCE, OPEN_READ_WRITE, ("Could not initialise Wayland output"), ("Failed to create GstWlDisplay: '%s'", error->message)); g_error_free (error); ret = FALSE; } else { /* inform the world about the new display */ context = gst_wayland_display_handle_context_new (sink->display->display); msg = gst_message_new_have_context (GST_OBJECT_CAST (sink), context); gst_element_post_message (GST_ELEMENT_CAST (sink), msg); } } } } g_mutex_unlock (&sink->display_lock); return ret; }
static GstStateChangeReturn gst_context_element_change_state (GstElement * element, GstStateChange transition) { GstContextElement *celement = (GstContextElement *) element; if (transition == GST_STATE_CHANGE_NULL_TO_READY) { GstContext *context; GstMessage *msg; gboolean have_foobar = celement->have_foobar; if (celement->set_before_ready && !have_foobar) return GST_STATE_CHANGE_FAILURE; else if (celement->set_before_ready) return GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state (element, transition); if (celement->set_from_need_context && have_foobar) return GST_STATE_CHANGE_FAILURE; if (!have_foobar) { /* Here we would first query downstream for a context but we have no pads */ msg = gst_message_new_need_context (GST_OBJECT (element), "foobar"); gst_element_post_message (element, msg); have_foobar = celement->have_foobar; } if (celement->set_from_need_context && !have_foobar) return GST_STATE_CHANGE_FAILURE; else if (celement->set_from_need_context) return GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state (element, transition); if (celement->create_self && have_foobar) return GST_STATE_CHANGE_FAILURE; if (!have_foobar) { context = gst_context_new ("foobar", FALSE); gst_element_set_context (element, context); msg = gst_message_new_have_context (GST_OBJECT (element), gst_context_ref (context)); gst_element_post_message (element, msg); gst_context_unref (context); } return GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state (element, transition); } return GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state (element, transition); }
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); }
static void _gst_context_query (GstElement * element, const gchar * display_type) { GstQuery *query; GstContext *ctxt; _init_context_debug (); /* 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. */ query = gst_query_new_context (display_type); if (gst_gl_run_query (element, query, GST_PAD_SRC)) { gst_query_parse_context (query, &ctxt); GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "found context (%p) in downstream query", ctxt); gst_element_set_context (element, ctxt); } else if (gst_gl_run_query (element, query, GST_PAD_SINK)) { gst_query_parse_context (query, &ctxt); GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "found context (%p) in upstream query", ctxt); gst_element_set_context (element, 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), display_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(). */ gst_query_unref (query); }
static void _gst_context_query (GstElement * element, const gchar * context_type) { GstQuery *query; GstMessage *msg; _init_context_debug (); /* 2) Query downstream with GST_QUERY_CONTEXT for the context and check if downstream already has a context of the specific type */ /* 3) Query upstream with GST_QUERY_CONTEXT for the context and check if upstream already has a context of the specific type */ query = gst_query_new_context (context_type); if (_gst_context_get_from_query (element, query, GST_PAD_SRC)) goto found; if (_gst_context_get_from_query (element, query, GST_PAD_SINK)) goto found; /* 4) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required context types and afterwards check if an usable context was set now as in 1). The message could be handled by the parent bins of the element and the application. */ GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "posting `need-context' message"); msg = gst_message_new_need_context (GST_OBJECT_CAST (element), 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 */ found: gst_query_unref (query); }
gboolean gst_egl_adaptation_init_egl_display (GstEglAdaptationContext * ctx) { GstMessage *msg; EGLDisplay display; GST_DEBUG_OBJECT (ctx->element, "Enter EGL initial configuration"); if (!platform_wrapper_init ()) { GST_ERROR_OBJECT (ctx->element, "Couldn't init EGL platform wrapper"); goto HANDLE_ERROR; } msg = gst_message_new_need_context (GST_OBJECT_CAST (ctx->element), GST_EGL_DISPLAY_CONTEXT_TYPE); gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg); GST_OBJECT_LOCK (ctx->element); if (!ctx->set_display) { GstContext *context; GST_OBJECT_UNLOCK (ctx->element); display = eglGetDisplay (EGL_DEFAULT_DISPLAY); if (display == EGL_NO_DISPLAY) { GST_ERROR_OBJECT (ctx->element, "Could not get EGL display connection"); goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */ } ctx->display = gst_egl_display_new (display, (GDestroyNotify) eglTerminate); context = gst_context_new_egl_display (ctx->display, FALSE); msg = gst_message_new_have_context (GST_OBJECT (ctx->element), context); gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg); } if (!eglInitialize (gst_egl_display_get (ctx->display), &ctx->eglglesctx->egl_major, &ctx->eglglesctx->egl_minor)) { got_egl_error ("eglInitialize"); GST_ERROR_OBJECT (ctx->element, "Could not init EGL display connection"); goto HANDLE_EGL_ERROR; } /* Check against required EGL version * XXX: Need to review the version requirement in terms of the needed API */ if (ctx->eglglesctx->egl_major < GST_EGLGLESSINK_EGL_MIN_VERSION) { GST_ERROR_OBJECT (ctx->element, "EGL v%d needed, but you only have v%d.%d", GST_EGLGLESSINK_EGL_MIN_VERSION, ctx->eglglesctx->egl_major, ctx->eglglesctx->egl_minor); goto HANDLE_ERROR; } GST_INFO_OBJECT (ctx->element, "System reports supported EGL version v%d.%d", ctx->eglglesctx->egl_major, ctx->eglglesctx->egl_minor); eglBindAPI (EGL_OPENGL_ES_API); return TRUE; /* Errors */ HANDLE_EGL_ERROR: GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", eglGetError ()); HANDLE_ERROR: GST_ERROR_OBJECT (ctx->element, "Couldn't setup window/surface from handle"); return FALSE; }