diff options
author | Dave Robillard <dave@drobilla.net> | 2009-05-25 22:23:04 -0400 |
---|---|---|
committer | Dave Robillard <dave@drobilla.net> | 2009-05-25 22:23:04 -0400 |
commit | e9f9ffa0e5ca0844a499a106963888176b6a7372 (patch) | |
tree | b86653bbb9f9f19c5d6adf29198bf2b168813cfe /gst/rtpmanager/gstrtpbin.c | |
parent | 9e306663812d0af7d6889c1c314f2148e2dd40cf (diff) | |
parent | 023af351fba4b22db782b39f4aa8ae75b70cc10f (diff) | |
download | gst-plugins-bad-e9f9ffa0e5ca0844a499a106963888176b6a7372.tar.gz gst-plugins-bad-e9f9ffa0e5ca0844a499a106963888176b6a7372.tar.bz2 gst-plugins-bad-e9f9ffa0e5ca0844a499a106963888176b6a7372.zip |
Merge git://anongit.freedesktop.org/gstreamer/gst-plugins-bad into lv2
Diffstat (limited to 'gst/rtpmanager/gstrtpbin.c')
-rw-r--r-- | gst/rtpmanager/gstrtpbin.c | 361 |
1 files changed, 232 insertions, 129 deletions
diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 7d3b9823..19de4f1b 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -297,12 +297,17 @@ 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; 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; @@ -332,6 +337,7 @@ struct _GstRtpBinSession /* the SSRC demuxer */ GstElement *demux; gulong demux_newpad_sig; + gulong demux_padremoved_sig; GMutex *lock; @@ -343,12 +349,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 @@ -389,9 +400,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; @@ -467,6 +479,36 @@ 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, guint ssrc, GstPad * pad, + GstRtpBinSession * session) +{ + GstRtpBinStream *stream = NULL; + + GST_RTP_SESSION_LOCK (session); + if ((stream = find_stream_by_ssrc (session, ssrc))) + session->streams = g_slist_remove (session->streams, 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 */ static GstRtpBinSession * create_session (GstRtpBin * rtpbin, gint id) @@ -474,6 +516,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; @@ -522,11 +565,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; @@ -545,16 +593,12 @@ 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->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); @@ -588,27 +632,9 @@ 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); } -#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) @@ -822,8 +848,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); @@ -1079,6 +1106,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; @@ -1086,9 +1115,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; @@ -1097,22 +1128,29 @@ 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); - 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 */ @@ -1133,16 +1171,29 @@ static void free_stream (GstRtpBinStream * stream) { GstRtpBinSession *session; + GSList *walk; 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); + 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); } @@ -1481,11 +1532,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; @@ -1556,6 +1607,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); @@ -1564,6 +1617,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 * @@ -1836,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; @@ -1947,7 +2004,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 @@ -1986,7 +2043,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; @@ -2008,8 +2065,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 */ @@ -2039,14 +2096,16 @@ 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, + "removed-ssrc-pad", (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: @@ -2059,12 +2118,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"); @@ -2078,10 +2131,31 @@ link_failed: } static void -remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - 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->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); + gst_object_unref (session->recv_rtp_sink); + session->recv_rtp_sink = 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 @@ -2091,7 +2165,6 @@ static GstPad * create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result; guint sessid; GstRtpBinSession *session; GstPad *sinkdpad; @@ -2114,8 +2187,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"); @@ -2137,12 +2210,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: @@ -2155,12 +2229,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"); @@ -2174,10 +2242,24 @@ link_failed: } static void -remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (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); + session->sync_src = NULL; + } + 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; + } } /* Create a pad for sending RTP for the session in @name. Must be called with @@ -2186,7 +2268,6 @@ remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) static GstPad * create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) { - GstPad *result, *srcghost; gchar *gname; guint sessid; GstRtpBinSession *session; @@ -2206,8 +2287,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 = @@ -2215,10 +2296,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 = @@ -2230,13 +2311,13 @@ 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; + return session->send_rtp_sink_ghost; /* ERRORS */ no_name: @@ -2249,12 +2330,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); @@ -2269,10 +2344,30 @@ no_srcpad: } static void -remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - 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); + gst_object_unref (session->send_rtp_sink); + session->send_rtp_sink = NULL; + } + 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 @@ -2281,7 +2376,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; @@ -2295,8 +2389,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 = @@ -2304,12 +2398,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: @@ -2322,12 +2416,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); @@ -2336,10 +2424,19 @@ pad_failed: } static void -remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, GstPad * pad) +remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session) { - g_warning ("gstrtpbin: releasing pad %s:%s is not implemented", - GST_DEBUG_PAD_NAME (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); + session->send_rtcp_src = NULL; + } } /* If the requested name is NULL we should create a name with @@ -2403,7 +2500,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")) { @@ -2440,32 +2537,39 @@ 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); - if (!(session = find_session_by_pad (rtpbin, target))) + GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + 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); } - GST_RTP_BIN_UNLOCK (rtpbin); - gst_object_unref (target); + /* no more request pads, free the complete session */ + 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); return; @@ -2473,7 +2577,6 @@ gst_rtp_bin_release_pad (GstElement * element, GstPad * pad) 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; |