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 GST_DEBUG_OBJECT (rtpsession, "reading receiving RTP packet");
456 if (rtpsession->recv_rtp_src) {
457 result = gst_pad_push (rtpsession->recv_rtp_src, buffer);
459 gst_buffer_unref (buffer);
460 result = GST_FLOW_OK;
465 /* called when the session manager has an RTP packet ready for further
468 gst_rtp_session_send_rtp (RTPSession * sess, RTPSource * src,
469 GstBuffer * buffer, gpointer user_data)
471 GstFlowReturn result;
472 GstRTPSession *rtpsession;
473 GstRTPSessionPrivate *priv;
475 rtpsession = GST_RTP_SESSION (user_data);
476 priv = rtpsession->priv;
478 GST_DEBUG_OBJECT (rtpsession, "sending RTP packet");
480 if (rtpsession->send_rtp_src) {
481 result = gst_pad_push (rtpsession->send_rtp_src, buffer);
483 gst_buffer_unref (buffer);
484 result = GST_FLOW_OK;
489 /* called when the session manager has an RTCP packet ready for further
492 gst_rtp_session_send_rtcp (RTPSession * sess, RTPSource * src,
493 GstBuffer * buffer, gpointer user_data)
495 GstFlowReturn result;
496 GstRTPSession *rtpsession;
497 GstRTPSessionPrivate *priv;
499 rtpsession = GST_RTP_SESSION (user_data);
500 priv = rtpsession->priv;
502 GST_DEBUG_OBJECT (rtpsession, "sending RTCP");
504 if (rtpsession->send_rtcp_src) {
505 result = gst_pad_push (rtpsession->send_rtcp_src, buffer);
507 gst_buffer_unref (buffer);
508 result = GST_FLOW_OK;
514 /* called when the session manager needs the clock rate */
516 gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload,
520 GstRTPSession *rtpsession;
522 GValue args[2] = { {0}, {0} };
524 const GstStructure *caps_struct;
526 rtpsession = GST_RTP_SESSION_CAST (user_data);
528 g_value_init (&args[0], GST_TYPE_ELEMENT);
529 g_value_set_object (&args[0], rtpsession);
530 g_value_init (&args[1], G_TYPE_UINT);
531 g_value_set_uint (&args[1], payload);
533 g_value_init (&ret, GST_TYPE_CAPS);
534 g_value_set_boxed (&ret, NULL);
536 g_signal_emitv (args, gst_rtp_session_signals[SIGNAL_REQUEST_PT_MAP], 0,
539 caps = (GstCaps *) g_value_get_boxed (&ret);
543 caps_struct = gst_caps_get_structure (caps, 0);
544 if (!gst_structure_get_int (caps_struct, "clock-rate", &result))
547 GST_DEBUG_OBJECT (rtpsession, "parsed clock-rate %d", result);
554 GST_DEBUG_OBJECT (rtpsession, "could not get caps");
559 GST_DEBUG_OBJECT (rtpsession, "could not clock-rate from caps");
564 /* called when the session manager needs the time of clock */
566 gst_rtp_session_get_time (RTPSession * sess, gpointer user_data)
569 GstRTPSession *rtpsession;
572 rtpsession = GST_RTP_SESSION_CAST (user_data);
574 clock = gst_element_get_clock (GST_ELEMENT_CAST (rtpsession));
576 result = gst_clock_get_time (clock);
577 gst_object_unref (clock);
579 result = GST_CLOCK_TIME_NONE;
584 /* called when the session manager asks us to reconsider the timeout */
586 gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data)
588 GstRTPSession *rtpsession;
590 rtpsession = GST_RTP_SESSION_CAST (user_data);
592 GST_RTP_SESSION_LOCK (rtpsession);
593 GST_DEBUG_OBJECT (rtpsession, "unlock timer for reconsideration");
594 if (rtpsession->priv->id)
595 gst_clock_id_unschedule (rtpsession->priv->id);
596 GST_RTP_SESSION_UNLOCK (rtpsession);
600 gst_rtp_session_event_recv_rtp_sink (GstPad * pad, GstEvent * event)
602 GstRTPSession *rtpsession;
603 GstRTPSessionPrivate *priv;
604 gboolean ret = FALSE;
606 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
607 priv = rtpsession->priv;
609 GST_DEBUG_OBJECT (rtpsession, "received event %s",
610 GST_EVENT_TYPE_NAME (event));
612 switch (GST_EVENT_TYPE (event)) {
614 ret = gst_pad_push_event (rtpsession->recv_rtp_src, event);
617 gst_object_unref (rtpsession);
622 /* receive a packet from a sender, send it to the RTP session manager and
623 * forward the packet on the rtp_src pad
626 gst_rtp_session_chain_recv_rtp (GstPad * pad, GstBuffer * buffer)
628 GstRTPSession *rtpsession;
629 GstRTPSessionPrivate *priv;
632 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
633 priv = rtpsession->priv;
635 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
637 ret = rtp_session_process_rtp (priv->session, buffer);
639 gst_object_unref (rtpsession);
645 gst_rtp_session_event_recv_rtcp_sink (GstPad * pad, GstEvent * event)
647 GstRTPSession *rtpsession;
648 GstRTPSessionPrivate *priv;
649 gboolean ret = FALSE;
651 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
652 priv = rtpsession->priv;
654 GST_DEBUG_OBJECT (rtpsession, "received event %s",
655 GST_EVENT_TYPE_NAME (event));
657 switch (GST_EVENT_TYPE (event)) {
659 ret = gst_pad_push_event (rtpsession->sync_src, event);
662 gst_object_unref (rtpsession);
667 /* Receive an RTCP packet from a sender, send it to the RTP session manager and
668 * forward the SR packets to the sync_src pad.
671 gst_rtp_session_chain_recv_rtcp (GstPad * pad, GstBuffer * buffer)
673 GstRTPSession *rtpsession;
674 GstRTPSessionPrivate *priv;
677 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
678 priv = rtpsession->priv;
680 GST_DEBUG_OBJECT (rtpsession, "received RTCP packet");
682 ret = rtp_session_process_rtcp (priv->session, buffer);
684 gst_object_unref (rtpsession);
690 gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event)
692 GstRTPSession *rtpsession;
693 GstRTPSessionPrivate *priv;
694 gboolean ret = FALSE;
696 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
697 priv = rtpsession->priv;
699 GST_DEBUG_OBJECT (rtpsession, "received event");
701 switch (GST_EVENT_TYPE (event)) {
703 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
706 gst_object_unref (rtpsession);
711 /* Recieve an RTP packet to be send to the receivers, send to RTP session
712 * manager and forward to send_rtp_src.
715 gst_rtp_session_chain_send_rtp (GstPad * pad, GstBuffer * buffer)
717 GstRTPSession *rtpsession;
718 GstRTPSessionPrivate *priv;
721 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
722 priv = rtpsession->priv;
724 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
726 ret = rtp_session_send_rtp (priv->session, buffer);
728 gst_object_unref (rtpsession);
734 /* Create sinkpad to receive RTP packets from senders. This will also create a
735 * srcpad for the RTP packets.
738 create_recv_rtp_sink (GstRTPSession * rtpsession)
740 GST_DEBUG_OBJECT (rtpsession, "creating RTP sink pad");
742 rtpsession->recv_rtp_sink =
743 gst_pad_new_from_static_template (&rtpsession_recv_rtp_sink_template,
745 gst_pad_set_chain_function (rtpsession->recv_rtp_sink,
746 gst_rtp_session_chain_recv_rtp);
747 gst_pad_set_event_function (rtpsession->recv_rtp_sink,
748 gst_rtp_session_event_recv_rtp_sink);
749 gst_pad_set_active (rtpsession->recv_rtp_sink, TRUE);
750 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
751 rtpsession->recv_rtp_sink);
753 GST_DEBUG_OBJECT (rtpsession, "creating RTP src pad");
754 rtpsession->recv_rtp_src =
755 gst_pad_new_from_static_template (&rtpsession_recv_rtp_src_template,
757 gst_pad_set_active (rtpsession->recv_rtp_src, TRUE);
758 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->recv_rtp_src);
760 return rtpsession->recv_rtp_sink;
763 /* Create a sinkpad to receive RTCP messages from senders, this will also create a
764 * sync_src pad for the SR packets.
767 create_recv_rtcp_sink (GstRTPSession * rtpsession)
769 GST_DEBUG_OBJECT (rtpsession, "creating RTCP sink pad");
771 rtpsession->recv_rtcp_sink =
772 gst_pad_new_from_static_template (&rtpsession_recv_rtcp_sink_template,
774 gst_pad_set_chain_function (rtpsession->recv_rtcp_sink,
775 gst_rtp_session_chain_recv_rtcp);
776 gst_pad_set_event_function (rtpsession->recv_rtcp_sink,
777 gst_rtp_session_event_recv_rtcp_sink);
778 gst_pad_set_active (rtpsession->recv_rtcp_sink, TRUE);
779 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
780 rtpsession->recv_rtcp_sink);
782 GST_DEBUG_OBJECT (rtpsession, "creating sync src pad");
783 rtpsession->sync_src =
784 gst_pad_new_from_static_template (&rtpsession_sync_src_template,
786 gst_pad_set_active (rtpsession->sync_src, TRUE);
787 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->sync_src);
789 return rtpsession->recv_rtcp_sink;
792 /* Create a sinkpad to receive RTP packets for receivers. This will also create a
796 create_send_rtp_sink (GstRTPSession * rtpsession)
798 GST_DEBUG_OBJECT (rtpsession, "creating pad");
800 rtpsession->send_rtp_sink =
801 gst_pad_new_from_static_template (&rtpsession_send_rtp_sink_template,
803 gst_pad_set_chain_function (rtpsession->send_rtp_sink,
804 gst_rtp_session_chain_send_rtp);
805 gst_pad_set_event_function (rtpsession->send_rtp_sink,
806 gst_rtp_session_event_send_rtp_sink);
807 gst_pad_set_active (rtpsession->send_rtp_sink, TRUE);
808 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
809 rtpsession->send_rtp_sink);
811 rtpsession->send_rtp_src =
812 gst_pad_new_from_static_template (&rtpsession_send_rtp_src_template,
814 gst_pad_set_active (rtpsession->send_rtp_src, TRUE);
815 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->send_rtp_src);
817 return rtpsession->send_rtp_sink;
820 /* Create a srcpad with the RTCP packets to send out.
821 * This pad will be driven by the RTP session manager when it wants to send out
825 create_send_rtcp_src (GstRTPSession * rtpsession)
827 GST_DEBUG_OBJECT (rtpsession, "creating pad");
829 rtpsession->send_rtcp_src =
830 gst_pad_new_from_static_template (&rtpsession_send_rtcp_src_template,
832 gst_pad_set_active (rtpsession->send_rtcp_src, TRUE);
833 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
834 rtpsession->send_rtcp_src);
836 return rtpsession->send_rtcp_src;
840 gst_rtp_session_request_new_pad (GstElement * element,
841 GstPadTemplate * templ, const gchar * name)
843 GstRTPSession *rtpsession;
844 GstElementClass *klass;
847 g_return_val_if_fail (templ != NULL, NULL);
848 g_return_val_if_fail (GST_IS_RTP_SESSION (element), NULL);
850 rtpsession = GST_RTP_SESSION (element);
851 klass = GST_ELEMENT_GET_CLASS (element);
853 GST_DEBUG_OBJECT (element, "requesting pad %s", GST_STR_NULL (name));
855 GST_RTP_SESSION_LOCK (rtpsession);
857 /* figure out the template */
858 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink")) {
859 if (rtpsession->recv_rtp_sink != NULL)
862 result = create_recv_rtp_sink (rtpsession);
863 } else if (templ == gst_element_class_get_pad_template (klass,
865 if (rtpsession->recv_rtcp_sink != NULL)
868 result = create_recv_rtcp_sink (rtpsession);
869 } else if (templ == gst_element_class_get_pad_template (klass,
871 if (rtpsession->send_rtp_sink != NULL)
874 result = create_send_rtp_sink (rtpsession);
875 } else if (templ == gst_element_class_get_pad_template (klass,
877 if (rtpsession->send_rtcp_src != NULL)
880 result = create_send_rtcp_src (rtpsession);
884 GST_RTP_SESSION_UNLOCK (rtpsession);
891 GST_RTP_SESSION_UNLOCK (rtpsession);
892 g_warning ("rtpsession: this is not our template");
897 GST_RTP_SESSION_UNLOCK (rtpsession);
898 g_warning ("rtpsession: pad already requested");
904 gst_rtp_session_release_pad (GstElement * element, GstPad * pad)