gst/rtpmanager/gstrtpbin.c: Add some more advanced example pipelines.
[platform/upstream/gstreamer.git] / gst / rtpmanager / gstrtpbin.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim@fluendo.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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-gstrtpbin
22  * @short_description: handle media from one RTP bin
23  * @see_also: gstrtpjitterbuffer, gstrtpsession, gstrtpptdemux, gstrtpssrcdemux
24  *
25  * <refsect2>
26  * <para>
27  * RTP bin combines the functions of gstrtpsession, gstrtpssrcdemux, gstrtpjitterbuffer
28  * and gstrtpptdemux in one element. It allows for multiple RTP sessions that will
29  * be synchronized together using RTCP SR packets.
30  * </para>
31  * <para>
32  * gstrtpbin is configured with a number of request pads that define the
33  * functionality that is activated, similar to the gstrtpsession element.
34  * </para>
35  * <para>
36  * To use gstrtpbin as an RTP receiver, request a recv_rtp_sink_%%d pad. The session
37  * number must be specified in the pad name. 
38  * Data received on the recv_rtp_sink_%%d pad will be processed in the gstrtpsession
39  * manager and after being validated forwarded on gstrtpssrcdemuxer element. Each
40  * RTP stream is demuxed based on the SSRC and send to a gstrtpjitterbuffer. After
41  * the packets are released from the jitterbuffer, they will be forwarded to a
42  * gstrtpptdemuxer element. The gstrtpptdemuxer element will demux the packets based
43  * on the payload type and will create a unique pad recv_rtp_src_%%d_%%d_%%d on
44  * gstrtpbin with the session number, SSRC and payload type respectively as the pad
45  * name.
46  * </para>
47  * <para>
48  * To also use gstrtpbin as an RTCP receiver, request a recv_rtcp_sink_%%d pad. The
49  * session number must be specified in the pad name.
50  * </para>
51  * <para>
52  * If you want the session manager to generate and send RTCP packets, request
53  * the send_rtcp_src_%%d pad with the session number in the pad name. Packet pushed
54  * on this pad contain SR/RR RTCP reports that should be sent to all participants
55  * in the session.
56  * </para>
57  * <para>
58  * To use gstrtpbin as a sender, request a send_rtp_sink_%%d pad, which will
59  * automatically create a send_rtp_src_%%d pad. The session number must be specified when
60  * requesting the sink pad. The session manager will modify the
61  * SSRC in the RTP packets to its own SSRC and wil forward the packets on the
62  * send_rtp_src_%%d pad after updating its internal state.
63  * </para>
64  * <para>
65  * The session manager needs the clock-rate of the payload types it is handling
66  * and will signal the GstRtpSession::request-pt-map signal when it needs such a
67  * mapping. One can clear the cached values with the GstRtpSession::clear-pt-map
68  * signal.
69  * </para>
70  * <title>Example pipelines</title>
71  * <para>
72  * <programlisting>
73  * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \
74  *     gstrtpbin ! rtptheoradepay ! theoradec ! xvimagesink
75  * </programlisting>
76  * Receive RTP data from port 5000 and send to the session 0 in gstrtpbin.
77  * </para>
78  * <para>
79  * <programlisting>
80  * gst-launch gstrtpbin name=rtpbin \
81  *         v4l2src ! ffmpegcolorspace ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
82  *                   rtpbin.send_rtp_src_0 ! udpsink port=5000             \
83  *                   rtpbin.send_rtcp_src_0 ! udpsink port=5001 sync=false \
84  *                   udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0            \
85  *         audiotestsrc ! amrnbenc ! rtpamrpay ! rtpbin.send_rtp_sink_1    \
86  *                   rtpbin.send_rtp_src_1 ! udpsink port=5002             \
87  *                   rtpbin.send_rtcp_src_1 ! udpsink port=5003 sync=false \
88  *                   udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1
89  * </programlisting>
90  * Encode and payload H263 video captured from a v4l2src. Encode and payload AMR
91  * audio generated from audiotestsrc. The video is sent to session 0 in rtpbin
92  * and the audio is sent to session 1. Video packets are sent on UDP port 5000
93  * and audio packets on port 5002. The video RTCP packets for session 0 are sent
94  * on port 5001 and the audio RTCP packets for session 0 are sent on port 5003.
95  * RTCP packets for session 0 are received on port 5005 and RTCP for session 1
96  * is received on port 5007. Since RTCP packets from the sender should be sent
97  * as soon as possible, sync=false is configured on udpsink.
98  * </para>
99  * <para>
100  * <programlisting>
101  *  gst-launch -v gstrtpbin name=rtpbin                                                \
102  *     udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263-1998" \
103  *             port=5000 ! rtpbin.recv_rtp_sink_0                            \
104  *         rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink                \
105  *      udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                            \
106  *      rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false             \
107  *     udpsrc caps="application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1"                                             \
108  *             port=5002 ! rtpbin.recv_rtp_sink_1                            \
109  *         rtpbin. ! rtpamrdepay ! amrnbdec ! alsasink                       \
110  *      udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                            \
111  *      rtpbin.send_rtcp_src_1 ! udpsink port=5007 sync=false
112  * </programlisting>
113  * Receive H263 on port 5000, send it through rtpbin in session 0, depayload,
114  * decode and display the video.
115  * Receive AMR on port 5002, send it through rtpbin in session 1, depayload,
116  * decode and play the audio.
117  * Receive server RTCP packets for session 0 on port 5001 and RTCP packets for
118  * session 1 on port 5003. These packets will be used for session management and
119  * synchronisation.
120  * Send RTCP reports for session 0 on port 5005 and RTCP reports for session 1
121  * on port 5007.
122  * </para>
123  * </refsect2>
124  *
125  * Last reviewed on 2007-08-28 (0.10.6)
126  */
127
128 #ifdef HAVE_CONFIG_H
129 #include "config.h"
130 #endif
131 #include <string.h>
132
133 #include "gstrtpbin-marshal.h"
134 #include "gstrtpbin.h"
135
136 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
137 #define GST_CAT_DEFAULT gst_rtp_bin_debug
138
139
140 /* elementfactory information */
141 static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin",
142     "Filter/Network/RTP",
143     "Implement an RTP bin",
144     "Wim Taymans <wim@fluendo.com>");
145
146 /* sink pads */
147 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
148 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%d",
149     GST_PAD_SINK,
150     GST_PAD_REQUEST,
151     GST_STATIC_CAPS ("application/x-rtp")
152     );
153
154 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
155 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%d",
156     GST_PAD_SINK,
157     GST_PAD_REQUEST,
158     GST_STATIC_CAPS ("application/x-rtcp")
159     );
160
161 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
162 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%d",
163     GST_PAD_SINK,
164     GST_PAD_REQUEST,
165     GST_STATIC_CAPS ("application/x-rtp")
166     );
167
168 /* src pads */
169 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
170 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
171     GST_PAD_SRC,
172     GST_PAD_SOMETIMES,
173     GST_STATIC_CAPS ("application/x-rtp")
174     );
175
176 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
177 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
178     GST_PAD_SRC,
179     GST_PAD_REQUEST,
180     GST_STATIC_CAPS ("application/x-rtcp")
181     );
182
183 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
184 GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%d",
185     GST_PAD_SRC,
186     GST_PAD_SOMETIMES,
187     GST_STATIC_CAPS ("application/x-rtp")
188     );
189
190 #define GST_RTP_BIN_GET_PRIVATE(obj)  \
191    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRtpBinPrivate))
192
193 #define GST_RTP_BIN_LOCK(bin)   g_mutex_lock ((bin)->priv->bin_lock)
194 #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock ((bin)->priv->bin_lock)
195
196 struct _GstRtpBinPrivate
197 {
198   GMutex *bin_lock;
199 };
200
201 /* signals and args */
202 enum
203 {
204   SIGNAL_REQUEST_PT_MAP,
205   SIGNAL_CLEAR_PT_MAP,
206
207   SIGNAL_ON_NEW_SSRC,
208   SIGNAL_ON_SSRC_COLLISION,
209   SIGNAL_ON_SSRC_VALIDATED,
210   SIGNAL_ON_BYE_SSRC,
211   SIGNAL_ON_BYE_TIMEOUT,
212   SIGNAL_ON_TIMEOUT,
213   LAST_SIGNAL
214 };
215
216 #define DEFAULT_LATENCY_MS      200
217
218 enum
219 {
220   PROP_0,
221   PROP_LATENCY
222 };
223
224 /* helper objects */
225 typedef struct _GstRtpBinSession GstRtpBinSession;
226 typedef struct _GstRtpBinStream GstRtpBinStream;
227 typedef struct _GstRtpBinClient GstRtpBinClient;
228
229 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
230
231 static GstCaps *pt_map_requested (GstElement * element, guint pt,
232     GstRtpBinSession * session);
233
234 /* Manages the RTP stream for one SSRC.
235  *
236  * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
237  * If we see an SDES RTCP packet that links multiple SSRCs together based on a
238  * common CNAME, we create a GstRtpBinClient structure to group the SSRCs
239  * together (see below).
240  */
241 struct _GstRtpBinStream
242 {
243   /* the SSRC of this stream */
244   guint32 ssrc;
245   /* parent bin */
246   GstRtpBin *bin;
247   /* the session this SSRC belongs to */
248   GstRtpBinSession *session;
249   /* the jitterbuffer of the SSRC */
250   GstElement *buffer;
251   /* the PT demuxer of the SSRC */
252   GstElement *demux;
253   gulong demux_newpad_sig;
254   gulong demux_ptreq_sig;
255 };
256
257 #define GST_RTP_SESSION_LOCK(sess)   g_mutex_lock ((sess)->lock)
258 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->lock)
259
260 /* Manages the receiving end of the packets.
261  *
262  * There is one such structure for each RTP session (audio/video/...).
263  * We get the RTP/RTCP packets and stuff them into the session manager. From
264  * there they are pushed into an SSRC demuxer that splits the stream based on
265  * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
266  * the GstRtpBinStream above).
267  */
268 struct _GstRtpBinSession
269 {
270   /* session id */
271   gint id;
272   /* the parent bin */
273   GstRtpBin *bin;
274   /* the session element */
275   GstElement *session;
276   /* the SSRC demuxer */
277   GstElement *demux;
278   gulong demux_newpad_sig;
279
280   GMutex *lock;
281
282   /* list of GstRtpBinStream */
283   GSList *streams;
284
285   /* mapping of payload type to caps */
286   GHashTable *ptmap;
287
288   /* the pads of the session */
289   GstPad *recv_rtp_sink;
290   GstPad *recv_rtp_src;
291   GstPad *recv_rtcp_sink;
292   GstPad *recv_rtcp_src;
293   GstPad *send_rtp_sink;
294   GstPad *send_rtp_src;
295   GstPad *send_rtcp_src;
296 };
297
298 /* find a session with the given id. Must be called with RTP_BIN_LOCK */
299 static GstRtpBinSession *
300 find_session_by_id (GstRtpBin * rtpbin, gint id)
301 {
302   GSList *walk;
303
304   for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
305     GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
306
307     if (sess->id == id)
308       return sess;
309   }
310   return NULL;
311 }
312
313 static void
314 on_new_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
315 {
316   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC], 0,
317       sess->id, ssrc);
318 }
319
320 static void
321 on_ssrc_collision (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
322 {
323   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION], 0,
324       sess->id, ssrc);
325 }
326
327 static void
328 on_ssrc_validated (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
329 {
330   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED], 0,
331       sess->id, ssrc);
332 }
333
334 static void
335 on_bye_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
336 {
337   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC], 0,
338       sess->id, ssrc);
339 }
340
341 static void
342 on_bye_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
343 {
344   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT], 0,
345       sess->id, ssrc);
346 }
347
348 static void
349 on_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
350 {
351   g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT], 0,
352       sess->id, ssrc);
353 }
354
355 /* create a session with the given id.  Must be called with RTP_BIN_LOCK */
356 static GstRtpBinSession *
357 create_session (GstRtpBin * rtpbin, gint id)
358 {
359   GstRtpBinSession *sess;
360   GstElement *session, *demux;
361
362   if (!(session = gst_element_factory_make ("gstrtpsession", NULL)))
363     goto no_session;
364
365   if (!(demux = gst_element_factory_make ("gstrtpssrcdemux", NULL)))
366     goto no_demux;
367
368   sess = g_new0 (GstRtpBinSession, 1);
369   sess->lock = g_mutex_new ();
370   sess->id = id;
371   sess->bin = rtpbin;
372   sess->session = session;
373   sess->demux = demux;
374   sess->ptmap = g_hash_table_new (NULL, NULL);
375   rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
376
377   /* provide clock_rate to the session manager when needed */
378   g_signal_connect (session, "request-pt-map",
379       (GCallback) pt_map_requested, sess);
380
381   g_signal_connect (sess->session, "on-new-ssrc",
382       (GCallback) on_new_ssrc, sess);
383   g_signal_connect (sess->session, "on-ssrc-collision",
384       (GCallback) on_ssrc_collision, sess);
385   g_signal_connect (sess->session, "on-ssrc-validated",
386       (GCallback) on_ssrc_validated, sess);
387   g_signal_connect (sess->session, "on-bye-ssrc",
388       (GCallback) on_bye_ssrc, sess);
389   g_signal_connect (sess->session, "on-bye-timeout",
390       (GCallback) on_bye_timeout, sess);
391   g_signal_connect (sess->session, "on-timeout", (GCallback) on_timeout, sess);
392
393   gst_bin_add (GST_BIN_CAST (rtpbin), session);
394   gst_element_set_state (session, GST_STATE_PLAYING);
395   gst_bin_add (GST_BIN_CAST (rtpbin), demux);
396   gst_element_set_state (demux, GST_STATE_PLAYING);
397
398   return sess;
399
400   /* ERRORS */
401 no_session:
402   {
403     g_warning ("gstrtpbin: could not create gstrtpsession element");
404     return NULL;
405   }
406 no_demux:
407   {
408     gst_object_unref (session);
409     g_warning ("gstrtpbin: could not create gstrtpssrcdemux element");
410     return NULL;
411   }
412 }
413
414 #if 0
415 static GstRtpBinStream *
416 find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc)
417 {
418   GSList *walk;
419
420   for (walk = session->streams; walk; walk = g_slist_next (walk)) {
421     GstRtpBinStream *stream = (GstRtpBinStream *) walk->data;
422
423     if (stream->ssrc == ssrc)
424       return stream;
425   }
426   return NULL;
427 }
428 #endif
429
430 /* get the payload type caps for the specific payload @pt in @session */
431 static GstCaps *
432 get_pt_map (GstRtpBinSession * session, guint pt)
433 {
434   GstCaps *caps = NULL;
435   GstRtpBin *bin;
436   GValue ret = { 0 };
437   GValue args[3] = { {0}, {0}, {0} };
438
439   GST_DEBUG ("searching pt %d in cache", pt);
440
441   GST_RTP_SESSION_LOCK (session);
442
443   /* first look in the cache */
444   caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
445   if (caps)
446     goto done;
447
448   bin = session->bin;
449
450   GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
451
452   /* not in cache, send signal to request caps */
453   g_value_init (&args[0], GST_TYPE_ELEMENT);
454   g_value_set_object (&args[0], bin);
455   g_value_init (&args[1], G_TYPE_UINT);
456   g_value_set_uint (&args[1], session->id);
457   g_value_init (&args[2], G_TYPE_UINT);
458   g_value_set_uint (&args[2], pt);
459
460   g_value_init (&ret, GST_TYPE_CAPS);
461   g_value_set_boxed (&ret, NULL);
462
463   g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
464
465   caps = (GstCaps *) g_value_get_boxed (&ret);
466   if (!caps)
467     goto no_caps;
468
469   GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
470
471   /* store in cache */
472   g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
473
474 done:
475   GST_RTP_SESSION_UNLOCK (session);
476
477   return caps;
478
479   /* ERRORS */
480 no_caps:
481   {
482     GST_RTP_SESSION_UNLOCK (session);
483     GST_DEBUG ("no pt map could be obtained");
484     return NULL;
485   }
486 }
487
488 static gboolean
489 return_true (gpointer key, gpointer value, gpointer user_data)
490 {
491   return TRUE;
492 }
493
494 static void
495 gst_rtp_bin_clear_pt_map (GstRtpBin * bin)
496 {
497   GSList *walk;
498
499   GST_RTP_BIN_LOCK (bin);
500   GST_DEBUG_OBJECT (bin, "clearing pt map");
501   for (walk = bin->sessions; walk; walk = g_slist_next (walk)) {
502     GstRtpBinSession *session = (GstRtpBinSession *) walk->data;
503
504     GST_RTP_SESSION_LOCK (session);
505 #if 0
506     /* This requires GLib 2.12 */
507     g_hash_table_remove_all (session->ptmap);
508 #else
509     g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
510 #endif
511     GST_RTP_SESSION_UNLOCK (session);
512   }
513   GST_RTP_BIN_UNLOCK (bin);
514 }
515
516 /* create a new stream with @ssrc in @session. Must be called with
517  * RTP_SESSION_LOCK. */
518 static GstRtpBinStream *
519 create_stream (GstRtpBinSession * session, guint32 ssrc)
520 {
521   GstElement *buffer, *demux;
522   GstRtpBinStream *stream;
523
524   if (!(buffer = gst_element_factory_make ("gstrtpjitterbuffer", NULL)))
525     goto no_jitterbuffer;
526
527   if (!(demux = gst_element_factory_make ("gstrtpptdemux", NULL)))
528     goto no_demux;
529
530   stream = g_new0 (GstRtpBinStream, 1);
531   stream->ssrc = ssrc;
532   stream->bin = session->bin;
533   stream->session = session;
534   stream->buffer = buffer;
535   stream->demux = demux;
536   session->streams = g_slist_prepend (session->streams, stream);
537
538   /* provide clock_rate to the jitterbuffer when needed */
539   g_signal_connect (buffer, "request-pt-map",
540       (GCallback) pt_map_requested, session);
541
542   /* configure latency */
543   g_object_set (buffer, "latency", session->bin->latency, NULL);
544
545   gst_bin_add (GST_BIN_CAST (session->bin), buffer);
546   gst_element_set_state (buffer, GST_STATE_PLAYING);
547   gst_bin_add (GST_BIN_CAST (session->bin), demux);
548   gst_element_set_state (demux, GST_STATE_PLAYING);
549
550   /* link stuff */
551   gst_element_link (buffer, demux);
552
553   return stream;
554
555   /* ERRORS */
556 no_jitterbuffer:
557   {
558     g_warning ("gstrtpbin: could not create gstrtpjitterbuffer element");
559     return NULL;
560   }
561 no_demux:
562   {
563     gst_object_unref (buffer);
564     g_warning ("gstrtpbin: could not create gstrtpptdemux element");
565     return NULL;
566   }
567 }
568
569 /* Manages the RTP streams that come from one client and should therefore be
570  * synchronized.
571  */
572 struct _GstRtpBinClient
573 {
574   /* the common CNAME for the streams */
575   gchar *cname;
576   /* the streams */
577   GSList *streams;
578 };
579
580 /* GObject vmethods */
581 static void gst_rtp_bin_finalize (GObject * object);
582 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
583     const GValue * value, GParamSpec * pspec);
584 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
585     GValue * value, GParamSpec * pspec);
586
587 /* GstElement vmethods */
588 static GstClock *gst_rtp_bin_provide_clock (GstElement * element);
589 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
590     GstStateChange transition);
591 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
592     GstPadTemplate * templ, const gchar * name);
593 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
594 static void gst_rtp_bin_clear_pt_map (GstRtpBin * bin);
595
596 GST_BOILERPLATE (GstRtpBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
597
598 static void
599 gst_rtp_bin_base_init (gpointer klass)
600 {
601   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
602
603   /* sink pads */
604   gst_element_class_add_pad_template (element_class,
605       gst_static_pad_template_get (&rtpbin_recv_rtp_sink_template));
606   gst_element_class_add_pad_template (element_class,
607       gst_static_pad_template_get (&rtpbin_recv_rtcp_sink_template));
608   gst_element_class_add_pad_template (element_class,
609       gst_static_pad_template_get (&rtpbin_send_rtp_sink_template));
610
611   /* src pads */
612   gst_element_class_add_pad_template (element_class,
613       gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
614   gst_element_class_add_pad_template (element_class,
615       gst_static_pad_template_get (&rtpbin_send_rtcp_src_template));
616   gst_element_class_add_pad_template (element_class,
617       gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
618
619   gst_element_class_set_details (element_class, &rtpbin_details);
620 }
621
622 static void
623 gst_rtp_bin_class_init (GstRtpBinClass * klass)
624 {
625   GObjectClass *gobject_class;
626   GstElementClass *gstelement_class;
627
628   gobject_class = (GObjectClass *) klass;
629   gstelement_class = (GstElementClass *) klass;
630
631   g_type_class_add_private (klass, sizeof (GstRtpBinPrivate));
632
633   gobject_class->finalize = gst_rtp_bin_finalize;
634   gobject_class->set_property = gst_rtp_bin_set_property;
635   gobject_class->get_property = gst_rtp_bin_get_property;
636
637   g_object_class_install_property (gobject_class, PROP_LATENCY,
638       g_param_spec_uint ("latency", "Buffer latency in ms",
639           "Default amount of ms to buffer in the jitterbuffers", 0,
640           G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE));
641
642   /**
643    * GstRtpBin::request-pt-map:
644    * @rtpbin: the object which received the signal
645    * @session: the session
646    * @pt: the pt
647    *
648    * Request the payload type as #GstCaps for @pt in @session.
649    */
650   gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
651       g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
652       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_pt_map),
653       NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2,
654       G_TYPE_UINT, G_TYPE_UINT);
655   /**
656    * GstRtpBin::clear-pt-map:
657    * @rtpbin: the object which received the signal
658    *
659    * Clear all previously cached pt-mapping obtained with
660    * GstRtpBin::request-pt-map.
661    */
662   gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] =
663       g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
664       G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, clear_pt_map),
665       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
666
667   /**
668    * GstRtpBin::on-new-ssrc:
669    * @rtpbin: the object which received the signal
670    * @session: the session
671    * @ssrc: the SSRC 
672    *
673    * Notify of a new SSRC that entered @session.
674    */
675   gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC] =
676       g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass),
677       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_ssrc),
678       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
679       G_TYPE_UINT, G_TYPE_UINT);
680   /**
681    * GstRtpBin::on-ssrc_collision:
682    * @rtpbin: the object which received the signal
683    * @session: the session
684    * @ssrc: the SSRC 
685    *
686    * Notify when we have an SSRC collision
687    */
688   gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION] =
689       g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass),
690       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_collision),
691       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
692       G_TYPE_UINT, G_TYPE_UINT);
693   /**
694    * GstRtpBin::on-ssrc_validated:
695    * @rtpbin: the object which received the signal
696    * @session: the session
697    * @ssrc: the SSRC 
698    *
699    * Notify of a new SSRC that became validated.
700    */
701   gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED] =
702       g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass),
703       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_validated),
704       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
705       G_TYPE_UINT, G_TYPE_UINT);
706
707   /**
708    * GstRtpBin::on-bye-ssrc:
709    * @rtpbin: the object which received the signal
710    * @session: the session
711    * @ssrc: the SSRC 
712    *
713    * Notify of an SSRC that became inactive because of a BYE packet.
714    */
715   gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC] =
716       g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass),
717       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_ssrc),
718       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
719       G_TYPE_UINT, G_TYPE_UINT);
720   /**
721    * GstRtpBin::on-bye-timeout:
722    * @rtpbin: the object which received the signal
723    * @session: the session
724    * @ssrc: the SSRC 
725    *
726    * Notify of an SSRC that has timed out because of BYE
727    */
728   gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT] =
729       g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass),
730       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_timeout),
731       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
732       G_TYPE_UINT, G_TYPE_UINT);
733   /**
734    * GstRtpBin::on-timeout:
735    * @rtpbin: the object which received the signal
736    * @session: the session
737    * @ssrc: the SSRC 
738    *
739    * Notify of an SSRC that has timed out
740    */
741   gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT] =
742       g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass),
743       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_timeout),
744       NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
745       G_TYPE_UINT, G_TYPE_UINT);
746
747   gstelement_class->provide_clock =
748       GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
749   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
750   gstelement_class->request_new_pad =
751       GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
752   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
753
754   klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
755
756   GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
757 }
758
759 static void
760 gst_rtp_bin_init (GstRtpBin * rtpbin, GstRtpBinClass * klass)
761 {
762   rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
763   rtpbin->priv->bin_lock = g_mutex_new ();
764   rtpbin->provided_clock = gst_system_clock_obtain ();
765 }
766
767 static void
768 gst_rtp_bin_finalize (GObject * object)
769 {
770   GstRtpBin *rtpbin;
771
772   rtpbin = GST_RTP_BIN (object);
773
774   g_mutex_free (rtpbin->priv->bin_lock);
775
776   G_OBJECT_CLASS (parent_class)->finalize (object);
777 }
778
779 static void
780 gst_rtp_bin_set_property (GObject * object, guint prop_id,
781     const GValue * value, GParamSpec * pspec)
782 {
783   GstRtpBin *rtpbin;
784
785   rtpbin = GST_RTP_BIN (object);
786
787   switch (prop_id) {
788     case PROP_LATENCY:
789       rtpbin->latency = g_value_get_uint (value);
790       break;
791     default:
792       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
793       break;
794   }
795 }
796
797 static void
798 gst_rtp_bin_get_property (GObject * object, guint prop_id,
799     GValue * value, GParamSpec * pspec)
800 {
801   GstRtpBin *rtpbin;
802
803   rtpbin = GST_RTP_BIN (object);
804
805   switch (prop_id) {
806     case PROP_LATENCY:
807       g_value_set_uint (value, rtpbin->latency);
808       break;
809     default:
810       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
811       break;
812   }
813 }
814
815 static GstClock *
816 gst_rtp_bin_provide_clock (GstElement * element)
817 {
818   GstRtpBin *rtpbin;
819
820   rtpbin = GST_RTP_BIN (element);
821
822   return GST_CLOCK_CAST (gst_object_ref (rtpbin->provided_clock));
823 }
824
825 static GstStateChangeReturn
826 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
827 {
828   GstStateChangeReturn res;
829   GstRtpBin *rtpbin;
830
831   rtpbin = GST_RTP_BIN (element);
832
833   switch (transition) {
834     case GST_STATE_CHANGE_NULL_TO_READY:
835       break;
836     case GST_STATE_CHANGE_READY_TO_PAUSED:
837       break;
838     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
839       break;
840     default:
841       break;
842   }
843
844   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
845
846   switch (transition) {
847     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
848       break;
849     case GST_STATE_CHANGE_PAUSED_TO_READY:
850       break;
851     case GST_STATE_CHANGE_READY_TO_NULL:
852       break;
853     default:
854       break;
855   }
856   return res;
857 }
858
859 /* a new pad (SSRC) was created in @session */
860 static void
861 new_payload_found (GstElement * element, guint pt, GstPad * pad,
862     GstRtpBinStream * stream)
863 {
864   GstRtpBin *rtpbin;
865   GstElementClass *klass;
866   GstPadTemplate *templ;
867   gchar *padname;
868   GstPad *gpad;
869
870   rtpbin = stream->bin;
871
872   GST_DEBUG ("new payload pad %d", pt);
873
874   /* ghost the pad to the parent */
875   klass = GST_ELEMENT_GET_CLASS (rtpbin);
876   templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
877   padname = g_strdup_printf ("recv_rtp_src_%d_%u_%d",
878       stream->session->id, stream->ssrc, pt);
879   gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
880   g_free (padname);
881
882   gst_pad_set_active (gpad, TRUE);
883   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
884 }
885
886 static GstCaps *
887 pt_map_requested (GstElement * element, guint pt, GstRtpBinSession * session)
888 {
889   GstRtpBin *rtpbin;
890   GstCaps *caps;
891
892   rtpbin = session->bin;
893
894   GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
895       session->id);
896
897   caps = get_pt_map (session, pt);
898   if (!caps)
899     goto no_caps;
900
901   return caps;
902
903   /* ERRORS */
904 no_caps:
905   {
906     GST_DEBUG_OBJECT (rtpbin, "could not get caps");
907     return NULL;
908   }
909 }
910
911 /* a new pad (SSRC) was created in @session */
912 static void
913 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
914     GstRtpBinSession * session)
915 {
916   GstRtpBinStream *stream;
917   GstPad *sinkpad;
918
919   GST_DEBUG_OBJECT (session->bin, "new SSRC pad %08x", ssrc);
920
921   GST_RTP_SESSION_LOCK (session);
922
923   /* create new stream */
924   stream = create_stream (session, ssrc);
925   if (!stream)
926     goto no_stream;
927
928   /* get pad and link */
929   GST_DEBUG_OBJECT (session->bin, "linking jitterbuffer");
930   sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
931   gst_pad_link (pad, sinkpad);
932   gst_object_unref (sinkpad);
933
934   /* connect to the new-pad signal of the payload demuxer, this will expose the
935    * new pad by ghosting it. */
936   stream->demux_newpad_sig = g_signal_connect (stream->demux,
937       "new-payload-type", (GCallback) new_payload_found, stream);
938   /* connect to the request-pt-map signal. This signal will be emited by the
939    * demuxer so that it can apply a proper caps on the buffers for the
940    * depayloaders. */
941   stream->demux_ptreq_sig = g_signal_connect (stream->demux,
942       "request-pt-map", (GCallback) pt_map_requested, session);
943
944   GST_RTP_SESSION_UNLOCK (session);
945
946   return;
947
948   /* ERRORS */
949 no_stream:
950   {
951     GST_RTP_SESSION_UNLOCK (session);
952     GST_DEBUG ("could not create stream");
953     return;
954   }
955 }
956
957 /* Create a pad for receiving RTP for the session in @name. Must be called with
958  * RTP_BIN_LOCK.
959  */
960 static GstPad *
961 create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
962 {
963   GstPad *result, *sinkdpad;
964   guint sessid;
965   GstRtpBinSession *session;
966   GstPadLinkReturn lres;
967
968   /* first get the session number */
969   if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
970     goto no_name;
971
972   GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
973
974   /* get or create session */
975   session = find_session_by_id (rtpbin, sessid);
976   if (!session) {
977     GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
978     /* create session now */
979     session = create_session (rtpbin, sessid);
980     if (session == NULL)
981       goto create_error;
982   }
983
984   /* check if pad was requested */
985   if (session->recv_rtp_sink != NULL)
986     goto existed;
987
988   GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
989   /* get recv_rtp pad and store */
990   session->recv_rtp_sink =
991       gst_element_get_request_pad (session->session, "recv_rtp_sink");
992   if (session->recv_rtp_sink == NULL)
993     goto pad_failed;
994
995   GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
996   /* get srcpad, link to SSRCDemux */
997   session->recv_rtp_src =
998       gst_element_get_static_pad (session->session, "recv_rtp_src");
999   if (session->recv_rtp_src == NULL)
1000     goto pad_failed;
1001
1002   GST_DEBUG_OBJECT (rtpbin, "getting demuxer sink pad");
1003   sinkdpad = gst_element_get_static_pad (session->demux, "sink");
1004   lres = gst_pad_link (session->recv_rtp_src, sinkdpad);
1005   gst_object_unref (sinkdpad);
1006   if (lres != GST_PAD_LINK_OK)
1007     goto link_failed;
1008
1009   /* connect to the new-ssrc-pad signal of the SSRC demuxer */
1010   session->demux_newpad_sig = g_signal_connect (session->demux,
1011       "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
1012
1013   GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
1014   result =
1015       gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
1016   gst_pad_set_active (result, TRUE);
1017   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1018
1019   return result;
1020
1021   /* ERRORS */
1022 no_name:
1023   {
1024     g_warning ("gstrtpbin: invalid name given");
1025     return NULL;
1026   }
1027 create_error:
1028   {
1029     /* create_session already warned */
1030     return NULL;
1031   }
1032 existed:
1033   {
1034     g_warning ("gstrtpbin: recv_rtp pad already requested for session %d",
1035         sessid);
1036     return NULL;
1037   }
1038 pad_failed:
1039   {
1040     g_warning ("gstrtpbin: failed to get session pad");
1041     return NULL;
1042   }
1043 link_failed:
1044   {
1045     g_warning ("gstrtpbin: failed to link pads");
1046     return NULL;
1047   }
1048 }
1049
1050 /* Create a pad for receiving RTCP for the session in @name. Must be called with
1051  * RTP_BIN_LOCK.
1052  */
1053 static GstPad *
1054 create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
1055     const gchar * name)
1056 {
1057   GstPad *result;
1058   guint sessid;
1059   GstRtpBinSession *session;
1060
1061 #if 0
1062   GstPad *sinkdpad;
1063   GstPadLinkReturn lres;
1064 #endif
1065
1066   /* first get the session number */
1067   if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
1068     goto no_name;
1069
1070   GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
1071
1072   /* get or create the session */
1073   session = find_session_by_id (rtpbin, sessid);
1074   if (!session) {
1075     GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
1076     /* create session now */
1077     session = create_session (rtpbin, sessid);
1078     if (session == NULL)
1079       goto create_error;
1080   }
1081
1082   /* check if pad was requested */
1083   if (session->recv_rtcp_sink != NULL)
1084     goto existed;
1085
1086   GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
1087
1088   /* get recv_rtp pad and store */
1089   session->recv_rtcp_sink =
1090       gst_element_get_request_pad (session->session, "recv_rtcp_sink");
1091   if (session->recv_rtcp_sink == NULL)
1092     goto pad_failed;
1093
1094 #if 0
1095   /* get srcpad, link to SSRCDemux */
1096   GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
1097   session->recv_rtcp_src =
1098       gst_element_get_static_pad (session->session, "sync_src");
1099   if (session->recv_rtcp_src == NULL)
1100     goto pad_failed;
1101
1102   GST_DEBUG_OBJECT (rtpbin, "linking sync to demux");
1103   sinkdpad = gst_element_get_static_pad (session->demux, "sink");
1104   lres = gst_pad_link (session->recv_rtcp_src, sinkdpad);
1105   gst_object_unref (sinkdpad);
1106   if (lres != GST_PAD_LINK_OK)
1107     goto link_failed;
1108 #endif
1109
1110   result =
1111       gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
1112   gst_pad_set_active (result, TRUE);
1113   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1114
1115   return result;
1116
1117   /* ERRORS */
1118 no_name:
1119   {
1120     g_warning ("gstrtpbin: invalid name given");
1121     return NULL;
1122   }
1123 create_error:
1124   {
1125     /* create_session already warned */
1126     return NULL;
1127   }
1128 existed:
1129   {
1130     g_warning ("gstrtpbin: recv_rtcp pad already requested for session %d",
1131         sessid);
1132     return NULL;
1133   }
1134 pad_failed:
1135   {
1136     g_warning ("gstrtpbin: failed to get session pad");
1137     return NULL;
1138   }
1139 #if 0
1140 link_failed:
1141   {
1142     g_warning ("gstrtpbin: failed to link pads");
1143     return NULL;
1144   }
1145 #endif
1146 }
1147
1148 /* Create a pad for sending RTP for the session in @name. Must be called with
1149  * RTP_BIN_LOCK.
1150  */
1151 static GstPad *
1152 create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
1153 {
1154   GstPad *result, *srcghost;
1155   gchar *gname;
1156   guint sessid;
1157   GstRtpBinSession *session;
1158   GstElementClass *klass;
1159
1160   /* first get the session number */
1161   if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
1162     goto no_name;
1163
1164   /* get or create session */
1165   session = find_session_by_id (rtpbin, sessid);
1166   if (!session) {
1167     /* create session now */
1168     session = create_session (rtpbin, sessid);
1169     if (session == NULL)
1170       goto create_error;
1171   }
1172
1173   /* check if pad was requested */
1174   if (session->send_rtp_sink != NULL)
1175     goto existed;
1176
1177   /* get send_rtp pad and store */
1178   session->send_rtp_sink =
1179       gst_element_get_request_pad (session->session, "send_rtp_sink");
1180   if (session->send_rtp_sink == NULL)
1181     goto pad_failed;
1182
1183   result =
1184       gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
1185   gst_pad_set_active (result, TRUE);
1186   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1187
1188   /* get srcpad */
1189   session->send_rtp_src =
1190       gst_element_get_static_pad (session->session, "send_rtp_src");
1191   if (session->send_rtp_src == NULL)
1192     goto no_srcpad;
1193
1194   /* ghost the new source pad */
1195   klass = GST_ELEMENT_GET_CLASS (rtpbin);
1196   gname = g_strdup_printf ("send_rtp_src_%d", sessid);
1197   templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
1198   srcghost =
1199       gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ);
1200   gst_pad_set_active (srcghost, TRUE);
1201   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
1202   g_free (gname);
1203
1204   return result;
1205
1206   /* ERRORS */
1207 no_name:
1208   {
1209     g_warning ("gstrtpbin: invalid name given");
1210     return NULL;
1211   }
1212 create_error:
1213   {
1214     /* create_session already warned */
1215     return NULL;
1216   }
1217 existed:
1218   {
1219     g_warning ("gstrtpbin: send_rtp pad already requested for session %d",
1220         sessid);
1221     return NULL;
1222   }
1223 pad_failed:
1224   {
1225     g_warning ("gstrtpbin: failed to get session pad for session %d", sessid);
1226     return NULL;
1227   }
1228 no_srcpad:
1229   {
1230     g_warning ("gstrtpbin: failed to get rtp source pad for session %d",
1231         sessid);
1232     return NULL;
1233   }
1234 }
1235
1236 /* Create a pad for sending RTCP for the session in @name. Must be called with
1237  * RTP_BIN_LOCK.
1238  */
1239 static GstPad *
1240 create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
1241 {
1242   GstPad *result;
1243   guint sessid;
1244   GstRtpBinSession *session;
1245
1246   /* first get the session number */
1247   if (name == NULL || sscanf (name, "send_rtcp_src_%d", &sessid) != 1)
1248     goto no_name;
1249
1250   /* get or create session */
1251   session = find_session_by_id (rtpbin, sessid);
1252   if (!session)
1253     goto no_session;
1254
1255   /* check if pad was requested */
1256   if (session->send_rtcp_src != NULL)
1257     goto existed;
1258
1259   /* get rtcp_src pad and store */
1260   session->send_rtcp_src =
1261       gst_element_get_request_pad (session->session, "send_rtcp_src");
1262   if (session->send_rtcp_src == NULL)
1263     goto pad_failed;
1264
1265   result =
1266       gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ);
1267   gst_pad_set_active (result, TRUE);
1268   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1269
1270   return result;
1271
1272   /* ERRORS */
1273 no_name:
1274   {
1275     g_warning ("gstrtpbin: invalid name given");
1276     return NULL;
1277   }
1278 no_session:
1279   {
1280     g_warning ("gstrtpbin: session with id %d does not exist", sessid);
1281     return NULL;
1282   }
1283 existed:
1284   {
1285     g_warning ("gstrtpbin: send_rtcp_src pad already requested for session %d",
1286         sessid);
1287     return NULL;
1288   }
1289 pad_failed:
1290   {
1291     g_warning ("gstrtpbin: failed to get rtcp pad for session %d", sessid);
1292     return NULL;
1293   }
1294 }
1295
1296 /* 
1297  */
1298 static GstPad *
1299 gst_rtp_bin_request_new_pad (GstElement * element,
1300     GstPadTemplate * templ, const gchar * name)
1301 {
1302   GstRtpBin *rtpbin;
1303   GstElementClass *klass;
1304   GstPad *result;
1305
1306   g_return_val_if_fail (templ != NULL, NULL);
1307   g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
1308
1309   rtpbin = GST_RTP_BIN (element);
1310   klass = GST_ELEMENT_GET_CLASS (element);
1311
1312   GST_RTP_BIN_LOCK (rtpbin);
1313
1314   /* figure out the template */
1315   if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
1316     result = create_recv_rtp (rtpbin, templ, name);
1317   } else if (templ == gst_element_class_get_pad_template (klass,
1318           "recv_rtcp_sink_%d")) {
1319     result = create_recv_rtcp (rtpbin, templ, name);
1320   } else if (templ == gst_element_class_get_pad_template (klass,
1321           "send_rtp_sink_%d")) {
1322     result = create_send_rtp (rtpbin, templ, name);
1323   } else if (templ == gst_element_class_get_pad_template (klass,
1324           "send_rtcp_src_%d")) {
1325     result = create_rtcp (rtpbin, templ, name);
1326   } else
1327     goto wrong_template;
1328
1329   GST_RTP_BIN_UNLOCK (rtpbin);
1330
1331   return result;
1332
1333   /* ERRORS */
1334 wrong_template:
1335   {
1336     GST_RTP_BIN_UNLOCK (rtpbin);
1337     g_warning ("gstrtpbin: this is not our template");
1338     return NULL;
1339   }
1340 }
1341
1342 static void
1343 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)
1344 {
1345 }