Rename elements to avoid conflict with farsight elements with the same name. Fixes...
[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  * </refsect2>
79  *
80  * Last reviewed on 2007-05-28 (0.10.5)
81  */
82
83 #ifdef HAVE_CONFIG_H
84 #include "config.h"
85 #endif
86 #include <string.h>
87
88 #include "gstrtpbin-marshal.h"
89 #include "gstrtpbin.h"
90
91 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
92 #define GST_CAT_DEFAULT gst_rtp_bin_debug
93
94
95 /* elementfactory information */
96 static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin",
97     "Filter/Network/RTP",
98     "Implement an RTP bin",
99     "Wim Taymans <wim@fluendo.com>");
100
101 /* sink pads */
102 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
103 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%d",
104     GST_PAD_SINK,
105     GST_PAD_REQUEST,
106     GST_STATIC_CAPS ("application/x-rtp")
107     );
108
109 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
110 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%d",
111     GST_PAD_SINK,
112     GST_PAD_REQUEST,
113     GST_STATIC_CAPS ("application/x-rtcp")
114     );
115
116 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
117 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%d",
118     GST_PAD_SINK,
119     GST_PAD_REQUEST,
120     GST_STATIC_CAPS ("application/x-rtp")
121     );
122
123 /* src pads */
124 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
125 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
126     GST_PAD_SRC,
127     GST_PAD_SOMETIMES,
128     GST_STATIC_CAPS ("application/x-rtp")
129     );
130
131 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
132 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
133     GST_PAD_SRC,
134     GST_PAD_REQUEST,
135     GST_STATIC_CAPS ("application/x-rtcp")
136     );
137
138 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
139 GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%d",
140     GST_PAD_SRC,
141     GST_PAD_SOMETIMES,
142     GST_STATIC_CAPS ("application/x-rtp")
143     );
144
145 #define GST_RTP_BIN_GET_PRIVATE(obj)  \
146    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRTPBinPrivate))
147
148 #define GST_RTP_BIN_LOCK(bin)   g_mutex_lock ((bin)->priv->bin_lock)
149 #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock ((bin)->priv->bin_lock)
150
151 struct _GstRTPBinPrivate
152 {
153   GMutex *bin_lock;
154 };
155
156 /* signals and args */
157 enum
158 {
159   SIGNAL_REQUEST_PT_MAP,
160   SIGNAL_CLEAR_PT_MAP,
161   LAST_SIGNAL
162 };
163
164 #define DEFAULT_LATENCY_MS      200
165
166 enum
167 {
168   PROP_0,
169   PROP_LATENCY
170 };
171
172 /* helper objects */
173 typedef struct _GstRTPBinSession GstRTPBinSession;
174 typedef struct _GstRTPBinStream GstRTPBinStream;
175 typedef struct _GstRTPBinClient GstRTPBinClient;
176
177 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
178
179 static GstCaps *pt_map_requested (GstElement * element, guint pt,
180     GstRTPBinSession * session);
181
182 /* Manages the RTP stream for one SSRC.
183  *
184  * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
185  * If we see an SDES RTCP packet that links multiple SSRCs together based on a
186  * common CNAME, we create a GstRTPBinClient structure to group the SSRCs
187  * together (see below).
188  */
189 struct _GstRTPBinStream
190 {
191   /* the SSRC of this stream */
192   guint32 ssrc;
193   /* parent bin */
194   GstRTPBin *bin;
195   /* the session this SSRC belongs to */
196   GstRTPBinSession *session;
197   /* the jitterbuffer of the SSRC */
198   GstElement *buffer;
199   /* the PT demuxer of the SSRC */
200   GstElement *demux;
201   gulong demux_newpad_sig;
202   gulong demux_ptreq_sig;
203 };
204
205 #define GST_RTP_SESSION_LOCK(sess)   g_mutex_lock ((sess)->lock)
206 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->lock)
207
208 /* Manages the receiving end of the packets.
209  *
210  * There is one such structure for each RTP session (audio/video/...).
211  * We get the RTP/RTCP packets and stuff them into the session manager. From
212  * there they are pushed into an SSRC demuxer that splits the stream based on
213  * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
214  * the GstRTPBinStream above).
215  */
216 struct _GstRTPBinSession
217 {
218   /* session id */
219   gint id;
220   /* the parent bin */
221   GstRTPBin *bin;
222   /* the session element */
223   GstElement *session;
224   /* the SSRC demuxer */
225   GstElement *demux;
226   gulong demux_newpad_sig;
227
228   GMutex *lock;
229
230   /* list of GstRTPBinStream */
231   GSList *streams;
232
233   /* mapping of payload type to caps */
234   GHashTable *ptmap;
235
236   /* the pads of the session */
237   GstPad *recv_rtp_sink;
238   GstPad *recv_rtp_src;
239   GstPad *recv_rtcp_sink;
240   GstPad *recv_rtcp_src;
241   GstPad *send_rtp_sink;
242   GstPad *send_rtp_src;
243   GstPad *send_rtcp_src;
244 };
245
246 /* find a session with the given id. Must be called with RTP_BIN_LOCK */
247 static GstRTPBinSession *
248 find_session_by_id (GstRTPBin * rtpbin, gint id)
249 {
250   GSList *walk;
251
252   for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
253     GstRTPBinSession *sess = (GstRTPBinSession *) walk->data;
254
255     if (sess->id == id)
256       return sess;
257   }
258   return NULL;
259 }
260
261 /* create a session with the given id.  Must be called with RTP_BIN_LOCK */
262 static GstRTPBinSession *
263 create_session (GstRTPBin * rtpbin, gint id)
264 {
265   GstRTPBinSession *sess;
266   GstElement *session, *demux;
267
268   if (!(session = gst_element_factory_make ("gstrtpsession", NULL)))
269     goto no_session;
270
271   if (!(demux = gst_element_factory_make ("gstrtpssrcdemux", NULL)))
272     goto no_demux;
273
274   sess = g_new0 (GstRTPBinSession, 1);
275   sess->lock = g_mutex_new ();
276   sess->id = id;
277   sess->bin = rtpbin;
278   sess->session = session;
279   sess->demux = demux;
280   sess->ptmap = g_hash_table_new (NULL, NULL);
281   rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
282
283   /* provide clock_rate to the session manager when needed */
284   g_signal_connect (session, "request-pt-map",
285       (GCallback) pt_map_requested, sess);
286
287   gst_bin_add (GST_BIN_CAST (rtpbin), session);
288   gst_element_set_state (session, GST_STATE_PLAYING);
289   gst_bin_add (GST_BIN_CAST (rtpbin), demux);
290   gst_element_set_state (demux, GST_STATE_PLAYING);
291
292   return sess;
293
294   /* ERRORS */
295 no_session:
296   {
297     g_warning ("gstrtpbin: could not create gstrtpsession element");
298     return NULL;
299   }
300 no_demux:
301   {
302     gst_object_unref (session);
303     g_warning ("gstrtpbin: could not create gstrtpssrcdemux element");
304     return NULL;
305   }
306 }
307
308 #if 0
309 static GstRTPBinStream *
310 find_stream_by_ssrc (GstRTPBinSession * session, guint32 ssrc)
311 {
312   GSList *walk;
313
314   for (walk = session->streams; walk; walk = g_slist_next (walk)) {
315     GstRTPBinStream *stream = (GstRTPBinStream *) walk->data;
316
317     if (stream->ssrc == ssrc)
318       return stream;
319   }
320   return NULL;
321 }
322 #endif
323
324 /* get the payload type caps for the specific payload @pt in @session */
325 static GstCaps *
326 get_pt_map (GstRTPBinSession * session, guint pt)
327 {
328   GstCaps *caps = NULL;
329   GstRTPBin *bin;
330   GValue ret = { 0 };
331   GValue args[3] = { {0}, {0}, {0} };
332
333   GST_DEBUG ("searching pt %d in cache", pt);
334
335   GST_RTP_SESSION_LOCK (session);
336
337   /* first look in the cache */
338   caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
339   if (caps)
340     goto done;
341
342   bin = session->bin;
343
344   GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
345
346   /* not in cache, send signal to request caps */
347   g_value_init (&args[0], GST_TYPE_ELEMENT);
348   g_value_set_object (&args[0], bin);
349   g_value_init (&args[1], G_TYPE_UINT);
350   g_value_set_uint (&args[1], session->id);
351   g_value_init (&args[2], G_TYPE_UINT);
352   g_value_set_uint (&args[2], pt);
353
354   g_value_init (&ret, GST_TYPE_CAPS);
355   g_value_set_boxed (&ret, NULL);
356
357   g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
358
359   caps = (GstCaps *) g_value_get_boxed (&ret);
360   if (!caps)
361     goto no_caps;
362
363   GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
364
365   /* store in cache */
366   g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
367
368 done:
369   GST_RTP_SESSION_UNLOCK (session);
370
371   return caps;
372
373   /* ERRORS */
374 no_caps:
375   {
376     GST_RTP_SESSION_UNLOCK (session);
377     GST_DEBUG ("no pt map could be obtained");
378     return NULL;
379   }
380 }
381
382 static gboolean
383 return_true (gpointer key, gpointer value, gpointer user_data)
384 {
385   return TRUE;
386 }
387
388 static void
389 gst_rtp_bin_clear_pt_map (GstRTPBin * bin)
390 {
391   GSList *walk;
392
393   GST_RTP_BIN_LOCK (bin);
394   for (walk = bin->sessions; walk; walk = g_slist_next (walk)) {
395     GstRTPBinSession *session = (GstRTPBinSession *) walk->data;
396
397     GST_RTP_SESSION_LOCK (session);
398 #if 0
399     /* This requires GLib 2.12 */
400     g_hash_table_remove_all (session->ptmap);
401 #else
402     g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
403 #endif
404     GST_RTP_SESSION_UNLOCK (session);
405   }
406   GST_RTP_BIN_UNLOCK (bin);
407 }
408
409 /* create a new stream with @ssrc in @session. Must be called with
410  * RTP_SESSION_LOCK. */
411 static GstRTPBinStream *
412 create_stream (GstRTPBinSession * session, guint32 ssrc)
413 {
414   GstElement *buffer, *demux;
415   GstRTPBinStream *stream;
416
417   if (!(buffer = gst_element_factory_make ("gstrtpjitterbuffer", NULL)))
418     goto no_jitterbuffer;
419
420   if (!(demux = gst_element_factory_make ("gstrtpptdemux", NULL)))
421     goto no_demux;
422
423   stream = g_new0 (GstRTPBinStream, 1);
424   stream->ssrc = ssrc;
425   stream->bin = session->bin;
426   stream->session = session;
427   stream->buffer = buffer;
428   stream->demux = demux;
429   session->streams = g_slist_prepend (session->streams, stream);
430
431   /* provide clock_rate to the jitterbuffer when needed */
432   g_signal_connect (buffer, "request-pt-map",
433       (GCallback) pt_map_requested, session);
434
435   /* configure latency */
436   g_object_set (buffer, "latency", session->bin->latency, NULL);
437
438   gst_bin_add (GST_BIN_CAST (session->bin), buffer);
439   gst_element_set_state (buffer, GST_STATE_PLAYING);
440   gst_bin_add (GST_BIN_CAST (session->bin), demux);
441   gst_element_set_state (demux, GST_STATE_PLAYING);
442
443   /* link stuff */
444   gst_element_link (buffer, demux);
445
446   return stream;
447
448   /* ERRORS */
449 no_jitterbuffer:
450   {
451     g_warning ("gstrtpbin: could not create gstrtpjitterbuffer element");
452     return NULL;
453   }
454 no_demux:
455   {
456     gst_object_unref (buffer);
457     g_warning ("gstrtpbin: could not create gstrtpptdemux element");
458     return NULL;
459   }
460 }
461
462 /* Manages the RTP streams that come from one client and should therefore be
463  * synchronized.
464  */
465 struct _GstRTPBinClient
466 {
467   /* the common CNAME for the streams */
468   gchar *cname;
469   /* the streams */
470   GSList *streams;
471 };
472
473 /* GObject vmethods */
474 static void gst_rtp_bin_finalize (GObject * object);
475 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
476     const GValue * value, GParamSpec * pspec);
477 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
478     GValue * value, GParamSpec * pspec);
479
480 /* GstElement vmethods */
481 static GstClock *gst_rtp_bin_provide_clock (GstElement * element);
482 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
483     GstStateChange transition);
484 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
485     GstPadTemplate * templ, const gchar * name);
486 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
487 static void gst_rtp_bin_clear_pt_map (GstRTPBin * bin);
488
489 GST_BOILERPLATE (GstRTPBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
490
491 static void
492 gst_rtp_bin_base_init (gpointer klass)
493 {
494   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
495
496   /* sink pads */
497   gst_element_class_add_pad_template (element_class,
498       gst_static_pad_template_get (&rtpbin_recv_rtp_sink_template));
499   gst_element_class_add_pad_template (element_class,
500       gst_static_pad_template_get (&rtpbin_recv_rtcp_sink_template));
501   gst_element_class_add_pad_template (element_class,
502       gst_static_pad_template_get (&rtpbin_send_rtp_sink_template));
503
504   /* src pads */
505   gst_element_class_add_pad_template (element_class,
506       gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
507   gst_element_class_add_pad_template (element_class,
508       gst_static_pad_template_get (&rtpbin_send_rtcp_src_template));
509   gst_element_class_add_pad_template (element_class,
510       gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
511
512   gst_element_class_set_details (element_class, &rtpbin_details);
513 }
514
515 static void
516 gst_rtp_bin_class_init (GstRTPBinClass * klass)
517 {
518   GObjectClass *gobject_class;
519   GstElementClass *gstelement_class;
520
521   gobject_class = (GObjectClass *) klass;
522   gstelement_class = (GstElementClass *) klass;
523
524   g_type_class_add_private (klass, sizeof (GstRTPBinPrivate));
525
526   gobject_class->finalize = gst_rtp_bin_finalize;
527   gobject_class->set_property = gst_rtp_bin_set_property;
528   gobject_class->get_property = gst_rtp_bin_get_property;
529
530   g_object_class_install_property (gobject_class, PROP_LATENCY,
531       g_param_spec_uint ("latency", "Buffer latency in ms",
532           "Default amount of ms to buffer in the jitterbuffers", 0,
533           G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE));
534
535   /**
536    * GstRTPBin::request-pt-map:
537    * @rtpbin: the object which received the signal
538    * @session: the session
539    * @pt: the pt
540    *
541    * Request the payload type as #GstCaps for @pt in @session.
542    */
543   gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
544       g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
545       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, request_pt_map),
546       NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2,
547       G_TYPE_UINT, G_TYPE_UINT);
548   /**
549    * GstRTPBin::clear-pt-map:
550    * @rtpbin: the object which received the signal
551    *
552    * Clear all previously cached pt-mapping obtained with
553    * GstRTPBin::request-pt-map.
554    */
555   gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] =
556       g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
557       G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTPBinClass, clear_pt_map),
558       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
559
560   gstelement_class->provide_clock =
561       GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
562   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
563   gstelement_class->request_new_pad =
564       GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
565   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
566
567   klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
568
569   GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
570 }
571
572 static void
573 gst_rtp_bin_init (GstRTPBin * rtpbin, GstRTPBinClass * klass)
574 {
575   rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
576   rtpbin->priv->bin_lock = g_mutex_new ();
577   rtpbin->provided_clock = gst_system_clock_obtain ();
578 }
579
580 static void
581 gst_rtp_bin_finalize (GObject * object)
582 {
583   GstRTPBin *rtpbin;
584
585   rtpbin = GST_RTP_BIN (object);
586
587   g_mutex_free (rtpbin->priv->bin_lock);
588
589   G_OBJECT_CLASS (parent_class)->finalize (object);
590 }
591
592 static void
593 gst_rtp_bin_set_property (GObject * object, guint prop_id,
594     const GValue * value, GParamSpec * pspec)
595 {
596   GstRTPBin *rtpbin;
597
598   rtpbin = GST_RTP_BIN (object);
599
600   switch (prop_id) {
601     case PROP_LATENCY:
602       rtpbin->latency = g_value_get_uint (value);
603       break;
604     default:
605       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
606       break;
607   }
608 }
609
610 static void
611 gst_rtp_bin_get_property (GObject * object, guint prop_id,
612     GValue * value, GParamSpec * pspec)
613 {
614   GstRTPBin *rtpbin;
615
616   rtpbin = GST_RTP_BIN (object);
617
618   switch (prop_id) {
619     case PROP_LATENCY:
620       g_value_set_uint (value, rtpbin->latency);
621       break;
622     default:
623       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
624       break;
625   }
626 }
627
628 static GstClock *
629 gst_rtp_bin_provide_clock (GstElement * element)
630 {
631   GstRTPBin *rtpbin;
632
633   rtpbin = GST_RTP_BIN (element);
634
635   return GST_CLOCK_CAST (gst_object_ref (rtpbin->provided_clock));
636 }
637
638 static GstStateChangeReturn
639 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
640 {
641   GstStateChangeReturn res;
642   GstRTPBin *rtpbin;
643
644   rtpbin = GST_RTP_BIN (element);
645
646   switch (transition) {
647     case GST_STATE_CHANGE_NULL_TO_READY:
648       break;
649     case GST_STATE_CHANGE_READY_TO_PAUSED:
650       break;
651     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
652       break;
653     default:
654       break;
655   }
656
657   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
658
659   switch (transition) {
660     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
661       break;
662     case GST_STATE_CHANGE_PAUSED_TO_READY:
663       break;
664     case GST_STATE_CHANGE_READY_TO_NULL:
665       break;
666     default:
667       break;
668   }
669   return res;
670 }
671
672 /* a new pad (SSRC) was created in @session */
673 static void
674 new_payload_found (GstElement * element, guint pt, GstPad * pad,
675     GstRTPBinStream * stream)
676 {
677   GstRTPBin *rtpbin;
678   GstElementClass *klass;
679   GstPadTemplate *templ;
680   gchar *padname;
681   GstPad *gpad;
682
683   rtpbin = stream->bin;
684
685   GST_DEBUG ("new payload pad %d", pt);
686
687   /* ghost the pad to the parent */
688   klass = GST_ELEMENT_GET_CLASS (rtpbin);
689   templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
690   padname = g_strdup_printf ("recv_rtp_src_%d_%u_%d",
691       stream->session->id, stream->ssrc, pt);
692   gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
693   g_free (padname);
694
695   gst_pad_set_active (gpad, TRUE);
696   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
697 }
698
699 static GstCaps *
700 pt_map_requested (GstElement * element, guint pt, GstRTPBinSession * session)
701 {
702   GstRTPBin *rtpbin;
703   GstCaps *caps;
704
705   rtpbin = session->bin;
706
707   GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
708       session->id);
709
710   caps = get_pt_map (session, pt);
711   if (!caps)
712     goto no_caps;
713
714   return caps;
715
716   /* ERRORS */
717 no_caps:
718   {
719     GST_DEBUG_OBJECT (rtpbin, "could not get caps");
720     return NULL;
721   }
722 }
723
724 /* a new pad (SSRC) was created in @session */
725 static void
726 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
727     GstRTPBinSession * session)
728 {
729   GstRTPBinStream *stream;
730   GstPad *sinkpad;
731
732   GST_DEBUG_OBJECT (session->bin, "new SSRC pad %08x", ssrc);
733
734   GST_RTP_SESSION_LOCK (session);
735
736   /* create new stream */
737   stream = create_stream (session, ssrc);
738   if (!stream)
739     goto no_stream;
740
741   /* get pad and link */
742   GST_DEBUG_OBJECT (session->bin, "linking jitterbuffer");
743   sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
744   gst_pad_link (pad, sinkpad);
745   gst_object_unref (sinkpad);
746
747   /* connect to the new-pad signal of the payload demuxer, this will expose the
748    * new pad by ghosting it. */
749   stream->demux_newpad_sig = g_signal_connect (stream->demux,
750       "new-payload-type", (GCallback) new_payload_found, stream);
751   /* connect to the request-pt-map signal. This signal will be emited by the
752    * demuxer so that it can apply a proper caps on the buffers for the
753    * depayloaders. */
754   stream->demux_ptreq_sig = g_signal_connect (stream->demux,
755       "request-pt-map", (GCallback) pt_map_requested, session);
756
757   GST_RTP_SESSION_UNLOCK (session);
758
759   return;
760
761   /* ERRORS */
762 no_stream:
763   {
764     GST_RTP_SESSION_UNLOCK (session);
765     GST_DEBUG ("could not create stream");
766     return;
767   }
768 }
769
770 /* Create a pad for receiving RTP for the session in @name. Must be called with
771  * RTP_BIN_LOCK.
772  */
773 static GstPad *
774 create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
775 {
776   GstPad *result, *sinkdpad;
777   guint sessid;
778   GstRTPBinSession *session;
779   GstPadLinkReturn lres;
780
781   /* first get the session number */
782   if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
783     goto no_name;
784
785   GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
786
787   /* get or create session */
788   session = find_session_by_id (rtpbin, sessid);
789   if (!session) {
790     GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
791     /* create session now */
792     session = create_session (rtpbin, sessid);
793     if (session == NULL)
794       goto create_error;
795   }
796
797   /* check if pad was requested */
798   if (session->recv_rtp_sink != NULL)
799     goto existed;
800
801   GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
802   /* get recv_rtp pad and store */
803   session->recv_rtp_sink =
804       gst_element_get_request_pad (session->session, "recv_rtp_sink");
805   if (session->recv_rtp_sink == NULL)
806     goto pad_failed;
807
808   GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
809   /* get srcpad, link to SSRCDemux */
810   session->recv_rtp_src =
811       gst_element_get_static_pad (session->session, "recv_rtp_src");
812   if (session->recv_rtp_src == NULL)
813     goto pad_failed;
814
815   GST_DEBUG_OBJECT (rtpbin, "getting demuxer sink pad");
816   sinkdpad = gst_element_get_static_pad (session->demux, "sink");
817   lres = gst_pad_link (session->recv_rtp_src, sinkdpad);
818   gst_object_unref (sinkdpad);
819   if (lres != GST_PAD_LINK_OK)
820     goto link_failed;
821
822   /* connect to the new-ssrc-pad signal of the SSRC demuxer */
823   session->demux_newpad_sig = g_signal_connect (session->demux,
824       "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
825
826   GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
827   result =
828       gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
829   gst_pad_set_active (result, TRUE);
830   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
831
832   return result;
833
834   /* ERRORS */
835 no_name:
836   {
837     g_warning ("gstrtpbin: invalid name given");
838     return NULL;
839   }
840 create_error:
841   {
842     /* create_session already warned */
843     return NULL;
844   }
845 existed:
846   {
847     g_warning ("gstrtpbin: recv_rtp pad already requested for session %d",
848         sessid);
849     return NULL;
850   }
851 pad_failed:
852   {
853     g_warning ("gstrtpbin: failed to get session pad");
854     return NULL;
855   }
856 link_failed:
857   {
858     g_warning ("gstrtpbin: failed to link pads");
859     return NULL;
860   }
861 }
862
863 /* Create a pad for receiving RTCP for the session in @name. Must be called with
864  * RTP_BIN_LOCK.
865  */
866 static GstPad *
867 create_recv_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ,
868     const gchar * name)
869 {
870   GstPad *result;
871   guint sessid;
872   GstRTPBinSession *session;
873
874 #if 0
875   GstPad *sinkdpad;
876   GstPadLinkReturn lres;
877 #endif
878
879   /* first get the session number */
880   if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
881     goto no_name;
882
883   GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
884
885   /* get or create the session */
886   session = find_session_by_id (rtpbin, sessid);
887   if (!session) {
888     GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
889     /* create session now */
890     session = create_session (rtpbin, sessid);
891     if (session == NULL)
892       goto create_error;
893   }
894
895   /* check if pad was requested */
896   if (session->recv_rtcp_sink != NULL)
897     goto existed;
898
899   GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
900
901   /* get recv_rtp pad and store */
902   session->recv_rtcp_sink =
903       gst_element_get_request_pad (session->session, "recv_rtcp_sink");
904   if (session->recv_rtcp_sink == NULL)
905     goto pad_failed;
906
907 #if 0
908   /* get srcpad, link to SSRCDemux */
909   GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
910   session->recv_rtcp_src =
911       gst_element_get_static_pad (session->session, "sync_src");
912   if (session->recv_rtcp_src == NULL)
913     goto pad_failed;
914
915   GST_DEBUG_OBJECT (rtpbin, "linking sync to demux");
916   sinkdpad = gst_element_get_static_pad (session->demux, "sink");
917   lres = gst_pad_link (session->recv_rtcp_src, sinkdpad);
918   gst_object_unref (sinkdpad);
919   if (lres != GST_PAD_LINK_OK)
920     goto link_failed;
921 #endif
922
923   result =
924       gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
925   gst_pad_set_active (result, TRUE);
926   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
927
928   return result;
929
930   /* ERRORS */
931 no_name:
932   {
933     g_warning ("gstrtpbin: invalid name given");
934     return NULL;
935   }
936 create_error:
937   {
938     /* create_session already warned */
939     return NULL;
940   }
941 existed:
942   {
943     g_warning ("gstrtpbin: recv_rtcp pad already requested for session %d",
944         sessid);
945     return NULL;
946   }
947 pad_failed:
948   {
949     g_warning ("gstrtpbin: failed to get session pad");
950     return NULL;
951   }
952 #if 0
953 link_failed:
954   {
955     g_warning ("gstrtpbin: failed to link pads");
956     return NULL;
957   }
958 #endif
959 }
960
961 /* Create a pad for sending RTP for the session in @name. Must be called with
962  * RTP_BIN_LOCK.
963  */
964 static GstPad *
965 create_send_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
966 {
967   GstPad *result, *srcghost;
968   gchar *gname;
969   guint sessid;
970   GstRTPBinSession *session;
971   GstElementClass *klass;
972
973   /* first get the session number */
974   if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
975     goto no_name;
976
977   /* get or create session */
978   session = find_session_by_id (rtpbin, sessid);
979   if (!session) {
980     /* create session now */
981     session = create_session (rtpbin, sessid);
982     if (session == NULL)
983       goto create_error;
984   }
985
986   /* check if pad was requested */
987   if (session->send_rtp_sink != NULL)
988     goto existed;
989
990   /* get send_rtp pad and store */
991   session->send_rtp_sink =
992       gst_element_get_request_pad (session->session, "send_rtp_sink");
993   if (session->send_rtp_sink == NULL)
994     goto pad_failed;
995
996   result =
997       gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
998   gst_pad_set_active (result, TRUE);
999   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1000
1001   /* get srcpad */
1002   session->send_rtp_src =
1003       gst_element_get_static_pad (session->session, "send_rtp_src");
1004   if (session->send_rtp_src == NULL)
1005     goto no_srcpad;
1006
1007   /* ghost the new source pad */
1008   klass = GST_ELEMENT_GET_CLASS (rtpbin);
1009   gname = g_strdup_printf ("send_rtp_src_%d", sessid);
1010   templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
1011   srcghost =
1012       gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ);
1013   gst_pad_set_active (srcghost, TRUE);
1014   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
1015   g_free (gname);
1016
1017   return result;
1018
1019   /* ERRORS */
1020 no_name:
1021   {
1022     g_warning ("gstrtpbin: invalid name given");
1023     return NULL;
1024   }
1025 create_error:
1026   {
1027     /* create_session already warned */
1028     return NULL;
1029   }
1030 existed:
1031   {
1032     g_warning ("gstrtpbin: send_rtp pad already requested for session %d",
1033         sessid);
1034     return NULL;
1035   }
1036 pad_failed:
1037   {
1038     g_warning ("gstrtpbin: failed to get session pad for session %d", sessid);
1039     return NULL;
1040   }
1041 no_srcpad:
1042   {
1043     g_warning ("gstrtpbin: failed to get rtp source pad for session %d",
1044         sessid);
1045     return NULL;
1046   }
1047 }
1048
1049 /* Create a pad for sending RTCP for the session in @name. Must be called with
1050  * RTP_BIN_LOCK.
1051  */
1052 static GstPad *
1053 create_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
1054 {
1055   GstPad *result;
1056   guint sessid;
1057   GstRTPBinSession *session;
1058
1059   /* first get the session number */
1060   if (name == NULL || sscanf (name, "send_rtcp_src_%d", &sessid) != 1)
1061     goto no_name;
1062
1063   /* get or create session */
1064   session = find_session_by_id (rtpbin, sessid);
1065   if (!session)
1066     goto no_session;
1067
1068   /* check if pad was requested */
1069   if (session->send_rtcp_src != NULL)
1070     goto existed;
1071
1072   /* get rtcp_src pad and store */
1073   session->send_rtcp_src =
1074       gst_element_get_request_pad (session->session, "send_rtcp_src");
1075   if (session->send_rtcp_src == NULL)
1076     goto pad_failed;
1077
1078   result =
1079       gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ);
1080   gst_pad_set_active (result, TRUE);
1081   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1082
1083   return result;
1084
1085   /* ERRORS */
1086 no_name:
1087   {
1088     g_warning ("gstrtpbin: invalid name given");
1089     return NULL;
1090   }
1091 no_session:
1092   {
1093     g_warning ("gstrtpbin: session with id %d does not exist", sessid);
1094     return NULL;
1095   }
1096 existed:
1097   {
1098     g_warning ("gstrtpbin: send_rtcp_src pad already requested for session %d",
1099         sessid);
1100     return NULL;
1101   }
1102 pad_failed:
1103   {
1104     g_warning ("gstrtpbin: failed to get rtcp pad for session %d", sessid);
1105     return NULL;
1106   }
1107 }
1108
1109 /* 
1110  */
1111 static GstPad *
1112 gst_rtp_bin_request_new_pad (GstElement * element,
1113     GstPadTemplate * templ, const gchar * name)
1114 {
1115   GstRTPBin *rtpbin;
1116   GstElementClass *klass;
1117   GstPad *result;
1118
1119   g_return_val_if_fail (templ != NULL, NULL);
1120   g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
1121
1122   rtpbin = GST_RTP_BIN (element);
1123   klass = GST_ELEMENT_GET_CLASS (element);
1124
1125   GST_RTP_BIN_LOCK (rtpbin);
1126
1127   /* figure out the template */
1128   if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
1129     result = create_recv_rtp (rtpbin, templ, name);
1130   } else if (templ == gst_element_class_get_pad_template (klass,
1131           "recv_rtcp_sink_%d")) {
1132     result = create_recv_rtcp (rtpbin, templ, name);
1133   } else if (templ == gst_element_class_get_pad_template (klass,
1134           "send_rtp_sink_%d")) {
1135     result = create_send_rtp (rtpbin, templ, name);
1136   } else if (templ == gst_element_class_get_pad_template (klass,
1137           "send_rtcp_src_%d")) {
1138     result = create_rtcp (rtpbin, templ, name);
1139   } else
1140     goto wrong_template;
1141
1142   GST_RTP_BIN_UNLOCK (rtpbin);
1143
1144   return result;
1145
1146   /* ERRORS */
1147 wrong_template:
1148   {
1149     GST_RTP_BIN_UNLOCK (rtpbin);
1150     g_warning ("gstrtpbin: this is not our template");
1151     return NULL;
1152   }
1153 }
1154
1155 static void
1156 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)
1157 {
1158 }