diff options
author | Stig Sandnes <stig.sandnes@tandberg.com> | 2009-09-08 13:18:29 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-09-08 13:18:29 +0200 |
commit | 8f3299c5474530d0a0b353160816d5b841b5d7cb (patch) | |
tree | c4c04a8d22302c193cf0ef25466a02c17cfec667 /gst | |
parent | e08e610db0d5e9f7e4d5d5c42b026b2853b1321d (diff) |
rtpbin: make free_session() remove stream references
When receiving a sync-packet, all sessions with the same cname will be compared
and synced together. In this process, there could still be references to a
session that has been shut down in the meanwhile.
This patch makes sure that these references are removed when shutting down a
session, so that the syncing can be done safely.
Fixes #594283
Diffstat (limited to 'gst')
-rw-r--r-- | gst/rtpmanager/gstrtpbin.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index d5448147..0c751192 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -259,6 +259,7 @@ static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 }; static GstCaps *pt_map_requested (GstElement * element, guint pt, GstRtpBinSession * session); +static void free_client (GstRtpBinClient * client, GstRtpBin * bin); static void free_stream (GstRtpBinStream * stream); /* Manages the RTP stream for one SSRC. @@ -575,6 +576,8 @@ no_demux: static void free_session (GstRtpBinSession * sess, GstRtpBin * bin) { + GSList *client_walk; + GST_DEBUG_OBJECT (bin, "freeing session %p", sess); gst_element_set_locked_state (sess->demux, TRUE); @@ -609,6 +612,39 @@ free_session (GstRtpBinSession * sess, GstRtpBin * bin) gst_bin_remove (GST_BIN_CAST (bin), sess->session); gst_bin_remove (GST_BIN_CAST (bin), sess->demux); + /* remove any references in bin->clients to the streams in sess->streams */ + client_walk = bin->clients; + while (client_walk) { + GSList *client_node = client_walk; + GstRtpBinClient *client = (GstRtpBinClient *) client_node->data; + GSList *stream_walk = client->streams; + + while (stream_walk) { + GSList *stream_node = stream_walk; + GstRtpBinStream *stream = (GstRtpBinStream *) stream_node->data; + GSList *inner_walk; + + stream_walk = g_slist_next (stream_walk); + + for (inner_walk = sess->streams; inner_walk; + inner_walk = g_slist_next (inner_walk)) { + if ((GstRtpBinStream *) inner_walk->data == stream) { + client->streams = g_slist_delete_link (client->streams, stream_node); + --client->nstreams; + break; + } + } + } + client_walk = g_slist_next (client_walk); + + g_assert ((client->streams && client->nstreams > 0) || (!client->streams + && client->streams == 0)); + if (client->nstreams == 0) { + free_client (client, bin); + bin->clients = g_slist_delete_link (bin->clients, client_node); + } + } + g_slist_foreach (sess->streams, (GFunc) free_stream, NULL); g_slist_free (sess->streams); |