From a5d5dd2ab43dd8c7e4b8098bde3dee2e0320aa3f Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Sat, 17 Jun 2023 07:59:34 -0400 Subject: [PATCH] ges: basebin: Handle removed tracks Cleaning up the pads and elements linked to that track. Part-of: --- .../plugins/ges/gesbasebin.c | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-editing-services/plugins/ges/gesbasebin.c b/subprojects/gst-editing-services/plugins/ges/gesbasebin.c index 6d7912cff5..98277f396e 100644 --- a/subprojects/gst-editing-services/plugins/ges/gesbasebin.c +++ b/subprojects/gst-editing-services/plugins/ges/gesbasebin.c @@ -35,10 +35,19 @@ static GstStaticPadTemplate audio_src_template = GST_PAD_SOMETIMES, GST_STATIC_CAPS ("audio/x-raw(ANY);")); +typedef struct +{ + GstPad *ghost_pad; + GstElement *queue; +} TrackInfo; + typedef struct { GESTimeline *timeline; GstFlowCombiner *flow_combiner; + + GHashTable *tracks; + gulong track_removed_sigid; } GESBaseBinPrivate; enum @@ -61,10 +70,23 @@ ges_base_bin_dispose (GObject * object) GESBaseBin *self = GES_BASE_BIN (object); GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + GST_OBJECT_LOCK (self); + if (priv->tracks) { + g_clear_pointer (&priv->tracks, g_hash_table_unref); + } + if (priv->timeline) { + g_signal_handler_disconnect (priv->timeline, priv->track_removed_sigid); + priv->track_removed_sigid = 0; + GST_OBJECT_UNLOCK (self); + gst_bin_remove (GST_BIN (self), GST_ELEMENT (priv->timeline)); + + GST_OBJECT_LOCK (self); gst_clear_object (&priv->timeline); } + + GST_OBJECT_UNLOCK (self); } static void @@ -152,6 +174,8 @@ ges_base_bin_init (GESBaseBin * self) ges_init (); priv->flow_combiner = gst_flow_combiner_new (); + priv->tracks = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) g_free); } static gboolean @@ -210,6 +234,33 @@ ges_base_bin_src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) return result; } +static void +ges_base_bin_track_removed_cb (GESTimeline * timeline, GESTrack * track, + GESBaseBin * self) +{ + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + GST_OBJECT_LOCK (self); + TrackInfo *info = g_hash_table_lookup (priv->tracks, track); + if (!info) { + GST_OBJECT_UNLOCK (self); + + return; + } + GstPad *ghost = gst_object_ref (info->ghost_pad); + GstElement *queue = gst_object_ref (info->queue); + + g_hash_table_remove (priv->tracks, track); + GST_OBJECT_UNLOCK (self); + + gst_element_remove_pad (GST_ELEMENT (self), ghost); + gst_element_set_state (queue, GST_STATE_NULL); + gst_bin_remove (GST_BIN (self), queue); + + gst_object_unref (queue); + gst_object_unref (ghost); +} + gboolean ges_base_bin_set_timeline (GESBaseBin * self, GESTimeline * timeline) @@ -228,6 +279,9 @@ ges_base_bin_set_timeline (GESBaseBin * self, GESTimeline * timeline) } priv->timeline = gst_object_ref (timeline); + /* FIXME Handle track-added */ + priv->track_removed_sigid = g_signal_connect (timeline, "track-removed", + G_CALLBACK (ges_base_bin_track_removed_cb), self); GST_INFO_OBJECT (sbin, "Setting timeline: %" GST_PTR_FORMAT, timeline); gst_element_set_locked_state (GST_ELEMENT (timeline), TRUE); if (!gst_bin_add (sbin, GST_ELEMENT (timeline))) { @@ -287,12 +341,23 @@ ges_base_bin_set_timeline (GESBaseBin * self, GESTimeline * timeline) gst_pad_set_active (gpad, TRUE); gst_element_add_pad (GST_ELEMENT (sbin), gpad); + TrackInfo *info = g_new0 (TrackInfo, 1); + info->queue = queue; + info->ghost_pad = gpad; + + GST_OBJECT_LOCK (self); + g_hash_table_insert (priv->tracks, track, info); + GST_OBJECT_UNLOCK (self); + proxy_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad))); gst_flow_combiner_add_pad (priv->flow_combiner, proxy_pad); gst_pad_set_chain_function (proxy_pad, ges_base_bin_src_chain); gst_pad_set_event_function (proxy_pad, ges_base_bin_event); gst_object_unref (proxy_pad); - GST_DEBUG_OBJECT (sbin, "Adding pad: %" GST_PTR_FORMAT, gpad); + + GST_DEBUG_OBJECT (sbin, + "Added pad: %" GST_PTR_FORMAT " for track %" GST_PTR_FORMAT, gpad, + track); } gst_element_set_locked_state (GST_ELEMENT (timeline), FALSE);