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_rtcp_src_template =
88 GST_STATIC_PAD_TEMPLATE ("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 struct _GstRTPBinPrivate
109 /* signals and args */
112 SIGNAL_REQUEST_PT_MAP,
122 typedef struct _GstRTPBinSession GstRTPBinSession;
123 typedef struct _GstRTPBinStream GstRTPBinStream;
124 typedef struct _GstRTPBinClient GstRTPBinClient;
126 static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
128 static GstCaps *pt_map_requested (GstElement * element, guint pt,
129 GstRTPBinStream * stream);
131 /* Manages the RTP stream for one SSRC.
133 * We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
134 * If we see an SDES RTCP packet that links multiple SSRCs together based on a
135 * common CNAME, we create a GstRTPBinClient structure to group the SSRCs
136 * together (see below).
138 struct _GstRTPBinStream
140 /* the SSRC of this stream */
144 /* the session this SSRC belongs to */
145 GstRTPBinSession *session;
146 /* the jitterbuffer of the SSRC */
148 /* the PT demuxer of the SSRC */
150 gulong demux_newpad_sig;
151 gulong demux_ptreq_sig;
154 /* Manages the receiving end of the packets.
156 * There is one such structure for each RTP session (audio/video/...).
157 * We get the RTP/RTCP packets and stuff them into the session manager. From
158 * there they are pushed into an SSRC demuxer that splits the stream based on
159 * SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
160 * the GstRTPBinStream above).
162 struct _GstRTPBinSession
168 /* the session element */
170 /* the SSRC demuxer */
172 gulong demux_newpad_sig;
174 /* list of GstRTPBinStream */
177 /* mapping of payload type to caps */
180 /* the pads of the session */
181 GstPad *recv_rtp_sink;
182 GstPad *recv_rtp_src;
183 GstPad *recv_rtcp_sink;
184 GstPad *recv_rtcp_src;
185 GstPad *send_rtp_sink;
186 GstPad *send_rtp_src;
190 /* find a session with the given id */
191 static GstRTPBinSession *
192 find_session_by_id (GstRTPBin * rtpbin, gint id)
196 for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
197 GstRTPBinSession *sess = (GstRTPBinSession *) walk->data;
205 /* create a session with the given id */
206 static GstRTPBinSession *
207 create_session (GstRTPBin * rtpbin, gint id)
209 GstRTPBinSession *sess;
210 GstElement *elem, *demux;
212 if (!(elem = gst_element_factory_make ("rtpsession", NULL)))
215 if (!(demux = gst_element_factory_make ("rtpssrcdemux", NULL)))
218 sess = g_new0 (GstRTPBinSession, 1);
221 sess->session = elem;
223 sess->ptmap = g_hash_table_new (NULL, NULL);
224 rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
226 gst_bin_add (GST_BIN_CAST (rtpbin), elem);
227 gst_element_set_state (elem, GST_STATE_PLAYING);
228 gst_bin_add (GST_BIN_CAST (rtpbin), demux);
229 gst_element_set_state (demux, GST_STATE_PLAYING);
236 g_warning ("rtpbin: could not create rtpsession element");
241 gst_object_unref (elem);
242 g_warning ("rtpbin: could not create rtpssrcdemux element");
248 static GstRTPBinStream *
249 find_stream_by_ssrc (GstRTPBinSession * session, guint32 ssrc)
253 for (walk = session->streams; walk; walk = g_slist_next (walk)) {
254 GstRTPBinStream *stream = (GstRTPBinStream *) walk->data;
256 if (stream->ssrc == ssrc)
263 /* get the payload type caps for the specific payload @pt in @session */
265 get_pt_map (GstRTPBinSession * session, guint pt)
267 GstCaps *caps = NULL;
270 GValue args[3] = { {0}, {0}, {0} };
272 GST_DEBUG ("searching pt %d in cache", pt);
274 /* first look in the cache */
275 caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
282 GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
284 /* not in cache, send signal to request caps */
285 g_value_init (&args[0], GST_TYPE_ELEMENT);
286 g_value_set_object (&args[0], bin);
287 g_value_init (&args[1], G_TYPE_UINT);
288 g_value_set_uint (&args[1], session->id);
289 g_value_init (&args[2], G_TYPE_UINT);
290 g_value_set_uint (&args[2], pt);
292 g_value_init (&ret, GST_TYPE_CAPS);
293 g_value_set_boxed (&ret, NULL);
295 g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
297 caps = (GstCaps *) g_value_get_boxed (&ret);
301 GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
304 g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
312 GST_DEBUG ("no pt map could be obtained");
317 static GstRTPBinStream *
318 create_stream (GstRTPBinSession * session, guint32 ssrc)
320 GstElement *buffer, *demux;
321 GstRTPBinStream *stream;
323 if (!(buffer = gst_element_factory_make ("rtpjitterbuffer", NULL)))
324 goto no_jitterbuffer;
326 if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
329 stream = g_new0 (GstRTPBinStream, 1);
331 stream->bin = session->bin;
332 stream->session = session;
333 stream->buffer = buffer;
334 stream->demux = demux;
335 session->streams = g_slist_prepend (session->streams, stream);
337 /* provide clock_rate to the jitterbuffer when needed */
338 g_signal_connect (buffer, "request-pt-map",
339 (GCallback) pt_map_requested, stream);
341 gst_bin_add (GST_BIN_CAST (session->bin), buffer);
342 gst_element_set_state (buffer, GST_STATE_PLAYING);
343 gst_bin_add (GST_BIN_CAST (session->bin), demux);
344 gst_element_set_state (demux, GST_STATE_PLAYING);
347 gst_element_link (buffer, demux);
354 g_warning ("rtpbin: could not create rtpjitterbuffer element");
359 gst_object_unref (buffer);
360 g_warning ("rtpbin: could not create rtpptdemux element");
365 /* Manages the RTP streams that come from one client and should therefore be
368 struct _GstRTPBinClient
370 /* the common CNAME for the streams */
376 /* GObject vmethods */
377 static void gst_rtp_bin_finalize (GObject * object);
378 static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
379 const GValue * value, GParamSpec * pspec);
380 static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
381 GValue * value, GParamSpec * pspec);
383 /* GstElement vmethods */
384 static GstClock *gst_rtp_bin_provide_clock (GstElement * element);
385 static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
386 GstStateChange transition);
387 static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
388 GstPadTemplate * templ, const gchar * name);
389 static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
391 GST_BOILERPLATE (GstRTPBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
394 gst_rtp_bin_base_init (gpointer klass)
396 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
399 gst_element_class_add_pad_template (element_class,
400 gst_static_pad_template_get (&rtpbin_recv_rtp_sink_template));
401 gst_element_class_add_pad_template (element_class,
402 gst_static_pad_template_get (&rtpbin_recv_rtcp_sink_template));
403 gst_element_class_add_pad_template (element_class,
404 gst_static_pad_template_get (&rtpbin_send_rtp_sink_template));
407 gst_element_class_add_pad_template (element_class,
408 gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
409 gst_element_class_add_pad_template (element_class,
410 gst_static_pad_template_get (&rtpbin_rtcp_src_template));
411 gst_element_class_add_pad_template (element_class,
412 gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
414 gst_element_class_set_details (element_class, &rtpbin_details);
418 gst_rtp_bin_class_init (GstRTPBinClass * klass)
420 GObjectClass *gobject_class;
421 GstElementClass *gstelement_class;
423 gobject_class = (GObjectClass *) klass;
424 gstelement_class = (GstElementClass *) klass;
426 g_type_class_add_private (klass, sizeof (GstRTPBinPrivate));
428 gobject_class->finalize = gst_rtp_bin_finalize;
429 gobject_class->set_property = gst_rtp_bin_set_property;
430 gobject_class->get_property = gst_rtp_bin_get_property;
433 * GstRTPBin::request-pt-map:
434 * @rtpbin: the object which received the signal
435 * @session: the session
438 * Request the payload type as #GstCaps for @pt in @session.
440 gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
441 g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
442 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPBinClass, request_pt_map),
443 NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2,
444 G_TYPE_UINT, G_TYPE_UINT);
446 gstelement_class->provide_clock =
447 GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
448 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
449 gstelement_class->request_new_pad =
450 GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
451 gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
453 GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
457 gst_rtp_bin_init (GstRTPBin * rtpbin, GstRTPBinClass * klass)
459 rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
460 rtpbin->provided_clock = gst_system_clock_obtain ();
464 gst_rtp_bin_finalize (GObject * object)
468 rtpbin = GST_RTP_BIN (object);
470 G_OBJECT_CLASS (parent_class)->finalize (object);
474 gst_rtp_bin_set_property (GObject * object, guint prop_id,
475 const GValue * value, GParamSpec * pspec)
479 rtpbin = GST_RTP_BIN (object);
483 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
489 gst_rtp_bin_get_property (GObject * object, guint prop_id,
490 GValue * value, GParamSpec * pspec)
494 rtpbin = GST_RTP_BIN (object);
498 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
504 gst_rtp_bin_provide_clock (GstElement * element)
508 rtpbin = GST_RTP_BIN (element);
510 return GST_CLOCK_CAST (gst_object_ref (rtpbin->provided_clock));
513 static GstStateChangeReturn
514 gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
516 GstStateChangeReturn res;
519 rtpbin = GST_RTP_BIN (element);
521 switch (transition) {
522 case GST_STATE_CHANGE_NULL_TO_READY:
524 case GST_STATE_CHANGE_READY_TO_PAUSED:
526 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
532 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
534 switch (transition) {
535 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
537 case GST_STATE_CHANGE_PAUSED_TO_READY:
539 case GST_STATE_CHANGE_READY_TO_NULL:
547 /* a new pad (SSRC) was created in @session */
549 new_payload_found (GstElement * element, guint pt, GstPad * pad,
550 GstRTPBinStream * stream)
553 GstElementClass *klass;
554 GstPadTemplate *templ;
558 rtpbin = stream->bin;
560 GST_DEBUG ("new payload pad %d", pt);
562 /* ghost the pad to the parent */
563 klass = GST_ELEMENT_GET_CLASS (rtpbin);
564 templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
565 padname = g_strdup_printf ("recv_rtp_src_%d_%u_%d",
566 stream->session->id, stream->ssrc, pt);
567 gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
570 gst_pad_set_active (gpad, TRUE);
571 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
575 pt_map_requested (GstElement * element, guint pt, GstRTPBinStream * stream)
578 GstRTPBinSession *session;
581 rtpbin = stream->bin;
582 session = stream->session;
584 GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
587 caps = get_pt_map (session, pt);
596 GST_DEBUG_OBJECT (rtpbin, "could not get caps");
601 /* a new pad (SSRC) was created in @session */
603 new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
604 GstRTPBinSession * session)
606 GstRTPBinStream *stream;
609 GST_DEBUG_OBJECT (session->bin, "new SSRC pad %08x", ssrc);
611 /* create new stream */
612 stream = create_stream (session, ssrc);
616 /* get pad and link */
617 GST_DEBUG_OBJECT (session->bin, "linking jitterbuffer");
618 sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
619 gst_pad_link (pad, sinkpad);
620 gst_object_unref (sinkpad);
622 /* connect to the new-pad signal of the payload demuxer, this will expose the
623 * new pad by ghosting it. */
624 stream->demux_newpad_sig = g_signal_connect (stream->demux,
625 "new-payload-type", (GCallback) new_payload_found, stream);
626 /* connect to the request-pt-map signal. This signal will be emited by the
627 * demuxer so that it can apply a proper caps on the buffers for the
629 stream->demux_ptreq_sig = g_signal_connect (stream->demux,
630 "request-pt-map", (GCallback) pt_map_requested, stream);
637 GST_DEBUG ("could not create stream");
642 /* Create a pad for receiving RTP for the session in @name
645 create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
647 GstPad *result, *sinkdpad;
649 GstRTPBinSession *session;
650 GstPadLinkReturn lres;
652 /* first get the session number */
653 if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
656 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
658 /* get or create session */
659 session = find_session_by_id (rtpbin, sessid);
661 GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
662 /* create session now */
663 session = create_session (rtpbin, sessid);
667 /* check if pad was requested */
668 if (session->recv_rtp_sink != NULL)
671 GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
672 /* get recv_rtp pad and store */
673 session->recv_rtp_sink =
674 gst_element_get_request_pad (session->session, "recv_rtp_sink");
675 if (session->recv_rtp_sink == NULL)
678 GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
679 /* get srcpad, link to SSRCDemux */
680 session->recv_rtp_src =
681 gst_element_get_static_pad (session->session, "recv_rtp_src");
682 if (session->recv_rtp_src == NULL)
685 GST_DEBUG_OBJECT (rtpbin, "getting demuxer sink pad");
686 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
687 lres = gst_pad_link (session->recv_rtp_src, sinkdpad);
688 gst_object_unref (sinkdpad);
689 if (lres != GST_PAD_LINK_OK)
692 /* connect to the new-ssrc-pad signal of the SSRC demuxer */
693 session->demux_newpad_sig = g_signal_connect (session->demux,
694 "new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
696 GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
698 gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
699 gst_pad_set_active (result, TRUE);
700 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
707 g_warning ("rtpbin: invalid name given");
712 /* create_session already warned */
717 g_warning ("rtpbin: recv_rtp pad already requested for session %d", sessid);
722 g_warning ("rtpbin: failed to get session pad");
727 g_warning ("rtpbin: failed to link pads");
732 /* Create a pad for receiving RTCP for the session in @name
735 create_recv_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ,
740 GstRTPBinSession *session;
744 GstPadLinkReturn lres;
747 /* first get the session number */
748 if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
751 GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
753 /* get the session, it must exist or we error */
754 session = find_session_by_id (rtpbin, sessid);
758 /* check if pad was requested */
759 if (session->recv_rtcp_sink != NULL)
762 GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
764 /* get recv_rtp pad and store */
765 session->recv_rtcp_sink =
766 gst_element_get_request_pad (session->session, "recv_rtcp_sink");
767 if (session->recv_rtcp_sink == NULL)
771 /* get srcpad, link to SSRCDemux */
772 GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
773 session->recv_rtcp_src =
774 gst_element_get_static_pad (session->session, "sync_src");
775 if (session->recv_rtcp_src == NULL)
778 GST_DEBUG_OBJECT (rtpbin, "linking sync to demux");
779 sinkdpad = gst_element_get_static_pad (session->demux, "sink");
780 lres = gst_pad_link (session->recv_rtcp_src, sinkdpad);
781 gst_object_unref (sinkdpad);
782 if (lres != GST_PAD_LINK_OK)
787 gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
788 gst_pad_set_active (result, TRUE);
789 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
796 g_warning ("rtpbin: invalid name given");
801 g_warning ("rtpbin: no session with id %d", sessid);
806 g_warning ("rtpbin: recv_rtcp pad already requested for session %d",
812 g_warning ("rtpbin: failed to get session pad");
818 g_warning ("rtpbin: failed to link pads");
824 /* Create a pad for sending RTP for the session in @name
827 create_send_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
829 GstPad *result, *srcpad, *srcghost;
832 GstRTPBinSession *session;
833 GstElementClass *klass;
835 /* first get the session number */
836 if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
839 /* get or create session */
840 session = find_session_by_id (rtpbin, sessid);
842 /* create session now */
843 session = create_session (rtpbin, sessid);
848 /* check if pad was requested */
849 if (session->send_rtp_sink != NULL)
852 /* get recv_rtp pad and store */
853 session->send_rtp_sink =
854 gst_element_get_request_pad (session->session, "send_rtp_sink");
855 if (session->send_rtp_sink == NULL)
859 gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
860 gst_pad_set_active (result, TRUE);
861 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
864 srcpad = gst_element_get_pad (session->session, "send_rtp_src");
868 /* ghost the new source pad */
869 klass = GST_ELEMENT_GET_CLASS (rtpbin);
870 gname = g_strdup_printf ("send_rtp_src_%d", sessid);
871 templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
873 gst_ghost_pad_new_from_template (gname, session->send_rtp_sink, templ);
874 gst_pad_set_active (srcghost, TRUE);
875 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
883 g_warning ("rtpbin: invalid name given");
888 /* create_session already warned */
893 g_warning ("rtpbin: send_rtp pad already requested for session %d", sessid);
898 g_warning ("rtpbin: failed to get session pad for session %d", sessid);
903 g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
908 /* Create a pad for sending RTCP for the session in @name
911 create_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
915 GstRTPBinSession *session;
917 /* first get the session number */
918 if (name == NULL || sscanf (name, "rtcp_src_%d", &sessid) != 1)
921 /* get or create session */
922 session = find_session_by_id (rtpbin, sessid);
926 /* check if pad was requested */
927 if (session->rtcp_src != NULL)
930 /* get rtcp_src pad and store */
932 gst_element_get_request_pad (session->session, "rtcp_src");
933 if (session->rtcp_src == NULL)
936 result = gst_ghost_pad_new_from_template (name, session->rtcp_src, templ);
937 gst_pad_set_active (result, TRUE);
938 gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
945 g_warning ("rtpbin: invalid name given");
950 g_warning ("rtpbin: session with id %d does not exist", sessid);
955 g_warning ("rtpbin: rtcp_src pad already requested for session %d", sessid);
960 g_warning ("rtpbin: failed to get rtcp pad for session %d", sessid);
968 gst_rtp_bin_request_new_pad (GstElement * element,
969 GstPadTemplate * templ, const gchar * name)
972 GstElementClass *klass;
975 g_return_val_if_fail (templ != NULL, NULL);
976 g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
978 rtpbin = GST_RTP_BIN (element);
979 klass = GST_ELEMENT_GET_CLASS (element);
981 /* figure out the template */
982 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
983 result = create_recv_rtp (rtpbin, templ, name);
984 } else if (templ == gst_element_class_get_pad_template (klass,
985 "recv_rtcp_sink_%d")) {
986 result = create_recv_rtcp (rtpbin, templ, name);
987 } else if (templ == gst_element_class_get_pad_template (klass,
988 "send_rtp_sink_%d")) {
989 result = create_send_rtp (rtpbin, templ, name);
990 } else if (templ == gst_element_class_get_pad_template (klass, "rtcp_src_%d")) {
991 result = create_rtcp (rtpbin, templ, name);
1000 g_warning ("rtpbin: this is not our template");
1006 gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)