gl/dispmanx: fix deadlock triggered by set_render_rectangle
When the gstglimagesink is started with the option `glimagesink render-rectangle="<0,0,1920,1080>"`, the pipeline reaches a deadlock. The reason the deadlock occurs is that the `gst_gl_window_set_render_rectangle` takes locks on the window, in addition it calls `window_class->set_render_rectangle(...)` which executes the `_on_resize` function. Since the `_on_resize` function also takes locks on the window the deadlock is achieved. By scheduling the adjustment of the render rectangle through an async message for `gst_gl_window_dispmanx_set_render_rectangle`, the actual resize happens in another context and therefore doesn't suffers from the lock taken in `gst_gl_window_set_render_rectangle`. This solution follows the same approach as gl/wayland. The problem was introduced by b887db1. For the full discussion check #849. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1030>
This commit is contained in:
parent
278b10dd2e
commit
57029ba098
@ -286,18 +286,53 @@ window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height,
|
|||||||
window_egl->native.height = height;
|
window_egl->native.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SetRenderRectangle
|
||||||
|
{
|
||||||
|
GstGLWindowDispmanxEGL *window_egl;
|
||||||
|
GstVideoRectangle rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_free_set_render_rectangle (struct SetRenderRectangle *render)
|
||||||
|
{
|
||||||
|
if (render) {
|
||||||
|
if (render->window_egl)
|
||||||
|
gst_object_unref (render->window_egl);
|
||||||
|
g_free (render);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_set_render_rectangle (gpointer data)
|
||||||
|
{
|
||||||
|
struct SetRenderRectangle *render = data;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (render->window_egl, "setting render rectangle %i,%i+%ix%i",
|
||||||
|
render->rect.x, render->rect.y, render->rect.w, render->rect.h);
|
||||||
|
|
||||||
|
window_resize (render->window_egl, render->rect.w, render->rect.h, TRUE);
|
||||||
|
|
||||||
|
render->window_egl->render_rect = render->rect;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_window_dispmanx_egl_set_render_rectangle (GstGLWindow * window,
|
gst_gl_window_dispmanx_egl_set_render_rectangle (GstGLWindow * window,
|
||||||
gint x, gint y, gint width, gint height)
|
gint x, gint y, gint width, gint height)
|
||||||
{
|
{
|
||||||
GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
|
GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
|
||||||
window_egl->render_rect.x = x;
|
struct SetRenderRectangle *render;
|
||||||
window_egl->render_rect.y = y;
|
|
||||||
window_egl->render_rect.w = width;
|
render = g_new0 (struct SetRenderRectangle, 1);
|
||||||
window_egl->render_rect.h = height;
|
render->window_egl = gst_object_ref (window_egl);
|
||||||
|
render->rect.x = x;
|
||||||
|
render->rect.y = y;
|
||||||
|
render->rect.w = width;
|
||||||
|
render->rect.h = height;
|
||||||
|
|
||||||
|
gst_gl_window_send_message_async (window,
|
||||||
|
(GstGLWindowCB) _set_render_rectangle, render,
|
||||||
|
(GDestroyNotify) _free_set_render_rectangle);
|
||||||
|
|
||||||
window_resize (window_egl, window_egl->render_rect.w,
|
|
||||||
window_egl->render_rect.h, TRUE);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user