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-gstrtpbin
22
* @see_also: gstrtpjitterbuffer, gstrtpsession, gstrtpptdemux, gstrtpssrcdemux
24
* RTP bin combines the functions of #GstRtpSession, #GstRtpsSrcDemux,
25
* #GstRtpJitterBuffer and #GstRtpPtDemux in one element. It allows for multiple
26
* RTP sessions that will be synchronized together using RTCP SR packets.
28
* #GstRtpBin is configured with a number of request pads that define the
29
* functionality that is activated, similar to the #GstRtpSession element.
31
* To use #GstRtpBin as an RTP receiver, request a recv_rtp_sink_%%d pad. The session
32
* number must be specified in the pad name.
33
* Data received on the recv_rtp_sink_%%d pad will be processed in the gstrtpsession
34
* manager and after being validated forwarded on #GstRtpsSrcDemux element. Each
35
* RTP stream is demuxed based on the SSRC and send to a #GstRtpJitterBuffer. After
36
* the packets are released from the jitterbuffer, they will be forwarded to a
37
* #GstRtpsSrcDemux element. The #GstRtpsSrcDemux element will demux the packets based
38
* on the payload type and will create a unique pad recv_rtp_src_%%d_%%d_%%d on
39
* gstrtpbin with the session number, SSRC and payload type respectively as the pad
42
* To also use #GstRtpBin as an RTCP receiver, request a recv_rtcp_sink_%%d pad. The
43
* session number must be specified in the pad name.
45
* If you want the session manager to generate and send RTCP packets, request
46
* the send_rtcp_src_%%d pad with the session number in the pad name. Packet pushed
47
* on this pad contain SR/RR RTCP reports that should be sent to all participants
50
* To use #GstRtpBin as a sender, request a send_rtp_sink_%%d pad, which will
51
* automatically create a send_rtp_src_%%d pad. If the session number is not provided,
52
* the pad from the lowest available session will be returned. The session manager will modify the
53
* SSRC in the RTP packets to its own SSRC and wil forward the packets on the
54
* send_rtp_src_%%d pad after updating its internal state.
56
* The session manager needs the clock-rate of the payload types it is handling
57
* and will signal the #GstRtpSession::request-pt-map signal when it needs such a
58
* mapping. One can clear the cached values with the #GstRtpSession::clear-pt-map
62
* <title>Example pipelines</title>
64
* gst-launch udpsrc port=5000 caps="application/x-rtp, ..." ! .recv_rtp_sink_0 \
65
* gstrtpbin ! rtptheoradepay ! theoradec ! xvimagesink
66
* ]| Receive RTP data from port 5000 and send to the session 0 in gstrtpbin.
68
* gst-launch gstrtpbin name=rtpbin \
69
* v4l2src ! ffmpegcolorspace ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
70
* rtpbin.send_rtp_src_0 ! udpsink port=5000 \
71
* rtpbin.send_rtcp_src_0 ! udpsink port=5001 sync=false async=false \
72
* udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0 \
73
* audiotestsrc ! amrnbenc ! rtpamrpay ! rtpbin.send_rtp_sink_1 \
74
* rtpbin.send_rtp_src_1 ! udpsink port=5002 \
75
* rtpbin.send_rtcp_src_1 ! udpsink port=5003 sync=false async=false \
76
* udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1
77
* ]| Encode and payload H263 video captured from a v4l2src. Encode and payload AMR
78
* audio generated from audiotestsrc. The video is sent to session 0 in rtpbin
79
* and the audio is sent to session 1. Video packets are sent on UDP port 5000
80
* and audio packets on port 5002. The video RTCP packets for session 0 are sent
81
* on port 5001 and the audio RTCP packets for session 0 are sent on port 5003.
82
* RTCP packets for session 0 are received on port 5005 and RTCP for session 1
83
* is received on port 5007. Since RTCP packets from the sender should be sent
84
* as soon as possible and do not participate in preroll, sync=false and
85
* async=false is configured on udpsink
87
* gst-launch -v gstrtpbin name=rtpbin \
88
* udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263-1998" \
89
* port=5000 ! rtpbin.recv_rtp_sink_0 \
90
* rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink \
91
* udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0 \
92
* rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false \
93
* udpsrc caps="application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1" \
94
* port=5002 ! rtpbin.recv_rtp_sink_1 \
95
* rtpbin. ! rtpamrdepay ! amrnbdec ! alsasink \
96
* udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1 \
97
* rtpbin.send_rtcp_src_1 ! udpsink port=5007 sync=false async=false
98
* ]| Receive H263 on port 5000, send it through rtpbin in session 0, depayload,
99
* decode and display the video.
100
* Receive AMR on port 5002, send it through rtpbin in session 1, depayload,
101
* decode and play the audio.
102
* Receive server RTCP packets for session 0 on port 5001 and RTCP packets for
103
* session 1 on port 5003. These packets will be used for session management and
105
* Send RTCP reports for session 0 on port 5005 and RTCP reports for session 1
109
* Last reviewed on 2007-08-30 (0.10.6)
117
#include <gst/rtp/gstrtpbuffer.h>
118
#include <gst/rtp/gstrtcpbuffer.h>
120
#include "gstrtpbin-marshal.h"
121
#include "gstrtpbin.h"
122
#include "rtpsession.h"
123
#include "gstrtpsession.h"
124
#include "gstrtpjitterbuffer.h"
126
GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
127
#define GST_CAT_DEFAULT gst_rtp_bin_debug
129
/* elementfactory information */
130
static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin",
131
"Filter/Network/RTP",
132
"Implement an RTP bin",
133
"Wim Taymans <wim.taymans@gmail.com>");
136
static GstStaticPadTemplate rtpbin_recv_rtp_sink_template =
137
GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink_%d",
140
GST_STATIC_CAPS ("application/x-rtp")
143
static GstStaticPadTemplate rtpbin_recv_rtcp_sink_template =
144
GST_STATIC_PAD_TEMPLATE ("recv_rtcp_sink_%d",
147
GST_STATIC_CAPS ("application/x-rtcp")
150
static GstStaticPadTemplate rtpbin_send_rtp_sink_template =
151
GST_STATIC_PAD_TEMPLATE ("send_rtp_sink_%d",
154
GST_STATIC_CAPS ("application/x-rtp")
158
static GstStaticPadTemplate rtpbin_recv_rtp_src_template =
159
GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
162
GST_STATIC_CAPS ("application/x-rtp")
165
static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
166
GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
169
GST_STATIC_CAPS ("application/x-rtcp")
172
static GstStaticPadTemplate rtpbin_send_rtp_src_template =
173
GST_STATIC_PAD_TEMPLATE ("send_rtp_src_%d",
176
GST_STATIC_CAPS ("application/x-rtp")
179
#define GST_RTP_BIN_GET_PRIVATE(obj) \
180
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BIN, GstRtpBinPrivate))
182
#define GST_RTP_BIN_LOCK(bin) g_mutex_lock ((bin)->priv->bin_lock)
183
#define GST_RTP_BIN_UNLOCK(bin) g_mutex_unlock ((bin)->priv->bin_lock)
185
/* lock to protect dynamic callbacks, like pad-added and new ssrc. */
186
#define GST_RTP_BIN_DYN_LOCK(bin) g_mutex_lock ((bin)->priv->dyn_lock)
187
#define GST_RTP_BIN_DYN_UNLOCK(bin) g_mutex_unlock ((bin)->priv->dyn_lock)
189
/* lock for shutdown */
190
#define GST_RTP_BIN_SHUTDOWN_LOCK(bin,label) \
192
if (g_atomic_int_get (&bin->priv->shutdown)) \
194
GST_RTP_BIN_DYN_LOCK (bin); \
195
if (g_atomic_int_get (&bin->priv->shutdown)) { \
196
GST_RTP_BIN_DYN_UNLOCK (bin); \
201
/* unlock for shutdown */
202
#define GST_RTP_BIN_SHUTDOWN_UNLOCK(bin) \
203
GST_RTP_BIN_DYN_UNLOCK (bin); \
205
struct _GstRtpBinPrivate
209
/* lock protecting dynamic adding/removing */
212
/* the time when we went to playing */
213
GstClockTime ntp_ns_base;
215
/* if we are shutting down or not */
219
/* signals and args */
222
SIGNAL_REQUEST_PT_MAP,
225
SIGNAL_GET_INTERNAL_SESSION,
228
SIGNAL_ON_SSRC_COLLISION,
229
SIGNAL_ON_SSRC_VALIDATED,
230
SIGNAL_ON_SSRC_ACTIVE,
233
SIGNAL_ON_BYE_TIMEOUT,
235
SIGNAL_ON_SENDER_TIMEOUT,
240
#define DEFAULT_LATENCY_MS 200
241
#define DEFAULT_SDES_CNAME NULL
242
#define DEFAULT_SDES_NAME NULL
243
#define DEFAULT_SDES_EMAIL NULL
244
#define DEFAULT_SDES_PHONE NULL
245
#define DEFAULT_SDES_LOCATION NULL
246
#define DEFAULT_SDES_TOOL NULL
247
#define DEFAULT_SDES_NOTE NULL
248
#define DEFAULT_DO_LOST FALSE
266
typedef struct _GstRtpBinSession GstRtpBinSession;
267
typedef struct _GstRtpBinStream GstRtpBinStream;
268
typedef struct _GstRtpBinClient GstRtpBinClient;
270
static guint gst_rtp_bin_signals[LAST_SIGNAL] = { 0 };
272
static GstCaps *pt_map_requested (GstElement * element, guint pt,
273
GstRtpBinSession * session);
274
static const gchar *sdes_type_to_name (GstRTCPSDESType type);
275
static void gst_rtp_bin_set_sdes_string (GstRtpBin * bin,
276
GstRTCPSDESType type, const gchar * data);
278
static void free_stream (GstRtpBinStream * stream);
280
/* Manages the RTP stream for one SSRC.
282
* We pipe the stream (comming from the SSRC demuxer) into a jitterbuffer.
283
* If we see an SDES RTCP packet that links multiple SSRCs together based on a
284
* common CNAME, we create a GstRtpBinClient structure to group the SSRCs
285
* together (see below).
287
struct _GstRtpBinStream
289
/* the SSRC of this stream */
295
/* the session this SSRC belongs to */
296
GstRtpBinSession *session;
298
/* the jitterbuffer of the SSRC */
300
gulong buffer_handlesync_sig;
301
gulong buffer_ptreq_sig;
302
gulong buffer_ntpstop_sig;
304
/* the PT demuxer of the SSRC */
306
gulong demux_newpad_sig;
307
gulong demux_ptreq_sig;
308
gulong demux_pt_change_sig;
309
/* ghostpads from the ptdemuxer */
312
/* if we have calculated a valid unix_delta for this stream */
314
/* mapping to local RTP and NTP time */
318
#define GST_RTP_SESSION_LOCK(sess) g_mutex_lock ((sess)->lock)
319
#define GST_RTP_SESSION_UNLOCK(sess) g_mutex_unlock ((sess)->lock)
321
/* Manages the receiving end of the packets.
323
* There is one such structure for each RTP session (audio/video/...).
324
* We get the RTP/RTCP packets and stuff them into the session manager. From
325
* there they are pushed into an SSRC demuxer that splits the stream based on
326
* SSRC. Each of the SSRC streams go into their own jitterbuffer (managed with
327
* the GstRtpBinStream above).
329
struct _GstRtpBinSession
335
/* the session element */
337
/* the SSRC demuxer */
339
gulong demux_newpad_sig;
340
gulong demux_padremoved_sig;
344
/* list of GstRtpBinStream */
347
/* mapping of payload type to caps */
350
/* the pads of the session */
351
GstPad *recv_rtp_sink;
352
GstPad *recv_rtp_sink_ghost;
353
GstPad *recv_rtp_src;
354
GstPad *recv_rtcp_sink;
355
GstPad *recv_rtcp_sink_ghost;
357
GstPad *send_rtp_sink;
358
GstPad *send_rtp_sink_ghost;
359
GstPad *send_rtp_src;
360
GstPad *send_rtp_src_ghost;
361
GstPad *send_rtcp_src;
362
GstPad *send_rtcp_src_ghost;
365
/* Manages the RTP streams that come from one client and should therefore be
368
struct _GstRtpBinClient
370
/* the common CNAME for the streams */
379
/* find a session with the given id. Must be called with RTP_BIN_LOCK */
380
static GstRtpBinSession *
381
find_session_by_id (GstRtpBin * rtpbin, gint id)
385
for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
386
GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
394
/* find a session with the given request pad. Must be called with RTP_BIN_LOCK */
395
static GstRtpBinSession *
396
find_session_by_pad (GstRtpBin * rtpbin, GstPad * pad)
400
for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
401
GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
403
if ((sess->recv_rtp_sink_ghost == pad) ||
404
(sess->recv_rtcp_sink_ghost == pad) ||
405
(sess->send_rtp_sink_ghost == pad)
406
|| (sess->send_rtcp_src_ghost == pad))
413
on_new_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
415
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC], 0,
420
on_ssrc_collision (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
422
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION], 0,
427
on_ssrc_validated (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
429
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED], 0,
434
on_ssrc_active (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
436
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE], 0,
441
on_ssrc_sdes (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
443
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES], 0,
448
on_bye_ssrc (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
450
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC], 0,
455
on_bye_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
457
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT], 0,
462
on_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
464
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT], 0,
469
on_sender_timeout (GstElement * session, guint32 ssrc, GstRtpBinSession * sess)
471
g_signal_emit (sess->bin, gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT], 0,
476
on_npt_stop (GstElement * jbuf, GstRtpBinStream * stream)
478
g_signal_emit (stream->bin, gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP], 0,
479
stream->session->id, stream->ssrc);
482
/* must be called with the SESSION lock */
483
static GstRtpBinStream *
484
find_stream_by_ssrc (GstRtpBinSession * session, guint32 ssrc)
488
for (walk = session->streams; walk; walk = g_slist_next (walk)) {
489
GstRtpBinStream *stream = (GstRtpBinStream *) walk->data;
491
if (stream->ssrc == ssrc)
498
ssrc_demux_pad_removed (GstElement * element, guint ssrc, GstPad * pad,
499
GstRtpBinSession * session)
501
GstRtpBinStream *stream = NULL;
503
GST_RTP_SESSION_LOCK (session);
504
if ((stream = find_stream_by_ssrc (session, ssrc)))
505
session->streams = g_slist_remove (session->streams, stream);
506
GST_RTP_SESSION_UNLOCK (session);
509
free_stream (stream);
512
/* create a session with the given id. Must be called with RTP_BIN_LOCK */
513
static GstRtpBinSession *
514
create_session (GstRtpBin * rtpbin, gint id)
516
GstRtpBinSession *sess;
517
GstElement *session, *demux;
521
if (!(session = gst_element_factory_make ("gstrtpsession", NULL)))
524
if (!(demux = gst_element_factory_make ("gstrtpssrcdemux", NULL)))
527
sess = g_new0 (GstRtpBinSession, 1);
528
sess->lock = g_mutex_new ();
531
sess->session = session;
533
sess->ptmap = g_hash_table_new_full (NULL, NULL, NULL,
534
(GDestroyNotify) gst_caps_unref);
535
rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
537
/* set NTP base or new session */
538
g_object_set (session, "ntp-ns-base", rtpbin->priv->ntp_ns_base, NULL);
539
/* configure SDES items */
540
GST_OBJECT_LOCK (rtpbin);
541
for (i = GST_RTCP_SDES_CNAME; i < GST_RTCP_SDES_PRIV; i++) {
542
g_object_set (session, sdes_type_to_name (i), rtpbin->sdes[i], NULL);
544
GST_OBJECT_UNLOCK (rtpbin);
546
/* provide clock_rate to the session manager when needed */
547
g_signal_connect (session, "request-pt-map",
548
(GCallback) pt_map_requested, sess);
550
g_signal_connect (sess->session, "on-new-ssrc",
551
(GCallback) on_new_ssrc, sess);
552
g_signal_connect (sess->session, "on-ssrc-collision",
553
(GCallback) on_ssrc_collision, sess);
554
g_signal_connect (sess->session, "on-ssrc-validated",
555
(GCallback) on_ssrc_validated, sess);
556
g_signal_connect (sess->session, "on-ssrc-active",
557
(GCallback) on_ssrc_active, sess);
558
g_signal_connect (sess->session, "on-ssrc-sdes",
559
(GCallback) on_ssrc_sdes, sess);
560
g_signal_connect (sess->session, "on-bye-ssrc",
561
(GCallback) on_bye_ssrc, sess);
562
g_signal_connect (sess->session, "on-bye-timeout",
563
(GCallback) on_bye_timeout, sess);
564
g_signal_connect (sess->session, "on-timeout", (GCallback) on_timeout, sess);
565
g_signal_connect (sess->session, "on-sender-timeout",
566
(GCallback) on_sender_timeout, sess);
568
gst_bin_add (GST_BIN_CAST (rtpbin), session);
569
gst_bin_add (GST_BIN_CAST (rtpbin), demux);
571
GST_OBJECT_LOCK (rtpbin);
572
target = GST_STATE_TARGET (rtpbin);
573
GST_OBJECT_UNLOCK (rtpbin);
575
/* change state only to what's needed */
576
gst_element_set_state (demux, target);
577
gst_element_set_state (session, target);
584
g_warning ("gstrtpbin: could not create gstrtpsession element");
589
gst_object_unref (session);
590
g_warning ("gstrtpbin: could not create gstrtpssrcdemux element");
596
free_session (GstRtpBinSession * sess, GstRtpBin * bin)
598
GST_DEBUG_OBJECT (bin, "freeing session %p", sess);
600
gst_element_set_state (sess->demux, GST_STATE_NULL);
601
gst_element_set_state (sess->session, GST_STATE_NULL);
603
if (sess->recv_rtp_sink != NULL) {
604
gst_element_release_request_pad (sess->session, sess->recv_rtp_sink);
605
gst_object_unref (sess->recv_rtp_sink);
607
if (sess->recv_rtp_src != NULL)
608
gst_object_unref (sess->recv_rtp_src);
609
if (sess->recv_rtcp_sink != NULL) {
610
gst_element_release_request_pad (sess->session, sess->recv_rtcp_sink);
611
gst_object_unref (sess->recv_rtcp_sink);
613
if (sess->sync_src != NULL)
614
gst_object_unref (sess->sync_src);
615
if (sess->send_rtp_sink != NULL) {
616
gst_element_release_request_pad (sess->session, sess->send_rtp_sink);
617
gst_object_unref (sess->send_rtp_sink);
619
if (sess->send_rtp_src != NULL)
620
gst_object_unref (sess->send_rtp_src);
621
if (sess->send_rtcp_src != NULL) {
622
gst_element_release_request_pad (sess->session, sess->send_rtcp_src);
623
gst_object_unref (sess->send_rtcp_src);
626
gst_bin_remove (GST_BIN_CAST (bin), sess->session);
627
gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
629
g_slist_foreach (sess->streams, (GFunc) free_stream, NULL);
630
g_slist_free (sess->streams);
632
g_mutex_free (sess->lock);
633
g_hash_table_destroy (sess->ptmap);
638
/* get the payload type caps for the specific payload @pt in @session */
640
get_pt_map (GstRtpBinSession * session, guint pt)
642
GstCaps *caps = NULL;
645
GValue args[3] = { {0}, {0}, {0} };
647
GST_DEBUG ("searching pt %d in cache", pt);
649
GST_RTP_SESSION_LOCK (session);
651
/* first look in the cache */
652
caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
660
GST_DEBUG ("emiting signal for pt %d in session %d", pt, session->id);
662
/* not in cache, send signal to request caps */
663
g_value_init (&args[0], GST_TYPE_ELEMENT);
664
g_value_set_object (&args[0], bin);
665
g_value_init (&args[1], G_TYPE_UINT);
666
g_value_set_uint (&args[1], session->id);
667
g_value_init (&args[2], G_TYPE_UINT);
668
g_value_set_uint (&args[2], pt);
670
g_value_init (&ret, GST_TYPE_CAPS);
671
g_value_set_boxed (&ret, NULL);
673
GST_RTP_SESSION_UNLOCK (session);
675
g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
677
GST_RTP_SESSION_LOCK (session);
679
g_value_unset (&args[0]);
680
g_value_unset (&args[1]);
681
g_value_unset (&args[2]);
683
/* look in the cache again because we let the lock go */
684
caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
687
g_value_unset (&ret);
691
caps = (GstCaps *) g_value_dup_boxed (&ret);
692
g_value_unset (&ret);
696
GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
698
/* store in cache, take additional ref */
699
g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt),
700
gst_caps_ref (caps));
703
GST_RTP_SESSION_UNLOCK (session);
710
GST_RTP_SESSION_UNLOCK (session);
711
GST_DEBUG ("no pt map could be obtained");
717
return_true (gpointer key, gpointer value, gpointer user_data)
723
gst_rtp_bin_reset_sync (GstRtpBin * rtpbin)
725
GSList *clients, *streams;
727
GST_DEBUG_OBJECT (rtpbin, "Reset sync on all clients");
729
GST_RTP_BIN_LOCK (rtpbin);
730
for (clients = rtpbin->clients; clients; clients = g_slist_next (clients)) {
731
GstRtpBinClient *client = (GstRtpBinClient *) clients->data;
733
/* reset sync on all streams for this client */
734
for (streams = client->streams; streams; streams = g_slist_next (streams)) {
735
GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
737
/* make use require a new SR packet for this stream before we attempt new
739
stream->have_sync = FALSE;
740
stream->unix_delta = 0;
743
GST_RTP_BIN_UNLOCK (rtpbin);
747
gst_rtp_bin_clear_pt_map (GstRtpBin * bin)
749
GSList *sessions, *streams;
751
GST_RTP_BIN_LOCK (bin);
752
GST_DEBUG_OBJECT (bin, "clearing pt map");
753
for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
754
GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
756
GST_DEBUG_OBJECT (bin, "clearing session %p", session);
757
g_signal_emit_by_name (session->session, "clear-pt-map", NULL);
759
GST_RTP_SESSION_LOCK (session);
760
g_hash_table_foreach_remove (session->ptmap, return_true, NULL);
762
for (streams = session->streams; streams; streams = g_slist_next (streams)) {
763
GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
765
GST_DEBUG_OBJECT (bin, "clearing stream %p", stream);
766
g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL);
767
g_signal_emit_by_name (stream->demux, "clear-pt-map", NULL);
769
GST_RTP_SESSION_UNLOCK (session);
771
GST_RTP_BIN_UNLOCK (bin);
774
gst_rtp_bin_reset_sync (bin);
778
gst_rtp_bin_get_internal_session (GstRtpBin * bin, guint session_id)
780
RTPSession *internal_session = NULL;
781
GstRtpBinSession *session;
783
GST_RTP_BIN_LOCK (bin);
784
GST_DEBUG_OBJECT (bin, "retrieving internal RTPSession object, index: %d",
786
session = find_session_by_id (bin, (gint) session_id);
788
g_object_get (session->session, "internal-session", &internal_session,
791
GST_RTP_BIN_UNLOCK (bin);
793
return internal_session;
797
gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin,
798
const gchar * name, const GValue * value)
800
GSList *sessions, *streams;
802
GST_RTP_BIN_LOCK (bin);
803
for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
804
GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
806
GST_RTP_SESSION_LOCK (session);
807
for (streams = session->streams; streams; streams = g_slist_next (streams)) {
808
GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
810
g_object_set_property (G_OBJECT (stream->buffer), name, value);
812
GST_RTP_SESSION_UNLOCK (session);
814
GST_RTP_BIN_UNLOCK (bin);
817
/* get a client with the given SDES name. Must be called with RTP_BIN_LOCK */
818
static GstRtpBinClient *
819
get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created)
821
GstRtpBinClient *result = NULL;
824
for (walk = bin->clients; walk; walk = g_slist_next (walk)) {
825
GstRtpBinClient *client = (GstRtpBinClient *) walk->data;
827
if (len != client->cname_len)
830
if (!strncmp ((gchar *) data, client->cname, client->cname_len)) {
831
GST_DEBUG_OBJECT (bin, "found existing client %p with CNAME %s", client,
838
/* nothing found, create one */
839
if (result == NULL) {
840
result = g_new0 (GstRtpBinClient, 1);
841
result->cname = g_strndup ((gchar *) data, len);
842
result->cname_len = len;
843
bin->clients = g_slist_prepend (bin->clients, result);
844
GST_DEBUG_OBJECT (bin, "created new client %p with CNAME %s", result,
851
free_client (GstRtpBinClient * client, GstRtpBin * bin)
853
GST_DEBUG_OBJECT (bin, "freeing client %p", client);
854
g_slist_free (client->streams);
855
g_free (client->cname);
859
/* associate a stream to the given CNAME. This will make sure all streams for
860
* that CNAME are synchronized together.
861
* Must be called with GST_RTP_BIN_LOCK */
863
gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len,
864
guint8 * data, guint64 last_unix, guint64 last_extrtptime,
865
guint64 clock_base, guint64 clock_base_time, guint clock_rate)
867
GstRtpBinClient *client;
873
/* first find or create the CNAME */
874
client = get_client (bin, len, data, &created);
876
/* find stream in the client */
877
for (walk = client->streams; walk; walk = g_slist_next (walk)) {
878
GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
880
if (ostream == stream)
883
/* not found, add it to the list */
885
GST_DEBUG_OBJECT (bin,
886
"new association of SSRC %08x with client %p with CNAME %s",
887
stream->ssrc, client, client->cname);
888
client->streams = g_slist_prepend (client->streams, stream);
891
GST_DEBUG_OBJECT (bin,
892
"found association of SSRC %08x with client %p with CNAME %s",
893
stream->ssrc, client, client->cname);
896
/* take the extended rtptime we found in the SR packet and map it to the
897
* local rtptime. The local rtp time is used to construct timestamps on the
899
local_rtp = last_extrtptime - clock_base;
901
GST_DEBUG_OBJECT (bin,
902
"base %" G_GUINT64_FORMAT ", extrtptime %" G_GUINT64_FORMAT
903
", local RTP %" G_GUINT64_FORMAT ", clock-rate %d", clock_base,
904
last_extrtptime, local_rtp, clock_rate);
906
/* calculate local NTP time in gstreamer timestamp, we essentially perform the
907
* same conversion that a jitterbuffer would use to convert an rtp timestamp
908
* into a corresponding gstreamer timestamp. */
909
local_unix = gst_util_uint64_scale_int (local_rtp, GST_SECOND, clock_rate);
910
local_unix += clock_base_time;
912
/* calculate delta between server and receiver. last_unix is created by
913
* converting the ntptime in the last SR packet to a gstreamer timestamp. This
914
* delta expresses the difference to our timeline and the server timeline. */
915
stream->unix_delta = last_unix - local_unix;
916
stream->have_sync = TRUE;
918
GST_DEBUG_OBJECT (bin,
919
"local UNIX %" G_GUINT64_FORMAT ", remote UNIX %" G_GUINT64_FORMAT
920
", delta %" G_GINT64_FORMAT, local_unix, last_unix, stream->unix_delta);
922
/* recalc inter stream playout offset, but only if there is more than one
924
if (client->nstreams > 1) {
927
/* calculate the min of all deltas, ignoring streams that did not yet have a
928
* valid unix_delta because we did not yet receive an SR packet for those
930
* We calculate the mininum because we would like to only apply positive
931
* offsets to streams, delaying their playback instead of trying to speed up
932
* other streams (which might be imposible when we have to create negative
934
* The stream that has the smallest diff is selected as the reference stream,
935
* all other streams will have a positive offset to this difference. */
937
for (walk = client->streams; walk; walk = g_slist_next (walk)) {
938
GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
940
if (!ostream->have_sync)
943
if (ostream->unix_delta < min)
944
min = ostream->unix_delta;
947
GST_DEBUG_OBJECT (bin, "client %p min delta %" G_GINT64_FORMAT, client,
950
/* calculate offsets for each stream */
951
for (walk = client->streams; walk; walk = g_slist_next (walk)) {
952
GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
953
gint64 ts_offset, prev_ts_offset;
955
/* ignore streams for which we didn't receive an SR packet yet, we
956
* can't synchronize them yet. We can however sync other streams just
958
if (!ostream->have_sync)
961
/* calculate offset to our reference stream, this should always give a
962
* positive number. */
963
ts_offset = ostream->unix_delta - min;
965
g_object_get (ostream->buffer, "ts-offset", &prev_ts_offset, NULL);
967
/* delta changed, see how much */
968
if (prev_ts_offset != ts_offset) {
971
if (prev_ts_offset > ts_offset)
972
diff = prev_ts_offset - ts_offset;
974
diff = ts_offset - prev_ts_offset;
976
GST_DEBUG_OBJECT (bin,
977
"ts-offset %" G_GUINT64_FORMAT ", prev %" G_GUINT64_FORMAT
978
", diff: %" G_GINT64_FORMAT, ts_offset, prev_ts_offset, diff);
980
/* only change diff when it changed more than 4 milliseconds. This
981
* compensates for rounding errors in NTP to RTP timestamp
983
if (diff > 4 * GST_MSECOND && diff < (3 * GST_SECOND)) {
984
g_object_set (ostream->buffer, "ts-offset", ts_offset, NULL);
987
GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT,
988
ostream->ssrc, ts_offset);
994
#define GST_RTCP_BUFFER_FOR_PACKETS(b,buffer,packet) \
995
for ((b) = gst_rtcp_buffer_get_first_packet ((buffer), (packet)); (b); \
996
(b) = gst_rtcp_packet_move_to_next ((packet)))
998
#define GST_RTCP_SDES_FOR_ITEMS(b,packet) \
999
for ((b) = gst_rtcp_packet_sdes_first_item ((packet)); (b); \
1000
(b) = gst_rtcp_packet_sdes_next_item ((packet)))
1002
#define GST_RTCP_SDES_FOR_ENTRIES(b,packet) \
1003
for ((b) = gst_rtcp_packet_sdes_first_entry ((packet)); (b); \
1004
(b) = gst_rtcp_packet_sdes_next_entry ((packet)))
1007
gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
1008
GstRtpBinStream * stream)
1011
GstRTCPPacket packet;
1014
gboolean have_sr, have_sdes;
1017
guint64 clock_base_time;
1024
GST_DEBUG_OBJECT (bin, "sync handler called");
1026
/* get the last relation between the rtp timestamps and the gstreamer
1027
* timestamps. We get this info directly from the jitterbuffer which
1028
* constructs gstreamer timestamps from rtp timestamps and so it know exactly
1029
* what the current situation is. */
1030
clock_base = g_value_get_uint64 (gst_structure_get_value (s, "base-rtptime"));
1032
g_value_get_uint64 (gst_structure_get_value (s, "base-time"));
1033
clock_rate = g_value_get_uint (gst_structure_get_value (s, "clock-rate"));
1035
g_value_get_uint64 (gst_structure_get_value (s, "sr-ext-rtptime"));
1036
buffer = gst_value_get_buffer (gst_structure_get_value (s, "sr-buffer"));
1040
GST_RTCP_BUFFER_FOR_PACKETS (more, buffer, &packet) {
1041
/* first packet must be SR or RR or else the validate would have failed */
1042
switch (gst_rtcp_packet_get_type (&packet)) {
1043
case GST_RTCP_TYPE_SR:
1044
/* only parse first. There is only supposed to be one SR in the packet
1045
* but we will deal with malformed packets gracefully */
1048
/* get NTP and RTP times */
1049
gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, NULL,
1052
GST_DEBUG_OBJECT (bin, "received sync packet from SSRC %08x", ssrc);
1053
/* ignore SR that is not ours */
1054
if (ssrc != stream->ssrc)
1059
case GST_RTCP_TYPE_SDES:
1061
gboolean more_items, more_entries;
1063
/* only deal with first SDES, there is only supposed to be one SDES in
1064
* the RTCP packet but we deal with bad packets gracefully. Also bail
1065
* out if we have not seen an SR item yet. */
1066
if (have_sdes || !have_sr)
1069
GST_RTCP_SDES_FOR_ITEMS (more_items, &packet) {
1070
/* skip items that are not about the SSRC of the sender */
1071
if (gst_rtcp_packet_sdes_get_ssrc (&packet) != ssrc)
1074
/* find the CNAME entry */
1075
GST_RTCP_SDES_FOR_ENTRIES (more_entries, &packet) {
1076
GstRTCPSDESType type;
1080
gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data);
1082
if (type == GST_RTCP_SDES_CNAME) {
1083
GST_RTP_BIN_LOCK (bin);
1084
/* associate the stream to CNAME */
1085
gst_rtp_bin_associate (bin, stream, len, data,
1086
gst_rtcp_ntp_to_unix (ntptime), extrtptime,
1087
clock_base, clock_base_time, clock_rate);
1088
GST_RTP_BIN_UNLOCK (bin);
1096
/* we can ignore these packets */
1102
/* create a new stream with @ssrc in @session. Must be called with
1103
* RTP_SESSION_LOCK. */
1104
static GstRtpBinStream *
1105
create_stream (GstRtpBinSession * session, guint32 ssrc)
1107
GstElement *buffer, *demux;
1108
GstRtpBinStream *stream;
1112
if (!(buffer = gst_element_factory_make ("gstrtpjitterbuffer", NULL)))
1113
goto no_jitterbuffer;
1115
if (!(demux = gst_element_factory_make ("gstrtpptdemux", NULL)))
1118
rtpbin = session->bin;
1120
stream = g_new0 (GstRtpBinStream, 1);
1121
stream->ssrc = ssrc;
1122
stream->bin = rtpbin;
1123
stream->session = session;
1124
stream->buffer = buffer;
1125
stream->demux = demux;
1126
stream->have_sync = FALSE;
1127
stream->unix_delta = 0;
1128
session->streams = g_slist_prepend (session->streams, stream);
1130
/* provide clock_rate to the jitterbuffer when needed */
1131
stream->buffer_ptreq_sig = g_signal_connect (buffer, "request-pt-map",
1132
(GCallback) pt_map_requested, session);
1133
stream->buffer_ntpstop_sig = g_signal_connect (buffer, "on-npt-stop",
1134
(GCallback) on_npt_stop, stream);
1136
/* configure latency and packet lost */
1137
g_object_set (buffer, "latency", rtpbin->latency, NULL);
1138
g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL);
1140
gst_bin_add (GST_BIN_CAST (rtpbin), demux);
1141
gst_bin_add (GST_BIN_CAST (rtpbin), buffer);
1144
gst_element_link (buffer, demux);
1146
GST_OBJECT_LOCK (rtpbin);
1147
target = GST_STATE_TARGET (rtpbin);
1148
GST_OBJECT_UNLOCK (rtpbin);
1150
/* from sink to source */
1151
gst_element_set_state (demux, target);
1152
gst_element_set_state (buffer, target);
1159
g_warning ("gstrtpbin: could not create gstrtpjitterbuffer element");
1164
gst_object_unref (buffer);
1165
g_warning ("gstrtpbin: could not create gstrtpptdemux element");
1171
free_stream (GstRtpBinStream * stream)
1173
GstRtpBinSession *session;
1176
session = stream->session;
1178
g_signal_handler_disconnect (stream->demux, stream->demux_newpad_sig);
1179
g_signal_handler_disconnect (stream->demux, stream->demux_ptreq_sig);
1180
g_signal_handler_disconnect (stream->buffer, stream->buffer_handlesync_sig);
1181
g_signal_handler_disconnect (stream->buffer, stream->buffer_ptreq_sig);
1182
g_signal_handler_disconnect (stream->buffer, stream->buffer_ntpstop_sig);
1184
gst_element_set_state (stream->demux, GST_STATE_NULL);
1185
gst_element_set_state (stream->buffer, GST_STATE_NULL);
1187
gst_bin_remove (GST_BIN_CAST (session->bin), stream->buffer);
1188
gst_bin_remove (GST_BIN_CAST (session->bin), stream->demux);
1190
for (walk = stream->pads; walk; walk = g_slist_next (walk)) {
1191
GstPad *gpad = GST_PAD_CAST (walk->data);
1193
gst_pad_set_active (gpad, FALSE);
1194
gst_element_remove_pad (GST_ELEMENT_CAST (session->bin), gpad);
1196
g_slist_free (stream->pads);
1201
/* GObject vmethods */
1202
static void gst_rtp_bin_dispose (GObject * object);
1203
static void gst_rtp_bin_finalize (GObject * object);
1204
static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
1205
const GValue * value, GParamSpec * pspec);
1206
static void gst_rtp_bin_get_property (GObject * object, guint prop_id,
1207
GValue * value, GParamSpec * pspec);
1209
/* GstElement vmethods */
1210
static GstStateChangeReturn gst_rtp_bin_change_state (GstElement * element,
1211
GstStateChange transition);
1212
static GstPad *gst_rtp_bin_request_new_pad (GstElement * element,
1213
GstPadTemplate * templ, const gchar * name);
1214
static void gst_rtp_bin_release_pad (GstElement * element, GstPad * pad);
1215
static void gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message);
1216
static void gst_rtp_bin_clear_pt_map (GstRtpBin * bin);
1218
GST_BOILERPLATE (GstRtpBin, gst_rtp_bin, GstBin, GST_TYPE_BIN);
1221
gst_rtp_bin_base_init (gpointer klass)
1223
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
1226
gst_element_class_add_pad_template (element_class,
1227
gst_static_pad_template_get (&rtpbin_recv_rtp_sink_template));
1228
gst_element_class_add_pad_template (element_class,
1229
gst_static_pad_template_get (&rtpbin_recv_rtcp_sink_template));
1230
gst_element_class_add_pad_template (element_class,
1231
gst_static_pad_template_get (&rtpbin_send_rtp_sink_template));
1234
gst_element_class_add_pad_template (element_class,
1235
gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
1236
gst_element_class_add_pad_template (element_class,
1237
gst_static_pad_template_get (&rtpbin_send_rtcp_src_template));
1238
gst_element_class_add_pad_template (element_class,
1239
gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
1241
gst_element_class_set_details (element_class, &rtpbin_details);
1245
gst_rtp_bin_class_init (GstRtpBinClass * klass)
1247
GObjectClass *gobject_class;
1248
GstElementClass *gstelement_class;
1249
GstBinClass *gstbin_class;
1251
gobject_class = (GObjectClass *) klass;
1252
gstelement_class = (GstElementClass *) klass;
1253
gstbin_class = (GstBinClass *) klass;
1255
g_type_class_add_private (klass, sizeof (GstRtpBinPrivate));
1257
gobject_class->dispose = gst_rtp_bin_dispose;
1258
gobject_class->finalize = gst_rtp_bin_finalize;
1259
gobject_class->set_property = gst_rtp_bin_set_property;
1260
gobject_class->get_property = gst_rtp_bin_get_property;
1262
g_object_class_install_property (gobject_class, PROP_LATENCY,
1263
g_param_spec_uint ("latency", "Buffer latency in ms",
1264
"Default amount of ms to buffer in the jitterbuffers", 0,
1265
G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE));
1268
* GstRtpBin::request-pt-map:
1269
* @rtpbin: the object which received the signal
1270
* @session: the session
1273
* Request the payload type as #GstCaps for @pt in @session.
1275
gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP] =
1276
g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
1277
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, request_pt_map),
1278
NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT_UINT, GST_TYPE_CAPS, 2,
1279
G_TYPE_UINT, G_TYPE_UINT);
1281
* GstRtpBin::clear-pt-map:
1282
* @rtpbin: the object which received the signal
1284
* Clear all previously cached pt-mapping obtained with
1285
* #GstRtpBin::request-pt-map.
1287
gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] =
1288
g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
1289
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
1290
clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
1293
* GstRtpBin::reset-sync:
1294
* @rtpbin: the object which received the signal
1296
* Reset all currently configured lip-sync parameters and require new SR
1297
* packets for all streams before lip-sync is attempted again.
1299
gst_rtp_bin_signals[SIGNAL_RESET_SYNC] =
1300
g_signal_new ("reset-sync", G_TYPE_FROM_CLASS (klass),
1301
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
1302
reset_sync), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
1306
* GstRtpBin::get-internal-session:
1307
* @rtpbin: the object which received the signal
1308
* @id: the session id
1310
* Request the internal RTPSession object as #GObject in session @id.
1312
gst_rtp_bin_signals[SIGNAL_GET_INTERNAL_SESSION] =
1313
g_signal_new ("get-internal-session", G_TYPE_FROM_CLASS (klass),
1314
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass,
1315
get_internal_session), NULL, NULL, gst_rtp_bin_marshal_OBJECT__UINT,
1316
RTP_TYPE_SESSION, 1, G_TYPE_UINT);
1319
* GstRtpBin::on-new-ssrc:
1320
* @rtpbin: the object which received the signal
1321
* @session: the session
1324
* Notify of a new SSRC that entered @session.
1326
gst_rtp_bin_signals[SIGNAL_ON_NEW_SSRC] =
1327
g_signal_new ("on-new-ssrc", G_TYPE_FROM_CLASS (klass),
1328
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_new_ssrc),
1329
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1330
G_TYPE_UINT, G_TYPE_UINT);
1332
* GstRtpBin::on-ssrc-collision:
1333
* @rtpbin: the object which received the signal
1334
* @session: the session
1337
* Notify when we have an SSRC collision
1339
gst_rtp_bin_signals[SIGNAL_ON_SSRC_COLLISION] =
1340
g_signal_new ("on-ssrc-collision", G_TYPE_FROM_CLASS (klass),
1341
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_collision),
1342
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1343
G_TYPE_UINT, G_TYPE_UINT);
1345
* GstRtpBin::on-ssrc-validated:
1346
* @rtpbin: the object which received the signal
1347
* @session: the session
1350
* Notify of a new SSRC that became validated.
1352
gst_rtp_bin_signals[SIGNAL_ON_SSRC_VALIDATED] =
1353
g_signal_new ("on-ssrc-validated", G_TYPE_FROM_CLASS (klass),
1354
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_validated),
1355
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1356
G_TYPE_UINT, G_TYPE_UINT);
1358
* GstRtpBin::on-ssrc-active:
1359
* @rtpbin: the object which received the signal
1360
* @session: the session
1363
* Notify of a SSRC that is active, i.e., sending RTCP.
1365
gst_rtp_bin_signals[SIGNAL_ON_SSRC_ACTIVE] =
1366
g_signal_new ("on-ssrc-active", G_TYPE_FROM_CLASS (klass),
1367
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_active),
1368
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1369
G_TYPE_UINT, G_TYPE_UINT);
1371
* GstRtpBin::on-ssrc-sdes:
1372
* @rtpbin: the object which received the signal
1373
* @session: the session
1376
* Notify of a SSRC that is active, i.e., sending RTCP.
1378
gst_rtp_bin_signals[SIGNAL_ON_SSRC_SDES] =
1379
g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass),
1380
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_ssrc_sdes),
1381
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1382
G_TYPE_UINT, G_TYPE_UINT);
1385
* GstRtpBin::on-bye-ssrc:
1386
* @rtpbin: the object which received the signal
1387
* @session: the session
1390
* Notify of an SSRC that became inactive because of a BYE packet.
1392
gst_rtp_bin_signals[SIGNAL_ON_BYE_SSRC] =
1393
g_signal_new ("on-bye-ssrc", G_TYPE_FROM_CLASS (klass),
1394
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_ssrc),
1395
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1396
G_TYPE_UINT, G_TYPE_UINT);
1398
* GstRtpBin::on-bye-timeout:
1399
* @rtpbin: the object which received the signal
1400
* @session: the session
1403
* Notify of an SSRC that has timed out because of BYE
1405
gst_rtp_bin_signals[SIGNAL_ON_BYE_TIMEOUT] =
1406
g_signal_new ("on-bye-timeout", G_TYPE_FROM_CLASS (klass),
1407
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_bye_timeout),
1408
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1409
G_TYPE_UINT, G_TYPE_UINT);
1411
* GstRtpBin::on-timeout:
1412
* @rtpbin: the object which received the signal
1413
* @session: the session
1416
* Notify of an SSRC that has timed out
1418
gst_rtp_bin_signals[SIGNAL_ON_TIMEOUT] =
1419
g_signal_new ("on-timeout", G_TYPE_FROM_CLASS (klass),
1420
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_timeout),
1421
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1422
G_TYPE_UINT, G_TYPE_UINT);
1424
* GstRtpBin::on-sender-timeout:
1425
* @rtpbin: the object which received the signal
1426
* @session: the session
1429
* Notify of a sender SSRC that has timed out and became a receiver
1431
gst_rtp_bin_signals[SIGNAL_ON_SENDER_TIMEOUT] =
1432
g_signal_new ("on-sender-timeout", G_TYPE_FROM_CLASS (klass),
1433
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_sender_timeout),
1434
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1435
G_TYPE_UINT, G_TYPE_UINT);
1438
* GstRtpBin::on-npt-stop:
1439
* @rtpbin: the object which received the signal
1440
* @session: the session
1443
* Notify that SSRC sender has sent data up to the configured NPT stop time.
1445
gst_rtp_bin_signals[SIGNAL_ON_NPT_STOP] =
1446
g_signal_new ("on-npt-stop", G_TYPE_FROM_CLASS (klass),
1447
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass, on_npt_stop),
1448
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2,
1449
G_TYPE_UINT, G_TYPE_UINT);
1451
g_object_class_install_property (gobject_class, PROP_SDES_CNAME,
1452
g_param_spec_string ("sdes-cname", "SDES CNAME",
1453
"The CNAME to put in SDES messages of this session",
1454
DEFAULT_SDES_CNAME, G_PARAM_READWRITE));
1456
g_object_class_install_property (gobject_class, PROP_SDES_NAME,
1457
g_param_spec_string ("sdes-name", "SDES NAME",
1458
"The NAME to put in SDES messages of this session",
1459
DEFAULT_SDES_NAME, G_PARAM_READWRITE));
1461
g_object_class_install_property (gobject_class, PROP_SDES_EMAIL,
1462
g_param_spec_string ("sdes-email", "SDES EMAIL",
1463
"The EMAIL to put in SDES messages of this session",
1464
DEFAULT_SDES_EMAIL, G_PARAM_READWRITE));
1466
g_object_class_install_property (gobject_class, PROP_SDES_PHONE,
1467
g_param_spec_string ("sdes-phone", "SDES PHONE",
1468
"The PHONE to put in SDES messages of this session",
1469
DEFAULT_SDES_PHONE, G_PARAM_READWRITE));
1471
g_object_class_install_property (gobject_class, PROP_SDES_LOCATION,
1472
g_param_spec_string ("sdes-location", "SDES LOCATION",
1473
"The LOCATION to put in SDES messages of this session",
1474
DEFAULT_SDES_LOCATION, G_PARAM_READWRITE));
1476
g_object_class_install_property (gobject_class, PROP_SDES_TOOL,
1477
g_param_spec_string ("sdes-tool", "SDES TOOL",
1478
"The TOOL to put in SDES messages of this session",
1479
DEFAULT_SDES_TOOL, G_PARAM_READWRITE));
1481
g_object_class_install_property (gobject_class, PROP_SDES_NOTE,
1482
g_param_spec_string ("sdes-note", "SDES NOTE",
1483
"The NOTE to put in SDES messages of this session",
1484
DEFAULT_SDES_NOTE, G_PARAM_READWRITE));
1486
g_object_class_install_property (gobject_class, PROP_DO_LOST,
1487
g_param_spec_boolean ("do-lost", "Do Lost",
1488
"Send an event downstream when a packet is lost", DEFAULT_DO_LOST,
1489
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1491
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
1492
gstelement_class->request_new_pad =
1493
GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
1494
gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_bin_release_pad);
1496
gstbin_class->handle_message = GST_DEBUG_FUNCPTR (gst_rtp_bin_handle_message);
1498
klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_bin_clear_pt_map);
1499
klass->reset_sync = GST_DEBUG_FUNCPTR (gst_rtp_bin_reset_sync);
1500
klass->get_internal_session =
1501
GST_DEBUG_FUNCPTR (gst_rtp_bin_get_internal_session);
1503
GST_DEBUG_CATEGORY_INIT (gst_rtp_bin_debug, "rtpbin", 0, "RTP bin");
1507
gst_rtp_bin_init (GstRtpBin * rtpbin, GstRtpBinClass * klass)
1511
rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
1512
rtpbin->priv->bin_lock = g_mutex_new ();
1513
rtpbin->priv->dyn_lock = g_mutex_new ();
1515
rtpbin->latency = DEFAULT_LATENCY_MS;
1516
rtpbin->do_lost = DEFAULT_DO_LOST;
1518
/* some default SDES entries */
1519
str = g_strdup_printf ("%s@%s", g_get_user_name (), g_get_host_name ());
1520
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_CNAME, str);
1523
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_NAME, g_get_real_name ());
1524
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_TOOL, "GStreamer");
1528
gst_rtp_bin_dispose (GObject * object)
1532
rtpbin = GST_RTP_BIN (object);
1534
GST_DEBUG_OBJECT (object, "freeing sessions");
1535
g_slist_foreach (rtpbin->sessions, (GFunc) free_session, rtpbin);
1536
g_slist_free (rtpbin->sessions);
1537
rtpbin->sessions = NULL;
1538
GST_DEBUG_OBJECT (object, "freeing clients");
1539
g_slist_foreach (rtpbin->clients, (GFunc) free_client, rtpbin);
1540
g_slist_free (rtpbin->clients);
1541
rtpbin->clients = NULL;
1543
G_OBJECT_CLASS (parent_class)->dispose (object);
1547
gst_rtp_bin_finalize (GObject * object)
1552
rtpbin = GST_RTP_BIN (object);
1554
for (i = 0; i < 9; i++)
1555
g_free (rtpbin->sdes[i]);
1557
g_mutex_free (rtpbin->priv->bin_lock);
1558
g_mutex_free (rtpbin->priv->dyn_lock);
1560
G_OBJECT_CLASS (parent_class)->finalize (object);
1563
static const gchar *
1564
sdes_type_to_name (GstRTCPSDESType type)
1566
const gchar *result;
1569
case GST_RTCP_SDES_CNAME:
1570
result = "sdes-cname";
1572
case GST_RTCP_SDES_NAME:
1573
result = "sdes-name";
1575
case GST_RTCP_SDES_EMAIL:
1576
result = "sdes-email";
1578
case GST_RTCP_SDES_PHONE:
1579
result = "sdes-phone";
1581
case GST_RTCP_SDES_LOC:
1582
result = "sdes-location";
1584
case GST_RTCP_SDES_TOOL:
1585
result = "sdes-tool";
1587
case GST_RTCP_SDES_NOTE:
1588
result = "sdes-note";
1590
case GST_RTCP_SDES_PRIV:
1591
result = "sdes-priv";
1601
gst_rtp_bin_set_sdes_string (GstRtpBin * bin, GstRTCPSDESType type,
1607
if (type < 0 || type > 8)
1610
GST_RTP_BIN_LOCK (bin);
1612
GST_OBJECT_LOCK (bin);
1613
g_free (bin->sdes[type]);
1614
bin->sdes[type] = g_strdup (data);
1615
name = sdes_type_to_name (type);
1616
/* store in all sessions */
1617
for (item = bin->sessions; item; item = g_slist_next (item))
1618
g_object_set (item->data, name, bin->sdes[type], NULL);
1619
GST_OBJECT_UNLOCK (bin);
1621
GST_RTP_BIN_UNLOCK (bin);
1625
gst_rtp_bin_get_sdes_string (GstRtpBin * bin, GstRTCPSDESType type)
1629
if (type < 0 || type > 8)
1632
GST_OBJECT_LOCK (bin);
1633
result = g_strdup (bin->sdes[type]);
1634
GST_OBJECT_UNLOCK (bin);
1640
gst_rtp_bin_set_property (GObject * object, guint prop_id,
1641
const GValue * value, GParamSpec * pspec)
1645
rtpbin = GST_RTP_BIN (object);
1649
GST_RTP_BIN_LOCK (rtpbin);
1650
rtpbin->latency = g_value_get_uint (value);
1651
GST_RTP_BIN_UNLOCK (rtpbin);
1652
/* propegate the property down to the jitterbuffer */
1653
gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "latency", value);
1655
case PROP_SDES_CNAME:
1656
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_CNAME,
1657
g_value_get_string (value));
1659
case PROP_SDES_NAME:
1660
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_NAME,
1661
g_value_get_string (value));
1663
case PROP_SDES_EMAIL:
1664
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_EMAIL,
1665
g_value_get_string (value));
1667
case PROP_SDES_PHONE:
1668
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_PHONE,
1669
g_value_get_string (value));
1671
case PROP_SDES_LOCATION:
1672
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_LOC,
1673
g_value_get_string (value));
1675
case PROP_SDES_TOOL:
1676
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_TOOL,
1677
g_value_get_string (value));
1679
case PROP_SDES_NOTE:
1680
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_NOTE,
1681
g_value_get_string (value));
1684
GST_RTP_BIN_LOCK (rtpbin);
1685
rtpbin->do_lost = g_value_get_boolean (value);
1686
GST_RTP_BIN_UNLOCK (rtpbin);
1687
gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "do-lost", value);
1690
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1696
gst_rtp_bin_get_property (GObject * object, guint prop_id,
1697
GValue * value, GParamSpec * pspec)
1701
rtpbin = GST_RTP_BIN (object);
1705
GST_RTP_BIN_LOCK (rtpbin);
1706
g_value_set_uint (value, rtpbin->latency);
1707
GST_RTP_BIN_UNLOCK (rtpbin);
1709
case PROP_SDES_CNAME:
1710
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1711
GST_RTCP_SDES_CNAME));
1713
case PROP_SDES_NAME:
1714
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1715
GST_RTCP_SDES_NAME));
1717
case PROP_SDES_EMAIL:
1718
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1719
GST_RTCP_SDES_EMAIL));
1721
case PROP_SDES_PHONE:
1722
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1723
GST_RTCP_SDES_PHONE));
1725
case PROP_SDES_LOCATION:
1726
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1727
GST_RTCP_SDES_LOC));
1729
case PROP_SDES_TOOL:
1730
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1731
GST_RTCP_SDES_TOOL));
1733
case PROP_SDES_NOTE:
1734
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
1735
GST_RTCP_SDES_NOTE));
1738
GST_RTP_BIN_LOCK (rtpbin);
1739
g_value_set_boolean (value, rtpbin->do_lost);
1740
GST_RTP_BIN_UNLOCK (rtpbin);
1743
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1749
gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
1753
rtpbin = GST_RTP_BIN (bin);
1755
switch (GST_MESSAGE_TYPE (message)) {
1756
case GST_MESSAGE_ELEMENT:
1758
const GstStructure *s = gst_message_get_structure (message);
1760
/* we change the structure name and add the session ID to it */
1761
if (gst_structure_has_name (s, "application/x-rtp-source-sdes")) {
1764
/* find the session, the message source has it */
1765
for (walk = rtpbin->sessions; walk; walk = g_slist_next (walk)) {
1766
GstRtpBinSession *sess = (GstRtpBinSession *) walk->data;
1768
/* if we found the session, change message. else we exit the loop and
1769
* leave the message unchanged */
1770
if (GST_OBJECT_CAST (sess->session) == GST_MESSAGE_SRC (message)) {
1771
message = gst_message_make_writable (message);
1772
s = gst_message_get_structure (message);
1774
gst_structure_set ((GstStructure *) s, "session", G_TYPE_UINT,
1780
/* fallthrough to forward the modified message to the parent */
1784
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
1791
calc_ntp_ns_base (GstRtpBin * bin)
1797
/* get the current time and convert it to NTP time in nanoseconds */
1798
g_get_current_time (¤t);
1799
now = GST_TIMEVAL_TO_TIME (current);
1800
now += (2208988800LL * GST_SECOND);
1802
GST_RTP_BIN_LOCK (bin);
1803
bin->priv->ntp_ns_base = now;
1804
for (walk = bin->sessions; walk; walk = g_slist_next (walk)) {
1805
GstRtpBinSession *session = (GstRtpBinSession *) walk->data;
1807
g_object_set (session->session, "ntp-ns-base", now, NULL);
1809
GST_RTP_BIN_UNLOCK (bin);
1814
static GstStateChangeReturn
1815
gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
1817
GstStateChangeReturn res;
1819
GstRtpBinPrivate *priv;
1821
rtpbin = GST_RTP_BIN (element);
1822
priv = rtpbin->priv;
1824
switch (transition) {
1825
case GST_STATE_CHANGE_NULL_TO_READY:
1827
case GST_STATE_CHANGE_READY_TO_PAUSED:
1828
GST_LOG_OBJECT (rtpbin, "clearing shutdown flag");
1829
g_atomic_int_set (&priv->shutdown, 0);
1831
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1832
calc_ntp_ns_base (rtpbin);
1834
case GST_STATE_CHANGE_PAUSED_TO_READY:
1835
GST_LOG_OBJECT (rtpbin, "setting shutdown flag");
1836
g_atomic_int_set (&priv->shutdown, 1);
1837
/* wait for all callbacks to end by taking the lock. No new callbacks will
1838
* be able to happen as we set the shutdown flag. */
1839
GST_RTP_BIN_DYN_LOCK (rtpbin);
1840
GST_LOG_OBJECT (rtpbin, "dynamic lock taken, we can continue shutdown");
1841
GST_RTP_BIN_DYN_UNLOCK (rtpbin);
1847
res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1849
switch (transition) {
1850
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1852
case GST_STATE_CHANGE_PAUSED_TO_READY:
1854
case GST_STATE_CHANGE_READY_TO_NULL:
1862
/* a new pad (SSRC) was created in @session. This signal is emited from the
1863
* payload demuxer. */
1865
new_payload_found (GstElement * element, guint pt, GstPad * pad,
1866
GstRtpBinStream * stream)
1869
GstElementClass *klass;
1870
GstPadTemplate *templ;
1874
rtpbin = stream->bin;
1876
GST_DEBUG ("new payload pad %d", pt);
1878
GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
1880
/* ghost the pad to the parent */
1881
klass = GST_ELEMENT_GET_CLASS (rtpbin);
1882
templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
1883
padname = g_strdup_printf ("recv_rtp_src_%d_%u_%d",
1884
stream->session->id, stream->ssrc, pt);
1885
gpad = gst_ghost_pad_new_from_template (padname, pad, templ);
1888
gst_pad_set_caps (gpad, GST_PAD_CAPS (pad));
1889
gst_pad_set_active (gpad, TRUE);
1890
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), gpad);
1892
stream->pads = g_slist_prepend (stream->pads, gpad);
1894
GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
1900
GST_DEBUG ("ignoring, we are shutting down");
1906
pt_map_requested (GstElement * element, guint pt, GstRtpBinSession * session)
1911
rtpbin = session->bin;
1913
GST_DEBUG_OBJECT (rtpbin, "payload map requested for pt %d in session %d", pt,
1916
caps = get_pt_map (session, pt);
1925
GST_DEBUG_OBJECT (rtpbin, "could not get caps");
1930
/* emited when caps changed for the session */
1932
caps_changed (GstPad * pad, GParamSpec * pspec, GstRtpBinSession * session)
1937
const GstStructure *s;
1941
g_object_get (pad, "caps", &caps, NULL);
1946
GST_DEBUG_OBJECT (bin, "got caps %" GST_PTR_FORMAT, caps);
1948
s = gst_caps_get_structure (caps, 0);
1950
/* get payload, finish when it's not there */
1951
if (!gst_structure_get_int (s, "payload", &payload))
1954
GST_RTP_SESSION_LOCK (session);
1955
GST_DEBUG_OBJECT (bin, "insert caps for payload %d", payload);
1956
g_hash_table_insert (session->ptmap, GINT_TO_POINTER (payload), caps);
1957
GST_RTP_SESSION_UNLOCK (session);
1960
/* a new pad (SSRC) was created in @session */
1962
new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
1963
GstRtpBinSession * session)
1966
GstRtpBinStream *stream;
1967
GstPad *sinkpad, *srcpad;
1970
rtpbin = session->bin;
1972
GST_DEBUG_OBJECT (rtpbin, "new SSRC pad %08x, %s:%s", ssrc,
1973
GST_DEBUG_PAD_NAME (pad));
1975
GST_RTP_BIN_SHUTDOWN_LOCK (rtpbin, shutdown);
1977
GST_RTP_SESSION_LOCK (session);
1979
/* create new stream */
1980
stream = create_stream (session, ssrc);
1984
/* get pad and link */
1985
GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTP");
1986
padname = g_strdup_printf ("src_%d", ssrc);
1987
srcpad = gst_element_get_static_pad (element, padname);
1989
sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
1990
gst_pad_link (srcpad, sinkpad);
1991
gst_object_unref (sinkpad);
1992
gst_object_unref (srcpad);
1994
GST_DEBUG_OBJECT (rtpbin, "linking jitterbuffer RTCP");
1995
padname = g_strdup_printf ("rtcp_src_%d", ssrc);
1996
srcpad = gst_element_get_static_pad (element, padname);
1998
sinkpad = gst_element_get_request_pad (stream->buffer, "sink_rtcp");
1999
gst_pad_link (srcpad, sinkpad);
2000
gst_object_unref (sinkpad);
2001
gst_object_unref (srcpad);
2003
/* connect to the RTCP sync signal from the jitterbuffer */
2004
GST_DEBUG_OBJECT (rtpbin, "connecting sync signal");
2005
stream->buffer_handlesync_sig = g_signal_connect (stream->buffer,
2006
"handle-sync", (GCallback) gst_rtp_bin_handle_sync, stream);
2008
/* connect to the new-pad signal of the payload demuxer, this will expose the
2009
* new pad by ghosting it. */
2010
stream->demux_newpad_sig = g_signal_connect (stream->demux,
2011
"new-payload-type", (GCallback) new_payload_found, stream);
2012
/* connect to the request-pt-map signal. This signal will be emited by the
2013
* demuxer so that it can apply a proper caps on the buffers for the
2015
stream->demux_ptreq_sig = g_signal_connect (stream->demux,
2016
"request-pt-map", (GCallback) pt_map_requested, session);
2018
GST_RTP_SESSION_UNLOCK (session);
2019
GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
2026
GST_DEBUG_OBJECT (rtpbin, "we are shutting down");
2031
GST_RTP_SESSION_UNLOCK (session);
2032
GST_RTP_BIN_SHUTDOWN_UNLOCK (rtpbin);
2033
GST_DEBUG_OBJECT (rtpbin, "could not create stream");
2038
/* Create a pad for receiving RTP for the session in @name. Must be called with
2042
create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
2046
GstRtpBinSession *session;
2047
GstPadLinkReturn lres;
2049
/* first get the session number */
2050
if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
2053
GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
2055
/* get or create session */
2056
session = find_session_by_id (rtpbin, sessid);
2058
GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
2059
/* create session now */
2060
session = create_session (rtpbin, sessid);
2061
if (session == NULL)
2065
/* check if pad was requested */
2066
if (session->recv_rtp_sink_ghost != NULL)
2067
return session->recv_rtp_sink_ghost;
2069
GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
2070
/* get recv_rtp pad and store */
2071
session->recv_rtp_sink =
2072
gst_element_get_request_pad (session->session, "recv_rtp_sink");
2073
if (session->recv_rtp_sink == NULL)
2076
g_signal_connect (session->recv_rtp_sink, "notify::caps",
2077
(GCallback) caps_changed, session);
2079
GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
2080
/* get srcpad, link to SSRCDemux */
2081
session->recv_rtp_src =
2082
gst_element_get_static_pad (session->session, "recv_rtp_src");
2083
if (session->recv_rtp_src == NULL)
2086
GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
2087
sinkdpad = gst_element_get_static_pad (session->demux, "sink");
2088
GST_DEBUG_OBJECT (rtpbin, "linking demuxer RTP sink pad");
2089
lres = gst_pad_link (session->recv_rtp_src, sinkdpad);
2090
gst_object_unref (sinkdpad);
2091
if (lres != GST_PAD_LINK_OK)
2094
/* connect to the new-ssrc-pad signal of the SSRC demuxer */
2095
session->demux_newpad_sig = g_signal_connect (session->demux,
2096
"new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
2097
session->demux_padremoved_sig = g_signal_connect (session->demux,
2098
"removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session);
2100
GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
2101
session->recv_rtp_sink_ghost =
2102
gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
2103
gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
2104
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
2106
return session->recv_rtp_sink_ghost;
2111
g_warning ("gstrtpbin: invalid name given");
2116
/* create_session already warned */
2121
g_warning ("gstrtpbin: failed to get session pad");
2126
g_warning ("gstrtpbin: failed to link pads");
2132
remove_recv_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
2134
if (session->demux_newpad_sig) {
2135
g_signal_handler_disconnect (session->demux, session->demux_newpad_sig);
2136
session->demux_newpad_sig = 0;
2138
if (session->demux_padremoved_sig) {
2139
g_signal_handler_disconnect (session->demux, session->demux_padremoved_sig);
2140
session->demux_padremoved_sig = 0;
2142
if (session->recv_rtp_src) {
2143
gst_object_unref (session->recv_rtp_src);
2144
session->recv_rtp_src = NULL;
2146
if (session->recv_rtp_sink) {
2147
gst_element_release_request_pad (session->session, session->recv_rtp_sink);
2148
gst_object_unref (session->recv_rtp_sink);
2149
session->recv_rtp_sink = NULL;
2151
if (session->recv_rtp_sink_ghost) {
2152
gst_pad_set_active (session->recv_rtp_sink_ghost, FALSE);
2153
gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
2154
session->recv_rtp_sink_ghost);
2155
session->recv_rtp_sink_ghost = NULL;
2159
/* Create a pad for receiving RTCP for the session in @name. Must be called with
2163
create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
2167
GstRtpBinSession *session;
2169
GstPadLinkReturn lres;
2171
/* first get the session number */
2172
if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
2175
GST_DEBUG_OBJECT (rtpbin, "finding session %d", sessid);
2177
/* get or create the session */
2178
session = find_session_by_id (rtpbin, sessid);
2180
GST_DEBUG_OBJECT (rtpbin, "creating session %d", sessid);
2181
/* create session now */
2182
session = create_session (rtpbin, sessid);
2183
if (session == NULL)
2187
/* check if pad was requested */
2188
if (session->recv_rtcp_sink_ghost != NULL)
2189
return session->recv_rtcp_sink_ghost;
2191
/* get recv_rtp pad and store */
2192
GST_DEBUG_OBJECT (rtpbin, "getting RTCP sink pad");
2193
session->recv_rtcp_sink =
2194
gst_element_get_request_pad (session->session, "recv_rtcp_sink");
2195
if (session->recv_rtcp_sink == NULL)
2198
/* get srcpad, link to SSRCDemux */
2199
GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
2200
session->sync_src = gst_element_get_static_pad (session->session, "sync_src");
2201
if (session->sync_src == NULL)
2204
GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTCP sink pad");
2205
sinkdpad = gst_element_get_static_pad (session->demux, "rtcp_sink");
2206
lres = gst_pad_link (session->sync_src, sinkdpad);
2207
gst_object_unref (sinkdpad);
2208
if (lres != GST_PAD_LINK_OK)
2211
session->recv_rtcp_sink_ghost =
2212
gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
2213
gst_pad_set_active (session->recv_rtcp_sink_ghost, TRUE);
2214
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin),
2215
session->recv_rtcp_sink_ghost);
2217
return session->recv_rtcp_sink_ghost;
2222
g_warning ("gstrtpbin: invalid name given");
2227
/* create_session already warned */
2232
g_warning ("gstrtpbin: failed to get session pad");
2237
g_warning ("gstrtpbin: failed to link pads");
2243
remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
2245
if (session->recv_rtcp_sink_ghost) {
2246
gst_pad_set_active (session->recv_rtcp_sink_ghost, FALSE);
2247
gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
2248
session->recv_rtcp_sink_ghost);
2249
session->recv_rtcp_sink_ghost = NULL;
2251
if (session->sync_src) {
2252
/* releasing the request pad should also unref the sync pad */
2253
gst_object_unref (session->sync_src);
2254
session->sync_src = NULL;
2256
if (session->recv_rtcp_sink) {
2257
gst_element_release_request_pad (session->session, session->recv_rtcp_sink);
2258
gst_object_unref (session->recv_rtcp_sink);
2259
session->recv_rtcp_sink = NULL;
2263
/* Create a pad for sending RTP for the session in @name. Must be called with
2267
create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
2271
GstRtpBinSession *session;
2272
GstElementClass *klass;
2274
/* first get the session number */
2275
if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
2278
/* get or create session */
2279
session = find_session_by_id (rtpbin, sessid);
2281
/* create session now */
2282
session = create_session (rtpbin, sessid);
2283
if (session == NULL)
2287
/* check if pad was requested */
2288
if (session->send_rtp_sink_ghost != NULL)
2289
return session->send_rtp_sink_ghost;
2291
/* get send_rtp pad and store */
2292
session->send_rtp_sink =
2293
gst_element_get_request_pad (session->session, "send_rtp_sink");
2294
if (session->send_rtp_sink == NULL)
2297
session->send_rtp_sink_ghost =
2298
gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
2299
gst_pad_set_active (session->send_rtp_sink_ghost, TRUE);
2300
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_ghost);
2303
session->send_rtp_src =
2304
gst_element_get_static_pad (session->session, "send_rtp_src");
2305
if (session->send_rtp_src == NULL)
2308
/* ghost the new source pad */
2309
klass = GST_ELEMENT_GET_CLASS (rtpbin);
2310
gname = g_strdup_printf ("send_rtp_src_%d", sessid);
2311
templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
2312
session->send_rtp_src_ghost =
2313
gst_ghost_pad_new_from_template (gname, session->send_rtp_src, templ);
2314
gst_pad_set_active (session->send_rtp_src_ghost, TRUE);
2315
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost);
2318
return session->send_rtp_sink_ghost;
2323
g_warning ("gstrtpbin: invalid name given");
2328
/* create_session already warned */
2333
g_warning ("gstrtpbin: failed to get session pad for session %d", sessid);
2338
g_warning ("gstrtpbin: failed to get rtp source pad for session %d",
2345
remove_send_rtp (GstRtpBin * rtpbin, GstRtpBinSession * session)
2347
if (session->send_rtp_src_ghost) {
2348
gst_pad_set_active (session->send_rtp_src_ghost, FALSE);
2349
gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
2350
session->send_rtp_src_ghost);
2351
session->send_rtp_src_ghost = NULL;
2353
if (session->send_rtp_src) {
2354
gst_object_unref (session->send_rtp_src);
2355
session->send_rtp_src = NULL;
2357
if (session->send_rtp_sink) {
2358
gst_element_release_request_pad (GST_ELEMENT_CAST (session->session),
2359
session->send_rtp_sink);
2360
gst_object_unref (session->send_rtp_sink);
2361
session->send_rtp_sink = NULL;
2363
if (session->send_rtp_sink_ghost) {
2364
gst_pad_set_active (session->send_rtp_sink_ghost, FALSE);
2365
gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
2366
session->send_rtp_sink_ghost);
2367
session->send_rtp_sink_ghost = NULL;
2371
/* Create a pad for sending RTCP for the session in @name. Must be called with
2375
create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
2378
GstRtpBinSession *session;
2380
/* first get the session number */
2381
if (name == NULL || sscanf (name, "send_rtcp_src_%d", &sessid) != 1)
2384
/* get or create session */
2385
session = find_session_by_id (rtpbin, sessid);
2389
/* check if pad was requested */
2390
if (session->send_rtcp_src_ghost != NULL)
2391
return session->send_rtcp_src_ghost;
2393
/* get rtcp_src pad and store */
2394
session->send_rtcp_src =
2395
gst_element_get_request_pad (session->session, "send_rtcp_src");
2396
if (session->send_rtcp_src == NULL)
2399
session->send_rtcp_src_ghost =
2400
gst_ghost_pad_new_from_template (name, session->send_rtcp_src, templ);
2401
gst_pad_set_active (session->send_rtcp_src_ghost, TRUE);
2402
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtcp_src_ghost);
2404
return session->send_rtcp_src_ghost;
2409
g_warning ("gstrtpbin: invalid name given");
2414
g_warning ("gstrtpbin: session with id %d does not exist", sessid);
2419
g_warning ("gstrtpbin: failed to get rtcp pad for session %d", sessid);
2425
remove_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
2427
if (session->send_rtcp_src_ghost) {
2428
gst_pad_set_active (session->send_rtcp_src_ghost, FALSE);
2429
gst_element_remove_pad (GST_ELEMENT_CAST (rtpbin),
2430
session->send_rtcp_src_ghost);
2431
session->send_rtcp_src_ghost = NULL;
2433
if (session->send_rtcp_src) {
2434
gst_element_release_request_pad (session->session, session->send_rtcp_src);
2435
gst_object_unref (session->send_rtcp_src);
2436
session->send_rtcp_src = NULL;
2440
/* If the requested name is NULL we should create a name with
2441
* the session number assuming we want the lowest posible session
2442
* with a free pad like the template */
2444
gst_rtp_bin_get_free_pad_name (GstElement * element, GstPadTemplate * templ)
2446
gboolean name_found = FALSE;
2449
GstIterator *pad_it = NULL;
2450
gchar *pad_name = NULL;
2452
GST_DEBUG_OBJECT (element, "find a free pad name for template");
2453
while (!name_found) {
2455
pad_name = g_strdup_printf (templ->name_template, session++);
2456
pad_it = gst_element_iterate_pads (GST_ELEMENT (element));
2458
while (gst_iterator_next (pad_it, (gpointer) & pad) == GST_ITERATOR_OK) {
2461
name = gst_pad_get_name (pad);
2462
if (strcmp (name, pad_name) == 0)
2466
gst_iterator_free (pad_it);
2469
GST_DEBUG_OBJECT (element, "free pad name found: '%s'", pad_name);
2476
gst_rtp_bin_request_new_pad (GstElement * element,
2477
GstPadTemplate * templ, const gchar * name)
2480
GstElementClass *klass;
2483
gchar *pad_name = NULL;
2485
g_return_val_if_fail (templ != NULL, NULL);
2486
g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
2488
rtpbin = GST_RTP_BIN (element);
2489
klass = GST_ELEMENT_GET_CLASS (element);
2491
GST_RTP_BIN_LOCK (rtpbin);
2494
/* use a free pad name */
2495
pad_name = gst_rtp_bin_get_free_pad_name (element, templ);
2497
/* use the provided name */
2498
pad_name = g_strdup (name);
2501
GST_DEBUG_OBJECT (rtpbin, "Trying to request a pad with name %s", pad_name);
2503
/* figure out the template */
2504
if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
2505
result = create_recv_rtp (rtpbin, templ, pad_name);
2506
} else if (templ == gst_element_class_get_pad_template (klass,
2507
"recv_rtcp_sink_%d")) {
2508
result = create_recv_rtcp (rtpbin, templ, pad_name);
2509
} else if (templ == gst_element_class_get_pad_template (klass,
2510
"send_rtp_sink_%d")) {
2511
result = create_send_rtp (rtpbin, templ, pad_name);
2512
} else if (templ == gst_element_class_get_pad_template (klass,
2513
"send_rtcp_src_%d")) {
2514
result = create_rtcp (rtpbin, templ, pad_name);
2516
goto wrong_template;
2519
GST_RTP_BIN_UNLOCK (rtpbin);
2527
GST_RTP_BIN_UNLOCK (rtpbin);
2528
g_warning ("gstrtpbin: this is not our template");
2534
gst_rtp_bin_release_pad (GstElement * element, GstPad * pad)
2536
GstRtpBinSession *session;
2539
g_return_if_fail (GST_IS_GHOST_PAD (pad));
2540
g_return_if_fail (GST_IS_RTP_BIN (element));
2542
rtpbin = GST_RTP_BIN (element);
2544
GST_RTP_BIN_LOCK (rtpbin);
2545
GST_DEBUG_OBJECT (rtpbin, "Trying to release pad %s:%s",
2546
GST_DEBUG_PAD_NAME (pad));
2548
if (!(session = find_session_by_pad (rtpbin, pad)))
2551
if (session->recv_rtp_sink_ghost == pad) {
2552
remove_recv_rtp (rtpbin, session);
2553
} else if (session->recv_rtcp_sink_ghost == pad) {
2554
remove_recv_rtcp (rtpbin, session);
2555
} else if (session->send_rtp_sink_ghost == pad) {
2556
remove_send_rtp (rtpbin, session);
2557
} else if (session->send_rtcp_src_ghost == pad) {
2558
remove_rtcp (rtpbin, session);
2561
/* no more request pads, free the complete session */
2562
if (session->recv_rtp_sink_ghost == NULL
2563
&& session->recv_rtcp_sink_ghost == NULL
2564
&& session->send_rtp_sink_ghost == NULL
2565
&& session->send_rtcp_src_ghost == NULL) {
2566
GST_DEBUG_OBJECT (rtpbin, "no more pads for session %p", session);
2567
rtpbin->sessions = g_slist_remove (rtpbin->sessions, session);
2568
free_session (session, rtpbin);
2570
GST_RTP_BIN_UNLOCK (rtpbin);
2577
GST_RTP_BIN_UNLOCK (rtpbin);
2578
g_warning ("gstrtpbin: %s:%s is not one of our request pads",
2579
GST_DEBUG_PAD_NAME (pad));