2 * Copyright (C) <2007> Wim Taymans <wim@fluendo.com>
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.
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.
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.
21 * SECTION:element-rtpbin
22 * @short_description: handle media from one RTP bin
23 * @see_also: rtpjitterbuffer, rtpsession, rtpptdemux, rtpssrcdemux
27 * RTP bin combines the functions of rtpsession, rtpssrcdemux, rtpjitterbuffer
28 * and rtpptdemux in one element. It allows for multiple rtpsessions that will
29 * be synchronized together using RTCP SR packets.
32 * rtpbin is configured with a number of request pads that define the
33 * functionality that is activated, similar to the rtpsession element.
36 * To use rtpbin 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 rtpsession
39 * manager and after being validated forwarded on rtpssrcdemuxer element. Each
40 * RTP stream is demuxed based on the SSRC and send to a rtpjitterbuffer. After
41 * the packets are released from the jitterbuffer, they will be forwarded to an
42 * rtpptdemuxer element. The rtpptdemuxer 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 * rtpbin with the session number, SSRC and payload type respectively as the pad
48 * To also use rtpbin as an RTCP receiver, request a recv_rtcp_sink_%%d pad. The
49 * session number must be specified in the pad name.
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
58 * To use rtpbin 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.
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
70 * <title>Example pipelines</title>
73 * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \
74 * rtpbin ! rtptheoradepay ! theoradec ! xvimagesink
76 * Receive RTP data from port 5000 and send to the session 0 in rtpbin.
80 * Last reviewed on 2007-05-23 (0.10.6)
88 #include "gstrtpbin-marshal.h"
89 #include "gstrtpbin.h"
91 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
92 #define GST_CAT_DEFAULT gst_rtp_bin_debug
95 /* elementfactory information */
96 static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin",
98 "Implement an RTP bin",
99 "Wim Taymans <wim@fluendo.com>");
102 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
103 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%d",
106 GST_STATIC_CAPS ("application/x-rtp")
109 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
110 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%d",
113 GST_STATIC_CAPS ("application/x-rtcp")
116 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
117 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%d",
120 GST_STATIC_CAPS ("application/x-rtp")
124 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
125 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
128 GST_STATIC_CAPS ("application/x-rtp")
131 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
132 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
135 GST_STATIC_CAPS ("application/x-rtcp")
138 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
139 GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%d",
142 GST_STATIC_CAPS ("application/x-rtp")
145 #define GST_RTP_BIN_GET_PRIVATE(obj) \
146 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRTPBinPrivate))
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)
151 struct _GstRTPBinPrivate
156 /* signals and args */
159 SIGNAL_REQUEST_PT_MAP,
164 #define DEFAULT_LATENCY_MS 200
173 typedef struct _GstRTPBinSession GstRTPBinSession;
174 typedef struct _GstRTPBinStream GstRTPBinStream;
175 typedef struct _GstRTPBinClient GstRTPBinClient;
177 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
179 static GstCaps *pt_map_requested (GstElement * element, guint pt,
180 GstRTPBinSession * session);
182 /* Manages the RTP stream for one SSRC.
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).
189 struct _GstRTPBinStream
191 /* the SSRC of this stream */
195 /* the session this SSRC belongs to */
196 GstRTPBinSession *session;
197 /* the jitterbuffer of the SSRC */
199 /* the PT demuxer of the SSRC */
201 gulong demux_newpad_sig;
202 gulong demux_ptreq_sig;
205 #define GST_RTP_SESSION_LOCK(sess) g_mutex_lock ((sess)->lock)
206 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->lock)
208 /* Manages the receiving end of the packets.
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).
216 struct _GstRTPBinSession
222 /* the session element */
224 /* the SSRC demuxer */
226 gulong demux_newpad_sig;
230 /* list of GstRTPBinStream */
233 /* mapping of payload type to caps */
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;
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)
252 for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
253 GstRTPBinSession *sess = (GstRTPBinSession *) walk->data;
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)
265 GstRTPBinSession *sess;
266 GstElement *session, *demux;
268 if (!(session = gst_element_factory_make ("rtpsession", NULL)))
271 if (!(demux = gst_element_factory_make ("rtpssrcdemux", NULL)))
274 sess = g_new0 (GstRTPBinSession, 1);
275 sess->lock = g_mutex_new ();
278 sess->session = session;
280 sess->ptmap = g_hash_table_new (NULL, NULL);
281 rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
283 /* provide clock_rate to the session manager when needed */
284 g_signal_connect (session, "request-pt-map",
285 (GCallback) pt_map_requested, sess);
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);
297 g_warning ("rtpbin: could not create rtpsession element");
302 gst_object_unref (session);
303 g_warning ("rtpbin: could not create rtpssrcdemux element");
309 static GstRTPBinStream *
310 find_stream_by_ssrc (GstRTPBinSession * session, guint32 ssrc)
314 for (walk = session->streams; walk; walk = g_slist_next (walk)) {
315 GstRTPBinStream *stream = (GstRTPBinStream *) walk->data;
317 if (stream->ssrc == ssrc)
324 /* get the payload type caps for the specific payload @pt in @session */
326 get_pt_map (GstRTPBinSession * session, guint pt)
328 GstCaps *caps = NULL;
331 GValue args[3] = { {0}, {0}, {0} };
333 GST_DEBUG ("searching pt %d in cache", pt);
335 GST_RTP_SESSION_LOCK (session);
337 /* first look in the cache */
338 caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
344 GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
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);
354 g_value_init (&ret, GST_TYPE_CAPS);
355 g_value_set_boxed (&ret, NULL);
357 g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
359 caps = (GstCaps *) g_value_get_boxed (&ret);
363 GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
366 g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
369 GST_RTP_SESSION_UNLOCK (session);
376 GST_RTP_SESSION_UNLOCK (session);
377 GST_DEBUG ("no pt map could be obtained");
383 return_true (gpointer key, gpointer value, gpointer user_data)
389 gst_rtp_bin_clear_pt_map (GstRTPBin * bin)
393 GST_RTP_BIN_LOCK (bin);
394 for (walk = bin->sessions; walk; walk = g_slist_next (walk)) {
395 GstRTPBinSession *session = (GstRTPBinSession *) walk->data;
397 GST_RTP_SESSION_LOCK (session);
399 /* This requires GLib 2.12 */
400 g_hash_table_remove_all (session->ptmap);
402 g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
404 GST_RTP_SESSION_UNLOCK (session);
406 GST_RTP_BIN_UNLOCK (bin);
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)
414 GstElement *buffer, *demux;
415 GstRTPBinStream *stream;
417 if (!(buffer = gst_element_factory_make ("rtpjitterbuffer", NULL)))
418 goto no_jitterbuffer;
420 if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
423 stream = g_new0 (GstRTPBinStream, 1);
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);
431 /* provide clock_rate to the jitterbuffer when needed */
432 g_signal_connect (buffer, "request-pt-map",
433 (GCallback) pt_map_requested, session);
435 /* configure latency */
436 g_object_set (buffer, "latency", session->bin->latency, NULL);
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);
444 gst_element_link (buffer, demux);
451 g_warning ("rtpbin: could not create rtpjitterbuffer element");
456 gst_object_unref (buffer);
457 g_warning ("rtpbin: could not create rtpptdemux element");
462 /* Manages the RTP streams that come from one client and should therefore be
465 struct _GstRTPBinClient
467 /* the common CNAME for the streams */
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);
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);
489 GST_BOILERPLATE (GstRTPBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
492 gst_rtp_bin_base_init (gpointer klass)
494 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
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));
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));
512 gst_element_class_set_details (element_class, &rtpbin_details);
516 gst_rtp_bin_class_init (GstRTPBinClass * klass)
518 GObjectClass *gobject_class;
519 GstElementClass *gstelement_class;
521 gobject_class = (GObjectClass *) klass;
522 gstelement_class = (GstElementClass *) klass;
524 g_type_class_add_private (klass, sizeof (GstRTPBinPrivate));
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;
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));
536 * GstRTPBin::request-pt-map:
537 * @rtpbin: the object which received the signal
538 * @session: the session
541 * Request the payload type as #GstCaps for @pt in @session.
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);
549 * GstRTPBin::clear-pt-map:
550 * @rtpbin: the object which received the signal
552 * Clear all previously cached pt-mapping obtained with
553 * GstRTPBin::request-pt-map.
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);
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);
567 klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
569 GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
573 gst_rtp_bin_init (GstRTPBin * rtpbin, GstRTPBinClass * klass)
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 ();
581 gst_rtp_bin_finalize (GObject * object)
585 rtpbin = GST_RTP_BIN (object);
587 g_mutex_free (rtpbin->priv->bin_lock);
589 G_OBJECT_CLASS (parent_class)->finalize (object);
593 gst_rtp_bin_set_property (GObject * object, guint prop_id,
594 const GValue * value, GParamSpec * pspec)
598 rtpbin = GST_RTP_BIN (object);
602 rtpbin->latency = g_value_get_uint (value);
605 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
611 gst_rtp_bin_get_property (GObject * object, guint prop_id,
612 GValue * value, GParamSpec * pspec)
616 rtpbin = GST_RTP_BIN (object);
620 g_value_set_uint (value, rtpbin->latency);
623 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
629 gst_rtp_bin_provide_clock (GstElement * element)
633 rtpbin = GST_RTP_BIN (element);
635 return GST_CLOCK_CAST (gst_object_ref (rtpbin->provided_clock));
638 static GstStateChangeReturn
639 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
641 GstStateChangeReturn res;
644 rtpbin = GST_RTP_BIN (element);
646 switch (transition) {
647 case GST_STATE_CHANGE_NULL_TO_READY:
649 case GST_STATE_CHANGE_READY_TO_PAUSED:
651 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
657 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
659 switch (transition) {
660 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
662 case GST_STATE_CHANGE_PAUSED_TO_READY:
664 case GST_STATE_CHANGE_READY_TO_NULL:
672 /* a new pad (SSRC) was created in @session */
674 new_payload_found (GstElement * element, guint pt, GstPad * pad,
675 GstRTPBinStream * stream)
678 GstElementClass *klass;
679 GstPadTemplate *templ;
683 rtpbin = stream->bin;
685 GST_DEBUG ("new payload pad %d", pt);
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);
695 gst_pad_set_active (gpad, TRUE);
696 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
700 pt_map_requested (GstElement * element, guint pt, GstRTPBinSession * session)
705 rtpbin = session->bin;
707 GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
710 caps = get_pt_map (session, pt);
719 GST_DEBUG_OBJECT (rtpbin, "could not get caps");
724 /* a new pad (SSRC) was created in @session */
726 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
727 GstRTPBinSession * session)
729 GstRTPBinStream *stream;
732 GST_DEBUG_OBJECT (session->bin, "new SSRC pad %08x", ssrc);
734 GST_RTP_SESSION_LOCK (session);
736 /* create new stream */
737 stream = create_stream (session, ssrc);
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);
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
754 stream->demux_ptreq_sig = g_signal_connect (stream->demux,
755 "request-pt-map", (GCallback) pt_map_requested, session);
757 GST_RTP_SESSION_UNLOCK (session);
764 GST_RTP_SESSION_UNLOCK (session);
765 GST_DEBUG ("could not create stream");
770 /* Create a pad for receiving RTP for the session in @name. Must be called with
774 create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
776 GstPad *result, *sinkdpad;
778 GstRTPBinSession *session;
779 GstPadLinkReturn lres;
781 /* first get the session number */
782 if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
785 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
787 /* get or create session */
788 session = find_session_by_id (rtpbin, sessid);
790 GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
791 /* create session now */
792 session = create_session (rtpbin, sessid);
797 /* check if pad was requested */
798 if (session->recv_rtp_sink != NULL)
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)
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)
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)
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);
826 GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
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);
837 g_warning ("rtpbin: invalid name given");
842 /* create_session already warned */
847 g_warning ("rtpbin: recv_rtp pad already requested for session %d", sessid);
852 g_warning ("rtpbin: failed to get session pad");
857 g_warning ("rtpbin: failed to link pads");
862 /* Create a pad for receiving RTCP for the session in @name. Must be called with
866 create_recv_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ,
871 GstRTPBinSession *session;
875 GstPadLinkReturn lres;
878 /* first get the session number */
879 if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
882 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
884 /* get or create the session */
885 session = find_session_by_id (rtpbin, sessid);
887 GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
888 /* create session now */
889 session = create_session (rtpbin, sessid);
894 /* check if pad was requested */
895 if (session->recv_rtcp_sink != NULL)
898 GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
900 /* get recv_rtp pad and store */
901 session->recv_rtcp_sink =
902 gst_element_get_request_pad (session->session, "recv_rtcp_sink");
903 if (session->recv_rtcp_sink == NULL)
907 /* get srcpad, link to SSRCDemux */
908 GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
909 session->recv_rtcp_src =
910 gst_element_get_static_pad (session->session, "sync_src");
911 if (session->recv_rtcp_src == NULL)
914 GST_DEBUG_OBJECT (rtpbin, "linking sync to demux");
915 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
916 lres = gst_pad_link (session->recv_rtcp_src, sinkdpad);
917 gst_object_unref (sinkdpad);
918 if (lres != GST_PAD_LINK_OK)
923 gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
924 gst_pad_set_active (result, TRUE);
925 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
932 g_warning ("rtpbin: invalid name given");
937 /* create_session already warned */
942 g_warning ("rtpbin: recv_rtcp pad already requested for session %d",
948 g_warning ("rtpbin: failed to get session pad");
954 g_warning ("rtpbin: failed to link pads");
960 /* Create a pad for sending RTP for the session in @name. Must be called with
964 create_send_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
966 GstPad *result, *srcghost;
969 GstRTPBinSession *session;
970 GstElementClass *klass;
972 /* first get the session number */
973 if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
976 /* get or create session */
977 session = find_session_by_id (rtpbin, sessid);
979 /* create session now */
980 session = create_session (rtpbin, sessid);
985 /* check if pad was requested */
986 if (session->send_rtp_sink != NULL)
989 /* get send_rtp pad and store */
990 session->send_rtp_sink =
991 gst_element_get_request_pad (session->session, "send_rtp_sink");
992 if (session->send_rtp_sink == NULL)
996 gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
997 gst_pad_set_active (result, TRUE);
998 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1001 session->send_rtp_src =
1002 gst_element_get_static_pad (session->session, "send_rtp_src");
1003 if (session->send_rtp_src == NULL)
1006 /* ghost the new source pad */
1007 klass = GST_ELEMENT_GET_CLASS (rtpbin);
1008 gname = g_strdup_printf ("send_rtp_src_%d", sessid);
1009 templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
1011 gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ);
1012 gst_pad_set_active (srcghost, TRUE);
1013 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
1021 g_warning ("rtpbin: invalid name given");
1026 /* create_session already warned */
1031 g_warning ("rtpbin: send_rtp pad already requested for session %d", sessid);
1036 g_warning ("rtpbin: failed to get session pad for session %d", sessid);
1041 g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
1046 /* Create a pad for sending RTCP for the session in @name. Must be called with
1050 create_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
1054 GstRTPBinSession *session;
1056 /* first get the session number */
1057 if (name == NULL || sscanf (name, "send_rtcp_src_%d", &sessid) != 1)
1060 /* get or create session */
1061 session = find_session_by_id (rtpbin, sessid);
1065 /* check if pad was requested */
1066 if (session->send_rtcp_src != NULL)
1069 /* get rtcp_src pad and store */
1070 session->send_rtcp_src =
1071 gst_element_get_request_pad (session->session, "send_rtcp_src");
1072 if (session->send_rtcp_src == NULL)
1076 gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ);
1077 gst_pad_set_active (result, TRUE);
1078 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
1085 g_warning ("rtpbin: invalid name given");
1090 g_warning ("rtpbin: session with id %d does not exist", sessid);
1095 g_warning ("rtpbin: send_rtcp_src pad already requested for session %d",
1101 g_warning ("rtpbin: failed to get rtcp pad for session %d", sessid);
1109 gst_rtp_bin_request_new_pad (GstElement * element,
1110 GstPadTemplate * templ, const gchar * name)
1113 GstElementClass *klass;
1116 g_return_val_if_fail (templ != NULL, NULL);
1117 g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
1119 rtpbin = GST_RTP_BIN (element);
1120 klass = GST_ELEMENT_GET_CLASS (element);
1122 GST_RTP_BIN_LOCK (rtpbin);
1124 /* figure out the template */
1125 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
1126 result = create_recv_rtp (rtpbin, templ, name);
1127 } else if (templ == gst_element_class_get_pad_template (klass,
1128 "recv_rtcp_sink_%d")) {
1129 result = create_recv_rtcp (rtpbin, templ, name);
1130 } else if (templ == gst_element_class_get_pad_template (klass,
1131 "send_rtp_sink_%d")) {
1132 result = create_send_rtp (rtpbin, templ, name);
1133 } else if (templ == gst_element_class_get_pad_template (klass,
1134 "send_rtcp_src_%d")) {
1135 result = create_rtcp (rtpbin, templ, name);
1137 goto wrong_template;
1139 GST_RTP_BIN_UNLOCK (rtpbin);
1146 GST_RTP_BIN_UNLOCK (rtpbin);
1147 g_warning ("rtpbin: this is not our template");
1153 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)