2 * Copyright (C) <2007> Wim Taymans <wim@fluendo.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * SECTION:element-rtpssrcdemux
24 * @short_description: separate RTP payloads based on the SSRC
28 * rtpssrcdemux acts as a demuxer for RTP packets based on the SSRC of the
29 * packets. Its main purpose is to allow an application to easily receive and
30 * decode an RTP stream with multiple SSRCs.
33 * For each SSRC that is detected, a new pad will be created and the
34 * ::new-ssrc-pad signal will be emitted.
36 * <title>Example pipelines</title>
39 * gst-launch udpsrc caps="application/x-rtp" ! rtpssrcdemux ! fakesink
41 * Takes an RTP stream and send the RTP packets with the first detected SSRC
42 * to fakesink, discarding the other SSRCs.
46 * Last reviewed on 2007-05-23 (0.10.6)
54 #include <gst/rtp/gstrtpbuffer.h>
56 #include "gstrtpbin-marshal.h"
57 #include "gstrtpssrcdemux.h"
59 GST_DEBUG_CATEGORY_STATIC (gst_rtp_ssrc_demux_debug);
60 #define GST_CAT_DEFAULT gst_rtp_ssrc_demux_debug
62 /* generic templates */
63 static GstStaticPadTemplate rtp_ssrc_demux_sink_template =
64 GST_STATIC_PAD_TEMPLATE ("sink",
67 GST_STATIC_CAPS ("application/x-rtp")
70 static GstStaticPadTemplate rtp_ssrc_demux_src_template =
71 GST_STATIC_PAD_TEMPLATE ("src_%d",
74 GST_STATIC_CAPS ("application/x-rtp")
77 static GstElementDetails gst_rtp_ssrc_demux_details = {
80 "Splits RTP streams based on the SSRC",
81 "Wim Taymans <wim@fluendo.com>"
91 GST_BOILERPLATE (GstRTPSsrcDemux, gst_rtp_ssrc_demux, GstElement,
95 /* GObject vmethods */
96 static void gst_rtp_ssrc_demux_finalize (GObject * object);
98 /* GstElement vmethods */
99 static GstStateChangeReturn gst_rtp_ssrc_demux_change_state (GstElement *
100 element, GstStateChange transition);
103 static GstFlowReturn gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf);
104 static gboolean gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event);
107 static gboolean gst_rtp_ssrc_demux_src_event (GstPad * pad, GstEvent * event);
109 static guint gst_rtp_ssrc_demux_signals[LAST_SIGNAL] = { 0 };
112 * Item for storing GstPad <-> SSRC pairs.
114 struct _GstRTPSsrcDemuxPad
121 /* find a src pad for a given SSRC, returns NULL if the SSRC was not found
124 find_rtp_pad_for_ssrc (GstRTPSsrcDemux * demux, guint32 ssrc)
128 for (walk = demux->rtp_srcpads; walk; walk = g_slist_next (walk)) {
129 GstRTPSsrcDemuxPad *pad = (GstRTPSsrcDemuxPad *) walk->data;
131 if (pad->ssrc == ssrc)
138 create_rtp_pad_for_ssrc (GstRTPSsrcDemux * demux, guint32 ssrc)
141 GstElementClass *klass;
142 GstPadTemplate *templ;
144 GstRTPSsrcDemuxPad *demuxpad;
146 klass = GST_ELEMENT_GET_CLASS (demux);
147 templ = gst_element_class_get_pad_template (klass, "src_%d");
148 padname = g_strdup_printf ("src_%d", ssrc);
149 result = gst_pad_new_from_template (templ, padname);
152 /* wrap in structure and add to list */
153 demuxpad = g_new0 (GstRTPSsrcDemuxPad, 1);
154 demuxpad->ssrc = ssrc;
155 demuxpad->pad = result;
156 demux->rtp_srcpads = g_slist_prepend (demux->rtp_srcpads, demuxpad);
158 /* copy caps from input */
159 gst_pad_set_caps (result, GST_PAD_CAPS (demux->rtp_sink));
161 gst_pad_set_event_function (result, gst_rtp_ssrc_demux_src_event);
162 gst_pad_set_active (result, TRUE);
163 gst_element_add_pad (GST_ELEMENT_CAST (demux), result);
165 g_signal_emit (G_OBJECT (demux),
166 gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, result);
172 gst_rtp_ssrc_demux_base_init (gpointer g_class)
174 GstElementClass *gstelement_klass = GST_ELEMENT_CLASS (g_class);
176 gst_element_class_add_pad_template (gstelement_klass,
177 gst_static_pad_template_get (&rtp_ssrc_demux_sink_template));
178 gst_element_class_add_pad_template (gstelement_klass,
179 gst_static_pad_template_get (&rtp_ssrc_demux_src_template));
181 gst_element_class_set_details (gstelement_klass, &gst_rtp_ssrc_demux_details);
185 gst_rtp_ssrc_demux_class_init (GstRTPSsrcDemuxClass * klass)
187 GObjectClass *gobject_klass;
188 GstElementClass *gstelement_klass;
190 gobject_klass = (GObjectClass *) klass;
191 gstelement_klass = (GstElementClass *) klass;
193 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_finalize);
196 * GstRTPSsrcDemux::new-ssrc-pad:
197 * @demux: the object which received the signal
198 * @ssrc: the SSRC of the pad
201 * Emited when a new SSRC pad has been created.
203 gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD] =
204 g_signal_new ("new-ssrc-pad",
205 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
206 G_STRUCT_OFFSET (GstRTPSsrcDemuxClass, new_ssrc_pad),
207 NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_OBJECT,
208 G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_PAD);
210 gstelement_klass->change_state =
211 GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_change_state);
213 GST_DEBUG_CATEGORY_INIT (gst_rtp_ssrc_demux_debug,
214 "rtpssrcdemux", 0, "RTP SSRC demuxer");
218 gst_rtp_ssrc_demux_init (GstRTPSsrcDemux * demux,
219 GstRTPSsrcDemuxClass * g_class)
221 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
224 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
226 gst_pad_set_chain_function (demux->rtp_sink, gst_rtp_ssrc_demux_chain);
227 gst_pad_set_event_function (demux->rtp_sink, gst_rtp_ssrc_demux_sink_event);
228 gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->rtp_sink);
232 gst_rtp_ssrc_demux_finalize (GObject * object)
234 GstRTPSsrcDemux *demux;
236 demux = GST_RTP_SSRC_DEMUX (object);
238 G_OBJECT_CLASS (parent_class)->finalize (object);
242 gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event)
244 GstRTPSsrcDemux *demux;
245 gboolean res = FALSE;
247 demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));
249 switch (GST_EVENT_TYPE (event)) {
250 case GST_EVENT_NEWSEGMENT:
252 res = gst_pad_event_default (pad, event);
256 gst_object_unref (demux);
261 gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf)
264 GstRTPSsrcDemux *demux;
268 demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));
270 if (!gst_rtp_buffer_validate (buf))
271 goto invalid_payload;
273 ssrc = gst_rtp_buffer_get_ssrc (buf);
275 GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);
277 srcpad = find_rtp_pad_for_ssrc (demux, ssrc);
278 if (srcpad == NULL) {
279 GST_DEBUG_OBJECT (demux, "creating pad for SSRC %08x", ssrc);
280 srcpad = create_rtp_pad_for_ssrc (demux, ssrc);
286 ret = gst_pad_push (srcpad, buf);
293 /* this is fatal and should be filtered earlier */
294 GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
295 ("Dropping invalid RTP payload"));
296 gst_buffer_unref (buf);
297 return GST_FLOW_ERROR;
301 /* this is not fatal yet */
302 GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
303 ("Could not create new pad"));
304 gst_buffer_unref (buf);
305 return GST_FLOW_ERROR;
310 gst_rtp_ssrc_demux_src_event (GstPad * pad, GstEvent * event)
312 GstRTPSsrcDemux *demux;
313 gboolean res = FALSE;
315 demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));
317 switch (GST_EVENT_TYPE (event)) {
320 res = gst_pad_event_default (pad, event);
323 gst_object_unref (demux);
327 static GstStateChangeReturn
328 gst_rtp_ssrc_demux_change_state (GstElement * element,
329 GstStateChange transition)
331 GstStateChangeReturn ret;
332 GstRTPSsrcDemux *demux;
334 demux = GST_RTP_SSRC_DEMUX (element);
336 switch (transition) {
337 case GST_STATE_CHANGE_NULL_TO_READY:
338 case GST_STATE_CHANGE_READY_TO_PAUSED:
339 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
344 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
346 switch (transition) {
347 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
348 case GST_STATE_CHANGE_PAUSED_TO_READY:
349 case GST_STATE_CHANGE_READY_TO_NULL: