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, rtpclient, rtpsession
28 * <title>Example pipelines</title>
31 * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
36 * Last reviewed on 2007-04-02 (0.10.6)
44 #include "gstrtpbin-marshal.h"
45 #include "gstrtpbin.h"
47 GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
48 #define GST_CAT_DEFAULT gst_rtp_bin_debug
51 /* elementfactory information */
52 static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin",
53 "Filter/Editor/Video",
54 "Implement an RTP bin",
55 "Wim Taymans <wim@fluendo.com>");
58 static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
59 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%d",
62 GST_STATIC_CAPS ("application/x-rtp")
65 static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
66 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%d",
69 GST_STATIC_CAPS ("application/x-rtcp")
72 static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
73 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%d",
76 GST_STATIC_CAPS ("application/x-rtp")
80 static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
81 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
84 GST_STATIC_CAPS ("application/x-rtp")
87 static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
88 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
91 GST_STATIC_CAPS ("application/x-rtcp")
94 static GstStaticPadTemplate rtpbin_send_rtp_src_template =
95 GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%d",
98 GST_STATIC_CAPS ("application/x-rtp")
101 #define GST_RTP_BIN_GET_PRIVATE(obj) \
102 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRTPBinPrivate))
104 #define GST_RTP_BIN_LOCK(bin) g_mutex_lock ((bin)->priv->bin_lock)
105 #define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock ((bin)->priv->bin_lock)
107 struct _GstRTPBinPrivate
112 /* signals and args */
115 SIGNAL_REQUEST_PT_MAP,
119 #define DEFAULT_LATENCY_MS 200
128 typedef struct _GstRTPBinSession GstRTPBinSession;
129 typedef struct _GstRTPBinStream GstRTPBinStream;
130 typedef struct _GstRTPBinClient GstRTPBinClient;
132 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
134 static GstCaps *pt_map_requested (GstElement * element, guint pt,
135 GstRTPBinSession * session);
137 /* Manages the RTP stream for one SSRC.
139 * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
140 * If we see an SDES RTCP packet that links multiple SSRCs together based on a
141 * common CNAME, we create a GstRTPBinClient structure to group the SSRCs
142 * together (see below).
144 struct _GstRTPBinStream
146 /* the SSRC of this stream */
150 /* the session this SSRC belongs to */
151 GstRTPBinSession *session;
152 /* the jitterbuffer of the SSRC */
154 /* the PT demuxer of the SSRC */
156 gulong demux_newpad_sig;
157 gulong demux_ptreq_sig;
160 #define GST_RTP_SESSION_LOCK(sess) g_mutex_lock ((sess)->lock)
161 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->lock)
163 /* Manages the receiving end of the packets.
165 * There is one such structure for each RTP session (audio/video/...).
166 * We get the RTP/RTCP packets and stuff them into the session manager. From
167 * there they are pushed into an SSRC demuxer that splits the stream based on
168 * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
169 * the GstRTPBinStream above).
171 struct _GstRTPBinSession
177 /* the session element */
179 /* the SSRC demuxer */
181 gulong demux_newpad_sig;
185 /* list of GstRTPBinStream */
188 /* mapping of payload type to caps */
191 /* the pads of the session */
192 GstPad *recv_rtp_sink;
193 GstPad *recv_rtp_src;
194 GstPad *recv_rtcp_sink;
195 GstPad *recv_rtcp_src;
196 GstPad *send_rtp_sink;
197 GstPad *send_rtp_src;
198 GstPad *send_rtcp_src;
201 /* find a session with the given id. Must be called with RTP_BIN_LOCK */
202 static GstRTPBinSession *
203 find_session_by_id (GstRTPBin * rtpbin, gint id)
207 for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
208 GstRTPBinSession *sess = (GstRTPBinSession *) walk->data;
216 /* create a session with the given id. Must be called with RTP_BIN_LOCK */
217 static GstRTPBinSession *
218 create_session (GstRTPBin * rtpbin, gint id)
220 GstRTPBinSession *sess;
221 GstElement *session, *demux;
223 if (!(session = gst_element_factory_make ("rtpsession", NULL)))
226 if (!(demux = gst_element_factory_make ("rtpssrcdemux", NULL)))
229 sess = g_new0 (GstRTPBinSession, 1);
230 sess->lock = g_mutex_new ();
233 sess->session = session;
235 sess->ptmap = g_hash_table_new (NULL, NULL);
236 rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
238 /* provide clock_rate to the session manager when needed */
239 g_signal_connect (session, "request-pt-map",
240 (GCallback) pt_map_requested, sess);
242 gst_bin_add (GST_BIN_CAST (rtpbin), session);
243 gst_element_set_state (session, GST_STATE_PLAYING);
244 gst_bin_add (GST_BIN_CAST (rtpbin), demux);
245 gst_element_set_state (demux, GST_STATE_PLAYING);
252 g_warning ("rtpbin: could not create rtpsession element");
257 gst_object_unref (session);
258 g_warning ("rtpbin: could not create rtpssrcdemux element");
264 static GstRTPBinStream *
265 find_stream_by_ssrc (GstRTPBinSession * session, guint32 ssrc)
269 for (walk = session->streams; walk; walk = g_slist_next (walk)) {
270 GstRTPBinStream *stream = (GstRTPBinStream *) walk->data;
272 if (stream->ssrc == ssrc)
279 /* get the payload type caps for the specific payload @pt in @session */
281 get_pt_map (GstRTPBinSession * session, guint pt)
283 GstCaps *caps = NULL;
286 GValue args[3] = { {0}, {0}, {0} };
288 GST_DEBUG ("searching pt %d in cache", pt);
290 GST_RTP_SESSION_LOCK (session);
292 /* first look in the cache */
293 caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
299 GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
301 /* not in cache, send signal to request caps */
302 g_value_init (&args[0], GST_TYPE_ELEMENT);
303 g_value_set_object (&args[0], bin);
304 g_value_init (&args[1], G_TYPE_UINT);
305 g_value_set_uint (&args[1], session->id);
306 g_value_init (&args[2], G_TYPE_UINT);
307 g_value_set_uint (&args[2], pt);
309 g_value_init (&ret, GST_TYPE_CAPS);
310 g_value_set_boxed (&ret, NULL);
312 g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
314 caps = (GstCaps *) g_value_get_boxed (&ret);
318 GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
321 g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
324 GST_RTP_SESSION_UNLOCK (session);
331 GST_RTP_SESSION_UNLOCK (session);
332 GST_DEBUG ("no pt map could be obtained");
337 /* create a new stream with @ssrc in @session. Must be called with
338 * RTP_SESSION_LOCK. */
339 static GstRTPBinStream *
340 create_stream (GstRTPBinSession * session, guint32 ssrc)
342 GstElement *buffer, *demux;
343 GstRTPBinStream *stream;
345 if (!(buffer = gst_element_factory_make ("rtpjitterbuffer", NULL)))
346 goto no_jitterbuffer;
348 if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
351 stream = g_new0 (GstRTPBinStream, 1);
353 stream->bin = session->bin;
354 stream->session = session;
355 stream->buffer = buffer;
356 stream->demux = demux;
357 session->streams = g_slist_prepend (session->streams, stream);
359 /* provide clock_rate to the jitterbuffer when needed */
360 g_signal_connect (buffer, "request-pt-map",
361 (GCallback) pt_map_requested, session);
363 /* configure latency */
364 g_object_set (buffer, "latency", session->bin->latency, NULL);
366 gst_bin_add (GST_BIN_CAST (session->bin), buffer);
367 gst_element_set_state (buffer, GST_STATE_PLAYING);
368 gst_bin_add (GST_BIN_CAST (session->bin), demux);
369 gst_element_set_state (demux, GST_STATE_PLAYING);
372 gst_element_link (buffer, demux);
379 g_warning ("rtpbin: could not create rtpjitterbuffer element");
384 gst_object_unref (buffer);
385 g_warning ("rtpbin: could not create rtpptdemux element");
390 /* Manages the RTP streams that come from one client and should therefore be
393 struct _GstRTPBinClient
395 /* the common CNAME for the streams */
401 /* GObject vmethods */
402 static void gst_rtp_bin_finalize (GObject * object);
403 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
404 const GValue * value, GParamSpec * pspec);
405 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
406 GValue * value, GParamSpec * pspec);
408 /* GstElement vmethods */
409 static GstClock *gst_rtp_bin_provide_clock (GstElement * element);
410 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
411 GstStateChange transition);
412 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
413 GstPadTemplate * templ, const gchar * name);
414 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
416 GST_BOILERPLATE (GstRTPBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
419 gst_rtp_bin_base_init (gpointer klass)
421 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
424 gst_element_class_add_pad_template (element_class,
425 gst_static_pad_template_get (&rtpbin_recv_rtp_sink_template));
426 gst_element_class_add_pad_template (element_class,
427 gst_static_pad_template_get (&rtpbin_recv_rtcp_sink_template));
428 gst_element_class_add_pad_template (element_class,
429 gst_static_pad_template_get (&rtpbin_send_rtp_sink_template));
432 gst_element_class_add_pad_template (element_class,
433 gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
434 gst_element_class_add_pad_template (element_class,
435 gst_static_pad_template_get (&rtpbin_send_rtcp_src_template));
436 gst_element_class_add_pad_template (element_class,
437 gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
439 gst_element_class_set_details (element_class, &rtpbin_details);
443 gst_rtp_bin_class_init (GstRTPBinClass * klass)
445 GObjectClass *gobject_class;
446 GstElementClass *gstelement_class;
448 gobject_class = (GObjectClass *) klass;
449 gstelement_class = (GstElementClass *) klass;
451 g_type_class_add_private (klass, sizeof (GstRTPBinPrivate));
453 gobject_class->finalize = gst_rtp_bin_finalize;
454 gobject_class->set_property = gst_rtp_bin_set_property;
455 gobject_class->get_property = gst_rtp_bin_get_property;
457 g_object_class_install_property (gobject_class, PROP_LATENCY,
458 g_param_spec_uint ("latency", "Buffer latency in ms",
459 "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS,
463 * GstRTPBin::request-pt-map:
464 * @rtpbin: the object which received the signal
465 * @session: the session
468 * Request the payload type as #GstCaps for @pt in @session.
470 gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
471 g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
472 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, request_pt_map),
473 NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2,
474 G_TYPE_UINT, G_TYPE_UINT);
476 gstelement_class->provide_clock =
477 GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
478 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
479 gstelement_class->request_new_pad =
480 GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
481 gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
483 GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
487 gst_rtp_bin_init (GstRTPBin * rtpbin, GstRTPBinClass * klass)
489 rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
490 rtpbin->priv->bin_lock = g_mutex_new ();
491 rtpbin->provided_clock = gst_system_clock_obtain ();
495 gst_rtp_bin_finalize (GObject * object)
499 rtpbin = GST_RTP_BIN (object);
501 g_mutex_free (rtpbin->priv->bin_lock);
503 G_OBJECT_CLASS (parent_class)->finalize (object);
507 gst_rtp_bin_set_property (GObject * object, guint prop_id,
508 const GValue * value, GParamSpec * pspec)
512 rtpbin = GST_RTP_BIN (object);
516 rtpbin->latency = g_value_get_uint (value);
519 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
525 gst_rtp_bin_get_property (GObject * object, guint prop_id,
526 GValue * value, GParamSpec * pspec)
530 rtpbin = GST_RTP_BIN (object);
534 g_value_set_uint (value, rtpbin->latency);
537 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
543 gst_rtp_bin_provide_clock (GstElement * element)
547 rtpbin = GST_RTP_BIN (element);
549 return GST_CLOCK_CAST (gst_object_ref (rtpbin->provided_clock));
552 static GstStateChangeReturn
553 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
555 GstStateChangeReturn res;
558 rtpbin = GST_RTP_BIN (element);
560 switch (transition) {
561 case GST_STATE_CHANGE_NULL_TO_READY:
563 case GST_STATE_CHANGE_READY_TO_PAUSED:
565 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
571 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
573 switch (transition) {
574 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
576 case GST_STATE_CHANGE_PAUSED_TO_READY:
578 case GST_STATE_CHANGE_READY_TO_NULL:
586 /* a new pad (SSRC) was created in @session */
588 new_payload_found (GstElement * element, guint pt, GstPad * pad,
589 GstRTPBinStream * stream)
592 GstElementClass *klass;
593 GstPadTemplate *templ;
597 rtpbin = stream->bin;
599 GST_DEBUG ("new payload pad %d", pt);
601 /* ghost the pad to the parent */
602 klass = GST_ELEMENT_GET_CLASS (rtpbin);
603 templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
604 padname = g_strdup_printf ("recv_rtp_src_%d_%u_%d",
605 stream->session->id, stream->ssrc, pt);
606 gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
609 gst_pad_set_active (gpad, TRUE);
610 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
614 pt_map_requested (GstElement * element, guint pt, GstRTPBinSession * session)
619 rtpbin = session->bin;
621 GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
624 caps = get_pt_map (session, pt);
633 GST_DEBUG_OBJECT (rtpbin, "could not get caps");
638 /* a new pad (SSRC) was created in @session */
640 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
641 GstRTPBinSession * session)
643 GstRTPBinStream *stream;
646 GST_DEBUG_OBJECT (session->bin, "new SSRC pad %08x", ssrc);
648 GST_RTP_SESSION_LOCK (session);
650 /* create new stream */
651 stream = create_stream (session, ssrc);
655 /* get pad and link */
656 GST_DEBUG_OBJECT (session->bin, "linking jitterbuffer");
657 sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
658 gst_pad_link (pad, sinkpad);
659 gst_object_unref (sinkpad);
661 /* connect to the new-pad signal of the payload demuxer, this will expose the
662 * new pad by ghosting it. */
663 stream->demux_newpad_sig = g_signal_connect (stream->demux,
664 "new-payload-type", (GCallback) new_payload_found, stream);
665 /* connect to the request-pt-map signal. This signal will be emited by the
666 * demuxer so that it can apply a proper caps on the buffers for the
668 stream->demux_ptreq_sig = g_signal_connect (stream->demux,
669 "request-pt-map", (GCallback) pt_map_requested, session);
671 GST_RTP_SESSION_UNLOCK (session);
678 GST_RTP_SESSION_UNLOCK (session);
679 GST_DEBUG ("could not create stream");
684 /* Create a pad for receiving RTP for the session in @name. Must be called with
688 create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
690 GstPad *result, *sinkdpad;
692 GstRTPBinSession *session;
693 GstPadLinkReturn lres;
695 /* first get the session number */
696 if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
699 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
701 /* get or create session */
702 session = find_session_by_id (rtpbin, sessid);
704 GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
705 /* create session now */
706 session = create_session (rtpbin, sessid);
711 /* check if pad was requested */
712 if (session->recv_rtp_sink != NULL)
715 GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
716 /* get recv_rtp pad and store */
717 session->recv_rtp_sink =
718 gst_element_get_request_pad (session->session, "recv_rtp_sink");
719 if (session->recv_rtp_sink == NULL)
722 GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
723 /* get srcpad, link to SSRCDemux */
724 session->recv_rtp_src =
725 gst_element_get_static_pad (session->session, "recv_rtp_src");
726 if (session->recv_rtp_src == NULL)
729 GST_DEBUG_OBJECT (rtpbin, "getting demuxer sink pad");
730 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
731 lres = gst_pad_link (session->recv_rtp_src, sinkdpad);
732 gst_object_unref (sinkdpad);
733 if (lres != GST_PAD_LINK_OK)
736 /* connect to the new-ssrc-pad signal of the SSRC demuxer */
737 session->demux_newpad_sig = g_signal_connect (session->demux,
738 "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
740 GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
742 gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
743 gst_pad_set_active (result, TRUE);
744 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
751 g_warning ("rtpbin: invalid name given");
756 /* create_session already warned */
761 g_warning ("rtpbin: recv_rtp pad already requested for session %d", sessid);
766 g_warning ("rtpbin: failed to get session pad");
771 g_warning ("rtpbin: failed to link pads");
776 /* Create a pad for receiving RTCP for the session in @name. Must be called with
780 create_recv_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ,
785 GstRTPBinSession *session;
789 GstPadLinkReturn lres;
792 /* first get the session number */
793 if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
796 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
798 /* get or create the session */
799 session = find_session_by_id (rtpbin, sessid);
801 GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
802 /* create session now */
803 session = create_session (rtpbin, sessid);
808 /* check if pad was requested */
809 if (session->recv_rtcp_sink != NULL)
812 GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
814 /* get recv_rtp pad and store */
815 session->recv_rtcp_sink =
816 gst_element_get_request_pad (session->session, "recv_rtcp_sink");
817 if (session->recv_rtcp_sink == NULL)
821 /* get srcpad, link to SSRCDemux */
822 GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
823 session->recv_rtcp_src =
824 gst_element_get_static_pad (session->session, "sync_src");
825 if (session->recv_rtcp_src == NULL)
828 GST_DEBUG_OBJECT (rtpbin, "linking sync to demux");
829 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
830 lres = gst_pad_link (session->recv_rtcp_src, sinkdpad);
831 gst_object_unref (sinkdpad);
832 if (lres != GST_PAD_LINK_OK)
837 gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
838 gst_pad_set_active (result, TRUE);
839 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
846 g_warning ("rtpbin: invalid name given");
851 /* create_session already warned */
856 g_warning ("rtpbin: recv_rtcp pad already requested for session %d",
862 g_warning ("rtpbin: failed to get session pad");
868 g_warning ("rtpbin: failed to link pads");
874 /* Create a pad for sending RTP for the session in @name. Must be called with
878 create_send_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
880 GstPad *result, *srcghost;
883 GstRTPBinSession *session;
884 GstElementClass *klass;
886 /* first get the session number */
887 if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
890 /* get or create session */
891 session = find_session_by_id (rtpbin, sessid);
893 /* create session now */
894 session = create_session (rtpbin, sessid);
899 /* check if pad was requested */
900 if (session->send_rtp_sink != NULL)
903 /* get send_rtp pad and store */
904 session->send_rtp_sink =
905 gst_element_get_request_pad (session->session, "send_rtp_sink");
906 if (session->send_rtp_sink == NULL)
910 gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
911 gst_pad_set_active (result, TRUE);
912 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
915 session->send_rtp_src =
916 gst_element_get_static_pad (session->session, "send_rtp_src");
917 if (session->send_rtp_src == NULL)
920 /* ghost the new source pad */
921 klass = GST_ELEMENT_GET_CLASS (rtpbin);
922 gname = g_strdup_printf ("send_rtp_src_%d", sessid);
923 templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
925 gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ);
926 gst_pad_set_active (srcghost, TRUE);
927 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
935 g_warning ("rtpbin: invalid name given");
940 /* create_session already warned */
945 g_warning ("rtpbin: send_rtp pad already requested for session %d", sessid);
950 g_warning ("rtpbin: failed to get session pad for session %d", sessid);
955 g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
960 /* Create a pad for sending RTCP for the session in @name. Must be called with
964 create_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
968 GstRTPBinSession *session;
970 /* first get the session number */
971 if (name == NULL || sscanf (name, "send_rtcp_src_%d", &sessid) != 1)
974 /* get or create session */
975 session = find_session_by_id (rtpbin, sessid);
979 /* check if pad was requested */
980 if (session->send_rtcp_src != NULL)
983 /* get rtcp_src pad and store */
984 session->send_rtcp_src =
985 gst_element_get_request_pad (session->session, "send_rtcp_src");
986 if (session->send_rtcp_src == NULL)
990 gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ);
991 gst_pad_set_active (result, TRUE);
992 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
999 g_warning ("rtpbin: invalid name given");
1004 g_warning ("rtpbin: session with id %d does not exist", sessid);
1009 g_warning ("rtpbin: send_rtcp_src pad already requested for session %d",
1015 g_warning ("rtpbin: failed to get rtcp pad for session %d", sessid);
1023 gst_rtp_bin_request_new_pad (GstElement * element,
1024 GstPadTemplate * templ, const gchar * name)
1027 GstElementClass *klass;
1030 g_return_val_if_fail (templ != NULL, NULL);
1031 g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
1033 rtpbin = GST_RTP_BIN (element);
1034 klass = GST_ELEMENT_GET_CLASS (element);
1036 GST_RTP_BIN_LOCK (rtpbin);
1038 /* figure out the template */
1039 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
1040 result = create_recv_rtp (rtpbin, templ, name);
1041 } else if (templ == gst_element_class_get_pad_template (klass,
1042 "recv_rtcp_sink_%d")) {
1043 result = create_recv_rtcp (rtpbin, templ, name);
1044 } else if (templ == gst_element_class_get_pad_template (klass,
1045 "send_rtp_sink_%d")) {
1046 result = create_send_rtp (rtpbin, templ, name);
1047 } else if (templ == gst_element_class_get_pad_template (klass,
1048 "send_rtcp_src_%d")) {
1049 result = create_rtcp (rtpbin, templ, name);
1051 goto wrong_template;
1053 GST_RTP_BIN_UNLOCK (rtpbin);
1060 GST_RTP_BIN_UNLOCK (rtpbin);
1061 g_warning ("rtpbin: this is not our template");
1067 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)