Send seek event to baseparse when aacparse seek failed in push mode
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / gstrtpbin.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /**
21  * SECTION:element-rtpbin
22  * @title: rtpbin
23  * @see_also: rtpjitterbuffer, rtpsession, rtpptdemux, rtpssrcdemux
24  *
25  * RTP bin combines the functions of #GstRtpSession, #GstRtpSsrcDemux,
26  * #GstRtpJitterBuffer and #GstRtpPtDemux in one element. It allows for multiple
27  * RTP sessions that will be synchronized together using RTCP SR packets.
28  *
29  * #GstRtpBin is configured with a number of request pads that define the
30  * functionality that is activated, similar to the #GstRtpSession element.
31  *
32  * To use #GstRtpBin as an RTP receiver, request a recv_rtp_sink_\%u pad. The session
33  * number must be specified in the pad name.
34  * Data received on the recv_rtp_sink_\%u pad will be processed in the #GstRtpSession
35  * manager and after being validated forwarded on #GstRtpSsrcDemux element. Each
36  * RTP stream is demuxed based on the SSRC and send to a #GstRtpJitterBuffer. After
37  * the packets are released from the jitterbuffer, they will be forwarded to a
38  * #GstRtpPtDemux element. The #GstRtpPtDemux element will demux the packets based
39  * on the payload type and will create a unique pad recv_rtp_src_\%u_\%u_\%u on
40  * rtpbin with the session number, SSRC and payload type respectively as the pad
41  * name.
42  *
43  * To also use #GstRtpBin as an RTCP receiver, request a recv_rtcp_sink_\%u pad. The
44  * session number must be specified in the pad name.
45  *
46  * If you want the session manager to generate and send RTCP packets, request
47  * the send_rtcp_src_\%u pad with the session number in the pad name. Packet pushed
48  * on this pad contain SR/RR RTCP reports that should be sent to all participants
49  * in the session.
50  *
51  * To use #GstRtpBin as a sender, request a send_rtp_sink_\%u pad, which will
52  * automatically create a send_rtp_src_\%u pad. If the session number is not provided,
53  * the pad from the lowest available session will be returned. The session manager will modify the
54  * SSRC in the RTP packets to its own SSRC and will forward the packets on the
55  * send_rtp_src_\%u pad after updating its internal state.
56  *
57  * The session manager needs the clock-rate of the payload types it is handling
58  * and will signal the #GstRtpSession::request-pt-map signal when it needs such a
59  * mapping. One can clear the cached values with the #GstRtpSession::clear-pt-map
60  * signal.
61  *
62  * Access to the internal statistics of rtpbin is provided with the
63  * get-internal-session property. This action signal gives access to the
64  * RTPSession object which further provides action signals to retrieve the
65  * internal source and other sources.
66  *
67  * #GstRtpBin also has signals (#GstRtpBin::request-rtp-encoder,
68  * #GstRtpBin::request-rtp-decoder, #GstRtpBin::request-rtcp-encoder and
69  * #GstRtpBin::request-rtp-decoder) to dynamically request for RTP and RTCP encoders
70  * and decoders in order to support SRTP. The encoders must provide the pads
71  * rtp_sink_\%u and rtp_src_\%u for RTP and rtcp_sink_\%u and rtcp_src_\%u for
72  * RTCP. The session number will be used in the pad name. The decoders must provide
73  * rtp_sink and rtp_src for RTP and rtcp_sink and rtcp_src for RTCP. The decoders will
74  * be placed before the #GstRtpSession element, thus they must support SSRC demuxing
75  * internally.
76  *
77  * #GstRtpBin has signals (#GstRtpBin::request-aux-sender and
78  * #GstRtpBin::request-aux-receiver to dynamically request an element that can be
79  * used to create or merge additional RTP streams. AUX elements are needed to
80  * implement FEC or retransmission (such as RFC 4588). An AUX sender must have one
81  * sink_\%u pad that matches the sessionid in the signal and it should have 1 or
82  * more src_\%u pads. For each src_%\u pad, a session will be made (if needed)
83  * and the pad will be linked to the session send_rtp_sink pad. Each session will
84  * then expose its source pad as send_rtp_src_\%u on #GstRtpBin.
85  * An AUX receiver has 1 src_\%u pad that much match the sessionid in the signal
86  * and 1 or more sink_\%u pads. A session will be made for each sink_\%u pad
87  * when the corresponding recv_rtp_sink_\%u pad is requested on #GstRtpBin.
88  * The #GstRtpBin::request-jitterbuffer signal can be used to provide a custom
89  * element to perform arrival time smoothing, reordering and optionally packet
90  * loss detection and retransmission requests.
91  *
92  * ## Example pipelines
93  *
94  * |[
95  * gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \
96  *     rtpbin ! rtptheoradepay ! theoradec ! xvimagesink
97  * ]| Receive RTP data from port 5000 and send to the session 0 in rtpbin.
98  * |[
99  * gst-launch-1.0 rtpbin name=rtpbin \
100  *         v4l2src ! videoconvert ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
101  *                   rtpbin.send_rtp_src_0 ! udpsink port=5000                            \
102  *                   rtpbin.send_rtcp_src_0 ! udpsink port=5001 sync=false async=false    \
103  *                   udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0                           \
104  *         audiotestsrc ! amrnbenc ! rtpamrpay ! rtpbin.send_rtp_sink_1                   \
105  *                   rtpbin.send_rtp_src_1 ! udpsink port=5002                            \
106  *                   rtpbin.send_rtcp_src_1 ! udpsink port=5003 sync=false async=false    \
107  *                   udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1
108  * ]| Encode and payload H263 video captured from a v4l2src. Encode and payload AMR
109  * audio generated from audiotestsrc. The video is sent to session 0 in rtpbin
110  * and the audio is sent to session 1. Video packets are sent on UDP port 5000
111  * and audio packets on port 5002. The video RTCP packets for session 0 are sent
112  * on port 5001 and the audio RTCP packets for session 0 are sent on port 5003.
113  * RTCP packets for session 0 are received on port 5005 and RTCP for session 1
114  * is received on port 5007. Since RTCP packets from the sender should be sent
115  * as soon as possible and do not participate in preroll, sync=false and
116  * async=false is configured on udpsink
117  * |[
118  * gst-launch-1.0 -v rtpbin name=rtpbin                                          \
119  *     udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263-1998" \
120  *             port=5000 ! rtpbin.recv_rtp_sink_0                                \
121  *         rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink                    \
122  *      udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                               \
123  *      rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false        \
124  *     udpsrc caps="application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1" \
125  *             port=5002 ! rtpbin.recv_rtp_sink_1                                \
126  *         rtpbin. ! rtpamrdepay ! amrnbdec ! alsasink                           \
127  *      udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                               \
128  *      rtpbin.send_rtcp_src_1 ! udpsink port=5007 sync=false async=false
129  * ]| Receive H263 on port 5000, send it through rtpbin in session 0, depayload,
130  * decode and display the video.
131  * Receive AMR on port 5002, send it through rtpbin in session 1, depayload,
132  * decode and play the audio.
133  * Receive server RTCP packets for session 0 on port 5001 and RTCP packets for
134  * session 1 on port 5003. These packets will be used for session management and
135  * synchronisation.
136  * Send RTCP reports for session 0 on port 5005 and RTCP reports for session 1
137  * on port 5007.
138  *
139  */
140
141 #ifdef HAVE_CONFIG_H
142 #include "config.h"
143 #endif
144 #include <stdio.h>
145 #include <string.h>
146
147 #include <gst/rtp/gstrtpbuffer.h>
148 #include <gst/rtp/gstrtcpbuffer.h>
149
150 #include "gstrtpbin.h"
151 #include "rtpsession.h"
152 #include "gstrtpsession.h"
153 #include "gstrtpjitterbuffer.h"
154
155 #include <gst/glib-compat-private.h>
156
157 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
158 #define GST_CAT_DEFAULT gst_rtp_bin_debug
159
160 /* sink pads */
161 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
162     GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%u",
163     GST_PAD_SINK,
164     GST_PAD_REQUEST,
165     GST_STATIC_CAPS ("application/x-rtp;application/x-srtp")
166     );
167
168 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
169     GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%u",
170     GST_PAD_SINK,
171     GST_PAD_REQUEST,
172     GST_STATIC_CAPS ("application/x-rtcp;application/x-srtcp")
173     );
174
175 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
176 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%u",
177     GST_PAD_SINK,
178     GST_PAD_REQUEST,
179     GST_STATIC_CAPS ("application/x-rtp")
180     );
181
182 /* src pads */
183 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
184 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%u_%u_%u",
185     GST_PAD_SRC,
186     GST_PAD_SOMETIMES,
187     GST_STATIC_CAPS ("application/x-rtp")
188     );
189
190 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
191     GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%u",
192     GST_PAD_SRC,
193     GST_PAD_REQUEST,
194     GST_STATIC_CAPS ("application/x-rtcp;application/x-srtcp")
195     );
196
197 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
198     GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%u",
199     GST_PAD_SRC,
200     GST_PAD_SOMETIMES,
201     GST_STATIC_CAPS ("application/x-rtp;application/x-srtp")
202     );
203
204 #define GST_RTP_BIN_LOCK(bin)   g_mutex_lock (&(bin)->priv->bin_lock)
205 #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock (&(bin)->priv->bin_lock)
206
207 /* lock to protect dynamic callbacks, like pad-added and new ssrc. */
208 #define GST_RTP_BIN_DYN_LOCK(bin)    g_mutex_lock (&(bin)->priv->dyn_lock)
209 #define GST_RTP_BIN_DYN_UNLOCK(bin)  g_mutex_unlock (&(bin)->priv->dyn_lock)
210
211 /* lock for shutdown */
212 #define GST_RTP_BIN_SHUTDOWN_LOCK(bin,label)     \
213 G_STMT_START {                                   \
214   if (g_atomic_int_get (&bin->priv->shutdown))   \
215     goto label;                                  \
216   GST_RTP_BIN_DYN_LOCK (bin);                    \
217   if (g_atomic_int_get (&bin->priv->shutdown)) { \
218     GST_RTP_BIN_DYN_UNLOCK (bin);                \
219     goto label;                                  \
220   }                                              \
221 } G_STMT_END
222
223 /* unlock for shutdown */
224 #define GST_RTP_BIN_SHUTDOWN_UNLOCK(bin)         \
225   GST_RTP_BIN_DYN_UNLOCK (bin);                  \
226
227 /* Minimum time offset to apply. This compensates for rounding errors in NTP to
228  * RTP timestamp conversions */
229 #define MIN_TS_OFFSET (4 * GST_MSECOND)
230
231 struct _GstRtpBinPrivate
232 {
233   GMutex bin_lock;
234
235   /* lock protecting dynamic adding/removing */
236   GMutex dyn_lock;
237
238   /* if we are shutting down or not */
239   gint shutdown;
240
241   gboolean autoremove;
242
243   /* NTP time in ns of last SR sync used */
244   guint64 last_ntpnstime;
245
246   /* list of extra elements */
247   GList *elements;
248 };
249
250 /* signals and args */
251 enum
252 {
253   SIGNAL_REQUEST_PT_MAP,
254   SIGNAL_PAYLOAD_TYPE_CHANGE,
255   SIGNAL_CLEAR_PT_MAP,
256   SIGNAL_RESET_SYNC,
257   SIGNAL_GET_SESSION,
258   SIGNAL_GET_INTERNAL_SESSION,
259   SIGNAL_GET_STORAGE,
260   SIGNAL_GET_INTERNAL_STORAGE,
261
262   SIGNAL_ON_NEW_SSRC,
263   SIGNAL_ON_SSRC_COLLISION,
264   SIGNAL_ON_SSRC_VALIDATED,
265   SIGNAL_ON_SSRC_ACTIVE,
266   SIGNAL_ON_SSRC_SDES,
267   SIGNAL_ON_BYE_SSRC,
268   SIGNAL_ON_BYE_TIMEOUT,
269   SIGNAL_ON_TIMEOUT,
270   SIGNAL_ON_SENDER_TIMEOUT,
271   SIGNAL_ON_NPT_STOP,
272
273   SIGNAL_REQUEST_RTP_ENCODER,
274   SIGNAL_REQUEST_RTP_DECODER,
275   SIGNAL_REQUEST_RTCP_ENCODER,
276   SIGNAL_REQUEST_RTCP_DECODER,
277
278   SIGNAL_REQUEST_FEC_DECODER,
279   SIGNAL_REQUEST_FEC_ENCODER,
280
281   SIGNAL_REQUEST_JITTERBUFFER,
282
283   SIGNAL_NEW_JITTERBUFFER,
284   SIGNAL_NEW_STORAGE,
285
286   SIGNAL_REQUEST_AUX_SENDER,
287   SIGNAL_REQUEST_AUX_RECEIVER,
288
289   SIGNAL_ON_NEW_SENDER_SSRC,
290   SIGNAL_ON_SENDER_SSRC_ACTIVE,
291
292   SIGNAL_ON_BUNDLED_SSRC,
293
294   LAST_SIGNAL
295 };
296
297 #define DEFAULT_LATENCY_MS           200
298 #define DEFAULT_DROP_ON_LATENCY      FALSE
299 #define DEFAULT_SDES                 NULL
300 #define DEFAULT_DO_LOST              FALSE
301 #define DEFAULT_IGNORE_PT            FALSE
302 #define DEFAULT_NTP_SYNC             FALSE
303 #define DEFAULT_AUTOREMOVE           FALSE
304 #define DEFAULT_BUFFER_MODE          RTP_JITTER_BUFFER_MODE_SLAVE
305 #define DEFAULT_USE_PIPELINE_CLOCK   FALSE
306 #define DEFAULT_RTCP_SYNC            GST_RTP_BIN_RTCP_SYNC_ALWAYS
307 #define DEFAULT_RTCP_SYNC_INTERVAL   0
308 #define DEFAULT_DO_SYNC_EVENT        FALSE
309 #define DEFAULT_DO_RETRANSMISSION    FALSE
310 #define DEFAULT_RTP_PROFILE          GST_RTP_PROFILE_AVP
311 #define DEFAULT_NTP_TIME_SOURCE      GST_RTP_NTP_TIME_SOURCE_NTP
312 #define DEFAULT_RTCP_SYNC_SEND_TIME  TRUE
313 #define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000
314 #define DEFAULT_MAX_DROPOUT_TIME     60000
315 #define DEFAULT_MAX_MISORDER_TIME    2000
316 #define DEFAULT_RFC7273_SYNC         FALSE
317 #define DEFAULT_MAX_STREAMS          G_MAXUINT
318 #define DEFAULT_MAX_TS_OFFSET_ADJUSTMENT G_GUINT64_CONSTANT(0)
319 #define DEFAULT_MAX_TS_OFFSET        G_GINT64_CONSTANT(3000000000)
320 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
321 #define DEFAULT_RTSP_USE_BUFFERING  FALSE
322 #endif
323
324 enum
325 {
326   PROP_0,
327   PROP_LATENCY,
328   PROP_DROP_ON_LATENCY,
329   PROP_SDES,
330   PROP_DO_LOST,
331   PROP_IGNORE_PT,
332   PROP_NTP_SYNC,
333   PROP_RTCP_SYNC,
334   PROP_RTCP_SYNC_INTERVAL,
335   PROP_AUTOREMOVE,
336   PROP_BUFFER_MODE,
337   PROP_USE_PIPELINE_CLOCK,
338   PROP_DO_SYNC_EVENT,
339   PROP_DO_RETRANSMISSION,
340   PROP_RTP_PROFILE,
341   PROP_NTP_TIME_SOURCE,
342   PROP_RTCP_SYNC_SEND_TIME,
343   PROP_MAX_RTCP_RTP_TIME_DIFF,
344   PROP_MAX_DROPOUT_TIME,
345   PROP_MAX_MISORDER_TIME,
346   PROP_RFC7273_SYNC,
347   PROP_MAX_STREAMS,
348   PROP_MAX_TS_OFFSET_ADJUSTMENT,
349   PROP_MAX_TS_OFFSET,
350 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
351   PROP_USE_RTSP_BUFFERING       /* use for player RTSP buffering */
352 #endif
353 };
354
355 #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type())
356 static GType
357 gst_rtp_bin_rtcp_sync_get_type (void)
358 {
359   static GType rtcp_sync_type = 0;
360   static const GEnumValue rtcp_sync_types[] = {
361     {GST_RTP_BIN_RTCP_SYNC_ALWAYS, "always", "always"},
362     {GST_RTP_BIN_RTCP_SYNC_INITIAL, "initial", "initial"},
363     {GST_RTP_BIN_RTCP_SYNC_RTP, "rtp-info", "rtp-info"},
364     {0, NULL, NULL},
365   };
366
367   if (!rtcp_sync_type) {
368     rtcp_sync_type = g_enum_register_static ("GstRTCPSync", rtcp_sync_types);
369   }
370   return rtcp_sync_type;
371 }
372
373 /* helper objects */
374 typedef struct _GstRtpBinSession GstRtpBinSession;
375 typedef struct _GstRtpBinStream GstRtpBinStream;
376 typedef struct _GstRtpBinClient GstRtpBinClient;
377
378 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
379
380 static GstCaps *pt_map_requested (GstElement * element, guint pt,
381     GstRtpBinSession * session);
382 static void payload_type_change (GstElement * element, guint pt,
383     GstRtpBinSession * session);
384 static void remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
385 static void remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
386 static void remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session);
387 static void remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session);
388 static void free_client (GstRtpBinClient * client, GstRtpBin * bin);
389 static void free_stream (GstRtpBinStream * stream, GstRtpBin * bin);
390 static GstRtpBinSession *create_session (GstRtpBin * rtpbin, gint id);
391 static GstPad *complete_session_sink (GstRtpBin * rtpbin,
392     GstRtpBinSession * session);
393 static void
394 complete_session_receiver (GstRtpBin * rtpbin, GstRtpBinSession * session,
395     guint sessid);
396 static GstPad *complete_session_rtcp (GstRtpBin * rtpbin,
397     GstRtpBinSession * session, guint sessid);
398 static GstElement *session_request_element (GstRtpBinSession * session,
399     guint signal);
400
401 /* Manages the RTP stream for one SSRC.
402  *
403  * We pipe the stream (coming from the SSRC demuxer) into a jitterbuffer.
404  * If we see an SDES RTCP packet that links multiple SSRCs together based on a
405  * common CNAME, we create a GstRtpBinClient structure to group the SSRCs
406  * together (see below).
407  */
408 struct _GstRtpBinStream
409 {
410   /* the SSRC of this stream */
411   guint32 ssrc;
412
413   /* parent bin */
414   GstRtpBin *bin;
415
416   /* the session this SSRC belongs to */
417   GstRtpBinSession *session;
418
419   /* the jitterbuffer of the SSRC */
420   GstElement *buffer;
421   gulong buffer_handlesync_sig;
422   gulong buffer_ptreq_sig;
423   gulong buffer_ntpstop_sig;
424   gint percent;
425 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
426   gint prev_percent;
427 #endif
428   /* the PT demuxer of the SSRC */
429   GstElement *demux;
430   gulong demux_newpad_sig;
431   gulong demux_padremoved_sig;
432   gulong demux_ptreq_sig;
433   gulong demux_ptchange_sig;
434
435   /* if we have calculated a valid rt_delta for this stream */
436   gboolean have_sync;
437   /* mapping to local RTP and NTP time */
438   gint64 rt_delta;
439   gint64 rtp_delta;
440   /* base rtptime in gst time */
441   gint64 clock_base;
442 };
443
444 #define GST_RTP_SESSION_LOCK(sess)   g_mutex_lock (&(sess)->lock)
445 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock (&(sess)->lock)
446
447 /* Manages the receiving end of the packets.
448  *
449  * There is one such structure for each RTP session (audio/video/...).
450  * We get the RTP/RTCP packets and stuff them into the session manager. From
451  * there they are pushed into an SSRC demuxer that splits the stream based on
452  * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
453  * the GstRtpBinStream above).
454  *
455  * Before the SSRC demuxer, a storage element may be inserted for the purpose
456  * of Forward Error Correction.
457  */
458 struct _GstRtpBinSession
459 {
460   /* session id */
461   gint id;
462   /* the parent bin */
463   GstRtpBin *bin;
464   /* the session element */
465   GstElement *session;
466   /* the SSRC demuxer */
467   GstElement *demux;
468   gulong demux_newpad_sig;
469   gulong demux_padremoved_sig;
470
471   /* Fec support */
472   GstElement *storage;
473
474   GMutex lock;
475
476   /* list of GstRtpBinStream */
477   GSList *streams;
478
479   /* list of elements */
480   GSList *elements;
481
482   /* mapping of payload type to caps */
483   GHashTable *ptmap;
484
485   /* the pads of the session */
486   GstPad *recv_rtp_sink;
487   GstPad *recv_rtp_sink_ghost;
488   GstPad *recv_rtp_src;
489   GstPad *recv_rtcp_sink;
490   GstPad *recv_rtcp_sink_ghost;
491   GstPad *sync_src;
492   GstPad *send_rtp_sink;
493   GstPad *send_rtp_sink_ghost;
494   GstPad *send_rtp_src_ghost;
495   GstPad *send_rtcp_src;
496   GstPad *send_rtcp_src_ghost;
497 };
498
499 /* Manages the RTP streams that come from one client and should therefore be
500  * synchronized.
501  */
502 struct _GstRtpBinClient
503 {
504   /* the common CNAME for the streams */
505   gchar *cname;
506   guint cname_len;
507
508   /* the streams */
509   guint nstreams;
510   GSList *streams;
511 };
512
513 /* find a session with the given id. Must be called with RTP_BIN_LOCK */
514 static GstRtpBinSession *
515 find_session_by_id (GstRtpBin * rtpbin, gint id)
516 {
517   GSList *walk;
518
519   for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
520     GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
521
522     if (sess->id == id)
523       return sess;
524   }
525   return NULL;
526 }
527
528 /* find a session with the given request pad. Must be called with RTP_BIN_LOCK */
529 static GstRtpBinSession *
530 find_session_by_pad (GstRtpBin * rtpbin, GstPad * pad)
531 {
532   GSList *walk;
533
534   for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
535     GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
536
537     if ((sess->recv_rtp_sink_ghost == pad) ||
538         (sess->recv_rtcp_sink_ghost == pad) ||
539         (sess->send_rtp_sink_ghost == pad)
540         || (sess->send_rtcp_src_ghost == pad))
541       return sess;
542   }
543   return NULL;
544 }
545
546 static void
547 on_new_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
548 {
549   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC], 0,
550       sess->id, ssrc);
551 }
552
553 static void
554 on_ssrc_collision (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
555 {
556   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION], 0,
557       sess->id, ssrc);
558 }
559
560 static void
561 on_ssrc_validated (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
562 {
563   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED], 0,
564       sess->id, ssrc);
565 }
566
567 static void
568 on_ssrc_active (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
569 {
570   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE], 0,
571       sess->id, ssrc);
572 }
573
574 static void
575 on_ssrc_sdes (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
576 {
577   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES], 0,
578       sess->id, ssrc);
579 }
580
581 static void
582 on_bye_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
583 {
584   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC], 0,
585       sess->id, ssrc);
586 }
587
588 static void
589 on_bye_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
590 {
591   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT], 0,
592       sess->id, ssrc);
593
594   if (sess->bin->priv->autoremove)
595     g_signal_emit_by_name (sess->demux, "clear-ssrc", ssrc, NULL);
596 }
597
598 static void
599 on_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
600 {
601   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT], 0,
602       sess->id, ssrc);
603
604   if (sess->bin->priv->autoremove)
605     g_signal_emit_by_name (sess->demux, "clear-ssrc", ssrc, NULL);
606 }
607
608 static void
609 on_sender_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
610 {
611   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT], 0,
612       sess->id, ssrc);
613 }
614
615 static void
616 on_npt_stop (GstElement * jbuf, GstRtpBinStream * stream)
617 {
618   g_signal_emit (stream->bin, gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP], 0,
619       stream->session->id, stream->ssrc);
620 }
621
622 static void
623 on_new_sender_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
624 {
625   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SENDER_SSRC], 0,
626       sess->id, ssrc);
627 }
628
629 static void
630 on_sender_ssrc_active (GstElement * session, guint32 ssrc,
631     GstRtpBinSession * sess)
632 {
633   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SENDER_SSRC_ACTIVE],
634       0, sess->id, ssrc);
635 }
636
637 /* must be called with the SESSION lock */
638 static GstRtpBinStream *
639 find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc)
640 {
641   GSList *walk;
642
643   for (walk = session->streams; walk; walk = g_slist_next (walk)) {
644     GstRtpBinStream *stream = (GstRtpBinStream *) walk->data;
645
646     if (stream->ssrc == ssrc)
647       return stream;
648   }
649   return NULL;
650 }
651
652 static void
653 ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad,
654     GstRtpBinSession * session)
655 {
656   GstRtpBinStream *stream = NULL;
657   GstRtpBin *rtpbin;
658
659   rtpbin = session->bin;
660
661   GST_RTP_BIN_LOCK (rtpbin);
662
663   GST_RTP_SESSION_LOCK (session);
664   if ((stream = find_stream_by_ssrc (session, ssrc)))
665     session->streams = g_slist_remove (session->streams, stream);
666   GST_RTP_SESSION_UNLOCK (session);
667
668   if (stream)
669     free_stream (stream, rtpbin);
670
671   GST_RTP_BIN_UNLOCK (rtpbin);
672 }
673
674 /* create a session with the given id.  Must be called with RTP_BIN_LOCK */
675 static GstRtpBinSession *
676 create_session (GstRtpBin * rtpbin, gint id)
677 {
678   GstRtpBinSession *sess;
679   GstElement *session, *demux;
680   GstElement *storage = NULL;
681   GstState target;
682
683   if (!(session = gst_element_factory_make ("rtpsession", NULL)))
684     goto no_session;
685
686   if (!(demux = gst_element_factory_make ("rtpssrcdemux", NULL)))
687     goto no_demux;
688
689   if (!(storage = gst_element_factory_make ("rtpstorage", NULL)))
690     goto no_storage;
691
692   /* need to sink the storage or otherwise signal handlers from bindings will
693    * take ownership of it and we don't own it anymore */
694   gst_object_ref_sink (storage);
695   g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_STORAGE], 0, storage,
696       id);
697
698   sess = g_new0 (GstRtpBinSession, 1);
699   g_mutex_init (&sess->lock);
700   sess->id = id;
701   sess->bin = rtpbin;
702   sess->session = session;
703   sess->demux = demux;
704   sess->storage = storage;
705
706   sess->ptmap = g_hash_table_new_full (NULL, NULL, NULL,
707       (GDestroyNotify) gst_caps_unref);
708   rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
709
710   /* configure SDES items */
711   GST_OBJECT_LOCK (rtpbin);
712   g_object_set (demux, "max-streams", rtpbin->max_streams, NULL);
713   g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile",
714       rtpbin->rtp_profile, "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time,
715       NULL);
716   if (rtpbin->use_pipeline_clock)
717     g_object_set (session, "use-pipeline-clock", rtpbin->use_pipeline_clock,
718         NULL);
719   else
720     g_object_set (session, "ntp-time-source", rtpbin->ntp_time_source, NULL);
721
722   g_object_set (session, "max-dropout-time", rtpbin->max_dropout_time,
723       "max-misorder-time", rtpbin->max_misorder_time, NULL);
724   GST_OBJECT_UNLOCK (rtpbin);
725
726   /* provide clock_rate to the session manager when needed */
727   g_signal_connect (session, "request-pt-map",
728       (GCallback) pt_map_requested, sess);
729
730   g_signal_connect (sess->session, "on-new-ssrc",
731       (GCallback) on_new_ssrc, sess);
732   g_signal_connect (sess->session, "on-ssrc-collision",
733       (GCallback) on_ssrc_collision, sess);
734   g_signal_connect (sess->session, "on-ssrc-validated",
735       (GCallback) on_ssrc_validated, sess);
736   g_signal_connect (sess->session, "on-ssrc-active",
737       (GCallback) on_ssrc_active, sess);
738   g_signal_connect (sess->session, "on-ssrc-sdes",
739       (GCallback) on_ssrc_sdes, sess);
740   g_signal_connect (sess->session, "on-bye-ssrc",
741       (GCallback) on_bye_ssrc, sess);
742   g_signal_connect (sess->session, "on-bye-timeout",
743       (GCallback) on_bye_timeout, sess);
744   g_signal_connect (sess->session, "on-timeout", (GCallback) on_timeout, sess);
745   g_signal_connect (sess->session, "on-sender-timeout",
746       (GCallback) on_sender_timeout, sess);
747   g_signal_connect (sess->session, "on-new-sender-ssrc",
748       (GCallback) on_new_sender_ssrc, sess);
749   g_signal_connect (sess->session, "on-sender-ssrc-active",
750       (GCallback) on_sender_ssrc_active, sess);
751
752   gst_bin_add (GST_BIN_CAST (rtpbin), session);
753   gst_bin_add (GST_BIN_CAST (rtpbin), demux);
754   gst_bin_add (GST_BIN_CAST (rtpbin), storage);
755
756   /* unref the storage again, the bin has a reference now and
757    * we don't need it anymore */
758   gst_object_unref (storage);
759
760   GST_OBJECT_LOCK (rtpbin);
761   target = GST_STATE_TARGET (rtpbin);
762   GST_OBJECT_UNLOCK (rtpbin);
763
764   /* change state only to what's needed */
765   gst_element_set_state (demux, target);
766   gst_element_set_state (session, target);
767   gst_element_set_state (storage, target);
768
769   return sess;
770
771   /* ERRORS */
772 no_session:
773   {
774     g_warning ("rtpbin: could not create rtpsession element");
775     return NULL;
776   }
777 no_demux:
778   {
779     gst_object_unref (session);
780     g_warning ("rtpbin: could not create rtpssrcdemux element");
781     return NULL;
782   }
783 no_storage:
784   {
785     gst_object_unref (session);
786     gst_object_unref (demux);
787     g_warning ("rtpbin: could not create rtpstorage element");
788     return NULL;
789   }
790 }
791
792 static gboolean
793 bin_manage_element (GstRtpBin * bin, GstElement * element)
794 {
795   GstRtpBinPrivate *priv = bin->priv;
796
797   if (g_list_find (priv->elements, element)) {
798     GST_DEBUG_OBJECT (bin, "requested element %p already in bin", element);
799   } else {
800     GST_DEBUG_OBJECT (bin, "adding requested element %p", element);
801
802     if (g_object_is_floating (element))
803       element = gst_object_ref_sink (element);
804
805     if (!gst_bin_add (GST_BIN_CAST (bin), element))
806       goto add_failed;
807     if (!gst_element_sync_state_with_parent (element))
808       GST_WARNING_OBJECT (bin, "unable to sync element state with rtpbin");
809   }
810   /* we add the element multiple times, each we need an equal number of
811    * removes to really remove the element from the bin */
812   priv->elements = g_list_prepend (priv->elements, element);
813
814   return TRUE;
815
816   /* ERRORS */
817 add_failed:
818   {
819     GST_WARNING_OBJECT (bin, "unable to add element");
820     gst_object_unref (element);
821     return FALSE;
822   }
823 }
824
825 static void
826 remove_bin_element (GstElement * element, GstRtpBin * bin)
827 {
828   GstRtpBinPrivate *priv = bin->priv;
829   GList *find;
830
831   find = g_list_find (priv->elements, element);
832   if (find) {
833     priv->elements = g_list_delete_link (priv->elements, find);
834
835     if (!g_list_find (priv->elements, element)) {
836       gst_element_set_locked_state (element, TRUE);
837       gst_bin_remove (GST_BIN_CAST (bin), element);
838       gst_element_set_state (element, GST_STATE_NULL);
839     }
840
841     gst_object_unref (element);
842   }
843 }
844
845 /* called with RTP_BIN_LOCK */
846 static void
847 free_session (GstRtpBinSession * sess, GstRtpBin * bin)
848 {
849   GST_DEBUG_OBJECT (bin, "freeing session %p", sess);
850
851   gst_element_set_locked_state (sess->demux, TRUE);
852   gst_element_set_locked_state (sess->session, TRUE);
853   gst_element_set_locked_state (sess->storage, TRUE);
854
855   gst_element_set_state (sess->demux, GST_STATE_NULL);
856   gst_element_set_state (sess->session, GST_STATE_NULL);
857   gst_element_set_state (sess->storage, GST_STATE_NULL);
858
859   remove_recv_rtp (bin, sess);
860   remove_recv_rtcp (bin, sess);
861   remove_send_rtp (bin, sess);
862   remove_rtcp (bin, sess);
863
864   gst_bin_remove (GST_BIN_CAST (bin), sess->session);
865   gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
866   gst_bin_remove (GST_BIN_CAST (bin), sess->storage);
867
868   g_slist_foreach (sess->elements, (GFunc) remove_bin_element, bin);
869   g_slist_free (sess->elements);
870   sess->elements = NULL;
871
872   g_slist_foreach (sess->streams, (GFunc) free_stream, bin);
873   g_slist_free (sess->streams);
874
875   g_mutex_clear (&sess->lock);
876   g_hash_table_destroy (sess->ptmap);
877
878   g_free (sess);
879 }
880
881 /* get the payload type caps for the specific payload @pt in @session */
882 static GstCaps *
883 get_pt_map (GstRtpBinSession * session, guint pt)
884 {
885   GstCaps *caps = NULL;
886   GstRtpBin *bin;
887   GValue ret = { 0 };
888   GValue args[3] = { {0}, {0}, {0} };
889
890   GST_DEBUG ("searching pt %u in cache", pt);
891
892   GST_RTP_SESSION_LOCK (session);
893
894   /* first look in the cache */
895   caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
896   if (caps) {
897     gst_caps_ref (caps);
898     goto done;
899   }
900
901   bin = session->bin;
902
903   GST_DEBUG ("emitting signal for pt %u in session %u", pt, session->id);
904
905   /* not in cache, send signal to request caps */
906   g_value_init (&args[0], GST_TYPE_ELEMENT);
907   g_value_set_object (&args[0], bin);
908   g_value_init (&args[1], G_TYPE_UINT);
909   g_value_set_uint (&args[1], session->id);
910   g_value_init (&args[2], G_TYPE_UINT);
911   g_value_set_uint (&args[2], pt);
912
913   g_value_init (&ret, GST_TYPE_CAPS);
914   g_value_set_boxed (&ret, NULL);
915
916   GST_RTP_SESSION_UNLOCK (session);
917
918   g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
919
920   GST_RTP_SESSION_LOCK (session);
921
922   g_value_unset (&args[0]);
923   g_value_unset (&args[1]);
924   g_value_unset (&args[2]);
925
926   /* look in the cache again because we let the lock go */
927   caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
928   if (caps) {
929     gst_caps_ref (caps);
930     g_value_unset (&ret);
931     goto done;
932   }
933
934   caps = (GstCaps *) g_value_dup_boxed (&ret);
935   g_value_unset (&ret);
936   if (!caps)
937     goto no_caps;
938
939   GST_DEBUG ("caching pt %u as %" GST_PTR_FORMAT, pt, caps);
940
941   /* store in cache, take additional ref */
942   g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt),
943       gst_caps_ref (caps));
944
945 done:
946   GST_RTP_SESSION_UNLOCK (session);
947
948   return caps;
949
950   /* ERRORS */
951 no_caps:
952   {
953     GST_RTP_SESSION_UNLOCK (session);
954     GST_DEBUG ("no pt map could be obtained");
955     return NULL;
956   }
957 }
958
959 static gboolean
960 return_true (gpointer key, gpointer value, gpointer user_data)
961 {
962   return TRUE;
963 }
964
965 static void
966 gst_rtp_bin_reset_sync (GstRtpBin * rtpbin)
967 {
968   GSList *clients, *streams;
969
970   GST_DEBUG_OBJECT (rtpbin, "Reset sync on all clients");
971
972   GST_RTP_BIN_LOCK (rtpbin);
973   for (clients = rtpbin->clients; clients; clients = g_slist_next (clients)) {
974     GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
975
976     /* reset sync on all streams for this client */
977     for (streams = client->streams; streams; streams = g_slist_next (streams)) {
978       GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
979
980       /* make use require a new SR packet for this stream before we attempt new
981        * lip-sync */
982       stream->have_sync = FALSE;
983       stream->rt_delta = 0;
984       stream->rtp_delta = 0;
985       stream->clock_base = -100 * GST_SECOND;
986     }
987   }
988   GST_RTP_BIN_UNLOCK (rtpbin);
989 }
990
991 static void
992 gst_rtp_bin_clear_pt_map (GstRtpBin * bin)
993 {
994   GSList *sessions, *streams;
995
996   GST_RTP_BIN_LOCK (bin);
997   GST_DEBUG_OBJECT (bin, "clearing pt map");
998   for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
999     GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
1000
1001     GST_DEBUG_OBJECT (bin, "clearing session %p", session);
1002     g_signal_emit_by_name (session->session, "clear-pt-map", NULL);
1003
1004     GST_RTP_SESSION_LOCK (session);
1005     g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
1006
1007     for (streams = session->streams; streams; streams = g_slist_next (streams)) {
1008       GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
1009
1010       GST_DEBUG_OBJECT (bin, "clearing stream %p", stream);
1011       if (g_signal_lookup ("clear-pt-map", G_OBJECT_TYPE (stream->buffer)) != 0)
1012         g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL);
1013       if (stream->demux)
1014         g_signal_emit_by_name (stream->demux, "clear-pt-map", NULL);
1015     }
1016     GST_RTP_SESSION_UNLOCK (session);
1017   }
1018   GST_RTP_BIN_UNLOCK (bin);
1019
1020   /* reset sync too */
1021   gst_rtp_bin_reset_sync (bin);
1022 }
1023
1024 static GstElement *
1025 gst_rtp_bin_get_session (GstRtpBin * bin, guint session_id)
1026 {
1027   GstRtpBinSession *session;
1028   GstElement *ret = NULL;
1029
1030   GST_RTP_BIN_LOCK (bin);
1031   GST_DEBUG_OBJECT (bin, "retrieving GstRtpSession, index: %u", session_id);
1032   session = find_session_by_id (bin, (gint) session_id);
1033   if (session) {
1034     ret = gst_object_ref (session->session);
1035   }
1036   GST_RTP_BIN_UNLOCK (bin);
1037
1038   return ret;
1039 }
1040
1041 static RTPSession *
1042 gst_rtp_bin_get_internal_session (GstRtpBin * bin, guint session_id)
1043 {
1044   RTPSession *internal_session = NULL;
1045   GstRtpBinSession *session;
1046
1047   GST_RTP_BIN_LOCK (bin);
1048   GST_DEBUG_OBJECT (bin, "retrieving internal RTPSession object, index: %u",
1049       session_id);
1050   session = find_session_by_id (bin, (gint) session_id);
1051   if (session) {
1052     g_object_get (session->session, "internal-session", &internal_session,
1053         NULL);
1054   }
1055   GST_RTP_BIN_UNLOCK (bin);
1056
1057   return internal_session;
1058 }
1059
1060 static GstElement *
1061 gst_rtp_bin_get_storage (GstRtpBin * bin, guint session_id)
1062 {
1063   GstRtpBinSession *session;
1064   GstElement *res = NULL;
1065
1066   GST_RTP_BIN_LOCK (bin);
1067   GST_DEBUG_OBJECT (bin, "retrieving internal storage object, index: %u",
1068       session_id);
1069   session = find_session_by_id (bin, (gint) session_id);
1070   if (session && session->storage) {
1071     res = gst_object_ref (session->storage);
1072   }
1073   GST_RTP_BIN_UNLOCK (bin);
1074
1075   return res;
1076 }
1077
1078 static GObject *
1079 gst_rtp_bin_get_internal_storage (GstRtpBin * bin, guint session_id)
1080 {
1081   GObject *internal_storage = NULL;
1082   GstRtpBinSession *session;
1083
1084   GST_RTP_BIN_LOCK (bin);
1085   GST_DEBUG_OBJECT (bin, "retrieving internal storage object, index: %u",
1086       session_id);
1087   session = find_session_by_id (bin, (gint) session_id);
1088   if (session && session->storage) {
1089     g_object_get (session->storage, "internal-storage", &internal_storage,
1090         NULL);
1091   }
1092   GST_RTP_BIN_UNLOCK (bin);
1093
1094   return internal_storage;
1095 }
1096
1097 static GstElement *
1098 gst_rtp_bin_request_encoder (GstRtpBin * bin, guint session_id)
1099 {
1100   GST_DEBUG_OBJECT (bin, "return NULL encoder");
1101   return NULL;
1102 }
1103
1104 static GstElement *
1105 gst_rtp_bin_request_decoder (GstRtpBin * bin, guint session_id)
1106 {
1107   GST_DEBUG_OBJECT (bin, "return NULL decoder");
1108   return NULL;
1109 }
1110
1111 static GstElement *
1112 gst_rtp_bin_request_jitterbuffer (GstRtpBin * bin, guint session_id)
1113 {
1114   return gst_element_factory_make ("rtpjitterbuffer", NULL);
1115 }
1116
1117 static void
1118 gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin,
1119     const gchar * name, const GValue * value)
1120 {
1121   GSList *sessions, *streams;
1122
1123   GST_RTP_BIN_LOCK (bin);
1124   for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
1125     GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
1126
1127     GST_RTP_SESSION_LOCK (session);
1128     for (streams = session->streams; streams; streams = g_slist_next (streams)) {
1129       GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
1130       GObjectClass *jb_class;
1131
1132       jb_class = G_OBJECT_GET_CLASS (G_OBJECT (stream->buffer));
1133       if (g_object_class_find_property (jb_class, name))
1134         g_object_set_property (G_OBJECT (stream->buffer), name, value);
1135       else
1136         GST_WARNING_OBJECT (bin,
1137             "Stream jitterbuffer does not expose property %s", name);
1138     }
1139     GST_RTP_SESSION_UNLOCK (session);
1140   }
1141   GST_RTP_BIN_UNLOCK (bin);
1142 }
1143
1144 static void
1145 gst_rtp_bin_propagate_property_to_session (GstRtpBin * bin,
1146     const gchar * name, const GValue * value)
1147 {
1148   GSList *sessions;
1149
1150   GST_RTP_BIN_LOCK (bin);
1151   for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
1152     GstRtpBinSession *sess = (GstRtpBinSession *) sessions->data;
1153
1154     g_object_set_property (G_OBJECT (sess->session), name, value);
1155   }
1156   GST_RTP_BIN_UNLOCK (bin);
1157 }
1158
1159 /* get a client with the given SDES name. Must be called with RTP_BIN_LOCK */
1160 static GstRtpBinClient *
1161 get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created)
1162 {
1163   GstRtpBinClient *result = NULL;
1164   GSList *walk;
1165
1166   for (walk = bin->clients; walk; walk = g_slist_next (walk)) {
1167     GstRtpBinClient *client = (GstRtpBinClient *) walk->data;
1168
1169     if (len != client->cname_len)
1170       continue;
1171
1172     if (!strncmp ((gchar *) data, client->cname, client->cname_len)) {
1173       GST_DEBUG_OBJECT (bin, "found existing client %p with CNAME %s", client,
1174           client->cname);
1175       result = client;
1176       break;
1177     }
1178   }
1179
1180   /* nothing found, create one */
1181   if (result == NULL) {
1182     result = g_new0 (GstRtpBinClient, 1);
1183     result->cname = g_strndup ((gchar *) data, len);
1184     result->cname_len = len;
1185     bin->clients = g_slist_prepend (bin->clients, result);
1186     GST_DEBUG_OBJECT (bin, "created new client %p with CNAME %s", result,
1187         result->cname);
1188   }
1189   return result;
1190 }
1191
1192 static void
1193 free_client (GstRtpBinClient * client, GstRtpBin * bin)
1194 {
1195   GST_DEBUG_OBJECT (bin, "freeing client %p", client);
1196   g_slist_free (client->streams);
1197   g_free (client->cname);
1198   g_free (client);
1199 }
1200
1201 static void
1202 get_current_times (GstRtpBin * bin, GstClockTime * running_time,
1203     guint64 * ntpnstime)
1204 {
1205   guint64 ntpns = -1;
1206   GstClock *clock;
1207   GstClockTime base_time, rt, clock_time;
1208
1209   GST_OBJECT_LOCK (bin);
1210   if ((clock = GST_ELEMENT_CLOCK (bin))) {
1211     base_time = GST_ELEMENT_CAST (bin)->base_time;
1212     gst_object_ref (clock);
1213     GST_OBJECT_UNLOCK (bin);
1214
1215     /* get current clock time and convert to running time */
1216     clock_time = gst_clock_get_time (clock);
1217     rt = clock_time - base_time;
1218
1219     if (bin->use_pipeline_clock) {
1220       ntpns = rt;
1221       /* add constant to convert from 1970 based time to 1900 based time */
1222       ntpns += (2208988800LL * GST_SECOND);
1223     } else {
1224       switch (bin->ntp_time_source) {
1225         case GST_RTP_NTP_TIME_SOURCE_NTP:
1226         case GST_RTP_NTP_TIME_SOURCE_UNIX:{
1227           /* get current NTP time */
1228           ntpns = g_get_real_time () * GST_USECOND;
1229
1230           /* add constant to convert from 1970 based time to 1900 based time */
1231           if (bin->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
1232             ntpns += (2208988800LL * GST_SECOND);
1233           break;
1234         }
1235         case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
1236           ntpns = rt;
1237           break;
1238         case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
1239           ntpns = clock_time;
1240           break;
1241         default:
1242           ntpns = -1;           /* Fix uninited compiler warning */
1243           g_assert_not_reached ();
1244           break;
1245       }
1246     }
1247
1248     gst_object_unref (clock);
1249   } else {
1250     GST_OBJECT_UNLOCK (bin);
1251     rt = -1;
1252     ntpns = -1;
1253   }
1254   if (running_time)
1255     *running_time = rt;
1256   if (ntpnstime)
1257     *ntpnstime = ntpns;
1258 }
1259
1260 static void
1261 stream_set_ts_offset (GstRtpBin * bin, GstRtpBinStream * stream,
1262     gint64 ts_offset, gint64 max_ts_offset, gint64 min_ts_offset,
1263     gboolean allow_positive_ts_offset)
1264 {
1265   gint64 prev_ts_offset;
1266   GObjectClass *jb_class;
1267
1268   jb_class = G_OBJECT_GET_CLASS (G_OBJECT (stream->buffer));
1269
1270   if (!g_object_class_find_property (jb_class, "ts-offset")) {
1271     GST_LOG_OBJECT (bin,
1272         "stream's jitterbuffer does not expose ts-offset property");
1273     return;
1274   }
1275
1276   g_object_get (stream->buffer, "ts-offset", &prev_ts_offset, NULL);
1277
1278   /* delta changed, see how much */
1279   if (prev_ts_offset != ts_offset) {
1280     gint64 diff;
1281
1282     diff = prev_ts_offset - ts_offset;
1283
1284     GST_DEBUG_OBJECT (bin,
1285         "ts-offset %" G_GINT64_FORMAT ", prev %" G_GINT64_FORMAT
1286         ", diff: %" G_GINT64_FORMAT, ts_offset, prev_ts_offset, diff);
1287
1288     /* ignore minor offsets */
1289     if (ABS (diff) < min_ts_offset) {
1290       GST_DEBUG_OBJECT (bin, "offset too small, ignoring");
1291       return;
1292     }
1293
1294     /* sanity check offset */
1295     if (max_ts_offset > 0) {
1296       if (ts_offset > 0 && !allow_positive_ts_offset) {
1297         GST_DEBUG_OBJECT (bin,
1298             "offset is positive (clocks are out of sync), ignoring");
1299         return;
1300       }
1301       if (ABS (ts_offset) > max_ts_offset) {
1302         GST_DEBUG_OBJECT (bin, "offset too large, ignoring");
1303         return;
1304       }
1305     }
1306
1307     g_object_set (stream->buffer, "ts-offset", ts_offset, NULL);
1308   }
1309   GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT,
1310       stream->ssrc, ts_offset);
1311 }
1312
1313 static void
1314 gst_rtp_bin_send_sync_event (GstRtpBinStream * stream)
1315 {
1316   if (stream->bin->send_sync_event) {
1317     GstEvent *event;
1318     GstPad *srcpad;
1319
1320     GST_DEBUG_OBJECT (stream->bin,
1321         "sending GstRTCPSRReceived event downstream");
1322
1323     event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1324         gst_structure_new_empty ("GstRTCPSRReceived"));
1325
1326     srcpad = gst_element_get_static_pad (stream->buffer, "src");
1327     gst_pad_push_event (srcpad, event);
1328     gst_object_unref (srcpad);
1329   }
1330 }
1331
1332 /* associate a stream to the given CNAME. This will make sure all streams for
1333  * that CNAME are synchronized together.
1334  * Must be called with GST_RTP_BIN_LOCK */
1335 static void
1336 gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len,
1337     guint8 * data, guint64 ntptime, guint64 last_extrtptime,
1338     guint64 base_rtptime, guint64 base_time, guint clock_rate,
1339     gint64 rtp_clock_base)
1340 {
1341   GstRtpBinClient *client;
1342   gboolean created;
1343   GSList *walk;
1344   GstClockTime running_time, running_time_rtp;
1345   guint64 ntpnstime;
1346
1347   /* first find or create the CNAME */
1348   client = get_client (bin, len, data, &created);
1349
1350   /* find stream in the client */
1351   for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1352     GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1353
1354     if (ostream == stream)
1355       break;
1356   }
1357   /* not found, add it to the list */
1358   if (walk == NULL) {
1359     GST_DEBUG_OBJECT (bin,
1360         "new association of SSRC %08x with client %p with CNAME %s",
1361         stream->ssrc, client, client->cname);
1362     client->streams = g_slist_prepend (client->streams, stream);
1363     client->nstreams++;
1364   } else {
1365     GST_DEBUG_OBJECT (bin,
1366         "found association of SSRC %08x with client %p with CNAME %s",
1367         stream->ssrc, client, client->cname);
1368   }
1369
1370   if (!GST_CLOCK_TIME_IS_VALID (last_extrtptime)) {
1371     GST_DEBUG_OBJECT (bin, "invalidated sync data");
1372     if (bin->rtcp_sync == GST_RTP_BIN_RTCP_SYNC_RTP) {
1373       /* we don't need that data, so carry on,
1374        * but make some values look saner */
1375       last_extrtptime = base_rtptime;
1376     } else {
1377       /* nothing we can do with this data in this case */
1378       GST_DEBUG_OBJECT (bin, "bailing out");
1379       return;
1380     }
1381   }
1382
1383   /* Take the extended rtptime we found in the SR packet and map it to the
1384    * local rtptime. The local rtp time is used to construct timestamps on the
1385    * buffers so we will calculate what running_time corresponds to the RTP
1386    * timestamp in the SR packet. */
1387   running_time_rtp = last_extrtptime - base_rtptime;
1388
1389   GST_DEBUG_OBJECT (bin,
1390       "base %" G_GUINT64_FORMAT ", extrtptime %" G_GUINT64_FORMAT
1391       ", local RTP %" G_GUINT64_FORMAT ", clock-rate %d, "
1392       "clock-base %" G_GINT64_FORMAT, base_rtptime,
1393       last_extrtptime, running_time_rtp, clock_rate, rtp_clock_base);
1394
1395   /* calculate local RTP time in gstreamer timestamp, we essentially perform the
1396    * same conversion that a jitterbuffer would use to convert an rtp timestamp
1397    * into a corresponding gstreamer timestamp. Note that the base_time also
1398    * contains the drift between sender and receiver. */
1399   running_time =
1400       gst_util_uint64_scale_int (running_time_rtp, GST_SECOND, clock_rate);
1401   running_time += base_time;
1402
1403   /* convert ntptime to nanoseconds */
1404   ntpnstime = gst_util_uint64_scale (ntptime, GST_SECOND,
1405       (G_GINT64_CONSTANT (1) << 32));
1406
1407   stream->have_sync = TRUE;
1408
1409   GST_DEBUG_OBJECT (bin,
1410       "SR RTP running time %" G_GUINT64_FORMAT ", SR NTP %" G_GUINT64_FORMAT,
1411       running_time, ntpnstime);
1412
1413   /* recalc inter stream playout offset, but only if there is more than one
1414    * stream or we're doing NTP sync. */
1415   if (bin->ntp_sync) {
1416     gint64 ntpdiff, rtdiff;
1417     guint64 local_ntpnstime;
1418     GstClockTime local_running_time;
1419
1420     /* For NTP sync we need to first get a snapshot of running_time and NTP
1421      * time. We know at what running_time we play a certain RTP time, we also
1422      * calculated when we would play the RTP time in the SR packet. Now we need
1423      * to know how the running_time and the NTP time relate to each other. */
1424     get_current_times (bin, &local_running_time, &local_ntpnstime);
1425
1426     /* see how far away the NTP time is. This is the difference between the
1427      * current NTP time and the NTP time in the last SR packet. */
1428     ntpdiff = local_ntpnstime - ntpnstime;
1429     /* see how far away the running_time is. This is the difference between the
1430      * current running_time and the running_time of the RTP timestamp in the
1431      * last SR packet. */
1432     rtdiff = local_running_time - running_time;
1433
1434     GST_DEBUG_OBJECT (bin,
1435         "local NTP time %" G_GUINT64_FORMAT ", SR NTP time %" G_GUINT64_FORMAT,
1436         local_ntpnstime, ntpnstime);
1437     GST_DEBUG_OBJECT (bin,
1438         "local running time %" G_GUINT64_FORMAT ", SR RTP running time %"
1439         G_GUINT64_FORMAT, local_running_time, running_time);
1440     GST_DEBUG_OBJECT (bin,
1441         "NTP diff %" G_GINT64_FORMAT ", RT diff %" G_GINT64_FORMAT, ntpdiff,
1442         rtdiff);
1443
1444     /* combine to get the final diff to apply to the running_time */
1445     stream->rt_delta = rtdiff - ntpdiff;
1446
1447     stream_set_ts_offset (bin, stream, stream->rt_delta, bin->max_ts_offset,
1448         0, FALSE);
1449   } else {
1450     gint64 min, rtp_min, clock_base = stream->clock_base;
1451     gboolean all_sync, use_rtp;
1452     gboolean rtcp_sync = g_atomic_int_get (&bin->rtcp_sync);
1453
1454     /* calculate delta between server and receiver. ntpnstime is created by
1455      * converting the ntptime in the last SR packet to a gstreamer timestamp. This
1456      * delta expresses the difference to our timeline and the server timeline. The
1457      * difference in itself doesn't mean much but we can combine the delta of
1458      * multiple streams to create a stream specific offset. */
1459     stream->rt_delta = ntpnstime - running_time;
1460
1461     /* calculate the min of all deltas, ignoring streams that did not yet have a
1462      * valid rt_delta because we did not yet receive an SR packet for those
1463      * streams.
1464      * We calculate the minimum because we would like to only apply positive
1465      * offsets to streams, delaying their playback instead of trying to speed up
1466      * other streams (which might be impossible when we have to create negative
1467      * latencies).
1468      * The stream that has the smallest diff is selected as the reference stream,
1469      * all other streams will have a positive offset to this difference. */
1470
1471     /* some alternative setting allow ignoring RTCP as much as possible,
1472      * for servers generating bogus ntp timeline */
1473     min = rtp_min = G_MAXINT64;
1474     use_rtp = FALSE;
1475     if (rtcp_sync == GST_RTP_BIN_RTCP_SYNC_RTP) {
1476       guint64 ext_base;
1477
1478       use_rtp = TRUE;
1479       /* signed version for convenience */
1480       clock_base = base_rtptime;
1481       /* deal with possible wrap-around */
1482       ext_base = base_rtptime;
1483       rtp_clock_base = gst_rtp_buffer_ext_timestamp (&ext_base, rtp_clock_base);
1484       /* sanity check; base rtp and provided clock_base should be close */
1485       if (rtp_clock_base >= clock_base) {
1486         if (rtp_clock_base - clock_base < 10 * clock_rate) {
1487           rtp_clock_base = base_time +
1488               gst_util_uint64_scale_int (rtp_clock_base - clock_base,
1489               GST_SECOND, clock_rate);
1490         } else {
1491           use_rtp = FALSE;
1492         }
1493       } else {
1494         if (clock_base - rtp_clock_base < 10 * clock_rate) {
1495           rtp_clock_base = base_time -
1496               gst_util_uint64_scale_int (clock_base - rtp_clock_base,
1497               GST_SECOND, clock_rate);
1498         } else {
1499           use_rtp = FALSE;
1500         }
1501       }
1502       /* warn and bail for clarity out if no sane values */
1503       if (!use_rtp) {
1504         GST_WARNING_OBJECT (bin, "unable to sync to provided rtptime");
1505         return;
1506       }
1507       /* store to track changes */
1508       clock_base = rtp_clock_base;
1509       /* generate a fake as before,
1510        * now equating rtptime obtained from RTP-Info,
1511        * where the large time represent the otherwise irrelevant npt/ntp time */
1512       stream->rtp_delta = (GST_SECOND << 28) - rtp_clock_base;
1513     } else {
1514       clock_base = rtp_clock_base;
1515     }
1516
1517     all_sync = TRUE;
1518     for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1519       GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1520
1521       if (!ostream->have_sync) {
1522         all_sync = FALSE;
1523         continue;
1524       }
1525
1526       /* change in current stream's base from previously init'ed value
1527        * leads to reset of all stream's base */
1528       if (stream != ostream && stream->clock_base >= 0 &&
1529           (stream->clock_base != clock_base)) {
1530         GST_DEBUG_OBJECT (bin, "reset upon clock base change");
1531         ostream->clock_base = -100 * GST_SECOND;
1532         ostream->rtp_delta = 0;
1533       }
1534
1535       if (ostream->rt_delta < min)
1536         min = ostream->rt_delta;
1537       if (ostream->rtp_delta < rtp_min)
1538         rtp_min = ostream->rtp_delta;
1539     }
1540
1541     /* arrange to re-sync for each stream upon significant change,
1542      * e.g. post-seek */
1543     all_sync = all_sync && (stream->clock_base == clock_base);
1544     stream->clock_base = clock_base;
1545
1546     /* may need init performed above later on, but nothing more to do now */
1547     if (client->nstreams <= 1)
1548       return;
1549
1550     GST_DEBUG_OBJECT (bin, "client %p min delta %" G_GINT64_FORMAT
1551         " all sync %d", client, min, all_sync);
1552     GST_DEBUG_OBJECT (bin, "rtcp sync mode %d, use_rtp %d", rtcp_sync, use_rtp);
1553
1554     switch (rtcp_sync) {
1555       case GST_RTP_BIN_RTCP_SYNC_RTP:
1556         if (!use_rtp)
1557           break;
1558         GST_DEBUG_OBJECT (bin, "using rtp generated reports; "
1559             "client %p min rtp delta %" G_GINT64_FORMAT, client, rtp_min);
1560         /* fall-through */
1561       case GST_RTP_BIN_RTCP_SYNC_INITIAL:
1562         /* if all have been synced already, do not bother further */
1563         if (all_sync) {
1564           GST_DEBUG_OBJECT (bin, "all streams already synced; done");
1565           return;
1566         }
1567         break;
1568       default:
1569         break;
1570     }
1571
1572     /* bail out if we adjusted recently enough */
1573     if (all_sync && (ntpnstime - bin->priv->last_ntpnstime) <
1574         bin->rtcp_sync_interval * GST_MSECOND) {
1575       GST_DEBUG_OBJECT (bin, "discarding RTCP sender packet for sync; "
1576           "previous sender info too recent "
1577           "(previous NTP %" G_GUINT64_FORMAT ")", bin->priv->last_ntpnstime);
1578       return;
1579     }
1580     bin->priv->last_ntpnstime = ntpnstime;
1581
1582     /* calculate offsets for each stream */
1583     for (walk = client->streams; walk; walk = g_slist_next (walk)) {
1584       GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
1585       gint64 ts_offset;
1586
1587       /* ignore streams for which we didn't receive an SR packet yet, we
1588        * can't synchronize them yet. We can however sync other streams just
1589        * fine. */
1590       if (!ostream->have_sync)
1591         continue;
1592
1593       /* calculate offset to our reference stream, this should always give a
1594        * positive number. */
1595       if (use_rtp)
1596         ts_offset = ostream->rtp_delta - rtp_min;
1597       else
1598         ts_offset = ostream->rt_delta - min;
1599
1600       stream_set_ts_offset (bin, ostream, ts_offset, bin->max_ts_offset,
1601           MIN_TS_OFFSET, TRUE);
1602     }
1603   }
1604   gst_rtp_bin_send_sync_event (stream);
1605
1606   return;
1607 }
1608
1609 #define GST_RTCP_BUFFER_FOR_PACKETS(b,buffer,packet) \
1610   for ((b) = gst_rtcp_buffer_get_first_packet ((buffer), (packet)); (b); \
1611           (b) = gst_rtcp_packet_move_to_next ((packet)))
1612
1613 #define GST_RTCP_SDES_FOR_ITEMS(b,packet) \
1614   for ((b) = gst_rtcp_packet_sdes_first_item ((packet)); (b); \
1615           (b) = gst_rtcp_packet_sdes_next_item ((packet)))
1616
1617 #define GST_RTCP_SDES_FOR_ENTRIES(b,packet) \
1618   for ((b) = gst_rtcp_packet_sdes_first_entry ((packet)); (b); \
1619           (b) = gst_rtcp_packet_sdes_next_entry ((packet)))
1620
1621 static void
1622 gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
1623     GstRtpBinStream * stream)
1624 {
1625   GstRtpBin *bin;
1626   GstRTCPPacket packet;
1627   guint32 ssrc;
1628   guint64 ntptime;
1629   gboolean have_sr, have_sdes;
1630   gboolean more;
1631   guint64 base_rtptime;
1632   guint64 base_time;
1633   guint clock_rate;
1634   guint64 clock_base;
1635   guint64 extrtptime;
1636   GstBuffer *buffer;
1637   GstRTCPBuffer rtcp = { NULL, };
1638
1639   bin = stream->bin;
1640
1641   GST_DEBUG_OBJECT (bin, "sync handler called");
1642
1643   /* get the last relation between the rtp timestamps and the gstreamer
1644    * timestamps. We get this info directly from the jitterbuffer which
1645    * constructs gstreamer timestamps from rtp timestamps and so it know exactly
1646    * what the current situation is. */
1647   base_rtptime =
1648       g_value_get_uint64 (gst_structure_get_value (s, "base-rtptime"));
1649   base_time = g_value_get_uint64 (gst_structure_get_value (s, "base-time"));
1650   clock_rate = g_value_get_uint (gst_structure_get_value (s, "clock-rate"));
1651   clock_base = g_value_get_uint64 (gst_structure_get_value (s, "clock-base"));
1652   extrtptime =
1653       g_value_get_uint64 (gst_structure_get_value (s, "sr-ext-rtptime"));
1654   buffer = gst_value_get_buffer (gst_structure_get_value (s, "sr-buffer"));
1655
1656   have_sr = FALSE;
1657   have_sdes = FALSE;
1658
1659   gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
1660
1661   GST_RTCP_BUFFER_FOR_PACKETS (more, &rtcp, &packet) {
1662     /* first packet must be SR or RR or else the validate would have failed */
1663     switch (gst_rtcp_packet_get_type (&packet)) {
1664       case GST_RTCP_TYPE_SR:
1665         /* only parse first. There is only supposed to be one SR in the packet
1666          * but we will deal with malformed packets gracefully */
1667         if (have_sr)
1668           break;
1669         /* get NTP and RTP times */
1670         gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, NULL,
1671             NULL, NULL);
1672
1673         GST_DEBUG_OBJECT (bin, "received sync packet from SSRC %08x", ssrc);
1674         /* ignore SR that is not ours */
1675         if (ssrc != stream->ssrc)
1676           continue;
1677
1678         have_sr = TRUE;
1679         break;
1680       case GST_RTCP_TYPE_SDES:
1681       {
1682         gboolean more_items, more_entries;
1683
1684         /* only deal with first SDES, there is only supposed to be one SDES in
1685          * the RTCP packet but we deal with bad packets gracefully. Also bail
1686          * out if we have not seen an SR item yet. */
1687         if (have_sdes || !have_sr)
1688           break;
1689
1690         GST_RTCP_SDES_FOR_ITEMS (more_items, &packet) {
1691           /* skip items that are not about the SSRC of the sender */
1692           if (gst_rtcp_packet_sdes_get_ssrc (&packet) != ssrc)
1693             continue;
1694
1695           /* find the CNAME entry */
1696           GST_RTCP_SDES_FOR_ENTRIES (more_entries, &packet) {
1697             GstRTCPSDESType type;
1698             guint8 len;
1699             guint8 *data;
1700
1701             gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data);
1702
1703             if (type == GST_RTCP_SDES_CNAME) {
1704               GST_RTP_BIN_LOCK (bin);
1705               /* associate the stream to CNAME */
1706               gst_rtp_bin_associate (bin, stream, len, data,
1707                   ntptime, extrtptime, base_rtptime, base_time, clock_rate,
1708                   clock_base);
1709               GST_RTP_BIN_UNLOCK (bin);
1710             }
1711           }
1712         }
1713         have_sdes = TRUE;
1714         break;
1715       }
1716       default:
1717         /* we can ignore these packets */
1718         break;
1719     }
1720   }
1721   gst_rtcp_buffer_unmap (&rtcp);
1722 }
1723
1724 /* create a new stream with @ssrc in @session. Must be called with
1725  * RTP_SESSION_LOCK. */
1726 static GstRtpBinStream *
1727 create_stream (GstRtpBinSession * session, guint32 ssrc)
1728 {
1729   GstElement *buffer, *demux = NULL;
1730 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1731   GstElement *queue2 = NULL;
1732 #endif
1733   GstRtpBinStream *stream;
1734   GstRtpBin *rtpbin;
1735   GstState target;
1736   GObjectClass *jb_class;
1737
1738   rtpbin = session->bin;
1739
1740   if (g_slist_length (session->streams) >= rtpbin->max_streams)
1741     goto max_streams;
1742
1743   if (!(buffer =
1744           session_request_element (session, SIGNAL_REQUEST_JITTERBUFFER)))
1745     goto no_jitterbuffer;
1746
1747   if (!rtpbin->ignore_pt) {
1748     if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
1749       goto no_demux;
1750   }
1751 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1752   if (rtpbin->use_rtsp_buffering &&
1753       rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) {
1754     if (!(queue2 = gst_element_factory_make ("queue2", NULL)))
1755       goto no_queue2;
1756   }
1757 #endif
1758
1759   stream = g_new0 (GstRtpBinStream, 1);
1760   stream->ssrc = ssrc;
1761   stream->bin = rtpbin;
1762   stream->session = session;
1763   stream->buffer = gst_object_ref (buffer);
1764   stream->demux = demux;
1765
1766   stream->have_sync = FALSE;
1767   stream->rt_delta = 0;
1768   stream->rtp_delta = 0;
1769   stream->percent = 100;
1770 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1771   stream->prev_percent = 0;
1772 #endif
1773   stream->clock_base = -100 * GST_SECOND;
1774   session->streams = g_slist_prepend (session->streams, stream);
1775
1776   jb_class = G_OBJECT_GET_CLASS (G_OBJECT (buffer));
1777
1778   if (g_signal_lookup ("request-pt-map", G_OBJECT_TYPE (buffer)) != 0) {
1779     /* provide clock_rate to the jitterbuffer when needed */
1780     stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map",
1781         (GCallback) pt_map_requested, session);
1782   }
1783   if (g_signal_lookup ("on-npt-stop", G_OBJECT_TYPE (buffer)) != 0) {
1784     stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop",
1785         (GCallback) on_npt_stop, stream);
1786   }
1787
1788   g_object_set_data (G_OBJECT (buffer), "GstRTPBin.session", session);
1789   g_object_set_data (G_OBJECT (buffer), "GstRTPBin.stream", stream);
1790
1791   /* configure latency and packet lost */
1792   g_object_set (buffer, "latency", rtpbin->latency_ms, NULL);
1793
1794   if (g_object_class_find_property (jb_class, "drop-on-latency"))
1795     g_object_set (buffer, "drop-on-latency", rtpbin->drop_on_latency, NULL);
1796   if (g_object_class_find_property (jb_class, "do-lost"))
1797     g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL);
1798   if (g_object_class_find_property (jb_class, "mode"))
1799     g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL);
1800   if (g_object_class_find_property (jb_class, "do-retransmission"))
1801     g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL);
1802   if (g_object_class_find_property (jb_class, "max-rtcp-rtp-time-diff"))
1803     g_object_set (buffer, "max-rtcp-rtp-time-diff",
1804         rtpbin->max_rtcp_rtp_time_diff, NULL);
1805   if (g_object_class_find_property (jb_class, "max-dropout-time"))
1806     g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time, NULL);
1807   if (g_object_class_find_property (jb_class, "max-misorder-time"))
1808     g_object_set (buffer, "max-misorder-time", rtpbin->max_misorder_time, NULL);
1809   if (g_object_class_find_property (jb_class, "rfc7273-sync"))
1810     g_object_set (buffer, "rfc7273-sync", rtpbin->rfc7273_sync, NULL);
1811   if (g_object_class_find_property (jb_class, "max-ts-offset-adjustment"))
1812     g_object_set (buffer, "max-ts-offset-adjustment",
1813         rtpbin->max_ts_offset_adjustment, NULL);
1814
1815 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1816   /* configure queue2 to use live buffering */
1817   if (queue2) {
1818     g_object_set_data (G_OBJECT (queue2), "GstRTPBin.stream", stream);
1819     g_object_set (queue2, "use-buffering", TRUE, NULL);
1820     g_object_set (queue2, "buffer-mode", GST_BUFFERING_LIVE, NULL);
1821   }
1822 #endif
1823   g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0,
1824       buffer, session->id, ssrc);
1825
1826   if (!rtpbin->ignore_pt)
1827     gst_bin_add (GST_BIN_CAST (rtpbin), demux);
1828
1829 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1830   if (queue2)
1831     gst_bin_add (GST_BIN_CAST (rtpbin), queue2);
1832 #endif
1833
1834   /* link stuff */
1835 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1836   if (queue2) {
1837     gst_element_link_pads_full (buffer, "src", queue2, "sink",
1838         GST_PAD_LINK_CHECK_NOTHING);
1839     if (demux) {
1840       gst_element_link_pads_full (queue2, "src", demux, "sink",
1841           GST_PAD_LINK_CHECK_NOTHING);
1842     }
1843   } else if (demux) {
1844     gst_element_link_pads_full (buffer, "src", demux, "sink",
1845         GST_PAD_LINK_CHECK_NOTHING);
1846   }
1847 #else
1848   if (demux)
1849     gst_element_link_pads_full (buffer, "src", demux, "sink",
1850         GST_PAD_LINK_CHECK_NOTHING);
1851
1852 #endif
1853   if (rtpbin->buffering) {
1854     guint64 last_out;
1855
1856     if (g_signal_lookup ("set-active", G_OBJECT_TYPE (buffer)) != 0) {
1857       GST_INFO_OBJECT (rtpbin,
1858           "bin is buffering, set jitterbuffer as not active");
1859       g_signal_emit_by_name (buffer, "set-active", FALSE, (gint64) 0,
1860           &last_out);
1861     }
1862   }
1863
1864
1865   GST_OBJECT_LOCK (rtpbin);
1866   target = GST_STATE_TARGET (rtpbin);
1867   GST_OBJECT_UNLOCK (rtpbin);
1868
1869   /* from sink to source */
1870   if (demux)
1871     gst_element_set_state (demux, target);
1872
1873   gst_element_set_state (buffer, target);
1874
1875 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1876   if (queue2)
1877     gst_element_set_state (queue2, target);
1878 #endif
1879
1880   return stream;
1881
1882   /* ERRORS */
1883 max_streams:
1884   {
1885     GST_WARNING_OBJECT (rtpbin, "stream exceeds maximum (%d)",
1886         rtpbin->max_streams);
1887     return NULL;
1888   }
1889 no_jitterbuffer:
1890   {
1891     g_warning ("rtpbin: could not create rtpjitterbuffer element");
1892     return NULL;
1893   }
1894 no_demux:
1895   {
1896     gst_object_unref (buffer);
1897     g_warning ("rtpbin: could not create rtpptdemux element");
1898     return NULL;
1899   }
1900 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1901 no_queue2:
1902   {
1903     gst_object_unref (buffer);
1904     gst_object_unref (demux);
1905     g_warning ("rtpbin: could not create queue2 element");
1906     return NULL;
1907   }
1908 #endif
1909 }
1910
1911 /* called with RTP_BIN_LOCK */
1912 static void
1913 free_stream (GstRtpBinStream * stream, GstRtpBin * bin)
1914 {
1915   GstRtpBinSession *sess = stream->session;
1916   GSList *clients, *next_client;
1917
1918   GST_DEBUG_OBJECT (bin, "freeing stream %p", stream);
1919
1920   gst_element_set_locked_state (stream->buffer, TRUE);
1921   if (stream->demux)
1922     gst_element_set_locked_state (stream->demux, TRUE);
1923
1924   gst_element_set_state (stream->buffer, GST_STATE_NULL);
1925   if (stream->demux)
1926     gst_element_set_state (stream->demux, GST_STATE_NULL);
1927
1928   if (stream->demux) {
1929     g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig);
1930     g_signal_handler_disconnect (stream->demux, stream->demux_ptreq_sig);
1931     g_signal_handler_disconnect (stream->demux, stream->demux_ptchange_sig);
1932     g_signal_handler_disconnect (stream->demux, stream->demux_padremoved_sig);
1933   }
1934
1935   if (stream->buffer_handlesync_sig)
1936     g_signal_handler_disconnect (stream->buffer, stream->buffer_handlesync_sig);
1937   if (stream->buffer_ptreq_sig)
1938     g_signal_handler_disconnect (stream->buffer, stream->buffer_ptreq_sig);
1939   if (stream->buffer_ntpstop_sig)
1940     g_signal_handler_disconnect (stream->buffer, stream->buffer_ntpstop_sig);
1941
1942   sess->elements = g_slist_remove (sess->elements, stream->buffer);
1943   remove_bin_element (stream->buffer, bin);
1944   gst_object_unref (stream->buffer);
1945
1946   if (stream->demux)
1947     gst_bin_remove (GST_BIN_CAST (bin), stream->demux);
1948
1949   for (clients = bin->clients; clients; clients = next_client) {
1950     GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
1951     GSList *streams, *next_stream;
1952
1953     next_client = g_slist_next (clients);
1954
1955     for (streams = client->streams; streams; streams = next_stream) {
1956       GstRtpBinStream *ostream = (GstRtpBinStream *) streams->data;
1957
1958       next_stream = g_slist_next (streams);
1959
1960       if (ostream == stream) {
1961         client->streams = g_slist_delete_link (client->streams, streams);
1962         /* If this was the last stream belonging to this client,
1963          * clean up the client. */
1964         if (--client->nstreams == 0) {
1965           bin->clients = g_slist_delete_link (bin->clients, clients);
1966           free_client (client, bin);
1967           break;
1968         }
1969       }
1970     }
1971   }
1972   g_free (stream);
1973 }
1974
1975 /* GObject vmethods */
1976 static void gst_rtp_bin_dispose (GObject * object);
1977 static void gst_rtp_bin_finalize (GObject * object);
1978 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
1979     const GValue * value, GParamSpec * pspec);
1980 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
1981     GValue * value, GParamSpec * pspec);
1982
1983 /* GstElement vmethods */
1984 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
1985     GstStateChange transition);
1986 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
1987     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
1988 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
1989 static void gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message);
1990
1991 #define gst_rtp_bin_parent_class parent_class
1992 G_DEFINE_TYPE_WITH_PRIVATE (GstRtpBin, gst_rtp_bin, GST_TYPE_BIN);
1993
1994 static gboolean
1995 _gst_element_accumulator (GSignalInvocationHint * ihint,
1996     GValue * return_accu, const GValue * handler_return, gpointer dummy)
1997 {
1998   GstElement *element;
1999
2000   element = g_value_get_object (handler_return);
2001   GST_DEBUG ("got element %" GST_PTR_FORMAT, element);
2002
2003   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
2004     g_value_set_object (return_accu, element);
2005
2006   /* stop emission if we have an element */
2007   return (element == NULL);
2008 }
2009
2010 static gboolean
2011 _gst_caps_accumulator (GSignalInvocationHint * ihint,
2012     GValue * return_accu, const GValue * handler_return, gpointer dummy)
2013 {
2014   GstCaps *caps;
2015
2016   caps = g_value_get_boxed (handler_return);
2017   GST_DEBUG ("got caps %" GST_PTR_FORMAT, caps);
2018
2019   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
2020     g_value_set_boxed (return_accu, caps);
2021
2022   /* stop emission if we have a caps */
2023   return (caps == NULL);
2024 }
2025
2026 static void
2027 gst_rtp_bin_class_init (GstRtpBinClass * klass)
2028 {
2029   GObjectClass *gobject_class;
2030   GstElementClass *gstelement_class;
2031   GstBinClass *gstbin_class;
2032
2033   gobject_class = (GObjectClass *) klass;
2034   gstelement_class = (GstElementClass *) klass;
2035   gstbin_class = (GstBinClass *) klass;
2036
2037   gobject_class->dispose = gst_rtp_bin_dispose;
2038   gobject_class->finalize = gst_rtp_bin_finalize;
2039   gobject_class->set_property = gst_rtp_bin_set_property;
2040   gobject_class->get_property = gst_rtp_bin_get_property;
2041
2042   g_object_class_install_property (gobject_class, PROP_LATENCY,
2043       g_param_spec_uint ("latency", "Buffer latency in ms",
2044           "Default amount of ms to buffer in the jitterbuffers", 0,
2045           G_MAXUINT, DEFAULT_LATENCY_MS,
2046           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2047
2048   g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY,
2049       g_param_spec_boolean ("drop-on-latency",
2050           "Drop buffers when maximum latency is reached",
2051           "Tells the jitterbuffer to never exceed the given latency in size",
2052           DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2053
2054   /**
2055    * GstRtpBin::request-pt-map:
2056    * @rtpbin: the object which received the signal
2057    * @session: the session
2058    * @pt: the pt
2059    *
2060    * Request the payload type as #GstCaps for @pt in @session.
2061    */
2062   gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
2063       g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
2064       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_pt_map),
2065       _gst_caps_accumulator, NULL, NULL, GST_TYPE_CAPS, 2, G_TYPE_UINT,
2066       G_TYPE_UINT);
2067
2068     /**
2069    * GstRtpBin::payload-type-change:
2070    * @rtpbin: the object which received the signal
2071    * @session: the session
2072    * @pt: the pt
2073    *
2074    * Signal that the current payload type changed to @pt in @session.
2075    */
2076   gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] =
2077       g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass),
2078       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, payload_type_change),
2079       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2080
2081   /**
2082    * GstRtpBin::clear-pt-map:
2083    * @rtpbin: the object which received the signal
2084    *
2085    * Clear all previously cached pt-mapping obtained with
2086    * #GstRtpBin::request-pt-map.
2087    */
2088   gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] =
2089       g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
2090       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2091           clear_pt_map), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
2092
2093   /**
2094    * GstRtpBin::reset-sync:
2095    * @rtpbin: the object which received the signal
2096    *
2097    * Reset all currently configured lip-sync parameters and require new SR
2098    * packets for all streams before lip-sync is attempted again.
2099    */
2100   gst_rtp_bin_signals[SIGNAL_RESET_SYNC] =
2101       g_signal_new ("reset-sync", G_TYPE_FROM_CLASS (klass),
2102       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2103           reset_sync), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
2104
2105   /**
2106    * GstRtpBin::get-session:
2107    * @rtpbin: the object which received the signal
2108    * @id: the session id
2109    *
2110    * Request the related GstRtpSession as #GstElement related with session @id.
2111    *
2112    * Since: 1.8
2113    */
2114   gst_rtp_bin_signals[SIGNAL_GET_SESSION] =
2115       g_signal_new ("get-session", G_TYPE_FROM_CLASS (klass),
2116       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2117           get_session), NULL, NULL, NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2118
2119   /**
2120    * GstRtpBin::get-internal-session:
2121    * @rtpbin: the object which received the signal
2122    * @id: the session id
2123    *
2124    * Request the internal RTPSession object as #GObject in session @id.
2125    */
2126   gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_SESSION] =
2127       g_signal_new ("get-internal-session", G_TYPE_FROM_CLASS (klass),
2128       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2129           get_internal_session), NULL, NULL, NULL, RTP_TYPE_SESSION, 1,
2130       G_TYPE_UINT);
2131
2132   /**
2133    * GstRtpBin::get-internal-storage:
2134    * @rtpbin: the object which received the signal
2135    * @id: the session id
2136    *
2137    * Request the internal RTPStorage object as #GObject in session @id. This
2138    * is the internal storage used by the RTPStorage element, which is used to
2139    * keep a backlog of received RTP packets for the session @id.
2140    *
2141    * Since: 1.14
2142    */
2143   gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_STORAGE] =
2144       g_signal_new ("get-internal-storage", G_TYPE_FROM_CLASS (klass),
2145       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2146           get_internal_storage), NULL, NULL, NULL, G_TYPE_OBJECT, 1,
2147       G_TYPE_UINT);
2148
2149   /**
2150    * GstRtpBin::get-storage:
2151    * @rtpbin: the object which received the signal
2152    * @id: the session id
2153    *
2154    * Request the RTPStorage element as #GObject in session @id. This element
2155    * is used to keep a backlog of received RTP packets for the session @id.
2156    *
2157    * Since: 1.16
2158    */
2159   gst_rtp_bin_signals[SIGNAL_GET_STORAGE] =
2160       g_signal_new ("get-storage", G_TYPE_FROM_CLASS (klass),
2161       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
2162           get_storage), NULL, NULL, NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2163
2164   /**
2165    * GstRtpBin::on-new-ssrc:
2166    * @rtpbin: the object which received the signal
2167    * @session: the session
2168    * @ssrc: the SSRC
2169    *
2170    * Notify of a new SSRC that entered @session.
2171    */
2172   gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC] =
2173       g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass),
2174       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_ssrc),
2175       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2176   /**
2177    * GstRtpBin::on-ssrc-collision:
2178    * @rtpbin: the object which received the signal
2179    * @session: the session
2180    * @ssrc: the SSRC
2181    *
2182    * Notify when we have an SSRC collision
2183    */
2184   gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION] =
2185       g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass),
2186       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_collision),
2187       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2188   /**
2189    * GstRtpBin::on-ssrc-validated:
2190    * @rtpbin: the object which received the signal
2191    * @session: the session
2192    * @ssrc: the SSRC
2193    *
2194    * Notify of a new SSRC that became validated.
2195    */
2196   gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED] =
2197       g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass),
2198       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_validated),
2199       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2200   /**
2201    * GstRtpBin::on-ssrc-active:
2202    * @rtpbin: the object which received the signal
2203    * @session: the session
2204    * @ssrc: the SSRC
2205    *
2206    * Notify of a SSRC that is active, i.e., sending RTCP.
2207    */
2208   gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE] =
2209       g_signal_new ("on-ssrc-active", G_TYPE_FROM_CLASS (klass),
2210       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_active),
2211       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2212   /**
2213    * GstRtpBin::on-ssrc-sdes:
2214    * @rtpbin: the object which received the signal
2215    * @session: the session
2216    * @ssrc: the SSRC
2217    *
2218    * Notify of a SSRC that is active, i.e., sending RTCP.
2219    */
2220   gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES] =
2221       g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass),
2222       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_sdes),
2223       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2224
2225   /**
2226    * GstRtpBin::on-bye-ssrc:
2227    * @rtpbin: the object which received the signal
2228    * @session: the session
2229    * @ssrc: the SSRC
2230    *
2231    * Notify of an SSRC that became inactive because of a BYE packet.
2232    */
2233   gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC] =
2234       g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass),
2235       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_ssrc),
2236       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2237   /**
2238    * GstRtpBin::on-bye-timeout:
2239    * @rtpbin: the object which received the signal
2240    * @session: the session
2241    * @ssrc: the SSRC
2242    *
2243    * Notify of an SSRC that has timed out because of BYE
2244    */
2245   gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT] =
2246       g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass),
2247       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_timeout),
2248       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2249   /**
2250    * GstRtpBin::on-timeout:
2251    * @rtpbin: the object which received the signal
2252    * @session: the session
2253    * @ssrc: the SSRC
2254    *
2255    * Notify of an SSRC that has timed out
2256    */
2257   gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT] =
2258       g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass),
2259       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_timeout),
2260       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2261   /**
2262    * GstRtpBin::on-sender-timeout:
2263    * @rtpbin: the object which received the signal
2264    * @session: the session
2265    * @ssrc: the SSRC
2266    *
2267    * Notify of a sender SSRC that has timed out and became a receiver
2268    */
2269   gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT] =
2270       g_signal_new ("on-sender-timeout", G_TYPE_FROM_CLASS (klass),
2271       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_sender_timeout),
2272       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2273
2274   /**
2275    * GstRtpBin::on-npt-stop:
2276    * @rtpbin: the object which received the signal
2277    * @session: the session
2278    * @ssrc: the SSRC
2279    *
2280    * Notify that SSRC sender has sent data up to the configured NPT stop time.
2281    */
2282   gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP] =
2283       g_signal_new ("on-npt-stop", G_TYPE_FROM_CLASS (klass),
2284       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_npt_stop),
2285       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2286
2287   /**
2288    * GstRtpBin::request-rtp-encoder:
2289    * @rtpbin: the object which received the signal
2290    * @session: the session
2291    *
2292    * Request an RTP encoder element for the given @session. The encoder
2293    * element will be added to the bin if not previously added.
2294    *
2295    * If no handler is connected, no encoder will be used.
2296    *
2297    * Since: 1.4
2298    */
2299   gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_ENCODER] =
2300       g_signal_new ("request-rtp-encoder", G_TYPE_FROM_CLASS (klass),
2301       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2302           request_rtp_encoder), _gst_element_accumulator, NULL, NULL,
2303       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2304
2305   /**
2306    * GstRtpBin::request-rtp-decoder:
2307    * @rtpbin: the object which received the signal
2308    * @session: the session
2309    *
2310    * Request an RTP decoder element for the given @session. The decoder
2311    * element will be added to the bin if not previously added.
2312    *
2313    * If no handler is connected, no encoder will be used.
2314    *
2315    * Since: 1.4
2316    */
2317   gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_DECODER] =
2318       g_signal_new ("request-rtp-decoder", G_TYPE_FROM_CLASS (klass),
2319       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2320           request_rtp_decoder), _gst_element_accumulator, NULL,
2321       NULL, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2322
2323   /**
2324    * GstRtpBin::request-rtcp-encoder:
2325    * @rtpbin: the object which received the signal
2326    * @session: the session
2327    *
2328    * Request an RTCP encoder element for the given @session. The encoder
2329    * element will be added to the bin if not previously added.
2330    *
2331    * If no handler is connected, no encoder will be used.
2332    *
2333    * Since: 1.4
2334    */
2335   gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_ENCODER] =
2336       g_signal_new ("request-rtcp-encoder", G_TYPE_FROM_CLASS (klass),
2337       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2338           request_rtcp_encoder), _gst_element_accumulator, NULL, NULL,
2339       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2340
2341   /**
2342    * GstRtpBin::request-rtcp-decoder:
2343    * @rtpbin: the object which received the signal
2344    * @session: the session
2345    *
2346    * Request an RTCP decoder element for the given @session. The decoder
2347    * element will be added to the bin if not previously added.
2348    *
2349    * If no handler is connected, no encoder will be used.
2350    *
2351    * Since: 1.4
2352    */
2353   gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_DECODER] =
2354       g_signal_new ("request-rtcp-decoder", G_TYPE_FROM_CLASS (klass),
2355       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2356           request_rtcp_decoder), _gst_element_accumulator, NULL, NULL,
2357       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2358
2359   /**
2360    * GstRtpBin::request-jitterbuffer:
2361    * @rtpbin: the object which received the signal
2362    * @session: the session
2363    *
2364    * Request a jitterbuffer element for the given @session.
2365    *
2366    * If no handler is connected, the default jitterbuffer will be used.
2367    *
2368    * Note: The provided element is expected to conform to the API exposed
2369    * by the standard #GstRtpJitterBuffer. Runtime checks will be made to
2370    * determine whether it exposes properties and signals before attempting
2371    * to set, call or connect to them, and some functionalities of #GstRtpBin
2372    * may not be available when that is not the case.
2373    *
2374    * This should be considered experimental API, as the standard jitterbuffer
2375    * API is susceptible to change, provided elements will have to update their
2376    * custom jitterbuffer's API to match the API of #GstRtpJitterBuffer if and
2377    * when it changes.
2378    *
2379    * Since: 1.18
2380    */
2381   gst_rtp_bin_signals[SIGNAL_REQUEST_JITTERBUFFER] =
2382       g_signal_new ("request-jitterbuffer", G_TYPE_FROM_CLASS (klass),
2383       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2384           request_jitterbuffer), _gst_element_accumulator, NULL,
2385       g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2386
2387   /**
2388    * GstRtpBin::new-jitterbuffer:
2389    * @rtpbin: the object which received the signal
2390    * @jitterbuffer: the new jitterbuffer
2391    * @session: the session
2392    * @ssrc: the SSRC
2393    *
2394    * Notify that a new @jitterbuffer was created for @session and @ssrc.
2395    * This signal can, for example, be used to configure @jitterbuffer.
2396    *
2397    * Since: 1.4
2398    */
2399   gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER] =
2400       g_signal_new ("new-jitterbuffer", G_TYPE_FROM_CLASS (klass),
2401       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2402           new_jitterbuffer), NULL, NULL, NULL,
2403       G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT);
2404
2405   /**
2406    * GstRtpBin::new-storage:
2407    * @rtpbin: the object which received the signal
2408    * @storage: the new storage
2409    * @session: the session
2410    *
2411    * Notify that a new @storage was created for @session.
2412    * This signal can, for example, be used to configure @storage.
2413    *
2414    * Since: 1.14
2415    */
2416   gst_rtp_bin_signals[SIGNAL_NEW_STORAGE] =
2417       g_signal_new ("new-storage", G_TYPE_FROM_CLASS (klass),
2418       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2419           new_storage), NULL, NULL, NULL,
2420       G_TYPE_NONE, 2, GST_TYPE_ELEMENT, G_TYPE_UINT);
2421
2422   /**
2423    * GstRtpBin::request-aux-sender:
2424    * @rtpbin: the object which received the signal
2425    * @session: the session
2426    *
2427    * Request an AUX sender element for the given @session. The AUX
2428    * element will be added to the bin.
2429    *
2430    * If no handler is connected, no AUX element will be used.
2431    *
2432    * Since: 1.4
2433    */
2434   gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_SENDER] =
2435       g_signal_new ("request-aux-sender", G_TYPE_FROM_CLASS (klass),
2436       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2437           request_aux_sender), _gst_element_accumulator, NULL, NULL,
2438       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2439
2440   /**
2441    * GstRtpBin::request-aux-receiver:
2442    * @rtpbin: the object which received the signal
2443    * @session: the session
2444    *
2445    * Request an AUX receiver element for the given @session. The AUX
2446    * element will be added to the bin.
2447    *
2448    * If no handler is connected, no AUX element will be used.
2449    *
2450    * Since: 1.4
2451    */
2452   gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_RECEIVER] =
2453       g_signal_new ("request-aux-receiver", G_TYPE_FROM_CLASS (klass),
2454       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2455           request_aux_receiver), _gst_element_accumulator, NULL, NULL,
2456       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2457
2458   /**
2459    * GstRtpBin::request-fec-decoder:
2460    * @rtpbin: the object which received the signal
2461    * @session: the session index
2462    *
2463    * Request a FEC decoder element for the given @session. The element
2464    * will be added to the bin after the pt demuxer.
2465    *
2466    * If no handler is connected, no FEC decoder will be used.
2467    *
2468    * Since: 1.14
2469    */
2470   gst_rtp_bin_signals[SIGNAL_REQUEST_FEC_DECODER] =
2471       g_signal_new ("request-fec-decoder", G_TYPE_FROM_CLASS (klass),
2472       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2473           request_fec_decoder), _gst_element_accumulator, NULL, NULL,
2474       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2475
2476   /**
2477    * GstRtpBin::request-fec-encoder:
2478    * @rtpbin: the object which received the signal
2479    * @session: the session index
2480    *
2481    * Request a FEC encoder element for the given @session. The element
2482    * will be added to the bin after the RTPSession.
2483    *
2484    * If no handler is connected, no FEC encoder will be used.
2485    *
2486    * Since: 1.14
2487    */
2488   gst_rtp_bin_signals[SIGNAL_REQUEST_FEC_ENCODER] =
2489       g_signal_new ("request-fec-encoder", G_TYPE_FROM_CLASS (klass),
2490       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2491           request_fec_encoder), _gst_element_accumulator, NULL, NULL,
2492       GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
2493
2494   /**
2495    * GstRtpBin::on-new-sender-ssrc:
2496    * @rtpbin: the object which received the signal
2497    * @session: the session
2498    * @ssrc: the sender SSRC
2499    *
2500    * Notify of a new sender SSRC that entered @session.
2501    *
2502    * Since: 1.8
2503    */
2504   gst_rtp_bin_signals[SIGNAL_ON_NEW_SENDER_SSRC] =
2505       g_signal_new ("on-new-sender-ssrc", G_TYPE_FROM_CLASS (klass),
2506       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_sender_ssrc),
2507       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2508   /**
2509    * GstRtpBin::on-sender-ssrc-active:
2510    * @rtpbin: the object which received the signal
2511    * @session: the session
2512    * @ssrc: the sender SSRC
2513    *
2514    * Notify of a sender SSRC that is active, i.e., sending RTCP.
2515    *
2516    * Since: 1.8
2517    */
2518   gst_rtp_bin_signals[SIGNAL_ON_SENDER_SSRC_ACTIVE] =
2519       g_signal_new ("on-sender-ssrc-active", G_TYPE_FROM_CLASS (klass),
2520       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
2521           on_sender_ssrc_active), NULL, NULL, NULL,
2522       G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2523
2524   g_object_class_install_property (gobject_class, PROP_SDES,
2525       g_param_spec_boxed ("sdes", "SDES",
2526           "The SDES items of this session",
2527           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
2528 #ifndef TIZEN_FEATURE_GST_UPSTREAM_AVOID_BUILD_BREAK
2529           | GST_PARAM_DOC_SHOW_DEFAULT));
2530 #else
2531           ));
2532 #endif
2533
2534   g_object_class_install_property (gobject_class, PROP_DO_LOST,
2535       g_param_spec_boolean ("do-lost", "Do Lost",
2536           "Send an event downstream when a packet is lost", DEFAULT_DO_LOST,
2537           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2538
2539   g_object_class_install_property (gobject_class, PROP_AUTOREMOVE,
2540       g_param_spec_boolean ("autoremove", "Auto Remove",
2541           "Automatically remove timed out sources", DEFAULT_AUTOREMOVE,
2542           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2543
2544   g_object_class_install_property (gobject_class, PROP_IGNORE_PT,
2545       g_param_spec_boolean ("ignore-pt", "Ignore PT",
2546           "Do not demultiplex based on PT values", DEFAULT_IGNORE_PT,
2547           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2548
2549   g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
2550       g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
2551           "Use the pipeline running-time to set the NTP time in the RTCP SR messages "
2552           "(DEPRECATED: Use ntp-time-source property)",
2553           DEFAULT_USE_PIPELINE_CLOCK,
2554           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
2555   /**
2556    * GstRtpBin:buffer-mode:
2557    *
2558    * Control the buffering and timestamping mode used by the jitterbuffer.
2559    */
2560   g_object_class_install_property (gobject_class, PROP_BUFFER_MODE,
2561       g_param_spec_enum ("buffer-mode", "Buffer Mode",
2562           "Control the buffering algorithm in use", RTP_TYPE_JITTER_BUFFER_MODE,
2563           DEFAULT_BUFFER_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2564   /**
2565    * GstRtpBin:ntp-sync:
2566    *
2567    * Set the NTP time from the sender reports as the running-time on the
2568    * buffers. When both the sender and receiver have sychronized
2569    * running-time, i.e. when the clock and base-time is shared
2570    * between the receivers and the and the senders, this option can be
2571    * used to synchronize receivers on multiple machines.
2572    */
2573   g_object_class_install_property (gobject_class, PROP_NTP_SYNC,
2574       g_param_spec_boolean ("ntp-sync", "Sync on NTP clock",
2575           "Synchronize received streams to the NTP clock", DEFAULT_NTP_SYNC,
2576           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2577
2578   /**
2579    * GstRtpBin:rtcp-sync:
2580    *
2581    * If not synchronizing (directly) to the NTP clock, determines how to sync
2582    * the various streams.
2583    */
2584   g_object_class_install_property (gobject_class, PROP_RTCP_SYNC,
2585       g_param_spec_enum ("rtcp-sync", "RTCP Sync",
2586           "Use of RTCP SR in synchronization", GST_RTP_BIN_RTCP_SYNC_TYPE,
2587           DEFAULT_RTCP_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2588
2589   /**
2590    * GstRtpBin:rtcp-sync-interval:
2591    *
2592    * Determines how often to sync streams using RTCP data.
2593    */
2594   g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_INTERVAL,
2595       g_param_spec_uint ("rtcp-sync-interval", "RTCP Sync Interval",
2596           "RTCP SR interval synchronization (ms) (0 = always)",
2597           0, G_MAXUINT, DEFAULT_RTCP_SYNC_INTERVAL,
2598           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2599
2600   g_object_class_install_property (gobject_class, PROP_DO_SYNC_EVENT,
2601       g_param_spec_boolean ("do-sync-event", "Do Sync Event",
2602           "Send event downstream when a stream is synchronized to the sender",
2603           DEFAULT_DO_SYNC_EVENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2604
2605   /**
2606    * GstRtpBin:do-retransmission:
2607    *
2608    * Enables RTP retransmission on all streams. To control retransmission on
2609    * a per-SSRC basis, connect to the #GstRtpBin::new-jitterbuffer signal and
2610    * set the #GstRtpJitterBuffer:do-retransmission property on the
2611    * #GstRtpJitterBuffer object instead.
2612    */
2613   g_object_class_install_property (gobject_class, PROP_DO_RETRANSMISSION,
2614       g_param_spec_boolean ("do-retransmission", "Do retransmission",
2615           "Enable retransmission on all streams",
2616           DEFAULT_DO_RETRANSMISSION,
2617           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2618
2619   /**
2620    * GstRtpBin:rtp-profile:
2621    *
2622    * Sets the default RTP profile of newly created RTP sessions. The
2623    * profile can be changed afterwards on a per-session basis.
2624    */
2625   g_object_class_install_property (gobject_class, PROP_RTP_PROFILE,
2626       g_param_spec_enum ("rtp-profile", "RTP Profile",
2627           "Default RTP profile of newly created sessions",
2628           GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
2629           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2630
2631   g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
2632       g_param_spec_enum ("ntp-time-source", "NTP Time Source",
2633           "NTP time source for RTCP packets",
2634           gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
2635           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2636
2637   g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_SEND_TIME,
2638       g_param_spec_boolean ("rtcp-sync-send-time", "RTCP Sync Send Time",
2639           "Use send time or capture time for RTCP sync "
2640           "(TRUE = send time, FALSE = capture time)",
2641           DEFAULT_RTCP_SYNC_SEND_TIME,
2642           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2643
2644   g_object_class_install_property (gobject_class, PROP_MAX_RTCP_RTP_TIME_DIFF,
2645       g_param_spec_int ("max-rtcp-rtp-time-diff", "Max RTCP RTP Time Diff",
2646           "Maximum amount of time in ms that the RTP time in RTCP SRs "
2647           "is allowed to be ahead (-1 disabled)", -1, G_MAXINT,
2648           DEFAULT_MAX_RTCP_RTP_TIME_DIFF,
2649           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2650
2651   g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME,
2652       g_param_spec_uint ("max-dropout-time", "Max dropout time",
2653           "The maximum time (milliseconds) of missing packets tolerated.",
2654           0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME,
2655           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2656
2657   g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME,
2658       g_param_spec_uint ("max-misorder-time", "Max misorder time",
2659           "The maximum time (milliseconds) of misordered packets tolerated.",
2660           0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME,
2661           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2662
2663   g_object_class_install_property (gobject_class, PROP_RFC7273_SYNC,
2664       g_param_spec_boolean ("rfc7273-sync", "Sync on RFC7273 clock",
2665           "Synchronize received streams to the RFC7273 clock "
2666           "(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC,
2667           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2668
2669   g_object_class_install_property (gobject_class, PROP_MAX_STREAMS,
2670       g_param_spec_uint ("max-streams", "Max Streams",
2671           "The maximum number of streams to create for one session",
2672           0, G_MAXUINT, DEFAULT_MAX_STREAMS,
2673           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2674
2675   /**
2676    * GstRtpBin:max-ts-offset-adjustment:
2677    *
2678    * Syncing time stamps to NTP time adds a time offset. This parameter
2679    * specifies the maximum number of nanoseconds per frame that this time offset
2680    * may be adjusted with. This is used to avoid sudden large changes to time
2681    * stamps.
2682    *
2683    * Since: 1.14
2684    */
2685   g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET_ADJUSTMENT,
2686       g_param_spec_uint64 ("max-ts-offset-adjustment",
2687           "Max Timestamp Offset Adjustment",
2688           "The maximum number of nanoseconds per frame that time stamp offsets "
2689           "may be adjusted (0 = no limit).", 0, G_MAXUINT64,
2690           DEFAULT_MAX_TS_OFFSET_ADJUSTMENT, G_PARAM_READWRITE |
2691           G_PARAM_STATIC_STRINGS));
2692
2693   /**
2694    * GstRtpBin:max-ts-offset:
2695    *
2696    * Used to set an upper limit of how large a time offset may be. This
2697    * is used to protect against unrealistic values as a result of either
2698    * client,server or clock issues.
2699    *
2700    * Since: 1.14
2701    */
2702   g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET,
2703       g_param_spec_int64 ("max-ts-offset", "Max TS Offset",
2704           "The maximum absolute value of the time offset in (nanoseconds). "
2705           "Note, if the ntp-sync parameter is set the default value is "
2706           "changed to 0 (no limit)", 0, G_MAXINT64, DEFAULT_MAX_TS_OFFSET,
2707           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2708
2709 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2710   g_object_class_install_property (gobject_class, PROP_USE_RTSP_BUFFERING,
2711       g_param_spec_boolean ("use-rtsp-buffering", "Use RTSP buffering",
2712           "Use RTSP buffering in RTP_JITTER_BUFFER_MODE_SLAVE buffer mode",
2713           DEFAULT_RTSP_USE_BUFFERING,
2714           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2715 #endif
2716
2717   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
2718   gstelement_class->request_new_pad =
2719       GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
2720   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
2721
2722   /* sink pads */
2723   gst_element_class_add_static_pad_template (gstelement_class,
2724       &rtpbin_recv_rtp_sink_template);
2725   gst_element_class_add_static_pad_template (gstelement_class,
2726       &rtpbin_recv_rtcp_sink_template);
2727   gst_element_class_add_static_pad_template (gstelement_class,
2728       &rtpbin_send_rtp_sink_template);
2729
2730   /* src pads */
2731   gst_element_class_add_static_pad_template (gstelement_class,
2732       &rtpbin_recv_rtp_src_template);
2733   gst_element_class_add_static_pad_template (gstelement_class,
2734       &rtpbin_send_rtcp_src_template);
2735   gst_element_class_add_static_pad_template (gstelement_class,
2736       &rtpbin_send_rtp_src_template);
2737
2738   gst_element_class_set_static_metadata (gstelement_class, "RTP Bin",
2739       "Filter/Network/RTP",
2740       "Real-Time Transport Protocol bin",
2741       "Wim Taymans <wim.taymans@gmail.com>");
2742
2743   gstbin_class->handle_message = GST_DEBUG_FUNCPTR (gst_rtp_bin_handle_message);
2744
2745   klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
2746   klass->reset_sync = GST_DEBUG_FUNCPTR (gst_rtp_bin_reset_sync);
2747   klass->get_session = GST_DEBUG_FUNCPTR (gst_rtp_bin_get_session);
2748   klass->get_internal_session =
2749       GST_DEBUG_FUNCPTR (gst_rtp_bin_get_internal_session);
2750   klass->get_storage = GST_DEBUG_FUNCPTR (gst_rtp_bin_get_storage);
2751   klass->get_internal_storage =
2752       GST_DEBUG_FUNCPTR (gst_rtp_bin_get_internal_storage);
2753   klass->request_rtp_encoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_encoder);
2754   klass->request_rtp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder);
2755   klass->request_rtcp_encoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_encoder);
2756   klass->request_rtcp_decoder = GST_DEBUG_FUNCPTR (gst_rtp_bin_request_decoder);
2757   klass->request_jitterbuffer =
2758       GST_DEBUG_FUNCPTR (gst_rtp_bin_request_jitterbuffer);
2759
2760   GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
2761
2762 #ifndef TIZEN_FEATURE_GST_UPSTREAM_AVOID_BUILD_BREAK
2763   gst_type_mark_as_plugin_api (GST_RTP_BIN_RTCP_SYNC_TYPE, 0);
2764 #endif
2765 }
2766
2767 static void
2768 gst_rtp_bin_init (GstRtpBin * rtpbin)
2769 {
2770   gchar *cname;
2771
2772   rtpbin->priv = gst_rtp_bin_get_instance_private (rtpbin);
2773   g_mutex_init (&rtpbin->priv->bin_lock);
2774   g_mutex_init (&rtpbin->priv->dyn_lock);
2775
2776   rtpbin->latency_ms = DEFAULT_LATENCY_MS;
2777   rtpbin->latency_ns = DEFAULT_LATENCY_MS * GST_MSECOND;
2778   rtpbin->drop_on_latency = DEFAULT_DROP_ON_LATENCY;
2779   rtpbin->do_lost = DEFAULT_DO_LOST;
2780   rtpbin->ignore_pt = DEFAULT_IGNORE_PT;
2781   rtpbin->ntp_sync = DEFAULT_NTP_SYNC;
2782   rtpbin->rtcp_sync = DEFAULT_RTCP_SYNC;
2783   rtpbin->rtcp_sync_interval = DEFAULT_RTCP_SYNC_INTERVAL;
2784   rtpbin->priv->autoremove = DEFAULT_AUTOREMOVE;
2785   rtpbin->buffer_mode = DEFAULT_BUFFER_MODE;
2786   rtpbin->use_pipeline_clock = DEFAULT_USE_PIPELINE_CLOCK;
2787   rtpbin->send_sync_event = DEFAULT_DO_SYNC_EVENT;
2788   rtpbin->do_retransmission = DEFAULT_DO_RETRANSMISSION;
2789   rtpbin->rtp_profile = DEFAULT_RTP_PROFILE;
2790   rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
2791   rtpbin->rtcp_sync_send_time = DEFAULT_RTCP_SYNC_SEND_TIME;
2792   rtpbin->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF;
2793   rtpbin->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME;
2794   rtpbin->max_misorder_time = DEFAULT_MAX_MISORDER_TIME;
2795   rtpbin->rfc7273_sync = DEFAULT_RFC7273_SYNC;
2796   rtpbin->max_streams = DEFAULT_MAX_STREAMS;
2797   rtpbin->max_ts_offset_adjustment = DEFAULT_MAX_TS_OFFSET_ADJUSTMENT;
2798   rtpbin->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
2799   rtpbin->max_ts_offset_is_set = FALSE;
2800 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2801   rtpbin->use_rtsp_buffering = FALSE;
2802 #endif
2803
2804   /* some default SDES entries */
2805   cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ());
2806   rtpbin->sdes = gst_structure_new ("application/x-rtp-source-sdes",
2807       "cname", G_TYPE_STRING, cname, "tool", G_TYPE_STRING, "GStreamer", NULL);
2808   g_free (cname);
2809 }
2810
2811 static void
2812 gst_rtp_bin_dispose (GObject * object)
2813 {
2814   GstRtpBin *rtpbin;
2815
2816   rtpbin = GST_RTP_BIN (object);
2817
2818   GST_RTP_BIN_LOCK (rtpbin);
2819   GST_DEBUG_OBJECT (object, "freeing sessions");
2820   g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin);
2821   g_slist_free (rtpbin->sessions);
2822   rtpbin->sessions = NULL;
2823   GST_RTP_BIN_UNLOCK (rtpbin);
2824
2825   G_OBJECT_CLASS (parent_class)->dispose (object);
2826 }
2827
2828 static void
2829 gst_rtp_bin_finalize (GObject * object)
2830 {
2831   GstRtpBin *rtpbin;
2832
2833   rtpbin = GST_RTP_BIN (object);
2834
2835   if (rtpbin->sdes)
2836     gst_structure_free (rtpbin->sdes);
2837
2838   g_mutex_clear (&rtpbin->priv->bin_lock);
2839   g_mutex_clear (&rtpbin->priv->dyn_lock);
2840
2841   G_OBJECT_CLASS (parent_class)->finalize (object);
2842 }
2843
2844
2845 static void
2846 gst_rtp_bin_set_sdes_struct (GstRtpBin * bin, const GstStructure * sdes)
2847 {
2848   GSList *item;
2849
2850   if (sdes == NULL)
2851     return;
2852
2853   GST_RTP_BIN_LOCK (bin);
2854
2855   GST_OBJECT_LOCK (bin);
2856   if (bin->sdes)
2857     gst_structure_free (bin->sdes);
2858   bin->sdes = gst_structure_copy (sdes);
2859   GST_OBJECT_UNLOCK (bin);
2860
2861   /* store in all sessions */
2862   for (item = bin->sessions; item; item = g_slist_next (item)) {
2863     GstRtpBinSession *session = item->data;
2864     g_object_set (session->session, "sdes", sdes, NULL);
2865   }
2866
2867   GST_RTP_BIN_UNLOCK (bin);
2868 }
2869
2870 static GstStructure *
2871 gst_rtp_bin_get_sdes_struct (GstRtpBin * bin)
2872 {
2873   GstStructure *result;
2874
2875   GST_OBJECT_LOCK (bin);
2876   result = gst_structure_copy (bin->sdes);
2877   GST_OBJECT_UNLOCK (bin);
2878
2879   return result;
2880 }
2881
2882 static void
2883 gst_rtp_bin_set_property (GObject * object, guint prop_id,
2884     const GValue * value, GParamSpec * pspec)
2885 {
2886   GstRtpBin *rtpbin;
2887
2888   rtpbin = GST_RTP_BIN (object);
2889
2890   switch (prop_id) {
2891 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2892     case PROP_USE_RTSP_BUFFERING:
2893       GST_RTP_BIN_LOCK (rtpbin);
2894       rtpbin->use_rtsp_buffering = g_value_get_boolean (value);
2895       GST_RTP_BIN_UNLOCK (rtpbin);
2896       break;
2897 #endif
2898     case PROP_LATENCY:
2899       GST_RTP_BIN_LOCK (rtpbin);
2900       rtpbin->latency_ms = g_value_get_uint (value);
2901       rtpbin->latency_ns = rtpbin->latency_ms * GST_MSECOND;
2902       GST_RTP_BIN_UNLOCK (rtpbin);
2903       /* propagate the property down to the jitterbuffer */
2904       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "latency", value);
2905       break;
2906     case PROP_DROP_ON_LATENCY:
2907       GST_RTP_BIN_LOCK (rtpbin);
2908       rtpbin->drop_on_latency = g_value_get_boolean (value);
2909       GST_RTP_BIN_UNLOCK (rtpbin);
2910       /* propagate the property down to the jitterbuffer */
2911       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2912           "drop-on-latency", value);
2913       break;
2914     case PROP_SDES:
2915       gst_rtp_bin_set_sdes_struct (rtpbin, g_value_get_boxed (value));
2916       break;
2917     case PROP_DO_LOST:
2918       GST_RTP_BIN_LOCK (rtpbin);
2919       rtpbin->do_lost = g_value_get_boolean (value);
2920       GST_RTP_BIN_UNLOCK (rtpbin);
2921       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "do-lost", value);
2922       break;
2923     case PROP_NTP_SYNC:
2924       rtpbin->ntp_sync = g_value_get_boolean (value);
2925       /* The default value of max_ts_offset depends on ntp_sync. If user
2926        * hasn't set it then change default value */
2927       if (!rtpbin->max_ts_offset_is_set) {
2928         if (rtpbin->ntp_sync) {
2929           rtpbin->max_ts_offset = 0;
2930         } else {
2931           rtpbin->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
2932         }
2933       }
2934       break;
2935     case PROP_RTCP_SYNC:
2936       g_atomic_int_set (&rtpbin->rtcp_sync, g_value_get_enum (value));
2937       break;
2938     case PROP_RTCP_SYNC_INTERVAL:
2939       rtpbin->rtcp_sync_interval = g_value_get_uint (value);
2940       break;
2941     case PROP_IGNORE_PT:
2942       rtpbin->ignore_pt = g_value_get_boolean (value);
2943       break;
2944     case PROP_AUTOREMOVE:
2945       rtpbin->priv->autoremove = g_value_get_boolean (value);
2946       break;
2947     case PROP_USE_PIPELINE_CLOCK:
2948     {
2949       GSList *sessions;
2950       GST_RTP_BIN_LOCK (rtpbin);
2951       rtpbin->use_pipeline_clock = g_value_get_boolean (value);
2952       for (sessions = rtpbin->sessions; sessions;
2953           sessions = g_slist_next (sessions)) {
2954         GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
2955
2956         g_object_set (G_OBJECT (session->session),
2957             "use-pipeline-clock", rtpbin->use_pipeline_clock, NULL);
2958       }
2959       GST_RTP_BIN_UNLOCK (rtpbin);
2960     }
2961       break;
2962     case PROP_DO_SYNC_EVENT:
2963       rtpbin->send_sync_event = g_value_get_boolean (value);
2964       break;
2965     case PROP_BUFFER_MODE:
2966       GST_RTP_BIN_LOCK (rtpbin);
2967       rtpbin->buffer_mode = g_value_get_enum (value);
2968       GST_RTP_BIN_UNLOCK (rtpbin);
2969       /* propagate the property down to the jitterbuffer */
2970       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "mode", value);
2971       break;
2972     case PROP_DO_RETRANSMISSION:
2973       GST_RTP_BIN_LOCK (rtpbin);
2974       rtpbin->do_retransmission = g_value_get_boolean (value);
2975       GST_RTP_BIN_UNLOCK (rtpbin);
2976       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
2977           "do-retransmission", value);
2978       break;
2979     case PROP_RTP_PROFILE:
2980       rtpbin->rtp_profile = g_value_get_enum (value);
2981       break;
2982     case PROP_NTP_TIME_SOURCE:{
2983       GSList *sessions;
2984       GST_RTP_BIN_LOCK (rtpbin);
2985       rtpbin->ntp_time_source = g_value_get_enum (value);
2986       for (sessions = rtpbin->sessions; sessions;
2987           sessions = g_slist_next (sessions)) {
2988         GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
2989
2990         g_object_set (G_OBJECT (session->session),
2991             "ntp-time-source", rtpbin->ntp_time_source, NULL);
2992       }
2993       GST_RTP_BIN_UNLOCK (rtpbin);
2994       break;
2995     }
2996     case PROP_RTCP_SYNC_SEND_TIME:{
2997       GSList *sessions;
2998       GST_RTP_BIN_LOCK (rtpbin);
2999       rtpbin->rtcp_sync_send_time = g_value_get_boolean (value);
3000       for (sessions = rtpbin->sessions; sessions;
3001           sessions = g_slist_next (sessions)) {
3002         GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
3003
3004         g_object_set (G_OBJECT (session->session),
3005             "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time, NULL);
3006       }
3007       GST_RTP_BIN_UNLOCK (rtpbin);
3008       break;
3009     }
3010     case PROP_MAX_RTCP_RTP_TIME_DIFF:
3011       GST_RTP_BIN_LOCK (rtpbin);
3012       rtpbin->max_rtcp_rtp_time_diff = g_value_get_int (value);
3013       GST_RTP_BIN_UNLOCK (rtpbin);
3014       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
3015           "max-rtcp-rtp-time-diff", value);
3016       break;
3017     case PROP_MAX_DROPOUT_TIME:
3018       GST_RTP_BIN_LOCK (rtpbin);
3019       rtpbin->max_dropout_time = g_value_get_uint (value);
3020       GST_RTP_BIN_UNLOCK (rtpbin);
3021       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
3022           "max-dropout-time", value);
3023       gst_rtp_bin_propagate_property_to_session (rtpbin, "max-dropout-time",
3024           value);
3025       break;
3026     case PROP_MAX_MISORDER_TIME:
3027       GST_RTP_BIN_LOCK (rtpbin);
3028       rtpbin->max_misorder_time = g_value_get_uint (value);
3029       GST_RTP_BIN_UNLOCK (rtpbin);
3030       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
3031           "max-misorder-time", value);
3032       gst_rtp_bin_propagate_property_to_session (rtpbin, "max-misorder-time",
3033           value);
3034       break;
3035     case PROP_RFC7273_SYNC:
3036       rtpbin->rfc7273_sync = g_value_get_boolean (value);
3037       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
3038           "rfc7273-sync", value);
3039       break;
3040     case PROP_MAX_STREAMS:
3041       rtpbin->max_streams = g_value_get_uint (value);
3042       break;
3043     case PROP_MAX_TS_OFFSET_ADJUSTMENT:
3044       rtpbin->max_ts_offset_adjustment = g_value_get_uint64 (value);
3045       gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin,
3046           "max-ts-offset-adjustment", value);
3047       break;
3048     case PROP_MAX_TS_OFFSET:
3049       rtpbin->max_ts_offset = g_value_get_int64 (value);
3050       rtpbin->max_ts_offset_is_set = TRUE;
3051       break;
3052     default:
3053       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3054       break;
3055   }
3056 }
3057
3058 static void
3059 gst_rtp_bin_get_property (GObject * object, guint prop_id,
3060     GValue * value, GParamSpec * pspec)
3061 {
3062   GstRtpBin *rtpbin;
3063
3064   rtpbin = GST_RTP_BIN (object);
3065
3066   switch (prop_id) {
3067 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3068     case PROP_USE_RTSP_BUFFERING:
3069       GST_RTP_BIN_LOCK (rtpbin);
3070       g_value_set_boolean (value, rtpbin->use_rtsp_buffering);
3071       GST_RTP_BIN_UNLOCK (rtpbin);
3072       break;
3073 #endif
3074     case PROP_LATENCY:
3075       GST_RTP_BIN_LOCK (rtpbin);
3076       g_value_set_uint (value, rtpbin->latency_ms);
3077       GST_RTP_BIN_UNLOCK (rtpbin);
3078       break;
3079     case PROP_DROP_ON_LATENCY:
3080       GST_RTP_BIN_LOCK (rtpbin);
3081       g_value_set_boolean (value, rtpbin->drop_on_latency);
3082       GST_RTP_BIN_UNLOCK (rtpbin);
3083       break;
3084     case PROP_SDES:
3085       g_value_take_boxed (value, gst_rtp_bin_get_sdes_struct (rtpbin));
3086       break;
3087     case PROP_DO_LOST:
3088       GST_RTP_BIN_LOCK (rtpbin);
3089       g_value_set_boolean (value, rtpbin->do_lost);
3090       GST_RTP_BIN_UNLOCK (rtpbin);
3091       break;
3092     case PROP_IGNORE_PT:
3093       g_value_set_boolean (value, rtpbin->ignore_pt);
3094       break;
3095     case PROP_NTP_SYNC:
3096       g_value_set_boolean (value, rtpbin->ntp_sync);
3097       break;
3098     case PROP_RTCP_SYNC:
3099       g_value_set_enum (value, g_atomic_int_get (&rtpbin->rtcp_sync));
3100       break;
3101     case PROP_RTCP_SYNC_INTERVAL:
3102       g_value_set_uint (value, rtpbin->rtcp_sync_interval);
3103       break;
3104     case PROP_AUTOREMOVE:
3105       g_value_set_boolean (value, rtpbin->priv->autoremove);
3106       break;
3107     case PROP_BUFFER_MODE:
3108       g_value_set_enum (value, rtpbin->buffer_mode);
3109       break;
3110     case PROP_USE_PIPELINE_CLOCK:
3111       g_value_set_boolean (value, rtpbin->use_pipeline_clock);
3112       break;
3113     case PROP_DO_SYNC_EVENT:
3114       g_value_set_boolean (value, rtpbin->send_sync_event);
3115       break;
3116     case PROP_DO_RETRANSMISSION:
3117       GST_RTP_BIN_LOCK (rtpbin);
3118       g_value_set_boolean (value, rtpbin->do_retransmission);
3119       GST_RTP_BIN_UNLOCK (rtpbin);
3120       break;
3121     case PROP_RTP_PROFILE:
3122       g_value_set_enum (value, rtpbin->rtp_profile);
3123       break;
3124     case PROP_NTP_TIME_SOURCE:
3125       g_value_set_enum (value, rtpbin->ntp_time_source);
3126       break;
3127     case PROP_RTCP_SYNC_SEND_TIME:
3128       g_value_set_boolean (value, rtpbin->rtcp_sync_send_time);
3129       break;
3130     case PROP_MAX_RTCP_RTP_TIME_DIFF:
3131       GST_RTP_BIN_LOCK (rtpbin);
3132       g_value_set_int (value, rtpbin->max_rtcp_rtp_time_diff);
3133       GST_RTP_BIN_UNLOCK (rtpbin);
3134       break;
3135     case PROP_MAX_DROPOUT_TIME:
3136       g_value_set_uint (value, rtpbin->max_dropout_time);
3137       break;
3138     case PROP_MAX_MISORDER_TIME:
3139       g_value_set_uint (value, rtpbin->max_misorder_time);
3140       break;
3141     case PROP_RFC7273_SYNC:
3142       g_value_set_boolean (value, rtpbin->rfc7273_sync);
3143       break;
3144     case PROP_MAX_STREAMS:
3145       g_value_set_uint (value, rtpbin->max_streams);
3146       break;
3147     case PROP_MAX_TS_OFFSET_ADJUSTMENT:
3148       g_value_set_uint64 (value, rtpbin->max_ts_offset_adjustment);
3149       break;
3150     case PROP_MAX_TS_OFFSET:
3151       g_value_set_int64 (value, rtpbin->max_ts_offset);
3152       break;
3153     default:
3154       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3155       break;
3156   }
3157 }
3158
3159 static void
3160 gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
3161 {
3162   GstRtpBin *rtpbin;
3163
3164   rtpbin = GST_RTP_BIN (bin);
3165
3166   switch (GST_MESSAGE_TYPE (message)) {
3167     case GST_MESSAGE_ELEMENT:
3168     {
3169       const GstStructure *s = gst_message_get_structure (message);
3170
3171       /* we change the structure name and add the session ID to it */
3172       if (gst_structure_has_name (s, "application/x-rtp-source-sdes")) {
3173         GstRtpBinSession *sess;
3174
3175         /* find the session we set it as object data */
3176         sess = g_object_get_data (G_OBJECT (GST_MESSAGE_SRC (message)),
3177             "GstRTPBin.session");
3178
3179         if (G_LIKELY (sess)) {
3180           message = gst_message_make_writable (message);
3181           s = gst_message_get_structure (message);
3182           gst_structure_set ((GstStructure *) s, "session", G_TYPE_UINT,
3183               sess->id, NULL);
3184         }
3185       }
3186       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
3187       break;
3188     }
3189     case GST_MESSAGE_BUFFERING:
3190     {
3191       gint percent;
3192       gint min_percent = 100;
3193       GSList *sessions, *streams;
3194       GstRtpBinStream *stream;
3195 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3196       gboolean buffering_flag = FALSE, update_buffering_status = TRUE;
3197 #endif
3198       gboolean change = FALSE, active = FALSE;
3199       GstClockTime min_out_time;
3200       GstBufferingMode mode;
3201       gint avg_in, avg_out;
3202       gint64 buffering_left;
3203
3204       gst_message_parse_buffering (message, &percent);
3205       gst_message_parse_buffering_stats (message, &mode, &avg_in, &avg_out,
3206           &buffering_left);
3207
3208       stream =
3209           g_object_get_data (G_OBJECT (GST_MESSAGE_SRC (message)),
3210           "GstRTPBin.stream");
3211
3212       GST_DEBUG_OBJECT (bin, "got percent %d from stream %p", percent, stream);
3213
3214       /* get the stream */
3215       if (G_LIKELY (stream)) {
3216         GST_RTP_BIN_LOCK (rtpbin);
3217         /* fill in the percent */
3218         stream->percent = percent;
3219
3220         /* calculate the min value for all streams */
3221         for (sessions = rtpbin->sessions; sessions;
3222             sessions = g_slist_next (sessions)) {
3223           GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
3224
3225           GST_RTP_SESSION_LOCK (session);
3226           if (session->streams) {
3227             for (streams = session->streams; streams;
3228                 streams = g_slist_next (streams)) {
3229               GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
3230
3231 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3232               if (rtpbin->use_rtsp_buffering &&
3233                   rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) {
3234                 GstPad *temp_pad_src = NULL;
3235                 GstCaps *temp_caps_src = NULL;
3236                 GstStructure *caps_structure;
3237                 const gchar *caps_str_media = NULL;
3238                 temp_pad_src = gst_element_get_static_pad (stream->buffer, "src");
3239                 temp_caps_src = gst_pad_get_current_caps (temp_pad_src);
3240                 GST_DEBUG_OBJECT (bin,
3241                     "stream %p percent %d : temp_caps_src=%" GST_PTR_FORMAT,
3242                     stream, stream->percent, temp_caps_src);
3243                 if (temp_caps_src) {
3244                   caps_structure = gst_caps_get_structure (temp_caps_src, 0);
3245                   caps_str_media =
3246                       gst_structure_get_string (caps_structure, "media");
3247                   if (caps_str_media != NULL) {
3248                     if ((strcmp (caps_str_media, "video") != 0)
3249                         && (strcmp (caps_str_media, "audio") != 0)) {
3250                       GST_DEBUG_OBJECT (bin,
3251                           "Non Audio/Video Stream.. ignoring the same !!");
3252                       gst_caps_unref (temp_caps_src);
3253                       gst_object_unref (temp_pad_src);
3254                       continue;
3255                     } else if (stream->percent >= 100) {
3256                       /* Most of the time buffering icon displays in rtsp playback.
3257                          Optimizing the buffering updation code. Whenever any stream percentage
3258                          reaches 100 do not post buffering messages. */
3259                       if (stream->prev_percent < 100)
3260                         buffering_flag = TRUE;
3261                       else
3262                         update_buffering_status = FALSE;
3263                     }
3264                   }
3265                   gst_caps_unref (temp_caps_src);
3266                 }
3267                 gst_object_unref (temp_pad_src);
3268                 /* Updating prev stream percentage */
3269                 stream->prev_percent = stream->percent;
3270               } else {
3271                 GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream,
3272                     stream->percent);
3273               }
3274 #else
3275               GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream,
3276                   stream->percent);
3277
3278 #endif
3279               /* find min percent */
3280               if (min_percent > stream->percent)
3281                 min_percent = stream->percent;
3282             }
3283           } else {
3284             GST_INFO_OBJECT (bin,
3285                 "session has no streams, setting min_percent to 0");
3286             min_percent = 0;
3287           }
3288           GST_RTP_SESSION_UNLOCK (session);
3289         }
3290         GST_DEBUG_OBJECT (bin, "min percent %d", min_percent);
3291
3292 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3293         if (!(rtpbin->use_rtsp_buffering &&
3294             rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE)) {
3295 #endif
3296         if (rtpbin->buffering) {
3297           if (min_percent == 100) {
3298             rtpbin->buffering = FALSE;
3299             active = TRUE;
3300             change = TRUE;
3301           }
3302         } else {
3303           if (min_percent < 100) {
3304             /* pause the streams */
3305             rtpbin->buffering = TRUE;
3306             active = FALSE;
3307             change = TRUE;
3308           }
3309         }
3310 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3311         }
3312 #endif
3313         GST_RTP_BIN_UNLOCK (rtpbin);
3314
3315         gst_message_unref (message);
3316
3317 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3318           if (rtpbin->use_rtsp_buffering &&
3319               rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE) {
3320           if (update_buffering_status == FALSE)
3321             break;
3322           if (buffering_flag) {
3323             min_percent = 100;
3324             GST_DEBUG_OBJECT (bin, "forcefully change min_percent to 100!!!");
3325           }
3326         }
3327 #endif
3328         /* make a new buffering message with the min value */
3329         message =
3330             gst_message_new_buffering (GST_OBJECT_CAST (bin), min_percent);
3331         gst_message_set_buffering_stats (message, mode, avg_in, avg_out,
3332             buffering_left);
3333
3334 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3335         if (rtpbin->use_rtsp_buffering &&
3336             rtpbin->buffer_mode == RTP_JITTER_BUFFER_MODE_SLAVE)
3337           goto slave_buffering;
3338 #endif
3339         if (G_UNLIKELY (change)) {
3340           GstClock *clock;
3341           guint64 running_time = 0;
3342           guint64 offset = 0;
3343
3344           /* figure out the running time when we have a clock */
3345           if (G_LIKELY ((clock =
3346                       gst_element_get_clock (GST_ELEMENT_CAST (bin))))) {
3347             guint64 now, base_time;
3348
3349             now = gst_clock_get_time (clock);
3350             base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bin));
3351             running_time = now - base_time;
3352             gst_object_unref (clock);
3353           }
3354           GST_DEBUG_OBJECT (bin,
3355               "running time now %" GST_TIME_FORMAT,
3356               GST_TIME_ARGS (running_time));
3357
3358           GST_RTP_BIN_LOCK (rtpbin);
3359
3360           /* when we reactivate, calculate the offsets so that all streams have
3361            * an output time that is at least as big as the running_time */
3362           offset = 0;
3363           if (active) {
3364             if (running_time > rtpbin->buffer_start) {
3365               offset = running_time - rtpbin->buffer_start;
3366               if (offset >= rtpbin->latency_ns)
3367                 offset -= rtpbin->latency_ns;
3368               else
3369                 offset = 0;
3370             }
3371           }
3372
3373           /* pause all streams */
3374           min_out_time = -1;
3375           for (sessions = rtpbin->sessions; sessions;
3376               sessions = g_slist_next (sessions)) {
3377             GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
3378
3379             GST_RTP_SESSION_LOCK (session);
3380             for (streams = session->streams; streams;
3381                 streams = g_slist_next (streams)) {
3382               GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
3383               GstElement *element = stream->buffer;
3384               guint64 last_out = -1;
3385
3386               if (g_signal_lookup ("set-active", G_OBJECT_TYPE (element)) != 0) {
3387                 g_signal_emit_by_name (element, "set-active", active, offset,
3388                     &last_out);
3389               }
3390
3391               if (!active) {
3392                 g_object_get (element, "percent", &stream->percent, NULL);
3393
3394                 if (last_out == -1)
3395                   last_out = 0;
3396                 if (min_out_time == -1 || last_out < min_out_time)
3397                   min_out_time = last_out;
3398               }
3399
3400               GST_DEBUG_OBJECT (bin,
3401                   "setting %p to %d, offset %" GST_TIME_FORMAT ", last %"
3402                   GST_TIME_FORMAT ", percent %d", element, active,
3403                   GST_TIME_ARGS (offset), GST_TIME_ARGS (last_out),
3404                   stream->percent);
3405             }
3406             GST_RTP_SESSION_UNLOCK (session);
3407           }
3408           GST_DEBUG_OBJECT (bin,
3409               "min out time %" GST_TIME_FORMAT, GST_TIME_ARGS (min_out_time));
3410
3411           /* the buffer_start is the min out time of all paused jitterbuffers */
3412           if (!active)
3413             rtpbin->buffer_start = min_out_time;
3414
3415           GST_RTP_BIN_UNLOCK (rtpbin);
3416         }
3417       }
3418 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3419 slave_buffering:
3420 #endif
3421       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
3422       break;
3423     }
3424     default:
3425     {
3426       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
3427       break;
3428     }
3429   }
3430 }
3431
3432 static GstStateChangeReturn
3433 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
3434 {
3435   GstStateChangeReturn res;
3436   GstRtpBin *rtpbin;
3437   GstRtpBinPrivate *priv;
3438
3439   rtpbin = GST_RTP_BIN (element);
3440   priv = rtpbin->priv;
3441
3442   switch (transition) {
3443     case GST_STATE_CHANGE_NULL_TO_READY:
3444       break;
3445     case GST_STATE_CHANGE_READY_TO_PAUSED:
3446       priv->last_ntpnstime = 0;
3447       GST_LOG_OBJECT (rtpbin, "clearing shutdown flag");
3448       g_atomic_int_set (&priv->shutdown, 0);
3449       break;
3450     case GST_STATE_CHANGE_PAUSED_TO_READY:
3451       GST_LOG_OBJECT (rtpbin, "setting shutdown flag");
3452       g_atomic_int_set (&priv->shutdown, 1);
3453       /* wait for all callbacks to end by taking the lock. No new callbacks will
3454        * be able to happen as we set the shutdown flag. */
3455       GST_RTP_BIN_DYN_LOCK (rtpbin);
3456       GST_LOG_OBJECT (rtpbin, "dynamic lock taken, we can continue shutdown");
3457       GST_RTP_BIN_DYN_UNLOCK (rtpbin);
3458       break;
3459     default:
3460       break;
3461   }
3462
3463   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3464
3465   switch (transition) {
3466     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3467       break;
3468     case GST_STATE_CHANGE_PAUSED_TO_READY:
3469       break;
3470     case GST_STATE_CHANGE_READY_TO_NULL:
3471       break;
3472     default:
3473       break;
3474   }
3475   return res;
3476 }
3477
3478 static GstElement *
3479 session_request_element (GstRtpBinSession * session, guint signal)
3480 {
3481   GstElement *element = NULL;
3482   GstRtpBin *bin = session->bin;
3483
3484   g_signal_emit (bin, gst_rtp_bin_signals[signal], 0, session->id, &element);
3485
3486   if (element) {
3487     if (!bin_manage_element (bin, element))
3488       goto manage_failed;
3489     session->elements = g_slist_prepend (session->elements, element);
3490   }
3491   return element;
3492
3493   /* ERRORS */
3494 manage_failed:
3495   {
3496     GST_WARNING_OBJECT (bin, "unable to manage element");
3497     gst_object_unref (element);
3498     return NULL;
3499   }
3500 }
3501
3502 static gboolean
3503 copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
3504 {
3505   GstPad *gpad = GST_PAD_CAST (user_data);
3506
3507   GST_DEBUG_OBJECT (gpad, "store sticky event %" GST_PTR_FORMAT, *event);
3508   gst_pad_store_sticky_event (gpad, *event);
3509
3510   return TRUE;
3511 }
3512
3513 static void
3514 expose_recv_src_pad (GstRtpBin * rtpbin, GstPad * pad, GstRtpBinStream * stream,
3515     guint8 pt)
3516 {
3517   GstElementClass *klass;
3518   GstPadTemplate *templ;
3519   gchar *padname;
3520   GstPad *gpad;
3521
3522   gst_object_ref (pad);
3523
3524   if (stream->session->storage) {
3525     GstElement *fec_decoder =
3526         session_request_element (stream->session, SIGNAL_REQUEST_FEC_DECODER);
3527
3528     if (fec_decoder) {
3529       GstPad *sinkpad, *srcpad;
3530       GstPadLinkReturn ret;
3531
3532       sinkpad = gst_element_get_static_pad (fec_decoder, "sink");
3533
3534       if (!sinkpad)
3535         goto fec_decoder_sink_failed;
3536
3537       ret = gst_pad_link (pad, sinkpad);
3538       gst_object_unref (sinkpad);
3539
3540       if (ret != GST_PAD_LINK_OK)
3541         goto fec_decoder_link_failed;
3542
3543       srcpad = gst_element_get_static_pad (fec_decoder, "src");
3544
3545       if (!srcpad)
3546         goto fec_decoder_src_failed;
3547
3548       gst_pad_sticky_events_foreach (pad, copy_sticky_events, srcpad);
3549       gst_object_unref (pad);
3550       pad = srcpad;
3551     }
3552   }
3553
3554   GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
3555
3556   /* ghost the pad to the parent */
3557   klass = GST_ELEMENT_GET_CLASS (rtpbin);
3558   templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u");
3559   padname = g_strdup_printf ("recv_rtp_src_%u_%u_%u",
3560       stream->session->id, stream->ssrc, pt);
3561   gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
3562   g_free (padname);
3563   g_object_set_data (G_OBJECT (pad), "GstRTPBin.ghostpad", gpad);
3564
3565   gst_pad_set_active (gpad, TRUE);
3566   GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3567
3568   gst_pad_sticky_events_foreach (pad, copy_sticky_events, gpad);
3569   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
3570
3571 done:
3572   gst_object_unref (pad);
3573
3574   return;
3575
3576 shutdown:
3577   {
3578     GST_DEBUG ("ignoring, we are shutting down");
3579     goto done;
3580   }
3581 fec_decoder_sink_failed:
3582   {
3583     g_warning ("rtpbin: failed to get fec encoder sink pad for session %u",
3584         stream->session->id);
3585     goto done;
3586   }
3587 fec_decoder_src_failed:
3588   {
3589     g_warning ("rtpbin: failed to get fec encoder src pad for session %u",
3590         stream->session->id);
3591     goto done;
3592   }
3593 fec_decoder_link_failed:
3594   {
3595     g_warning ("rtpbin: failed to link fec decoder for session %u",
3596         stream->session->id);
3597     goto done;
3598   }
3599 }
3600
3601 /* a new pad (SSRC) was created in @session. This signal is emitted from the
3602  * payload demuxer. */
3603 static void
3604 new_payload_found (GstElement * element, guint pt, GstPad * pad,
3605     GstRtpBinStream * stream)
3606 {
3607   GstRtpBin *rtpbin;
3608
3609   rtpbin = stream->bin;
3610
3611   GST_DEBUG_OBJECT (rtpbin, "new payload pad %u", pt);
3612
3613   expose_recv_src_pad (rtpbin, pad, stream, pt);
3614 }
3615
3616 static void
3617 payload_pad_removed (GstElement * element, GstPad * pad,
3618     GstRtpBinStream * stream)
3619 {
3620   GstRtpBin *rtpbin;
3621   GstPad *gpad;
3622
3623   rtpbin = stream->bin;
3624
3625   GST_DEBUG ("payload pad removed");
3626
3627   GST_RTP_BIN_DYN_LOCK (rtpbin);
3628   if ((gpad = g_object_get_data (G_OBJECT (pad), "GstRTPBin.ghostpad"))) {
3629     g_object_set_data (G_OBJECT (pad), "GstRTPBin.ghostpad", NULL);
3630
3631     gst_pad_set_active (gpad, FALSE);
3632     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin), gpad);
3633   }
3634   GST_RTP_BIN_DYN_UNLOCK (rtpbin);
3635 }
3636
3637 static GstCaps *
3638 pt_map_requested (GstElement * element, guint pt, GstRtpBinSession * session)
3639 {
3640   GstRtpBin *rtpbin;
3641   GstCaps *caps;
3642
3643   rtpbin = session->bin;
3644
3645   GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %u in session %u", pt,
3646       session->id);
3647
3648   caps = get_pt_map (session, pt);
3649   if (!caps)
3650     goto no_caps;
3651
3652   return caps;
3653
3654   /* ERRORS */
3655 no_caps:
3656   {
3657     GST_DEBUG_OBJECT (rtpbin, "could not get caps");
3658     return NULL;
3659   }
3660 }
3661
3662 static GstCaps *
3663 ptdemux_pt_map_requested (GstElement * element, guint pt,
3664     GstRtpBinSession * session)
3665 {
3666   GstCaps *ret = pt_map_requested (element, pt, session);
3667
3668   if (ret && gst_caps_get_size (ret) == 1) {
3669     const GstStructure *s = gst_caps_get_structure (ret, 0);
3670     gboolean is_fec;
3671
3672     if (gst_structure_get_boolean (s, "is-fec", &is_fec) && is_fec) {
3673       GValue v = G_VALUE_INIT;
3674       GValue v2 = G_VALUE_INIT;
3675
3676       GST_INFO_OBJECT (session->bin, "Will ignore FEC pt %u in session %u", pt,
3677           session->id);
3678       g_value_init (&v, GST_TYPE_ARRAY);
3679       g_value_init (&v2, G_TYPE_INT);
3680       g_object_get_property (G_OBJECT (element), "ignored-payload-types", &v);
3681       g_value_set_int (&v2, pt);
3682       gst_value_array_append_value (&v, &v2);
3683       g_value_unset (&v2);
3684       g_object_set_property (G_OBJECT (element), "ignored-payload-types", &v);
3685       g_value_unset (&v);
3686     }
3687   }
3688
3689   return ret;
3690 }
3691
3692 static void
3693 payload_type_change (GstElement * element, guint pt, GstRtpBinSession * session)
3694 {
3695   GST_DEBUG_OBJECT (session->bin,
3696       "emitting signal for pt type changed to %u in session %u", pt,
3697       session->id);
3698
3699   g_signal_emit (session->bin, gst_rtp_bin_signals[SIGNAL_PAYLOAD_TYPE_CHANGE],
3700       0, session->id, pt);
3701 }
3702
3703 /* emitted when caps changed for the session */
3704 static void
3705 caps_changed (GstPad * pad, GParamSpec * pspec, GstRtpBinSession * session)
3706 {
3707   GstRtpBin *bin;
3708   GstCaps *caps;
3709   gint payload;
3710   const GstStructure *s;
3711
3712   bin = session->bin;
3713
3714   g_object_get (pad, "caps", &caps, NULL);
3715
3716   if (caps == NULL)
3717     return;
3718
3719   GST_DEBUG_OBJECT (bin, "got caps %" GST_PTR_FORMAT, caps);
3720
3721   s = gst_caps_get_structure (caps, 0);
3722
3723   /* get payload, finish when it's not there */
3724   if (!gst_structure_get_int (s, "payload", &payload)) {
3725     gst_caps_unref (caps);
3726     return;
3727   }
3728
3729   GST_RTP_SESSION_LOCK (session);
3730   GST_DEBUG_OBJECT (bin, "insert caps for payload %d", payload);
3731   g_hash_table_insert (session->ptmap, GINT_TO_POINTER (payload), caps);
3732   GST_RTP_SESSION_UNLOCK (session);
3733 }
3734
3735 /* a new pad (SSRC) was created in @session */
3736 static void
3737 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
3738     GstRtpBinSession * session)
3739 {
3740   GstRtpBin *rtpbin;
3741   GstRtpBinStream *stream;
3742   GstPad *sinkpad, *srcpad;
3743   gchar *padname;
3744
3745   rtpbin = session->bin;
3746
3747   GST_DEBUG_OBJECT (rtpbin, "new SSRC pad %08x, %s:%s", ssrc,
3748       GST_DEBUG_PAD_NAME (pad));
3749
3750   GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
3751
3752   GST_RTP_SESSION_LOCK (session);
3753
3754   /* create new stream */
3755   stream = create_stream (session, ssrc);
3756   if (!stream)
3757     goto no_stream;
3758
3759   /* get pad and link */
3760   GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTP");
3761   padname = g_strdup_printf ("src_%u", ssrc);
3762   srcpad = gst_element_get_static_pad (element, padname);
3763   g_free (padname);
3764   sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
3765   gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
3766   gst_object_unref (sinkpad);
3767   gst_object_unref (srcpad);
3768
3769   sinkpad = gst_element_get_request_pad (stream->buffer, "sink_rtcp");
3770   if (sinkpad) {
3771     GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTCP");
3772     padname = g_strdup_printf ("rtcp_src_%u", ssrc);
3773     srcpad = gst_element_get_static_pad (element, padname);
3774     g_free (padname);
3775     gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
3776     gst_object_unref (sinkpad);
3777     gst_object_unref (srcpad);
3778   }
3779
3780   if (g_signal_lookup ("handle-sync", G_OBJECT_TYPE (stream->buffer)) != 0) {
3781     /* connect to the RTCP sync signal from the jitterbuffer */
3782     GST_DEBUG_OBJECT (rtpbin, "connecting sync signal");
3783     stream->buffer_handlesync_sig = g_signal_connect (stream->buffer,
3784         "handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream);
3785   }
3786
3787   if (stream->demux) {
3788     /* connect to the new-pad signal of the payload demuxer, this will expose the
3789      * new pad by ghosting it. */
3790     stream->demux_newpad_sig = g_signal_connect (stream->demux,
3791         "new-payload-type", (GCallback) new_payload_found, stream);
3792     stream->demux_padremoved_sig = g_signal_connect (stream->demux,
3793         "pad-removed", (GCallback) payload_pad_removed, stream);
3794
3795     /* connect to the request-pt-map signal. This signal will be emitted by the
3796      * demuxer so that it can apply a proper caps on the buffers for the
3797      * depayloaders. */
3798     stream->demux_ptreq_sig = g_signal_connect (stream->demux,
3799         "request-pt-map", (GCallback) ptdemux_pt_map_requested, session);
3800     /* connect to the  signal so it can be forwarded. */
3801     stream->demux_ptchange_sig = g_signal_connect (stream->demux,
3802         "payload-type-change", (GCallback) payload_type_change, session);
3803
3804     GST_RTP_SESSION_UNLOCK (session);
3805     GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3806   } else {
3807     /* add rtpjitterbuffer src pad to pads */
3808     GstPad *pad;
3809
3810     pad = gst_element_get_static_pad (stream->buffer, "src");
3811
3812     GST_RTP_SESSION_UNLOCK (session);
3813     GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3814
3815     expose_recv_src_pad (rtpbin, pad, stream, 255);
3816
3817     gst_object_unref (pad);
3818   }
3819
3820   return;
3821
3822   /* ERRORS */
3823 shutdown:
3824   {
3825     GST_DEBUG_OBJECT (rtpbin, "we are shutting down");
3826     return;
3827   }
3828 no_stream:
3829   {
3830     GST_RTP_SESSION_UNLOCK (session);
3831     GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
3832     GST_DEBUG_OBJECT (rtpbin, "could not create stream");
3833     return;
3834   }
3835 }
3836
3837 static GstPad *
3838 complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session)
3839 {
3840   guint sessid = session->id;
3841   GstPad *recv_rtp_sink;
3842   GstElement *decoder;
3843
3844   g_assert (!session->recv_rtp_sink);
3845
3846   /* get recv_rtp pad and store */
3847   session->recv_rtp_sink =
3848       gst_element_get_request_pad (session->session, "recv_rtp_sink");
3849   if (session->recv_rtp_sink == NULL)
3850     goto pad_failed;
3851
3852   g_signal_connect (session->recv_rtp_sink, "notify::caps",
3853       (GCallback) caps_changed, session);
3854
3855   GST_DEBUG_OBJECT (rtpbin, "requesting RTP decoder");
3856   decoder = session_request_element (session, SIGNAL_REQUEST_RTP_DECODER);
3857   if (decoder) {
3858     GstPad *decsrc, *decsink;
3859     GstPadLinkReturn ret;
3860
3861     GST_DEBUG_OBJECT (rtpbin, "linking RTP decoder");
3862     decsink = gst_element_get_static_pad (decoder, "rtp_sink");
3863     if (decsink == NULL)
3864       goto dec_sink_failed;
3865
3866     recv_rtp_sink = decsink;
3867
3868     decsrc = gst_element_get_static_pad (decoder, "rtp_src");
3869     if (decsrc == NULL)
3870       goto dec_src_failed;
3871
3872     ret = gst_pad_link (decsrc, session->recv_rtp_sink);
3873
3874     gst_object_unref (decsrc);
3875
3876     if (ret != GST_PAD_LINK_OK)
3877       goto dec_link_failed;
3878
3879   } else {
3880     GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given");
3881     recv_rtp_sink = gst_object_ref (session->recv_rtp_sink);
3882   }
3883
3884   return recv_rtp_sink;
3885
3886   /* ERRORS */
3887 pad_failed:
3888   {
3889     g_warning ("rtpbin: failed to get session recv_rtp_sink pad");
3890     return NULL;
3891   }
3892 dec_sink_failed:
3893   {
3894     g_warning ("rtpbin: failed to get decoder sink pad for session %u", sessid);
3895     return NULL;
3896   }
3897 dec_src_failed:
3898   {
3899     g_warning ("rtpbin: failed to get decoder src pad for session %u", sessid);
3900     gst_object_unref (recv_rtp_sink);
3901     return NULL;
3902   }
3903 dec_link_failed:
3904   {
3905     g_warning ("rtpbin: failed to link rtp decoder for session %u", sessid);
3906     gst_object_unref (recv_rtp_sink);
3907     return NULL;
3908   }
3909 }
3910
3911 static void
3912 complete_session_receiver (GstRtpBin * rtpbin, GstRtpBinSession * session,
3913     guint sessid)
3914 {
3915   GstElement *aux;
3916   GstPad *recv_rtp_src;
3917
3918   g_assert (!session->recv_rtp_src);
3919
3920   session->recv_rtp_src =
3921       gst_element_get_static_pad (session->session, "recv_rtp_src");
3922   if (session->recv_rtp_src == NULL)
3923     goto pad_failed;
3924
3925   /* find out if we need AUX elements */
3926   aux = session_request_element (session, SIGNAL_REQUEST_AUX_RECEIVER);
3927   if (aux) {
3928     gchar *pname;
3929     GstPad *auxsink;
3930     GstPadLinkReturn ret;
3931
3932     GST_DEBUG_OBJECT (rtpbin, "linking AUX receiver");
3933
3934     pname = g_strdup_printf ("sink_%u", sessid);
3935     auxsink = gst_element_get_static_pad (aux, pname);
3936     g_free (pname);
3937     if (auxsink == NULL)
3938       goto aux_sink_failed;
3939
3940     ret = gst_pad_link (session->recv_rtp_src, auxsink);
3941     gst_object_unref (auxsink);
3942     if (ret != GST_PAD_LINK_OK)
3943       goto aux_link_failed;
3944
3945     /* this can be NULL when this AUX element is not to be linked any further */
3946     pname = g_strdup_printf ("src_%u", sessid);
3947     recv_rtp_src = gst_element_get_static_pad (aux, pname);
3948     g_free (pname);
3949   } else {
3950     recv_rtp_src = gst_object_ref (session->recv_rtp_src);
3951   }
3952
3953   /* Add a storage element if needed */
3954   if (recv_rtp_src && session->storage) {
3955     GstPadLinkReturn ret;
3956     GstPad *sinkpad = gst_element_get_static_pad (session->storage, "sink");
3957
3958     ret = gst_pad_link (recv_rtp_src, sinkpad);
3959
3960     gst_object_unref (sinkpad);
3961     gst_object_unref (recv_rtp_src);
3962
3963     if (ret != GST_PAD_LINK_OK)
3964       goto storage_link_failed;
3965
3966     recv_rtp_src = gst_element_get_static_pad (session->storage, "src");
3967   }
3968
3969   if (recv_rtp_src) {
3970     GstPad *sinkdpad;
3971
3972     GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
3973     sinkdpad = gst_element_get_static_pad (session->demux, "sink");
3974     GST_DEBUG_OBJECT (rtpbin, "linking demuxer RTP sink pad");
3975     gst_pad_link_full (recv_rtp_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING);
3976     gst_object_unref (sinkdpad);
3977     gst_object_unref (recv_rtp_src);
3978
3979     /* connect to the new-ssrc-pad signal of the SSRC demuxer */
3980     session->demux_newpad_sig = g_signal_connect (session->demux,
3981         "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
3982     session->demux_padremoved_sig = g_signal_connect (session->demux,
3983         "removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session);
3984   }
3985
3986   return;
3987
3988 pad_failed:
3989   {
3990     g_warning ("rtpbin: failed to get session recv_rtp_src pad");
3991     return;
3992   }
3993 aux_sink_failed:
3994   {
3995     g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
3996     return;
3997   }
3998 aux_link_failed:
3999   {
4000     g_warning ("rtpbin: failed to link AUX pad to session %u", sessid);
4001     return;
4002   }
4003 storage_link_failed:
4004   {
4005     g_warning ("rtpbin: failed to link storage");
4006     return;
4007   }
4008 }
4009
4010 /* Create a pad for receiving RTP for the session in @name. Must be called with
4011  * RTP_BIN_LOCK.
4012  */
4013 static GstPad *
4014 create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
4015 {
4016   guint sessid;
4017   GstRtpBinSession *session;
4018   GstPad *recv_rtp_sink;
4019
4020   /* first get the session number */
4021   if (name == NULL || sscanf (name, "recv_rtp_sink_%u", &sessid) != 1)
4022     goto no_name;
4023
4024   GST_DEBUG_OBJECT (rtpbin, "finding session %u", sessid);
4025
4026   /* get or create session */
4027   session = find_session_by_id (rtpbin, sessid);
4028   if (!session) {
4029     GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
4030     /* create session now */
4031     session = create_session (rtpbin, sessid);
4032     if (session == NULL)
4033       goto create_error;
4034   }
4035
4036   /* check if pad was requested */
4037   if (session->recv_rtp_sink_ghost != NULL)
4038     return session->recv_rtp_sink_ghost;
4039
4040   /* setup the session sink pad */
4041   recv_rtp_sink = complete_session_sink (rtpbin, session);
4042   if (!recv_rtp_sink)
4043     goto session_sink_failed;
4044
4045   GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
4046   session->recv_rtp_sink_ghost =
4047       gst_ghost_pad_new_from_template (name, recv_rtp_sink, templ);
4048   gst_object_unref (recv_rtp_sink);
4049   gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
4050   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
4051
4052   complete_session_receiver (rtpbin, session, sessid);
4053
4054   return session->recv_rtp_sink_ghost;
4055
4056   /* ERRORS */
4057 no_name:
4058   {
4059     g_warning ("rtpbin: cannot find session id for pad: %s",
4060         GST_STR_NULL (name));
4061     return NULL;
4062   }
4063 create_error:
4064   {
4065     /* create_session already warned */
4066     return NULL;
4067   }
4068 session_sink_failed:
4069   {
4070     /* warning already done */
4071     return NULL;
4072   }
4073 }
4074
4075 static void
4076 remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4077 {
4078   if (session->demux_newpad_sig) {
4079     g_signal_handler_disconnect (session->demux, session->demux_newpad_sig);
4080     session->demux_newpad_sig = 0;
4081   }
4082   if (session->demux_padremoved_sig) {
4083     g_signal_handler_disconnect (session->demux, session->demux_padremoved_sig);
4084     session->demux_padremoved_sig = 0;
4085   }
4086   if (session->recv_rtp_src) {
4087     gst_object_unref (session->recv_rtp_src);
4088     session->recv_rtp_src = NULL;
4089   }
4090   if (session->recv_rtp_sink) {
4091     gst_element_release_request_pad (session->session, session->recv_rtp_sink);
4092     gst_object_unref (session->recv_rtp_sink);
4093     session->recv_rtp_sink = NULL;
4094   }
4095   if (session->recv_rtp_sink_ghost) {
4096     gst_pad_set_active (session->recv_rtp_sink_ghost, FALSE);
4097     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4098         session->recv_rtp_sink_ghost);
4099     session->recv_rtp_sink_ghost = NULL;
4100   }
4101 }
4102
4103 static GstPad *
4104 complete_session_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session,
4105     guint sessid)
4106 {
4107   GstElement *decoder;
4108   GstPad *sinkdpad;
4109   GstPad *decsink = NULL;
4110
4111   /* get recv_rtp pad and store */
4112   GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
4113   session->recv_rtcp_sink =
4114       gst_element_get_request_pad (session->session, "recv_rtcp_sink");
4115   if (session->recv_rtcp_sink == NULL)
4116     goto pad_failed;
4117
4118   GST_DEBUG_OBJECT (rtpbin, "getting RTCP decoder");
4119   decoder = session_request_element (session, SIGNAL_REQUEST_RTCP_DECODER);
4120   if (decoder) {
4121     GstPad *decsrc;
4122     GstPadLinkReturn ret;
4123
4124     GST_DEBUG_OBJECT (rtpbin, "linking RTCP decoder");
4125     decsink = gst_element_get_static_pad (decoder, "rtcp_sink");
4126     decsrc = gst_element_get_static_pad (decoder, "rtcp_src");
4127
4128     if (decsink == NULL)
4129       goto dec_sink_failed;
4130
4131     if (decsrc == NULL)
4132       goto dec_src_failed;
4133
4134     ret = gst_pad_link (decsrc, session->recv_rtcp_sink);
4135
4136     gst_object_unref (decsrc);
4137
4138     if (ret != GST_PAD_LINK_OK)
4139       goto dec_link_failed;
4140   } else {
4141     GST_DEBUG_OBJECT (rtpbin, "no RTCP decoder given");
4142     decsink = gst_object_ref (session->recv_rtcp_sink);
4143   }
4144
4145   /* get srcpad, link to SSRCDemux */
4146   GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
4147   session->sync_src = gst_element_get_static_pad (session->session, "sync_src");
4148   if (session->sync_src == NULL)
4149     goto src_pad_failed;
4150
4151   GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTCP sink pad");
4152   sinkdpad = gst_element_get_static_pad (session->demux, "rtcp_sink");
4153   gst_pad_link_full (session->sync_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING);
4154   gst_object_unref (sinkdpad);
4155
4156   return decsink;
4157
4158 pad_failed:
4159   {
4160     g_warning ("rtpbin: failed to get session rtcp_sink pad");
4161     return NULL;
4162   }
4163 dec_sink_failed:
4164   {
4165     g_warning ("rtpbin: failed to get decoder sink pad for session %u", sessid);
4166     return NULL;
4167   }
4168 dec_src_failed:
4169   {
4170     g_warning ("rtpbin: failed to get decoder src pad for session %u", sessid);
4171     goto cleanup;
4172   }
4173 dec_link_failed:
4174   {
4175     g_warning ("rtpbin: failed to link rtcp decoder for session %u", sessid);
4176     goto cleanup;
4177   }
4178 src_pad_failed:
4179   {
4180     g_warning ("rtpbin: failed to get session sync_src pad");
4181   }
4182
4183 cleanup:
4184   gst_object_unref (decsink);
4185   return NULL;
4186 }
4187
4188 /* Create a pad for receiving RTCP for the session in @name. Must be called with
4189  * RTP_BIN_LOCK.
4190  */
4191 static GstPad *
4192 create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
4193     const gchar * name)
4194 {
4195   guint sessid;
4196   GstRtpBinSession *session;
4197   GstPad *decsink = NULL;
4198
4199   /* first get the session number */
4200   if (name == NULL || sscanf (name, "recv_rtcp_sink_%u", &sessid) != 1)
4201     goto no_name;
4202
4203   GST_DEBUG_OBJECT (rtpbin, "finding session %u", sessid);
4204
4205   /* get or create the session */
4206   session = find_session_by_id (rtpbin, sessid);
4207   if (!session) {
4208     GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
4209     /* create session now */
4210     session = create_session (rtpbin, sessid);
4211     if (session == NULL)
4212       goto create_error;
4213   }
4214
4215   /* check if pad was requested */
4216   if (session->recv_rtcp_sink_ghost != NULL)
4217     return session->recv_rtcp_sink_ghost;
4218
4219   decsink = complete_session_rtcp (rtpbin, session, sessid);
4220   if (!decsink)
4221     goto create_error;
4222
4223   session->recv_rtcp_sink_ghost =
4224       gst_ghost_pad_new_from_template (name, decsink, templ);
4225   gst_object_unref (decsink);
4226   gst_pad_set_active (session->recv_rtcp_sink_ghost, TRUE);
4227   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin),
4228       session->recv_rtcp_sink_ghost);
4229
4230   return session->recv_rtcp_sink_ghost;
4231
4232   /* ERRORS */
4233 no_name:
4234   {
4235     g_warning ("rtpbin: cannot find session id for pad: %s",
4236         GST_STR_NULL (name));
4237     return NULL;
4238   }
4239 create_error:
4240   {
4241     /* create_session already warned */
4242     return NULL;
4243   }
4244 }
4245
4246 static void
4247 remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4248 {
4249   if (session->recv_rtcp_sink_ghost) {
4250     gst_pad_set_active (session->recv_rtcp_sink_ghost, FALSE);
4251     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4252         session->recv_rtcp_sink_ghost);
4253     session->recv_rtcp_sink_ghost = NULL;
4254   }
4255   if (session->sync_src) {
4256     /* releasing the request pad should also unref the sync pad */
4257     gst_object_unref (session->sync_src);
4258     session->sync_src = NULL;
4259   }
4260   if (session->recv_rtcp_sink) {
4261     gst_element_release_request_pad (session->session, session->recv_rtcp_sink);
4262     gst_object_unref (session->recv_rtcp_sink);
4263     session->recv_rtcp_sink = NULL;
4264   }
4265 }
4266
4267 static gboolean
4268 complete_session_src (GstRtpBin * rtpbin, GstRtpBinSession * session)
4269 {
4270   gchar *gname;
4271   guint sessid = session->id;
4272   GstPad *send_rtp_src;
4273   GstElement *encoder;
4274   GstElementClass *klass;
4275   GstPadTemplate *templ;
4276   gboolean ret = FALSE;
4277
4278   /* get srcpad */
4279   send_rtp_src = gst_element_get_static_pad (session->session, "send_rtp_src");
4280
4281   if (send_rtp_src == NULL)
4282     goto no_srcpad;
4283
4284   GST_DEBUG_OBJECT (rtpbin, "getting RTP encoder");
4285   encoder = session_request_element (session, SIGNAL_REQUEST_RTP_ENCODER);
4286   if (encoder) {
4287     gchar *ename;
4288     GstPad *encsrc, *encsink;
4289     GstPadLinkReturn ret;
4290
4291     GST_DEBUG_OBJECT (rtpbin, "linking RTP encoder");
4292     ename = g_strdup_printf ("rtp_src_%u", sessid);
4293     encsrc = gst_element_get_static_pad (encoder, ename);
4294     g_free (ename);
4295
4296     if (encsrc == NULL)
4297       goto enc_src_failed;
4298
4299     ename = g_strdup_printf ("rtp_sink_%u", sessid);
4300     encsink = gst_element_get_static_pad (encoder, ename);
4301     g_free (ename);
4302     if (encsink == NULL)
4303       goto enc_sink_failed;
4304
4305     ret = gst_pad_link (send_rtp_src, encsink);
4306     gst_object_unref (encsink);
4307     gst_object_unref (send_rtp_src);
4308
4309     send_rtp_src = encsrc;
4310
4311     if (ret != GST_PAD_LINK_OK)
4312       goto enc_link_failed;
4313   } else {
4314     GST_DEBUG_OBJECT (rtpbin, "no RTP encoder given");
4315   }
4316
4317   /* ghost the new source pad */
4318   klass = GST_ELEMENT_GET_CLASS (rtpbin);
4319   gname = g_strdup_printf ("send_rtp_src_%u", sessid);
4320   templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%u");
4321   session->send_rtp_src_ghost =
4322       gst_ghost_pad_new_from_template (gname, send_rtp_src, templ);
4323   gst_pad_set_active (session->send_rtp_src_ghost, TRUE);
4324   gst_pad_sticky_events_foreach (send_rtp_src, copy_sticky_events,
4325       session->send_rtp_src_ghost);
4326   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost);
4327   g_free (gname);
4328
4329   ret = TRUE;
4330
4331 done:
4332   if (send_rtp_src)
4333     gst_object_unref (send_rtp_src);
4334
4335   return ret;
4336
4337   /* ERRORS */
4338 no_srcpad:
4339   {
4340     g_warning ("rtpbin: failed to get rtp source pad for session %u", sessid);
4341     goto done;
4342   }
4343 enc_src_failed:
4344   {
4345     g_warning ("rtpbin: failed to get %" GST_PTR_FORMAT
4346         " src pad for session %u", encoder, sessid);
4347     goto done;
4348   }
4349 enc_sink_failed:
4350   {
4351     g_warning ("rtpbin: failed to get %" GST_PTR_FORMAT
4352         " sink pad for session %u", encoder, sessid);
4353     goto done;
4354   }
4355 enc_link_failed:
4356   {
4357     g_warning ("rtpbin: failed to link %" GST_PTR_FORMAT " for session %u",
4358         encoder, sessid);
4359     goto done;
4360   }
4361 }
4362
4363 static gboolean
4364 setup_aux_sender_fold (const GValue * item, GValue * result, gpointer user_data)
4365 {
4366   GstPad *pad;
4367   gchar *name;
4368   guint sessid;
4369   GstRtpBinSession *session = user_data, *newsess;
4370   GstRtpBin *rtpbin = session->bin;
4371   GstPadLinkReturn ret;
4372
4373   pad = g_value_get_object (item);
4374   name = gst_pad_get_name (pad);
4375
4376   if (name == NULL || sscanf (name, "src_%u", &sessid) != 1)
4377     goto no_name;
4378
4379   g_free (name);
4380
4381   newsess = find_session_by_id (rtpbin, sessid);
4382   if (newsess == NULL) {
4383     /* create new session */
4384     newsess = create_session (rtpbin, sessid);
4385     if (newsess == NULL)
4386       goto create_error;
4387   } else if (newsess->send_rtp_sink != NULL)
4388     goto existing_session;
4389
4390   /* get send_rtp pad and store */
4391   newsess->send_rtp_sink =
4392       gst_element_get_request_pad (newsess->session, "send_rtp_sink");
4393   if (newsess->send_rtp_sink == NULL)
4394     goto pad_failed;
4395
4396   ret = gst_pad_link (pad, newsess->send_rtp_sink);
4397   if (ret != GST_PAD_LINK_OK)
4398     goto aux_link_failed;
4399
4400   if (!complete_session_src (rtpbin, newsess))
4401     goto session_src_failed;
4402
4403   return TRUE;
4404
4405   /* ERRORS */
4406 no_name:
4407   {
4408     GST_WARNING ("ignoring invalid pad name %s", GST_STR_NULL (name));
4409     g_free (name);
4410     return TRUE;
4411   }
4412 create_error:
4413   {
4414     /* create_session already warned */
4415     return FALSE;
4416   }
4417 existing_session:
4418   {
4419     GST_DEBUG_OBJECT (rtpbin,
4420         "skipping src_%i setup, since it is already configured.", sessid);
4421     return TRUE;
4422   }
4423 pad_failed:
4424   {
4425     g_warning ("rtpbin: failed to get session pad for session %u", sessid);
4426     return FALSE;
4427   }
4428 aux_link_failed:
4429   {
4430     g_warning ("rtpbin: failed to link AUX for session %u", sessid);
4431     return FALSE;
4432   }
4433 session_src_failed:
4434   {
4435     g_warning ("rtpbin: failed to complete AUX for session %u", sessid);
4436     return FALSE;
4437   }
4438 }
4439
4440 static gboolean
4441 setup_aux_sender (GstRtpBin * rtpbin, GstRtpBinSession * session,
4442     GstElement * aux)
4443 {
4444   GstIterator *it;
4445   GValue result = { 0, };
4446   GstIteratorResult res;
4447
4448   it = gst_element_iterate_src_pads (aux);
4449   res = gst_iterator_fold (it, setup_aux_sender_fold, &result, session);
4450   gst_iterator_free (it);
4451
4452   return res == GST_ITERATOR_DONE;
4453 }
4454
4455 /* Create a pad for sending RTP for the session in @name. Must be called with
4456  * RTP_BIN_LOCK.
4457  */
4458 static GstPad *
4459 create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
4460 {
4461   gchar *pname;
4462   guint sessid;
4463   GstPad *send_rtp_sink;
4464   GstElement *aux;
4465   GstElement *encoder;
4466   GstElement *prev = NULL;
4467   GstRtpBinSession *session;
4468
4469   /* first get the session number */
4470   if (name == NULL || sscanf (name, "send_rtp_sink_%u", &sessid) != 1)
4471     goto no_name;
4472
4473   /* get or create session */
4474   session = find_session_by_id (rtpbin, sessid);
4475   if (!session) {
4476     /* create session now */
4477     session = create_session (rtpbin, sessid);
4478     if (session == NULL)
4479       goto create_error;
4480   }
4481
4482   /* check if pad was requested */
4483   if (session->send_rtp_sink_ghost != NULL)
4484     return session->send_rtp_sink_ghost;
4485
4486   /* check if we are already using this session as a sender */
4487   if (session->send_rtp_sink != NULL)
4488     goto existing_session;
4489
4490   encoder = session_request_element (session, SIGNAL_REQUEST_FEC_ENCODER);
4491
4492   if (encoder) {
4493     GST_DEBUG_OBJECT (rtpbin, "Linking FEC encoder");
4494
4495     send_rtp_sink = gst_element_get_static_pad (encoder, "sink");
4496
4497     if (!send_rtp_sink)
4498       goto enc_sink_failed;
4499
4500     prev = encoder;
4501   }
4502
4503   GST_DEBUG_OBJECT (rtpbin, "getting RTP AUX sender");
4504   aux = session_request_element (session, SIGNAL_REQUEST_AUX_SENDER);
4505   if (aux) {
4506     GstPad *sinkpad;
4507     GST_DEBUG_OBJECT (rtpbin, "linking AUX sender");
4508     if (!setup_aux_sender (rtpbin, session, aux))
4509       goto aux_session_failed;
4510
4511     pname = g_strdup_printf ("sink_%u", sessid);
4512     sinkpad = gst_element_get_static_pad (aux, pname);
4513     g_free (pname);
4514
4515     if (sinkpad == NULL)
4516       goto aux_sink_failed;
4517
4518     if (!prev) {
4519       send_rtp_sink = sinkpad;
4520     } else {
4521       GstPad *srcpad = gst_element_get_static_pad (prev, "src");
4522       GstPadLinkReturn ret;
4523
4524       ret = gst_pad_link (srcpad, sinkpad);
4525       gst_object_unref (srcpad);
4526       if (ret != GST_PAD_LINK_OK) {
4527         goto aux_link_failed;
4528       }
4529     }
4530     prev = aux;
4531   } else {
4532     /* get send_rtp pad and store */
4533     session->send_rtp_sink =
4534         gst_element_get_request_pad (session->session, "send_rtp_sink");
4535     if (session->send_rtp_sink == NULL)
4536       goto pad_failed;
4537
4538     if (!complete_session_src (rtpbin, session))
4539       goto session_src_failed;
4540
4541     if (!prev) {
4542       send_rtp_sink = gst_object_ref (session->send_rtp_sink);
4543     } else {
4544       GstPad *srcpad = gst_element_get_static_pad (prev, "src");
4545       GstPadLinkReturn ret;
4546
4547       ret = gst_pad_link (srcpad, session->send_rtp_sink);
4548       gst_object_unref (srcpad);
4549       if (ret != GST_PAD_LINK_OK)
4550         goto session_link_failed;
4551     }
4552   }
4553
4554   session->send_rtp_sink_ghost =
4555       gst_ghost_pad_new_from_template (name, send_rtp_sink, templ);
4556   gst_object_unref (send_rtp_sink);
4557   gst_pad_set_active (session->send_rtp_sink_ghost, TRUE);
4558   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_ghost);
4559
4560   return session->send_rtp_sink_ghost;
4561
4562   /* ERRORS */
4563 no_name:
4564   {
4565     g_warning ("rtpbin: cannot find session id for pad: %s",
4566         GST_STR_NULL (name));
4567     return NULL;
4568   }
4569 create_error:
4570   {
4571     /* create_session already warned */
4572     return NULL;
4573   }
4574 existing_session:
4575   {
4576     g_warning ("rtpbin: session %u is already in use", sessid);
4577     return NULL;
4578   }
4579 aux_session_failed:
4580   {
4581     g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
4582     return NULL;
4583   }
4584 aux_sink_failed:
4585   {
4586     g_warning ("rtpbin: failed to get AUX sink pad for session %u", sessid);
4587     return NULL;
4588   }
4589 aux_link_failed:
4590   {
4591     g_warning ("rtpbin: failed to link %" GST_PTR_FORMAT " for session %u",
4592         aux, sessid);
4593     return NULL;
4594   }
4595 pad_failed:
4596   {
4597     g_warning ("rtpbin: failed to get session pad for session %u", sessid);
4598     return NULL;
4599   }
4600 session_src_failed:
4601   {
4602     g_warning ("rtpbin: failed to setup source pads for session %u", sessid);
4603     return NULL;
4604   }
4605 session_link_failed:
4606   {
4607     g_warning ("rtpbin: failed to link %" GST_PTR_FORMAT " for session %u",
4608         session, sessid);
4609     return NULL;
4610   }
4611 enc_sink_failed:
4612   {
4613     g_warning ("rtpbin: failed to get %" GST_PTR_FORMAT
4614         " sink pad for session %u", encoder, sessid);
4615     return NULL;
4616   }
4617 }
4618
4619 static void
4620 remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4621 {
4622   if (session->send_rtp_src_ghost) {
4623     gst_pad_set_active (session->send_rtp_src_ghost, FALSE);
4624     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4625         session->send_rtp_src_ghost);
4626     session->send_rtp_src_ghost = NULL;
4627   }
4628   if (session->send_rtp_sink) {
4629     gst_element_release_request_pad (GST_ELEMENT_CAST (session->session),
4630         session->send_rtp_sink);
4631     gst_object_unref (session->send_rtp_sink);
4632     session->send_rtp_sink = NULL;
4633   }
4634   if (session->send_rtp_sink_ghost) {
4635     gst_pad_set_active (session->send_rtp_sink_ghost, FALSE);
4636     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4637         session->send_rtp_sink_ghost);
4638     session->send_rtp_sink_ghost = NULL;
4639   }
4640 }
4641
4642 /* Create a pad for sending RTCP for the session in @name. Must be called with
4643  * RTP_BIN_LOCK.
4644  */
4645 static GstPad *
4646 create_send_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
4647     const gchar * name)
4648 {
4649   guint sessid;
4650   GstPad *encsrc;
4651   GstElement *encoder;
4652   GstRtpBinSession *session;
4653
4654   /* first get the session number */
4655   if (name == NULL || sscanf (name, "send_rtcp_src_%u", &sessid) != 1)
4656     goto no_name;
4657
4658   /* get or create session */
4659   session = find_session_by_id (rtpbin, sessid);
4660   if (!session) {
4661     GST_DEBUG_OBJECT (rtpbin, "creating session %u", sessid);
4662     /* create session now */
4663     session = create_session (rtpbin, sessid);
4664     if (session == NULL)
4665       goto create_error;
4666   }
4667
4668   /* check if pad was requested */
4669   if (session->send_rtcp_src_ghost != NULL)
4670     return session->send_rtcp_src_ghost;
4671
4672   /* get rtcp_src pad and store */
4673   session->send_rtcp_src =
4674       gst_element_get_request_pad (session->session, "send_rtcp_src");
4675   if (session->send_rtcp_src == NULL)
4676     goto pad_failed;
4677
4678   GST_DEBUG_OBJECT (rtpbin, "getting RTCP encoder");
4679   encoder = session_request_element (session, SIGNAL_REQUEST_RTCP_ENCODER);
4680   if (encoder) {
4681     gchar *ename;
4682     GstPad *encsink;
4683     GstPadLinkReturn ret;
4684
4685     GST_DEBUG_OBJECT (rtpbin, "linking RTCP encoder");
4686
4687     ename = g_strdup_printf ("rtcp_src_%u", sessid);
4688     encsrc = gst_element_get_static_pad (encoder, ename);
4689     g_free (ename);
4690     if (encsrc == NULL)
4691       goto enc_src_failed;
4692
4693     ename = g_strdup_printf ("rtcp_sink_%u", sessid);
4694     encsink = gst_element_get_static_pad (encoder, ename);
4695     g_free (ename);
4696     if (encsink == NULL)
4697       goto enc_sink_failed;
4698
4699     ret = gst_pad_link (session->send_rtcp_src, encsink);
4700     gst_object_unref (encsink);
4701
4702     if (ret != GST_PAD_LINK_OK)
4703       goto enc_link_failed;
4704   } else {
4705     GST_DEBUG_OBJECT (rtpbin, "no RTCP encoder given");
4706     encsrc = gst_object_ref (session->send_rtcp_src);
4707   }
4708
4709   session->send_rtcp_src_ghost =
4710       gst_ghost_pad_new_from_template (name, encsrc, templ);
4711   gst_object_unref (encsrc);
4712   gst_pad_set_active (session->send_rtcp_src_ghost, TRUE);
4713   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtcp_src_ghost);
4714
4715   return session->send_rtcp_src_ghost;
4716
4717   /* ERRORS */
4718 no_name:
4719   {
4720     g_warning ("rtpbin: cannot find session id for pad: %s",
4721         GST_STR_NULL (name));
4722     return NULL;
4723   }
4724 create_error:
4725   {
4726     /* create_session already warned */
4727     return NULL;
4728   }
4729 pad_failed:
4730   {
4731     g_warning ("rtpbin: failed to get rtcp pad for session %u", sessid);
4732     return NULL;
4733   }
4734 enc_src_failed:
4735   {
4736     g_warning ("rtpbin: failed to get encoder src pad for session %u", sessid);
4737     return NULL;
4738   }
4739 enc_sink_failed:
4740   {
4741     g_warning ("rtpbin: failed to get encoder sink pad for session %u", sessid);
4742     gst_object_unref (encsrc);
4743     return NULL;
4744   }
4745 enc_link_failed:
4746   {
4747     g_warning ("rtpbin: failed to link rtcp encoder for session %u", sessid);
4748     gst_object_unref (encsrc);
4749     return NULL;
4750   }
4751 }
4752
4753 static void
4754 remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
4755 {
4756   if (session->send_rtcp_src_ghost) {
4757     gst_pad_set_active (session->send_rtcp_src_ghost, FALSE);
4758     gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
4759         session->send_rtcp_src_ghost);
4760     session->send_rtcp_src_ghost = NULL;
4761   }
4762   if (session->send_rtcp_src) {
4763     gst_element_release_request_pad (session->session, session->send_rtcp_src);
4764     gst_object_unref (session->send_rtcp_src);
4765     session->send_rtcp_src = NULL;
4766   }
4767 }
4768
4769 /* If the requested name is NULL we should create a name with
4770  * the session number assuming we want the lowest possible session
4771  * with a free pad like the template */
4772 static gchar *
4773 gst_rtp_bin_get_free_pad_name (GstElement * element, GstPadTemplate * templ)
4774 {
4775   gboolean name_found = FALSE;
4776   gint session = 0;
4777   GstIterator *pad_it = NULL;
4778   gchar *pad_name = NULL;
4779   GValue data = { 0, };
4780
4781   GST_DEBUG_OBJECT (element, "find a free pad name for template");
4782   while (!name_found) {
4783     gboolean done = FALSE;
4784
4785     g_free (pad_name);
4786     pad_name = g_strdup_printf (templ->name_template, session++);
4787     pad_it = gst_element_iterate_pads (GST_ELEMENT (element));
4788     name_found = TRUE;
4789     while (!done) {
4790       switch (gst_iterator_next (pad_it, &data)) {
4791         case GST_ITERATOR_OK:
4792         {
4793           GstPad *pad;
4794           gchar *name;
4795
4796           pad = g_value_get_object (&data);
4797           name = gst_pad_get_name (pad);
4798
4799           if (strcmp (name, pad_name) == 0) {
4800             done = TRUE;
4801             name_found = FALSE;
4802           }
4803           g_free (name);
4804           g_value_reset (&data);
4805           break;
4806         }
4807         case GST_ITERATOR_ERROR:
4808         case GST_ITERATOR_RESYNC:
4809           /* restart iteration */
4810           done = TRUE;
4811           name_found = FALSE;
4812           session = 0;
4813           break;
4814         case GST_ITERATOR_DONE:
4815           done = TRUE;
4816           break;
4817       }
4818     }
4819     g_value_unset (&data);
4820     gst_iterator_free (pad_it);
4821   }
4822
4823   GST_DEBUG_OBJECT (element, "free pad name found: '%s'", pad_name);
4824   return pad_name;
4825 }
4826
4827 /*
4828  */
4829 static GstPad *
4830 gst_rtp_bin_request_new_pad (GstElement * element,
4831     GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
4832 {
4833   GstRtpBin *rtpbin;
4834   GstElementClass *klass;
4835   GstPad *result;
4836
4837   gchar *pad_name = NULL;
4838
4839   g_return_val_if_fail (templ != NULL, NULL);
4840   g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
4841
4842   rtpbin = GST_RTP_BIN (element);
4843   klass = GST_ELEMENT_GET_CLASS (element);
4844
4845   GST_RTP_BIN_LOCK (rtpbin);
4846
4847   if (name == NULL) {
4848     /* use a free pad name */
4849     pad_name = gst_rtp_bin_get_free_pad_name (element, templ);
4850   } else {
4851     /* use the provided name */
4852     pad_name = g_strdup (name);
4853   }
4854
4855   GST_DEBUG_OBJECT (rtpbin, "Trying to request a pad with name %s", pad_name);
4856
4857   /* figure out the template */
4858   if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%u")) {
4859     result = create_recv_rtp (rtpbin, templ, pad_name);
4860   } else if (templ == gst_element_class_get_pad_template (klass,
4861           "recv_rtcp_sink_%u")) {
4862     result = create_recv_rtcp (rtpbin, templ, pad_name);
4863   } else if (templ == gst_element_class_get_pad_template (klass,
4864           "send_rtp_sink_%u")) {
4865     result = create_send_rtp (rtpbin, templ, pad_name);
4866   } else if (templ == gst_element_class_get_pad_template (klass,
4867           "send_rtcp_src_%u")) {
4868     result = create_send_rtcp (rtpbin, templ, pad_name);
4869   } else
4870     goto wrong_template;
4871
4872   g_free (pad_name);
4873   GST_RTP_BIN_UNLOCK (rtpbin);
4874
4875   return result;
4876
4877   /* ERRORS */
4878 wrong_template:
4879   {
4880     g_free (pad_name);
4881     GST_RTP_BIN_UNLOCK (rtpbin);
4882     g_warning ("rtpbin: this is not our template");
4883     return NULL;
4884   }
4885 }
4886
4887 static void
4888 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)
4889 {
4890   GstRtpBinSession *session;
4891   GstRtpBin *rtpbin;
4892
4893   g_return_if_fail (GST_IS_GHOST_PAD (pad));
4894   g_return_if_fail (GST_IS_RTP_BIN (element));
4895
4896   rtpbin = GST_RTP_BIN (element);
4897
4898   GST_RTP_BIN_LOCK (rtpbin);
4899   GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s",
4900       GST_DEBUG_PAD_NAME (pad));
4901
4902   if (!(session = find_session_by_pad (rtpbin, pad)))
4903     goto unknown_pad;
4904
4905   if (session->recv_rtp_sink_ghost == pad) {
4906     remove_recv_rtp (rtpbin, session);
4907   } else if (session->recv_rtcp_sink_ghost == pad) {
4908     remove_recv_rtcp (rtpbin, session);
4909   } else if (session->send_rtp_sink_ghost == pad) {
4910     remove_send_rtp (rtpbin, session);
4911   } else if (session->send_rtcp_src_ghost == pad) {
4912     remove_rtcp (rtpbin, session);
4913   }
4914
4915   /* no more request pads, free the complete session */
4916   if (session->recv_rtp_sink_ghost == NULL
4917       && session->recv_rtcp_sink_ghost == NULL
4918       && session->send_rtp_sink_ghost == NULL
4919       && session->send_rtcp_src_ghost == NULL) {
4920     GST_DEBUG_OBJECT (rtpbin, "no more pads for session %p", session);
4921     rtpbin->sessions = g_slist_remove (rtpbin->sessions, session);
4922     free_session (session, rtpbin);
4923   }
4924   GST_RTP_BIN_UNLOCK (rtpbin);
4925
4926   return;
4927
4928   /* ERROR */
4929 unknown_pad:
4930   {
4931     GST_RTP_BIN_UNLOCK (rtpbin);
4932     g_warning ("rtpbin: %s:%s is not one of our request pads",
4933         GST_DEBUG_PAD_NAME (pad));
4934     return;
4935   }
4936 }