mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
rtpbin: rework cleanup of streams
Move the work of cleaning up the client streams in the free_stream function. This allows us to properly clean up the client streams when we remove an RTP stream as well. Based on patch by Sujay <sdatar@cisco.com> Fixes https://bugzilla.gnome.org/show_bug.cgi?id=660156
This commit is contained in:
parent
3a5d17e852
commit
978cc9f538
1 changed files with 39 additions and 47 deletions
|
@ -312,7 +312,7 @@ static void remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
|
||||||
static void remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
|
static void remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
|
||||||
static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
|
static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
|
||||||
static void free_client (GstRtpBinClient * client, GstRtpBin * bin);
|
static void free_client (GstRtpBinClient * client, GstRtpBin * bin);
|
||||||
static void free_stream (GstRtpBinStream * stream);
|
static void free_stream (GstRtpBinStream * stream, GstRtpBin * bin);
|
||||||
|
|
||||||
/* Manages the RTP stream for one SSRC.
|
/* Manages the RTP stream for one SSRC.
|
||||||
*
|
*
|
||||||
|
@ -545,6 +545,11 @@ ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad,
|
||||||
GstRtpBinSession * session)
|
GstRtpBinSession * session)
|
||||||
{
|
{
|
||||||
GstRtpBinStream *stream = NULL;
|
GstRtpBinStream *stream = NULL;
|
||||||
|
GstRtpBin *rtpbin;
|
||||||
|
|
||||||
|
rtpbin = session->bin;
|
||||||
|
|
||||||
|
GST_RTP_BIN_LOCK (rtpbin);
|
||||||
|
|
||||||
GST_RTP_SESSION_LOCK (session);
|
GST_RTP_SESSION_LOCK (session);
|
||||||
if ((stream = find_stream_by_ssrc (session, ssrc)))
|
if ((stream = find_stream_by_ssrc (session, ssrc)))
|
||||||
|
@ -552,7 +557,9 @@ ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad,
|
||||||
GST_RTP_SESSION_UNLOCK (session);
|
GST_RTP_SESSION_UNLOCK (session);
|
||||||
|
|
||||||
if (stream)
|
if (stream)
|
||||||
free_stream (stream);
|
free_stream (stream, rtpbin);
|
||||||
|
|
||||||
|
GST_RTP_BIN_UNLOCK (rtpbin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a session with the given id. Must be called with RTP_BIN_LOCK */
|
/* create a session with the given id. Must be called with RTP_BIN_LOCK */
|
||||||
|
@ -638,8 +645,6 @@ no_demux:
|
||||||
static void
|
static void
|
||||||
free_session (GstRtpBinSession * sess, GstRtpBin * bin)
|
free_session (GstRtpBinSession * sess, GstRtpBin * bin)
|
||||||
{
|
{
|
||||||
GSList *client_walk;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (bin, "freeing session %p", sess);
|
GST_DEBUG_OBJECT (bin, "freeing session %p", sess);
|
||||||
|
|
||||||
gst_element_set_locked_state (sess->demux, TRUE);
|
gst_element_set_locked_state (sess->demux, TRUE);
|
||||||
|
@ -656,40 +661,7 @@ free_session (GstRtpBinSession * sess, GstRtpBin * bin)
|
||||||
gst_bin_remove (GST_BIN_CAST (bin), sess->session);
|
gst_bin_remove (GST_BIN_CAST (bin), sess->session);
|
||||||
gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
|
gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
|
||||||
|
|
||||||
/* remove any references in bin->clients to the streams in sess->streams */
|
g_slist_foreach (sess->streams, (GFunc) free_stream, bin);
|
||||||
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);
|
g_slist_free (sess->streams);
|
||||||
|
|
||||||
g_mutex_clear (&sess->lock);
|
g_mutex_clear (&sess->lock);
|
||||||
|
@ -1479,12 +1451,13 @@ no_demux:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called with RTP_BIN_LOCK */
|
||||||
static void
|
static void
|
||||||
free_stream (GstRtpBinStream * stream)
|
free_stream (GstRtpBinStream * stream, GstRtpBin * bin)
|
||||||
{
|
{
|
||||||
GstRtpBinSession *session;
|
GSList *clients, *next_client;
|
||||||
|
|
||||||
session = stream->session;
|
GST_DEBUG_OBJECT (bin, "freeing stream %p", stream);
|
||||||
|
|
||||||
if (stream->demux) {
|
if (stream->demux) {
|
||||||
g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig);
|
g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig);
|
||||||
|
@ -1508,10 +1481,33 @@ free_stream (GstRtpBinStream * stream)
|
||||||
if (stream->demux)
|
if (stream->demux)
|
||||||
g_signal_handler_disconnect (stream->demux, stream->demux_padremoved_sig);
|
g_signal_handler_disconnect (stream->demux, stream->demux_padremoved_sig);
|
||||||
|
|
||||||
gst_bin_remove (GST_BIN_CAST (session->bin), stream->buffer);
|
gst_bin_remove (GST_BIN_CAST (bin), stream->buffer);
|
||||||
if (stream->demux)
|
if (stream->demux)
|
||||||
gst_bin_remove (GST_BIN_CAST (session->bin), stream->demux);
|
gst_bin_remove (GST_BIN_CAST (bin), stream->demux);
|
||||||
|
|
||||||
|
for (clients = bin->clients; clients; clients = next_client) {
|
||||||
|
GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
|
||||||
|
GSList *streams, *next_stream;
|
||||||
|
|
||||||
|
next_client = g_slist_next (clients);
|
||||||
|
|
||||||
|
for (streams = client->streams; streams; streams = next_stream) {
|
||||||
|
GstRtpBinStream *ostream = (GstRtpBinStream *) streams->data;
|
||||||
|
|
||||||
|
next_stream = g_slist_next (streams);
|
||||||
|
|
||||||
|
if (ostream == stream) {
|
||||||
|
client->streams = g_slist_delete_link (client->streams, streams);
|
||||||
|
/* If this was the last stream belonging to this client,
|
||||||
|
* clean up the client. */
|
||||||
|
if (--client->nstreams == 0) {
|
||||||
|
bin->clients = g_slist_delete_link (bin->clients, clients);
|
||||||
|
free_client (client, bin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
g_free (stream);
|
g_free (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1920,10 +1916,6 @@ gst_rtp_bin_dispose (GObject * object)
|
||||||
g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin);
|
g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin);
|
||||||
g_slist_free (rtpbin->sessions);
|
g_slist_free (rtpbin->sessions);
|
||||||
rtpbin->sessions = NULL;
|
rtpbin->sessions = NULL;
|
||||||
GST_DEBUG_OBJECT (object, "freeing clients");
|
|
||||||
g_slist_foreach (rtpbin->clients, (GFunc) free_client, rtpbin);
|
|
||||||
g_slist_free (rtpbin->clients);
|
|
||||||
rtpbin->clients = NULL;
|
|
||||||
GST_RTP_BIN_UNLOCK (rtpbin);
|
GST_RTP_BIN_UNLOCK (rtpbin);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
|
Loading…
Reference in a new issue