d3d11videosink: disconnect signals before releasing the window

It might happen that the key event arrives when the d3d11videosink
is stopping. In case of GstD3D11WindowWin32 it can raise a
navigation event even when the sink is already freed, because the
window object's refcount may reach 0 in the window thread. In
other words sometimes the GstD3D11WindowWin32 lives few ms more
then the GstD3D11VideoSink, because it's freed asynchronously.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6476>
This commit is contained in:
Alexander Slobodeniuk 2024-03-28 21:59:02 +01:00 committed by GStreamer Marge Bot
parent 941793c7e4
commit 7b69d1758f

View file

@ -958,6 +958,17 @@ gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
return TRUE;
}
static void
gst_d3d11_video_sink_release_window (GstD3D11VideoSink * self)
{
if (self->window == NULL)
return;
g_signal_handlers_disconnect_by_data (self->window, self);
gst_d3d11_window_unprepare (self->window);
gst_clear_object (&self->window);
}
static GstFlowReturn
gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
{
@ -1087,8 +1098,7 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
if (ret == GST_FLOW_FLUSHING) {
GstD3D11CSLockGuard lk (&self->lock);
GST_WARNING_OBJECT (self, "Couldn't prepare window but we are flushing");
gst_d3d11_window_unprepare (self->window);
gst_clear_object (&self->window);
gst_d3d11_video_sink_release_window (self);
gst_object_unref (window);
return GST_FLOW_FLUSHING;
@ -1330,10 +1340,8 @@ gst_d3d11_video_sink_stop (GstBaseSink * sink)
gst_clear_object (&self->pool);
}
if (self->window)
gst_d3d11_window_unprepare (self->window);
gst_d3d11_video_sink_release_window (self);
gst_clear_object (&self->window);
gst_clear_object (&self->device);
g_clear_pointer (&self->title, g_free);