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