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