2 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * SECTION:element-rtpbin
22 * @see_also: rtpjitterbuffer, rtpsession, rtpptdemux, rtpssrcdemux
24 * RTP bin combines the functions of #GstRtpSession, #GstRtpSsrcDemux,
25 * #GstRtpJitterBuffer and #GstRtpPtDemux in one element. It allows for multiple
26 * RTP sessions that will be synchronized together using RTCP SR packets.
28 * #GstRtpBin is configured with a number of request pads that define the
29 * functionality that is activated, similar to the #GstRtpSession element.
31 * To use #GstRtpBin as an RTP receiver, request a recv_rtp_sink_\%u pad. The session
32 * number must be specified in the pad name.
33 * Data received on the recv_rtp_sink_\%u pad will be processed in the #GstRtpSession
34 * manager and after being validated forwarded on #GstRtpSsrcDemux element. Each
35 * RTP stream is demuxed based on the SSRC and send to a #GstRtpJitterBuffer. After
36 * the packets are released from the jitterbuffer, they will be forwarded to a
37 * #GstRtpPtDemux element. The #GstRtpPtDemux element will demux the packets based
38 * on the payload type and will create a unique pad recv_rtp_src_\%u_\%u_\%u on
39 * rtpbin with the session number, SSRC and payload type respectively as the pad
42 * To also use #GstRtpBin as an RTCP receiver, request a recv_rtcp_sink_\%u pad. The
43 * session number must be specified in the pad name.
45 * If you want the session manager to generate and send RTCP packets, request
46 * the send_rtcp_src_\%u pad with the session number in the pad name. Packet pushed
47 * on this pad contain SR/RR RTCP reports that should be sent to all participants
50 * To use #GstRtpBin as a sender, request a send_rtp_sink_\%u pad, which will
51 * automatically create a send_rtp_src_\%u pad. If the session number is not provided,
52 * the pad from the lowest available session will be returned. The session manager will modify the
53 * SSRC in the RTP packets to its own SSRC and wil forward the packets on the
54 * send_rtp_src_\%u pad after updating its internal state.
56 * #GstRtpBin can also demultiplex incoming bundled streams. The first
57 * #GstRtpSession will have a #GstRtpSsrcDemux element splitting the streams
58 * based on their SSRC and potentially dispatched to a different #GstRtpSession.
59 * Because retransmission SSRCs need to be merged with the corresponding media
60 * stream the #GstRtpBin::on-bundled-ssrc signal is emitted so that the
61 * application can find out to which session the SSRC belongs.
63 * The session manager needs the clock-rate of the payload types it is handling
64 * and will signal the #GstRtpSession::request-pt-map signal when it needs such a
65 * mapping. One can clear the cached values with the #GstRtpSession::clear-pt-map
68 * Access to the internal statistics of rtpbin is provided with the
69 * get-internal-session property. This action signal gives access to the
70 * RTPSession object which further provides action signals to retrieve the
71 * internal source and other sources.
73 * #GstRtpBin also has signals (#GstRtpBin::request-rtp-encoder,
74 * #GstRtpBin::request-rtp-decoder, #GstRtpBin::request-rtcp-encoder and
75 * #GstRtpBin::request-rtp-decoder) to dynamically request for RTP and RTCP encoders
76 * and decoders in order to support SRTP. The encoders must provide the pads
77 * rtp_sink_\%u and rtp_src_\%u for RTP and rtcp_sink_\%u and rtcp_src_\%u for
78 * RTCP. The session number will be used in the pad name. The decoders must provide
79 * rtp_sink and rtp_src for RTP and rtcp_sink and rtcp_src for RTCP. The decoders will
80 * be placed before the #GstRtpSession element, thus they must support SSRC demuxing
83 * #GstRtpBin has signals (#GstRtpBin::request-aux-sender and
84 * #GstRtpBin::request-aux-receiver to dynamically request an element that can be
85 * used to create or merge additional RTP streams. AUX elements are needed to
86 * implement FEC or retransmission (such as RFC 4588). An AUX sender must have one
87 * sink_\%u pad that matches the sessionid in the signal and it should have 1 or
88 * more src_\%u pads. For each src_%\u pad, a session will be made (if needed)
89 * and the pad will be linked to the session send_rtp_sink pad. Each session will
90 * then expose its source pad as send_rtp_src_\%u on #GstRtpBin.
91 * An AUX receiver has 1 src_\%u pad that much match the sessionid in the signal
92 * and 1 or more sink_\%u pads. A session will be made for each sink_\%u pad
93 * when the corresponding recv_rtp_sink_\%u pad is requested on #GstRtpBin.
96 * <title>Example pipelines</title>
98 * gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \
99 * rtpbin ! rtptheoradepay ! theoradec ! xvimagesink
100 * ]| Receive RTP data from port 5000 and send to the session 0 in rtpbin.
102 * gst-launch-1.0 rtpbin name=rtpbin \
103 * v4l2src ! videoconvert ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
104 * rtpbin.send_rtp_src_0 ! udpsink port=5000 \
105 * rtpbin.send_rtcp_src_0 ! udpsink port=5001 sync=false async=false \
106 * udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0 \
107 * audiotestsrc ! amrnbenc ! rtpamrpay ! rtpbin.send_rtp_sink_1 \
108 * rtpbin.send_rtp_src_1 ! udpsink port=5002 \
109 * rtpbin.send_rtcp_src_1 ! udpsink port=5003 sync=false async=false \
110 * udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1
111 * ]| Encode and payload H263 video captured from a v4l2src. Encode and payload AMR
112 * audio generated from audiotestsrc. The video is sent to session 0 in rtpbin
113 * and the audio is sent to session 1. Video packets are sent on UDP port 5000
114 * and audio packets on port 5002. The video RTCP packets for session 0 are sent
115 * on port 5001 and the audio RTCP packets for session 0 are sent on port 5003.
116 * RTCP packets for session 0 are received on port 5005 and RTCP for session 1
117 * is received on port 5007. Since RTCP packets from the sender should be sent
118 * as soon as possible and do not participate in preroll, sync=false and
119 * async=false is configured on udpsink
121 * gst-launch-1.0 -v rtpbin name=rtpbin \
122 * udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263-1998" \
123 * port=5000 ! rtpbin.recv_rtp_sink_0 \
124 * rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink \
125 * udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0 \
126 * rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false \
127 * udpsrc caps="application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1" \
128 * port=5002 ! rtpbin.recv_rtp_sink_1 \
129 * rtpbin. ! rtpamrdepay ! amrnbdec ! alsasink \
130 * udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1 \
131 * rtpbin.send_rtcp_src_1 ! udpsink port=5007 sync=false async=false
132 * ]| Receive H263 on port 5000, send it through rtpbin in session 0, depayload,
133 * decode and display the video.
134 * Receive AMR on port 5002, send it through rtpbin in session 1, depayload,
135 * decode and play the audio.
136 * Receive server RTCP packets for session 0 on port 5001 and RTCP packets for
137 * session 1 on port 5003. These packets will be used for session management and
139 * Send RTCP reports for session 0 on port 5005 and RTCP reports for session 1
150 #include <gst/rtp/gstrtpbuffer.h>
151 #include <gst/rtp/gstrtcpbuffer.h>
153 #include "gstrtpbin.h"
154 #include "rtpsession.h"
155 #include "gstrtpsession.h"
156 #include "gstrtpjitterbuffer.h"
158 #include <gst/glib-compat-private.h>
160 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
161 #define GST_CAT_DEFAULT gst_rtp_bin_debug
164 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
165 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%u",
168 GST_STATIC_CAPS ("application/x-rtp;application/x-srtp")
171 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
172 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%u",
175 GST_STATIC_CAPS ("application/x-rtcp;application/x-srtcp")
178 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
179 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%u",
182 GST_STATIC_CAPS ("application/x-rtp")
186 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
187 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%u_%u_%u",
190 GST_STATIC_CAPS ("application/x-rtp")
193 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
194 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%u",
197 GST_STATIC_CAPS ("application/x-rtcp;application/x-srtcp")
200 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
201 GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%u",
204 GST_STATIC_CAPS ("application/x-rtp;application/x-srtp")
207 #define GST_RTP_BIN_GET_PRIVATE(obj) \
208 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRtpBinPrivate))
210 #define GST_RTP_BIN_LOCK(bin) g_mutex_lock (&(bin)->priv->bin_lock)
211 #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock (&(bin)->priv->bin_lock)
213 /* lock to protect dynamic callbacks, like pad-added and new ssrc. */
214 #define GST_RTP_BIN_DYN_LOCK(bin) g_mutex_lock (&(bin)->priv->dyn_lock)
215 #define GST_RTP_BIN_DYN_UNLOCK(bin) g_mutex_unlock (&(bin)->priv->dyn_lock)
217 /* lock for shutdown */
218 #define GST_RTP_BIN_SHUTDOWN_LOCK(bin,label) \
220 if (g_atomic_int_get (&bin->priv->shutdown)) \
222 GST_RTP_BIN_DYN_LOCK (bin); \
223 if (g_atomic_int_get (&bin->priv->shutdown)) { \
224 GST_RTP_BIN_DYN_UNLOCK (bin); \
229 /* unlock for shutdown */
230 #define GST_RTP_BIN_SHUTDOWN_UNLOCK(bin) \
231 GST_RTP_BIN_DYN_UNLOCK (bin); \
233 /* Minimum time offset to apply. This compensates for rounding errors in NTP to
234 * RTP timestamp conversions */
235 #define MIN_TS_OFFSET (4 * GST_MSECOND)
237 struct _GstRtpBinPrivate
241 /* lock protecting dynamic adding/removing */
244 /* if we are shutting down or not */
249 /* NTP time in ns of last SR sync used */
250 guint64 last_ntpnstime;
252 /* list of extra elements */
256 /* signals and args */
259 SIGNAL_REQUEST_PT_MAP,
260 SIGNAL_PAYLOAD_TYPE_CHANGE,
264 SIGNAL_GET_INTERNAL_SESSION,
267 SIGNAL_ON_SSRC_COLLISION,
268 SIGNAL_ON_SSRC_VALIDATED,
269 SIGNAL_ON_SSRC_ACTIVE,
272 SIGNAL_ON_BYE_TIMEOUT,
274 SIGNAL_ON_SENDER_TIMEOUT,
277 SIGNAL_REQUEST_RTP_ENCODER,
278 SIGNAL_REQUEST_RTP_DECODER,
279 SIGNAL_REQUEST_RTCP_ENCODER,
280 SIGNAL_REQUEST_RTCP_DECODER,
282 SIGNAL_NEW_JITTERBUFFER,
284 SIGNAL_REQUEST_AUX_SENDER,
285 SIGNAL_REQUEST_AUX_RECEIVER,
287 SIGNAL_ON_NEW_SENDER_SSRC,
288 SIGNAL_ON_SENDER_SSRC_ACTIVE,
290 SIGNAL_ON_BUNDLED_SSRC,
295 #define DEFAULT_LATENCY_MS 200
296 #define DEFAULT_DROP_ON_LATENCY FALSE
297 #define DEFAULT_SDES NULL
298 #define DEFAULT_DO_LOST FALSE
299 #define DEFAULT_IGNORE_PT FALSE
300 #define DEFAULT_NTP_SYNC FALSE
301 #define DEFAULT_AUTOREMOVE FALSE
302 #define DEFAULT_BUFFER_MODE RTP_JITTER_BUFFER_MODE_SLAVE
303 #define DEFAULT_USE_PIPELINE_CLOCK FALSE
304 #define DEFAULT_RTCP_SYNC GST_RTP_BIN_RTCP_SYNC_ALWAYS
305 #define DEFAULT_RTCP_SYNC_INTERVAL 0
306 #define DEFAULT_DO_SYNC_EVENT FALSE
307 #define DEFAULT_DO_RETRANSMISSION FALSE
308 #define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP
309 #define DEFAULT_NTP_TIME_SOURCE GST_RTP_NTP_TIME_SOURCE_NTP
310 #define DEFAULT_RTCP_SYNC_SEND_TIME TRUE
311 #define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000
312 #define DEFAULT_MAX_DROPOUT_TIME 60000
313 #define DEFAULT_MAX_MISORDER_TIME 2000
314 #define DEFAULT_RFC7273_SYNC FALSE
315 #define DEFAULT_MAX_STREAMS G_MAXUINT
316 #define DEFAULT_MAX_TS_OFFSET_ADJUSTMENT G_GUINT64_CONSTANT(0)
317 #define DEFAULT_MAX_TS_OFFSET G_GINT64_CONSTANT(3000000000)
323 PROP_DROP_ON_LATENCY,
329 PROP_RTCP_SYNC_INTERVAL,
332 PROP_USE_PIPELINE_CLOCK,
334 PROP_DO_RETRANSMISSION,
336 PROP_NTP_TIME_SOURCE,
337 PROP_RTCP_SYNC_SEND_TIME,
338 PROP_MAX_RTCP_RTP_TIME_DIFF,
339 PROP_MAX_DROPOUT_TIME,
340 PROP_MAX_MISORDER_TIME,
343 PROP_MAX_TS_OFFSET_ADJUSTMENT,
347 #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type())
349 gst_rtp_bin_rtcp_sync_get_type (void)
351 static GType rtcp_sync_type = 0;
352 static const GEnumValue rtcp_sync_types[] = {
353 {GST_RTP_BIN_RTCP_SYNC_ALWAYS, "always", "always"},
354 {GST_RTP_BIN_RTCP_SYNC_INITIAL, "initial", "initial"},
355 {GST_RTP_BIN_RTCP_SYNC_RTP, "rtp-info", "rtp-info"},
359 if (!rtcp_sync_type) {
360 rtcp_sync_type = g_enum_register_static ("GstRTCPSync", rtcp_sync_types);
362 return rtcp_sync_type;
366 typedef struct _GstRtpBinSession GstRtpBinSession;
367 typedef struct _GstRtpBinStream GstRtpBinStream;
368 typedef struct _GstRtpBinClient GstRtpBinClient;
370 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
372 static GstCaps *pt_map_requested (GstElement * element, guint pt,
373 GstRtpBinSession * session);
374 static void payload_type_change (GstElement * element, guint pt,
375 GstRtpBinSession * session);
376 static void remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
377 static void remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
378 static void remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
379 static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
380 static void free_client (GstRtpBinClient * client, GstRtpBin * bin);
381 static void free_stream (GstRtpBinStream * stream, GstRtpBin * bin);
382 static GstRtpBinSession *create_session (GstRtpBin * rtpbin, gint id);
383 static GstPad *complete_session_sink (GstRtpBin * rtpbin,
384 GstRtpBinSession * session, gboolean bundle_demuxer_needed);
386 complete_session_receiver (GstRtpBin * rtpbin, GstRtpBinSession * session,
388 static GstPad *complete_session_rtcp (GstRtpBin * rtpbin,
389 GstRtpBinSession * session, guint sessid, gboolean bundle_demuxer_needed);
391 /* Manages the RTP stream for one SSRC.
393 * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
394 * If we see an SDES RTCP packet that links multiple SSRCs together based on a
395 * common CNAME, we create a GstRtpBinClient structure to group the SSRCs
396 * together (see below).
398 struct _GstRtpBinStream
400 /* the SSRC of this stream */
406 /* the session this SSRC belongs to */
407 GstRtpBinSession *session;
409 /* the jitterbuffer of the SSRC */
411 gulong buffer_handlesync_sig;
412 gulong buffer_ptreq_sig;
413 gulong buffer_ntpstop_sig;
416 /* the PT demuxer of the SSRC */
418 gulong demux_newpad_sig;
419 gulong demux_padremoved_sig;
420 gulong demux_ptreq_sig;
421 gulong demux_ptchange_sig;
423 /* if we have calculated a valid rt_delta for this stream */
425 /* mapping to local RTP and NTP time */
428 /* base rtptime in gst time */
432 #define GST_RTP_SESSION_LOCK(sess) g_mutex_lock (&(sess)->lock)
433 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock (&(sess)->lock)
435 /* Manages the receiving end of the packets.
437 * There is one such structure for each RTP session (audio/video/...).
438 * We get the RTP/RTCP packets and stuff them into the session manager. From
439 * there they are pushed into an SSRC demuxer that splits the stream based on
440 * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
441 * the GstRtpBinStream above).
443 struct _GstRtpBinSession
449 /* the session element */
451 /* the SSRC demuxer */
453 gulong demux_newpad_sig;
454 gulong demux_padremoved_sig;
456 /* Bundling support */
457 GstElement *rtp_funnel;
458 GstElement *rtcp_funnel;
459 GstElement *bundle_demux;
460 gulong bundle_demux_newpad_sig;
464 /* list of GstRtpBinStream */
467 /* list of elements */
470 /* mapping of payload type to caps */
473 /* the pads of the session */
474 GstPad *recv_rtp_sink;
475 GstPad *recv_rtp_sink_ghost;
476 GstPad *recv_rtp_src;
477 GstPad *recv_rtcp_sink;
478 GstPad *recv_rtcp_sink_ghost;
480 GstPad *send_rtp_sink;
481 GstPad *send_rtp_sink_ghost;
482 GstPad *send_rtp_src;
483 GstPad *send_rtp_src_ghost;
484 GstPad *send_rtcp_src;
485 GstPad *send_rtcp_src_ghost;
488 /* Manages the RTP streams that come from one client and should therefore be
491 struct _GstRtpBinClient
493 /* the common CNAME for the streams */
502 /* find a session with the given id. Must be called with RTP_BIN_LOCK */
503 static GstRtpBinSession *
504 find_session_by_id (GstRtpBin * rtpbin, gint id)
508 for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
509 GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
517 /* find a session with the given request pad. Must be called with RTP_BIN_LOCK */
518 static GstRtpBinSession *
519 find_session_by_pad (GstRtpBin * rtpbin, GstPad * pad)
523 for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
524 GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
526 if ((sess->recv_rtp_sink_ghost == pad) ||
527 (sess->recv_rtcp_sink_ghost == pad) ||
528 (sess->send_rtp_sink_ghost == pad)
529 || (sess->send_rtcp_src_ghost == pad))
536 on_new_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
538 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC], 0,
543 on_ssrc_collision (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
545 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION], 0,
550 on_ssrc_validated (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
552 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED], 0,
557 on_ssrc_active (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
559 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE], 0,
564 on_ssrc_sdes (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
566 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES], 0,
571 on_bye_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
573 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC], 0,
578 on_bye_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
580 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT], 0,
583 if (sess->bin->priv->autoremove)
584 g_signal_emit_by_name (sess->demux, "clear-ssrc", ssrc, NULL);
588 on_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
590 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT], 0,
593 if (sess->bin->priv->autoremove)
594 g_signal_emit_by_name (sess->demux, "clear-ssrc", ssrc, NULL);
598 on_sender_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
600 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT], 0,
605 on_npt_stop (GstElement * jbuf, GstRtpBinStream * stream)
607 g_signal_emit (stream->bin, gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP], 0,
608 stream->session->id, stream->ssrc);
612 on_new_sender_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
614 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SENDER_SSRC], 0,
619 on_sender_ssrc_active (GstElement * session, guint32 ssrc,
620 GstRtpBinSession * sess)
622 g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SENDER_SSRC_ACTIVE],
626 /* must be called with the SESSION lock */
627 static GstRtpBinStream *
628 find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc)
632 for (walk = session->streams; walk; walk = g_slist_next (walk)) {
633 GstRtpBinStream *stream = (GstRtpBinStream *) walk->data;
635 if (stream->ssrc == ssrc)
642 ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad,
643 GstRtpBinSession * session)
645 GstRtpBinStream *stream = NULL;
648 rtpbin = session->bin;
650 GST_RTP_BIN_LOCK (rtpbin);
652 GST_RTP_SESSION_LOCK (session);
653 if ((stream = find_stream_by_ssrc (session, ssrc)))
654 session->streams = g_slist_remove (session->streams, stream);
655 GST_RTP_SESSION_UNLOCK (session);
658 free_stream (stream, rtpbin);
660 GST_RTP_BIN_UNLOCK (rtpbin);
664 new_bundled_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
665 GstRtpBinSession * session)
667 GValue result = G_VALUE_INIT;
668 GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
669 guint session_id = 0;
670 GstRtpBinSession *target_session = NULL;
671 GstRtpBin *rtpbin = session->bin;
674 GstPad *recv_rtp_sink = NULL;
675 GstPad *recv_rtcp_sink = NULL;
676 GstPadLinkReturn ret;
678 GST_RTP_BIN_DYN_LOCK (rtpbin);
679 GST_DEBUG_OBJECT (rtpbin, "new bundled SSRC pad %08x, %s:%s", ssrc,
680 GST_DEBUG_PAD_NAME (pad));
682 g_value_init (&result, G_TYPE_UINT);
683 g_value_init (¶ms[0], GST_TYPE_ELEMENT);
684 g_value_set_object (¶ms[0], rtpbin);
685 g_value_init (¶ms[1], G_TYPE_UINT);
686 g_value_set_uint (¶ms[1], ssrc);
688 g_signal_emitv (params,
689 gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC], 0, &result);
690 g_value_unset (¶ms[0]);
692 session_id = g_value_get_uint (&result);
693 if (session_id == 0) {
694 target_session = session;
696 target_session = find_session_by_id (rtpbin, (gint) session_id);
697 if (!target_session) {
698 target_session = create_session (rtpbin, session_id);
700 if (!target_session) {
701 /* create_session() warned already */
702 GST_RTP_BIN_DYN_UNLOCK (rtpbin);
706 if (!target_session->recv_rtp_sink) {
707 recv_rtp_sink = complete_session_sink (rtpbin, target_session, FALSE);
710 if (!target_session->recv_rtp_src)
711 complete_session_receiver (rtpbin, target_session, session_id);
713 if (!target_session->recv_rtcp_sink) {
715 complete_session_rtcp (rtpbin, target_session, session_id, FALSE);
719 GST_DEBUG_OBJECT (rtpbin, "Assigning bundled ssrc %u to session %u", ssrc,
722 if (!recv_rtp_sink) {
724 gst_element_get_request_pad (target_session->rtp_funnel, "sink_%u");
727 if (!recv_rtcp_sink) {
729 gst_element_get_request_pad (target_session->rtcp_funnel, "sink_%u");
732 name = g_strdup_printf ("src_%u", ssrc);
733 src_pad = gst_element_get_static_pad (element, name);
734 ret = gst_pad_link (src_pad, recv_rtp_sink);
736 gst_object_unref (src_pad);
737 gst_object_unref (recv_rtp_sink);
738 if (ret != GST_PAD_LINK_OK) {
740 ("rtpbin: failed to link bundle demuxer to receive rtp funnel for session %u",
744 name = g_strdup_printf ("rtcp_src_%u", ssrc);
745 src_pad = gst_element_get_static_pad (element, name);
746 gst_pad_link (src_pad, recv_rtcp_sink);
748 gst_object_unref (src_pad);
749 gst_object_unref (recv_rtcp_sink);
750 if (ret != GST_PAD_LINK_OK) {
752 ("rtpbin: failed to link bundle demuxer to receive rtcp sink pad for session %u",
756 GST_RTP_BIN_DYN_UNLOCK (rtpbin);
759 /* create a session with the given id. Must be called with RTP_BIN_LOCK */
760 static GstRtpBinSession *
761 create_session (GstRtpBin * rtpbin, gint id)
763 GstRtpBinSession *sess;
764 GstElement *session, *demux;
767 if (!(session = gst_element_factory_make ("rtpsession", NULL)))
770 if (!(demux = gst_element_factory_make ("rtpssrcdemux", NULL)))
773 sess = g_new0 (GstRtpBinSession, 1);
774 g_mutex_init (&sess->lock);
777 sess->session = session;
780 sess->rtp_funnel = gst_element_factory_make ("funnel", NULL);
781 sess->rtcp_funnel = gst_element_factory_make ("funnel", NULL);
783 sess->ptmap = g_hash_table_new_full (NULL, NULL, NULL,
784 (GDestroyNotify) gst_caps_unref);
785 rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
787 /* configure SDES items */
788 GST_OBJECT_LOCK (rtpbin);
789 g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile",
790 rtpbin->rtp_profile, "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time,
792 if (rtpbin->use_pipeline_clock)
793 g_object_set (session, "use-pipeline-clock", rtpbin->use_pipeline_clock,
796 g_object_set (session, "ntp-time-source", rtpbin->ntp_time_source, NULL);
798 g_object_set (session, "max-dropout-time", rtpbin->max_dropout_time,
799 "max-misorder-time", rtpbin->max_misorder_time, NULL);
800 GST_OBJECT_UNLOCK (rtpbin);
802 /* provide clock_rate to the session manager when needed */
803 g_signal_connect (session, "request-pt-map",
804 (GCallback) pt_map_requested, sess);
806 g_signal_connect (sess->session, "on-new-ssrc",
807 (GCallback) on_new_ssrc, sess);
808 g_signal_connect (sess->session, "on-ssrc-collision",
809 (GCallback) on_ssrc_collision, sess);
810 g_signal_connect (sess->session, "on-ssrc-validated",
811 (GCallback) on_ssrc_validated, sess);
812 g_signal_connect (sess->session, "on-ssrc-active",
813 (GCallback) on_ssrc_active, sess);
814 g_signal_connect (sess->session, "on-ssrc-sdes",
815 (GCallback) on_ssrc_sdes, sess);
816 g_signal_connect (sess->session, "on-bye-ssrc",
817 (GCallback) on_bye_ssrc, sess);
818 g_signal_connect (sess->session, "on-bye-timeout",
819 (GCallback) on_bye_timeout, sess);
820 g_signal_connect (sess->session, "on-timeout", (GCallback) on_timeout, sess);
821 g_signal_connect (sess->session, "on-sender-timeout",
822 (GCallback) on_sender_timeout, sess);
823 g_signal_connect (sess->session, "on-new-sender-ssrc",
824 (GCallback) on_new_sender_ssrc, sess);
825 g_signal_connect (sess->session, "on-sender-ssrc-active",
826 (GCallback) on_sender_ssrc_active, sess);
828 gst_bin_add (GST_BIN_CAST (rtpbin), session);
829 gst_bin_add (GST_BIN_CAST (rtpbin), demux);
830 gst_bin_add (GST_BIN_CAST (rtpbin), sess->rtp_funnel);
831 gst_bin_add (GST_BIN_CAST (rtpbin), sess->rtcp_funnel);
833 GST_OBJECT_LOCK (rtpbin);
834 target = GST_STATE_TARGET (rtpbin);
835 GST_OBJECT_UNLOCK (rtpbin);
837 /* change state only to what's needed */
838 gst_element_set_state (demux, target);
839 gst_element_set_state (session, target);
840 gst_element_set_state (sess->rtp_funnel, target);
841 gst_element_set_state (sess->rtcp_funnel, target);
848 g_warning ("rtpbin: could not create rtpsession element");
853 gst_object_unref (session);
854 g_warning ("rtpbin: could not create rtpssrcdemux element");
860 bin_manage_element (GstRtpBin * bin, GstElement * element)
862 GstRtpBinPrivate *priv = bin->priv;
864 if (g_list_find (priv->elements, element)) {
865 GST_DEBUG_OBJECT (bin, "requested element %p already in bin", element);
867 GST_DEBUG_OBJECT (bin, "adding requested element %p", element);
869 if (g_object_is_floating (element))
870 element = gst_object_ref_sink (element);
872 if (!gst_bin_add (GST_BIN_CAST (bin), element))
874 if (!gst_element_sync_state_with_parent (element))
875 GST_WARNING_OBJECT (bin, "unable to sync element state with rtpbin");
877 /* we add the element multiple times, each we need an equal number of
878 * removes to really remove the element from the bin */
879 priv->elements = g_list_prepend (priv->elements, element);
886 GST_WARNING_OBJECT (bin, "unable to add element");
887 gst_object_unref (element);
893 remove_bin_element (GstElement * element, GstRtpBin * bin)
895 GstRtpBinPrivate *priv = bin->priv;
898 find = g_list_find (priv->elements, element);
900 priv->elements = g_list_delete_link (priv->elements, find);
902 if (!g_list_find (priv->elements, element)) {
903 gst_element_set_locked_state (element, TRUE);
904 gst_bin_remove (GST_BIN_CAST (bin), element);
905 gst_element_set_state (element, GST_STATE_NULL);
908 gst_object_unref (element);
912 /* called with RTP_BIN_LOCK */
914 free_session (GstRtpBinSession * sess, GstRtpBin * bin)
916 GST_DEBUG_OBJECT (bin, "freeing session %p", sess);
918 gst_element_set_locked_state (sess->demux, TRUE);
919 gst_element_set_locked_state (sess->session, TRUE);
921 gst_element_set_state (sess->demux, GST_STATE_NULL);
922 gst_element_set_state (sess->session, GST_STATE_NULL);
924 remove_recv_rtp (bin, sess);
925 remove_recv_rtcp (bin, sess);
926 remove_send_rtp (bin, sess);
927 remove_rtcp (bin, sess);
929 gst_bin_remove (GST_BIN_CAST (bin), sess->session);
930 gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
932 g_slist_foreach (sess->elements, (GFunc) remove_bin_element, bin);
933 g_slist_free (sess->elements);
935 g_slist_foreach (sess->streams, (GFunc) free_stream, bin);
936 g_slist_free (sess->streams);
938 g_mutex_clear (&sess->lock);
939 g_hash_table_destroy (sess->ptmap);
944 /* get the payload type caps for the specific payload @pt in @session */
946 get_pt_map (GstRtpBinSession * session, guint pt)
948 GstCaps *caps = NULL;
951 GValue args[3] = { {0}, {0}, {0} };
953 GST_DEBUG ("searching pt %u in cache", pt);
955 GST_RTP_SESSION_LOCK (session);
957 /* first look in the cache */
958 caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
966 GST_DEBUG ("emiting signal for pt %u in session %u", pt, session->id);
968 /* not in cache, send signal to request caps */
969 g_value_init (&args[0], GST_TYPE_ELEMENT);
970 g_value_set_object (&args[0], bin);
971 g_value_init (&args[1], G_TYPE_UINT);
972 g_value_set_uint (&args[1], session->id);
973 g_value_init (&args[2], G_TYPE_UINT);
974 g_value_set_uint (&args[2], pt);
976 g_value_init (&ret, GST_TYPE_CAPS);
977 g_value_set_boxed (&ret, NULL);
979 GST_RTP_SESSION_UNLOCK (session);
981 g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
983 GST_RTP_SESSION_LOCK (session);
985 g_value_unset (&args[0]);
986 g_value_unset (&args[1]);
987 g_value_unset (&args[2]);
989 /* look in the cache again because we let the lock go */
990 caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
993 g_value_unset (&ret);
997 caps = (GstCaps *) g_value_dup_boxed (&ret);
998 g_value_unset (&ret);
1002 GST_DEBUG ("caching pt %u as %" GST_PTR_FORMAT, pt, caps);
1004 /* store in cache, take additional ref */
1005 g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt),
1006 gst_caps_ref (caps));
1009 GST_RTP_SESSION_UNLOCK (session);
1016 GST_RTP_SESSION_UNLOCK (session);
1017 GST_DEBUG ("no pt map could be obtained");
1023 return_true (gpointer key, gpointer value, gpointer user_data)
1029 gst_rtp_bin_reset_sync (GstRtpBin * rtpbin)
1031 GSList *clients, *streams;
1033 GST_DEBUG_OBJECT (rtpbin, "Reset sync on all clients");
1035 GST_RTP_BIN_LOCK (rtpbin);
1036 for (clients = rtpbin->clients; clients; clients = g_slist_next (clients)) {
1037 GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
1039 /* reset sync on all streams for this client */
1040 for (streams = client->streams; streams; streams = g_slist_next (streams)) {
1041 GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
1043 /* make use require a new SR packet for this stream before we attempt new
1045 stream->have_sync = FALSE;
1046 stream->rt_delta = 0;
1047 stream->rtp_delta = 0;
1048 stream->clock_base = -100 * GST_SECOND;
1051 GST_RTP_BIN_UNLOCK (rtpbin);
1055 gst_rtp_bin_clear_pt_map (GstRtpBin * bin)
1057 GSList *sessions, *streams;
1059 GST_RTP_BIN_LOCK (bin);
1060 GST_DEBUG_OBJECT (bin, "clearing pt map");
1061 for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
1062 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
1064 GST_DEBUG_OBJECT (bin, "clearing session %p", session);
1065 g_signal_emit_by_name (session->session, "clear-pt-map", NULL);
1067 GST_RTP_SESSION_LOCK (session);
1068 g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
1070 for (streams = session->streams; streams; streams = g_slist_next (streams)) {
1071 GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
1073 GST_DEBUG_OBJECT (bin, "clearing stream %p", stream);
1074 g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL);
1076 g_signal_emit_by_name (stream->demux, "clear-pt-map", NULL);
1078 GST_RTP_SESSION_UNLOCK (session);
1080 GST_RTP_BIN_UNLOCK (bin);
1082 /* reset sync too */
1083 gst_rtp_bin_reset_sync (bin);
1087 gst_rtp_bin_get_session (GstRtpBin * bin, guint session_id)
1089 GstRtpBinSession *session;
1090 GstElement *ret = NULL;
1092 GST_RTP_BIN_LOCK (bin);
1093 GST_DEBUG_OBJECT (bin, "retrieving GstRtpSession, index: %u", session_id);
1094 session = find_session_by_id (bin, (gint) session_id);
1096 ret = gst_object_ref (session->session);
1098 GST_RTP_BIN_UNLOCK (bin);
1104 gst_rtp_bin_get_internal_session (GstRtpBin * bin, guint session_id)
1106 RTPSession *internal_session = NULL;
1107 GstRtpBinSession *session;
1109 GST_RTP_BIN_LOCK (bin);
1110 GST_DEBUG_OBJECT (bin, "retrieving internal RTPSession object, index: %u",
1112 session = find_session_by_id (bin, (gint) session_id);
1114 g_object_get (session->session, "internal-session", &internal_session,
1117 GST_RTP_BIN_UNLOCK (bin);
1119 return internal_session;
1123 gst_rtp_bin_request_encoder (GstRtpBin * bin, guint session_id)
1125 GST_DEBUG_OBJECT (bin, "return NULL encoder");
1130 gst_rtp_bin_request_decoder (GstRtpBin * bin, guint session_id)
1132 GST_DEBUG_OBJECT (bin, "return NULL decoder");
1137 gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin,
1138 const gchar * name, const GValue * value)
1140 GSList *sessions, *streams;
1142 GST_RTP_BIN_LOCK (bin);
1143 for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
1144 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
1146 GST_RTP_SESSION_LOCK (session);
1147 for (streams = session->streams; streams; streams = g_slist_next (streams)) {
1148 GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
1150 g_object_set_property (G_OBJECT (stream->buffer), name, value);
1152 GST_RTP_SESSION_UNLOCK (session);
1154 GST_RTP_BIN_UNLOCK (bin);
1158 gst_rtp_bin_propagate_property_to_session (GstRtpBin * bin,
1159 const gchar * name, const GValue * value)
1163 GST_RTP_BIN_LOCK (bin);
1164 for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
1165 GstRtpBinSession *sess = (GstRtpBinSession *) sessions->data;
1167 g_object_set_property (G_OBJECT (sess->session), name, value);
1169 GST_RTP_BIN_UNLOCK (bin);
1172 /* get a client with the given SDES name. Must be called with RTP_BIN_LOCK */
1173 static GstRtpBinClient *
1174 get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created)
1176 GstRtpBinClient *result = NULL;
1179 for (walk = bin->clients; walk; walk = g_slist_next (walk)) {
1180 GstRtpBinClient *client = (GstRtpBinClient *) walk->data;
1182 if (len != client->cname_len)
1185 if (!strncmp ((gchar *) data, client->cname, client->cname_len)) {
1186 GST_DEBUG_OBJECT (bin, "found existing client %p with CNAME %s", client,
1193 /* nothing found, create one */
1194 if (result == NULL) {
1195 result = g_new0 (GstRtpBinClient, 1);
1196 result->cname = g_strndup ((gchar *) data, len);
1197 result->cname_len = len;
1198 bin->clients = g_slist_prepend (bin->clients, result);
1199 GST_DEBUG_OBJECT (bin, "created new client %p with CNAME %s", result,
1206 free_client (GstRtpBinClient * client, GstRtpBin * bin)
1208 GST_DEBUG_OBJECT (bin, "freeing client %p", client);
1209 g_slist_free (client->streams);
1210 g_free (client->cname);
1215 get_current_times (GstRtpBin * bin, GstClockTime * running_time,
1216 guint64 * ntpnstime)
1220 GstClockTime base_time, rt, clock_time;
1222 GST_OBJECT_LOCK (bin);
1223 if ((clock = GST_ELEMENT_CLOCK (bin))) {
1224 base_time = GST_ELEMENT_CAST (bin)->base_time;
1225 gst_object_ref (clock);
1226 GST_OBJECT_UNLOCK (bin);
1228 /* get current clock time and convert to running time */
1229 clock_time = gst_clock_get_time (clock);
1230 rt = clock_time - base_time;
1232 if (bin->use_pipeline_clock) {
1234 /* add constant to convert from 1970 based time to 1900 based time */
1235 ntpns += (2208988800LL * GST_SECOND);
1237 switch (bin->ntp_time_source) {
1238 case GST_RTP_NTP_TIME_SOURCE_NTP:
1239 case GST_RTP_NTP_TIME_SOURCE_UNIX:{
1242 /* get current NTP time */
1243 g_get_current_time (¤t);
1244 ntpns = GST_TIMEVAL_TO_TIME (current);
1246 /* add constant to convert from 1970 based time to 1900 based time */
1247 if (bin->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
1248 ntpns += (2208988800LL * GST_SECOND);
1251 case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
1254 case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
1258 ntpns = -1; /* Fix uninited compiler warning */
1259 g_assert_not_reached ();
1264 gst_object_unref (clock);
1266 GST_OBJECT_UNLOCK (bin);
1277 stream_set_ts_offset (GstRtpBin * bin, GstRtpBinStream * stream,
1278 gint64 ts_offset, gint64 max_ts_offset, gint64 min_ts_offset,
1279 gboolean allow_positive_ts_offset)
1281 gint64 prev_ts_offset;
1283 g_object_get (stream->buffer, "ts-offset", &prev_ts_offset, NULL);
1285 /* delta changed, see how much */
1286 if (prev_ts_offset != ts_offset) {
1289 diff = prev_ts_offset - ts_offset;
1291 GST_DEBUG_OBJECT (bin,
1292 "ts-offset %" G_GINT64_FORMAT ", prev %" G_GINT64_FORMAT
1293 ", diff: %" G_GINT64_FORMAT, ts_offset, prev_ts_offset, diff);
1295 /* ignore minor offsets */
1296 if (ABS (diff) < min_ts_offset) {
1297 GST_DEBUG_OBJECT (bin, "offset too small, ignoring");
1301 /* sanity check offset */
1302 if (max_ts_offset > 0) {
1303 if (ts_offset > 0 && !allow_positive_ts_offset) {
1304 GST_DEBUG_OBJECT (bin,
1305 "offset is positive (clocks are out of sync), ignoring");
1308 if (ABS (ts_offset) > max_ts_offset) {
1309 GST_DEBUG_OBJECT (bin, "offset too large, ignoring");
1314 g_object_set (stream->buffer, "ts-offset", ts_offset, NULL);
1316 GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT,
1317 stream->ssrc, ts_offset);
1321 gst_rtp_bin_send_sync_event (GstRtpBinStream * stream)
1323 if (stream->bin->send_sync_event) {
1327 GST_DEBUG_OBJECT (stream->bin,
1328 "sending GstRTCPSRReceived event downstream");
1330 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1331 gst_structure_new_empty ("GstRTCPSRReceived"));
1333 srcpad = gst_element_get_static_pad (stream->buffer, "src");
1334 gst_pad_push_event (srcpad, event);
1335 gst_object_unref (srcpad);
1339 /* associate a stream to the given CNAME. This will make sure all streams for
1340 * that CNAME are synchronized together.
1341 * Must be called with GST_RTP_BIN_LOCK */
1343 gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len,
1344 guint8 * data, guint64 ntptime, guint64 last_extrtptime,
1345 guint64 base_rtptime, guint64 base_time, guint clock_rate,
1346 gint64 rtp_clock_base)
1348 GstRtpBinClient *client;
1351 GstClockTime running_time, running_time_rtp;
1354 /* first find or create the CNAME */
1355 client = get_client (bin, len, data, &created);
1357 /* find stream in the client */
1358 for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1359 GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1361 if (ostream == stream)
1364 /* not found, add it to the list */
1366 GST_DEBUG_OBJECT (bin,
1367 "new association of SSRC %08x with client %p with CNAME %s",
1368 stream->ssrc, client, client->cname);
1369 client->streams = g_slist_prepend (client->streams, stream);
1372 GST_DEBUG_OBJECT (bin,
1373 "found association of SSRC %08x with client %p with CNAME %s",
1374 stream->ssrc, client, client->cname);
1377 if (!GST_CLOCK_TIME_IS_VALID (last_extrtptime)) {
1378 GST_DEBUG_OBJECT (bin, "invalidated sync data");
1379 if (bin->rtcp_sync == GST_RTP_BIN_RTCP_SYNC_RTP) {
1380 /* we don't need that data, so carry on,
1381 * but make some values look saner */
1382 last_extrtptime = base_rtptime;
1384 /* nothing we can do with this data in this case */
1385 GST_DEBUG_OBJECT (bin, "bailing out");
1390 /* Take the extended rtptime we found in the SR packet and map it to the
1391 * local rtptime. The local rtp time is used to construct timestamps on the
1392 * buffers so we will calculate what running_time corresponds to the RTP
1393 * timestamp in the SR packet. */
1394 running_time_rtp = last_extrtptime - base_rtptime;
1396 GST_DEBUG_OBJECT (bin,
1397 "base %" G_GUINT64_FORMAT ", extrtptime %" G_GUINT64_FORMAT
1398 ", local RTP %" G_GUINT64_FORMAT ", clock-rate %d, "
1399 "clock-base %" G_GINT64_FORMAT, base_rtptime,
1400 last_extrtptime, running_time_rtp, clock_rate, rtp_clock_base);
1402 /* calculate local RTP time in gstreamer timestamp, we essentially perform the
1403 * same conversion that a jitterbuffer would use to convert an rtp timestamp
1404 * into a corresponding gstreamer timestamp. Note that the base_time also
1405 * contains the drift between sender and receiver. */
1407 gst_util_uint64_scale_int (running_time_rtp, GST_SECOND, clock_rate);
1408 running_time += base_time;
1410 /* convert ntptime to nanoseconds */
1411 ntpnstime = gst_util_uint64_scale (ntptime, GST_SECOND,
1412 (G_GINT64_CONSTANT (1) << 32));
1414 stream->have_sync = TRUE;
1416 GST_DEBUG_OBJECT (bin,
1417 "SR RTP running time %" G_GUINT64_FORMAT ", SR NTP %" G_GUINT64_FORMAT,
1418 running_time, ntpnstime);
1420 /* recalc inter stream playout offset, but only if there is more than one
1421 * stream or we're doing NTP sync. */
1422 if (bin->ntp_sync) {
1423 gint64 ntpdiff, rtdiff;
1424 guint64 local_ntpnstime;
1425 GstClockTime local_running_time;
1427 /* For NTP sync we need to first get a snapshot of running_time and NTP
1428 * time. We know at what running_time we play a certain RTP time, we also
1429 * calculated when we would play the RTP time in the SR packet. Now we need
1430 * to know how the running_time and the NTP time relate to eachother. */
1431 get_current_times (bin, &local_running_time, &local_ntpnstime);
1433 /* see how far away the NTP time is. This is the difference between the
1434 * current NTP time and the NTP time in the last SR packet. */
1435 ntpdiff = local_ntpnstime - ntpnstime;
1436 /* see how far away the running_time is. This is the difference between the
1437 * current running_time and the running_time of the RTP timestamp in the
1438 * last SR packet. */
1439 rtdiff = local_running_time - running_time;
1441 GST_DEBUG_OBJECT (bin,
1442 "local NTP time %" G_GUINT64_FORMAT ", SR NTP time %" G_GUINT64_FORMAT,
1443 local_ntpnstime, ntpnstime);
1444 GST_DEBUG_OBJECT (bin,
1445 "local running time %" G_GUINT64_FORMAT ", SR RTP running time %"
1446 G_GUINT64_FORMAT, local_running_time, running_time);
1447 GST_DEBUG_OBJECT (bin,
1448 "NTP diff %" G_GINT64_FORMAT ", RT diff %" G_GINT64_FORMAT, ntpdiff,
1451 /* combine to get the final diff to apply to the running_time */
1452 stream->rt_delta = rtdiff - ntpdiff;
1454 stream_set_ts_offset (bin, stream, stream->rt_delta, bin->max_ts_offset,
1457 gint64 min, rtp_min, clock_base = stream->clock_base;
1458 gboolean all_sync, use_rtp;
1459 gboolean rtcp_sync = g_atomic_int_get (&bin->rtcp_sync);
1461 /* calculate delta between server and receiver. ntpnstime is created by
1462 * converting the ntptime in the last SR packet to a gstreamer timestamp. This
1463 * delta expresses the difference to our timeline and the server timeline. The
1464 * difference in itself doesn't mean much but we can combine the delta of
1465 * multiple streams to create a stream specific offset. */
1466 stream->rt_delta = ntpnstime - running_time;
1468 /* calculate the min of all deltas, ignoring streams that did not yet have a
1469 * valid rt_delta because we did not yet receive an SR packet for those
1471 * We calculate the mininum because we would like to only apply positive
1472 * offsets to streams, delaying their playback instead of trying to speed up
1473 * other streams (which might be imposible when we have to create negative
1475 * The stream that has the smallest diff is selected as the reference stream,
1476 * all other streams will have a positive offset to this difference. */
1478 /* some alternative setting allow ignoring RTCP as much as possible,
1479 * for servers generating bogus ntp timeline */
1480 min = rtp_min = G_MAXINT64;
1482 if (rtcp_sync == GST_RTP_BIN_RTCP_SYNC_RTP) {
1486 /* signed version for convienience */
1487 clock_base = base_rtptime;
1488 /* deal with possible wrap-around */
1489 ext_base = base_rtptime;
1490 rtp_clock_base = gst_rtp_buffer_ext_timestamp (&ext_base, rtp_clock_base);
1491 /* sanity check; base rtp and provided clock_base should be close */
1492 if (rtp_clock_base >= clock_base) {
1493 if (rtp_clock_base - clock_base < 10 * clock_rate) {
1494 rtp_clock_base = base_time +
1495 gst_util_uint64_scale_int (rtp_clock_base - clock_base,
1496 GST_SECOND, clock_rate);
1501 if (clock_base - rtp_clock_base < 10 * clock_rate) {
1502 rtp_clock_base = base_time -
1503 gst_util_uint64_scale_int (clock_base - rtp_clock_base,
1504 GST_SECOND, clock_rate);
1509 /* warn and bail for clarity out if no sane values */
1511 GST_WARNING_OBJECT (bin, "unable to sync to provided rtptime");
1514 /* store to track changes */
1515 clock_base = rtp_clock_base;
1516 /* generate a fake as before,
1517 * now equating rtptime obtained from RTP-Info,
1518 * where the large time represent the otherwise irrelevant npt/ntp time */
1519 stream->rtp_delta = (GST_SECOND << 28) - rtp_clock_base;
1521 clock_base = rtp_clock_base;
1525 for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1526 GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1528 if (!ostream->have_sync) {
1533 /* change in current stream's base from previously init'ed value
1534 * leads to reset of all stream's base */
1535 if (stream != ostream && stream->clock_base >= 0 &&
1536 (stream->clock_base != clock_base)) {
1537 GST_DEBUG_OBJECT (bin, "reset upon clock base change");
1538 ostream->clock_base = -100 * GST_SECOND;
1539 ostream->rtp_delta = 0;
1542 if (ostream->rt_delta < min)
1543 min = ostream->rt_delta;
1544 if (ostream->rtp_delta < rtp_min)
1545 rtp_min = ostream->rtp_delta;
1548 /* arrange to re-sync for each stream upon significant change,
1550 all_sync = all_sync && (stream->clock_base == clock_base);
1551 stream->clock_base = clock_base;
1553 /* may need init performed above later on, but nothing more to do now */
1554 if (client->nstreams <= 1)
1557 GST_DEBUG_OBJECT (bin, "client %p min delta %" G_GINT64_FORMAT
1558 " all sync %d", client, min, all_sync);
1559 GST_DEBUG_OBJECT (bin, "rtcp sync mode %d, use_rtp %d", rtcp_sync, use_rtp);
1561 switch (rtcp_sync) {
1562 case GST_RTP_BIN_RTCP_SYNC_RTP:
1565 GST_DEBUG_OBJECT (bin, "using rtp generated reports; "
1566 "client %p min rtp delta %" G_GINT64_FORMAT, client, rtp_min);
1568 case GST_RTP_BIN_RTCP_SYNC_INITIAL:
1569 /* if all have been synced already, do not bother further */
1571 GST_DEBUG_OBJECT (bin, "all streams already synced; done");
1579 /* bail out if we adjusted recently enough */
1580 if (all_sync && (ntpnstime - bin->priv->last_ntpnstime) <
1581 bin->rtcp_sync_interval * GST_MSECOND) {
1582 GST_DEBUG_OBJECT (bin, "discarding RTCP sender packet for sync; "
1583 "previous sender info too recent "
1584 "(previous NTP %" G_GUINT64_FORMAT ")", bin->priv->last_ntpnstime);
1587 bin->priv->last_ntpnstime = ntpnstime;
1589 /* calculate offsets for each stream */
1590 for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1591 GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1594 /* ignore streams for which we didn't receive an SR packet yet, we
1595 * can't synchronize them yet. We can however sync other streams just
1597 if (!ostream->have_sync)
1600 /* calculate offset to our reference stream, this should always give a
1601 * positive number. */
1603 ts_offset = ostream->rtp_delta - rtp_min;
1605 ts_offset = ostream->rt_delta - min;
1607 stream_set_ts_offset (bin, ostream, ts_offset, bin->max_ts_offset,
1608 MIN_TS_OFFSET, TRUE);
1611 gst_rtp_bin_send_sync_event (stream);
1616 #define GST_RTCP_BUFFER_FOR_PACKETS(b,buffer,packet) \
1617 for ((b) = gst_rtcp_buffer_get_first_packet ((buffer), (packet)); (b); \
1618 (b) = gst_rtcp_packet_move_to_next ((packet)))
1620 #define GST_RTCP_SDES_FOR_ITEMS(b,packet) \
1621 for ((b) = gst_rtcp_packet_sdes_first_item ((packet)); (b); \
1622 (b) = gst_rtcp_packet_sdes_next_item ((packet)))
1624 #define GST_RTCP_SDES_FOR_ENTRIES(b,packet) \
1625 for ((b) = gst_rtcp_packet_sdes_first_entry ((packet)); (b); \
1626 (b) = gst_rtcp_packet_sdes_next_entry ((packet)))
1629 gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
1630 GstRtpBinStream * stream)
1633 GstRTCPPacket packet;
1636 gboolean have_sr, have_sdes;
1638 guint64 base_rtptime;
1644 GstRTCPBuffer rtcp = { NULL, };
1648 GST_DEBUG_OBJECT (bin, "sync handler called");
1650 /* get the last relation between the rtp timestamps and the gstreamer
1651 * timestamps. We get this info directly from the jitterbuffer which
1652 * constructs gstreamer timestamps from rtp timestamps and so it know exactly
1653 * what the current situation is. */
1655 g_value_get_uint64 (gst_structure_get_value (s, "base-rtptime"));
1656 base_time = g_value_get_uint64 (gst_structure_get_value (s, "base-time"));
1657 clock_rate = g_value_get_uint (gst_structure_get_value (s, "clock-rate"));
1658 clock_base = g_value_get_uint64 (gst_structure_get_value (s, "clock-base"));
1660 g_value_get_uint64 (gst_structure_get_value (s, "sr-ext-rtptime"));
1661 buffer = gst_value_get_buffer (gst_structure_get_value (s, "sr-buffer"));
1666 gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
1668 GST_RTCP_BUFFER_FOR_PACKETS (more, &rtcp, &packet) {
1669 /* first packet must be SR or RR or else the validate would have failed */
1670 switch (gst_rtcp_packet_get_type (&packet)) {
1671 case GST_RTCP_TYPE_SR:
1672 /* only parse first. There is only supposed to be one SR in the packet
1673 * but we will deal with malformed packets gracefully */
1676 /* get NTP and RTP times */
1677 gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, NULL,
1680 GST_DEBUG_OBJECT (bin, "received sync packet from SSRC %08x", ssrc);
1681 /* ignore SR that is not ours */
1682 if (ssrc != stream->ssrc)
1687 case GST_RTCP_TYPE_SDES:
1689 gboolean more_items, more_entries;
1691 /* only deal with first SDES, there is only supposed to be one SDES in
1692 * the RTCP packet but we deal with bad packets gracefully. Also bail
1693 * out if we have not seen an SR item yet. */
1694 if (have_sdes || !have_sr)
1697 GST_RTCP_SDES_FOR_ITEMS (more_items, &packet) {
1698 /* skip items that are not about the SSRC of the sender */
1699 if (gst_rtcp_packet_sdes_get_ssrc (&packet) != ssrc)
1702 /* find the CNAME entry */
1703 GST_RTCP_SDES_FOR_ENTRIES (more_entries, &packet) {
1704 GstRTCPSDESType type;
1708 gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data);
1710 if (type == GST_RTCP_SDES_CNAME) {
1711 GST_RTP_BIN_LOCK (bin);
1712 /* associate the stream to CNAME */
1713 gst_rtp_bin_associate (bin, stream, len, data,
1714 ntptime, extrtptime, base_rtptime, base_time, clock_rate,
1716 GST_RTP_BIN_UNLOCK (bin);
1724 /* we can ignore these packets */
1728 gst_rtcp_buffer_unmap (&rtcp);
1731 /* create a new stream with @ssrc in @session. Must be called with
1732 * RTP_SESSION_LOCK. */
1733 static GstRtpBinStream *
1734 create_stream (GstRtpBinSession * session, guint32 ssrc)
1736 GstElement *buffer, *demux = NULL;
1737 GstRtpBinStream *stream;
1741 rtpbin = session->bin;
1743 if (g_slist_length (session->streams) >= rtpbin->max_streams)
1746 if (!(buffer = gst_element_factory_make ("rtpjitterbuffer", NULL)))
1747 goto no_jitterbuffer;
1749 if (!rtpbin->ignore_pt)
1750 if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
1753 stream = g_new0 (GstRtpBinStream, 1);
1754 stream->ssrc = ssrc;
1755 stream->bin = rtpbin;
1756 stream->session = session;
1757 stream->buffer = buffer;
1758 stream->demux = demux;
1760 stream->have_sync = FALSE;
1761 stream->rt_delta = 0;
1762 stream->rtp_delta = 0;
1763 stream->percent = 100;
1764 stream->clock_base = -100 * GST_SECOND;
1765 session->streams = g_slist_prepend (session->streams, stream);
1767 /* provide clock_rate to the jitterbuffer when needed */
1768 stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map",
1769 (GCallback) pt_map_requested, session);
1770 stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop",
1771 (GCallback) on_npt_stop, stream);
1773 g_object_set_data (G_OBJECT (buffer), "GstRTPBin.session", session);
1774 g_object_set_data (G_OBJECT (buffer), "GstRTPBin.stream", stream);
1776 /* configure latency and packet lost */
1777 g_object_set (buffer, "latency", rtpbin->latency_ms, NULL);
1778 g_object_set (buffer, "drop-on-latency", rtpbin->drop_on_latency, NULL);
1779 g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL);
1780 g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL);
1781 g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL);
1782 g_object_set (buffer, "max-rtcp-rtp-time-diff",
1783 rtpbin->max_rtcp_rtp_time_diff, NULL);
1784 g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time,
1785 "max-misorder-time", rtpbin->max_misorder_time, NULL);
1786 g_object_set (buffer, "rfc7273-sync", rtpbin->rfc7273_sync, NULL);
1787 g_object_set (buffer, "max-ts-offset-adjustment",
1788 rtpbin->max_ts_offset_adjustment, NULL);
1790 g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0,
1791 buffer, session->id, ssrc);
1793 if (!rtpbin->ignore_pt)
1794 gst_bin_add (GST_BIN_CAST (rtpbin), demux);
1795 gst_bin_add (GST_BIN_CAST (rtpbin), buffer);
1799 gst_element_link_pads_full (buffer, "src", demux, "sink",
1800 GST_PAD_LINK_CHECK_NOTHING);
1802 if (rtpbin->buffering) {
1805 GST_INFO_OBJECT (rtpbin,
1806 "bin is buffering, set jitterbuffer as not active");
1807 g_signal_emit_by_name (buffer, "set-active", FALSE, (gint64) 0, &last_out);
1811 GST_OBJECT_LOCK (rtpbin);
1812 target = GST_STATE_TARGET (rtpbin);
1813 GST_OBJECT_UNLOCK (rtpbin);
1815 /* from sink to source */
1817 gst_element_set_state (demux, target);
1819 gst_element_set_state (buffer, target);
1826 GST_WARNING_OBJECT (rtpbin, "stream exeeds maximum (%d)",
1827 rtpbin->max_streams);
1832 g_warning ("rtpbin: could not create rtpjitterbuffer element");
1837 gst_object_unref (buffer);
1838 g_warning ("rtpbin: could not create rtpptdemux element");
1843 /* called with RTP_BIN_LOCK */
1845 free_stream (GstRtpBinStream * stream, GstRtpBin * bin)
1847 GSList *clients, *next_client;
1849 GST_DEBUG_OBJECT (bin, "freeing stream %p", stream);
1851 if (stream->demux) {
1852 g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig);
1853 g_signal_handler_disconnect (stream->demux, stream->demux_ptreq_sig);
1854 g_signal_handler_disconnect (stream->demux, stream->demux_ptchange_sig);
1856 g_signal_handler_disconnect (stream->buffer, stream->buffer_handlesync_sig);
1857 g_signal_handler_disconnect (stream->buffer, stream->buffer_ptreq_sig);
1858 g_signal_handler_disconnect (stream->buffer, stream->buffer_ntpstop_sig);
1861 gst_element_set_locked_state (stream->demux, TRUE);
1862 gst_element_set_locked_state (stream->buffer, TRUE);
1865 gst_element_set_state (stream->demux, GST_STATE_NULL);
1866 gst_element_set_state (stream->buffer, GST_STATE_NULL);
1868 /* now remove this signal, we need this while going to NULL because it to
1869 * do some cleanups */
1871 g_signal_handler_disconnect (stream->demux, stream->demux_padremoved_sig);
1873 gst_bin_remove (GST_BIN_CAST (bin), stream->buffer);
1875 gst_bin_remove (GST_BIN_CAST (bin), stream->demux);
1877 for (clients = bin->clients; clients; clients = next_client) {
1878 GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
1879 GSList *streams, *next_stream;
1881 next_client = g_slist_next (clients);
1883 for (streams = client->streams; streams; streams = next_stream) {
1884 GstRtpBinStream *ostream = (GstRtpBinStream *) streams->data;
1886 next_stream = g_slist_next (streams);
1888 if (ostream == stream) {
1889 client->streams = g_slist_delete_link (client->streams, streams);
1890 /* If this was the last stream belonging to this client,
1891 * clean up the client. */
1892 if (--client->nstreams == 0) {
1893 bin->clients = g_slist_delete_link (bin->clients, clients);
1894 free_client (client, bin);
1903 /* GObject vmethods */
1904 static void gst_rtp_bin_dispose (GObject * object);
1905 static void gst_rtp_bin_finalize (GObject * object);
1906 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
1907 const GValue * value, GParamSpec * pspec);
1908 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
1909 GValue * value, GParamSpec * pspec);
1911 /* GstElement vmethods */
1912 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
1913 GstStateChange transition);
1914 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
1915 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
1916 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
1917 static void gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message);
1919 #define gst_rtp_bin_parent_class parent_class
1920 G_DEFINE_TYPE (GstRtpBin, gst_rtp_bin, GST_TYPE_BIN);
1923 _gst_element_accumulator (GSignalInvocationHint * ihint,
1924 GValue * return_accu, const GValue * handler_return, gpointer dummy)
1926 GstElement *element;
1928 element = g_value_get_object (handler_return);
1929 GST_DEBUG ("got element %" GST_PTR_FORMAT, element);
1931 if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
1932 g_value_set_object (return_accu, element);
1934 /* stop emission if we have an element */
1935 return (element == NULL);
1939 _gst_caps_accumulator (GSignalInvocationHint * ihint,
1940 GValue * return_accu, const GValue * handler_return, gpointer dummy)
1944 caps = g_value_get_boxed (handler_return);
1945 GST_DEBUG ("got caps %" GST_PTR_FORMAT, caps);
1947 if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
1948 g_value_set_boxed (return_accu, caps);
1950 /* stop emission if we have a caps */
1951 return (caps == NULL);
1955 gst_rtp_bin_class_init (GstRtpBinClass * klass)
1957 GObjectClass *gobject_class;
1958 GstElementClass *gstelement_class;
1959 GstBinClass *gstbin_class;
1961 gobject_class = (GObjectClass *) klass;
1962 gstelement_class = (GstElementClass *) klass;
1963 gstbin_class = (GstBinClass *) klass;
1965 g_type_class_add_private (klass, sizeof (GstRtpBinPrivate));
1967 gobject_class->dispose = gst_rtp_bin_dispose;
1968 gobject_class->finalize = gst_rtp_bin_finalize;
1969 gobject_class->set_property = gst_rtp_bin_set_property;
1970 gobject_class->get_property = gst_rtp_bin_get_property;
1972 g_object_class_install_property (gobject_class, PROP_LATENCY,
1973 g_param_spec_uint ("latency", "Buffer latency in ms",
1974 "Default amount of ms to buffer in the jitterbuffers", 0,
1975 G_MAXUINT, DEFAULT_LATENCY_MS,
1976 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1978 g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY,
1979 g_param_spec_boolean ("drop-on-latency",
1980 "Drop buffers when maximum latency is reached",
1981 "Tells the jitterbuffer to never exceed the given latency in size",
1982 DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1985 * GstRtpBin::request-pt-map:
1986 * @rtpbin: the object which received the signal
1987 * @session: the session
1990 * Request the payload type as #GstCaps for @pt in @session.
1992 gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
1993 g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
1994 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_pt_map),
1995 _gst_caps_accumulator, NULL, g_cclosure_marshal_generic, GST_TYPE_CAPS,
1996 2, G_TYPE_UINT, G_TYPE_UINT);
1999 * GstRtpBin::payload-type-change:
2000 * @rtpbin: the object which received the signal
2001 * @session: the session
2004 * Signal that the current payload type changed to @pt in @session.
2006 gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] =
2007 g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass),
2008 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, payload_type_change),
2009 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2013 * GstRtpBin::clear-pt-map:
2014 * @rtpbin: the object which received the signal
2016 * Clear all previously cached pt-mapping obtained with
2017 * #GstRtpBin::request-pt-map.
2019 gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] =
2020 g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
2021 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2022 clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
2026 * GstRtpBin::reset-sync:
2027 * @rtpbin: the object which received the signal
2029 * Reset all currently configured lip-sync parameters and require new SR
2030 * packets for all streams before lip-sync is attempted again.
2032 gst_rtp_bin_signals[SIGNAL_RESET_SYNC] =
2033 g_signal_new ("reset-sync", G_TYPE_FROM_CLASS (klass),
2034 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2035 reset_sync), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
2039 * GstRtpBin::get-session:
2040 * @rtpbin: the object which received the signal
2041 * @id: the session id
2043 * Request the related GstRtpSession as #GstElement related with session @id.
2047 gst_rtp_bin_signals[SIGNAL_GET_SESSION] =
2048 g_signal_new ("get-session", G_TYPE_FROM_CLASS (klass),
2049 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2050 get_session), NULL, NULL, g_cclosure_marshal_generic,
2051 GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2054 * GstRtpBin::get-internal-session:
2055 * @rtpbin: the object which received the signal
2056 * @id: the session id
2058 * Request the internal RTPSession object as #GObject in session @id.
2060 gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_SESSION] =
2061 g_signal_new ("get-internal-session", G_TYPE_FROM_CLASS (klass),
2062 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2063 get_internal_session), NULL, NULL, g_cclosure_marshal_generic,
2064 RTP_TYPE_SESSION, 1, G_TYPE_UINT);
2067 * GstRtpBin::on-new-ssrc:
2068 * @rtpbin: the object which received the signal
2069 * @session: the session
2072 * Notify of a new SSRC that entered @session.
2074 gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC] =
2075 g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass),
2076 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_ssrc),
2077 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2080 * GstRtpBin::on-ssrc-collision:
2081 * @rtpbin: the object which received the signal
2082 * @session: the session
2085 * Notify when we have an SSRC collision
2087 gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION] =
2088 g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass),
2089 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_collision),
2090 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2093 * GstRtpBin::on-ssrc-validated:
2094 * @rtpbin: the object which received the signal
2095 * @session: the session
2098 * Notify of a new SSRC that became validated.
2100 gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED] =
2101 g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass),
2102 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_validated),
2103 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2106 * GstRtpBin::on-ssrc-active:
2107 * @rtpbin: the object which received the signal
2108 * @session: the session
2111 * Notify of a SSRC that is active, i.e., sending RTCP.
2113 gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE] =
2114 g_signal_new ("on-ssrc-active", G_TYPE_FROM_CLASS (klass),
2115 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_active),
2116 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2119 * GstRtpBin::on-ssrc-sdes:
2120 * @rtpbin: the object which received the signal
2121 * @session: the session
2124 * Notify of a SSRC that is active, i.e., sending RTCP.
2126 gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES] =
2127 g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass),
2128 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_sdes),
2129 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2133 * GstRtpBin::on-bye-ssrc:
2134 * @rtpbin: the object which received the signal
2135 * @session: the session
2138 * Notify of an SSRC that became inactive because of a BYE packet.
2140 gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC] =
2141 g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass),
2142 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_ssrc),
2143 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2146 * GstRtpBin::on-bye-timeout:
2147 * @rtpbin: the object which received the signal
2148 * @session: the session
2151 * Notify of an SSRC that has timed out because of BYE
2153 gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT] =
2154 g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass),
2155 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_timeout),
2156 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2159 * GstRtpBin::on-timeout:
2160 * @rtpbin: the object which received the signal
2161 * @session: the session
2164 * Notify of an SSRC that has timed out
2166 gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT] =
2167 g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass),
2168 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_timeout),
2169 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2172 * GstRtpBin::on-sender-timeout:
2173 * @rtpbin: the object which received the signal
2174 * @session: the session
2177 * Notify of a sender SSRC that has timed out and became a receiver
2179 gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT] =
2180 g_signal_new ("on-sender-timeout", G_TYPE_FROM_CLASS (klass),
2181 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_sender_timeout),
2182 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2186 * GstRtpBin::on-npt-stop:
2187 * @rtpbin: the object which received the signal
2188 * @session: the session
2191 * Notify that SSRC sender has sent data up to the configured NPT stop time.
2193 gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP] =
2194 g_signal_new ("on-npt-stop", G_TYPE_FROM_CLASS (klass),
2195 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_npt_stop),
2196 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2200 * GstRtpBin::request-rtp-encoder:
2201 * @rtpbin: the object which received the signal
2202 * @session: the session
2204 * Request an RTP encoder element for the given @session. The encoder
2205 * element will be added to the bin if not previously added.
2207 * If no handler is connected, no encoder will be used.
2211 gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_ENCODER] =
2212 g_signal_new ("request-rtp-encoder", G_TYPE_FROM_CLASS (klass),
2213 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2214 request_rtp_encoder), _gst_element_accumulator, NULL,
2215 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2218 * GstRtpBin::request-rtp-decoder:
2219 * @rtpbin: the object which received the signal
2220 * @session: the session
2222 * Request an RTP decoder element for the given @session. The decoder
2223 * element will be added to the bin if not previously added.
2225 * If no handler is connected, no encoder will be used.
2229 gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_DECODER] =
2230 g_signal_new ("request-rtp-decoder", G_TYPE_FROM_CLASS (klass),
2231 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2232 request_rtp_decoder), _gst_element_accumulator, NULL,
2233 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2236 * GstRtpBin::request-rtcp-encoder:
2237 * @rtpbin: the object which received the signal
2238 * @session: the session
2240 * Request an RTCP encoder element for the given @session. The encoder
2241 * element will be added to the bin if not previously added.
2243 * If no handler is connected, no encoder will be used.
2247 gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_ENCODER] =
2248 g_signal_new ("request-rtcp-encoder", G_TYPE_FROM_CLASS (klass),
2249 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2250 request_rtcp_encoder), _gst_element_accumulator, NULL,
2251 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2254 * GstRtpBin::request-rtcp-decoder:
2255 * @rtpbin: the object which received the signal
2256 * @session: the session
2258 * Request an RTCP decoder element for the given @session. The decoder
2259 * element will be added to the bin if not previously added.
2261 * If no handler is connected, no encoder will be used.
2265 gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_DECODER] =
2266 g_signal_new ("request-rtcp-decoder", G_TYPE_FROM_CLASS (klass),
2267 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2268 request_rtcp_decoder), _gst_element_accumulator, NULL,
2269 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2272 * GstRtpBin::new-jitterbuffer:
2273 * @rtpbin: the object which received the signal
2274 * @jitterbuffer: the new jitterbuffer
2275 * @session: the session
2278 * Notify that a new @jitterbuffer was created for @session and @ssrc.
2279 * This signal can, for example, be used to configure @jitterbuffer.
2283 gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER] =
2284 g_signal_new ("new-jitterbuffer", G_TYPE_FROM_CLASS (klass),
2285 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2286 new_jitterbuffer), NULL, NULL, g_cclosure_marshal_generic,
2287 G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT);
2290 * GstRtpBin::request-aux-sender:
2291 * @rtpbin: the object which received the signal
2292 * @session: the session
2294 * Request an AUX sender element for the given @session. The AUX
2295 * element will be added to the bin.
2297 * If no handler is connected, no AUX element will be used.
2301 gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_SENDER] =
2302 g_signal_new ("request-aux-sender", G_TYPE_FROM_CLASS (klass),
2303 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2304 request_aux_sender), _gst_element_accumulator, NULL,
2305 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2307 * GstRtpBin::request-aux-receiver:
2308 * @rtpbin: the object which received the signal
2309 * @session: the session
2311 * Request an AUX receiver element for the given @session. The AUX
2312 * element will be added to the bin.
2314 * If no handler is connected, no AUX element will be used.
2318 gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_RECEIVER] =
2319 g_signal_new ("request-aux-receiver", G_TYPE_FROM_CLASS (klass),
2320 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2321 request_aux_receiver), _gst_element_accumulator, NULL,
2322 g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2324 * GstRtpBin::on-new-sender-ssrc:
2325 * @rtpbin: the object which received the signal
2326 * @session: the session
2327 * @ssrc: the sender SSRC
2329 * Notify of a new sender SSRC that entered @session.
2333 gst_rtp_bin_signals[SIGNAL_ON_NEW_SENDER_SSRC] =
2334 g_signal_new ("on-new-sender-ssrc", G_TYPE_FROM_CLASS (klass),
2335 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_sender_ssrc),
2336 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
2339 * GstRtpBin::on-sender-ssrc-active:
2340 * @rtpbin: the object which received the signal
2341 * @session: the session
2342 * @ssrc: the sender SSRC
2344 * Notify of a sender SSRC that is active, i.e., sending RTCP.
2348 gst_rtp_bin_signals[SIGNAL_ON_SENDER_SSRC_ACTIVE] =
2349 g_signal_new ("on-sender-ssrc-active", G_TYPE_FROM_CLASS (klass),
2350 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2351 on_sender_ssrc_active), NULL, NULL, g_cclosure_marshal_generic,
2352 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2356 * GstRtpBin::on-bundled-ssrc:
2357 * @rtpbin: the object which received the signal
2358 * @ssrc: the bundled SSRC
2360 * Notify of a new incoming bundled SSRC. If no handler is connected to the
2361 * signal then the #GstRtpSession created for the recv_rtp_sink_\%u
2362 * request pad will be managing this new SSRC. However if there is a handler
2363 * connected then the application can decided to dispatch this new stream to
2364 * another session by providing its ID as return value of the handler. This
2365 * can be particularly useful to keep retransmission SSRCs grouped with the
2366 * session for which they handle retransmission.
2370 gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC] =
2371 g_signal_new ("on-bundled-ssrc", G_TYPE_FROM_CLASS (klass),
2372 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2373 on_bundled_ssrc), NULL, NULL,
2374 g_cclosure_marshal_generic, G_TYPE_UINT, 1, G_TYPE_UINT);
2377 g_object_class_install_property (gobject_class, PROP_SDES,
2378 g_param_spec_boxed ("sdes", "SDES",
2379 "The SDES items of this session",
2380 GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2382 g_object_class_install_property (gobject_class, PROP_DO_LOST,
2383 g_param_spec_boolean ("do-lost", "Do Lost",
2384 "Send an event downstream when a packet is lost", DEFAULT_DO_LOST,
2385 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2387 g_object_class_install_property (gobject_class, PROP_AUTOREMOVE,
2388 g_param_spec_boolean ("autoremove", "Auto Remove",
2389 "Automatically remove timed out sources", DEFAULT_AUTOREMOVE,
2390 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2392 g_object_class_install_property (gobject_class, PROP_IGNORE_PT,
2393 g_param_spec_boolean ("ignore-pt", "Ignore PT",
2394 "Do not demultiplex based on PT values", DEFAULT_IGNORE_PT,
2395 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2397 g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
2398 g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
2399 "Use the pipeline running-time to set the NTP time in the RTCP SR messages "
2400 "(DEPRECATED: Use ntp-time-source property)",
2401 DEFAULT_USE_PIPELINE_CLOCK,
2402 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
2404 * GstRtpBin:buffer-mode:
2406 * Control the buffering and timestamping mode used by the jitterbuffer.
2408 g_object_class_install_property (gobject_class, PROP_BUFFER_MODE,
2409 g_param_spec_enum ("buffer-mode", "Buffer Mode",
2410 "Control the buffering algorithm in use", RTP_TYPE_JITTER_BUFFER_MODE,
2411 DEFAULT_BUFFER_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2413 * GstRtpBin:ntp-sync:
2415 * Set the NTP time from the sender reports as the running-time on the
2416 * buffers. When both the sender and receiver have sychronized
2417 * running-time, i.e. when the clock and base-time is shared
2418 * between the receivers and the and the senders, this option can be
2419 * used to synchronize receivers on multiple machines.
2421 g_object_class_install_property (gobject_class, PROP_NTP_SYNC,
2422 g_param_spec_boolean ("ntp-sync", "Sync on NTP clock",
2423 "Synchronize received streams to the NTP clock", DEFAULT_NTP_SYNC,
2424 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2427 * GstRtpBin:rtcp-sync:
2429 * If not synchronizing (directly) to the NTP clock, determines how to sync
2430 * the various streams.
2432 g_object_class_install_property (gobject_class, PROP_RTCP_SYNC,
2433 g_param_spec_enum ("rtcp-sync", "RTCP Sync",
2434 "Use of RTCP SR in synchronization", GST_RTP_BIN_RTCP_SYNC_TYPE,
2435 DEFAULT_RTCP_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2438 * GstRtpBin:rtcp-sync-interval:
2440 * Determines how often to sync streams using RTCP data.
2442 g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_INTERVAL,
2443 g_param_spec_uint ("rtcp-sync-interval", "RTCP Sync Interval",
2444 "RTCP SR interval synchronization (ms) (0 = always)",
2445 0, G_MAXUINT, DEFAULT_RTCP_SYNC_INTERVAL,
2446 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2448 g_object_class_install_property (gobject_class, PROP_DO_SYNC_EVENT,
2449 g_param_spec_boolean ("do-sync-event", "Do Sync Event",
2450 "Send event downstream when a stream is synchronized to the sender",
2451 DEFAULT_DO_SYNC_EVENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2454 * GstRtpBin:do-retransmission:
2456 * Enables RTP retransmission on all streams. To control retransmission on
2457 * a per-SSRC basis, connect to the #GstRtpBin::new-jitterbuffer signal and
2458 * set the #GstRtpJitterBuffer::do-retransmission property on the
2459 * #GstRtpJitterBuffer object instead.
2461 g_object_class_install_property (gobject_class, PROP_DO_RETRANSMISSION,
2462 g_param_spec_boolean ("do-retransmission", "Do retransmission",
2463 "Enable retransmission on all streams",
2464 DEFAULT_DO_RETRANSMISSION,
2465 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2468 * GstRtpBin:rtp-profile:
2470 * Sets the default RTP profile of newly created RTP sessions. The
2471 * profile can be changed afterwards on a per-session basis.
2473 g_object_class_install_property (gobject_class, PROP_RTP_PROFILE,
2474 g_param_spec_enum ("rtp-profile", "RTP Profile",
2475 "Default RTP profile of newly created sessions",
2476 GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
2477 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2479 g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
2480 g_param_spec_enum ("ntp-time-source", "NTP Time Source",
2481 "NTP time source for RTCP packets",
2482 gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
2483 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2485 g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_SEND_TIME,
2486 g_param_spec_boolean ("rtcp-sync-send-time", "RTCP Sync Send Time",
2487 "Use send time or capture time for RTCP sync "
2488 "(TRUE = send time, FALSE = capture time)",
2489 DEFAULT_RTCP_SYNC_SEND_TIME,
2490 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2492 g_object_class_install_property (gobject_class, PROP_MAX_RTCP_RTP_TIME_DIFF,
2493 g_param_spec_int ("max-rtcp-rtp-time-diff", "Max RTCP RTP Time Diff",
2494 "Maximum amount of time in ms that the RTP time in RTCP SRs "
2495 "is allowed to be ahead (-1 disabled)", -1, G_MAXINT,
2496 DEFAULT_MAX_RTCP_RTP_TIME_DIFF,
2497 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2499 g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME,
2500 g_param_spec_uint ("max-dropout-time", "Max dropout time",
2501 "The maximum time (milliseconds) of missing packets tolerated.",
2502 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME,
2503 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2505 g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME,
2506 g_param_spec_uint ("max-misorder-time", "Max misorder time",
2507 "The maximum time (milliseconds) of misordered packets tolerated.",
2508 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME,
2509 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2511 g_object_class_install_property (gobject_class, PROP_RFC7273_SYNC,
2512 g_param_spec_boolean ("rfc7273-sync", "Sync on RFC7273 clock",
2513 "Synchronize received streams to the RFC7273 clock "
2514 "(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC,
2515 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2517 g_object_class_install_property (gobject_class, PROP_MAX_STREAMS,
2518 g_param_spec_uint ("max-streams", "Max Streams",
2519 "The maximum number of streams to create for one session",
2520 0, G_MAXUINT, DEFAULT_MAX_STREAMS,
2521 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2524 * GstRtpBin:max-ts-offset-adjustment:
2526 * Syncing time stamps to NTP time adds a time offset. This parameter
2527 * specifies the maximum number of nanoseconds per frame that this time offset
2528 * may be adjusted with. This is used to avoid sudden large changes to time
2531 g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET_ADJUSTMENT,
2532 g_param_spec_uint64 ("max-ts-offset-adjustment",
2533 "Max Timestamp Offset Adjustment",
2534 "The maximum number of nanoseconds per frame that time stamp offsets "
2535 "may be adjusted (0 = no limit).", 0, G_MAXUINT64,
2536 DEFAULT_MAX_TS_OFFSET_ADJUSTMENT, G_PARAM_READWRITE |
2537 G_PARAM_STATIC_STRINGS));
2540 * GstRtpBin:max-ts-offset:
2542 * Used to set an upper limit of how large a time offset may be. This
2543 * is used to protect against unrealistic values as a result of either
2544 * client,server or clock issues.
2546 g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET,
2547 g_param_spec_int64 ("max-ts-offset", "Max TS Offset",
2548 "The maximum absolute value of the time offset in (nanoseconds). "
2549 "Note, if the ntp-sync parameter is set the default value is "
2550 "changed to 0 (no limit)", 0, G_MAXINT64, DEFAULT_MAX_TS_OFFSET,
2551 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2553 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
2554 gstelement_class->request_new_pad =
2555 GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
2556 gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
2559 gst_element_class_add_static_pad_template (gstelement_class,
2560 &rtpbin_recv_rtp_sink_template);
2561 gst_element_class_add_static_pad_template (gstelement_class,
2562 &rtpbin_recv_rtcp_sink_template);
2563 gst_element_class_add_static_pad_template (gstelement_class,
2564 &rtpbin_send_rtp_sink_template);
2567 gst_element_class_add_static_pad_template (gstelement_class,
2568 &rtpbin_recv_rtp_src_template);
2569 gst_element_class_add_static_pad_template (gstelement_class,
2570 &rtpbin_send_rtcp_src_template);
2571 gst_element_class_add_static_pad_template (gstelement_class,
2572 &rtpbin_send_rtp_src_template);
2574 gst_element_class_set_static_metadata (gstelement_class, "RTP Bin",
2575 "Filter/Network/RTP",
2576 "Real-Time Transport Protocol bin",
2577 "Wim Taymans <wim.taymans@gmail.com>");
2579 gstbin_class->handle_message = GST_DEBUG_FUNCPTR (gst_rtp_bin_handle_message);
2581 klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
2582 klass->reset_sync = GST_DEBUG_FUNCPTR (gst_rtp_bin_reset_sync);
2583 klass->get_session = GST_DEBUG_FUNCPTR (gst_rtp_bin_get_session);
2584 klass->get_internal_session =
2585 GST_DEBUG_FUNCPTR (gst_rtp_bin_get_internal_session);
2586 klass->request_rtp_encoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_encoder);
2587 klass->request_rtp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder);
2588 klass->request_rtcp_encoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_encoder);
2589 klass->request_rtcp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder);
2591 GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
2595 gst_rtp_bin_init (GstRtpBin * rtpbin)
2599 rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
2600 g_mutex_init (&rtpbin->priv->bin_lock);
2601 g_mutex_init (&rtpbin->priv->dyn_lock);
2603 rtpbin->latency_ms = DEFAULT_LATENCY_MS;
2604 rtpbin->latency_ns = DEFAULT_LATENCY_MS * GST_MSECOND;
2605 rtpbin->drop_on_latency = DEFAULT_DROP_ON_LATENCY;
2606 rtpbin->do_lost = DEFAULT_DO_LOST;
2607 rtpbin->ignore_pt = DEFAULT_IGNORE_PT;
2608 rtpbin->ntp_sync = DEFAULT_NTP_SYNC;
2609 rtpbin->rtcp_sync = DEFAULT_RTCP_SYNC;
2610 rtpbin->rtcp_sync_interval = DEFAULT_RTCP_SYNC_INTERVAL;
2611 rtpbin->priv->autoremove = DEFAULT_AUTOREMOVE;
2612 rtpbin->buffer_mode = DEFAULT_BUFFER_MODE;
2613 rtpbin->use_pipeline_clock = DEFAULT_USE_PIPELINE_CLOCK;
2614 rtpbin->send_sync_event = DEFAULT_DO_SYNC_EVENT;
2615 rtpbin->do_retransmission = DEFAULT_DO_RETRANSMISSION;
2616 rtpbin->rtp_profile = DEFAULT_RTP_PROFILE;
2617 rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
2618 rtpbin->rtcp_sync_send_time = DEFAULT_RTCP_SYNC_SEND_TIME;
2619 rtpbin->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF;
2620 rtpbin->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME;
2621 rtpbin->max_misorder_time = DEFAULT_MAX_MISORDER_TIME;
2622 rtpbin->rfc7273_sync = DEFAULT_RFC7273_SYNC;
2623 rtpbin->max_streams = DEFAULT_MAX_STREAMS;
2624 rtpbin->max_ts_offset_adjustment = DEFAULT_MAX_TS_OFFSET_ADJUSTMENT;
2625 rtpbin->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
2626 rtpbin->max_ts_offset_is_set = FALSE;
2628 /* some default SDES entries */
2629 cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ());
2630 rtpbin->sdes = gst_structure_new ("application/x-rtp-source-sdes",
2631 "cname", G_TYPE_STRING, cname, "tool", G_TYPE_STRING, "GStreamer", NULL);
2636 gst_rtp_bin_dispose (GObject * object)
2640 rtpbin = GST_RTP_BIN (object);
2642 GST_RTP_BIN_LOCK (rtpbin);
2643 GST_DEBUG_OBJECT (object, "freeing sessions");
2644 g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin);
2645 g_slist_free (rtpbin->sessions);
2646 rtpbin->sessions = NULL;
2647 GST_RTP_BIN_UNLOCK (rtpbin);
2649 G_OBJECT_CLASS (parent_class)->dispose (object);
2653 gst_rtp_bin_finalize (GObject * object)
2657 rtpbin = GST_RTP_BIN (object);
2660 gst_structure_free (rtpbin->sdes);
2662 g_mutex_clear (&rtpbin->priv->bin_lock);
2663 g_mutex_clear (&rtpbin->priv->dyn_lock);
2665 G_OBJECT_CLASS (parent_class)->finalize (object);
2670 gst_rtp_bin_set_sdes_struct (GstRtpBin * bin, const GstStructure * sdes)
2677 GST_RTP_BIN_LOCK (bin);
2679 GST_OBJECT_LOCK (bin);
2681 gst_structure_free (bin->sdes);
2682 bin->sdes = gst_structure_copy (sdes);
2683 GST_OBJECT_UNLOCK (bin);
2685 /* store in all sessions */
2686 for (item = bin->sessions; item; item = g_slist_next (item)) {
2687 GstRtpBinSession *session = item->data;
2688 g_object_set (session->session, "sdes", sdes, NULL);
2691 GST_RTP_BIN_UNLOCK (bin);
2694 static GstStructure *
2695 gst_rtp_bin_get_sdes_struct (GstRtpBin * bin)
2697 GstStructure *result;
2699 GST_OBJECT_LOCK (bin);
2700 result = gst_structure_copy (bin->sdes);
2701 GST_OBJECT_UNLOCK (bin);
2707 gst_rtp_bin_set_property (GObject * object, guint prop_id,
2708 const GValue * value, GParamSpec * pspec)
2712 rtpbin = GST_RTP_BIN (object);
2716 GST_RTP_BIN_LOCK (rtpbin);
2717 rtpbin->latency_ms = g_value_get_uint (value);
2718 rtpbin->latency_ns = rtpbin->latency_ms * GST_MSECOND;
2719 GST_RTP_BIN_UNLOCK (rtpbin);
2720 /* propagate the property down to the jitterbuffer */
2721 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "latency", value);
2723 case PROP_DROP_ON_LATENCY:
2724 GST_RTP_BIN_LOCK (rtpbin);
2725 rtpbin->drop_on_latency = g_value_get_boolean (value);
2726 GST_RTP_BIN_UNLOCK (rtpbin);
2727 /* propagate the property down to the jitterbuffer */
2728 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2729 "drop-on-latency", value);
2732 gst_rtp_bin_set_sdes_struct (rtpbin, g_value_get_boxed (value));
2735 GST_RTP_BIN_LOCK (rtpbin);
2736 rtpbin->do_lost = g_value_get_boolean (value);
2737 GST_RTP_BIN_UNLOCK (rtpbin);
2738 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "do-lost", value);
2741 rtpbin->ntp_sync = g_value_get_boolean (value);
2742 /* The default value of max_ts_offset depends on ntp_sync. If user
2743 * hasn't set it then change default value */
2744 if (!rtpbin->max_ts_offset_is_set) {
2745 if (rtpbin->ntp_sync) {
2746 rtpbin->max_ts_offset = 0;
2748 rtpbin->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
2752 case PROP_RTCP_SYNC:
2753 g_atomic_int_set (&rtpbin->rtcp_sync, g_value_get_enum (value));
2755 case PROP_RTCP_SYNC_INTERVAL:
2756 rtpbin->rtcp_sync_interval = g_value_get_uint (value);
2758 case PROP_IGNORE_PT:
2759 rtpbin->ignore_pt = g_value_get_boolean (value);
2761 case PROP_AUTOREMOVE:
2762 rtpbin->priv->autoremove = g_value_get_boolean (value);
2764 case PROP_USE_PIPELINE_CLOCK:
2767 GST_RTP_BIN_LOCK (rtpbin);
2768 rtpbin->use_pipeline_clock = g_value_get_boolean (value);
2769 for (sessions = rtpbin->sessions; sessions;
2770 sessions = g_slist_next (sessions)) {
2771 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
2773 g_object_set (G_OBJECT (session->session),
2774 "use-pipeline-clock", rtpbin->use_pipeline_clock, NULL);
2776 GST_RTP_BIN_UNLOCK (rtpbin);
2779 case PROP_DO_SYNC_EVENT:
2780 rtpbin->send_sync_event = g_value_get_boolean (value);
2782 case PROP_BUFFER_MODE:
2783 GST_RTP_BIN_LOCK (rtpbin);
2784 rtpbin->buffer_mode = g_value_get_enum (value);
2785 GST_RTP_BIN_UNLOCK (rtpbin);
2786 /* propagate the property down to the jitterbuffer */
2787 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "mode", value);
2789 case PROP_DO_RETRANSMISSION:
2790 GST_RTP_BIN_LOCK (rtpbin);
2791 rtpbin->do_retransmission = g_value_get_boolean (value);
2792 GST_RTP_BIN_UNLOCK (rtpbin);
2793 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2794 "do-retransmission", value);
2796 case PROP_RTP_PROFILE:
2797 rtpbin->rtp_profile = g_value_get_enum (value);
2799 case PROP_NTP_TIME_SOURCE:{
2801 GST_RTP_BIN_LOCK (rtpbin);
2802 rtpbin->ntp_time_source = g_value_get_enum (value);
2803 for (sessions = rtpbin->sessions; sessions;
2804 sessions = g_slist_next (sessions)) {
2805 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
2807 g_object_set (G_OBJECT (session->session),
2808 "ntp-time-source", rtpbin->ntp_time_source, NULL);
2810 GST_RTP_BIN_UNLOCK (rtpbin);
2813 case PROP_RTCP_SYNC_SEND_TIME:{
2815 GST_RTP_BIN_LOCK (rtpbin);
2816 rtpbin->rtcp_sync_send_time = g_value_get_boolean (value);
2817 for (sessions = rtpbin->sessions; sessions;
2818 sessions = g_slist_next (sessions)) {
2819 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
2821 g_object_set (G_OBJECT (session->session),
2822 "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time, NULL);
2824 GST_RTP_BIN_UNLOCK (rtpbin);
2827 case PROP_MAX_RTCP_RTP_TIME_DIFF:
2828 GST_RTP_BIN_LOCK (rtpbin);
2829 rtpbin->max_rtcp_rtp_time_diff = g_value_get_int (value);
2830 GST_RTP_BIN_UNLOCK (rtpbin);
2831 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2832 "max-rtcp-rtp-time-diff", value);
2834 case PROP_MAX_DROPOUT_TIME:
2835 GST_RTP_BIN_LOCK (rtpbin);
2836 rtpbin->max_dropout_time = g_value_get_uint (value);
2837 GST_RTP_BIN_UNLOCK (rtpbin);
2838 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2839 "max-dropout-time", value);
2840 gst_rtp_bin_propagate_property_to_session (rtpbin, "max-dropout-time",
2843 case PROP_MAX_MISORDER_TIME:
2844 GST_RTP_BIN_LOCK (rtpbin);
2845 rtpbin->max_misorder_time = g_value_get_uint (value);
2846 GST_RTP_BIN_UNLOCK (rtpbin);
2847 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2848 "max-misorder-time", value);
2849 gst_rtp_bin_propagate_property_to_session (rtpbin, "max-misorder-time",
2852 case PROP_RFC7273_SYNC:
2853 rtpbin->rfc7273_sync = g_value_get_boolean (value);
2854 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2855 "rfc7273-sync", value);
2857 case PROP_MAX_STREAMS:
2858 rtpbin->max_streams = g_value_get_uint (value);
2860 case PROP_MAX_TS_OFFSET_ADJUSTMENT:
2861 rtpbin->max_ts_offset_adjustment = g_value_get_uint64 (value);
2862 gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2863 "max-ts-offset-adjustment", value);
2865 case PROP_MAX_TS_OFFSET:
2866 rtpbin->max_ts_offset = g_value_get_int64 (value);
2867 rtpbin->max_ts_offset_is_set = TRUE;
2870 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2876 gst_rtp_bin_get_property (GObject * object, guint prop_id,
2877 GValue * value, GParamSpec * pspec)
2881 rtpbin = GST_RTP_BIN (object);
2885 GST_RTP_BIN_LOCK (rtpbin);
2886 g_value_set_uint (value, rtpbin->latency_ms);
2887 GST_RTP_BIN_UNLOCK (rtpbin);
2889 case PROP_DROP_ON_LATENCY:
2890 GST_RTP_BIN_LOCK (rtpbin);
2891 g_value_set_boolean (value, rtpbin->drop_on_latency);
2892 GST_RTP_BIN_UNLOCK (rtpbin);
2895 g_value_take_boxed (value, gst_rtp_bin_get_sdes_struct (rtpbin));
2898 GST_RTP_BIN_LOCK (rtpbin);
2899 g_value_set_boolean (value, rtpbin->do_lost);
2900 GST_RTP_BIN_UNLOCK (rtpbin);
2902 case PROP_IGNORE_PT:
2903 g_value_set_boolean (value, rtpbin->ignore_pt);
2906 g_value_set_boolean (value, rtpbin->ntp_sync);
2908 case PROP_RTCP_SYNC:
2909 g_value_set_enum (value, g_atomic_int_get (&rtpbin->rtcp_sync));
2911 case PROP_RTCP_SYNC_INTERVAL:
2912 g_value_set_uint (value, rtpbin->rtcp_sync_interval);
2914 case PROP_AUTOREMOVE:
2915 g_value_set_boolean (value, rtpbin->priv->autoremove);
2917 case PROP_BUFFER_MODE:
2918 g_value_set_enum (value, rtpbin->buffer_mode);
2920 case PROP_USE_PIPELINE_CLOCK:
2921 g_value_set_boolean (value, rtpbin->use_pipeline_clock);
2923 case PROP_DO_SYNC_EVENT:
2924 g_value_set_boolean (value, rtpbin->send_sync_event);
2926 case PROP_DO_RETRANSMISSION:
2927 GST_RTP_BIN_LOCK (rtpbin);
2928 g_value_set_boolean (value, rtpbin->do_retransmission);
2929 GST_RTP_BIN_UNLOCK (rtpbin);
2931 case PROP_RTP_PROFILE:
2932 g_value_set_enum (value, rtpbin->rtp_profile);
2934 case PROP_NTP_TIME_SOURCE:
2935 g_value_set_enum (value, rtpbin->ntp_time_source);
2937 case PROP_RTCP_SYNC_SEND_TIME:
2938 g_value_set_boolean (value, rtpbin->rtcp_sync_send_time);
2940 case PROP_MAX_RTCP_RTP_TIME_DIFF:
2941 GST_RTP_BIN_LOCK (rtpbin);
2942 g_value_set_int (value, rtpbin->max_rtcp_rtp_time_diff);
2943 GST_RTP_BIN_UNLOCK (rtpbin);
2945 case PROP_MAX_DROPOUT_TIME:
2946 g_value_set_uint (value, rtpbin->max_dropout_time);
2948 case PROP_MAX_MISORDER_TIME:
2949 g_value_set_uint (value, rtpbin->max_misorder_time);
2951 case PROP_RFC7273_SYNC:
2952 g_value_set_boolean (value, rtpbin->rfc7273_sync);
2954 case PROP_MAX_STREAMS:
2955 g_value_set_uint (value, rtpbin->max_streams);
2957 case PROP_MAX_TS_OFFSET_ADJUSTMENT:
2958 g_value_set_uint64 (value, rtpbin->max_ts_offset_adjustment);
2960 case PROP_MAX_TS_OFFSET:
2961 g_value_set_int64 (value, rtpbin->max_ts_offset);
2964 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2970 gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
2974 rtpbin = GST_RTP_BIN (bin);
2976 switch (GST_MESSAGE_TYPE (message)) {
2977 case GST_MESSAGE_ELEMENT:
2979 const GstStructure *s = gst_message_get_structure (message);
2981 /* we change the structure name and add the session ID to it */
2982 if (gst_structure_has_name (s, "application/x-rtp-source-sdes")) {
2983 GstRtpBinSession *sess;
2985 /* find the session we set it as object data */
2986 sess = g_object_get_data (G_OBJECT (GST_MESSAGE_SRC (message)),
2987 "GstRTPBin.session");
2989 if (G_LIKELY (sess)) {
2990 message = gst_message_make_writable (message);
2991 s = gst_message_get_structure (message);
2992 gst_structure_set ((GstStructure *) s, "session", G_TYPE_UINT,
2996 GST_BIN_CLASS (parent_class)->handle_message (bin, message);
2999 case GST_MESSAGE_BUFFERING:
3002 gint min_percent = 100;
3003 GSList *sessions, *streams;
3004 GstRtpBinStream *stream;
3005 gboolean change = FALSE, active = FALSE;
3006 GstClockTime min_out_time;
3007 GstBufferingMode mode;
3008 gint avg_in, avg_out;
3009 gint64 buffering_left;
3011 gst_message_parse_buffering (message, &percent);
3012 gst_message_parse_buffering_stats (message, &mode, &avg_in, &avg_out,
3016 g_object_get_data (G_OBJECT (GST_MESSAGE_SRC (message)),
3017 "GstRTPBin.stream");
3019 GST_DEBUG_OBJECT (bin, "got percent %d from stream %p", percent, stream);
3021 /* get the stream */
3022 if (G_LIKELY (stream)) {
3023 GST_RTP_BIN_LOCK (rtpbin);
3024 /* fill in the percent */
3025 stream->percent = percent;
3027 /* calculate the min value for all streams */
3028 for (sessions = rtpbin->sessions; sessions;
3029 sessions = g_slist_next (sessions)) {
3030 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
3032 GST_RTP_SESSION_LOCK (session);
3033 if (session->streams) {
3034 for (streams = session->streams; streams;
3035 streams = g_slist_next (streams)) {
3036 GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
3038 GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream,
3041 /* find min percent */
3042 if (min_percent > stream->percent)
3043 min_percent = stream->percent;
3046 GST_INFO_OBJECT (bin,
3047 "session has no streams, setting min_percent to 0");
3050 GST_RTP_SESSION_UNLOCK (session);
3052 GST_DEBUG_OBJECT (bin, "min percent %d", min_percent);
3054 if (rtpbin->buffering) {
3055 if (min_percent == 100) {
3056 rtpbin->buffering = FALSE;
3061 if (min_percent < 100) {
3062 /* pause the streams */
3063 rtpbin->buffering = TRUE;
3068 GST_RTP_BIN_UNLOCK (rtpbin);
3070 gst_message_unref (message);
3072 /* make a new buffering message with the min value */
3074 gst_message_new_buffering (GST_OBJECT_CAST (bin), min_percent);
3075 gst_message_set_buffering_stats (message, mode, avg_in, avg_out,
3078 if (G_UNLIKELY (change)) {
3080 guint64 running_time = 0;
3083 /* figure out the running time when we have a clock */
3084 if (G_LIKELY ((clock =
3085 gst_element_get_clock (GST_ELEMENT_CAST (bin))))) {
3086 guint64 now, base_time;
3088 now = gst_clock_get_time (clock);
3089 base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bin));
3090 running_time = now - base_time;
3091 gst_object_unref (clock);
3093 GST_DEBUG_OBJECT (bin,
3094 "running time now %" GST_TIME_FORMAT,
3095 GST_TIME_ARGS (running_time));
3097 GST_RTP_BIN_LOCK (rtpbin);
3099 /* when we reactivate, calculate the offsets so that all streams have
3100 * an output time that is at least as big as the running_time */
3103 if (running_time > rtpbin->buffer_start) {
3104 offset = running_time - rtpbin->buffer_start;
3105 if (offset >= rtpbin->latency_ns)
3106 offset -= rtpbin->latency_ns;
3112 /* pause all streams */
3114 for (sessions = rtpbin->sessions; sessions;
3115 sessions = g_slist_next (sessions)) {
3116 GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
3118 GST_RTP_SESSION_LOCK (session);
3119 for (streams = session->streams; streams;
3120 streams = g_slist_next (streams)) {
3121 GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
3122 GstElement *element = stream->buffer;
3125 g_signal_emit_by_name (element, "set-active", active, offset,
3129 g_object_get (element, "percent", &stream->percent, NULL);
3133 if (min_out_time == -1 || last_out < min_out_time)
3134 min_out_time = last_out;
3137 GST_DEBUG_OBJECT (bin,
3138 "setting %p to %d, offset %" GST_TIME_FORMAT ", last %"
3139 GST_TIME_FORMAT ", percent %d", element, active,
3140 GST_TIME_ARGS (offset), GST_TIME_ARGS (last_out),
3143 GST_RTP_SESSION_UNLOCK (session);
3145 GST_DEBUG_OBJECT (bin,
3146 "min out time %" GST_TIME_FORMAT, GST_TIME_ARGS (min_out_time));
3148 /* the buffer_start is the min out time of all paused jitterbuffers */
3150 rtpbin->buffer_start = min_out_time;
3152 GST_RTP_BIN_UNLOCK (rtpbin);
3155 GST_BIN_CLASS (parent_class)->handle_message (bin, message);
3160 GST_BIN_CLASS (parent_class)->handle_message (bin, message);
3166 static GstStateChangeReturn
3167 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
3169 GstStateChangeReturn res;
3171 GstRtpBinPrivate *priv;
3173 rtpbin = GST_RTP_BIN (element);
3174 priv = rtpbin->priv;
3176 switch (transition) {
3177 case GST_STATE_CHANGE_NULL_TO_READY:
3179 case GST_STATE_CHANGE_READY_TO_PAUSED:
3180 priv->last_ntpnstime = 0;
3181 GST_LOG_OBJECT (rtpbin, "clearing shutdown flag");
3182 g_atomic_int_set (&priv->shutdown, 0);
3184 case GST_STATE_CHANGE_PAUSED_TO_READY:
3185 GST_LOG_OBJECT (rtpbin, "setting shutdown flag");
3186 g_atomic_int_set (&priv->shutdown, 1);
3187 /* wait for all callbacks to end by taking the lock. No new callbacks will
3188 * be able to happen as we set the shutdown flag. */
3189 GST_RTP_BIN_DYN_LOCK (rtpbin);
3190 GST_LOG_OBJECT (rtpbin, "dynamic lock taken, we can continue shutdown");
3191 GST_RTP_BIN_DYN_UNLOCK (rtpbin);
3197 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3199 switch (transition) {
3200 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3202 case GST_STATE_CHANGE_PAUSED_TO_READY:
3204 case GST_STATE_CHANGE_READY_TO_NULL:
3213 session_request_element (GstRtpBinSession * session, guint signal)
3215 GstElement *element = NULL;
3216 GstRtpBin *bin = session->bin;
3218 g_signal_emit (bin, gst_rtp_bin_signals[signal], 0, session->id, &element);
3221 if (!bin_manage_element (bin, element))
3223 session->elements = g_slist_prepend (session->elements, element);
3230 GST_WARNING_OBJECT (bin, "unable to manage element");
3231 gst_object_unref (element);
3237 copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
3239 GstPad *gpad = GST_PAD_CAST (user_data);
3241 GST_DEBUG_OBJECT (gpad, "store sticky event %" GST_PTR_FORMAT, *event);
3242 gst_pad_store_sticky_event (gpad, *event);
3247 /* a new pad (SSRC) was created in @session. This signal is emited from the
3248 * payload demuxer. */
3250 new_payload_found (GstElement * element, guint pt, GstPad * pad,
3251 GstRtpBinStream * stream)
3254 GstElementClass *klass;
3255 GstPadTemplate *templ;
3259 rtpbin = stream->bin;
3261 GST_DEBUG_OBJECT (rtpbin, "new payload pad %u", pt);
3263 GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
3265 /* ghost the pad to the parent */
3266 klass = GST_ELEMENT_GET_CLASS (rtpbin);
3267 templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u");
3268 padname = g_strdup_printf ("recv_rtp_src_%u_%u_%u",
3269 stream->session->id, stream->ssrc, pt);
3270 gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
3272 g_object_set_data (G_OBJECT (pad), "GstRTPBin.ghostpad", gpad);
3274 gst_pad_set_active (gpad, TRUE);
3275 GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3277 gst_pad_sticky_events_foreach (pad, copy_sticky_events, gpad);
3278 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
3284 GST_DEBUG ("ignoring, we are shutting down");
3290 payload_pad_removed (GstElement * element, GstPad * pad,
3291 GstRtpBinStream * stream)
3296 rtpbin = stream->bin;
3298 GST_DEBUG ("payload pad removed");
3300 GST_RTP_BIN_DYN_LOCK (rtpbin);
3301 if ((gpad = g_object_get_data (G_OBJECT (pad), "GstRTPBin.ghostpad"))) {
3302 g_object_set_data (G_OBJECT (pad), "GstRTPBin.ghostpad", NULL);
3304 gst_pad_set_active (gpad, FALSE);
3305 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), gpad);
3307 GST_RTP_BIN_DYN_UNLOCK (rtpbin);
3311 pt_map_requested (GstElement * element, guint pt, GstRtpBinSession * session)
3316 rtpbin = session->bin;
3318 GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %u in session %u", pt,
3321 caps = get_pt_map (session, pt);
3330 GST_DEBUG_OBJECT (rtpbin, "could not get caps");
3336 payload_type_change (GstElement * element, guint pt, GstRtpBinSession * session)
3338 GST_DEBUG_OBJECT (session->bin,
3339 "emiting signal for pt type changed to %u in session %u", pt,
3342 g_signal_emit (session->bin, gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE],
3343 0, session->id, pt);
3346 /* emited when caps changed for the session */
3348 caps_changed (GstPad * pad, GParamSpec * pspec, GstRtpBinSession * session)
3353 const GstStructure *s;
3357 g_object_get (pad, "caps", &caps, NULL);
3362 GST_DEBUG_OBJECT (bin, "got caps %" GST_PTR_FORMAT, caps);
3364 s = gst_caps_get_structure (caps, 0);
3366 /* get payload, finish when it's not there */
3367 if (!gst_structure_get_int (s, "payload", &payload)) {
3368 gst_caps_unref (caps);
3372 GST_RTP_SESSION_LOCK (session);
3373 GST_DEBUG_OBJECT (bin, "insert caps for payload %d", payload);
3374 g_hash_table_insert (session->ptmap, GINT_TO_POINTER (payload), caps);
3375 GST_RTP_SESSION_UNLOCK (session);
3378 /* a new pad (SSRC) was created in @session */
3380 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
3381 GstRtpBinSession * session)
3384 GstRtpBinStream *stream;
3385 GstPad *sinkpad, *srcpad;
3388 rtpbin = session->bin;
3390 GST_DEBUG_OBJECT (rtpbin, "new SSRC pad %08x, %s:%s", ssrc,
3391 GST_DEBUG_PAD_NAME (pad));
3393 GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
3395 GST_RTP_SESSION_LOCK (session);
3397 /* create new stream */
3398 stream = create_stream (session, ssrc);
3402 /* get pad and link */
3403 GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTP");
3404 padname = g_strdup_printf ("src_%u", ssrc);
3405 srcpad = gst_element_get_static_pad (element, padname);
3407 sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
3408 gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
3409 gst_object_unref (sinkpad);
3410 gst_object_unref (srcpad);
3412 GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTCP");
3413 padname = g_strdup_printf ("rtcp_src_%u", ssrc);
3414 srcpad = gst_element_get_static_pad (element, padname);
3416 sinkpad = gst_element_get_request_pad (stream->buffer, "sink_rtcp");
3417 gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
3418 gst_object_unref (sinkpad);
3419 gst_object_unref (srcpad);
3421 /* connect to the RTCP sync signal from the jitterbuffer */
3422 GST_DEBUG_OBJECT (rtpbin, "connecting sync signal");
3423 stream->buffer_handlesync_sig = g_signal_connect (stream->buffer,
3424 "handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream);
3426 if (stream->demux) {
3427 /* connect to the new-pad signal of the payload demuxer, this will expose the
3428 * new pad by ghosting it. */
3429 stream->demux_newpad_sig = g_signal_connect (stream->demux,
3430 "new-payload-type", (GCallback) new_payload_found, stream);
3431 stream->demux_padremoved_sig = g_signal_connect (stream->demux,
3432 "pad-removed", (GCallback) payload_pad_removed, stream);
3434 /* connect to the request-pt-map signal. This signal will be emited by the
3435 * demuxer so that it can apply a proper caps on the buffers for the
3437 stream->demux_ptreq_sig = g_signal_connect (stream->demux,
3438 "request-pt-map", (GCallback) pt_map_requested, session);
3439 /* connect to the signal so it can be forwarded. */
3440 stream->demux_ptchange_sig = g_signal_connect (stream->demux,
3441 "payload-type-change", (GCallback) payload_type_change, session);
3443 /* add rtpjitterbuffer src pad to pads */
3444 GstElementClass *klass;
3445 GstPadTemplate *templ;
3449 pad = gst_element_get_static_pad (stream->buffer, "src");
3451 /* ghost the pad to the parent */
3452 klass = GST_ELEMENT_GET_CLASS (rtpbin);
3453 templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u");
3454 padname = g_strdup_printf ("recv_rtp_src_%u_%u_%u",
3455 stream->session->id, stream->ssrc, 255);
3456 gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
3459 gst_pad_set_active (gpad, TRUE);
3460 gst_pad_sticky_events_foreach (pad, copy_sticky_events, gpad);
3461 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
3463 gst_object_unref (pad);
3466 GST_RTP_SESSION_UNLOCK (session);
3467 GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3474 GST_DEBUG_OBJECT (rtpbin, "we are shutting down");
3479 GST_RTP_SESSION_UNLOCK (session);
3480 GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3481 GST_DEBUG_OBJECT (rtpbin, "could not create stream");
3487 session_maybe_create_bundle_demuxer (GstRtpBinSession * session)
3491 if (session->bundle_demux)
3494 rtpbin = session->bin;
3495 if (g_signal_has_handler_pending (rtpbin,
3496 gst_rtp_bin_signals[SIGNAL_ON_BUNDLED_SSRC], 0, TRUE)) {
3497 GST_DEBUG_OBJECT (rtpbin, "Adding a bundle SSRC demuxer to session %u",
3499 session->bundle_demux = gst_element_factory_make ("rtpssrcdemux", NULL);
3500 session->bundle_demux_newpad_sig = g_signal_connect (session->bundle_demux,
3501 "new-ssrc-pad", (GCallback) new_bundled_ssrc_pad_found, session);
3503 gst_bin_add (GST_BIN_CAST (rtpbin), session->bundle_demux);
3504 gst_element_sync_state_with_parent (session->bundle_demux);
3506 GST_DEBUG_OBJECT (rtpbin,
3507 "No handler for the on-bundled-ssrc signal so no need for a bundle SSRC demuxer in session %u",
3513 complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session,
3514 gboolean bundle_demuxer_needed)
3516 guint sessid = session->id;
3517 GstPad *recv_rtp_sink;
3519 GstElement *decoder;
3521 g_assert (!session->recv_rtp_sink);
3523 /* get recv_rtp pad and store */
3524 session->recv_rtp_sink =
3525 gst_element_get_request_pad (session->session, "recv_rtp_sink");
3526 if (session->recv_rtp_sink == NULL)
3529 g_signal_connect (session->recv_rtp_sink, "notify::caps",
3530 (GCallback) caps_changed, session);
3532 if (bundle_demuxer_needed)
3533 session_maybe_create_bundle_demuxer (session);
3535 GST_DEBUG_OBJECT (rtpbin, "requesting RTP decoder");
3536 decoder = session_request_element (session, SIGNAL_REQUEST_RTP_DECODER);
3538 GstPad *decsrc, *decsink;
3539 GstPadLinkReturn ret;
3541 GST_DEBUG_OBJECT (rtpbin, "linking RTP decoder");
3542 decsink = gst_element_get_static_pad (decoder, "rtp_sink");
3543 if (decsink == NULL)
3544 goto dec_sink_failed;
3546 recv_rtp_sink = decsink;
3548 decsrc = gst_element_get_static_pad (decoder, "rtp_src");
3550 goto dec_src_failed;
3552 if (session->bundle_demux) {
3554 demux_sink = gst_element_get_static_pad (session->bundle_demux, "sink");
3555 ret = gst_pad_link (decsrc, demux_sink);
3556 gst_object_unref (demux_sink);
3558 ret = gst_pad_link (decsrc, session->recv_rtp_sink);
3560 gst_object_unref (decsrc);
3562 if (ret != GST_PAD_LINK_OK)
3563 goto dec_link_failed;
3566 GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given");
3567 if (session->bundle_demux) {
3569 gst_element_get_static_pad (session->bundle_demux, "sink");
3572 gst_element_get_request_pad (session->rtp_funnel, "sink_%u");
3576 funnel_src = gst_element_get_static_pad (session->rtp_funnel, "src");
3577 gst_pad_link (funnel_src, session->recv_rtp_sink);
3578 gst_object_unref (funnel_src);
3580 return recv_rtp_sink;
3585 g_warning ("rtpbin: failed to get session recv_rtp_sink pad");
3590 g_warning ("rtpbin: failed to get decoder sink pad for session %u", sessid);
3595 g_warning ("rtpbin: failed to get decoder src pad for session %u", sessid);
3596 gst_object_unref (recv_rtp_sink);
3601 g_warning ("rtpbin: failed to link rtp decoder for session %u", sessid);
3602 gst_object_unref (recv_rtp_sink);
3608 complete_session_receiver (GstRtpBin * rtpbin, GstRtpBinSession * session,
3612 GstPad *recv_rtp_src;
3614 g_assert (!session->recv_rtp_src);
3616 session->recv_rtp_src =
3617 gst_element_get_static_pad (session->session, "recv_rtp_src");
3618 if (session->recv_rtp_src == NULL)
3621 /* find out if we need AUX elements or if we can go into the SSRC demuxer
3623 aux = session_request_element (session, SIGNAL_REQUEST_AUX_RECEIVER);
3627 GstPadLinkReturn ret;
3629 GST_DEBUG_OBJECT (rtpbin, "linking AUX receiver");
3631 pname = g_strdup_printf ("sink_%u", sessid);
3632 auxsink = gst_element_get_static_pad (aux, pname);
3634 if (auxsink == NULL)
3635 goto aux_sink_failed;
3637 ret = gst_pad_link (session->recv_rtp_src, auxsink);
3638 gst_object_unref (auxsink);
3639 if (ret != GST_PAD_LINK_OK)
3640 goto aux_link_failed;
3642 /* this can be NULL when this AUX element is not to be linked to
3643 * an SSRC demuxer */
3644 pname = g_strdup_printf ("src_%u", sessid);
3645 recv_rtp_src = gst_element_get_static_pad (aux, pname);
3648 recv_rtp_src = gst_object_ref (session->recv_rtp_src);
3654 GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
3655 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
3656 GST_DEBUG_OBJECT (rtpbin, "linking demuxer RTP sink pad");
3657 gst_pad_link_full (recv_rtp_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING);
3658 gst_object_unref (sinkdpad);
3659 gst_object_unref (recv_rtp_src);
3661 /* connect to the new-ssrc-pad signal of the SSRC demuxer */
3662 session->demux_newpad_sig = g_signal_connect (session->demux,
3663 "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
3664 session->demux_padremoved_sig = g_signal_connect (session->demux,
3665 "removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session);
3672 g_warning ("rtpbin: failed to get session recv_rtp_src pad");
3677 g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
3682 g_warning ("rtpbin: failed to link AUX pad to session %u", sessid);
3687 /* Create a pad for receiving RTP for the session in @name. Must be called with
3691 create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
3694 GstRtpBinSession *session;
3695 GstPad *recv_rtp_sink;
3697 /* first get the session number */
3698 if (name == NULL || sscanf (name, "recv_rtp_sink_%u", &sessid) != 1)
3701 GST_DEBUG_OBJECT (rtpbin, "finding session %u", sessid);
3703 /* get or create session */
3704 session = find_session_by_id (rtpbin, sessid);
3706 GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
3707 /* create session now */
3708 session = create_session (rtpbin, sessid);
3709 if (session == NULL)
3713 /* check if pad was requested */
3714 if (session->recv_rtp_sink_ghost != NULL)
3715 return session->recv_rtp_sink_ghost;
3717 /* setup the session sink pad */
3718 recv_rtp_sink = complete_session_sink (rtpbin, session, TRUE);
3720 goto session_sink_failed;
3723 GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
3724 session->recv_rtp_sink_ghost =
3725 gst_ghost_pad_new_from_template (name, recv_rtp_sink, templ);
3726 gst_object_unref (recv_rtp_sink);
3727 gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
3728 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
3730 complete_session_receiver (rtpbin, session, sessid);
3732 return session->recv_rtp_sink_ghost;
3737 g_warning ("rtpbin: invalid name given");
3742 /* create_session already warned */
3745 session_sink_failed:
3747 /* warning already done */
3753 remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
3755 if (session->demux_newpad_sig) {
3756 g_signal_handler_disconnect (session->demux, session->demux_newpad_sig);
3757 session->demux_newpad_sig = 0;
3759 if (session->demux_padremoved_sig) {
3760 g_signal_handler_disconnect (session->demux, session->demux_padremoved_sig);
3761 session->demux_padremoved_sig = 0;
3763 if (session->bundle_demux_newpad_sig) {
3764 g_signal_handler_disconnect (session->bundle_demux,
3765 session->bundle_demux_newpad_sig);
3766 session->bundle_demux_newpad_sig = 0;
3768 if (session->recv_rtp_src) {
3769 gst_object_unref (session->recv_rtp_src);
3770 session->recv_rtp_src = NULL;
3772 if (session->recv_rtp_sink) {
3773 gst_element_release_request_pad (session->session, session->recv_rtp_sink);
3774 gst_object_unref (session->recv_rtp_sink);
3775 session->recv_rtp_sink = NULL;
3777 if (session->recv_rtp_sink_ghost) {
3778 gst_pad_set_active (session->recv_rtp_sink_ghost, FALSE);
3779 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
3780 session->recv_rtp_sink_ghost);
3781 session->recv_rtp_sink_ghost = NULL;
3786 complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session,
3787 guint sessid, gboolean bundle_demuxer_needed)
3789 GstElement *decoder;
3791 GstPad *decsink = NULL;
3794 /* get recv_rtp pad and store */
3795 GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
3796 session->recv_rtcp_sink =
3797 gst_element_get_request_pad (session->session, "recv_rtcp_sink");
3798 if (session->recv_rtcp_sink == NULL)
3801 if (bundle_demuxer_needed)
3802 session_maybe_create_bundle_demuxer (session);
3804 GST_DEBUG_OBJECT (rtpbin, "getting RTCP decoder");
3805 decoder = session_request_element (session, SIGNAL_REQUEST_RTCP_DECODER);
3808 GstPadLinkReturn ret;
3810 GST_DEBUG_OBJECT (rtpbin, "linking RTCP decoder");
3811 decsink = gst_element_get_static_pad (decoder, "rtcp_sink");
3812 decsrc = gst_element_get_static_pad (decoder, "rtcp_src");
3814 if (decsink == NULL)
3815 goto dec_sink_failed;
3818 goto dec_src_failed;
3820 if (session->bundle_demux) {
3823 gst_element_get_static_pad (session->bundle_demux, "rtcp_sink");
3824 ret = gst_pad_link (decsrc, demux_sink);
3825 gst_object_unref (demux_sink);
3827 ret = gst_pad_link (decsrc, session->recv_rtcp_sink);
3829 gst_object_unref (decsrc);
3831 if (ret != GST_PAD_LINK_OK)
3832 goto dec_link_failed;
3834 GST_DEBUG_OBJECT (rtpbin, "no RTCP decoder given");
3835 if (session->bundle_demux) {
3836 decsink = gst_element_get_static_pad (session->bundle_demux, "rtcp_sink");
3838 decsink = gst_element_get_request_pad (session->rtcp_funnel, "sink_%u");
3842 /* get srcpad, link to SSRCDemux */
3843 GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
3844 session->sync_src = gst_element_get_static_pad (session->session, "sync_src");
3845 if (session->sync_src == NULL)
3846 goto src_pad_failed;
3848 GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTCP sink pad");
3849 sinkdpad = gst_element_get_static_pad (session->demux, "rtcp_sink");
3850 gst_pad_link_full (session->sync_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING);
3851 gst_object_unref (sinkdpad);
3853 funnel_src = gst_element_get_static_pad (session->rtcp_funnel, "src");
3854 gst_pad_link (funnel_src, session->recv_rtcp_sink);
3855 gst_object_unref (funnel_src);
3861 g_warning ("rtpbin: failed to get session rtcp_sink pad");
3866 g_warning ("rtpbin: failed to get decoder sink pad for session %u", sessid);
3871 g_warning ("rtpbin: failed to get decoder src pad for session %u", sessid);
3876 g_warning ("rtpbin: failed to link rtcp decoder for session %u", sessid);
3881 g_warning ("rtpbin: failed to get session sync_src pad");
3885 gst_object_unref (decsink);
3889 /* Create a pad for receiving RTCP for the session in @name. Must be called with
3893 create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
3897 GstRtpBinSession *session;
3898 GstPad *decsink = NULL;
3900 /* first get the session number */
3901 if (name == NULL || sscanf (name, "recv_rtcp_sink_%u", &sessid) != 1)
3904 GST_DEBUG_OBJECT (rtpbin, "finding session %u", sessid);
3906 /* get or create the session */
3907 session = find_session_by_id (rtpbin, sessid);
3909 GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
3910 /* create session now */
3911 session = create_session (rtpbin, sessid);
3912 if (session == NULL)
3916 /* check if pad was requested */
3917 if (session->recv_rtcp_sink_ghost != NULL)
3918 return session->recv_rtcp_sink_ghost;
3920 decsink = complete_session_rtcp (rtpbin, session, sessid, TRUE);
3924 session->recv_rtcp_sink_ghost =
3925 gst_ghost_pad_new_from_template (name, decsink, templ);
3926 gst_object_unref (decsink);
3927 gst_pad_set_active (session->recv_rtcp_sink_ghost, TRUE);
3928 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin),
3929 session->recv_rtcp_sink_ghost);
3931 return session->recv_rtcp_sink_ghost;
3936 g_warning ("rtpbin: invalid name given");
3941 /* create_session already warned */
3947 remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
3949 if (session->recv_rtcp_sink_ghost) {
3950 gst_pad_set_active (session->recv_rtcp_sink_ghost, FALSE);
3951 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
3952 session->recv_rtcp_sink_ghost);
3953 session->recv_rtcp_sink_ghost = NULL;
3955 if (session->sync_src) {
3956 /* releasing the request pad should also unref the sync pad */
3957 gst_object_unref (session->sync_src);
3958 session->sync_src = NULL;
3960 if (session->recv_rtcp_sink) {
3961 gst_element_release_request_pad (session->session, session->recv_rtcp_sink);
3962 gst_object_unref (session->recv_rtcp_sink);
3963 session->recv_rtcp_sink = NULL;
3968 complete_session_src (GstRtpBin * rtpbin, GstRtpBinSession * session)
3971 guint sessid = session->id;
3972 GstPad *send_rtp_src;
3973 GstElement *encoder;
3974 GstElementClass *klass;
3975 GstPadTemplate *templ;
3978 session->send_rtp_src =
3979 gst_element_get_static_pad (session->session, "send_rtp_src");
3980 if (session->send_rtp_src == NULL)
3983 GST_DEBUG_OBJECT (rtpbin, "getting RTP encoder");
3984 encoder = session_request_element (session, SIGNAL_REQUEST_RTP_ENCODER);
3987 GstPad *encsrc, *encsink;
3988 GstPadLinkReturn ret;
3990 GST_DEBUG_OBJECT (rtpbin, "linking RTP encoder");
3991 ename = g_strdup_printf ("rtp_src_%u", sessid);
3992 encsrc = gst_element_get_static_pad (encoder, ename);
3996 goto enc_src_failed;
3998 send_rtp_src = encsrc;
4000 ename = g_strdup_printf ("rtp_sink_%u", sessid);
4001 encsink = gst_element_get_static_pad (encoder, ename);
4003 if (encsink == NULL)
4004 goto enc_sink_failed;
4006 ret = gst_pad_link (session->send_rtp_src, encsink);
4007 gst_object_unref (encsink);
4009 if (ret != GST_PAD_LINK_OK)
4010 goto enc_link_failed;
4012 GST_DEBUG_OBJECT (rtpbin, "no RTP encoder given");
4013 send_rtp_src = gst_object_ref (session->send_rtp_src);
4016 /* ghost the new source pad */
4017 klass = GST_ELEMENT_GET_CLASS (rtpbin);
4018 gname = g_strdup_printf ("send_rtp_src_%u", sessid);
4019 templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%u");
4020 session->send_rtp_src_ghost =
4021 gst_ghost_pad_new_from_template (gname, send_rtp_src, templ);
4022 gst_object_unref (send_rtp_src);
4023 gst_pad_set_active (session->send_rtp_src_ghost, TRUE);
4024 gst_pad_sticky_events_foreach (send_rtp_src, copy_sticky_events,
4025 session->send_rtp_src_ghost);
4026 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost);
4034 g_warning ("rtpbin: failed to get rtp source pad for session %u", sessid);
4039 g_warning ("rtpbin: failed to get encoder src pad for session %u", sessid);
4044 g_warning ("rtpbin: failed to get encoder sink pad for session %u", sessid);
4045 gst_object_unref (send_rtp_src);
4050 g_warning ("rtpbin: failed to link rtp encoder for session %u", sessid);
4051 gst_object_unref (send_rtp_src);
4057 setup_aux_sender_fold (const GValue * item, GValue * result, gpointer user_data)
4062 GstRtpBinSession *session = user_data, *newsess;
4063 GstRtpBin *rtpbin = session->bin;
4064 GstPadLinkReturn ret;
4066 pad = g_value_get_object (item);
4067 name = gst_pad_get_name (pad);
4069 if (name == NULL || sscanf (name, "src_%u", &sessid) != 1)
4074 newsess = find_session_by_id (rtpbin, sessid);
4075 if (newsess == NULL) {
4076 /* create new session */
4077 newsess = create_session (rtpbin, sessid);
4078 if (newsess == NULL)
4080 } else if (newsess->send_rtp_sink != NULL)
4081 goto existing_session;
4083 /* get send_rtp pad and store */
4084 newsess->send_rtp_sink =
4085 gst_element_get_request_pad (newsess->session, "send_rtp_sink");
4086 if (newsess->send_rtp_sink == NULL)
4089 ret = gst_pad_link (pad, newsess->send_rtp_sink);
4090 if (ret != GST_PAD_LINK_OK)
4091 goto aux_link_failed;
4093 if (!complete_session_src (rtpbin, newsess))
4094 goto session_src_failed;
4101 GST_WARNING ("ignoring invalid pad name %s", GST_STR_NULL (name));
4107 /* create_session already warned */
4112 g_warning ("rtpbin: session %u is already a sender", sessid);
4117 g_warning ("rtpbin: failed to get session pad for session %u", sessid);
4122 g_warning ("rtpbin: failed to link AUX for session %u", sessid);
4127 g_warning ("rtpbin: failed to complete AUX for session %u", sessid);
4133 setup_aux_sender (GstRtpBin * rtpbin, GstRtpBinSession * session,
4137 GValue result = { 0, };
4138 GstIteratorResult res;
4140 it = gst_element_iterate_src_pads (aux);
4141 res = gst_iterator_fold (it, setup_aux_sender_fold, &result, session);
4142 gst_iterator_free (it);
4144 return res == GST_ITERATOR_DONE;
4147 /* Create a pad for sending RTP for the session in @name. Must be called with
4151 create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
4155 GstPad *send_rtp_sink;
4157 GstRtpBinSession *session;
4159 /* first get the session number */
4160 if (name == NULL || sscanf (name, "send_rtp_sink_%u", &sessid) != 1)
4163 /* get or create session */
4164 session = find_session_by_id (rtpbin, sessid);
4166 /* create session now */
4167 session = create_session (rtpbin, sessid);
4168 if (session == NULL)
4172 /* check if pad was requested */
4173 if (session->send_rtp_sink_ghost != NULL)
4174 return session->send_rtp_sink_ghost;
4176 /* check if we are already using this session as a sender */
4177 if (session->send_rtp_sink != NULL)
4178 goto existing_session;
4180 GST_DEBUG_OBJECT (rtpbin, "getting RTP AUX sender");
4181 aux = session_request_element (session, SIGNAL_REQUEST_AUX_SENDER);
4183 GST_DEBUG_OBJECT (rtpbin, "linking AUX sender");
4184 if (!setup_aux_sender (rtpbin, session, aux))
4185 goto aux_session_failed;
4187 pname = g_strdup_printf ("sink_%u", sessid);
4188 send_rtp_sink = gst_element_get_static_pad (aux, pname);
4191 if (send_rtp_sink == NULL)
4192 goto aux_sink_failed;
4194 /* get send_rtp pad and store */
4195 session->send_rtp_sink =
4196 gst_element_get_request_pad (session->session, "send_rtp_sink");
4197 if (session->send_rtp_sink == NULL)
4200 if (!complete_session_src (rtpbin, session))
4201 goto session_src_failed;
4203 send_rtp_sink = gst_object_ref (session->send_rtp_sink);
4206 session->send_rtp_sink_ghost =
4207 gst_ghost_pad_new_from_template (name, send_rtp_sink, templ);
4208 gst_object_unref (send_rtp_sink);
4209 gst_pad_set_active (session->send_rtp_sink_ghost, TRUE);
4210 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_ghost);
4212 return session->send_rtp_sink_ghost;
4217 g_warning ("rtpbin: invalid name given");
4222 /* create_session already warned */
4227 g_warning ("rtpbin: session %u is already in use", sessid);
4232 g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
4237 g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
4242 g_warning ("rtpbin: failed to get session pad for session %u", sessid);
4247 g_warning ("rtpbin: failed to setup source pads for session %u", sessid);
4253 remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4255 if (session->send_rtp_src_ghost) {
4256 gst_pad_set_active (session->send_rtp_src_ghost, FALSE);
4257 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4258 session->send_rtp_src_ghost);
4259 session->send_rtp_src_ghost = NULL;
4261 if (session->send_rtp_src) {
4262 gst_object_unref (session->send_rtp_src);
4263 session->send_rtp_src = NULL;
4265 if (session->send_rtp_sink) {
4266 gst_element_release_request_pad (GST_ELEMENT_CAST (session->session),
4267 session->send_rtp_sink);
4268 gst_object_unref (session->send_rtp_sink);
4269 session->send_rtp_sink = NULL;
4271 if (session->send_rtp_sink_ghost) {
4272 gst_pad_set_active (session->send_rtp_sink_ghost, FALSE);
4273 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4274 session->send_rtp_sink_ghost);
4275 session->send_rtp_sink_ghost = NULL;
4279 /* Create a pad for sending RTCP for the session in @name. Must be called with
4283 create_send_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
4288 GstElement *encoder;
4289 GstRtpBinSession *session;
4291 /* first get the session number */
4292 if (name == NULL || sscanf (name, "send_rtcp_src_%u", &sessid) != 1)
4295 /* get or create session */
4296 session = find_session_by_id (rtpbin, sessid);
4298 GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
4299 /* create session now */
4300 session = create_session (rtpbin, sessid);
4301 if (session == NULL)
4305 /* check if pad was requested */
4306 if (session->send_rtcp_src_ghost != NULL)
4307 return session->send_rtcp_src_ghost;
4309 /* get rtcp_src pad and store */
4310 session->send_rtcp_src =
4311 gst_element_get_request_pad (session->session, "send_rtcp_src");
4312 if (session->send_rtcp_src == NULL)
4315 GST_DEBUG_OBJECT (rtpbin, "getting RTCP encoder");
4316 encoder = session_request_element (session, SIGNAL_REQUEST_RTCP_ENCODER);
4320 GstPadLinkReturn ret;
4322 GST_DEBUG_OBJECT (rtpbin, "linking RTCP encoder");
4324 ename = g_strdup_printf ("rtcp_src_%u", sessid);
4325 encsrc = gst_element_get_static_pad (encoder, ename);
4328 goto enc_src_failed;
4330 ename = g_strdup_printf ("rtcp_sink_%u", sessid);
4331 encsink = gst_element_get_static_pad (encoder, ename);
4333 if (encsink == NULL)
4334 goto enc_sink_failed;
4336 ret = gst_pad_link (session->send_rtcp_src, encsink);
4337 gst_object_unref (encsink);
4339 if (ret != GST_PAD_LINK_OK)
4340 goto enc_link_failed;
4342 GST_DEBUG_OBJECT (rtpbin, "no RTCP encoder given");
4343 encsrc = gst_object_ref (session->send_rtcp_src);
4346 session->send_rtcp_src_ghost =
4347 gst_ghost_pad_new_from_template (name, encsrc, templ);
4348 gst_object_unref (encsrc);
4349 gst_pad_set_active (session->send_rtcp_src_ghost, TRUE);
4350 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtcp_src_ghost);
4352 return session->send_rtcp_src_ghost;
4357 g_warning ("rtpbin: invalid name given");
4362 /* create_session already warned */
4367 g_warning ("rtpbin: failed to get rtcp pad for session %u", sessid);
4372 g_warning ("rtpbin: failed to get encoder src pad for session %u", sessid);
4377 g_warning ("rtpbin: failed to get encoder sink pad for session %u", sessid);
4378 gst_object_unref (encsrc);
4383 g_warning ("rtpbin: failed to link rtcp encoder for session %u", sessid);
4384 gst_object_unref (encsrc);
4390 remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4392 if (session->send_rtcp_src_ghost) {
4393 gst_pad_set_active (session->send_rtcp_src_ghost, FALSE);
4394 gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4395 session->send_rtcp_src_ghost);
4396 session->send_rtcp_src_ghost = NULL;
4398 if (session->send_rtcp_src) {
4399 gst_element_release_request_pad (session->session, session->send_rtcp_src);
4400 gst_object_unref (session->send_rtcp_src);
4401 session->send_rtcp_src = NULL;
4405 /* If the requested name is NULL we should create a name with
4406 * the session number assuming we want the lowest posible session
4407 * with a free pad like the template */
4409 gst_rtp_bin_get_free_pad_name (GstElement * element, GstPadTemplate * templ)
4411 gboolean name_found = FALSE;
4413 GstIterator *pad_it = NULL;
4414 gchar *pad_name = NULL;
4415 GValue data = { 0, };
4417 GST_DEBUG_OBJECT (element, "find a free pad name for template");
4418 while (!name_found) {
4419 gboolean done = FALSE;
4422 pad_name = g_strdup_printf (templ->name_template, session++);
4423 pad_it = gst_element_iterate_pads (GST_ELEMENT (element));
4426 switch (gst_iterator_next (pad_it, &data)) {
4427 case GST_ITERATOR_OK:
4432 pad = g_value_get_object (&data);
4433 name = gst_pad_get_name (pad);
4435 if (strcmp (name, pad_name) == 0) {
4440 g_value_reset (&data);
4443 case GST_ITERATOR_ERROR:
4444 case GST_ITERATOR_RESYNC:
4445 /* restart iteration */
4450 case GST_ITERATOR_DONE:
4455 g_value_unset (&data);
4456 gst_iterator_free (pad_it);
4459 GST_DEBUG_OBJECT (element, "free pad name found: '%s'", pad_name);
4466 gst_rtp_bin_request_new_pad (GstElement * element,
4467 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
4470 GstElementClass *klass;
4473 gchar *pad_name = NULL;
4475 g_return_val_if_fail (templ != NULL, NULL);
4476 g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
4478 rtpbin = GST_RTP_BIN (element);
4479 klass = GST_ELEMENT_GET_CLASS (element);
4481 GST_RTP_BIN_LOCK (rtpbin);
4484 /* use a free pad name */
4485 pad_name = gst_rtp_bin_get_free_pad_name (element, templ);
4487 /* use the provided name */
4488 pad_name = g_strdup (name);
4491 GST_DEBUG_OBJECT (rtpbin, "Trying to request a pad with name %s", pad_name);
4493 /* figure out the template */
4494 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%u")) {
4495 result = create_recv_rtp (rtpbin, templ, pad_name);
4496 } else if (templ == gst_element_class_get_pad_template (klass,
4497 "recv_rtcp_sink_%u")) {
4498 result = create_recv_rtcp (rtpbin, templ, pad_name);
4499 } else if (templ == gst_element_class_get_pad_template (klass,
4500 "send_rtp_sink_%u")) {
4501 result = create_send_rtp (rtpbin, templ, pad_name);
4502 } else if (templ == gst_element_class_get_pad_template (klass,
4503 "send_rtcp_src_%u")) {
4504 result = create_send_rtcp (rtpbin, templ, pad_name);
4506 goto wrong_template;
4509 GST_RTP_BIN_UNLOCK (rtpbin);
4517 GST_RTP_BIN_UNLOCK (rtpbin);
4518 g_warning ("rtpbin: this is not our template");
4524 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)
4526 GstRtpBinSession *session;
4529 g_return_if_fail (GST_IS_GHOST_PAD (pad));
4530 g_return_if_fail (GST_IS_RTP_BIN (element));
4532 rtpbin = GST_RTP_BIN (element);
4534 GST_RTP_BIN_LOCK (rtpbin);
4535 GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s",
4536 GST_DEBUG_PAD_NAME (pad));
4538 if (!(session = find_session_by_pad (rtpbin, pad)))
4541 if (session->recv_rtp_sink_ghost == pad) {
4542 remove_recv_rtp (rtpbin, session);
4543 } else if (session->recv_rtcp_sink_ghost == pad) {
4544 remove_recv_rtcp (rtpbin, session);
4545 } else if (session->send_rtp_sink_ghost == pad) {
4546 remove_send_rtp (rtpbin, session);
4547 } else if (session->send_rtcp_src_ghost == pad) {
4548 remove_rtcp (rtpbin, session);
4551 /* no more request pads, free the complete session */
4552 if (session->recv_rtp_sink_ghost == NULL
4553 && session->recv_rtcp_sink_ghost == NULL
4554 && session->send_rtp_sink_ghost == NULL
4555 && session->send_rtcp_src_ghost == NULL) {
4556 GST_DEBUG_OBJECT (rtpbin, "no more pads for session %p", session);
4557 rtpbin->sessions = g_slist_remove (rtpbin->sessions, session);
4558 free_session (session, rtpbin);
4560 GST_RTP_BIN_UNLOCK (rtpbin);
4567 GST_RTP_BIN_UNLOCK (rtpbin);
4568 g_warning ("rtpbin: %s:%s is not one of our request pads",
4569 GST_DEBUG_PAD_NAME (pad));