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