examples/qml: fix some leaks in the multisink example
authorMatthew Waters <matthew@centricular.com>
Wed, 21 Feb 2024 08:11:59 +0000 (19:11 +1100)
committerTim-Philipp Müller <tim@centricular.com>
Thu, 22 Feb 2024 10:26:39 +0000 (10:26 +0000)
A GstPad was being leaked and possibly the qmlglsink element depending
on if Qt runs the scenegraph thread again when destroying the example
video item.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6160>

subprojects/gst-plugins-good/tests/examples/qt/qmlsink-multisink/videoitem/videoitem.cpp

index 9d2bb09af194e2efc9b6e2a5c075808351956bbb..3c8d22e6f43a1577a62f00d74dc0fed488cdc8d5 100644 (file)
@@ -230,6 +230,7 @@ void VideoItem::componentComplete()
         if (window) {
             GstElement *glsink = gst_element_factory_make("qmlglsink", nullptr);
             Q_ASSERT(glsink);
+            gst_object_ref_sink (glsink);
 
             GstState current {GST_STATE_NULL}, pending {GST_STATE_NULL}, target {GST_STATE_NULL};
             auto status = gst_element_get_state(_priv->pipeline, &current, &pending, 0);
@@ -253,13 +254,12 @@ void VideoItem::componentComplete()
 
             gst_element_set_state(_priv->pipeline, GST_STATE_NULL);
 
-            glsink = GST_ELEMENT(gst_object_ref(glsink));
-
             window->scheduleRenderJob(new RenderJob([=] {
                 g_object_set(glsink, "widget", videoItem, nullptr);
                 _priv->renderPad = gst_element_get_static_pad(glsink, "sink");
                 g_object_set(_priv->sink, "sink", glsink, nullptr);
                 gst_element_set_state(_priv->pipeline, target);
+                gst_object_unref (glsink);
                 }),
                 QQuickWindow::BeforeSynchronizingStage);
         }
@@ -272,20 +272,16 @@ void VideoItem::componentComplete()
 void VideoItem::releaseResources()
 {
     GstElement *sink { nullptr };
-    QQuickWindow *win { window() };
 
     gst_element_set_state(_priv->pipeline, GST_STATE_NULL);
     g_object_get(_priv->sink, "sink", &sink, nullptr);
 
-    if (_priv->renderPad) {
+    if (sink && _priv->renderPad) {
         g_object_set(sink, "widget", nullptr, nullptr);
-        _priv->renderPad = nullptr;
     }
 
-    connect(this, &VideoItem::destroyed, this, [sink, win] {
-        auto job = new RenderJob(std::bind(&gst_object_unref, sink));
-        win->scheduleRenderJob(job, QQuickWindow::AfterSwapStage);
-    });
+    gst_clear_object (&_priv->renderPad);
+    gst_clear_object (&sink);
 }
 
 void VideoItem::updateRect()
@@ -318,6 +314,7 @@ void VideoItem::updateRect()
         setRect(QRect(span / 2, 0, winWidth - span, winHeight));
     }
     setResolution(QSize(picWidth, picHeight));
+    gst_clear_caps(&caps);
 }
 
 VideoItem::State VideoItem::state() const