ges: basebin: Handle removed tracks

Cleaning up the pads and elements linked to that track.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4882>
This commit is contained in:
Thibault Saunier 2023-06-17 07:59:34 -04:00 committed by GStreamer Marge Bot
parent a8b3e6122f
commit a5d5dd2ab4

View file

@ -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);