summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHe Junyan <junyan.he@intel.com>2020-11-06 14:05:39 +0800
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2020-12-05 22:04:21 +0000
commit86058c831c30243d1e1905f7eac0ddf7906cdebb (patch)
tree057f1742e3cef2b17d081eb688f0ce946b5775e7
parent02e04b0cf6dfdd6863f1f94406ac5a7c55e90f9e (diff)
downloadgstreamer-plugins-base-86058c831c30243d1e1905f7eac0ddf7906cdebb.tar.gz
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/962>
-rw-r--r--ext/gl/gstglimagesink.c131
1 files changed, 99 insertions, 32 deletions
diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
index b403b4c52..2c023ce7c 100644
--- a/ext/gl/gstglimagesink.c
+++ b/ext/gl/gstglimagesink.c
@@ -965,6 +965,39 @@ gst_glimage_sink_mouse_scroll_event_cb (GstGLWindow * window,
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
_ensure_gl_setup (GstGLImageSink * gl_sink)
{
@@ -976,12 +1009,10 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
GST_OBJECT_LOCK (gl_sink->display);
do {
GstGLContext *other_context = NULL;
+ GstGLContext *context = NULL;
GstGLWindow *window = NULL;
- if (gl_sink->context) {
- gst_object_unref (gl_sink->context);
- gl_sink->context = NULL;
- }
+ _set_context (gl_sink, NULL);
GST_DEBUG_OBJECT (gl_sink,
"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,
- other_context, &gl_sink->context, &error)) {
+ other_context, &context, &error)) {
if (other_context)
gst_object_unref (other_context);
GST_OBJECT_UNLOCK (gl_sink->display);
goto context_error;
}
+ _set_context (gl_sink, context);
+ context = NULL;
GST_DEBUG_OBJECT (gl_sink,
"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),
(NULL));
- if (gl_sink->context) {
- gst_object_unref (gl_sink->context);
- gl_sink->context = NULL;
- }
+ _set_context (gl_sink, NULL);
g_clear_error (&error);
@@ -1134,10 +1164,30 @@ gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query)
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONTEXT:
{
- if (gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
- glimage_sink->display, glimage_sink->context,
- glimage_sink->other_context))
- return TRUE;
+ GstGLContext *context = NULL;
+ GstGLContext *other_context = NULL;
+ GstGLDisplay *display = NULL;
+
+ 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;
}
case GST_QUERY_DRAIN:
@@ -1176,9 +1226,12 @@ static void
gst_glimage_sink_set_context (GstElement * element, GstContext * context)
{
GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (element);
+ GstGLContext *other_context = NULL;
+ GstGLDisplay *display = NULL;
- gst_gl_handle_set_context (element, context, &gl_sink->display,
- &gl_sink->other_context);
+ gst_gl_handle_set_context (element, context, &display, &other_context);
+ _set_other_context (gl_sink, other_context);
+ _set_display (gl_sink, display);
if (gl_sink->display)
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;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstGLContext *context;
GST_DEBUG ("changing state: %s => %s",
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;
}
- if (glimage_sink->context) {
- GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);
+ context = NULL;
+ 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_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;
gst_object_unref (window);
- gst_object_unref (glimage_sink->context);
- glimage_sink->context = NULL;
+ _set_context (glimage_sink, NULL);
+
+ gst_object_unref (context);
}
glimage_sink->window_id = 0;
- if (glimage_sink->other_context) {
- gst_object_unref (glimage_sink->other_context);
- glimage_sink->other_context = NULL;
- }
-
- if (glimage_sink->display) {
- gst_object_unref (glimage_sink->display);
- glimage_sink->display = NULL;
- }
+ _set_other_context (glimage_sink, NULL);
+ _set_display (glimage_sink, NULL);
break;
default:
break;
@@ -1939,10 +1993,19 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
guint size;
gboolean need_pool;
GstStructure *allocation_meta = NULL;
+ GstGLContext *context = NULL;
if (!_ensure_gl_setup (glimage_sink))
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);
if (caps == NULL)
@@ -1957,7 +2020,7 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
if (need_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);
gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
gst_buffer_pool_config_add_option (config,
@@ -1974,7 +2037,7 @@ gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
if (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);
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)
gst_structure_free (allocation_meta);
+ gst_object_unref (context);
return TRUE;
/* ERRORS */
no_caps:
{
+ gst_object_unref (context);
GST_WARNING_OBJECT (bsink, "no caps specified");
return FALSE;
}
invalid_caps:
{
+ gst_object_unref (context);
GST_WARNING_OBJECT (bsink, "invalid caps specified");
return FALSE;
}
config_failed:
{
+ gst_object_unref (context);
GST_WARNING_OBJECT (bsink, "failed setting config");
return FALSE;
}
@@ -2274,10 +2341,10 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
g_return_if_fail (GST_IS_GLIMAGE_SINK (gl_sink));
- gl = gl_sink->context->gl_vtable;
-
GST_GLIMAGE_SINK_LOCK (gl_sink);
+ gl = gl_sink->context->gl_vtable;
+
/* check if texture is ready for being drawn */
if (!gl_sink->redisplay_texture) {
GST_GLIMAGE_SINK_UNLOCK (gl_sink);