• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * RTP SSRC demuxer
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 /**
23  * SECTION:element-rtpssrcdemux
24  * @title: rtpssrcdemux
25  *
26  * rtpssrcdemux acts as a demuxer for RTP packets based on the SSRC of the
27  * packets. Its main purpose is to allow an application to easily receive and
28  * decode an RTP stream with multiple SSRCs.
29  *
30  * For each SSRC that is detected, a new pad will be created and the
31  * #GstRtpSsrcDemux::new-ssrc-pad signal will be emitted.
32  *
33  * ## Example pipelines
34  * |[
35  * gst-launch-1.0 udpsrc caps="application/x-rtp" ! rtpssrcdemux ! fakesink
36  * ]| Takes an RTP stream and send the RTP packets with the first detected SSRC
37  * to fakesink, discarding the other SSRCs.
38  *
39  */
40 
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44 
45 #include <string.h>
46 #include <gst/rtp/gstrtpbuffer.h>
47 #include <gst/rtp/gstrtcpbuffer.h>
48 
49 #include "gstrtpssrcdemux.h"
50 
51 GST_DEBUG_CATEGORY_STATIC (gst_rtp_ssrc_demux_debug);
52 #define GST_CAT_DEFAULT gst_rtp_ssrc_demux_debug
53 
54 /* generic templates */
55 static GstStaticPadTemplate rtp_ssrc_demux_sink_template =
56 GST_STATIC_PAD_TEMPLATE ("sink",
57     GST_PAD_SINK,
58     GST_PAD_ALWAYS,
59     GST_STATIC_CAPS ("application/x-rtp")
60     );
61 
62 static GstStaticPadTemplate rtp_ssrc_demux_rtcp_sink_template =
63 GST_STATIC_PAD_TEMPLATE ("rtcp_sink",
64     GST_PAD_SINK,
65     GST_PAD_ALWAYS,
66     GST_STATIC_CAPS ("application/x-rtcp")
67     );
68 
69 static GstStaticPadTemplate rtp_ssrc_demux_src_template =
70 GST_STATIC_PAD_TEMPLATE ("src_%u",
71     GST_PAD_SRC,
72     GST_PAD_SOMETIMES,
73     GST_STATIC_CAPS ("application/x-rtp")
74     );
75 
76 static GstStaticPadTemplate rtp_ssrc_demux_rtcp_src_template =
77 GST_STATIC_PAD_TEMPLATE ("rtcp_src_%u",
78     GST_PAD_SRC,
79     GST_PAD_SOMETIMES,
80     GST_STATIC_CAPS ("application/x-rtcp")
81     );
82 
83 #define INTERNAL_STREAM_LOCK(obj)   (g_rec_mutex_lock (&(obj)->padlock))
84 #define INTERNAL_STREAM_UNLOCK(obj) (g_rec_mutex_unlock (&(obj)->padlock))
85 
86 #define GST_PAD_FLAG_STICKIES_SENT (GST_PAD_FLAG_LAST << 0)
87 #define GST_PAD_STICKIES_SENT(pad)  (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_STICKIES_SENT))
88 #define GST_PAD_SET_STICKIES_SENT(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_STICKIES_SENT))
89 
90 typedef enum
91 {
92   RTP_PAD,
93   RTCP_PAD
94 } PadType;
95 
96 #define DEFAULT_MAX_STREAMS G_MAXUINT
97 enum
98 {
99   PROP_0,
100   PROP_MAX_STREAMS
101 };
102 
103 /* signals */
104 enum
105 {
106   SIGNAL_NEW_SSRC_PAD,
107   SIGNAL_REMOVED_SSRC_PAD,
108   SIGNAL_CLEAR_SSRC,
109   LAST_SIGNAL
110 };
111 
112 #define gst_rtp_ssrc_demux_parent_class parent_class
113 G_DEFINE_TYPE (GstRtpSsrcDemux, gst_rtp_ssrc_demux, GST_TYPE_ELEMENT);
114 GST_ELEMENT_REGISTER_DEFINE (rtpssrcdemux, "rtpssrcdemux", GST_RANK_NONE,
115     GST_TYPE_RTP_SSRC_DEMUX);
116 
117 /* GObject vmethods */
118 static void gst_rtp_ssrc_demux_dispose (GObject * object);
119 static void gst_rtp_ssrc_demux_finalize (GObject * object);
120 
121 /* GstElement vmethods */
122 static GstStateChangeReturn gst_rtp_ssrc_demux_change_state (GstElement *
123     element, GstStateChange transition);
124 
125 static void gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux,
126     guint32 ssrc);
127 
128 /* sinkpad stuff */
129 static GstFlowReturn gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent,
130     GstBuffer * buf);
131 static gboolean gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstObject * parent,
132     GstEvent * event);
133 
134 static GstFlowReturn gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad,
135     GstObject * parent, GstBuffer * buf);
136 static GstIterator *gst_rtp_ssrc_demux_iterate_internal_links_sink (GstPad *
137     pad, GstObject * parent);
138 
139 /* srcpad stuff */
140 static gboolean gst_rtp_ssrc_demux_src_event (GstPad * pad, GstObject * parent,
141     GstEvent * event);
142 static GstIterator *gst_rtp_ssrc_demux_iterate_internal_links_src (GstPad * pad,
143     GstObject * parent);
144 static gboolean gst_rtp_ssrc_demux_src_query (GstPad * pad, GstObject * parent,
145     GstQuery * query);
146 
147 static guint gst_rtp_ssrc_demux_signals[LAST_SIGNAL] = { 0 };
148 
149 /*
150  * Item for storing GstPad <-> SSRC pairs.
151  */
152 typedef struct
153 {
154   guint32 ssrc;
155   GstPad *rtp_pad;
156   GstCaps *caps;
157   GstPad *rtcp_pad;
158 } GstRtpSsrcDemuxPads;
159 
160 /* find a src pad for a given SSRC, returns NULL if the SSRC was not found
161  * MUST be called with object lock
162  */
163 static GstRtpSsrcDemuxPads *
find_demux_pads_for_ssrc(GstRtpSsrcDemux * demux,guint32 ssrc)164 find_demux_pads_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
165 {
166   GSList *walk;
167 
168   for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
169     GstRtpSsrcDemuxPads *pad = (GstRtpSsrcDemuxPads *) walk->data;
170 
171     if (pad->ssrc == ssrc)
172       return pad;
173   }
174   return NULL;
175 }
176 
177 /* returns a reference to the pad if found, %NULL otherwise */
178 static GstPad *
get_demux_pad_for_ssrc(GstRtpSsrcDemux * demux,guint32 ssrc,PadType padtype)179 get_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc, PadType padtype)
180 {
181   GstRtpSsrcDemuxPads *dpads;
182   GstPad *retpad;
183 
184   GST_OBJECT_LOCK (demux);
185 
186   dpads = find_demux_pads_for_ssrc (demux, ssrc);
187   if (!dpads) {
188     GST_OBJECT_UNLOCK (demux);
189     return NULL;
190   }
191 
192   switch (padtype) {
193     case RTP_PAD:
194       retpad = gst_object_ref (dpads->rtp_pad);
195       break;
196     case RTCP_PAD:
197       retpad = gst_object_ref (dpads->rtcp_pad);
198       break;
199     default:
200       retpad = NULL;
201       g_assert_not_reached ();
202   }
203 
204   GST_OBJECT_UNLOCK (demux);
205 
206   return retpad;
207 }
208 
209 static GstEvent *
add_ssrc_and_ref(GstEvent * event,guint32 ssrc)210 add_ssrc_and_ref (GstEvent * event, guint32 ssrc)
211 {
212   /* Set the ssrc on the output caps */
213   switch (GST_EVENT_TYPE (event)) {
214     case GST_EVENT_CAPS:
215     {
216       GstCaps *caps;
217       GstCaps *newcaps;
218       GstStructure *s;
219 
220       gst_event_parse_caps (event, &caps);
221       newcaps = gst_caps_copy (caps);
222 
223       s = gst_caps_get_structure (newcaps, 0);
224       gst_structure_set (s, "ssrc", G_TYPE_UINT, ssrc, NULL);
225       event = gst_event_new_caps (newcaps);
226       gst_caps_unref (newcaps);
227       break;
228     }
229     default:
230       gst_event_ref (event);
231       break;
232   }
233 
234   return event;
235 }
236 
237 struct ForwardStickyEventData
238 {
239   GstPad *pad;
240   guint32 ssrc;
241 };
242 
243 /* With internal stream lock held */
244 static gboolean
forward_sticky_events(GstPad * pad,GstEvent ** event,gpointer user_data)245 forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
246 {
247   struct ForwardStickyEventData *data = user_data;
248   GstEvent *newevent;
249 
250   newevent = add_ssrc_and_ref (*event, data->ssrc);
251   gst_pad_push_event (data->pad, newevent);
252 
253   return TRUE;
254 }
255 
256 static void
forward_initial_events(GstRtpSsrcDemux * demux,guint32 ssrc,GstPad * pad,PadType padtype)257 forward_initial_events (GstRtpSsrcDemux * demux, guint32 ssrc, GstPad * pad,
258     PadType padtype)
259 {
260   struct ForwardStickyEventData fdata;
261   GstPad *sinkpad = NULL;
262 
263   if (padtype == RTP_PAD)
264     sinkpad = demux->rtp_sink;
265   else if (padtype == RTCP_PAD)
266     sinkpad = demux->rtcp_sink;
267   else
268     g_assert_not_reached ();
269 
270   fdata.ssrc = ssrc;
271   fdata.pad = pad;
272 
273   gst_pad_sticky_events_foreach (sinkpad, forward_sticky_events, &fdata);
274 }
275 
276 /* MUST only be called from streaming thread */
277 static GstPad *
find_or_create_demux_pad_for_ssrc(GstRtpSsrcDemux * demux,guint32 ssrc,PadType padtype)278 find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
279     PadType padtype)
280 {
281   GstPad *rtp_pad, *rtcp_pad;
282   GstElementClass *klass;
283   GstPadTemplate *templ;
284   gchar *padname;
285   GstRtpSsrcDemuxPads *dpads;
286   GstPad *retpad;
287   guint num_streams;
288 
289   INTERNAL_STREAM_LOCK (demux);
290 
291   retpad = get_demux_pad_for_ssrc (demux, ssrc, padtype);
292   if (retpad != NULL) {
293     INTERNAL_STREAM_UNLOCK (demux);
294     return retpad;
295   }
296   /* We create 2 src pads per ssrc (RTP & RTCP). Checking if we are allowed
297      to create 2 more pads */
298   num_streams = (GST_ELEMENT_CAST (demux)->numsrcpads) >> 1;
299   if (num_streams >= demux->max_streams) {
300     INTERNAL_STREAM_UNLOCK (demux);
301     return NULL;
302   }
303 
304   GST_DEBUG_OBJECT (demux, "creating new pad for SSRC %08x", ssrc);
305 
306   klass = GST_ELEMENT_GET_CLASS (demux);
307   templ = gst_element_class_get_pad_template (klass, "src_%u");
308   padname = g_strdup_printf ("src_%u", ssrc);
309   rtp_pad = gst_pad_new_from_template (templ, padname);
310   g_free (padname);
311 
312   templ = gst_element_class_get_pad_template (klass, "rtcp_src_%u");
313   padname = g_strdup_printf ("rtcp_src_%u", ssrc);
314   rtcp_pad = gst_pad_new_from_template (templ, padname);
315   g_free (padname);
316 
317   /* wrap in structure and add to list */
318   dpads = g_new0 (GstRtpSsrcDemuxPads, 1);
319   dpads->ssrc = ssrc;
320   dpads->rtp_pad = rtp_pad;
321   dpads->rtcp_pad = rtcp_pad;
322 
323   GST_OBJECT_LOCK (demux);
324   demux->srcpads = g_slist_prepend (demux->srcpads, dpads);
325   GST_OBJECT_UNLOCK (demux);
326 
327   gst_pad_set_query_function (rtp_pad, gst_rtp_ssrc_demux_src_query);
328   gst_pad_set_iterate_internal_links_function (rtp_pad,
329       gst_rtp_ssrc_demux_iterate_internal_links_src);
330   gst_pad_set_event_function (rtp_pad, gst_rtp_ssrc_demux_src_event);
331   gst_pad_use_fixed_caps (rtp_pad);
332   gst_pad_set_active (rtp_pad, TRUE);
333 
334   gst_pad_set_event_function (rtcp_pad, gst_rtp_ssrc_demux_src_event);
335   gst_pad_set_iterate_internal_links_function (rtcp_pad,
336       gst_rtp_ssrc_demux_iterate_internal_links_src);
337   gst_pad_use_fixed_caps (rtcp_pad);
338   gst_pad_set_active (rtcp_pad, TRUE);
339 
340   gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
341   gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_pad);
342 
343   switch (padtype) {
344     case RTP_PAD:
345       retpad = gst_object_ref (dpads->rtp_pad);
346       break;
347     case RTCP_PAD:
348       retpad = gst_object_ref (dpads->rtcp_pad);
349       break;
350     default:
351       retpad = NULL;
352       g_assert_not_reached ();
353   }
354 
355   g_signal_emit (G_OBJECT (demux),
356       gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad);
357 
358   INTERNAL_STREAM_UNLOCK (demux);
359 
360   return retpad;
361 }
362 
363 static void
gst_rtp_ssrc_demux_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)364 gst_rtp_ssrc_demux_set_property (GObject * object, guint prop_id,
365     const GValue * value, GParamSpec * pspec)
366 {
367   GstRtpSsrcDemux *demux;
368 
369   demux = GST_RTP_SSRC_DEMUX (object);
370   switch (prop_id) {
371     case PROP_MAX_STREAMS:
372       demux->max_streams = g_value_get_uint (value);
373       break;
374     default:
375       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
376       break;
377   }
378 }
379 
380 static void
gst_rtp_ssrc_demux_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)381 gst_rtp_ssrc_demux_get_property (GObject * object, guint prop_id,
382     GValue * value, GParamSpec * pspec)
383 {
384   GstRtpSsrcDemux *demux;
385 
386   demux = GST_RTP_SSRC_DEMUX (object);
387   switch (prop_id) {
388     case PROP_MAX_STREAMS:
389       g_value_set_uint (value, demux->max_streams);
390       break;
391     default:
392       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393       break;
394   }
395 }
396 
397 static void
gst_rtp_ssrc_demux_class_init(GstRtpSsrcDemuxClass * klass)398 gst_rtp_ssrc_demux_class_init (GstRtpSsrcDemuxClass * klass)
399 {
400   GObjectClass *gobject_klass;
401   GstElementClass *gstelement_klass;
402   GstRtpSsrcDemuxClass *gstrtpssrcdemux_klass;
403 
404   gobject_klass = (GObjectClass *) klass;
405   gstelement_klass = (GstElementClass *) klass;
406   gstrtpssrcdemux_klass = (GstRtpSsrcDemuxClass *) klass;
407 
408   gobject_klass->dispose = gst_rtp_ssrc_demux_dispose;
409   gobject_klass->finalize = gst_rtp_ssrc_demux_finalize;
410   gobject_klass->set_property = gst_rtp_ssrc_demux_set_property;
411   gobject_klass->get_property = gst_rtp_ssrc_demux_get_property;
412 
413   g_object_class_install_property (gobject_klass, PROP_MAX_STREAMS,
414       g_param_spec_uint ("max-streams", "Max Streams",
415           "The maximum number of streams allowed",
416           0, G_MAXUINT, DEFAULT_MAX_STREAMS,
417           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
418 
419   /**
420    * GstRtpSsrcDemux::new-ssrc-pad:
421    * @demux: the object which received the signal
422    * @ssrc: the SSRC of the pad
423    * @pad: the new pad.
424    *
425    * Emitted when a new SSRC pad has been created.
426    */
427   gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD] =
428       g_signal_new ("new-ssrc-pad",
429       G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
430       G_STRUCT_OFFSET (GstRtpSsrcDemuxClass, new_ssrc_pad),
431       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_PAD);
432 
433   /**
434    * GstRtpSsrcDemux::removed-ssrc-pad:
435    * @demux: the object which received the signal
436    * @ssrc: the SSRC of the pad
437    * @pad: the removed pad.
438    *
439    * Emitted when a SSRC pad has been removed.
440    */
441   gst_rtp_ssrc_demux_signals[SIGNAL_REMOVED_SSRC_PAD] =
442       g_signal_new ("removed-ssrc-pad",
443       G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
444       G_STRUCT_OFFSET (GstRtpSsrcDemuxClass, removed_ssrc_pad),
445       NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_PAD);
446 
447   /**
448    * GstRtpSsrcDemux::clear-ssrc:
449    * @demux: the object which received the signal
450    * @ssrc: the SSRC of the pad
451    *
452    * Action signal to remove the pad for SSRC.
453    */
454   gst_rtp_ssrc_demux_signals[SIGNAL_CLEAR_SSRC] =
455       g_signal_new ("clear-ssrc",
456       G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
457       G_STRUCT_OFFSET (GstRtpSsrcDemuxClass, clear_ssrc),
458       NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
459 
460   gstelement_klass->change_state =
461       GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_change_state);
462   gstrtpssrcdemux_klass->clear_ssrc =
463       GST_DEBUG_FUNCPTR (gst_rtp_ssrc_demux_clear_ssrc);
464 
465   gst_element_class_add_static_pad_template (gstelement_klass,
466       &rtp_ssrc_demux_sink_template);
467   gst_element_class_add_static_pad_template (gstelement_klass,
468       &rtp_ssrc_demux_rtcp_sink_template);
469   gst_element_class_add_static_pad_template (gstelement_klass,
470       &rtp_ssrc_demux_src_template);
471   gst_element_class_add_static_pad_template (gstelement_klass,
472       &rtp_ssrc_demux_rtcp_src_template);
473 
474   gst_element_class_set_static_metadata (gstelement_klass, "RTP SSRC Demux",
475       "Demux/Network/RTP",
476       "Splits RTP streams based on the SSRC",
477       "Wim Taymans <wim.taymans@gmail.com>");
478 
479   GST_DEBUG_CATEGORY_INIT (gst_rtp_ssrc_demux_debug,
480       "rtpssrcdemux", 0, "RTP SSRC demuxer");
481 
482   GST_DEBUG_REGISTER_FUNCPTR (gst_rtp_ssrc_demux_chain);
483   GST_DEBUG_REGISTER_FUNCPTR (gst_rtp_ssrc_demux_rtcp_chain);
484 }
485 
486 static void
gst_rtp_ssrc_demux_init(GstRtpSsrcDemux * demux)487 gst_rtp_ssrc_demux_init (GstRtpSsrcDemux * demux)
488 {
489   GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
490 
491   demux->rtp_sink =
492       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
493           "sink"), "sink");
494   gst_pad_set_chain_function (demux->rtp_sink, gst_rtp_ssrc_demux_chain);
495   gst_pad_set_event_function (demux->rtp_sink, gst_rtp_ssrc_demux_sink_event);
496   gst_pad_set_iterate_internal_links_function (demux->rtp_sink,
497       gst_rtp_ssrc_demux_iterate_internal_links_sink);
498   gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->rtp_sink);
499 
500   demux->rtcp_sink =
501       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
502           "rtcp_sink"), "rtcp_sink");
503   gst_pad_set_chain_function (demux->rtcp_sink, gst_rtp_ssrc_demux_rtcp_chain);
504   gst_pad_set_event_function (demux->rtcp_sink, gst_rtp_ssrc_demux_sink_event);
505   gst_pad_set_iterate_internal_links_function (demux->rtcp_sink,
506       gst_rtp_ssrc_demux_iterate_internal_links_sink);
507   gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->rtcp_sink);
508 
509   demux->max_streams = DEFAULT_MAX_STREAMS;
510 
511   g_rec_mutex_init (&demux->padlock);
512 }
513 
514 static void
gst_rtp_ssrc_demux_pads_free(GstRtpSsrcDemuxPads * dpads)515 gst_rtp_ssrc_demux_pads_free (GstRtpSsrcDemuxPads * dpads)
516 {
517   gst_pad_set_active (dpads->rtp_pad, FALSE);
518   gst_pad_set_active (dpads->rtcp_pad, FALSE);
519 
520   gst_element_remove_pad (GST_PAD_PARENT (dpads->rtp_pad), dpads->rtp_pad);
521   gst_element_remove_pad (GST_PAD_PARENT (dpads->rtcp_pad), dpads->rtcp_pad);
522 
523   g_free (dpads);
524 }
525 
526 static void
gst_rtp_ssrc_demux_reset(GstRtpSsrcDemux * demux)527 gst_rtp_ssrc_demux_reset (GstRtpSsrcDemux * demux)
528 {
529   g_slist_free_full (demux->srcpads,
530       (GDestroyNotify) gst_rtp_ssrc_demux_pads_free);
531   demux->srcpads = NULL;
532 }
533 
534 static void
gst_rtp_ssrc_demux_dispose(GObject * object)535 gst_rtp_ssrc_demux_dispose (GObject * object)
536 {
537   GstRtpSsrcDemux *demux;
538 
539   demux = GST_RTP_SSRC_DEMUX (object);
540 
541   gst_rtp_ssrc_demux_reset (demux);
542 
543   G_OBJECT_CLASS (parent_class)->dispose (object);
544 }
545 
546 static void
gst_rtp_ssrc_demux_finalize(GObject * object)547 gst_rtp_ssrc_demux_finalize (GObject * object)
548 {
549   GstRtpSsrcDemux *demux;
550 
551   demux = GST_RTP_SSRC_DEMUX (object);
552   g_rec_mutex_clear (&demux->padlock);
553 
554   G_OBJECT_CLASS (parent_class)->finalize (object);
555 }
556 
557 static void
gst_rtp_ssrc_demux_clear_ssrc(GstRtpSsrcDemux * demux,guint32 ssrc)558 gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
559 {
560   GstRtpSsrcDemuxPads *dpads;
561 
562   GST_OBJECT_LOCK (demux);
563   dpads = find_demux_pads_for_ssrc (demux, ssrc);
564   if (dpads == NULL) {
565     GST_OBJECT_UNLOCK (demux);
566     goto unknown_pad;
567   }
568 
569   GST_DEBUG_OBJECT (demux, "clearing pad for SSRC %08x", ssrc);
570 
571   demux->srcpads = g_slist_remove (demux->srcpads, dpads);
572   GST_OBJECT_UNLOCK (demux);
573 
574   g_signal_emit (G_OBJECT (demux),
575       gst_rtp_ssrc_demux_signals[SIGNAL_REMOVED_SSRC_PAD], 0, ssrc,
576       dpads->rtp_pad);
577 
578   gst_rtp_ssrc_demux_pads_free (dpads);
579 
580   return;
581 
582   /* ERRORS */
583 unknown_pad:
584   {
585     GST_WARNING_OBJECT (demux, "unknown SSRC %08x", ssrc);
586     return;
587   }
588 }
589 
590 struct ForwardEventData
591 {
592   GstRtpSsrcDemux *demux;
593   GstEvent *event;
594   gboolean res;
595   GstPad *pad;
596 };
597 
598 static gboolean
forward_event(GstPad * pad,gpointer user_data)599 forward_event (GstPad * pad, gpointer user_data)
600 {
601   struct ForwardEventData *fdata = user_data;
602   GSList *walk = NULL;
603   GstEvent *newevent = NULL;
604 
605   /* special case for EOS */
606   if (GST_EVENT_TYPE (fdata->event) == GST_EVENT_EOS)
607     GST_PAD_SET_STICKIES_SENT (pad);
608 
609   if (GST_EVENT_IS_STICKY (fdata->event) && !GST_PAD_STICKIES_SENT (pad))
610     return FALSE;
611 
612   GST_OBJECT_LOCK (fdata->demux);
613   for (walk = fdata->demux->srcpads; walk; walk = walk->next) {
614     GstRtpSsrcDemuxPads *dpads = (GstRtpSsrcDemuxPads *) walk->data;
615 
616     if (pad == dpads->rtp_pad || pad == dpads->rtcp_pad) {
617       newevent = add_ssrc_and_ref (fdata->event, dpads->ssrc);
618       break;
619     }
620   }
621   GST_OBJECT_UNLOCK (fdata->demux);
622 
623   if (newevent)
624     fdata->res &= gst_pad_push_event (pad, newevent);
625 
626   return FALSE;
627 }
628 
629 
630 static gboolean
gst_rtp_ssrc_demux_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)631 gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstObject * parent,
632     GstEvent * event)
633 {
634   GstRtpSsrcDemux *demux;
635   struct ForwardEventData fdata;
636 
637   demux = GST_RTP_SSRC_DEMUX (parent);
638 
639   fdata.demux = demux;
640   fdata.pad = pad;
641   fdata.event = event;
642   fdata.res = TRUE;
643 
644   gst_pad_forward (pad, forward_event, &fdata);
645 
646   gst_event_unref (event);
647 
648   return fdata.res;
649 }
650 
651 static GstFlowReturn
gst_rtp_ssrc_demux_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)652 gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
653 {
654   GstFlowReturn ret;
655   GstRtpSsrcDemux *demux;
656   guint32 ssrc;
657   GstRTPBuffer rtp = { NULL };
658   GstPad *srcpad;
659 
660   demux = GST_RTP_SSRC_DEMUX (parent);
661 
662   if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
663     goto invalid_payload;
664 
665   ssrc = gst_rtp_buffer_get_ssrc (&rtp);
666   gst_rtp_buffer_unmap (&rtp);
667 
668   GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);
669 
670   srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
671   if (srcpad == NULL)
672     goto create_failed;
673 
674   if (!GST_PAD_STICKIES_SENT (srcpad)) {
675     forward_initial_events (demux, ssrc, srcpad, RTP_PAD);
676     GST_PAD_SET_STICKIES_SENT (srcpad);
677   }
678 
679   /* push to srcpad */
680   ret = gst_pad_push (srcpad, buf);
681 
682   if (ret != GST_FLOW_OK) {
683     GstPad *active_pad;
684 
685     /* check if the ssrc still there, may have been removed */
686     active_pad = get_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
687 
688     if (active_pad == NULL || active_pad != srcpad) {
689       /* SSRC was removed during the push ... ignore the error */
690       ret = GST_FLOW_OK;
691     }
692 
693     g_clear_object (&active_pad);
694   }
695 
696   gst_object_unref (srcpad);
697 
698   return ret;
699 
700   /* ERRORS */
701 invalid_payload:
702   {
703     GST_DEBUG_OBJECT (demux, "Dropping invalid RTP packet");
704     gst_buffer_unref (buf);
705     return GST_FLOW_OK;
706   }
707 create_failed:
708   {
709     gst_buffer_unref (buf);
710     GST_WARNING_OBJECT (demux,
711         "Dropping buffer SSRC %08x. "
712         "Max streams number reached (%u)", ssrc, demux->max_streams);
713     return GST_FLOW_OK;
714   }
715 }
716 
717 static GstFlowReturn
gst_rtp_ssrc_demux_rtcp_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)718 gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstObject * parent,
719     GstBuffer * buf)
720 {
721   GstFlowReturn ret;
722   GstRtpSsrcDemux *demux;
723   guint32 ssrc;
724   GstRTCPPacket packet;
725   GstRTCPBuffer rtcp = { NULL, };
726   GstPad *srcpad;
727 
728   demux = GST_RTP_SSRC_DEMUX (parent);
729 
730   if (!gst_rtcp_buffer_validate_reduced (buf))
731     goto invalid_rtcp;
732 
733   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
734   if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet)) {
735     gst_rtcp_buffer_unmap (&rtcp);
736     goto invalid_rtcp;
737   }
738 
739   /* first packet must be SR or RR, or in case of a reduced size RTCP packet
740    * it must be APP, RTPFB or PSFB feeadback, or else the validate would
741    * have failed */
742   switch (gst_rtcp_packet_get_type (&packet)) {
743     case GST_RTCP_TYPE_SR:
744       /* get the ssrc so that we can route it to the right source pad */
745       gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, NULL, NULL, NULL,
746           NULL);
747       break;
748     case GST_RTCP_TYPE_RR:
749       ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);
750       break;
751     case GST_RTCP_TYPE_APP:
752       ssrc = gst_rtcp_packet_app_get_ssrc (&packet);
753       break;
754     case GST_RTCP_TYPE_RTPFB:
755     case GST_RTCP_TYPE_PSFB:
756       ssrc = gst_rtcp_packet_fb_get_sender_ssrc (&packet);
757       break;
758     default:
759       goto unexpected_rtcp;
760   }
761   gst_rtcp_buffer_unmap (&rtcp);
762 
763   GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc);
764 
765   srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTCP_PAD);
766   if (srcpad == NULL)
767     goto create_failed;
768 
769   if (!GST_PAD_STICKIES_SENT (srcpad)) {
770     forward_initial_events (demux, ssrc, srcpad, RTCP_PAD);
771     GST_PAD_SET_STICKIES_SENT (srcpad);
772   }
773 
774   /* push to srcpad */
775   ret = gst_pad_push (srcpad, buf);
776 
777   if (ret != GST_FLOW_OK) {
778     GstPad *active_pad;
779 
780     /* check if the ssrc still there, may have been removed */
781     active_pad = get_demux_pad_for_ssrc (demux, ssrc, RTCP_PAD);
782     if (active_pad == NULL || active_pad != srcpad) {
783       /* SSRC was removed during the push ... ignore the error */
784       ret = GST_FLOW_OK;
785     }
786 
787     g_clear_object (&active_pad);
788   }
789 
790   gst_object_unref (srcpad);
791 
792   return ret;
793 
794   /* ERRORS */
795 invalid_rtcp:
796   {
797     GST_DEBUG_OBJECT (demux, "Dropping invalid RTCP packet");
798     gst_buffer_unref (buf);
799     return GST_FLOW_OK;
800   }
801 unexpected_rtcp:
802   {
803     GST_DEBUG_OBJECT (demux, "dropping unexpected RTCP packet");
804     gst_buffer_unref (buf);
805     return GST_FLOW_OK;
806   }
807 create_failed:
808   {
809     gst_buffer_unref (buf);
810     GST_WARNING_OBJECT (demux,
811         "Dropping buffer SSRC %08x. "
812         "Max streams number reached (%u)", ssrc, demux->max_streams);
813     return GST_FLOW_OK;
814   }
815 }
816 
817 static GstRtpSsrcDemuxPads *
find_demux_pad_for_pad(GstRtpSsrcDemux * demux,GstPad * pad)818 find_demux_pad_for_pad (GstRtpSsrcDemux * demux, GstPad * pad)
819 {
820   GSList *walk;
821 
822   for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
823     GstRtpSsrcDemuxPads *dpads = (GstRtpSsrcDemuxPads *) walk->data;
824     if (dpads->rtp_pad == pad || dpads->rtcp_pad == pad) {
825       return dpads;
826     }
827   }
828 
829   return NULL;
830 }
831 
832 
833 static gboolean
gst_rtp_ssrc_demux_src_event(GstPad * pad,GstObject * parent,GstEvent * event)834 gst_rtp_ssrc_demux_src_event (GstPad * pad, GstObject * parent,
835     GstEvent * event)
836 {
837   GstRtpSsrcDemux *demux;
838   const GstStructure *s;
839 
840   demux = GST_RTP_SSRC_DEMUX (parent);
841 
842   switch (GST_EVENT_TYPE (event)) {
843     case GST_EVENT_CUSTOM_UPSTREAM:
844     case GST_EVENT_CUSTOM_BOTH:
845     case GST_EVENT_CUSTOM_BOTH_OOB:
846       s = gst_event_get_structure (event);
847       if (s && !gst_structure_has_field (s, "ssrc")) {
848         GstRtpSsrcDemuxPads *dpads = find_demux_pad_for_pad (demux, pad);
849 
850         if (dpads) {
851           GstStructure *ws;
852 
853           event = gst_event_make_writable (event);
854           ws = gst_event_writable_structure (event);
855           gst_structure_set (ws, "ssrc", G_TYPE_UINT, dpads->ssrc, NULL);
856         }
857       }
858       break;
859     default:
860       break;
861   }
862 
863   return gst_pad_event_default (pad, parent, event);
864 }
865 
866 static GstIterator *
gst_rtp_ssrc_demux_iterate_internal_links_src(GstPad * pad,GstObject * parent)867 gst_rtp_ssrc_demux_iterate_internal_links_src (GstPad * pad, GstObject * parent)
868 {
869   GstRtpSsrcDemux *demux;
870   GstPad *otherpad = NULL;
871   GstIterator *it = NULL;
872   GSList *current;
873 
874   demux = GST_RTP_SSRC_DEMUX (parent);
875 
876   GST_OBJECT_LOCK (demux);
877   for (current = demux->srcpads; current; current = g_slist_next (current)) {
878     GstRtpSsrcDemuxPads *dpads = (GstRtpSsrcDemuxPads *) current->data;
879 
880     if (pad == dpads->rtp_pad) {
881       otherpad = demux->rtp_sink;
882       break;
883     } else if (pad == dpads->rtcp_pad) {
884       otherpad = demux->rtcp_sink;
885       break;
886     }
887   }
888   if (otherpad) {
889     GValue val = { 0, };
890 
891     g_value_init (&val, GST_TYPE_PAD);
892     g_value_set_object (&val, otherpad);
893     it = gst_iterator_new_single (GST_TYPE_PAD, &val);
894     g_value_unset (&val);
895 
896   }
897   GST_OBJECT_UNLOCK (demux);
898 
899   return it;
900 }
901 
902 /* Should return 0 for elements to be included */
903 static gint
src_pad_compare_func(gconstpointer a,gconstpointer b)904 src_pad_compare_func (gconstpointer a, gconstpointer b)
905 {
906   GstPad *pad = GST_PAD (g_value_get_object (a));
907   const gchar *prefix = g_value_get_string (b);
908   gint res;
909 
910   /* 0 means equal means we accept the pad, accepted if there is a name
911    * and it starts with the prefix */
912   GST_OBJECT_LOCK (pad);
913   res = !GST_PAD_NAME (pad) || !g_str_has_prefix (GST_PAD_NAME (pad), prefix);
914   GST_OBJECT_UNLOCK (pad);
915 
916   return res;
917 }
918 
919 static GstIterator *
gst_rtp_ssrc_demux_iterate_internal_links_sink(GstPad * pad,GstObject * parent)920 gst_rtp_ssrc_demux_iterate_internal_links_sink (GstPad * pad,
921     GstObject * parent)
922 {
923   GstRtpSsrcDemux *demux;
924   GstIterator *it = NULL;
925   GValue gval = { 0, };
926 
927   demux = GST_RTP_SSRC_DEMUX (parent);
928 
929   g_value_init (&gval, G_TYPE_STRING);
930   if (pad == demux->rtp_sink)
931     g_value_set_static_string (&gval, "src_");
932   else if (pad == demux->rtcp_sink)
933     g_value_set_static_string (&gval, "rtcp_src_");
934   else
935     g_assert_not_reached ();
936 
937   it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (demux));
938   it = gst_iterator_filter (it, src_pad_compare_func, &gval);
939 
940   return it;
941 }
942 
943 
944 static gboolean
gst_rtp_ssrc_demux_src_query(GstPad * pad,GstObject * parent,GstQuery * query)945 gst_rtp_ssrc_demux_src_query (GstPad * pad, GstObject * parent,
946     GstQuery * query)
947 {
948   GstRtpSsrcDemux *demux;
949   gboolean res = FALSE;
950 
951   demux = GST_RTP_SSRC_DEMUX (parent);
952 
953   switch (GST_QUERY_TYPE (query)) {
954     case GST_QUERY_LATENCY:
955     {
956 
957       if ((res = gst_pad_peer_query (demux->rtp_sink, query))) {
958         gboolean live;
959         GstClockTime min_latency, max_latency;
960 
961         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
962 
963         GST_DEBUG_OBJECT (pad, "peer min latency %" GST_TIME_FORMAT,
964             GST_TIME_ARGS (min_latency));
965 
966         gst_query_set_latency (query, live, min_latency, max_latency);
967       }
968       break;
969     }
970     default:
971       res = gst_pad_query_default (pad, parent, query);
972       break;
973   }
974 
975   return res;
976 }
977 
978 static GstStateChangeReturn
gst_rtp_ssrc_demux_change_state(GstElement * element,GstStateChange transition)979 gst_rtp_ssrc_demux_change_state (GstElement * element,
980     GstStateChange transition)
981 {
982   GstStateChangeReturn ret;
983   GstRtpSsrcDemux *demux;
984 
985   demux = GST_RTP_SSRC_DEMUX (element);
986 
987   switch (transition) {
988     case GST_STATE_CHANGE_NULL_TO_READY:
989     case GST_STATE_CHANGE_READY_TO_PAUSED:
990     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
991     default:
992       break;
993   }
994 
995   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
996 
997   switch (transition) {
998     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
999       break;
1000     case GST_STATE_CHANGE_PAUSED_TO_READY:
1001     case GST_STATE_CHANGE_READY_TO_NULL:
1002       gst_rtp_ssrc_demux_reset (demux);
1003       break;
1004     default:
1005       break;
1006   }
1007   return ret;
1008 }
1009