summaryrefslogtreecommitdiffstats
path: root/gst/rtpmanager
diff options
context:
space:
mode:
authorStig Sandnes <stig.sandnes@tandberg.com>2009-09-08 13:18:29 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2009-09-08 13:18:29 +0200
commit8f3299c5474530d0a0b353160816d5b841b5d7cb (patch)
treec4c04a8d22302c193cf0ef25466a02c17cfec667 /gst/rtpmanager
parente08e610db0d5e9f7e4d5d5c42b026b2853b1321d (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/rtpmanager')
-rw-r--r--gst/rtpmanager/gstrtpbin.c36
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);