X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Frtpmanager%2Fgstrtpbin.c;h=d10cd01502eb9622d34bca0332624ea3d38b2520;hb=6c86b2832f30e0eb8ccd7c7e186892caceb34325;hp=66470c2d25be8cb029feda987f78a46abfa6a03a;hpb=db688c5504916b780514aa3fda63fb6487a83174;p=platform%2Fupstream%2Fgst-plugins-good.git diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 66470c2..d10cd01 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -19,6 +19,7 @@ /** * SECTION:element-rtpbin + * @title: rtpbin * @see_also: rtpjitterbuffer, rtpsession, rtpptdemux, rtpssrcdemux * * RTP bin combines the functions of #GstRtpSession, #GstRtpSsrcDemux, @@ -50,16 +51,9 @@ * To use #GstRtpBin as a sender, request a send_rtp_sink_\%u pad, which will * automatically create a send_rtp_src_\%u pad. If the session number is not provided, * the pad from the lowest available session will be returned. The session manager will modify the - * SSRC in the RTP packets to its own SSRC and wil forward the packets on the + * SSRC in the RTP packets to its own SSRC and will forward the packets on the * send_rtp_src_\%u pad after updating its internal state. * - * #GstRtpBin can also demultiplex incoming bundled streams. The first - * #GstRtpSession will have a #GstRtpSsrcDemux element splitting the streams - * based on their SSRC and potentially dispatched to a different #GstRtpSession. - * Because retransmission SSRCs need to be merged with the corresponding media - * stream the #GstRtpBin::on-bundled-ssrc signal is emitted so that the - * application can find out to which session the SSRC belongs. - * * The session manager needs the clock-rate of the payload types it is handling * and will signal the #GstRtpSession::request-pt-map signal when it needs such a * mapping. One can clear the cached values with the #GstRtpSession::clear-pt-map @@ -91,9 +85,12 @@ * An AUX receiver has 1 src_\%u pad that much match the sessionid in the signal * and 1 or more sink_\%u pads. A session will be made for each sink_\%u pad * when the corresponding recv_rtp_sink_\%u pad is requested on #GstRtpBin. + * The #GstRtpBin::request-jitterbuffer signal can be used to provide a custom + * element to perform arrival time smoothing, reordering and optionally packet + * loss detection and retransmission requests. + * + * ## Example pipelines * - * - * Example pipelines * |[ * gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \ * rtpbin ! rtptheoradepay ! theoradec ! xvimagesink @@ -138,7 +135,7 @@ * synchronisation. * Send RTCP reports for session 0 on port 5005 and RTCP reports for session 1 * on port 5007. - * + * */ #ifdef HAVE_CONFIG_H @@ -204,9 +201,6 @@ static GstStaticPadTemplate rtpbin_send_rtp_src_template = GST_STATIC_CAPS ("application/x-rtp;application/x-srtp") ); -#define GST_RTP_BIN_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRtpBinPrivate)) - #define GST_RTP_BIN_LOCK(bin) g_mutex_lock (&(bin)->priv->bin_lock) #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock (&(bin)->priv->bin_lock) @@ -284,6 +278,8 @@ enum SIGNAL_REQUEST_FEC_DECODER, SIGNAL_REQUEST_FEC_ENCODER, + SIGNAL_REQUEST_JITTERBUFFER, + SIGNAL_NEW_JITTERBUFFER, SIGNAL_NEW_STORAGE, @@ -321,6 +317,9 @@ enum #define DEFAULT_MAX_STREAMS G_MAXUINT #define DEFAULT_MAX_TS_OFFSET_ADJUSTMENT G_GUINT64_CONSTANT(0) #define DEFAULT_MAX_TS_OFFSET G_GINT64_CONSTANT(3000000000) +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION +#define DEFAULT_RTSP_USE_BUFFERING FALSE +#endif enum { @@ -348,6 +347,9 @@ enum PROP_MAX_STREAMS, PROP_MAX_TS_OFFSET_ADJUSTMENT, PROP_MAX_TS_OFFSET, +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + PROP_USE_RTSP_BUFFERING /* use for player RTSP buffering */ +#endif }; #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type()) @@ -387,16 +389,18 @@ static void free_client (GstRtpBinClient * client, GstRtpBin * bin); static void free_stream (GstRtpBinStream * stream, GstRtpBin * bin); static GstRtpBinSession *create_session (GstRtpBin * rtpbin, gint id); static GstPad *complete_session_sink (GstRtpBin * rtpbin, - GstRtpBinSession * session, gboolean bundle_demuxer_needed); + GstRtpBinSession * session); static void complete_session_receiver (GstRtpBin * rtpbin, GstRtpBinSession * session, guint sessid); static GstPad *complete_session_rtcp (GstRtpBin * rtpbin, - GstRtpBinSession * session, guint sessid, gboolean bundle_demuxer_needed); + GstRtpBinSession * session, guint sessid); +static GstElement *session_request_element (GstRtpBinSession * session, + guint signal); /* Manages the RTP stream for one SSRC. * - * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer. + * We pipe the stream (coming from the SSRC demuxer) into a jitterbuffer. * If we see an SDES RTCP packet that links multiple SSRCs together based on a * common CNAME, we create a GstRtpBinClient structure to group the SSRCs * together (see below). @@ -418,7 +422,9 @@ struct _GstRtpBinStream gulong buffer_ptreq_sig; gulong buffer_ntpstop_sig; gint percent; - +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + gint prev_percent; +#endif /* the PT demuxer of the SSRC */ GstElement *demux; gulong demux_newpad_sig; @@ -465,12 +471,6 @@ struct _GstRtpBinSession /* Fec support */ GstElement *storage; - /* Bundling support */ - GstElement *rtp_funnel; - GstElement *rtcp_funnel; - GstElement *bundle_demux; - gulong bundle_demux_newpad_sig; - GMutex lock; /* list of GstRtpBinStream */ @@ -671,102 +671,6 @@ ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad, GST_RTP_BIN_UNLOCK (rtpbin); } -static void -new_bundled_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad, - GstRtpBinSession * session) -{ - GValue result = G_VALUE_INIT; - GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT }; - guint session_id = 0; - GstRtpBinSession *target_session = NULL; - GstRtpBin *rtpbin = session->bin; - gchar *name; - GstPad *src_pad; - GstPad *recv_rtp_sink = NULL; - GstPad *recv_rtcp_sink = NULL; - GstPadLinkReturn ret; - - GST_RTP_BIN_DYN_LOCK (rtpbin); - GST_DEBUG_OBJECT (rtpbin, "new bundled SSRC pad %08x, %s:%s", ssrc, - GST_DEBUG_PAD_NAME (pad)); - - g_value_init (&result, G_TYPE_UINT); - g_value_init (¶ms[0], GST_TYPE_ELEMENT); - g_value_set_object (¶ms[0], rtpbin); - g_value_init (¶ms[1], G_TYPE_UINT); - g_value_set_uint (¶ms[1], ssrc); - - g_signal_emitv (params, - gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC], 0, &result); - g_value_unset (¶ms[0]); - - session_id = g_value_get_uint (&result); - if (session_id == 0) { - target_session = session; - } else { - target_session = find_session_by_id (rtpbin, (gint) session_id); - if (!target_session) { - target_session = create_session (rtpbin, session_id); - } - if (!target_session) { - /* create_session() warned already */ - GST_RTP_BIN_DYN_UNLOCK (rtpbin); - return; - } - - if (!target_session->recv_rtp_sink) { - recv_rtp_sink = complete_session_sink (rtpbin, target_session, FALSE); - } - - if (!target_session->recv_rtp_src) - complete_session_receiver (rtpbin, target_session, session_id); - - if (!target_session->recv_rtcp_sink) { - recv_rtcp_sink = - complete_session_rtcp (rtpbin, target_session, session_id, FALSE); - } - } - - GST_DEBUG_OBJECT (rtpbin, "Assigning bundled ssrc %u to session %u", ssrc, - session_id); - - if (!recv_rtp_sink) { - recv_rtp_sink = - gst_element_get_request_pad (target_session->rtp_funnel, "sink_%u"); - } - - if (!recv_rtcp_sink) { - recv_rtcp_sink = - gst_element_get_request_pad (target_session->rtcp_funnel, "sink_%u"); - } - - name = g_strdup_printf ("src_%u", ssrc); - src_pad = gst_element_get_static_pad (element, name); - ret = gst_pad_link (src_pad, recv_rtp_sink); - g_free (name); - gst_object_unref (src_pad); - gst_object_unref (recv_rtp_sink); - if (ret != GST_PAD_LINK_OK) { - g_warning - ("rtpbin: failed to link bundle demuxer to receive rtp funnel for session %u", - session_id); - } - - name = g_strdup_printf ("rtcp_src_%u", ssrc); - src_pad = gst_element_get_static_pad (element, name); - gst_pad_link (src_pad, recv_rtcp_sink); - g_free (name); - gst_object_unref (src_pad); - gst_object_unref (recv_rtcp_sink); - if (ret != GST_PAD_LINK_OK) { - g_warning - ("rtpbin: failed to link bundle demuxer to receive rtcp sink pad for session %u", - session_id); - } - - GST_RTP_BIN_DYN_UNLOCK (rtpbin); -} - /* create a session with the given id. Must be called with RTP_BIN_LOCK */ static GstRtpBinSession * create_session (GstRtpBin * rtpbin, gint id) @@ -785,6 +689,9 @@ create_session (GstRtpBin * rtpbin, gint id) if (!(storage = gst_element_factory_make ("rtpstorage", NULL))) goto no_storage; + /* need to sink the storage or otherwise signal handlers from bindings will + * take ownership of it and we don't own it anymore */ + gst_object_ref_sink (storage); g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_STORAGE], 0, storage, id); @@ -796,15 +703,13 @@ create_session (GstRtpBin * rtpbin, gint id) sess->demux = demux; sess->storage = storage; - sess->rtp_funnel = gst_element_factory_make ("funnel", NULL); - sess->rtcp_funnel = gst_element_factory_make ("funnel", NULL); - sess->ptmap = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) gst_caps_unref); rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess); /* configure SDES items */ GST_OBJECT_LOCK (rtpbin); + g_object_set (demux, "max-streams", rtpbin->max_streams, NULL); g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile", rtpbin->rtp_profile, "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time, NULL); @@ -846,10 +751,12 @@ create_session (GstRtpBin * rtpbin, gint id) gst_bin_add (GST_BIN_CAST (rtpbin), session); gst_bin_add (GST_BIN_CAST (rtpbin), demux); - gst_bin_add (GST_BIN_CAST (rtpbin), sess->rtp_funnel); - gst_bin_add (GST_BIN_CAST (rtpbin), sess->rtcp_funnel); gst_bin_add (GST_BIN_CAST (rtpbin), storage); + /* unref the storage again, the bin has a reference now and + * we don't need it anymore */ + gst_object_unref (storage); + GST_OBJECT_LOCK (rtpbin); target = GST_STATE_TARGET (rtpbin); GST_OBJECT_UNLOCK (rtpbin); @@ -857,8 +764,6 @@ create_session (GstRtpBin * rtpbin, gint id) /* change state only to what's needed */ gst_element_set_state (demux, target); gst_element_set_state (session, target); - gst_element_set_state (sess->rtp_funnel, target); - gst_element_set_state (sess->rtcp_funnel, target); gst_element_set_state (storage, target); return sess; @@ -945,9 +850,11 @@ free_session (GstRtpBinSession * sess, GstRtpBin * bin) gst_element_set_locked_state (sess->demux, TRUE); gst_element_set_locked_state (sess->session, TRUE); + gst_element_set_locked_state (sess->storage, TRUE); gst_element_set_state (sess->demux, GST_STATE_NULL); gst_element_set_state (sess->session, GST_STATE_NULL); + gst_element_set_state (sess->storage, GST_STATE_NULL); remove_recv_rtp (bin, sess); remove_recv_rtcp (bin, sess); @@ -956,9 +863,11 @@ free_session (GstRtpBinSession * sess, GstRtpBin * bin) 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->storage); g_slist_foreach (sess->elements, (GFunc) remove_bin_element, bin); g_slist_free (sess->elements); + sess->elements = NULL; g_slist_foreach (sess->streams, (GFunc) free_stream, bin); g_slist_free (sess->streams); @@ -991,7 +900,7 @@ get_pt_map (GstRtpBinSession * session, guint pt) bin = session->bin; - GST_DEBUG ("emiting signal for pt %u in session %u", pt, session->id); + GST_DEBUG ("emitting signal for pt %u in session %u", pt, session->id); /* not in cache, send signal to request caps */ g_value_init (&args[0], GST_TYPE_ELEMENT); @@ -1099,7 +1008,8 @@ gst_rtp_bin_clear_pt_map (GstRtpBin * bin) GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; GST_DEBUG_OBJECT (bin, "clearing stream %p", stream); - g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL); + if (g_signal_lookup ("clear-pt-map", G_OBJECT_TYPE (stream->buffer)) != 0) + g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL); if (stream->demux) g_signal_emit_by_name (stream->demux, "clear-pt-map", NULL); } @@ -1198,6 +1108,12 @@ gst_rtp_bin_request_decoder (GstRtpBin * bin, guint session_id) return NULL; } +static GstElement * +gst_rtp_bin_request_jitterbuffer (GstRtpBin * bin, guint session_id) +{ + return gst_element_factory_make ("rtpjitterbuffer", NULL); +} + static void gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin, const gchar * name, const GValue * value) @@ -1211,8 +1127,14 @@ gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin, GST_RTP_SESSION_LOCK (session); for (streams = session->streams; streams; streams = g_slist_next (streams)) { GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; + GObjectClass *jb_class; - g_object_set_property (G_OBJECT (stream->buffer), name, value); + jb_class = G_OBJECT_GET_CLASS (G_OBJECT (stream->buffer)); + if (g_object_class_find_property (jb_class, name)) + g_object_set_property (G_OBJECT (stream->buffer), name, value); + else + GST_WARNING_OBJECT (bin, + "Stream jitterbuffer does not expose property %s", name); } GST_RTP_SESSION_UNLOCK (session); } @@ -1302,11 +1224,8 @@ get_current_times (GstRtpBin * bin, GstClockTime * running_time, switch (bin->ntp_time_source) { case GST_RTP_NTP_TIME_SOURCE_NTP: case GST_RTP_NTP_TIME_SOURCE_UNIX:{ - GTimeVal current; - /* get current NTP time */ - g_get_current_time (¤t); - ntpns = GST_TIMEVAL_TO_TIME (current); + ntpns = g_get_real_time () * GST_USECOND; /* add constant to convert from 1970 based time to 1900 based time */ if (bin->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP) @@ -1344,6 +1263,15 @@ stream_set_ts_offset (GstRtpBin * bin, GstRtpBinStream * stream, gboolean allow_positive_ts_offset) { gint64 prev_ts_offset; + GObjectClass *jb_class; + + jb_class = G_OBJECT_GET_CLASS (G_OBJECT (stream->buffer)); + + if (!g_object_class_find_property (jb_class, "ts-offset")) { + GST_LOG_OBJECT (bin, + "stream's jitterbuffer does not expose ts-offset property"); + return; + } g_object_get (stream->buffer, "ts-offset", &prev_ts_offset, NULL); @@ -1492,7 +1420,7 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len, /* For NTP sync we need to first get a snapshot of running_time and NTP * time. We know at what running_time we play a certain RTP time, we also * calculated when we would play the RTP time in the SR packet. Now we need - * to know how the running_time and the NTP time relate to eachother. */ + * to know how the running_time and the NTP time relate to each other. */ get_current_times (bin, &local_running_time, &local_ntpnstime); /* see how far away the NTP time is. This is the difference between the @@ -1533,9 +1461,9 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len, /* calculate the min of all deltas, ignoring streams that did not yet have a * valid rt_delta because we did not yet receive an SR packet for those * streams. - * We calculate the mininum because we would like to only apply positive + * We calculate the minimum because we would like to only apply positive * offsets to streams, delaying their playback instead of trying to speed up - * other streams (which might be imposible when we have to create negative + * other streams (which might be impossible when we have to create negative * latencies). * The stream that has the smallest diff is selected as the reference stream, * all other streams will have a positive offset to this difference. */ @@ -1548,7 +1476,7 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len, guint64 ext_base; use_rtp = TRUE; - /* signed version for convienience */ + /* signed version for convenience */ clock_base = base_rtptime; /* deal with possible wrap-around */ ext_base = base_rtptime; @@ -1799,78 +1727,138 @@ static GstRtpBinStream * create_stream (GstRtpBinSession * session, guint32 ssrc) { GstElement *buffer, *demux = NULL; +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + GstElement *queue2 = NULL; +#endif GstRtpBinStream *stream; GstRtpBin *rtpbin; GstState target; + GObjectClass *jb_class; rtpbin = session->bin; if (g_slist_length (session->streams) >= rtpbin->max_streams) goto max_streams; - if (!(buffer = gst_element_factory_make ("rtpjitterbuffer", NULL))) + if (!(buffer = + session_request_element (session, SIGNAL_REQUEST_JITTERBUFFER))) goto no_jitterbuffer; if (!rtpbin->ignore_pt) { if (!(demux = gst_element_factory_make ("rtpptdemux", NULL))) goto no_demux; } +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (rtpbin->use_rtsp_buffering && + rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) { + if (!(queue2 = gst_element_factory_make ("queue2", NULL))) + goto no_queue2; + } +#endif stream = g_new0 (GstRtpBinStream, 1); stream->ssrc = ssrc; stream->bin = rtpbin; stream->session = session; - stream->buffer = buffer; + stream->buffer = gst_object_ref (buffer); stream->demux = demux; stream->have_sync = FALSE; stream->rt_delta = 0; stream->rtp_delta = 0; stream->percent = 100; +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + stream->prev_percent = 0; +#endif stream->clock_base = -100 * GST_SECOND; session->streams = g_slist_prepend (session->streams, stream); - /* provide clock_rate to the jitterbuffer when needed */ - stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map", - (GCallback) pt_map_requested, session); - stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop", - (GCallback) on_npt_stop, stream); + jb_class = G_OBJECT_GET_CLASS (G_OBJECT (buffer)); + + if (g_signal_lookup ("request-pt-map", G_OBJECT_TYPE (buffer)) != 0) { + /* provide clock_rate to the jitterbuffer when needed */ + stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map", + (GCallback) pt_map_requested, session); + } + if (g_signal_lookup ("on-npt-stop", G_OBJECT_TYPE (buffer)) != 0) { + stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop", + (GCallback) on_npt_stop, stream); + } g_object_set_data (G_OBJECT (buffer), "GstRTPBin.session", session); g_object_set_data (G_OBJECT (buffer), "GstRTPBin.stream", stream); /* configure latency and packet lost */ g_object_set (buffer, "latency", rtpbin->latency_ms, NULL); - g_object_set (buffer, "drop-on-latency", rtpbin->drop_on_latency, NULL); - g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL); - g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL); - g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL); - g_object_set (buffer, "max-rtcp-rtp-time-diff", - rtpbin->max_rtcp_rtp_time_diff, NULL); - g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time, - "max-misorder-time", rtpbin->max_misorder_time, NULL); - g_object_set (buffer, "rfc7273-sync", rtpbin->rfc7273_sync, NULL); - g_object_set (buffer, "max-ts-offset-adjustment", - rtpbin->max_ts_offset_adjustment, NULL); + if (g_object_class_find_property (jb_class, "drop-on-latency")) + g_object_set (buffer, "drop-on-latency", rtpbin->drop_on_latency, NULL); + if (g_object_class_find_property (jb_class, "do-lost")) + g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL); + if (g_object_class_find_property (jb_class, "mode")) + g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL); + if (g_object_class_find_property (jb_class, "do-retransmission")) + g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL); + if (g_object_class_find_property (jb_class, "max-rtcp-rtp-time-diff")) + g_object_set (buffer, "max-rtcp-rtp-time-diff", + rtpbin->max_rtcp_rtp_time_diff, NULL); + if (g_object_class_find_property (jb_class, "max-dropout-time")) + g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time, NULL); + if (g_object_class_find_property (jb_class, "max-misorder-time")) + g_object_set (buffer, "max-misorder-time", rtpbin->max_misorder_time, NULL); + if (g_object_class_find_property (jb_class, "rfc7273-sync")) + g_object_set (buffer, "rfc7273-sync", rtpbin->rfc7273_sync, NULL); + if (g_object_class_find_property (jb_class, "max-ts-offset-adjustment")) + g_object_set (buffer, "max-ts-offset-adjustment", + rtpbin->max_ts_offset_adjustment, NULL); + +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + /* configure queue2 to use live buffering */ + if (queue2) { + g_object_set_data (G_OBJECT (queue2), "GstRTPBin.stream", stream); + g_object_set (queue2, "use-buffering", TRUE, NULL); + g_object_set (queue2, "buffer-mode", GST_BUFFERING_LIVE, NULL); + } +#endif g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0, buffer, session->id, ssrc); if (!rtpbin->ignore_pt) gst_bin_add (GST_BIN_CAST (rtpbin), demux); - gst_bin_add (GST_BIN_CAST (rtpbin), buffer); + +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (queue2) + gst_bin_add (GST_BIN_CAST (rtpbin), queue2); +#endif /* link stuff */ +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (queue2) { + gst_element_link_pads_full (buffer, "src", queue2, "sink", + GST_PAD_LINK_CHECK_NOTHING); + if (demux) { + gst_element_link_pads_full (queue2, "src", demux, "sink", + GST_PAD_LINK_CHECK_NOTHING); + } + } else if (demux) { + gst_element_link_pads_full (buffer, "src", demux, "sink", + GST_PAD_LINK_CHECK_NOTHING); + } +#else if (demux) gst_element_link_pads_full (buffer, "src", demux, "sink", GST_PAD_LINK_CHECK_NOTHING); +#endif if (rtpbin->buffering) { guint64 last_out; - GST_INFO_OBJECT (rtpbin, - "bin is buffering, set jitterbuffer as not active"); - g_signal_emit_by_name (buffer, "set-active", FALSE, (gint64) 0, &last_out); + if (g_signal_lookup ("set-active", G_OBJECT_TYPE (buffer)) != 0) { + GST_INFO_OBJECT (rtpbin, + "bin is buffering, set jitterbuffer as not active"); + g_signal_emit_by_name (buffer, "set-active", FALSE, (gint64) 0, + &last_out); + } } @@ -1884,12 +1872,17 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) gst_element_set_state (buffer, target); +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (queue2) + gst_element_set_state (queue2, target); +#endif + return stream; /* ERRORS */ max_streams: { - GST_WARNING_OBJECT (rtpbin, "stream exeeds maximum (%d)", + GST_WARNING_OBJECT (rtpbin, "stream exceeds maximum (%d)", rtpbin->max_streams); return NULL; } @@ -1904,39 +1897,52 @@ no_demux: g_warning ("rtpbin: could not create rtpptdemux element"); return NULL; } +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION +no_queue2: + { + gst_object_unref (buffer); + gst_object_unref (demux); + g_warning ("rtpbin: could not create queue2 element"); + return NULL; + } +#endif } /* called with RTP_BIN_LOCK */ static void free_stream (GstRtpBinStream * stream, GstRtpBin * bin) { + GstRtpBinSession *sess = stream->session; GSList *clients, *next_client; GST_DEBUG_OBJECT (bin, "freeing stream %p", stream); - if (stream->demux) { - 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->demux, stream->demux_ptchange_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_locked_state (stream->buffer, TRUE); if (stream->demux) gst_element_set_locked_state (stream->demux, TRUE); - gst_element_set_locked_state (stream->buffer, TRUE); + gst_element_set_state (stream->buffer, GST_STATE_NULL); if (stream->demux) gst_element_set_state (stream->demux, GST_STATE_NULL); - gst_element_set_state (stream->buffer, GST_STATE_NULL); - /* now remove this signal, we need this while going to NULL because it to - * do some cleanups */ - if (stream->demux) + if (stream->demux) { + 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->demux, stream->demux_ptchange_sig); g_signal_handler_disconnect (stream->demux, stream->demux_padremoved_sig); + } + + if (stream->buffer_handlesync_sig) + g_signal_handler_disconnect (stream->buffer, stream->buffer_handlesync_sig); + if (stream->buffer_ptreq_sig) + g_signal_handler_disconnect (stream->buffer, stream->buffer_ptreq_sig); + if (stream->buffer_ntpstop_sig) + g_signal_handler_disconnect (stream->buffer, stream->buffer_ntpstop_sig); + + sess->elements = g_slist_remove (sess->elements, stream->buffer); + remove_bin_element (stream->buffer, bin); + gst_object_unref (stream->buffer); - gst_bin_remove (GST_BIN_CAST (bin), stream->buffer); if (stream->demux) gst_bin_remove (GST_BIN_CAST (bin), stream->demux); @@ -1983,7 +1989,7 @@ static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad); static void gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message); #define gst_rtp_bin_parent_class parent_class -G_DEFINE_TYPE (GstRtpBin, gst_rtp_bin, GST_TYPE_BIN); +G_DEFINE_TYPE_WITH_PRIVATE (GstRtpBin, gst_rtp_bin, GST_TYPE_BIN); static gboolean _gst_element_accumulator (GSignalInvocationHint * ihint, @@ -2028,8 +2034,6 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gstelement_class = (GstElementClass *) klass; gstbin_class = (GstBinClass *) klass; - g_type_class_add_private (klass, sizeof (GstRtpBinPrivate)); - gobject_class->dispose = gst_rtp_bin_dispose; gobject_class->finalize = gst_rtp_bin_finalize; gobject_class->set_property = gst_rtp_bin_set_property; @@ -2058,8 +2062,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] = g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_pt_map), - _gst_caps_accumulator, NULL, g_cclosure_marshal_generic, GST_TYPE_CAPS, - 2, G_TYPE_UINT, G_TYPE_UINT); + _gst_caps_accumulator, NULL, NULL, GST_TYPE_CAPS, 2, G_TYPE_UINT, + G_TYPE_UINT); /** * GstRtpBin::payload-type-change: @@ -2072,8 +2076,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] = g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, payload_type_change), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::clear-pt-map: @@ -2085,8 +2088,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] = g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, - 0, G_TYPE_NONE); + clear_pt_map), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); /** * GstRtpBin::reset-sync: @@ -2098,8 +2100,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_RESET_SYNC] = g_signal_new ("reset-sync", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - reset_sync), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, - 0, G_TYPE_NONE); + reset_sync), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); /** * GstRtpBin::get-session: @@ -2113,8 +2114,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_GET_SESSION] = g_signal_new ("get-session", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - get_session), NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + get_session), NULL, NULL, NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::get-internal-session: @@ -2126,38 +2126,40 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_SESSION] = g_signal_new ("get-internal-session", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - get_internal_session), NULL, NULL, g_cclosure_marshal_generic, - RTP_TYPE_SESSION, 1, G_TYPE_UINT); + get_internal_session), NULL, NULL, NULL, RTP_TYPE_SESSION, 1, + G_TYPE_UINT); /** * GstRtpBin::get-internal-storage: * @rtpbin: the object which received the signal * @id: the session id * - * Request the internal RTPStorage object as #GObject in session @id. + * Request the internal RTPStorage object as #GObject in session @id. This + * is the internal storage used by the RTPStorage element, which is used to + * keep a backlog of received RTP packets for the session @id. * * Since: 1.14 */ gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_STORAGE] = g_signal_new ("get-internal-storage", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - get_internal_storage), NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_OBJECT, 1, G_TYPE_UINT); + get_internal_storage), NULL, NULL, NULL, G_TYPE_OBJECT, 1, + G_TYPE_UINT); /** * GstRtpBin::get-storage: * @rtpbin: the object which received the signal * @id: the session id * - * Request the RTPStorage element as #GObject in session @id. + * Request the RTPStorage element as #GObject in session @id. This element + * is used to keep a backlog of received RTP packets for the session @id. * * Since: 1.16 */ gst_rtp_bin_signals[SIGNAL_GET_STORAGE] = g_signal_new ("get-storage", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, - get_storage), NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + get_storage), NULL, NULL, NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::on-new-ssrc: @@ -2170,8 +2172,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC] = g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_ssrc), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-ssrc-collision: * @rtpbin: the object which received the signal @@ -2183,8 +2184,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION] = g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_collision), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-ssrc-validated: * @rtpbin: the object which received the signal @@ -2196,8 +2196,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED] = g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_validated), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-ssrc-active: * @rtpbin: the object which received the signal @@ -2209,8 +2208,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE] = g_signal_new ("on-ssrc-active", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_active), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-ssrc-sdes: * @rtpbin: the object which received the signal @@ -2222,8 +2220,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES] = g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_sdes), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-bye-ssrc: @@ -2236,8 +2233,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC] = g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_ssrc), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-bye-timeout: * @rtpbin: the object which received the signal @@ -2249,8 +2245,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT] = g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_timeout), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-timeout: * @rtpbin: the object which received the signal @@ -2262,8 +2257,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT] = g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_timeout), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-sender-timeout: * @rtpbin: the object which received the signal @@ -2275,8 +2269,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT] = g_signal_new ("on-sender-timeout", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_sender_timeout), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-npt-stop: @@ -2289,8 +2282,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP] = g_signal_new ("on-npt-stop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_npt_stop), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::request-rtp-encoder: @@ -2307,8 +2299,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_ENCODER] = g_signal_new ("request-rtp-encoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_rtp_encoder), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_rtp_encoder), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-rtp-decoder: @@ -2326,7 +2318,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) g_signal_new ("request-rtp-decoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_rtp_decoder), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-rtcp-encoder: @@ -2343,8 +2335,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_ENCODER] = g_signal_new ("request-rtcp-encoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_rtcp_encoder), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_rtcp_encoder), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-rtcp-decoder: @@ -2361,7 +2353,35 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_DECODER] = g_signal_new ("request-rtcp-decoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_rtcp_decoder), _gst_element_accumulator, NULL, + request_rtcp_decoder), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + + /** + * GstRtpBin::request-jitterbuffer: + * @rtpbin: the object which received the signal + * @session: the session + * + * Request a jitterbuffer element for the given @session. + * + * If no handler is connected, the default jitterbuffer will be used. + * + * Note: The provided element is expected to conform to the API exposed + * by the standard #GstRtpJitterBuffer. Runtime checks will be made to + * determine whether it exposes properties and signals before attempting + * to set, call or connect to them, and some functionalities of #GstRtpBin + * may not be available when that is not the case. + * + * This should be considered experimental API, as the standard jitterbuffer + * API is susceptible to change, provided elements will have to update their + * custom jitterbuffer's API to match the API of #GstRtpJitterBuffer if and + * when it changes. + * + * Since: 1.18 + */ + gst_rtp_bin_signals[SIGNAL_REQUEST_JITTERBUFFER] = + g_signal_new ("request-jitterbuffer", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, + request_jitterbuffer), _gst_element_accumulator, NULL, g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** @@ -2379,7 +2399,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER] = g_signal_new ("new-jitterbuffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - new_jitterbuffer), NULL, NULL, g_cclosure_marshal_generic, + new_jitterbuffer), NULL, NULL, NULL, G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT); /** @@ -2396,7 +2416,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_NEW_STORAGE] = g_signal_new ("new-storage", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - new_storage), NULL, NULL, g_cclosure_marshal_generic, + new_storage), NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_ELEMENT, G_TYPE_UINT); /** @@ -2414,8 +2434,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_SENDER] = g_signal_new ("request-aux-sender", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_aux_sender), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_aux_sender), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-aux-receiver: @@ -2432,8 +2452,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_RECEIVER] = g_signal_new ("request-aux-receiver", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_aux_receiver), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_aux_receiver), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-fec-decoder: @@ -2450,8 +2470,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_FEC_DECODER] = g_signal_new ("request-fec-decoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_fec_decoder), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_fec_decoder), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::request-fec-encoder: @@ -2468,8 +2488,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_REQUEST_FEC_ENCODER] = g_signal_new ("request-fec-encoder", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - request_fec_encoder), _gst_element_accumulator, NULL, - g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT); + request_fec_encoder), _gst_element_accumulator, NULL, NULL, + GST_TYPE_ELEMENT, 1, G_TYPE_UINT); /** * GstRtpBin::on-new-sender-ssrc: @@ -2484,8 +2504,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_NEW_SENDER_SSRC] = g_signal_new ("on-new-sender-ssrc", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_sender_ssrc), - NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_UINT); + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * GstRtpBin::on-sender-ssrc-active: * @rtpbin: the object which received the signal @@ -2499,36 +2518,18 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_bin_signals[SIGNAL_ON_SENDER_SSRC_ACTIVE] = g_signal_new ("on-sender-ssrc-active", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - on_sender_ssrc_active), NULL, NULL, g_cclosure_marshal_generic, + on_sender_ssrc_active), NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - /** - * GstRtpBin::on-bundled-ssrc: - * @rtpbin: the object which received the signal - * @ssrc: the bundled SSRC - * - * Notify of a new incoming bundled SSRC. If no handler is connected to the - * signal then the #GstRtpSession created for the recv_rtp_sink_\%u - * request pad will be managing this new SSRC. However if there is a handler - * connected then the application can decided to dispatch this new stream to - * another session by providing its ID as return value of the handler. This - * can be particularly useful to keep retransmission SSRCs grouped with the - * session for which they handle retransmission. - * - * Since: 1.12 - */ - gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC] = - g_signal_new ("on-bundled-ssrc", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, - on_bundled_ssrc), NULL, NULL, - g_cclosure_marshal_generic, G_TYPE_UINT, 1, G_TYPE_UINT); - - g_object_class_install_property (gobject_class, PROP_SDES, g_param_spec_boxed ("sdes", "SDES", "The SDES items of this session", - GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS +#ifndef TIZEN_FEATURE_GST_UPSTREAM_AVOID_BUILD_BREAK + | GST_PARAM_DOC_SHOW_DEFAULT)); +#else + )); +#endif g_object_class_install_property (gobject_class, PROP_DO_LOST, g_param_spec_boolean ("do-lost", "Do Lost", @@ -2606,7 +2607,7 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) * * Enables RTP retransmission on all streams. To control retransmission on * a per-SSRC basis, connect to the #GstRtpBin::new-jitterbuffer signal and - * set the #GstRtpJitterBuffer::do-retransmission property on the + * set the #GstRtpJitterBuffer:do-retransmission property on the * #GstRtpJitterBuffer object instead. */ g_object_class_install_property (gobject_class, PROP_DO_RETRANSMISSION, @@ -2705,6 +2706,14 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) "changed to 0 (no limit)", 0, G_MAXINT64, DEFAULT_MAX_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + g_object_class_install_property (gobject_class, PROP_USE_RTSP_BUFFERING, + g_param_spec_boolean ("use-rtsp-buffering", "Use RTSP buffering", + "Use RTSP buffering in RTP_JITTER_BUFFER_MODE_SLAVE buffer mode", + DEFAULT_RTSP_USE_BUFFERING, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state); gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad); @@ -2745,8 +2754,14 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) klass->request_rtp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder); klass->request_rtcp_encoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_encoder); klass->request_rtcp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder); + klass->request_jitterbuffer = + GST_DEBUG_FUNCPTR (gst_rtp_bin_request_jitterbuffer); GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin"); + +#ifndef TIZEN_FEATURE_GST_UPSTREAM_AVOID_BUILD_BREAK + gst_type_mark_as_plugin_api (GST_RTP_BIN_RTCP_SYNC_TYPE, 0); +#endif } static void @@ -2754,7 +2769,7 @@ gst_rtp_bin_init (GstRtpBin * rtpbin) { gchar *cname; - rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin); + rtpbin->priv = gst_rtp_bin_get_instance_private (rtpbin); g_mutex_init (&rtpbin->priv->bin_lock); g_mutex_init (&rtpbin->priv->dyn_lock); @@ -2782,6 +2797,9 @@ gst_rtp_bin_init (GstRtpBin * rtpbin) rtpbin->max_ts_offset_adjustment = DEFAULT_MAX_TS_OFFSET_ADJUSTMENT; rtpbin->max_ts_offset = DEFAULT_MAX_TS_OFFSET; rtpbin->max_ts_offset_is_set = FALSE; +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + rtpbin->use_rtsp_buffering = FALSE; +#endif /* some default SDES entries */ cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ()); @@ -2870,6 +2888,13 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id, rtpbin = GST_RTP_BIN (object); switch (prop_id) { +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + case PROP_USE_RTSP_BUFFERING: + GST_RTP_BIN_LOCK (rtpbin); + rtpbin->use_rtsp_buffering = g_value_get_boolean (value); + GST_RTP_BIN_UNLOCK (rtpbin); + break; +#endif case PROP_LATENCY: GST_RTP_BIN_LOCK (rtpbin); rtpbin->latency_ms = g_value_get_uint (value); @@ -3039,6 +3064,13 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id, rtpbin = GST_RTP_BIN (object); switch (prop_id) { +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + case PROP_USE_RTSP_BUFFERING: + GST_RTP_BIN_LOCK (rtpbin); + g_value_set_boolean (value, rtpbin->use_rtsp_buffering); + GST_RTP_BIN_UNLOCK (rtpbin); + break; +#endif case PROP_LATENCY: GST_RTP_BIN_LOCK (rtpbin); g_value_set_uint (value, rtpbin->latency_ms); @@ -3160,6 +3192,9 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) gint min_percent = 100; GSList *sessions, *streams; GstRtpBinStream *stream; +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + gboolean buffering_flag = FALSE, update_buffering_status = TRUE; +#endif gboolean change = FALSE, active = FALSE; GstClockTime min_out_time; GstBufferingMode mode; @@ -3193,9 +3228,54 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) streams = g_slist_next (streams)) { GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (rtpbin->use_rtsp_buffering && + rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) { + GstPad *temp_pad_src = NULL; + GstCaps *temp_caps_src = NULL; + GstStructure *caps_structure; + const gchar *caps_str_media = NULL; + temp_pad_src = gst_element_get_static_pad (stream->buffer, "src"); + temp_caps_src = gst_pad_get_current_caps (temp_pad_src); + GST_DEBUG_OBJECT (bin, + "stream %p percent %d : temp_caps_src=%" GST_PTR_FORMAT, + stream, stream->percent, temp_caps_src); + if (temp_caps_src) { + caps_structure = gst_caps_get_structure (temp_caps_src, 0); + caps_str_media = + gst_structure_get_string (caps_structure, "media"); + if (caps_str_media != NULL) { + if ((strcmp (caps_str_media, "video") != 0) + && (strcmp (caps_str_media, "audio") != 0)) { + GST_DEBUG_OBJECT (bin, + "Non Audio/Video Stream.. ignoring the same !!"); + gst_caps_unref (temp_caps_src); + gst_object_unref (temp_pad_src); + continue; + } else if (stream->percent >= 100) { + /* Most of the time buffering icon displays in rtsp playback. + Optimizing the buffering updation code. Whenever any stream percentage + reaches 100 do not post buffering messages. */ + if (stream->prev_percent < 100) + buffering_flag = TRUE; + else + update_buffering_status = FALSE; + } + } + gst_caps_unref (temp_caps_src); + } + gst_object_unref (temp_pad_src); + /* Updating prev stream percentage */ + stream->prev_percent = stream->percent; + } else { + GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream, + stream->percent); + } +#else GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream, stream->percent); +#endif /* find min percent */ if (min_percent > stream->percent) min_percent = stream->percent; @@ -3209,6 +3289,10 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) } GST_DEBUG_OBJECT (bin, "min percent %d", min_percent); +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (!(rtpbin->use_rtsp_buffering && + rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE)) { +#endif if (rtpbin->buffering) { if (min_percent == 100) { rtpbin->buffering = FALSE; @@ -3223,16 +3307,35 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) change = TRUE; } } +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + } +#endif GST_RTP_BIN_UNLOCK (rtpbin); gst_message_unref (message); +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (rtpbin->use_rtsp_buffering && + rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) { + if (update_buffering_status == FALSE) + break; + if (buffering_flag) { + min_percent = 100; + GST_DEBUG_OBJECT (bin, "forcefully change min_percent to 100!!!"); + } + } +#endif /* make a new buffering message with the min value */ message = gst_message_new_buffering (GST_OBJECT_CAST (bin), min_percent); gst_message_set_buffering_stats (message, mode, avg_in, avg_out, buffering_left); +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION + if (rtpbin->use_rtsp_buffering && + rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) + goto slave_buffering; +#endif if (G_UNLIKELY (change)) { GstClock *clock; guint64 running_time = 0; @@ -3278,10 +3381,12 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) streams = g_slist_next (streams)) { GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; GstElement *element = stream->buffer; - guint64 last_out; + guint64 last_out = -1; - g_signal_emit_by_name (element, "set-active", active, offset, - &last_out); + if (g_signal_lookup ("set-active", G_OBJECT_TYPE (element)) != 0) { + g_signal_emit_by_name (element, "set-active", active, offset, + &last_out); + } if (!active) { g_object_get (element, "percent", &stream->percent, NULL); @@ -3310,6 +3415,9 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message) GST_RTP_BIN_UNLOCK (rtpbin); } } +#ifdef TIZEN_FEATURE_RTSP_MODIFICATION +slave_buffering: +#endif GST_BIN_CLASS (parent_class)->handle_message (bin, message); break; } @@ -3402,23 +3510,16 @@ copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) return TRUE; } -/* a new pad (SSRC) was created in @session. This signal is emitted from the - * payload demuxer. */ static void -new_payload_found (GstElement * element, guint pt, GstPad * pad, - GstRtpBinStream * stream) +expose_recv_src_pad (GstRtpBin * rtpbin, GstPad * pad, GstRtpBinStream * stream, + guint8 pt) { - GstRtpBin *rtpbin; GstElementClass *klass; GstPadTemplate *templ; gchar *padname; GstPad *gpad; - rtpbin = stream->bin; - - GST_DEBUG_OBJECT (rtpbin, "new payload pad %u", pt); - - pad = gst_object_ref (pad); + gst_object_ref (pad); if (stream->session->storage) { GstElement *fec_decoder = @@ -3497,6 +3598,21 @@ fec_decoder_link_failed: } } +/* a new pad (SSRC) was created in @session. This signal is emitted from the + * payload demuxer. */ +static void +new_payload_found (GstElement * element, guint pt, GstPad * pad, + GstRtpBinStream * stream) +{ + GstRtpBin *rtpbin; + + rtpbin = stream->bin; + + GST_DEBUG_OBJECT (rtpbin, "new payload pad %u", pt); + + expose_recv_src_pad (rtpbin, pad, stream, pt); +} + static void payload_pad_removed (GstElement * element, GstPad * pad, GstRtpBinStream * stream) @@ -3577,7 +3693,7 @@ static void payload_type_change (GstElement * element, guint pt, GstRtpBinSession * session) { GST_DEBUG_OBJECT (session->bin, - "emiting signal for pt type changed to %u in session %u", pt, + "emitting signal for pt type changed to %u in session %u", pt, session->id); g_signal_emit (session->bin, gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE], @@ -3650,19 +3766,23 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad, gst_object_unref (sinkpad); gst_object_unref (srcpad); - GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTCP"); - padname = g_strdup_printf ("rtcp_src_%u", ssrc); - srcpad = gst_element_get_static_pad (element, padname); - g_free (padname); sinkpad = gst_element_get_request_pad (stream->buffer, "sink_rtcp"); - gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING); - gst_object_unref (sinkpad); - gst_object_unref (srcpad); + if (sinkpad) { + GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTCP"); + padname = g_strdup_printf ("rtcp_src_%u", ssrc); + srcpad = gst_element_get_static_pad (element, padname); + g_free (padname); + gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + } - /* connect to the RTCP sync signal from the jitterbuffer */ - GST_DEBUG_OBJECT (rtpbin, "connecting sync signal"); - stream->buffer_handlesync_sig = g_signal_connect (stream->buffer, - "handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream); + if (g_signal_lookup ("handle-sync", G_OBJECT_TYPE (stream->buffer)) != 0) { + /* connect to the RTCP sync signal from the jitterbuffer */ + GST_DEBUG_OBJECT (rtpbin, "connecting sync signal"); + stream->buffer_handlesync_sig = g_signal_connect (stream->buffer, + "handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream); + } if (stream->demux) { /* connect to the new-pad signal of the payload demuxer, this will expose the @@ -3680,33 +3800,23 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad, /* connect to the signal so it can be forwarded. */ stream->demux_ptchange_sig = g_signal_connect (stream->demux, "payload-type-change", (GCallback) payload_type_change, session); + + GST_RTP_SESSION_UNLOCK (session); + GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin); } else { /* add rtpjitterbuffer src pad to pads */ - GstElementClass *klass; - GstPadTemplate *templ; - gchar *padname; - GstPad *gpad, *pad; + GstPad *pad; pad = gst_element_get_static_pad (stream->buffer, "src"); - /* ghost the pad to the parent */ - klass = GST_ELEMENT_GET_CLASS (rtpbin); - templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u"); - padname = g_strdup_printf ("recv_rtp_src_%u_%u_%u", - stream->session->id, stream->ssrc, 255); - gpad = gst_ghost_pad_new_from_template (padname, pad, templ); - g_free (padname); + GST_RTP_SESSION_UNLOCK (session); + GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin); - gst_pad_set_active (gpad, TRUE); - gst_pad_sticky_events_foreach (pad, copy_sticky_events, gpad); - gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad); + expose_recv_src_pad (rtpbin, pad, stream, 255); gst_object_unref (pad); } - GST_RTP_SESSION_UNLOCK (session); - GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin); - return; /* ERRORS */ @@ -3724,39 +3834,11 @@ no_stream: } } -static void -session_maybe_create_bundle_demuxer (GstRtpBinSession * session) -{ - GstRtpBin *rtpbin; - - if (session->bundle_demux) - return; - - rtpbin = session->bin; - if (g_signal_has_handler_pending (rtpbin, - gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC], 0, TRUE)) { - GST_DEBUG_OBJECT (rtpbin, "Adding a bundle SSRC demuxer to session %u", - session->id); - session->bundle_demux = gst_element_factory_make ("rtpssrcdemux", NULL); - session->bundle_demux_newpad_sig = g_signal_connect (session->bundle_demux, - "new-ssrc-pad", (GCallback) new_bundled_ssrc_pad_found, session); - - gst_bin_add (GST_BIN_CAST (rtpbin), session->bundle_demux); - gst_element_sync_state_with_parent (session->bundle_demux); - } else { - GST_DEBUG_OBJECT (rtpbin, - "No handler for the on-bundled-ssrc signal so no need for a bundle SSRC demuxer in session %u", - session->id); - } -} - static GstPad * -complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session, - gboolean bundle_demuxer_needed) +complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session) { guint sessid = session->id; GstPad *recv_rtp_sink; - GstPad *funnel_src; GstElement *decoder; g_assert (!session->recv_rtp_sink); @@ -3770,9 +3852,6 @@ complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session, g_signal_connect (session->recv_rtp_sink, "notify::caps", (GCallback) caps_changed, session); - if (bundle_demuxer_needed) - session_maybe_create_bundle_demuxer (session); - GST_DEBUG_OBJECT (rtpbin, "requesting RTP decoder"); decoder = session_request_element (session, SIGNAL_REQUEST_RTP_DECODER); if (decoder) { @@ -3790,14 +3869,8 @@ complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session, if (decsrc == NULL) goto dec_src_failed; - if (session->bundle_demux) { - GstPad *demux_sink; - demux_sink = gst_element_get_static_pad (session->bundle_demux, "sink"); - ret = gst_pad_link (decsrc, demux_sink); - gst_object_unref (demux_sink); - } else { - ret = gst_pad_link (decsrc, session->recv_rtp_sink); - } + ret = gst_pad_link (decsrc, session->recv_rtp_sink); + gst_object_unref (decsrc); if (ret != GST_PAD_LINK_OK) @@ -3805,19 +3878,9 @@ complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session, } else { GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given"); - if (session->bundle_demux) { - recv_rtp_sink = - gst_element_get_static_pad (session->bundle_demux, "sink"); - } else { - recv_rtp_sink = - gst_element_get_request_pad (session->rtp_funnel, "sink_%u"); - } + recv_rtp_sink = gst_object_ref (session->recv_rtp_sink); } - funnel_src = gst_element_get_static_pad (session->rtp_funnel, "src"); - gst_pad_link (funnel_src, session->recv_rtp_sink); - gst_object_unref (funnel_src); - return recv_rtp_sink; /* ERRORS */ @@ -3975,11 +4038,10 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) return session->recv_rtp_sink_ghost; /* setup the session sink pad */ - recv_rtp_sink = complete_session_sink (rtpbin, session, TRUE); + recv_rtp_sink = complete_session_sink (rtpbin, session); if (!recv_rtp_sink) goto session_sink_failed; - GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad"); session->recv_rtp_sink_ghost = gst_ghost_pad_new_from_template (name, recv_rtp_sink, templ); @@ -3994,7 +4056,8 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) /* ERRORS */ no_name: { - g_warning ("rtpbin: invalid name given"); + g_warning ("rtpbin: cannot find session id for pad: %s", + GST_STR_NULL (name)); return NULL; } create_error: @@ -4020,11 +4083,6 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) g_signal_handler_disconnect (session->demux, session->demux_padremoved_sig); session->demux_padremoved_sig = 0; } - if (session->bundle_demux_newpad_sig) { - g_signal_handler_disconnect (session->bundle_demux, - session->bundle_demux_newpad_sig); - session->bundle_demux_newpad_sig = 0; - } if (session->recv_rtp_src) { gst_object_unref (session->recv_rtp_src); session->recv_rtp_src = NULL; @@ -4044,12 +4102,11 @@ remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session) static GstPad * complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, - guint sessid, gboolean bundle_demuxer_needed) + guint sessid) { GstElement *decoder; GstPad *sinkdpad; GstPad *decsink = NULL; - GstPad *funnel_src; /* get recv_rtp pad and store */ GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad"); @@ -4058,9 +4115,6 @@ complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, if (session->recv_rtcp_sink == NULL) goto pad_failed; - if (bundle_demuxer_needed) - session_maybe_create_bundle_demuxer (session); - GST_DEBUG_OBJECT (rtpbin, "getting RTCP decoder"); decoder = session_request_element (session, SIGNAL_REQUEST_RTCP_DECODER); if (decoder) { @@ -4077,26 +4131,15 @@ complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, if (decsrc == NULL) goto dec_src_failed; - if (session->bundle_demux) { - GstPad *demux_sink; - demux_sink = - gst_element_get_static_pad (session->bundle_demux, "rtcp_sink"); - ret = gst_pad_link (decsrc, demux_sink); - gst_object_unref (demux_sink); - } else { - ret = gst_pad_link (decsrc, session->recv_rtcp_sink); - } + ret = gst_pad_link (decsrc, session->recv_rtcp_sink); + gst_object_unref (decsrc); if (ret != GST_PAD_LINK_OK) goto dec_link_failed; } else { GST_DEBUG_OBJECT (rtpbin, "no RTCP decoder given"); - if (session->bundle_demux) { - decsink = gst_element_get_static_pad (session->bundle_demux, "rtcp_sink"); - } else { - decsink = gst_element_get_request_pad (session->rtcp_funnel, "sink_%u"); - } + decsink = gst_object_ref (session->recv_rtcp_sink); } /* get srcpad, link to SSRCDemux */ @@ -4110,10 +4153,6 @@ complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session, gst_pad_link_full (session->sync_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref (sinkdpad); - funnel_src = gst_element_get_static_pad (session->rtcp_funnel, "src"); - gst_pad_link (funnel_src, session->recv_rtcp_sink); - gst_object_unref (funnel_src); - return decsink; pad_failed: @@ -4177,7 +4216,7 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, if (session->recv_rtcp_sink_ghost != NULL) return session->recv_rtcp_sink_ghost; - decsink = complete_session_rtcp (rtpbin, session, sessid, TRUE); + decsink = complete_session_rtcp (rtpbin, session, sessid); if (!decsink) goto create_error; @@ -4193,7 +4232,8 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, /* ERRORS */ no_name: { - g_warning ("rtpbin: invalid name given"); + g_warning ("rtpbin: cannot find session id for pad: %s", + GST_STR_NULL (name)); return NULL; } create_error: @@ -4376,8 +4416,9 @@ create_error: } existing_session: { - g_warning ("rtpbin: session %u is already a sender", sessid); - return FALSE; + GST_DEBUG_OBJECT (rtpbin, + "skipping src_%i setup, since it is already configured.", sessid); + return TRUE; } pad_failed: { @@ -4521,7 +4562,8 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name) /* ERRORS */ no_name: { - g_warning ("rtpbin: invalid name given"); + g_warning ("rtpbin: cannot find session id for pad: %s", + GST_STR_NULL (name)); return NULL; } create_error: @@ -4675,7 +4717,8 @@ create_send_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, /* ERRORS */ no_name: { - g_warning ("rtpbin: invalid name given"); + g_warning ("rtpbin: cannot find session id for pad: %s", + GST_STR_NULL (name)); return NULL; } create_error: @@ -4724,7 +4767,7 @@ remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session) } /* If the requested name is NULL we should create a name with - * the session number assuming we want the lowest posible session + * the session number assuming we want the lowest possible session * with a free pad like the template */ static gchar * gst_rtp_bin_get_free_pad_name (GstElement * element, GstPadTemplate * templ)