mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-02 05:28:48 +00:00
glimagesink: Avoid assert in query.
The sink_query just uses context, other_context and display to query info. But all these objects can be changed or distroyed in state_change() func and other places. This patch is not very perfect. The condition race still exists in other places in this element. All the functions directly access these objects without protection. Most of them are executed when the data is pushing and draw context/window have already been established, so they should not have problems. But the sink_query and propose_allocation functions are the query -like functions and executed in query context, which can be called in any state of the element. So it can cause some crash issues because of destroyed context object. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/922>
This commit is contained in:
parent
f7ea6d9b64
commit
6ffddd27e5
1 changed files with 99 additions and 32 deletions
|
@ -965,6 +965,39 @@ gst_glimage_sink_mouse_scroll_event_cb (GstGLWindow * window,
|
||||||
posx, posy, delta_x, delta_y);
|
posx, posy, delta_x, delta_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_set_context (GstGLImageSink * gl_sink, GstGLContext * context)
|
||||||
|
{
|
||||||
|
GST_GLIMAGE_SINK_LOCK (gl_sink);
|
||||||
|
if (gl_sink->context)
|
||||||
|
gst_object_unref (gl_sink->context);
|
||||||
|
|
||||||
|
gl_sink->context = context;
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_set_other_context (GstGLImageSink * gl_sink, GstGLContext * other_context)
|
||||||
|
{
|
||||||
|
GST_GLIMAGE_SINK_LOCK (gl_sink);
|
||||||
|
if (gl_sink->other_context)
|
||||||
|
gst_object_unref (gl_sink->other_context);
|
||||||
|
|
||||||
|
gl_sink->other_context = other_context;
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_set_display (GstGLImageSink * gl_sink, GstGLDisplay * display)
|
||||||
|
{
|
||||||
|
GST_GLIMAGE_SINK_LOCK (gl_sink);
|
||||||
|
if (gl_sink->display)
|
||||||
|
gst_object_unref (gl_sink->display);
|
||||||
|
|
||||||
|
gl_sink->display = display;
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_ensure_gl_setup (GstGLImageSink * gl_sink)
|
_ensure_gl_setup (GstGLImageSink * gl_sink)
|
||||||
{
|
{
|
||||||
|
@ -976,12 +1009,10 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
|
||||||
GST_OBJECT_LOCK (gl_sink->display);
|
GST_OBJECT_LOCK (gl_sink->display);
|
||||||
do {
|
do {
|
||||||
GstGLContext *other_context = NULL;
|
GstGLContext *other_context = NULL;
|
||||||
|
GstGLContext *context = NULL;
|
||||||
GstGLWindow *window = NULL;
|
GstGLWindow *window = NULL;
|
||||||
|
|
||||||
if (gl_sink->context) {
|
_set_context (gl_sink, NULL);
|
||||||
gst_object_unref (gl_sink->context);
|
|
||||||
gl_sink->context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (gl_sink,
|
GST_DEBUG_OBJECT (gl_sink,
|
||||||
"No current context, creating one for %" GST_PTR_FORMAT,
|
"No current context, creating one for %" GST_PTR_FORMAT,
|
||||||
|
@ -995,12 +1026,14 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_gl_display_create_context (gl_sink->display,
|
if (!gst_gl_display_create_context (gl_sink->display,
|
||||||
other_context, &gl_sink->context, &error)) {
|
other_context, &context, &error)) {
|
||||||
if (other_context)
|
if (other_context)
|
||||||
gst_object_unref (other_context);
|
gst_object_unref (other_context);
|
||||||
GST_OBJECT_UNLOCK (gl_sink->display);
|
GST_OBJECT_UNLOCK (gl_sink->display);
|
||||||
goto context_error;
|
goto context_error;
|
||||||
}
|
}
|
||||||
|
_set_context (gl_sink, context);
|
||||||
|
context = NULL;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (gl_sink,
|
GST_DEBUG_OBJECT (gl_sink,
|
||||||
"created context %" GST_PTR_FORMAT " from other context %"
|
"created context %" GST_PTR_FORMAT " from other context %"
|
||||||
|
@ -1062,10 +1095,7 @@ context_error:
|
||||||
GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message),
|
GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message),
|
||||||
(NULL));
|
(NULL));
|
||||||
|
|
||||||
if (gl_sink->context) {
|
_set_context (gl_sink, NULL);
|
||||||
gst_object_unref (gl_sink->context);
|
|
||||||
gl_sink->context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
@ -1134,10 +1164,30 @@ gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query)
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_CONTEXT:
|
case GST_QUERY_CONTEXT:
|
||||||
{
|
{
|
||||||
if (gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
|
GstGLContext *context = NULL;
|
||||||
glimage_sink->display, glimage_sink->context,
|
GstGLContext *other_context = NULL;
|
||||||
glimage_sink->other_context))
|
GstGLDisplay *display = NULL;
|
||||||
return TRUE;
|
|
||||||
|
GST_GLIMAGE_SINK_LOCK (bsink);
|
||||||
|
if (glimage_sink->context)
|
||||||
|
context = gst_object_ref (glimage_sink->context);
|
||||||
|
if (glimage_sink->other_context)
|
||||||
|
other_context = gst_object_ref (glimage_sink->other_context);
|
||||||
|
if (glimage_sink->display)
|
||||||
|
display = gst_object_ref (glimage_sink->display);
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (bsink);
|
||||||
|
|
||||||
|
res = gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
|
||||||
|
display, context, other_context);
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
gst_object_unref (context);
|
||||||
|
if (other_context)
|
||||||
|
gst_object_unref (other_context);
|
||||||
|
if (display)
|
||||||
|
gst_object_unref (display);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_QUERY_DRAIN:
|
case GST_QUERY_DRAIN:
|
||||||
|
@ -1176,9 +1226,12 @@ static void
|
||||||
gst_glimage_sink_set_context (GstElement * element, GstContext * context)
|
gst_glimage_sink_set_context (GstElement * element, GstContext * context)
|
||||||
{
|
{
|
||||||
GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (element);
|
GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (element);
|
||||||
|
GstGLContext *other_context = NULL;
|
||||||
|
GstGLDisplay *display = NULL;
|
||||||
|
|
||||||
gst_gl_handle_set_context (element, context, &gl_sink->display,
|
gst_gl_handle_set_context (element, context, &display, &other_context);
|
||||||
&gl_sink->other_context);
|
_set_other_context (gl_sink, other_context);
|
||||||
|
_set_display (gl_sink, display);
|
||||||
|
|
||||||
if (gl_sink->display)
|
if (gl_sink->display)
|
||||||
gst_gl_display_filter_gl_api (gl_sink->display, SUPPORTED_GL_APIS);
|
gst_gl_display_filter_gl_api (gl_sink->display, SUPPORTED_GL_APIS);
|
||||||
|
@ -1191,6 +1244,7 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
GstGLImageSink *glimage_sink;
|
GstGLImageSink *glimage_sink;
|
||||||
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
||||||
|
GstGLContext *context;
|
||||||
|
|
||||||
GST_DEBUG ("changing state: %s => %s",
|
GST_DEBUG ("changing state: %s => %s",
|
||||||
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
|
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
|
||||||
|
@ -1277,8 +1331,14 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
glimage_sink->overlay_compositor = NULL;
|
glimage_sink->overlay_compositor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glimage_sink->context) {
|
context = NULL;
|
||||||
GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);
|
GST_GLIMAGE_SINK_LOCK (glimage_sink);
|
||||||
|
if (glimage_sink->context)
|
||||||
|
context = gst_object_ref (glimage_sink->context);
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
GstGLWindow *window = gst_gl_context_get_window (context);
|
||||||
|
|
||||||
gst_gl_window_send_message (window,
|
gst_gl_window_send_message (window,
|
||||||
GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink);
|
GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink);
|
||||||
|
@ -1299,21 +1359,15 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
glimage_sink->mouse_scroll_sig_id = 0;
|
glimage_sink->mouse_scroll_sig_id = 0;
|
||||||
|
|
||||||
gst_object_unref (window);
|
gst_object_unref (window);
|
||||||
gst_object_unref (glimage_sink->context);
|
_set_context (glimage_sink, NULL);
|
||||||
glimage_sink->context = NULL;
|
|
||||||
|
gst_object_unref (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
glimage_sink->window_id = 0;
|
glimage_sink->window_id = 0;
|
||||||
|
|
||||||
if (glimage_sink->other_context) {
|
_set_other_context (glimage_sink, NULL);
|
||||||
gst_object_unref (glimage_sink->other_context);
|
_set_display (glimage_sink, NULL);
|
||||||
glimage_sink->other_context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glimage_sink->display) {
|
|
||||||
gst_object_unref (glimage_sink->display);
|
|
||||||
glimage_sink->display = NULL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1939,10 +1993,19 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
guint size;
|
guint size;
|
||||||
gboolean need_pool;
|
gboolean need_pool;
|
||||||
GstStructure *allocation_meta = NULL;
|
GstStructure *allocation_meta = NULL;
|
||||||
|
GstGLContext *context = NULL;
|
||||||
|
|
||||||
if (!_ensure_gl_setup (glimage_sink))
|
if (!_ensure_gl_setup (glimage_sink))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
GST_GLIMAGE_SINK_LOCK (glimage_sink);
|
||||||
|
if (glimage_sink->context)
|
||||||
|
context = gst_object_ref (glimage_sink->context);
|
||||||
|
GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
gst_query_parse_allocation (query, &caps, &need_pool);
|
gst_query_parse_allocation (query, &caps, &need_pool);
|
||||||
|
|
||||||
if (caps == NULL)
|
if (caps == NULL)
|
||||||
|
@ -1957,7 +2020,7 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
if (need_pool) {
|
if (need_pool) {
|
||||||
GST_DEBUG_OBJECT (glimage_sink, "create new pool");
|
GST_DEBUG_OBJECT (glimage_sink, "create new pool");
|
||||||
|
|
||||||
pool = gst_gl_buffer_pool_new (glimage_sink->context);
|
pool = gst_gl_buffer_pool_new (context);
|
||||||
config = gst_buffer_pool_get_config (pool);
|
config = gst_buffer_pool_get_config (pool);
|
||||||
gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
|
gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
|
||||||
gst_buffer_pool_config_add_option (config,
|
gst_buffer_pool_config_add_option (config,
|
||||||
|
@ -1974,7 +2037,7 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
if (pool)
|
if (pool)
|
||||||
g_object_unref (pool);
|
g_object_unref (pool);
|
||||||
|
|
||||||
if (glimage_sink->context->gl_vtable->FenceSync)
|
if (context->gl_vtable->FenceSync)
|
||||||
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
|
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
|
||||||
|
|
||||||
if (glimage_sink->window_width != 0 && glimage_sink->window_height != 0) {
|
if (glimage_sink->window_width != 0 && glimage_sink->window_height != 0) {
|
||||||
|
@ -1994,21 +2057,25 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
if (allocation_meta)
|
if (allocation_meta)
|
||||||
gst_structure_free (allocation_meta);
|
gst_structure_free (allocation_meta);
|
||||||
|
|
||||||
|
gst_object_unref (context);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_caps:
|
no_caps:
|
||||||
{
|
{
|
||||||
|
gst_object_unref (context);
|
||||||
GST_WARNING_OBJECT (bsink, "no caps specified");
|
GST_WARNING_OBJECT (bsink, "no caps specified");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
invalid_caps:
|
invalid_caps:
|
||||||
{
|
{
|
||||||
|
gst_object_unref (context);
|
||||||
GST_WARNING_OBJECT (bsink, "invalid caps specified");
|
GST_WARNING_OBJECT (bsink, "invalid caps specified");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
config_failed:
|
config_failed:
|
||||||
{
|
{
|
||||||
|
gst_object_unref (context);
|
||||||
GST_WARNING_OBJECT (bsink, "failed setting config");
|
GST_WARNING_OBJECT (bsink, "failed setting config");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2274,10 +2341,10 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_GLIMAGE_SINK (gl_sink));
|
g_return_if_fail (GST_IS_GLIMAGE_SINK (gl_sink));
|
||||||
|
|
||||||
gl = gl_sink->context->gl_vtable;
|
|
||||||
|
|
||||||
GST_GLIMAGE_SINK_LOCK (gl_sink);
|
GST_GLIMAGE_SINK_LOCK (gl_sink);
|
||||||
|
|
||||||
|
gl = gl_sink->context->gl_vtable;
|
||||||
|
|
||||||
/* check if texture is ready for being drawn */
|
/* check if texture is ready for being drawn */
|
||||||
if (!gl_sink->redisplay_texture) {
|
if (!gl_sink->redisplay_texture) {
|
||||||
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
|
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
|
||||||
|
|
Loading…
Reference in a new issue