From 46139253bcb1ddc32fc8987c194c40d9c622e993 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 5 May 2009 16:48:37 +0200 Subject: rtpssrcdemux: drop unexpected RTCP packets We usually only get SR packets in our chain function but if an invalid packet contains the SR packet after the RR packet, we must not fail but simply ignore the malformed packet. Fixes #581375 --- gst/rtpmanager/gstrtpssrcdemux.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c index 64394c45..b9a279c2 100644 --- a/gst/rtpmanager/gstrtpssrcdemux.c +++ b/gst/rtpmanager/gstrtpssrcdemux.c @@ -483,7 +483,7 @@ gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstBuffer * buf) NULL); break; default: - goto invalid_rtcp; + goto unexpected_rtcp; } GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc); @@ -511,6 +511,12 @@ invalid_rtcp: gst_buffer_unref (buf); return GST_FLOW_ERROR; } +unexpected_rtcp: + { + GST_DEBUG_OBJECT (demux, "dropping unexpected RTCP packet"); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } create_failed: { GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), -- cgit v1.2.1 From ab80a4fa411e85380ee5da3e7f7abc1553053628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 00:16:19 +0200 Subject: rtpbin: Implement releasing of rtcp src pad See #561752 --- gst/rtpmanager/gstrtpbin.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 7d3b9823..4db28f73 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -2338,8 +2338,13 @@ pad_failed: static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (pad)); + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT (rtpbin), pad); + + if (session->send_rtcp_src) { + gst_element_release_request_pad (session->session, session->send_rtcp_src); + session->send_rtcp_src = NULL; + } } /* If the requested name is NULL we should create a name with -- cgit v1.2.1 From b831c9b434046ea7e8c6cc757607c67f7f7656dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 00:34:36 +0200 Subject: rtpbin: Implement release of the recv rtcp pad See #561752 --- gst/rtpmanager/gstrtpbin.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 4db28f73..b4e61ac2 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -2176,8 +2176,18 @@ link_failed: static void remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (pad)); + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); + + if (session->sync_src) { + /* releasing the request pad should also unref the sync pad */ + gst_object_unref (session->sync_src); + session->sync_src = NULL; + } + if (session->recv_rtcp_sink) { + gst_element_release_request_pad (session->session, session->recv_rtcp_sink); + session->recv_rtcp_sink = NULL; + } } /* Create a pad for sending RTP for the session in @name. Must be called with @@ -2339,7 +2349,7 @@ static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT (rtpbin), pad); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); if (session->send_rtcp_src) { gst_element_release_request_pad (session->session, session->send_rtcp_src); -- cgit v1.2.1 From 65d55e6b13c41f3ca6ff5e4e39fbd7ec990e8d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 00:44:51 +0200 Subject: rtpbin: Implement releasing of rtp send pads --- gst/rtpmanager/gstrtpbin.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index b4e61ac2..a1411e10 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -348,6 +348,7 @@ struct _GstRtpBinSession GstPad *sync_src; GstPad *send_rtp_sink; GstPad *send_rtp_src; + GstPad *send_rtp_src_ghost; GstPad *send_rtcp_src; }; @@ -2196,7 +2197,7 @@ remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) static GstPad * create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result, *srcghost; + GstPad *result; gchar *gname; guint sessid; GstRtpBinSession *session; @@ -2240,10 +2241,10 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) klass = GST_ELEMENT_GET_CLASS (rtpbin); gname = g_strdup_printf ("send_rtp_src_%d", sessid); templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d"); - srcghost = + session->send_rtp_src_ghost = gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ); - gst_pad_set_active (srcghost, TRUE); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost); + gst_pad_set_active (session->send_rtp_src_ghost, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost); g_free (gname); return result; @@ -2281,8 +2282,26 @@ no_srcpad: static void remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (pad)); + if (session->send_rtp_src_ghost) { + gst_pad_set_active (session->send_rtp_src_ghost, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), + session->send_rtp_src_ghost); + session->send_rtp_src_ghost = NULL; + } + + if (session->send_rtp_src) { + gst_object_unref (session->send_rtp_src); + session->send_rtp_src = NULL; + } + + if (session->send_rtp_sink) { + gst_element_release_request_pad (GST_ELEMENT_CAST (session->session), + session->send_rtp_sink); + session->send_rtp_sink = NULL; + } + + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); } /* Create a pad for sending RTCP for the session in @name. Must be called with -- cgit v1.2.1 From 4424fd3c93ab2f2b9590a3b0c461c16d01f8a00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 00:51:53 +0200 Subject: rtpbin: Implement relasing of the rtp recv pad --- gst/rtpmanager/gstrtpbin.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index a1411e10..075776ee 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -2081,8 +2081,23 @@ link_failed: static void remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (pad)); + if (session->demux_newpad_sig) { + g_signal_handler_disconnect (session->demux, session->demux_newpad_sig); + session->demux_newpad_sig = 0; + } + + if (session->recv_rtp_src) { + gst_object_unref (session->recv_rtp_src); + session->recv_rtp_src = NULL; + } + + if (session->recv_rtp_sink) { + gst_element_release_request_pad (session->session, session->recv_rtp_sink); + session->recv_rtp_sink = NULL; + } + + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); } /* Create a pad for receiving RTCP for the session in @name. Must be called with -- cgit v1.2.1 From fb59348dbe0dfd5b6cb0596a031e5c437265e85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 01:03:55 +0200 Subject: rtpbin: Free session if request pads are released Free the session when all the request pads are released. Don't mess with the session list in free_session as it is called from a foreach on that list. Set the state of the upstream element to NULL first. See #561752 --- gst/rtpmanager/gstrtpbin.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 075776ee..11cc2dd9 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -554,8 +554,8 @@ free_session (GstRtpBinSession * sess) GST_DEBUG_OBJECT (bin, "freeing session %p", sess); - gst_element_set_state (sess->session, GST_STATE_NULL); gst_element_set_state (sess->demux, GST_STATE_NULL); + gst_element_set_state (sess->session, GST_STATE_NULL); if (sess->recv_rtp_sink != NULL) { gst_element_release_request_pad (sess->session, sess->recv_rtp_sink); @@ -589,8 +589,6 @@ free_session (GstRtpBinSession * sess) g_mutex_free (sess->lock); g_hash_table_destroy (sess->ptmap); - bin->sessions = g_slist_remove (bin->sessions, sess); - g_free (sess); } @@ -2512,6 +2510,13 @@ gst_rtp_bin_release_pad (GstElement * element, GstPad * pad) } else if (session->send_rtcp_src == target) { remove_rtcp (rtpbin, session, pad); } + + /* no more request pads, free the complete session */ + if (session->recv_rtp_sink == NULL && session->recv_rtcp_sink == NULL && + session->send_rtp_sink == NULL && session->send_rtcp_src == NULL) { + rtpbin->sessions = g_slist_remove (rtpbin->sessions, session); + free_session (session); + } GST_RTP_BIN_UNLOCK (rtpbin); gst_object_unref (target); -- cgit v1.2.1 From b3aeee2bf281225495b09216ec3d796e6330c9e1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 01:12:57 +0200 Subject: rtpbin: use the right lock for the sessions Use the right lock when iterating the sessions. --- gst/rtpmanager/gstrtpbin.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 11cc2dd9..9ab50888 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -1555,6 +1555,8 @@ gst_rtp_bin_set_sdes_string (GstRtpBin * bin, GstRTCPSDESType type, if (type < 0 || type > 8) return; + GST_RTP_BIN_LOCK (bin); + GST_OBJECT_LOCK (bin); g_free (bin->sdes[type]); bin->sdes[type] = g_strdup (data); @@ -1563,6 +1565,8 @@ gst_rtp_bin_set_sdes_string (GstRtpBin * bin, GstRTCPSDESType type, for (item = bin->sessions; item; item = g_slist_next (item)) g_object_set (item->data, name, bin->sdes[type], NULL); GST_OBJECT_UNLOCK (bin); + + GST_RTP_BIN_UNLOCK (bin); } static gchar * -- cgit v1.2.1 From 451ca5dbc059b369de56cf1a8906f5bd5dc89943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 01:16:11 +0200 Subject: rtpbin: Keep jb signals handler Keep the signal handlers so they can be disconnected at release time See #561752 --- gst/rtpmanager/gstrtpbin.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 9ab50888..977fd787 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -297,6 +297,9 @@ struct _GstRtpBinStream /* the jitterbuffer of the SSRC */ GstElement *buffer; + gulong buffer_handlesync_sig; + gulong buffer_ptreq_sig; + gulong buffer_ntpstop_sig; /* the PT demuxer of the SSRC */ GstElement *demux; @@ -1096,9 +1099,10 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) session->streams = g_slist_prepend (session->streams, stream); /* provide clock_rate to the jitterbuffer when needed */ - g_signal_connect (buffer, "request-pt-map", + stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map", (GCallback) pt_map_requested, session); - g_signal_connect (buffer, "on-npt-stop", (GCallback) on_npt_stop, stream); + stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop", + (GCallback) on_npt_stop, stream); /* configure latency and packet lost */ g_object_set (buffer, "latency", session->bin->latency, NULL); @@ -1950,7 +1954,7 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad, /* connect to the RTCP sync signal from the jitterbuffer */ GST_DEBUG_OBJECT (rtpbin, "connecting sync signal"); - g_signal_connect (stream->buffer, + stream->buffer_handlesync_sig = g_signal_connect (stream->buffer, "handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream); /* connect to the new-pad signal of the payload demuxer, this will expose the -- cgit v1.2.1 From c5ab83a1cbfb5cae17717a3fe08d9f339181d813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 22 May 2009 01:43:50 +0200 Subject: rtpbin: Implement releasing the streams See #561752 --- gst/rtpmanager/gstrtpbin.c | 74 +++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 21 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 977fd787..7e14a0d9 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -335,6 +335,7 @@ struct _GstRtpBinSession /* the SSRC demuxer */ GstElement *demux; gulong demux_newpad_sig; + gulong demux_padremoved_sig; GMutex *lock; @@ -471,6 +472,45 @@ on_npt_stop (GstElement * jbuf, GstRtpBinStream * stream) stream->session->id, stream->ssrc); } +/* must be called with the SESSION lock */ +static GstRtpBinStream * +find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc) +{ + GSList *walk; + + for (walk = session->streams; walk; walk = g_slist_next (walk)) { + GstRtpBinStream *stream = (GstRtpBinStream *) walk->data; + + if (stream->ssrc == ssrc) + return stream; + } + return NULL; +} + +static void +ssrc_demux_pad_removed (GstElement * element, GstPad * pad, + GstRtpBinSession * session) +{ + guint ssrc; + GstRtpBinStream *stream = NULL; + gchar *name; + gint res; + + name = gst_pad_get_name (pad); + res = sscanf (name, "src_%d", &ssrc); + g_free (name); + + if (res != 1) + return; + + GST_RTP_SESSION_LOCK (session); + if ((stream = find_stream_by_ssrc (session, ssrc))) { + session->streams = g_slist_remove (session->streams, stream); + free_stream (stream); + } + GST_RTP_SESSION_UNLOCK (session); +} + /* create a session with the given id. Must be called with RTP_BIN_LOCK */ static GstRtpBinSession * create_session (GstRtpBin * rtpbin, gint id) @@ -595,22 +635,6 @@ free_session (GstRtpBinSession * sess) g_free (sess); } -#if 0 -static GstRtpBinStream * -find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc) -{ - GSList *walk; - - for (walk = session->streams; walk; walk = g_slist_next (walk)) { - GstRtpBinStream *stream = (GstRtpBinStream *) walk->data; - - if (stream->ssrc == ssrc) - return stream; - } - return NULL; -} -#endif - /* get the payload type caps for the specific payload @pt in @session */ static GstCaps * get_pt_map (GstRtpBinSession * session, guint pt) @@ -1139,14 +1163,18 @@ free_stream (GstRtpBinStream * stream) session = stream->session; - gst_element_set_state (stream->buffer, GST_STATE_NULL); + g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig); + g_signal_handler_disconnect (stream->demux, stream->demux_ptreq_sig); + g_signal_handler_disconnect (stream->buffer, stream->buffer_handlesync_sig); + g_signal_handler_disconnect (stream->buffer, stream->buffer_ptreq_sig); + g_signal_handler_disconnect (stream->buffer, stream->buffer_ntpstop_sig); + gst_element_set_state (stream->demux, GST_STATE_NULL); + gst_element_set_state (stream->buffer, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (session->bin), stream->buffer); gst_bin_remove (GST_BIN_CAST (session->bin), stream->demux); - session->streams = g_slist_remove (session->streams, stream); - g_free (stream); } @@ -2046,6 +2074,8 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) /* connect to the new-ssrc-pad signal of the SSRC demuxer */ session->demux_newpad_sig = g_signal_connect (session->demux, "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session); + session->demux_padremoved_sig = g_signal_connect (session->demux, + "pad-removed", (GCallback) ssrc_demux_pad_removed, session); GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad"); result = @@ -2091,12 +2121,14 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) g_signal_handler_disconnect (session->demux, session->demux_newpad_sig); session->demux_newpad_sig = 0; } - + if (session->demux_padremoved_sig) { + g_signal_handler_disconnect (session->demux, session->demux_padremoved_sig); + session->demux_padremoved_sig = 0; + } if (session->recv_rtp_src) { gst_object_unref (session->recv_rtp_src); session->recv_rtp_src = NULL; } - if (session->recv_rtp_sink) { gst_element_release_request_pad (session->session, session->recv_rtp_sink); session->recv_rtp_sink = NULL; -- cgit v1.2.1 From 58c59d7953e58e262e6eba7fc9906227e68552c6 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 11:59:17 +0200 Subject: rtpbin: unref requests pads after releasing --- gst/rtpmanager/gstrtpbin.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 7e14a0d9..e4892d49 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -2131,6 +2131,7 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) } if (session->recv_rtp_sink) { gst_element_release_request_pad (session->session, session->recv_rtp_sink); + gst_object_unref (session->recv_rtp_sink); session->recv_rtp_sink = NULL; } @@ -2240,6 +2241,7 @@ remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) } if (session->recv_rtcp_sink) { gst_element_release_request_pad (session->session, session->recv_rtcp_sink); + gst_object_unref (session->recv_rtcp_sink); session->recv_rtcp_sink = NULL; } } @@ -2350,6 +2352,7 @@ remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) if (session->send_rtp_sink) { gst_element_release_request_pad (GST_ELEMENT_CAST (session->session), session->send_rtp_sink); + gst_object_unref (session->send_rtp_sink); session->send_rtp_sink = NULL; } @@ -2425,6 +2428,7 @@ remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) if (session->send_rtcp_src) { gst_element_release_request_pad (session->session, session->send_rtcp_src); + gst_object_unref (session->send_rtcp_src); session->send_rtcp_src = NULL; } } -- cgit v1.2.1 From 142840432ba6c9641f134a1599a76f0c60dd7b5f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 12:20:13 +0200 Subject: rtpbin: set target state on new elements Set the state on newly added elements to the state of the parent. Add some debug info and do some cleanups --- gst/rtpmanager/gstrtpbin.c | 57 ++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index e4892d49..5c0948c6 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -518,6 +518,7 @@ create_session (GstRtpBin * rtpbin, gint id) GstRtpBinSession *sess; GstElement *session, *demux; gint i; + GstState target; if (!(session = gst_element_factory_make ("gstrtpsession", NULL))) goto no_session; @@ -566,11 +567,16 @@ create_session (GstRtpBin * rtpbin, gint id) g_signal_connect (sess->session, "on-sender-timeout", (GCallback) on_sender_timeout, sess); - /* FIXME, change state only to what's needed */ gst_bin_add (GST_BIN_CAST (rtpbin), session); - gst_element_set_state (session, GST_STATE_PLAYING); gst_bin_add (GST_BIN_CAST (rtpbin), demux); - gst_element_set_state (demux, GST_STATE_PLAYING); + + GST_OBJECT_LOCK (rtpbin); + target = GST_STATE_TARGET (rtpbin); + GST_OBJECT_UNLOCK (rtpbin); + + /* change state only to what's needed */ + gst_element_set_state (demux, target); + gst_element_set_state (session, target); return sess; @@ -589,12 +595,8 @@ no_demux: } static void -free_session (GstRtpBinSession * sess) +free_session (GstRtpBinSession * sess, GstRtpBin * bin) { - GstRtpBin *bin; - - bin = sess->bin; - GST_DEBUG_OBJECT (bin, "freeing session %p", sess); gst_element_set_state (sess->demux, GST_STATE_NULL); @@ -848,8 +850,9 @@ get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created) } static void -free_client (GstRtpBinClient * client) +free_client (GstRtpBinClient * client, GstRtpBin * bin) { + GST_DEBUG_OBJECT (bin, "freeing client %p", client); g_slist_free (client->streams); g_free (client->cname); g_free (client); @@ -1105,6 +1108,8 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) { GstElement *buffer, *demux; GstRtpBinStream *stream; + GstRtpBin *rtpbin; + GstState target; if (!(buffer = gst_element_factory_make ("gstrtpjitterbuffer", NULL))) goto no_jitterbuffer; @@ -1112,9 +1117,11 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) if (!(demux = gst_element_factory_make ("gstrtpptdemux", NULL))) goto no_demux; + rtpbin = session->bin; + stream = g_new0 (GstRtpBinStream, 1); stream->ssrc = ssrc; - stream->bin = session->bin; + stream->bin = rtpbin; stream->session = session; stream->buffer = buffer; stream->demux = demux; @@ -1129,17 +1136,23 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) (GCallback) on_npt_stop, stream); /* configure latency and packet lost */ - g_object_set (buffer, "latency", session->bin->latency, NULL); - g_object_set (buffer, "do-lost", session->bin->do_lost, NULL); + g_object_set (buffer, "latency", rtpbin->latency, NULL); + g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL); - gst_bin_add (GST_BIN_CAST (session->bin), buffer); - gst_element_set_state (buffer, GST_STATE_PLAYING); - gst_bin_add (GST_BIN_CAST (session->bin), demux); - gst_element_set_state (demux, GST_STATE_PLAYING); + gst_bin_add (GST_BIN_CAST (rtpbin), demux); + gst_bin_add (GST_BIN_CAST (rtpbin), buffer); /* link stuff */ gst_element_link (buffer, demux); + GST_OBJECT_LOCK (rtpbin); + target = GST_STATE_TARGET (rtpbin); + GST_OBJECT_UNLOCK (rtpbin); + + /* from sink to source */ + gst_element_set_state (demux, target); + gst_element_set_state (buffer, target); + return stream; /* ERRORS */ @@ -1512,11 +1525,11 @@ gst_rtp_bin_dispose (GObject * object) rtpbin = GST_RTP_BIN (object); GST_DEBUG_OBJECT (object, "freeing sessions"); - g_slist_foreach (rtpbin->sessions, (GFunc) free_session, NULL); + g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin); g_slist_free (rtpbin->sessions); rtpbin->sessions = NULL; GST_DEBUG_OBJECT (object, "freeing clients"); - g_slist_foreach (rtpbin->clients, (GFunc) free_client, NULL); + g_slist_foreach (rtpbin->clients, (GFunc) free_client, rtpbin); g_slist_free (rtpbin->clients); rtpbin->clients = NULL; @@ -2494,7 +2507,7 @@ gst_rtp_bin_request_new_pad (GstElement * element, pad_name = g_strdup (name); } - GST_DEBUG ("Trying to request a pad with name %s", pad_name); + GST_DEBUG_OBJECT (rtpbin, "Trying to request a pad with name %s", pad_name); /* figure out the template */ if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) { @@ -2542,6 +2555,9 @@ gst_rtp_bin_release_pad (GstElement * element, GstPad * pad) g_return_if_fail (target); GST_RTP_BIN_LOCK (rtpbin); + GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s", + GST_DEBUG_PAD_NAME (target)); + if (!(session = find_session_by_pad (rtpbin, target))) goto unknown_pad; @@ -2558,8 +2574,9 @@ gst_rtp_bin_release_pad (GstElement * element, GstPad * pad) /* no more request pads, free the complete session */ if (session->recv_rtp_sink == NULL && session->recv_rtcp_sink == NULL && session->send_rtp_sink == NULL && session->send_rtcp_src == NULL) { + GST_DEBUG_OBJECT (rtpbin, "no more pads for session %p", session); rtpbin->sessions = g_slist_remove (rtpbin->sessions, session); - free_session (session); + free_session (session, rtpbin); } GST_RTP_BIN_UNLOCK (rtpbin); -- cgit v1.2.1 From d48dcb04998835469d15cba23e455c61dfb1a80c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 13:45:15 +0200 Subject: rtpsession: reuse source code for SDES Reuse the RTPSource object property instead of duplicating code. --- gst/rtpmanager/gstrtpsession.c | 60 ++---------------------------------------- 1 file changed, 2 insertions(+), 58 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index 035d82a8..c33fdfc6 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -323,63 +323,6 @@ on_ssrc_active (RTPSession * session, RTPSource * src, GstRtpSession * sess) src->ssrc); } -static GstStructure * -source_get_sdes_structure (RTPSource * src) -{ - GstStructure *result; - GValue val = { 0 }; - gchar *str; - - result = gst_structure_empty_new ("GstRTPSessionSDES"); - - gst_structure_set (result, "ssrc", G_TYPE_UINT, src->ssrc, NULL); - - g_value_init (&val, G_TYPE_STRING); - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_CNAME); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "cname", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NAME); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "name", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_EMAIL); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "email", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_PHONE); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "phone", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_LOC); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "location", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_TOOL); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "tool", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NOTE); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "note", &val); - } - str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_PRIV); - if (str) { - g_value_take_string (&val, str); - gst_structure_set_value (result, "priv", &val); - } - g_value_unset (&val); - - return result; -} - static void on_ssrc_sdes (RTPSession * session, RTPSource * src, GstRtpSession * sess) { @@ -388,8 +331,9 @@ on_ssrc_sdes (RTPSession * session, RTPSource * src, GstRtpSession * sess) /* convert the new SDES info into a message */ RTP_SESSION_LOCK (session); - s = source_get_sdes_structure (src); + g_object_get (src, "sdes", &s, NULL); RTP_SESSION_UNLOCK (session); + m = gst_message_new_custom (GST_MESSAGE_ELEMENT, GST_OBJECT (sess), s); gst_element_post_message (GST_ELEMENT_CAST (sess), m); -- cgit v1.2.1 From a0b6202baf717f4a5aa74907f6bc8a3ec7e614c5 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 13:47:30 +0200 Subject: rtpsource: add RTP and RTCP source address Add the RTP and RTCP sender addresses in the stats structure. --- gst/rtpmanager/rtpsource.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/rtpsource.c b/gst/rtpmanager/rtpsource.c index a40d974f..6a3dc604 100644 --- a/gst/rtpmanager/rtpsource.c +++ b/gst/rtpmanager/rtpsource.c @@ -188,12 +188,50 @@ rtp_source_finalize (GObject * object) G_OBJECT_CLASS (rtp_source_parent_class)->finalize (object); } +#define MAX_ADDRESS 64 +static void +make_address_string (GstNetAddress * addr, gchar * dest, gulong n) +{ + switch (gst_netaddress_get_net_type (addr)) { + case GST_NET_TYPE_IP4: + { + guint32 address; + guint16 port; + + gst_netaddress_get_ip4_address (addr, &address, &port); + + g_snprintf (dest, n, "%d.%d.%d.%d:%d", (address >> 24) & 0xff, + (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff, port); + break; + } + case GST_NET_TYPE_IP6: + { + guint8 address[16]; + guint16 port; + + gst_netaddress_get_ip6_address (addr, address, &port); + + g_snprintf (dest, n, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%d", + (address[0] << 8) | address[1], (address[2] << 8) | address[3], + (address[4] << 8) | address[5], (address[6] << 8) | address[7], + (address[8] << 8) | address[9], (address[10] << 8) | address[11], + (address[12] << 8) | address[13], (address[14] << 8) | address[15], + port); + break; + } + default: + dest[0] = 0; + break; + } +} + static GstStructure * rtp_source_create_stats (RTPSource * src) { GstStructure *s; gboolean is_sender = src->is_sender; gboolean internal = src->internal; + gchar address_str[MAX_ADDRESS]; /* common data for all types of sources */ s = gst_structure_new ("application/x-rtp-source-stats", @@ -204,6 +242,16 @@ rtp_source_create_stats (RTPSource * src) "is-csrc", G_TYPE_BOOLEAN, src->is_csrc, "is-sender", G_TYPE_BOOLEAN, is_sender, NULL); + /* add address and port */ + if (src->have_rtp_from) { + make_address_string (&src->rtp_from, address_str, sizeof (address_str)); + gst_structure_set (s, "rtp-from", G_TYPE_STRING, address_str, NULL); + } + if (src->have_rtcp_from) { + make_address_string (&src->rtcp_from, address_str, sizeof (address_str)); + gst_structure_set (s, "rtcp-from", G_TYPE_STRING, address_str, NULL); + } + if (internal) { /* our internal source */ if (is_sender) { -- cgit v1.2.1 From 1c85da2d2bfc85722522e3c257271de2f97f734c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 15:36:17 +0200 Subject: rtpbin: don't warn when getting request pads twice Allow getting the request pads multiple times, just return the previously created pads. --- gst/rtpmanager/gstrtpbin.c | 86 ++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 52 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 5c0948c6..bcd363b0 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -347,13 +347,17 @@ struct _GstRtpBinSession /* the pads of the session */ GstPad *recv_rtp_sink; + GstPad *recv_rtp_sink_ghost; GstPad *recv_rtp_src; GstPad *recv_rtcp_sink; + GstPad *recv_rtcp_sink_ghost; GstPad *sync_src; GstPad *send_rtp_sink; + GstPad *send_rtp_sink_ghost; GstPad *send_rtp_src; GstPad *send_rtp_src_ghost; GstPad *send_rtcp_src; + GstPad *send_rtcp_src_ghost; }; /* Manages the RTP streams that come from one client and should therefore be @@ -2034,7 +2038,7 @@ no_stream: static GstPad * create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result, *sinkdpad; + GstPad *sinkdpad; guint sessid; GstRtpBinSession *session; GstPadLinkReturn lres; @@ -2056,8 +2060,8 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) } /* check if pad was requested */ - if (session->recv_rtp_sink != NULL) - goto existed; + if (session->recv_rtp_sink_ghost != NULL) + return session->recv_rtp_sink_ghost; GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad"); /* get recv_rtp pad and store */ @@ -2091,12 +2095,12 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) "pad-removed", (GCallback) ssrc_demux_pad_removed, session); GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad"); - result = + session->recv_rtp_sink_ghost = gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ); - gst_pad_set_active (result, TRUE); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result); + gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost); - return result; + return session->recv_rtp_sink_ghost; /* ERRORS */ no_name: @@ -2109,12 +2113,6 @@ create_error: /* create_session already warned */ return NULL; } -existed: - { - g_warning ("gstrtpbin: recv_rtp pad already requested for session %d", - sessid); - return NULL; - } pad_failed: { g_warning ("gstrtpbin: failed to get session pad"); @@ -2150,6 +2148,7 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) gst_pad_set_active (pad, FALSE); gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); + session->recv_rtp_sink_ghost = NULL; } /* Create a pad for receiving RTCP for the session in @name. Must be called with @@ -2159,7 +2158,6 @@ static GstPad * create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result; guint sessid; GstRtpBinSession *session; GstPad *sinkdpad; @@ -2182,8 +2180,8 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, } /* check if pad was requested */ - if (session->recv_rtcp_sink != NULL) - goto existed; + if (session->recv_rtcp_sink_ghost != NULL) + return session->recv_rtcp_sink_ghost; /* get recv_rtp pad and store */ GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad"); @@ -2205,12 +2203,13 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, if (lres != GST_PAD_LINK_OK) goto link_failed; - result = + session->recv_rtcp_sink_ghost = gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ); - gst_pad_set_active (result, TRUE); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result); + gst_pad_set_active (session->recv_rtcp_sink_ghost, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), + session->recv_rtcp_sink_ghost); - return result; + return session->recv_rtcp_sink_ghost; /* ERRORS */ no_name: @@ -2223,12 +2222,6 @@ create_error: /* create_session already warned */ return NULL; } -existed: - { - g_warning ("gstrtpbin: recv_rtcp pad already requested for session %d", - sessid); - return NULL; - } pad_failed: { g_warning ("gstrtpbin: failed to get session pad"); @@ -2244,6 +2237,7 @@ link_failed: static void remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { + session->recv_rtcp_sink_ghost = NULL; gst_pad_set_active (pad, FALSE); gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); @@ -2265,7 +2259,6 @@ remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) static GstPad * create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result; gchar *gname; guint sessid; GstRtpBinSession *session; @@ -2285,8 +2278,8 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) } /* check if pad was requested */ - if (session->send_rtp_sink != NULL) - goto existed; + if (session->send_rtp_sink_ghost != NULL) + return session->send_rtp_sink_ghost; /* get send_rtp pad and store */ session->send_rtp_sink = @@ -2294,10 +2287,10 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) if (session->send_rtp_sink == NULL) goto pad_failed; - result = + session->send_rtp_sink_ghost = gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ); - gst_pad_set_active (result, TRUE); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result); + gst_pad_set_active (session->send_rtp_sink_ghost, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_ghost); /* get srcpad */ session->send_rtp_src = @@ -2315,7 +2308,7 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost); g_free (gname); - return result; + return session->send_rtp_sink_ghost; /* ERRORS */ no_name: @@ -2328,12 +2321,6 @@ create_error: /* create_session already warned */ return NULL; } -existed: - { - g_warning ("gstrtpbin: send_rtp pad already requested for session %d", - sessid); - return NULL; - } pad_failed: { g_warning ("gstrtpbin: failed to get session pad for session %d", sessid); @@ -2369,6 +2356,7 @@ remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) session->send_rtp_sink = NULL; } + session->send_rtp_sink_ghost = NULL; gst_pad_set_active (pad, FALSE); gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); } @@ -2379,7 +2367,6 @@ remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) static GstPad * create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result; guint sessid; GstRtpBinSession *session; @@ -2393,8 +2380,8 @@ create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) goto no_session; /* check if pad was requested */ - if (session->send_rtcp_src != NULL) - goto existed; + if (session->send_rtcp_src_ghost != NULL) + return session->send_rtcp_src_ghost; /* get rtcp_src pad and store */ session->send_rtcp_src = @@ -2402,12 +2389,12 @@ create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) if (session->send_rtcp_src == NULL) goto pad_failed; - result = + session->send_rtcp_src_ghost = gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ); - gst_pad_set_active (result, TRUE); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result); + gst_pad_set_active (session->send_rtcp_src_ghost, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtcp_src_ghost); - return result; + return session->send_rtcp_src_ghost; /* ERRORS */ no_name: @@ -2420,12 +2407,6 @@ no_session: g_warning ("gstrtpbin: session with id %d does not exist", sessid); return NULL; } -existed: - { - g_warning ("gstrtpbin: send_rtcp_src pad already requested for session %d", - sessid); - return NULL; - } pad_failed: { g_warning ("gstrtpbin: failed to get rtcp pad for session %d", sessid); @@ -2436,6 +2417,7 @@ pad_failed: static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) { + session->send_rtcp_src_ghost = NULL; gst_pad_set_active (pad, FALSE); gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); -- cgit v1.2.1 From 9353ceb53049a2fe31a6b986d039dc64208779df Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 15:45:19 +0200 Subject: rtpbin: use our ghostpads instead of its target Since we keep a reference to our ghostpads, we can use them to track sessions. This avoid us having to mess with the target of the ghostpad. --- gst/rtpmanager/gstrtpbin.c | 90 +++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 44 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index bcd363b0..f7d7e54a 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -398,9 +398,10 @@ find_session_by_pad (GstRtpBin * rtpbin, GstPad * pad) for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) { GstRtpBinSession *sess = (GstRtpBinSession *) walk->data; - if ((sess->recv_rtp_sink == pad) || - (sess->recv_rtcp_sink == pad) || - (sess->send_rtp_sink == pad) || (sess->send_rtcp_src == pad)) + if ((sess->recv_rtp_sink_ghost == pad) || + (sess->recv_rtcp_sink_ghost == pad) || + (sess->send_rtp_sink_ghost == pad) + || (sess->send_rtcp_src_ghost == pad)) return sess; } return NULL; @@ -2126,7 +2127,7 @@ link_failed: } static void -remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) { if (session->demux_newpad_sig) { g_signal_handler_disconnect (session->demux, session->demux_newpad_sig); @@ -2145,10 +2146,12 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) gst_object_unref (session->recv_rtp_sink); session->recv_rtp_sink = NULL; } - - gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); - session->recv_rtp_sink_ghost = NULL; + if (session->recv_rtp_sink_ghost) { + gst_pad_set_active (session->recv_rtp_sink_ghost, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), + session->recv_rtp_sink_ghost); + session->recv_rtp_sink_ghost = NULL; + } } /* Create a pad for receiving RTCP for the session in @name. Must be called with @@ -2235,12 +2238,14 @@ link_failed: } static void -remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - session->recv_rtcp_sink_ghost = NULL; - gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); - + if (session->recv_rtcp_sink_ghost) { + gst_pad_set_active (session->recv_rtcp_sink_ghost, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), + session->recv_rtcp_sink_ghost); + session->recv_rtcp_sink_ghost = NULL; + } if (session->sync_src) { /* releasing the request pad should also unref the sync pad */ gst_object_unref (session->sync_src); @@ -2335,7 +2340,7 @@ no_srcpad: } static void -remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) { if (session->send_rtp_src_ghost) { gst_pad_set_active (session->send_rtp_src_ghost, FALSE); @@ -2343,22 +2348,22 @@ remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) session->send_rtp_src_ghost); session->send_rtp_src_ghost = NULL; } - if (session->send_rtp_src) { gst_object_unref (session->send_rtp_src); session->send_rtp_src = NULL; } - if (session->send_rtp_sink) { gst_element_release_request_pad (GST_ELEMENT_CAST (session->session), session->send_rtp_sink); gst_object_unref (session->send_rtp_sink); session->send_rtp_sink = NULL; } - - session->send_rtp_sink_ghost = NULL; - gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); + if (session->send_rtp_sink_ghost) { + gst_pad_set_active (session->send_rtp_sink_ghost, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), + session->send_rtp_sink_ghost); + session->send_rtp_sink_ghost = NULL; + } } /* Create a pad for sending RTCP for the session in @name. Must be called with @@ -2415,12 +2420,14 @@ pad_failed: } static void -remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - session->send_rtcp_src_ghost = NULL; - gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), pad); - + if (session->send_rtcp_src_ghost) { + gst_pad_set_active (session->send_rtcp_src_ghost, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), + session->send_rtcp_src_ghost); + session->send_rtcp_src_ghost = NULL; + } if (session->send_rtcp_src) { gst_element_release_request_pad (session->session, session->send_rtcp_src); gst_object_unref (session->send_rtcp_src); @@ -2526,51 +2533,46 @@ gst_rtp_bin_release_pad (GstElement * element, GstPad * pad) { GstRtpBinSession *session; GstRtpBin *rtpbin; - GstPad *target = NULL; g_return_if_fail (GST_IS_GHOST_PAD (pad)); g_return_if_fail (GST_IS_RTP_BIN (element)); rtpbin = GST_RTP_BIN (element); - target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)); - g_return_if_fail (target); - GST_RTP_BIN_LOCK (rtpbin); GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s", - GST_DEBUG_PAD_NAME (target)); + GST_DEBUG_PAD_NAME (pad)); - if (!(session = find_session_by_pad (rtpbin, target))) + if (!(session = find_session_by_pad (rtpbin, pad))) goto unknown_pad; - if (session->recv_rtp_sink == target) { - remove_recv_rtp (rtpbin, session, pad); - } else if (session->recv_rtcp_sink == target) { - remove_recv_rtcp (rtpbin, session, pad); - } else if (session->send_rtp_sink == target) { - remove_send_rtp (rtpbin, session, pad); - } else if (session->send_rtcp_src == target) { - remove_rtcp (rtpbin, session, pad); + if (session->recv_rtp_sink_ghost == pad) { + remove_recv_rtp (rtpbin, session); + } else if (session->recv_rtcp_sink_ghost == pad) { + remove_recv_rtcp (rtpbin, session); + } else if (session->send_rtp_sink_ghost == pad) { + remove_send_rtp (rtpbin, session); + } else if (session->send_rtcp_src_ghost == pad) { + remove_rtcp (rtpbin, session); } /* no more request pads, free the complete session */ - if (session->recv_rtp_sink == NULL && session->recv_rtcp_sink == NULL && - session->send_rtp_sink == NULL && session->send_rtcp_src == NULL) { + if (session->recv_rtp_sink_ghost == NULL + && session->recv_rtcp_sink_ghost == NULL + && session->send_rtp_sink_ghost == NULL + && session->send_rtcp_src_ghost == NULL) { GST_DEBUG_OBJECT (rtpbin, "no more pads for session %p", session); rtpbin->sessions = g_slist_remove (rtpbin->sessions, session); free_session (session, rtpbin); } GST_RTP_BIN_UNLOCK (rtpbin); - gst_object_unref (target); - return; /* ERROR */ unknown_pad: { GST_RTP_BIN_UNLOCK (rtpbin); - gst_object_unref (target); g_warning ("gstrtpbin: %s:%s is not one of our request pads", GST_DEBUG_PAD_NAME (pad)); return; -- cgit v1.2.1 From 0d014baaa4c61010c98c6899cd2338da1423014b Mon Sep 17 00:00:00 2001 From: Ali Sabil Date: Fri, 22 May 2009 16:35:20 +0200 Subject: ssrcdemux: emit signal when pads are removed Add action signal to clear an SSRC in the ssrc demuxer. Add signal to notify of removed ssrc. See #554839 --- gst/rtpmanager/gstrtpbin-marshal.list | 1 + gst/rtpmanager/gstrtpssrcdemux.c | 74 +++++++++++++++++++++++++++++++++++ gst/rtpmanager/gstrtpssrcdemux.h | 6 ++- 3 files changed, 80 insertions(+), 1 deletion(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin-marshal.list b/gst/rtpmanager/gstrtpbin-marshal.list index c4bc0bb2..ed73e43b 100644 --- a/gst/rtpmanager/gstrtpbin-marshal.list +++ b/gst/rtpmanager/gstrtpbin-marshal.list @@ -3,5 +3,6 @@ BOXED:UINT BOXED:UINT,UINT OBJECT:UINT VOID:UINT,OBJECT +VOID:UINT VOID:UINT,UINT VOID:OBJECT,OBJECT diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c index b9a279c2..6a305d8e 100644 --- a/gst/rtpmanager/gstrtpssrcdemux.c +++ b/gst/rtpmanager/gstrtpssrcdemux.c @@ -97,6 +97,8 @@ static GstElementDetails gst_rtp_ssrc_demux_details = { enum { SIGNAL_NEW_SSRC_PAD, + SIGNAL_REMOVED_SSRC_PAD, + SIGNAL_CLEAR_SSRC, LAST_SIGNAL }; @@ -112,6 +114,9 @@ static void gst_rtp_ssrc_demux_finalize (GObject * object); static GstStateChangeReturn gst_rtp_ssrc_demux_change_state (GstElement * element, GstStateChange transition); +static void gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux, + guint32 ssrc); + /* sinkpad stuff */ static GstFlowReturn gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf); static gboolean gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event); @@ -245,9 +250,11 @@ gst_rtp_ssrc_demux_class_init (GstRtpSsrcDemuxClass * klass) { GObjectClass *gobject_klass; GstElementClass *gstelement_klass; + GstRtpSsrcDemuxClass *gstrtpssrcdemux_klass; gobject_klass = (GObjectClass *) klass; gstelement_klass = (GstElementClass *) klass; + gstrtpssrcdemux_klass = (GstRtpSsrcDemuxClass *) klass; gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_dispose); gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_finalize); @@ -267,8 +274,38 @@ gst_rtp_ssrc_demux_class_init (GstRtpSsrcDemuxClass * klass) NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_OBJECT, G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_PAD); + /** + * GstRtpSsrcDemux::removed-ssrc-pad: + * @demux: the object which received the signal + * @ssrc: the SSRC of the pad + * @pad: the removed pad. + * + * Emited when a SSRC pad has been removed. + */ + gst_rtp_ssrc_demux_signals[SIGNAL_REMOVED_SSRC_PAD] = + g_signal_new ("removed-ssrc-pad", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRtpSsrcDemuxClass, removed_ssrc_pad), + NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_OBJECT, + G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_PAD); + + /** + * GstRtpSsrcDemux::clear-ssrc: + * @demux: the object which received the signal + * @ssrc: the SSRC of the pad + * + * Action signal to remove the pad for SSRC. + */ + gst_rtp_ssrc_demux_signals[SIGNAL_CLEAR_SSRC] = + g_signal_new ("clear-ssrc", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstRtpSsrcDemuxClass, clear_ssrc), + NULL, NULL, gst_rtp_bin_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); + gstelement_klass->change_state = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_change_state); + gstrtpssrcdemux_klass->clear_ssrc = + GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_clear_ssrc); GST_DEBUG_CATEGORY_INIT (gst_rtp_ssrc_demux_debug, "rtpssrcdemux", 0, "RTP SSRC demuxer"); @@ -342,6 +379,43 @@ gst_rtp_ssrc_demux_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc) +{ + GstRtpSsrcDemuxPad *dpad; + + GST_PAD_LOCK (demux); + dpad = find_demux_pad_for_ssrc (demux, ssrc); + if (dpad != NULL) + goto unknown_pad; + + GST_DEBUG_OBJECT (demux, "clearing pad for SSRC %08x", ssrc); + + demux->srcpads = g_slist_remove (demux->srcpads, dpad); + GST_PAD_UNLOCK (demux); + + gst_pad_set_active (dpad->rtp_pad, FALSE); + gst_pad_set_active (dpad->rtcp_pad, FALSE); + + g_signal_emit (G_OBJECT (demux), + gst_rtp_ssrc_demux_signals[SIGNAL_REMOVED_SSRC_PAD], 0, ssrc, + dpad->rtp_pad); + + gst_element_remove_pad (GST_ELEMENT_CAST (demux), dpad->rtp_pad); + gst_element_remove_pad (GST_ELEMENT_CAST (demux), dpad->rtcp_pad); + + g_free (dpad); + + return; + + /* ERRORS */ +unknown_pad: + { + g_warning ("unknown SSRC %08x", ssrc); + return; + } +} + static gboolean gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event) { diff --git a/gst/rtpmanager/gstrtpssrcdemux.h b/gst/rtpmanager/gstrtpssrcdemux.h index d89472af..d5a13caf 100644 --- a/gst/rtpmanager/gstrtpssrcdemux.h +++ b/gst/rtpmanager/gstrtpssrcdemux.h @@ -50,7 +50,11 @@ struct _GstRtpSsrcDemuxClass GstElementClass parent_class; /* signals */ - void (*new_ssrc_pad) (GstElement *element, guint32 ssrc, GstPad *pad); + void (*new_ssrc_pad) (GstRtpSsrcDemux *demux, guint32 ssrc, GstPad *pad); + void (*removed_ssrc_pad) (GstRtpSsrcDemux *demux, guint32 ssrc, GstPad *pad); + + /* actions */ + void (*clear_ssrc) (GstRtpSsrcDemux *demux, guint32 ssrc); }; GType gst_rtp_ssrc_demux_get_type (void); -- cgit v1.2.1 From e8423da78eea949f8223da5c27ea36544a3a6c5b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2009 16:41:19 +0200 Subject: rtpbin: add to new signal to remove SSRC pads --- gst/rtpmanager/gstrtpbin.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index f7d7e54a..017ffc02 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -493,27 +493,18 @@ find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc) } static void -ssrc_demux_pad_removed (GstElement * element, GstPad * pad, +ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad, GstRtpBinSession * session) { - guint ssrc; GstRtpBinStream *stream = NULL; - gchar *name; - gint res; - - name = gst_pad_get_name (pad); - res = sscanf (name, "src_%d", &ssrc); - g_free (name); - - if (res != 1) - return; GST_RTP_SESSION_LOCK (session); - if ((stream = find_stream_by_ssrc (session, ssrc))) { + if ((stream = find_stream_by_ssrc (session, ssrc))) session->streams = g_slist_remove (session->streams, stream); - free_stream (stream); - } GST_RTP_SESSION_UNLOCK (session); + + if (stream) + free_stream (stream); } /* create a session with the given id. Must be called with RTP_BIN_LOCK */ @@ -2093,7 +2084,7 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) session->demux_newpad_sig = g_signal_connect (session->demux, "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session); session->demux_padremoved_sig = g_signal_connect (session->demux, - "pad-removed", (GCallback) ssrc_demux_pad_removed, session); + "removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session); GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad"); session->recv_rtp_sink_ghost = -- cgit v1.2.1 From 269f3ff1a270e1c3cd9b6204c7171d47eb7dfbf1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 25 May 2009 13:46:29 +0200 Subject: rtpbin: remove ptdemux ghostpads --- gst/rtpmanager/gstrtpbin.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 017ffc02..19de4f1b 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -306,6 +306,8 @@ struct _GstRtpBinStream gulong demux_newpad_sig; gulong demux_ptreq_sig; gulong demux_pt_change_sig; + /* ghostpads from the ptdemuxer */ + GSList *pads; /* if we have calculated a valid unix_delta for this stream */ gboolean have_sync; @@ -1169,6 +1171,7 @@ static void free_stream (GstRtpBinStream * stream) { GstRtpBinSession *session; + GSList *walk; session = stream->session; @@ -1184,6 +1187,14 @@ free_stream (GstRtpBinStream * stream) gst_bin_remove (GST_BIN_CAST (session->bin), stream->buffer); gst_bin_remove (GST_BIN_CAST (session->bin), stream->demux); + for (walk = stream->pads; walk; walk = g_slist_next (walk)) { + GstPad *gpad = GST_PAD_CAST (walk->data); + + gst_pad_set_active (gpad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (session->bin), gpad); + } + g_slist_free (stream->pads); + g_free (stream); } @@ -1880,6 +1891,8 @@ new_payload_found (GstElement * element, guint pt, GstPad * pad, gst_pad_set_active (gpad, TRUE); gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad); + stream->pads = g_slist_prepend (stream->pads, gpad); + GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin); return; -- cgit v1.2.1