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-rtpsession
22 * @short_description: an RTP session manager
23 * @see_also: rtpjitterbuffer, rtpbin
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)
43 #include "gstrtpbin-marshal.h"
44 #include "gstrtpsession.h"
45 #include "rtpsession.h"
47 GST_DEBUG_CATEGORY_STATIC (gst_rtp_session_debug);
48 #define GST_CAT_DEFAULT gst_rtp_session_debug
50 /* elementfactory information */
51 static const GstElementDetails rtpsession_details =
52 GST_ELEMENT_DETAILS ("RTP Session",
53 "Filter/Editor/Video",
54 "Implement an RTP session",
55 "Wim Taymans <wim@fluendo.com>");
58 static GstStaticPadTemplate rtpsession_recv_rtp_sink_template =
59 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink",
62 GST_STATIC_CAPS ("application/x-rtp")
65 static GstStaticPadTemplate rtpsession_recv_rtcp_sink_template =
66 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink",
69 GST_STATIC_CAPS ("application/x-rtcp")
72 static GstStaticPadTemplate rtpsession_send_rtp_sink_template =
73 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink",
76 GST_STATIC_CAPS ("application/x-rtp")
80 static GstStaticPadTemplate rtpsession_recv_rtp_src_template =
81 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src",
84 GST_STATIC_CAPS ("application/x-rtp")
87 static GstStaticPadTemplate rtpsession_sync_src_template =
88 GST_STATIC_PAD_TEMPLATE ("sync_src",
91 GST_STATIC_CAPS ("application/x-rtcp")
94 static GstStaticPadTemplate rtpsession_send_rtp_src_template =
95 GST_STATIC_PAD_TEMPLATE ("send_rtp_src",
98 GST_STATIC_CAPS ("application/x-rtp")
101 static GstStaticPadTemplate rtpsession_send_rtcp_src_template =
102 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src",
105 GST_STATIC_CAPS ("application/x-rtcp")
108 /* signals and args */
111 SIGNAL_REQUEST_PT_MAP,
120 #define GST_RTP_SESSION_GET_PRIVATE(obj) \
121 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_SESSION, GstRTPSessionPrivate))
123 #define GST_RTP_SESSION_LOCK(sess) g_mutex_lock ((sess)->priv->lock)
124 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->priv->lock)
126 struct _GstRTPSessionPrivate
130 /* thread for sending out RTCP */
132 gboolean stop_thread;
136 /* callbacks to handle actions from the session manager */
137 static GstFlowReturn gst_rtp_session_process_rtp (RTPSession * sess,
138 RTPSource * src, GstBuffer * buffer, gpointer user_data);
139 static GstFlowReturn gst_rtp_session_send_rtp (RTPSession * sess,
140 RTPSource * src, GstBuffer * buffer, gpointer user_data);
141 static GstFlowReturn gst_rtp_session_send_rtcp (RTPSession * sess,
142 RTPSource * src, GstBuffer * buffer, gpointer user_data);
143 static gint gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload,
145 static GstClockTime gst_rtp_session_get_time (RTPSession * sess,
147 static void gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data);
149 static RTPSessionCallbacks callbacks = {
150 gst_rtp_session_process_rtp,
151 gst_rtp_session_send_rtp,
152 gst_rtp_session_send_rtcp,
153 gst_rtp_session_clock_rate,
154 gst_rtp_session_get_time,
155 gst_rtp_session_reconsider
158 /* GObject vmethods */
159 static void gst_rtp_session_finalize (GObject * object);
160 static void gst_rtp_session_set_property (GObject * object, guint prop_id,
161 const GValue * value, GParamSpec * pspec);
162 static void gst_rtp_session_get_property (GObject * object, guint prop_id,
163 GValue * value, GParamSpec * pspec);
165 /* GstElement vmethods */
166 static GstStateChangeReturn gst_rtp_session_change_state (GstElement * element,
167 GstStateChange transition);
168 static GstPad *gst_rtp_session_request_new_pad (GstElement * element,
169 GstPadTemplate * templ, const gchar * name);
170 static void gst_rtp_session_release_pad (GstElement * element, GstPad * pad);
172 static guint gst_rtp_session_signals[LAST_SIGNAL] = { 0 };
174 GST_BOILERPLATE (GstRTPSession, gst_rtp_session, GstElement, GST_TYPE_ELEMENT);
177 gst_rtp_session_base_init (gpointer klass)
179 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
182 gst_element_class_add_pad_template (element_class,
183 gst_static_pad_template_get (&rtpsession_recv_rtp_sink_template));
184 gst_element_class_add_pad_template (element_class,
185 gst_static_pad_template_get (&rtpsession_recv_rtcp_sink_template));
186 gst_element_class_add_pad_template (element_class,
187 gst_static_pad_template_get (&rtpsession_send_rtp_sink_template));
190 gst_element_class_add_pad_template (element_class,
191 gst_static_pad_template_get (&rtpsession_recv_rtp_src_template));
192 gst_element_class_add_pad_template (element_class,
193 gst_static_pad_template_get (&rtpsession_sync_src_template));
194 gst_element_class_add_pad_template (element_class,
195 gst_static_pad_template_get (&rtpsession_send_rtp_src_template));
196 gst_element_class_add_pad_template (element_class,
197 gst_static_pad_template_get (&rtpsession_send_rtcp_src_template));
199 gst_element_class_set_details (element_class, &rtpsession_details);
203 gst_rtp_session_class_init (GstRTPSessionClass * klass)
205 GObjectClass *gobject_class;
206 GstElementClass *gstelement_class;
208 gobject_class = (GObjectClass *) klass;
209 gstelement_class = (GstElementClass *) klass;
211 g_type_class_add_private (klass, sizeof (GstRTPSessionPrivate));
213 gobject_class->finalize = gst_rtp_session_finalize;
214 gobject_class->set_property = gst_rtp_session_set_property;
215 gobject_class->get_property = gst_rtp_session_get_property;
218 * GstRTPSession::request-pt-map:
219 * @sess: the object which received the signal
222 * Request the payload type as #GstCaps for @pt.
224 gst_rtp_session_signals[SIGNAL_REQUEST_PT_MAP] =
225 g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
226 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPSessionClass, request_pt_map),
227 NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1,
230 gstelement_class->change_state =
231 GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
232 gstelement_class->request_new_pad =
233 GST_DEBUG_FUNCPTR (gst_rtp_session_request_new_pad);
234 gstelement_class->release_pad =
235 GST_DEBUG_FUNCPTR (gst_rtp_session_release_pad);
237 GST_DEBUG_CATEGORY_INIT (gst_rtp_session_debug,
238 "rtpsession", 0, "RTP Session");
242 gst_rtp_session_init (GstRTPSession * rtpsession, GstRTPSessionClass * klass)
244 rtpsession->priv = GST_RTP_SESSION_GET_PRIVATE (rtpsession);
245 rtpsession->priv->lock = g_mutex_new ();
246 rtpsession->priv->session = rtp_session_new ();
247 /* configure callbacks */
248 rtp_session_set_callbacks (rtpsession->priv->session, &callbacks, rtpsession);
252 gst_rtp_session_finalize (GObject * object)
254 GstRTPSession *rtpsession;
256 rtpsession = GST_RTP_SESSION (object);
257 g_mutex_free (rtpsession->priv->lock);
258 g_object_unref (rtpsession->priv->session);
260 G_OBJECT_CLASS (parent_class)->finalize (object);
264 gst_rtp_session_set_property (GObject * object, guint prop_id,
265 const GValue * value, GParamSpec * pspec)
267 GstRTPSession *rtpsession;
269 rtpsession = GST_RTP_SESSION (object);
273 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279 gst_rtp_session_get_property (GObject * object, guint prop_id,
280 GValue * value, GParamSpec * pspec)
282 GstRTPSession *rtpsession;
284 rtpsession = GST_RTP_SESSION (object);
288 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294 rtcp_thread (GstRTPSession * rtpsession)
298 GstClockTime current_time;
299 GstClockTime next_timeout;
301 clock = gst_element_get_clock (GST_ELEMENT_CAST (rtpsession));
305 current_time = gst_clock_get_time (clock);
307 GST_DEBUG_OBJECT (rtpsession, "entering RTCP thread");
309 GST_RTP_SESSION_LOCK (rtpsession);
311 while (!rtpsession->priv->stop_thread) {
314 /* get initial estimate */
316 rtp_session_next_timeout (rtpsession->priv->session, current_time);
319 GST_DEBUG_OBJECT (rtpsession, "next check time %" GST_TIME_FORMAT,
320 GST_TIME_ARGS (next_timeout));
322 /* leave if no more timeouts, the session ended */
323 if (next_timeout == GST_CLOCK_TIME_NONE)
326 id = rtpsession->priv->id =
327 gst_clock_new_single_shot_id (clock, next_timeout);
328 GST_RTP_SESSION_UNLOCK (rtpsession);
330 res = gst_clock_id_wait (id, NULL);
332 GST_RTP_SESSION_LOCK (rtpsession);
333 gst_clock_id_unref (id);
334 rtpsession->priv->id = NULL;
336 if (rtpsession->priv->stop_thread)
339 /* update current time */
340 current_time = gst_clock_get_time (clock);
342 /* we get unlocked because we need to perform reconsideration, don't perform
343 * the timeout but get a new reporting estimate. */
344 GST_DEBUG_OBJECT (rtpsession, "unlocked %d, current %" GST_TIME_FORMAT,
345 res, GST_TIME_ARGS (current_time));
347 /* perform actions, we ignore result. */
348 rtp_session_on_timeout (rtpsession->priv->session, current_time);
350 GST_RTP_SESSION_UNLOCK (rtpsession);
352 gst_object_unref (clock);
354 GST_DEBUG_OBJECT (rtpsession, "leaving RTCP thread");
358 start_rtcp_thread (GstRTPSession * rtpsession)
360 GError *error = NULL;
363 GST_DEBUG_OBJECT (rtpsession, "starting RTCP thread");
365 GST_RTP_SESSION_LOCK (rtpsession);
366 rtpsession->priv->stop_thread = FALSE;
367 rtpsession->priv->thread =
368 g_thread_create ((GThreadFunc) rtcp_thread, rtpsession, TRUE, &error);
369 GST_RTP_SESSION_UNLOCK (rtpsession);
373 GST_DEBUG_OBJECT (rtpsession, "failed to start thread, %s", error->message);
374 g_error_free (error);
382 stop_rtcp_thread (GstRTPSession * rtpsession)
384 GST_DEBUG_OBJECT (rtpsession, "stopping RTCP thread");
386 GST_RTP_SESSION_LOCK (rtpsession);
387 rtpsession->priv->stop_thread = TRUE;
388 if (rtpsession->priv->id)
389 gst_clock_id_unschedule (rtpsession->priv->id);
390 GST_RTP_SESSION_UNLOCK (rtpsession);
392 g_thread_join (rtpsession->priv->thread);
395 static GstStateChangeReturn
396 gst_rtp_session_change_state (GstElement * element, GstStateChange transition)
398 GstStateChangeReturn res;
399 GstRTPSession *rtpsession;
401 rtpsession = GST_RTP_SESSION (element);
403 switch (transition) {
404 case GST_STATE_CHANGE_NULL_TO_READY:
406 case GST_STATE_CHANGE_READY_TO_PAUSED:
408 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
410 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
411 stop_rtcp_thread (rtpsession);
416 res = parent_class->change_state (element, transition);
418 switch (transition) {
419 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
420 if (!start_rtcp_thread (rtpsession))
423 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
425 case GST_STATE_CHANGE_PAUSED_TO_READY:
427 case GST_STATE_CHANGE_READY_TO_NULL:
437 return GST_STATE_CHANGE_FAILURE;
441 /* called when the session manager has an RTP packet ready for further
444 gst_rtp_session_process_rtp (RTPSession * sess, RTPSource * src,
445 GstBuffer * buffer, gpointer user_data)
447 GstFlowReturn result;
448 GstRTPSession *rtpsession;
449 GstRTPSessionPrivate *priv;
451 rtpsession = GST_RTP_SESSION (user_data);
452 priv = rtpsession->priv;
454 if (rtpsession->recv_rtp_src) {
455 result = gst_pad_push (rtpsession->recv_rtp_src, buffer);
457 gst_buffer_unref (buffer);
458 result = GST_FLOW_OK;
463 /* called when the session manager has an RTP packet ready for further
466 gst_rtp_session_send_rtp (RTPSession * sess, RTPSource * src,
467 GstBuffer * buffer, gpointer user_data)
469 GstFlowReturn result;
470 GstRTPSession *rtpsession;
471 GstRTPSessionPrivate *priv;
473 rtpsession = GST_RTP_SESSION (user_data);
474 priv = rtpsession->priv;
476 if (rtpsession->send_rtp_src) {
477 result = gst_pad_push (rtpsession->send_rtp_src, buffer);
479 gst_buffer_unref (buffer);
480 result = GST_FLOW_OK;
485 /* called when the session manager has an RTCP packet ready for further
488 gst_rtp_session_send_rtcp (RTPSession * sess, RTPSource * src,
489 GstBuffer * buffer, gpointer user_data)
491 GstFlowReturn result;
492 GstRTPSession *rtpsession;
493 GstRTPSessionPrivate *priv;
495 rtpsession = GST_RTP_SESSION (user_data);
496 priv = rtpsession->priv;
498 GST_DEBUG_OBJECT (rtpsession, "sending RTCP");
500 if (rtpsession->send_rtcp_src) {
501 result = gst_pad_push (rtpsession->send_rtcp_src, buffer);
503 gst_buffer_unref (buffer);
504 result = GST_FLOW_OK;
510 /* called when the session manager needs the clock rate */
512 gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload,
516 GstRTPSession *rtpsession;
518 GValue args[2] = { {0}, {0} };
520 const GstStructure *caps_struct;
522 rtpsession = GST_RTP_SESSION_CAST (user_data);
524 g_value_init (&args[0], GST_TYPE_ELEMENT);
525 g_value_set_object (&args[0], rtpsession);
526 g_value_init (&args[1], G_TYPE_UINT);
527 g_value_set_uint (&args[1], payload);
529 g_value_init (&ret, GST_TYPE_CAPS);
530 g_value_set_boxed (&ret, NULL);
532 g_signal_emitv (args, gst_rtp_session_signals[SIGNAL_REQUEST_PT_MAP], 0,
535 caps = (GstCaps *) g_value_get_boxed (&ret);
539 caps_struct = gst_caps_get_structure (caps, 0);
540 if (!gst_structure_get_int (caps_struct, "clock-rate", &result))
543 GST_DEBUG_OBJECT (rtpsession, "parsed clock-rate %d", result);
550 GST_DEBUG_OBJECT (rtpsession, "could not get caps");
555 GST_DEBUG_OBJECT (rtpsession, "could not clock-rate from caps");
560 /* called when the session manager needs the time of clock */
562 gst_rtp_session_get_time (RTPSession * sess, gpointer user_data)
565 GstRTPSession *rtpsession;
568 rtpsession = GST_RTP_SESSION_CAST (user_data);
570 clock = gst_element_get_clock (GST_ELEMENT_CAST (rtpsession));
572 result = gst_clock_get_time (clock);
573 gst_object_unref (clock);
575 result = GST_CLOCK_TIME_NONE;
580 /* called when the session manager asks us to reconsider the timeout */
582 gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data)
584 GstRTPSession *rtpsession;
586 rtpsession = GST_RTP_SESSION_CAST (user_data);
588 GST_RTP_SESSION_LOCK (rtpsession);
589 GST_DEBUG_OBJECT (rtpsession, "unlock timer for reconsideration");
590 if (rtpsession->priv->id)
591 gst_clock_id_unschedule (rtpsession->priv->id);
592 GST_RTP_SESSION_UNLOCK (rtpsession);
596 gst_rtp_session_event_recv_rtp_sink (GstPad * pad, GstEvent * event)
598 GstRTPSession *rtpsession;
599 GstRTPSessionPrivate *priv;
600 gboolean ret = FALSE;
602 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
603 priv = rtpsession->priv;
605 GST_DEBUG_OBJECT (rtpsession, "received event %s",
606 GST_EVENT_TYPE_NAME (event));
608 switch (GST_EVENT_TYPE (event)) {
610 ret = gst_pad_push_event (rtpsession->recv_rtp_src, event);
613 gst_object_unref (rtpsession);
618 /* receive a packet from a sender, send it to the RTP session manager and
619 * forward the packet on the rtp_src pad
622 gst_rtp_session_chain_recv_rtp (GstPad * pad, GstBuffer * buffer)
624 GstRTPSession *rtpsession;
625 GstRTPSessionPrivate *priv;
628 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
629 priv = rtpsession->priv;
631 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
633 ret = rtp_session_process_rtp (priv->session, buffer);
635 gst_object_unref (rtpsession);
641 gst_rtp_session_event_recv_rtcp_sink (GstPad * pad, GstEvent * event)
643 GstRTPSession *rtpsession;
644 GstRTPSessionPrivate *priv;
645 gboolean ret = FALSE;
647 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
648 priv = rtpsession->priv;
650 GST_DEBUG_OBJECT (rtpsession, "received event %s",
651 GST_EVENT_TYPE_NAME (event));
653 switch (GST_EVENT_TYPE (event)) {
655 ret = gst_pad_push_event (rtpsession->sync_src, event);
658 gst_object_unref (rtpsession);
663 /* Receive an RTCP packet from a sender, send it to the RTP session manager and
664 * forward the SR packets to the sync_src pad.
667 gst_rtp_session_chain_recv_rtcp (GstPad * pad, GstBuffer * buffer)
669 GstRTPSession *rtpsession;
670 GstRTPSessionPrivate *priv;
673 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
674 priv = rtpsession->priv;
676 GST_DEBUG_OBJECT (rtpsession, "received RTCP packet");
678 ret = rtp_session_process_rtcp (priv->session, buffer);
680 gst_object_unref (rtpsession);
686 gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event)
688 GstRTPSession *rtpsession;
689 GstRTPSessionPrivate *priv;
690 gboolean ret = FALSE;
692 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
693 priv = rtpsession->priv;
695 GST_DEBUG_OBJECT (rtpsession, "received event");
697 switch (GST_EVENT_TYPE (event)) {
699 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
702 gst_object_unref (rtpsession);
707 /* Recieve an RTP packet to be send to the receivers, send to RTP session
708 * manager and forward to send_rtp_src.
711 gst_rtp_session_chain_send_rtp (GstPad * pad, GstBuffer * buffer)
713 GstRTPSession *rtpsession;
714 GstRTPSessionPrivate *priv;
717 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
718 priv = rtpsession->priv;
720 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
722 ret = rtp_session_send_rtp (priv->session, buffer);
724 gst_object_unref (rtpsession);
730 /* Create sinkpad to receive RTP packets from senders. This will also create a
731 * srcpad for the RTP packets.
734 create_recv_rtp_sink (GstRTPSession * rtpsession)
736 GST_DEBUG_OBJECT (rtpsession, "creating RTP sink pad");
738 rtpsession->recv_rtp_sink =
739 gst_pad_new_from_static_template (&rtpsession_recv_rtp_sink_template,
741 gst_pad_set_chain_function (rtpsession->recv_rtp_sink,
742 gst_rtp_session_chain_recv_rtp);
743 gst_pad_set_event_function (rtpsession->recv_rtp_sink,
744 gst_rtp_session_event_recv_rtp_sink);
745 gst_pad_set_active (rtpsession->recv_rtp_sink, TRUE);
746 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
747 rtpsession->recv_rtp_sink);
749 GST_DEBUG_OBJECT (rtpsession, "creating RTP src pad");
750 rtpsession->recv_rtp_src =
751 gst_pad_new_from_static_template (&rtpsession_recv_rtp_src_template,
753 gst_pad_set_active (rtpsession->recv_rtp_src, TRUE);
754 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->recv_rtp_src);
756 return rtpsession->recv_rtp_sink;
759 /* Create a sinkpad to receive RTCP messages from senders, this will also create a
760 * sync_src pad for the SR packets.
763 create_recv_rtcp_sink (GstRTPSession * rtpsession)
765 GST_DEBUG_OBJECT (rtpsession, "creating RTCP sink pad");
767 rtpsession->recv_rtcp_sink =
768 gst_pad_new_from_static_template (&rtpsession_recv_rtcp_sink_template,
770 gst_pad_set_chain_function (rtpsession->recv_rtcp_sink,
771 gst_rtp_session_chain_recv_rtcp);
772 gst_pad_set_event_function (rtpsession->recv_rtcp_sink,
773 gst_rtp_session_event_recv_rtcp_sink);
774 gst_pad_set_active (rtpsession->recv_rtcp_sink, TRUE);
775 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
776 rtpsession->recv_rtcp_sink);
778 GST_DEBUG_OBJECT (rtpsession, "creating sync src pad");
779 rtpsession->sync_src =
780 gst_pad_new_from_static_template (&rtpsession_sync_src_template,
782 gst_pad_set_active (rtpsession->sync_src, TRUE);
783 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->sync_src);
785 return rtpsession->recv_rtcp_sink;
788 /* Create a sinkpad to receive RTP packets for receivers. This will also create a
792 create_send_rtp_sink (GstRTPSession * rtpsession)
794 GST_DEBUG_OBJECT (rtpsession, "creating pad");
796 rtpsession->send_rtp_sink =
797 gst_pad_new_from_static_template (&rtpsession_send_rtp_sink_template,
799 gst_pad_set_chain_function (rtpsession->send_rtp_sink,
800 gst_rtp_session_chain_send_rtp);
801 gst_pad_set_event_function (rtpsession->send_rtp_sink,
802 gst_rtp_session_event_send_rtp_sink);
803 gst_pad_set_active (rtpsession->send_rtp_sink, TRUE);
804 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
805 rtpsession->recv_rtcp_sink);
807 rtpsession->send_rtp_src =
808 gst_pad_new_from_static_template (&rtpsession_send_rtp_src_template,
810 gst_pad_set_active (rtpsession->send_rtp_src, TRUE);
811 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->send_rtp_src);
813 return rtpsession->send_rtp_sink;
816 /* Create a srcpad with the RTCP packets to send out.
817 * This pad will be driven by the RTP session manager when it wants to send out
821 create_send_rtcp_src (GstRTPSession * rtpsession)
823 GST_DEBUG_OBJECT (rtpsession, "creating pad");
825 rtpsession->send_rtcp_src =
826 gst_pad_new_from_static_template (&rtpsession_send_rtcp_src_template,
828 gst_pad_set_active (rtpsession->send_rtcp_src, TRUE);
829 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
830 rtpsession->send_rtcp_src);
832 return rtpsession->send_rtcp_src;
836 gst_rtp_session_request_new_pad (GstElement * element,
837 GstPadTemplate * templ, const gchar * name)
839 GstRTPSession *rtpsession;
840 GstElementClass *klass;
843 g_return_val_if_fail (templ != NULL, NULL);
844 g_return_val_if_fail (GST_IS_RTP_SESSION (element), NULL);
846 rtpsession = GST_RTP_SESSION (element);
847 klass = GST_ELEMENT_GET_CLASS (element);
849 GST_DEBUG_OBJECT (element, "requesting pad %s", GST_STR_NULL (name));
851 GST_RTP_SESSION_LOCK (rtpsession);
853 /* figure out the template */
854 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink")) {
855 if (rtpsession->recv_rtp_sink != NULL)
858 result = create_recv_rtp_sink (rtpsession);
859 } else if (templ == gst_element_class_get_pad_template (klass,
861 if (rtpsession->recv_rtcp_sink != NULL)
864 result = create_recv_rtcp_sink (rtpsession);
865 } else if (templ == gst_element_class_get_pad_template (klass,
867 if (rtpsession->send_rtp_sink != NULL)
870 result = create_send_rtp_sink (rtpsession);
871 } else if (templ == gst_element_class_get_pad_template (klass,
873 if (rtpsession->send_rtcp_src != NULL)
876 result = create_send_rtcp_src (rtpsession);
880 GST_RTP_SESSION_UNLOCK (rtpsession);
887 GST_RTP_SESSION_UNLOCK (rtpsession);
888 g_warning ("rtpsession: this is not our template");
893 GST_RTP_SESSION_UNLOCK (rtpsession);
894 g_warning ("rtpsession: pad already requested");
900 gst_rtp_session_release_pad (GstElement * element, GstPad * pad)