2 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.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-gstrtpsession
22 * @short_description: an RTP session manager
23 * @see_also: gstrtpjitterbuffer, gstrtpbin, gstrtpptdemux, gstrtpssrcdemux
27 * The RTP session manager models one participant with a unique SSRC in an RTP
28 * session. This session can be used to send and receive RTP and RTCP packets.
29 * Based on what REQUEST pads are requested from the session manager, specific
30 * functionality can be activated.
33 * The session manager currently implements RFC 3550 including:
36 * <para>RTP packet validation based on consecutive sequence numbers.</para>
39 * <para>Maintainance of the SSRC participant database.</para>
42 * <para>Keeping per participant statistics based on received RTCP packets.</para>
45 * <para>Scheduling of RR/SR RTCP packets.</para>
50 * The gstrtpsession will not demux packets based on SSRC or payload type, nor will
51 * it correct for packet reordering and jitter. Use gstrtpssrcdemux, gstrtpptdemux and
52 * gstrtpjitterbuffer in addition to gstrtpsession to perform these tasks. It is
53 * usually a good idea to use gstrtpbin, which combines all these features in one
57 * To use gstrtpsession as an RTP receiver, request a recv_rtp_sink pad, which will
58 * automatically create recv_rtp_src pad. Data received on the recv_rtp_sink pad
59 * will be processed in the session and after being validated forwarded on the
63 * To also use gstrtpsession as an RTCP receiver, request a recv_rtcp_sink pad,
64 * which will automatically create a sync_src pad. Packets received on the RTCP
65 * pad will be used by the session manager to update the stats and database of
66 * the other participants. SR packets will be forwarded on the sync_src pad
67 * so that they can be used to perform inter-stream synchronisation when needed.
70 * If you want the session manager to generate and send RTCP packets, request
71 * the send_rtcp_src pad. Packet pushed on this pad contain SR/RR RTCP reports
72 * that should be sent to all participants in the session.
75 * To use gstrtpsession as a sender, request a send_rtp_sink pad, which will
76 * automatically create a send_rtp_src pad. The session manager will modify the
77 * SSRC in the RTP packets to its own SSRC and wil forward the packets on the
78 * send_rtp_src pad after updating its internal state.
81 * The session manager needs the clock-rate of the payload types it is handling
82 * and will signal the GstRtpSession::request-pt-map signal when it needs such a
83 * mapping. One can clear the cached values with the GstRtpSession::clear-pt-map
86 * <title>Example pipelines</title>
89 * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink gstrtpsession .recv_rtp_src ! rtptheoradepay ! theoradec ! xvimagesink
91 * Receive theora RTP packets from port 5000 and send them to the depayloader,
92 * decoder and display. Note that the application/x-rtp caps on udpsrc should be
93 * configured based on some negotiation process such as RTSP for this pipeline
98 * gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink gstrtpsession name=session \
99 * .recv_rtp_src ! rtptheoradepay ! theoradec ! xvimagesink \
100 * udpsrc port=5001 caps="application/x-rtcp" ! session.recv_rtcp_sink
102 * Receive theora RTP packets from port 5000 and send them to the depayloader,
103 * decoder and display. Receive RTCP packets from port 5001 and process them in
104 * the session manager.
105 * Note that the application/x-rtp caps on udpsrc should be
106 * configured based on some negotiation process such as RTSP for this pipeline
111 * gst-launch videotestsrc ! theoraenc ! rtptheorapay ! .send_rtp_sink gstrtpsession .send_rtp_src ! udpsink port=5000
113 * Send theora RTP packets through the session manager and out on UDP port 5000.
117 * gst-launch videotestsrc ! theoraenc ! rtptheorapay ! .send_rtp_sink gstrtpsession name=session .send_rtp_src \
118 * ! udpsink port=5000 session.send_rtcp_src ! udpsink port=5001
120 * Send theora RTP packets through the session manager and out on UDP port 5000.
121 * Send RTCP packets on port 5001. Note that this pipeline will not preroll
122 * correctly because the second udpsink will not preroll correctly (no RTCP
123 * packets are sent in the PAUSED state). Applications should manually set and
124 * keep (see #gst_element_set_locked_state()) the RTCP udpsink to the PLAYING state.
128 * Last reviewed on 2007-05-28 (0.10.5)
135 #include <gst/rtp/gstrtpbuffer.h>
137 #include "gstrtpbin-marshal.h"
138 #include "gstrtpsession.h"
139 #include "rtpsession.h"
141 GST_DEBUG_CATEGORY_STATIC (gst_rtp_session_debug);
142 #define GST_CAT_DEFAULT gst_rtp_session_debug
144 /* elementfactory information */
145 static const GstElementDetails rtpsession_details =
146 GST_ELEMENT_DETAILS ("RTP Session",
147 "Filter/Network/RTP",
148 "Implement an RTP session",
149 "Wim Taymans <wim.taymans@gmail.com>");
152 static GstStaticPadTemplate rtpsession_recv_rtp_sink_template =
153 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink",
156 GST_STATIC_CAPS ("application/x-rtp")
159 static GstStaticPadTemplate rtpsession_recv_rtcp_sink_template =
160 GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink",
163 GST_STATIC_CAPS ("application/x-rtcp")
166 static GstStaticPadTemplate rtpsession_send_rtp_sink_template =
167 GST_STATIC_PAD_TEMPLATE ("send_rtp_sink",
170 GST_STATIC_CAPS ("application/x-rtp")
174 static GstStaticPadTemplate rtpsession_recv_rtp_src_template =
175 GST_STATIC_PAD_TEMPLATE ("recv_rtp_src",
178 GST_STATIC_CAPS ("application/x-rtp")
181 static GstStaticPadTemplate rtpsession_sync_src_template =
182 GST_STATIC_PAD_TEMPLATE ("sync_src",
185 GST_STATIC_CAPS ("application/x-rtcp")
188 static GstStaticPadTemplate rtpsession_send_rtp_src_template =
189 GST_STATIC_PAD_TEMPLATE ("send_rtp_src",
192 GST_STATIC_CAPS ("application/x-rtp")
195 static GstStaticPadTemplate rtpsession_send_rtcp_src_template =
196 GST_STATIC_PAD_TEMPLATE ("send_rtcp_src",
199 GST_STATIC_CAPS ("application/x-rtcp")
202 /* signals and args */
205 SIGNAL_REQUEST_PT_MAP,
209 SIGNAL_ON_SSRC_COLLISION,
210 SIGNAL_ON_SSRC_VALIDATED,
211 SIGNAL_ON_SSRC_ACTIVE,
214 SIGNAL_ON_BYE_TIMEOUT,
219 #define DEFAULT_NTP_NS_BASE 0
220 #define DEFAULT_BANDWIDTH RTP_STATS_BANDWIDTH
221 #define DEFAULT_RTCP_FRACTION RTP_STATS_RTCP_BANDWIDTH
222 #define DEFAULT_SDES_CNAME NULL
223 #define DEFAULT_SDES_NAME NULL
224 #define DEFAULT_SDES_EMAIL NULL
225 #define DEFAULT_SDES_PHONE NULL
226 #define DEFAULT_SDES_LOCATION NULL
227 #define DEFAULT_SDES_TOOL NULL
228 #define DEFAULT_SDES_NOTE NULL
229 #define DEFAULT_NUM_SOURCES 0
230 #define DEFAULT_NUM_ACTIVE_SOURCES 0
246 PROP_NUM_ACTIVE_SOURCES,
250 #define GST_RTP_SESSION_GET_PRIVATE(obj) \
251 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_SESSION, GstRtpSessionPrivate))
253 #define GST_RTP_SESSION_LOCK(sess) g_mutex_lock ((sess)->priv->lock)
254 #define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->priv->lock)
256 struct _GstRtpSessionPrivate
261 /* thread for sending out RTCP */
263 gboolean stop_thread;
265 gboolean thread_stopped;
274 /* callbacks to handle actions from the session manager */
275 static GstFlowReturn gst_rtp_session_process_rtp (RTPSession * sess,
276 RTPSource * src, GstBuffer * buffer, gpointer user_data);
277 static GstFlowReturn gst_rtp_session_send_rtp (RTPSession * sess,
278 RTPSource * src, GstBuffer * buffer, gpointer user_data);
279 static GstFlowReturn gst_rtp_session_send_rtcp (RTPSession * sess,
280 RTPSource * src, GstBuffer * buffer, gpointer user_data);
281 static GstFlowReturn gst_rtp_session_sync_rtcp (RTPSession * sess,
282 RTPSource * src, GstBuffer * buffer, gpointer user_data);
283 static gint gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload,
285 static void gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data);
287 static RTPSessionCallbacks callbacks = {
288 gst_rtp_session_process_rtp,
289 gst_rtp_session_send_rtp,
290 gst_rtp_session_sync_rtcp,
291 gst_rtp_session_send_rtcp,
292 gst_rtp_session_clock_rate,
293 gst_rtp_session_reconsider
296 /* GObject vmethods */
297 static void gst_rtp_session_finalize (GObject * object);
298 static void gst_rtp_session_set_property (GObject * object, guint prop_id,
299 const GValue * value, GParamSpec * pspec);
300 static void gst_rtp_session_get_property (GObject * object, guint prop_id,
301 GValue * value, GParamSpec * pspec);
303 /* GstElement vmethods */
304 static GstStateChangeReturn gst_rtp_session_change_state (GstElement * element,
305 GstStateChange transition);
306 static GstPad *gst_rtp_session_request_new_pad (GstElement * element,
307 GstPadTemplate * templ, const gchar * name);
308 static void gst_rtp_session_release_pad (GstElement * element, GstPad * pad);
310 static void gst_rtp_session_clear_pt_map (GstRtpSession * rtpsession);
312 static guint gst_rtp_session_signals[LAST_SIGNAL] = { 0 };
315 on_new_ssrc (RTPSession * session, RTPSource * src, GstRtpSession * sess)
317 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_NEW_SSRC], 0,
322 on_ssrc_collision (RTPSession * session, RTPSource * src, GstRtpSession * sess)
324 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_SSRC_COLLISION], 0,
329 on_ssrc_validated (RTPSession * session, RTPSource * src, GstRtpSession * sess)
331 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_SSRC_VALIDATED], 0,
336 on_ssrc_active (RTPSession * session, RTPSource * src, GstRtpSession * sess)
338 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_SSRC_ACTIVE], 0,
342 static GstStructure *
343 source_get_sdes_structure (RTPSource * src)
345 GstStructure *result;
349 result = gst_structure_empty_new ("GstRTPSessionSDES");
351 gst_structure_set (result, "ssrc", G_TYPE_UINT, src->ssrc, NULL);
353 g_value_init (&val, G_TYPE_STRING);
354 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_CNAME);
356 g_value_take_string (&val, str);
357 gst_structure_set_value (result, "cname", &val);
359 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NAME);
361 g_value_take_string (&val, str);
362 gst_structure_set_value (result, "name", &val);
364 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_EMAIL);
366 g_value_take_string (&val, str);
367 gst_structure_set_value (result, "email", &val);
369 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_PHONE);
371 g_value_take_string (&val, str);
372 gst_structure_set_value (result, "phone", &val);
374 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_LOC);
376 g_value_take_string (&val, str);
377 gst_structure_set_value (result, "location", &val);
379 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_TOOL);
381 g_value_take_string (&val, str);
382 gst_structure_set_value (result, "tool", &val);
384 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NOTE);
386 g_value_take_string (&val, str);
387 gst_structure_set_value (result, "note", &val);
389 str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_PRIV);
391 g_value_take_string (&val, str);
392 gst_structure_set_value (result, "priv", &val);
399 on_ssrc_sdes (RTPSession * session, RTPSource * src, GstRtpSession * sess)
404 /* convert the new SDES info into a message */
405 RTP_SESSION_LOCK (session);
406 s = source_get_sdes_structure (src);
407 RTP_SESSION_UNLOCK (session);
408 m = gst_message_new_custom (GST_MESSAGE_ELEMENT, GST_OBJECT (sess), s);
409 gst_element_post_message (GST_ELEMENT_CAST (sess), m);
411 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_SSRC_SDES], 0,
416 on_bye_ssrc (RTPSession * session, RTPSource * src, GstRtpSession * sess)
418 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_BYE_SSRC], 0,
423 on_bye_timeout (RTPSession * session, RTPSource * src, GstRtpSession * sess)
425 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_BYE_TIMEOUT], 0,
430 on_timeout (RTPSession * session, RTPSource * src, GstRtpSession * sess)
432 g_signal_emit (sess, gst_rtp_session_signals[SIGNAL_ON_TIMEOUT], 0,
436 GST_BOILERPLATE (GstRtpSession, gst_rtp_session, GstElement, GST_TYPE_ELEMENT);
439 gst_rtp_session_base_init (gpointer klass)
441 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
444 gst_element_class_add_pad_template (element_class,
445 gst_static_pad_template_get (&rtpsession_recv_rtp_sink_template));
446 gst_element_class_add_pad_template (element_class,
447 gst_static_pad_template_get (&rtpsession_recv_rtcp_sink_template));
448 gst_element_class_add_pad_template (element_class,
449 gst_static_pad_template_get (&rtpsession_send_rtp_sink_template));
452 gst_element_class_add_pad_template (element_class,
453 gst_static_pad_template_get (&rtpsession_recv_rtp_src_template));
454 gst_element_class_add_pad_template (element_class,
455 gst_static_pad_template_get (&rtpsession_sync_src_template));
456 gst_element_class_add_pad_template (element_class,
457 gst_static_pad_template_get (&rtpsession_send_rtp_src_template));
458 gst_element_class_add_pad_template (element_class,
459 gst_static_pad_template_get (&rtpsession_send_rtcp_src_template));
461 gst_element_class_set_details (element_class, &rtpsession_details);
465 gst_rtp_session_class_init (GstRtpSessionClass * klass)
467 GObjectClass *gobject_class;
468 GstElementClass *gstelement_class;
470 gobject_class = (GObjectClass *) klass;
471 gstelement_class = (GstElementClass *) klass;
473 g_type_class_add_private (klass, sizeof (GstRtpSessionPrivate));
475 gobject_class->finalize = gst_rtp_session_finalize;
476 gobject_class->set_property = gst_rtp_session_set_property;
477 gobject_class->get_property = gst_rtp_session_get_property;
480 * GstRtpSession::request-pt-map:
481 * @sess: the object which received the signal
484 * Request the payload type as #GstCaps for @pt.
486 gst_rtp_session_signals[SIGNAL_REQUEST_PT_MAP] =
487 g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
488 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, request_pt_map),
489 NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1,
492 * GstRtpSession::clear-pt-map:
493 * @sess: the object which received the signal
495 * Clear the cached pt-maps requested with GstRtpSession::request-pt-map.
497 gst_rtp_session_signals[SIGNAL_CLEAR_PT_MAP] =
498 g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
499 G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpSessionClass, clear_pt_map),
500 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
503 * GstRtpSession::on-new-ssrc:
504 * @sess: the object which received the signal
507 * Notify of a new SSRC that entered @session.
509 gst_rtp_session_signals[SIGNAL_ON_NEW_SSRC] =
510 g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass),
511 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, on_new_ssrc),
512 NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
514 * GstRtpSession::on-ssrc_collision:
515 * @sess: the object which received the signal
518 * Notify when we have an SSRC collision
520 gst_rtp_session_signals[SIGNAL_ON_SSRC_COLLISION] =
521 g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass),
522 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass,
523 on_ssrc_collision), NULL, NULL, g_cclosure_marshal_VOID__UINT,
524 G_TYPE_NONE, 1, G_TYPE_UINT);
526 * GstRtpSession::on-ssrc_validated:
527 * @sess: the object which received the signal
530 * Notify of a new SSRC that became validated.
532 gst_rtp_session_signals[SIGNAL_ON_SSRC_VALIDATED] =
533 g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass),
534 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass,
535 on_ssrc_validated), NULL, NULL, g_cclosure_marshal_VOID__UINT,
536 G_TYPE_NONE, 1, G_TYPE_UINT);
538 * GstRtpSession::on-ssrc_active:
539 * @sess: the object which received the signal
542 * Notify of a SSRC that is active, i.e., sending RTCP.
544 gst_rtp_session_signals[SIGNAL_ON_SSRC_ACTIVE] =
545 g_signal_new ("on-ssrc-active", G_TYPE_FROM_CLASS (klass),
546 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass,
547 on_ssrc_active), NULL, NULL, g_cclosure_marshal_VOID__UINT,
548 G_TYPE_NONE, 1, G_TYPE_UINT);
550 * GstRtpSession::on-ssrc-sdes:
551 * @session: the object which received the signal
554 * Notify that a new SDES was received for SSRC.
556 gst_rtp_session_signals[SIGNAL_ON_SSRC_SDES] =
557 g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass),
558 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, on_ssrc_sdes),
559 NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
562 * GstRtpSession::on-bye-ssrc:
563 * @sess: the object which received the signal
566 * Notify of an SSRC that became inactive because of a BYE packet.
568 gst_rtp_session_signals[SIGNAL_ON_BYE_SSRC] =
569 g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass),
570 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, on_bye_ssrc),
571 NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
573 * GstRtpSession::on-bye-timeout:
574 * @sess: the object which received the signal
577 * Notify of an SSRC that has timed out because of BYE
579 gst_rtp_session_signals[SIGNAL_ON_BYE_TIMEOUT] =
580 g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass),
581 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, on_bye_timeout),
582 NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
584 * GstRtpSession::on-timeout:
585 * @sess: the object which received the signal
588 * Notify of an SSRC that has timed out
590 gst_rtp_session_signals[SIGNAL_ON_TIMEOUT] =
591 g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass),
592 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpSessionClass, on_timeout),
593 NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
595 g_object_class_install_property (gobject_class, PROP_NTP_NS_BASE,
596 g_param_spec_uint64 ("ntp-ns-base", "NTP base time",
597 "The NTP base time corresponding to running_time 0", 0,
598 G_MAXUINT64, DEFAULT_NTP_NS_BASE, G_PARAM_READWRITE));
600 g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
601 g_param_spec_double ("bandwidth", "Bandwidth",
602 "The bandwidth of the session",
603 0.0, G_MAXDOUBLE, DEFAULT_BANDWIDTH, G_PARAM_READWRITE));
605 g_object_class_install_property (gobject_class, PROP_RTCP_FRACTION,
606 g_param_spec_double ("rtcp-fraction", "RTCP Fraction",
607 "The fraction of the bandwidth used for RTCP",
608 0.0, G_MAXDOUBLE, DEFAULT_RTCP_FRACTION, G_PARAM_READWRITE));
610 g_object_class_install_property (gobject_class, PROP_SDES_CNAME,
611 g_param_spec_string ("sdes-cname", "SDES CNAME",
612 "The CNAME to put in SDES messages of this session",
613 DEFAULT_SDES_CNAME, G_PARAM_READWRITE));
615 g_object_class_install_property (gobject_class, PROP_SDES_NAME,
616 g_param_spec_string ("sdes-name", "SDES NAME",
617 "The NAME to put in SDES messages of this session",
618 DEFAULT_SDES_NAME, G_PARAM_READWRITE));
620 g_object_class_install_property (gobject_class, PROP_SDES_EMAIL,
621 g_param_spec_string ("sdes-email", "SDES EMAIL",
622 "The EMAIL to put in SDES messages of this session",
623 DEFAULT_SDES_EMAIL, G_PARAM_READWRITE));
625 g_object_class_install_property (gobject_class, PROP_SDES_PHONE,
626 g_param_spec_string ("sdes-phone", "SDES PHONE",
627 "The PHONE to put in SDES messages of this session",
628 DEFAULT_SDES_PHONE, G_PARAM_READWRITE));
630 g_object_class_install_property (gobject_class, PROP_SDES_LOCATION,
631 g_param_spec_string ("sdes-location", "SDES LOCATION",
632 "The LOCATION to put in SDES messages of this session",
633 DEFAULT_SDES_LOCATION, G_PARAM_READWRITE));
635 g_object_class_install_property (gobject_class, PROP_SDES_TOOL,
636 g_param_spec_string ("sdes-tool", "SDES TOOL",
637 "The TOOL to put in SDES messages of this session",
638 DEFAULT_SDES_TOOL, G_PARAM_READWRITE));
640 g_object_class_install_property (gobject_class, PROP_SDES_NOTE,
641 g_param_spec_string ("sdes-note", "SDES NOTE",
642 "The NOTE to put in SDES messages of this session",
643 DEFAULT_SDES_NOTE, G_PARAM_READWRITE));
645 g_object_class_install_property (gobject_class, PROP_NUM_SOURCES,
646 g_param_spec_uint ("num-sources", "Num Sources",
647 "The number of sources in the session", 0, G_MAXUINT,
648 DEFAULT_NUM_SOURCES, G_PARAM_READABLE));
650 g_object_class_install_property (gobject_class, PROP_NUM_ACTIVE_SOURCES,
651 g_param_spec_uint ("num-active-sources", "Num Active Sources",
652 "The number of active sources in the session", 0, G_MAXUINT,
653 DEFAULT_NUM_ACTIVE_SOURCES, G_PARAM_READABLE));
655 gstelement_class->change_state =
656 GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
657 gstelement_class->request_new_pad =
658 GST_DEBUG_FUNCPTR (gst_rtp_session_request_new_pad);
659 gstelement_class->release_pad =
660 GST_DEBUG_FUNCPTR (gst_rtp_session_release_pad);
662 klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_session_clear_pt_map);
664 GST_DEBUG_CATEGORY_INIT (gst_rtp_session_debug,
665 "rtpsession", 0, "RTP Session");
669 gst_rtp_session_init (GstRtpSession * rtpsession, GstRtpSessionClass * klass)
671 rtpsession->priv = GST_RTP_SESSION_GET_PRIVATE (rtpsession);
672 rtpsession->priv->lock = g_mutex_new ();
673 rtpsession->priv->session = rtp_session_new ();
674 /* configure callbacks */
675 rtp_session_set_callbacks (rtpsession->priv->session, &callbacks, rtpsession);
676 /* configure signals */
677 g_signal_connect (rtpsession->priv->session, "on-new-ssrc",
678 (GCallback) on_new_ssrc, rtpsession);
679 g_signal_connect (rtpsession->priv->session, "on-ssrc-collision",
680 (GCallback) on_ssrc_collision, rtpsession);
681 g_signal_connect (rtpsession->priv->session, "on-ssrc-validated",
682 (GCallback) on_ssrc_validated, rtpsession);
683 g_signal_connect (rtpsession->priv->session, "on-ssrc-active",
684 (GCallback) on_ssrc_active, rtpsession);
685 g_signal_connect (rtpsession->priv->session, "on-ssrc-sdes",
686 (GCallback) on_ssrc_sdes, rtpsession);
687 g_signal_connect (rtpsession->priv->session, "on-bye-ssrc",
688 (GCallback) on_bye_ssrc, rtpsession);
689 g_signal_connect (rtpsession->priv->session, "on-bye-timeout",
690 (GCallback) on_bye_timeout, rtpsession);
691 g_signal_connect (rtpsession->priv->session, "on-timeout",
692 (GCallback) on_timeout, rtpsession);
693 rtpsession->priv->ptmap = g_hash_table_new (NULL, NULL);
695 gst_segment_init (&rtpsession->recv_rtp_seg, GST_FORMAT_UNDEFINED);
696 gst_segment_init (&rtpsession->send_rtp_seg, GST_FORMAT_UNDEFINED);
698 rtpsession->priv->thread_stopped = TRUE;
702 gst_rtp_session_finalize (GObject * object)
704 GstRtpSession *rtpsession;
706 rtpsession = GST_RTP_SESSION (object);
708 if (rtpsession->recv_rtp_sink != NULL)
709 gst_object_unref (rtpsession->recv_rtp_sink);
710 if (rtpsession->recv_rtcp_sink != NULL)
711 gst_object_unref (rtpsession->recv_rtcp_sink);
712 if (rtpsession->send_rtp_sink != NULL)
713 gst_object_unref (rtpsession->send_rtp_sink);
714 if (rtpsession->send_rtcp_src != NULL)
715 gst_object_unref (rtpsession->send_rtcp_src);
717 g_hash_table_destroy (rtpsession->priv->ptmap);
718 g_mutex_free (rtpsession->priv->lock);
719 g_object_unref (rtpsession->priv->session);
721 G_OBJECT_CLASS (parent_class)->finalize (object);
725 gst_rtp_session_set_property (GObject * object, guint prop_id,
726 const GValue * value, GParamSpec * pspec)
728 GstRtpSession *rtpsession;
729 GstRtpSessionPrivate *priv;
731 rtpsession = GST_RTP_SESSION (object);
732 priv = rtpsession->priv;
735 case PROP_NTP_NS_BASE:
736 GST_OBJECT_LOCK (rtpsession);
737 priv->ntpnsbase = g_value_get_uint64 (value);
738 GST_DEBUG_OBJECT (rtpsession, "setting NTP base to %" GST_TIME_FORMAT,
739 GST_TIME_ARGS (priv->ntpnsbase));
740 GST_OBJECT_UNLOCK (rtpsession);
743 rtp_session_set_bandwidth (priv->session, g_value_get_double (value));
745 case PROP_RTCP_FRACTION:
746 rtp_session_set_rtcp_fraction (priv->session, g_value_get_double (value));
748 case PROP_SDES_CNAME:
749 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_CNAME,
750 g_value_get_string (value));
753 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_NAME,
754 g_value_get_string (value));
756 case PROP_SDES_EMAIL:
757 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_EMAIL,
758 g_value_get_string (value));
760 case PROP_SDES_PHONE:
761 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_PHONE,
762 g_value_get_string (value));
764 case PROP_SDES_LOCATION:
765 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_LOC,
766 g_value_get_string (value));
769 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_TOOL,
770 g_value_get_string (value));
773 rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_NOTE,
774 g_value_get_string (value));
777 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
783 gst_rtp_session_get_property (GObject * object, guint prop_id,
784 GValue * value, GParamSpec * pspec)
786 GstRtpSession *rtpsession;
787 GstRtpSessionPrivate *priv;
789 rtpsession = GST_RTP_SESSION (object);
790 priv = rtpsession->priv;
793 case PROP_NTP_NS_BASE:
794 GST_OBJECT_LOCK (rtpsession);
795 g_value_set_uint64 (value, priv->ntpnsbase);
796 GST_OBJECT_UNLOCK (rtpsession);
799 g_value_set_double (value, rtp_session_get_bandwidth (priv->session));
801 case PROP_RTCP_FRACTION:
802 g_value_set_double (value, rtp_session_get_rtcp_fraction (priv->session));
804 case PROP_SDES_CNAME:
805 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
806 GST_RTCP_SDES_CNAME));
809 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
810 GST_RTCP_SDES_NAME));
812 case PROP_SDES_EMAIL:
813 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
814 GST_RTCP_SDES_EMAIL));
816 case PROP_SDES_PHONE:
817 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
818 GST_RTCP_SDES_PHONE));
820 case PROP_SDES_LOCATION:
821 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
825 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
826 GST_RTCP_SDES_TOOL));
829 g_value_take_string (value, rtp_session_get_sdes_string (priv->session,
830 GST_RTCP_SDES_NOTE));
832 case PROP_NUM_SOURCES:
833 g_value_set_uint (value, rtp_session_get_num_sources (priv->session));
835 case PROP_NUM_ACTIVE_SOURCES:
836 g_value_set_uint (value,
837 rtp_session_get_num_active_sources (priv->session));
840 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
846 get_current_ntp_ns_time (GstRtpSession * rtpsession)
850 GstClockTime base_time, ntpnsbase;
852 GST_OBJECT_LOCK (rtpsession);
853 if ((clock = GST_ELEMENT_CLOCK (rtpsession))) {
854 base_time = GST_ELEMENT_CAST (rtpsession)->base_time;
855 ntpnsbase = rtpsession->priv->ntpnsbase;
856 gst_object_ref (clock);
857 GST_OBJECT_UNLOCK (rtpsession);
859 /* get current NTP time */
860 ntpnstime = gst_clock_get_time (clock);
861 /* convert to running time */
862 ntpnstime -= base_time;
863 /* add NTP base offset */
864 ntpnstime += ntpnsbase;
866 gst_object_unref (clock);
868 GST_OBJECT_UNLOCK (rtpsession);
876 rtcp_thread (GstRtpSession * rtpsession)
880 GstClockTime current_time;
881 GstClockTime next_timeout;
884 /* for RTCP timeouts we use the system clock */
885 sysclock = gst_system_clock_obtain ();
886 if (sysclock == NULL)
889 current_time = gst_clock_get_time (sysclock);
891 GST_DEBUG_OBJECT (rtpsession, "entering RTCP thread");
893 GST_RTP_SESSION_LOCK (rtpsession);
895 while (!rtpsession->priv->stop_thread) {
898 /* get initial estimate */
900 rtp_session_next_timeout (rtpsession->priv->session, current_time);
902 GST_DEBUG_OBJECT (rtpsession, "next check time %" GST_TIME_FORMAT,
903 GST_TIME_ARGS (next_timeout));
905 /* leave if no more timeouts, the session ended */
906 if (next_timeout == GST_CLOCK_TIME_NONE)
909 id = rtpsession->priv->id =
910 gst_clock_new_single_shot_id (sysclock, next_timeout);
911 GST_RTP_SESSION_UNLOCK (rtpsession);
913 res = gst_clock_id_wait (id, NULL);
915 GST_RTP_SESSION_LOCK (rtpsession);
916 gst_clock_id_unref (id);
917 rtpsession->priv->id = NULL;
919 if (rtpsession->priv->stop_thread)
922 /* update current time */
923 current_time = gst_clock_get_time (sysclock);
925 /* get current NTP time */
926 ntpnstime = get_current_ntp_ns_time (rtpsession);
928 /* we get unlocked because we need to perform reconsideration, don't perform
929 * the timeout but get a new reporting estimate. */
930 GST_DEBUG_OBJECT (rtpsession, "unlocked %d, current %" GST_TIME_FORMAT,
931 res, GST_TIME_ARGS (current_time));
933 /* perform actions, we ignore result. Release lock because it might push. */
934 GST_RTP_SESSION_UNLOCK (rtpsession);
935 rtp_session_on_timeout (rtpsession->priv->session, current_time, ntpnstime);
936 GST_RTP_SESSION_LOCK (rtpsession);
938 /* mark the thread as stopped now */
939 rtpsession->priv->thread_stopped = TRUE;
940 GST_RTP_SESSION_UNLOCK (rtpsession);
942 gst_object_unref (sysclock);
944 GST_DEBUG_OBJECT (rtpsession, "leaving RTCP thread");
950 GST_ELEMENT_ERROR (rtpsession, CORE, CLOCK, (NULL),
951 ("Could not get system clock"));
957 start_rtcp_thread (GstRtpSession * rtpsession)
959 GError *error = NULL;
962 GST_DEBUG_OBJECT (rtpsession, "starting RTCP thread");
964 GST_RTP_SESSION_LOCK (rtpsession);
965 rtpsession->priv->stop_thread = FALSE;
966 if (rtpsession->priv->thread_stopped) {
967 /* only create a new thread if the old one was stopped. Otherwise we can
968 * just reuse the currently running one. */
969 rtpsession->priv->thread =
970 g_thread_create ((GThreadFunc) rtcp_thread, rtpsession, TRUE, &error);
971 rtpsession->priv->thread_stopped = FALSE;
973 GST_RTP_SESSION_UNLOCK (rtpsession);
977 GST_DEBUG_OBJECT (rtpsession, "failed to start thread, %s", error->message);
978 g_error_free (error);
986 stop_rtcp_thread (GstRtpSession * rtpsession)
988 GST_DEBUG_OBJECT (rtpsession, "stopping RTCP thread");
990 GST_RTP_SESSION_LOCK (rtpsession);
991 rtpsession->priv->stop_thread = TRUE;
992 if (rtpsession->priv->id)
993 gst_clock_id_unschedule (rtpsession->priv->id);
994 GST_RTP_SESSION_UNLOCK (rtpsession);
998 join_rtcp_thread (GstRtpSession * rtpsession)
1000 GST_RTP_SESSION_LOCK (rtpsession);
1001 /* don't try to join when we have no thread */
1002 if (rtpsession->priv->thread != NULL) {
1003 GST_DEBUG_OBJECT (rtpsession, "joining RTCP thread");
1004 GST_RTP_SESSION_UNLOCK (rtpsession);
1006 g_thread_join (rtpsession->priv->thread);
1008 GST_RTP_SESSION_LOCK (rtpsession);
1009 /* after the join, take the lock and clear the thread structure. The caller
1010 * is supposed to not concurrently call start and join. */
1011 rtpsession->priv->thread = NULL;
1013 GST_RTP_SESSION_UNLOCK (rtpsession);
1016 static GstStateChangeReturn
1017 gst_rtp_session_change_state (GstElement * element, GstStateChange transition)
1019 GstStateChangeReturn res;
1020 GstRtpSession *rtpsession;
1021 GstRtpSessionPrivate *priv;
1023 rtpsession = GST_RTP_SESSION (element);
1024 priv = rtpsession->priv;
1026 switch (transition) {
1027 case GST_STATE_CHANGE_NULL_TO_READY:
1029 case GST_STATE_CHANGE_READY_TO_PAUSED:
1031 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1033 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1034 case GST_STATE_CHANGE_PAUSED_TO_READY:
1035 /* no need to join yet, we might want to continue later. Also, the
1036 * dataflow could block downstream so that a join could just block
1038 stop_rtcp_thread (rtpsession);
1044 res = parent_class->change_state (element, transition);
1046 switch (transition) {
1047 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1048 if (!start_rtcp_thread (rtpsession))
1051 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1053 case GST_STATE_CHANGE_PAUSED_TO_READY:
1054 /* downstream is now releasing the dataflow and we can join. */
1055 join_rtcp_thread (rtpsession);
1057 case GST_STATE_CHANGE_READY_TO_NULL:
1067 return GST_STATE_CHANGE_FAILURE;
1072 gst_rtp_session_clear_pt_map (GstRtpSession * rtpsession)
1074 /* FIXME, do something */
1077 /* called when the session manager has an RTP packet ready for further
1079 static GstFlowReturn
1080 gst_rtp_session_process_rtp (RTPSession * sess, RTPSource * src,
1081 GstBuffer * buffer, gpointer user_data)
1083 GstFlowReturn result;
1084 GstRtpSession *rtpsession;
1085 GstRtpSessionPrivate *priv;
1087 rtpsession = GST_RTP_SESSION (user_data);
1088 priv = rtpsession->priv;
1090 if (rtpsession->recv_rtp_src) {
1091 GST_DEBUG_OBJECT (rtpsession, "pushing received RTP packet");
1092 result = gst_pad_push (rtpsession->recv_rtp_src, buffer);
1094 GST_DEBUG_OBJECT (rtpsession, "dropping received RTP packet");
1095 gst_buffer_unref (buffer);
1096 result = GST_FLOW_OK;
1101 /* called when the session manager has an RTP packet ready for further
1103 static GstFlowReturn
1104 gst_rtp_session_send_rtp (RTPSession * sess, RTPSource * src,
1105 GstBuffer * buffer, gpointer user_data)
1107 GstFlowReturn result;
1108 GstRtpSession *rtpsession;
1109 GstRtpSessionPrivate *priv;
1111 rtpsession = GST_RTP_SESSION (user_data);
1112 priv = rtpsession->priv;
1114 GST_DEBUG_OBJECT (rtpsession, "sending RTP packet");
1116 if (rtpsession->send_rtp_src) {
1117 result = gst_pad_push (rtpsession->send_rtp_src, buffer);
1119 gst_buffer_unref (buffer);
1120 result = GST_FLOW_OK;
1125 /* called when the session manager has an RTCP packet ready for further
1127 static GstFlowReturn
1128 gst_rtp_session_send_rtcp (RTPSession * sess, RTPSource * src,
1129 GstBuffer * buffer, gpointer user_data)
1131 GstFlowReturn result;
1132 GstRtpSession *rtpsession;
1133 GstRtpSessionPrivate *priv;
1135 rtpsession = GST_RTP_SESSION (user_data);
1136 priv = rtpsession->priv;
1138 if (rtpsession->send_rtcp_src) {
1141 /* set rtcp caps on output pad */
1142 if (!(caps = GST_PAD_CAPS (rtpsession->send_rtcp_src))) {
1143 caps = gst_caps_new_simple ("application/x-rtcp", NULL);
1144 gst_pad_set_caps (rtpsession->send_rtcp_src, caps);
1145 gst_caps_unref (caps);
1147 gst_buffer_set_caps (buffer, caps);
1148 GST_DEBUG_OBJECT (rtpsession, "sending RTCP");
1149 result = gst_pad_push (rtpsession->send_rtcp_src, buffer);
1151 GST_DEBUG_OBJECT (rtpsession, "not sending RTCP, no output pad");
1152 gst_buffer_unref (buffer);
1153 result = GST_FLOW_OK;
1158 /* called when the session manager has an SR RTCP packet ready for handling
1159 * inter stream synchronisation */
1160 static GstFlowReturn
1161 gst_rtp_session_sync_rtcp (RTPSession * sess,
1162 RTPSource * src, GstBuffer * buffer, gpointer user_data)
1164 GstFlowReturn result;
1165 GstRtpSession *rtpsession;
1166 GstRtpSessionPrivate *priv;
1168 rtpsession = GST_RTP_SESSION (user_data);
1169 priv = rtpsession->priv;
1171 if (rtpsession->sync_src) {
1174 /* set rtcp caps on output pad */
1175 if (!(caps = GST_PAD_CAPS (rtpsession->sync_src))) {
1176 caps = gst_caps_new_simple ("application/x-rtcp", NULL);
1177 gst_pad_set_caps (rtpsession->sync_src, caps);
1178 gst_caps_unref (caps);
1180 gst_buffer_set_caps (buffer, caps);
1181 GST_DEBUG_OBJECT (rtpsession, "sending Sync RTCP");
1182 result = gst_pad_push (rtpsession->sync_src, buffer);
1184 GST_DEBUG_OBJECT (rtpsession, "not sending Sync RTCP, no output pad");
1185 gst_buffer_unref (buffer);
1186 result = GST_FLOW_OK;
1192 gst_rtp_session_cache_caps (GstRtpSession * rtpsession, GstCaps * caps)
1194 GstRtpSessionPrivate *priv;
1195 const GstStructure *s;
1198 priv = rtpsession->priv;
1200 GST_DEBUG_OBJECT (rtpsession, "parsing caps");
1202 s = gst_caps_get_structure (caps, 0);
1203 if (!gst_structure_get_int (s, "payload", &payload))
1206 caps = g_hash_table_lookup (priv->ptmap, GINT_TO_POINTER (payload));
1210 g_hash_table_insert (priv->ptmap, GINT_TO_POINTER (payload), caps);
1213 /* called when the session manager needs the clock rate */
1215 gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload,
1218 gint ipayload, result = -1;
1219 GstRtpSession *rtpsession;
1220 GstRtpSessionPrivate *priv;
1222 GValue args[2] = { {0}, {0} };
1224 const GstStructure *s;
1226 rtpsession = GST_RTP_SESSION_CAST (user_data);
1227 priv = rtpsession->priv;
1229 GST_RTP_SESSION_LOCK (rtpsession);
1230 ipayload = payload; /* make compiler happy */
1231 caps = g_hash_table_lookup (priv->ptmap, GINT_TO_POINTER (ipayload));
1235 /* not found in the cache, try to get it with a signal */
1236 g_value_init (&args[0], GST_TYPE_ELEMENT);
1237 g_value_set_object (&args[0], rtpsession);
1238 g_value_init (&args[1], G_TYPE_UINT);
1239 g_value_set_uint (&args[1], payload);
1241 g_value_init (&ret, GST_TYPE_CAPS);
1242 g_value_set_boxed (&ret, NULL);
1244 g_signal_emitv (args, gst_rtp_session_signals[SIGNAL_REQUEST_PT_MAP], 0,
1247 g_value_unset (&args[0]);
1248 g_value_unset (&args[1]);
1249 caps = (GstCaps *) g_value_dup_boxed (&ret);
1250 g_value_unset (&ret);
1254 gst_rtp_session_cache_caps (rtpsession, caps);
1257 s = gst_caps_get_structure (caps, 0);
1258 if (!gst_structure_get_int (s, "clock-rate", &result))
1261 GST_DEBUG_OBJECT (rtpsession, "parsed clock-rate %d", result);
1264 GST_RTP_SESSION_UNLOCK (rtpsession);
1271 GST_DEBUG_OBJECT (rtpsession, "could not get caps");
1276 GST_DEBUG_OBJECT (rtpsession, "No clock-rate in caps!");
1281 /* called when the session manager asks us to reconsider the timeout */
1283 gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data)
1285 GstRtpSession *rtpsession;
1287 rtpsession = GST_RTP_SESSION_CAST (user_data);
1289 GST_RTP_SESSION_LOCK (rtpsession);
1290 GST_DEBUG_OBJECT (rtpsession, "unlock timer for reconsideration");
1291 if (rtpsession->priv->id)
1292 gst_clock_id_unschedule (rtpsession->priv->id);
1293 GST_RTP_SESSION_UNLOCK (rtpsession);
1297 gst_rtp_session_event_recv_rtp_sink (GstPad * pad, GstEvent * event)
1299 GstRtpSession *rtpsession;
1300 GstRtpSessionPrivate *priv;
1301 gboolean ret = FALSE;
1303 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1304 priv = rtpsession->priv;
1306 GST_DEBUG_OBJECT (rtpsession, "received event %s",
1307 GST_EVENT_TYPE_NAME (event));
1309 switch (GST_EVENT_TYPE (event)) {
1310 case GST_EVENT_FLUSH_STOP:
1311 gst_segment_init (&rtpsession->recv_rtp_seg, GST_FORMAT_UNDEFINED);
1312 ret = gst_pad_push_event (rtpsession->recv_rtp_src, event);
1314 case GST_EVENT_NEWSEGMENT:
1317 gdouble rate, arate;
1319 gint64 start, stop, time;
1320 GstSegment *segment;
1322 segment = &rtpsession->recv_rtp_seg;
1324 /* the newsegment event is needed to convert the RTP timestamp to
1325 * running_time, which is needed to generate a mapping from RTP to NTP
1326 * timestamps in SR reports */
1327 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1328 &start, &stop, &time);
1330 GST_DEBUG_OBJECT (rtpsession,
1331 "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
1332 "format GST_FORMAT_TIME, "
1333 "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
1334 ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
1335 update, rate, arate, GST_TIME_ARGS (segment->start),
1336 GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
1337 GST_TIME_ARGS (segment->accum));
1339 gst_segment_set_newsegment_full (segment, update, rate,
1340 arate, format, start, stop, time);
1342 /* push event forward */
1343 ret = gst_pad_push_event (rtpsession->recv_rtp_src, event);
1347 ret = gst_pad_push_event (rtpsession->recv_rtp_src, event);
1350 gst_object_unref (rtpsession);
1356 gst_rtp_session_internal_links (GstPad * pad)
1358 GstRtpSession *rtpsession;
1359 GstRtpSessionPrivate *priv;
1362 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1363 priv = rtpsession->priv;
1365 if (pad == rtpsession->recv_rtp_src) {
1366 res = g_list_prepend (res, rtpsession->recv_rtp_sink);
1367 } else if (pad == rtpsession->recv_rtp_sink) {
1368 res = g_list_prepend (res, rtpsession->recv_rtp_src);
1369 } else if (pad == rtpsession->send_rtp_src) {
1370 res = g_list_prepend (res, rtpsession->send_rtp_sink);
1371 } else if (pad == rtpsession->send_rtp_sink) {
1372 res = g_list_prepend (res, rtpsession->send_rtp_src);
1375 gst_object_unref (rtpsession);
1381 gst_rtp_session_sink_setcaps (GstPad * pad, GstCaps * caps)
1383 GstRtpSession *rtpsession;
1384 GstRtpSessionPrivate *priv;
1386 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1387 priv = rtpsession->priv;
1389 GST_RTP_SESSION_LOCK (rtpsession);
1390 gst_rtp_session_cache_caps (rtpsession, caps);
1391 GST_RTP_SESSION_UNLOCK (rtpsession);
1393 gst_object_unref (rtpsession);
1398 /* receive a packet from a sender, send it to the RTP session manager and
1399 * forward the packet on the rtp_src pad
1401 static GstFlowReturn
1402 gst_rtp_session_chain_recv_rtp (GstPad * pad, GstBuffer * buffer)
1404 GstRtpSession *rtpsession;
1405 GstRtpSessionPrivate *priv;
1408 GstClockTime timestamp;
1410 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1411 priv = rtpsession->priv;
1413 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
1415 /* get NTP time when this packet was captured, this depends on the timestamp. */
1416 timestamp = GST_BUFFER_TIMESTAMP (buffer);
1417 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1418 /* convert to running time using the segment values */
1420 gst_segment_to_running_time (&rtpsession->recv_rtp_seg, GST_FORMAT_TIME,
1422 /* add constant to convert running time to NTP time */
1423 ntpnstime += priv->ntpnsbase;
1425 ntpnstime = get_current_ntp_ns_time (rtpsession);
1428 ret = rtp_session_process_rtp (priv->session, buffer, ntpnstime);
1429 if (ret != GST_FLOW_OK)
1434 gst_object_unref (rtpsession);
1441 GST_DEBUG_OBJECT (rtpsession, "process returned %s",
1442 gst_flow_get_name (ret));
1448 gst_rtp_session_event_recv_rtcp_sink (GstPad * pad, GstEvent * event)
1450 GstRtpSession *rtpsession;
1451 GstRtpSessionPrivate *priv;
1452 gboolean ret = FALSE;
1454 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1455 priv = rtpsession->priv;
1457 GST_DEBUG_OBJECT (rtpsession, "received event %s",
1458 GST_EVENT_TYPE_NAME (event));
1460 switch (GST_EVENT_TYPE (event)) {
1462 if (rtpsession->send_rtcp_src) {
1463 gst_event_ref (event);
1464 ret = gst_pad_push_event (rtpsession->send_rtcp_src, event);
1466 ret = gst_pad_push_event (rtpsession->sync_src, event);
1469 gst_object_unref (rtpsession);
1474 /* Receive an RTCP packet from a sender, send it to the RTP session manager and
1475 * forward the SR packets to the sync_src pad.
1477 static GstFlowReturn
1478 gst_rtp_session_chain_recv_rtcp (GstPad * pad, GstBuffer * buffer)
1480 GstRtpSession *rtpsession;
1481 GstRtpSessionPrivate *priv;
1484 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1485 priv = rtpsession->priv;
1487 GST_DEBUG_OBJECT (rtpsession, "received RTCP packet");
1489 ret = rtp_session_process_rtcp (priv->session, buffer);
1491 gst_object_unref (rtpsession);
1497 gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event)
1499 GstRtpSession *rtpsession;
1500 GstRtpSessionPrivate *priv;
1501 gboolean ret = FALSE;
1503 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1504 priv = rtpsession->priv;
1506 GST_DEBUG_OBJECT (rtpsession, "received event");
1508 switch (GST_EVENT_TYPE (event)) {
1509 case GST_EVENT_FLUSH_STOP:
1510 gst_segment_init (&rtpsession->send_rtp_seg, GST_FORMAT_UNDEFINED);
1511 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
1513 case GST_EVENT_NEWSEGMENT:
1516 gdouble rate, arate;
1518 gint64 start, stop, time;
1519 GstSegment *segment;
1521 segment = &rtpsession->send_rtp_seg;
1523 /* the newsegment event is needed to convert the RTP timestamp to
1524 * running_time, which is needed to generate a mapping from RTP to NTP
1525 * timestamps in SR reports */
1526 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1527 &start, &stop, &time);
1529 GST_DEBUG_OBJECT (rtpsession,
1530 "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
1531 "format GST_FORMAT_TIME, "
1532 "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
1533 ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
1534 update, rate, arate, GST_TIME_ARGS (segment->start),
1535 GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
1536 GST_TIME_ARGS (segment->accum));
1538 gst_segment_set_newsegment_full (segment, update, rate,
1539 arate, format, start, stop, time);
1541 /* push event forward */
1542 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
1546 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
1549 ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
1552 gst_object_unref (rtpsession);
1558 gst_rtp_session_getcaps_send_rtp (GstPad * pad)
1560 GstRtpSession *rtpsession;
1561 GstRtpSessionPrivate *priv;
1563 GstStructure *s1, *s2;
1565 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1566 priv = rtpsession->priv;
1568 /* we can basically accept anything but we prefer to receive packets with our
1569 * internal SSRC so that we don't have to patch it. Create a structure with
1570 * the SSRC and another one without. */
1571 s1 = gst_structure_new ("application/x-rtp",
1572 "ssrc", G_TYPE_UINT, priv->session->source->ssrc, NULL);
1573 s2 = gst_structure_new ("application/x-rtp", NULL);
1575 result = gst_caps_new_full (s1, s2, NULL);
1577 GST_DEBUG_OBJECT (rtpsession, "getting caps %" GST_PTR_FORMAT, result);
1579 gst_object_unref (rtpsession);
1584 /* Recieve an RTP packet to be send to the receivers, send to RTP session
1585 * manager and forward to send_rtp_src.
1587 static GstFlowReturn
1588 gst_rtp_session_chain_send_rtp (GstPad * pad, GstBuffer * buffer)
1590 GstRtpSession *rtpsession;
1591 GstRtpSessionPrivate *priv;
1593 GstClockTime timestamp;
1596 rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
1597 priv = rtpsession->priv;
1599 GST_DEBUG_OBJECT (rtpsession, "received RTP packet");
1601 /* get NTP time when this packet was captured, this depends on the timestamp. */
1602 timestamp = GST_BUFFER_TIMESTAMP (buffer);
1603 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1604 /* convert to running time using the segment start value. */
1606 gst_segment_to_running_time (&rtpsession->send_rtp_seg, GST_FORMAT_TIME,
1608 /* convert to NTP time by adding the NTP base */
1609 ntpnstime += priv->ntpnsbase;
1611 /* no timestamp, we could take the current running_time and convert it to
1616 ret = rtp_session_send_rtp (priv->session, buffer, ntpnstime);
1617 if (ret != GST_FLOW_OK)
1621 gst_object_unref (rtpsession);
1628 GST_DEBUG_OBJECT (rtpsession, "process returned %s",
1629 gst_flow_get_name (ret));
1634 /* Create sinkpad to receive RTP packets from senders. This will also create a
1635 * srcpad for the RTP packets.
1638 create_recv_rtp_sink (GstRtpSession * rtpsession)
1640 GST_DEBUG_OBJECT (rtpsession, "creating RTP sink pad");
1642 rtpsession->recv_rtp_sink =
1643 gst_pad_new_from_static_template (&rtpsession_recv_rtp_sink_template,
1645 gst_pad_set_chain_function (rtpsession->recv_rtp_sink,
1646 gst_rtp_session_chain_recv_rtp);
1647 gst_pad_set_event_function (rtpsession->recv_rtp_sink,
1648 (GstPadEventFunction) gst_rtp_session_event_recv_rtp_sink);
1649 gst_pad_set_setcaps_function (rtpsession->recv_rtp_sink,
1650 gst_rtp_session_sink_setcaps);
1651 gst_pad_set_internal_link_function (rtpsession->recv_rtp_sink,
1652 gst_rtp_session_internal_links);
1653 gst_pad_set_active (rtpsession->recv_rtp_sink, TRUE);
1654 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
1655 rtpsession->recv_rtp_sink);
1657 GST_DEBUG_OBJECT (rtpsession, "creating RTP src pad");
1658 rtpsession->recv_rtp_src =
1659 gst_pad_new_from_static_template (&rtpsession_recv_rtp_src_template,
1661 gst_pad_set_internal_link_function (rtpsession->recv_rtp_src,
1662 gst_rtp_session_internal_links);
1663 gst_pad_use_fixed_caps (rtpsession->recv_rtp_src);
1664 gst_pad_set_active (rtpsession->recv_rtp_src, TRUE);
1665 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->recv_rtp_src);
1667 return rtpsession->recv_rtp_sink;
1670 /* Create a sinkpad to receive RTCP messages from senders, this will also create a
1671 * sync_src pad for the SR packets.
1674 create_recv_rtcp_sink (GstRtpSession * rtpsession)
1676 GST_DEBUG_OBJECT (rtpsession, "creating RTCP sink pad");
1678 rtpsession->recv_rtcp_sink =
1679 gst_pad_new_from_static_template (&rtpsession_recv_rtcp_sink_template,
1681 gst_pad_set_chain_function (rtpsession->recv_rtcp_sink,
1682 gst_rtp_session_chain_recv_rtcp);
1683 gst_pad_set_event_function (rtpsession->recv_rtcp_sink,
1684 (GstPadEventFunction) gst_rtp_session_event_recv_rtcp_sink);
1685 gst_pad_set_active (rtpsession->recv_rtcp_sink, TRUE);
1686 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
1687 rtpsession->recv_rtcp_sink);
1689 GST_DEBUG_OBJECT (rtpsession, "creating sync src pad");
1690 rtpsession->sync_src =
1691 gst_pad_new_from_static_template (&rtpsession_sync_src_template,
1693 gst_pad_use_fixed_caps (rtpsession->sync_src);
1694 gst_pad_set_active (rtpsession->sync_src, TRUE);
1695 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->sync_src);
1697 return rtpsession->recv_rtcp_sink;
1700 /* Create a sinkpad to receive RTP packets for receivers. This will also create a
1704 create_send_rtp_sink (GstRtpSession * rtpsession)
1706 GST_DEBUG_OBJECT (rtpsession, "creating pad");
1708 rtpsession->send_rtp_sink =
1709 gst_pad_new_from_static_template (&rtpsession_send_rtp_sink_template,
1711 gst_pad_set_chain_function (rtpsession->send_rtp_sink,
1712 gst_rtp_session_chain_send_rtp);
1713 gst_pad_set_getcaps_function (rtpsession->send_rtp_sink,
1714 gst_rtp_session_getcaps_send_rtp);
1715 gst_pad_set_event_function (rtpsession->send_rtp_sink,
1716 (GstPadEventFunction) gst_rtp_session_event_send_rtp_sink);
1717 gst_pad_set_internal_link_function (rtpsession->send_rtp_sink,
1718 gst_rtp_session_internal_links);
1719 gst_pad_set_active (rtpsession->send_rtp_sink, TRUE);
1720 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
1721 rtpsession->send_rtp_sink);
1723 rtpsession->send_rtp_src =
1724 gst_pad_new_from_static_template (&rtpsession_send_rtp_src_template,
1726 gst_pad_set_internal_link_function (rtpsession->send_rtp_src,
1727 gst_rtp_session_internal_links);
1728 gst_pad_set_active (rtpsession->send_rtp_src, TRUE);
1729 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->send_rtp_src);
1731 return rtpsession->send_rtp_sink;
1734 /* Create a srcpad with the RTCP packets to send out.
1735 * This pad will be driven by the RTP session manager when it wants to send out
1739 create_send_rtcp_src (GstRtpSession * rtpsession)
1741 GST_DEBUG_OBJECT (rtpsession, "creating pad");
1743 rtpsession->send_rtcp_src =
1744 gst_pad_new_from_static_template (&rtpsession_send_rtcp_src_template,
1746 gst_pad_use_fixed_caps (rtpsession->send_rtcp_src);
1747 gst_pad_set_active (rtpsession->send_rtcp_src, TRUE);
1748 gst_element_add_pad (GST_ELEMENT_CAST (rtpsession),
1749 rtpsession->send_rtcp_src);
1751 return rtpsession->send_rtcp_src;
1755 gst_rtp_session_request_new_pad (GstElement * element,
1756 GstPadTemplate * templ, const gchar * name)
1758 GstRtpSession *rtpsession;
1759 GstElementClass *klass;
1762 g_return_val_if_fail (templ != NULL, NULL);
1763 g_return_val_if_fail (GST_IS_RTP_SESSION (element), NULL);
1765 rtpsession = GST_RTP_SESSION (element);
1766 klass = GST_ELEMENT_GET_CLASS (element);
1768 GST_DEBUG_OBJECT (element, "requesting pad %s", GST_STR_NULL (name));
1770 GST_RTP_SESSION_LOCK (rtpsession);
1772 /* figure out the template */
1773 if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink")) {
1774 if (rtpsession->recv_rtp_sink != NULL)
1777 result = create_recv_rtp_sink (rtpsession);
1778 } else if (templ == gst_element_class_get_pad_template (klass,
1779 "recv_rtcp_sink")) {
1780 if (rtpsession->recv_rtcp_sink != NULL)
1783 result = create_recv_rtcp_sink (rtpsession);
1784 } else if (templ == gst_element_class_get_pad_template (klass,
1786 if (rtpsession->send_rtp_sink != NULL)
1789 result = create_send_rtp_sink (rtpsession);
1790 } else if (templ == gst_element_class_get_pad_template (klass,
1792 if (rtpsession->send_rtcp_src != NULL)
1795 result = create_send_rtcp_src (rtpsession);
1797 goto wrong_template;
1799 GST_RTP_SESSION_UNLOCK (rtpsession);
1806 GST_RTP_SESSION_UNLOCK (rtpsession);
1807 g_warning ("gstrtpsession: this is not our template");
1812 GST_RTP_SESSION_UNLOCK (rtpsession);
1813 g_warning ("gstrtpsession: pad already requested");
1819 gst_rtp_session_release_pad (GstElement * element, GstPad * pad)