• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim dot taymans at gmail dot com>
3  *
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.
8  *
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.
13  *
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:element-sdpdemux
21  * @title: sdpdemux
22  *
23  * sdpdemux currently understands SDP as the input format of the session description.
24  * For each stream listed in the SDP a new stream_\%u pad will be created
25  * with caps derived from the SDP media description. This is a caps of mime type
26  * "application/x-rtp" that can be connected to any available RTP depayloader
27  * element.
28  *
29  * sdpdemux will internally instantiate an RTP session manager element
30  * that will handle the RTCP messages to and from the server, jitter removal,
31  * packet reordering along with providing a clock for the pipeline.
32  *
33  * sdpdemux acts like a live element and will therefore only generate data in the
34  * PLAYING state.
35  *
36  * ## Example launch line
37  * |[
38  * gst-launch-1.0 souphttpsrc location=http://some.server/session.sdp ! sdpdemux ! fakesink
39  * ]| Establish a connection to an HTTP server that contains an SDP session description
40  * that gets parsed by sdpdemux and send the raw RTP packets to a fakesink.
41  *
42  */
43 
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47 
48 #include "gstsdpdemux.h"
49 
50 #include <gst/rtp/gstrtppayloads.h>
51 #include <gst/sdp/gstsdpmessage.h>
52 
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 
57 GST_DEBUG_CATEGORY_STATIC (sdpdemux_debug);
58 #define GST_CAT_DEFAULT (sdpdemux_debug)
59 
60 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
61     GST_PAD_SINK,
62     GST_PAD_ALWAYS,
63     GST_STATIC_CAPS ("application/sdp"));
64 
65 static GstStaticPadTemplate rtptemplate = GST_STATIC_PAD_TEMPLATE ("stream_%u",
66     GST_PAD_SRC,
67     GST_PAD_SOMETIMES,
68     GST_STATIC_CAPS ("application/x-rtp"));
69 
70 enum
71 {
72   /* FILL ME */
73   LAST_SIGNAL
74 };
75 
76 #define DEFAULT_DEBUG            FALSE
77 #define DEFAULT_TIMEOUT          10000000
78 #define DEFAULT_LATENCY_MS       200
79 #define DEFAULT_REDIRECT         TRUE
80 
81 enum
82 {
83   PROP_0,
84   PROP_DEBUG,
85   PROP_TIMEOUT,
86   PROP_LATENCY,
87   PROP_REDIRECT
88 };
89 
90 static void gst_sdp_demux_finalize (GObject * object);
91 
92 static void gst_sdp_demux_set_property (GObject * object, guint prop_id,
93     const GValue * value, GParamSpec * pspec);
94 static void gst_sdp_demux_get_property (GObject * object, guint prop_id,
95     GValue * value, GParamSpec * pspec);
96 
97 static GstStateChangeReturn gst_sdp_demux_change_state (GstElement * element,
98     GstStateChange transition);
99 static void gst_sdp_demux_handle_message (GstBin * bin, GstMessage * message);
100 
101 static void gst_sdp_demux_stream_push_event (GstSDPDemux * demux,
102     GstSDPStream * stream, GstEvent * event);
103 
104 static gboolean gst_sdp_demux_sink_event (GstPad * pad, GstObject * parent,
105     GstEvent * event);
106 static GstFlowReturn gst_sdp_demux_sink_chain (GstPad * pad, GstObject * parent,
107     GstBuffer * buffer);
108 
109 /*static guint gst_sdp_demux_signals[LAST_SIGNAL] = { 0 }; */
110 
111 #define gst_sdp_demux_parent_class parent_class
112 G_DEFINE_TYPE (GstSDPDemux, gst_sdp_demux, GST_TYPE_BIN);
113 GST_ELEMENT_REGISTER_DEFINE (sdpdemux, "sdpdemux", GST_RANK_NONE,
114     GST_TYPE_SDP_DEMUX);
115 
116 static void
gst_sdp_demux_class_init(GstSDPDemuxClass * klass)117 gst_sdp_demux_class_init (GstSDPDemuxClass * klass)
118 {
119   GObjectClass *gobject_class;
120   GstElementClass *gstelement_class;
121   GstBinClass *gstbin_class;
122 
123   gobject_class = (GObjectClass *) klass;
124   gstelement_class = (GstElementClass *) klass;
125   gstbin_class = (GstBinClass *) klass;
126 
127   gobject_class->set_property = gst_sdp_demux_set_property;
128   gobject_class->get_property = gst_sdp_demux_get_property;
129 
130   gobject_class->finalize = gst_sdp_demux_finalize;
131 
132   g_object_class_install_property (gobject_class, PROP_DEBUG,
133       g_param_spec_boolean ("debug", "Debug",
134           "Dump request and response messages to stdout",
135           DEFAULT_DEBUG,
136           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
137 
138   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
139       g_param_spec_uint64 ("timeout", "Timeout",
140           "Fail transport after UDP timeout microseconds (0 = disabled)",
141           0, G_MAXUINT64, DEFAULT_TIMEOUT,
142           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
143 
144   g_object_class_install_property (gobject_class, PROP_LATENCY,
145       g_param_spec_uint ("latency", "Buffer latency in ms",
146           "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS,
147           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
148 
149   g_object_class_install_property (gobject_class, PROP_REDIRECT,
150       g_param_spec_boolean ("redirect", "Redirect",
151           "Sends a redirection message instead of using a custom session element",
152           DEFAULT_REDIRECT,
153           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
154 
155   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
156   gst_element_class_add_static_pad_template (gstelement_class, &rtptemplate);
157 
158   gst_element_class_set_static_metadata (gstelement_class, "SDP session setup",
159       "Codec/Demuxer/Network/RTP",
160       "Receive data over the network via SDP",
161       "Wim Taymans <wim.taymans@gmail.com>");
162 
163   gstelement_class->change_state = gst_sdp_demux_change_state;
164 
165   gstbin_class->handle_message = gst_sdp_demux_handle_message;
166 
167   GST_DEBUG_CATEGORY_INIT (sdpdemux_debug, "sdpdemux", 0, "SDP demux");
168 }
169 
170 static void
gst_sdp_demux_init(GstSDPDemux * demux)171 gst_sdp_demux_init (GstSDPDemux * demux)
172 {
173   demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
174   gst_pad_set_event_function (demux->sinkpad,
175       GST_DEBUG_FUNCPTR (gst_sdp_demux_sink_event));
176   gst_pad_set_chain_function (demux->sinkpad,
177       GST_DEBUG_FUNCPTR (gst_sdp_demux_sink_chain));
178   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
179 
180   /* protects the streaming thread in interleaved mode or the polling
181    * thread in UDP mode. */
182   g_rec_mutex_init (&demux->stream_rec_lock);
183 
184   demux->adapter = gst_adapter_new ();
185 }
186 
187 static void
gst_sdp_demux_finalize(GObject * object)188 gst_sdp_demux_finalize (GObject * object)
189 {
190   GstSDPDemux *demux;
191 
192   demux = GST_SDP_DEMUX (object);
193 
194   /* free locks */
195   g_rec_mutex_clear (&demux->stream_rec_lock);
196 
197   g_object_unref (demux->adapter);
198 
199   G_OBJECT_CLASS (parent_class)->finalize (object);
200 }
201 
202 static void
gst_sdp_demux_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)203 gst_sdp_demux_set_property (GObject * object, guint prop_id,
204     const GValue * value, GParamSpec * pspec)
205 {
206   GstSDPDemux *demux;
207 
208   demux = GST_SDP_DEMUX (object);
209 
210   switch (prop_id) {
211     case PROP_DEBUG:
212       demux->debug = g_value_get_boolean (value);
213       break;
214     case PROP_TIMEOUT:
215       demux->udp_timeout = g_value_get_uint64 (value);
216       break;
217     case PROP_LATENCY:
218       demux->latency = g_value_get_uint (value);
219       break;
220     case PROP_REDIRECT:
221       demux->redirect = g_value_get_boolean (value);
222       break;
223     default:
224       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
225       break;
226   }
227 }
228 
229 static void
gst_sdp_demux_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)230 gst_sdp_demux_get_property (GObject * object, guint prop_id, GValue * value,
231     GParamSpec * pspec)
232 {
233   GstSDPDemux *demux;
234 
235   demux = GST_SDP_DEMUX (object);
236 
237   switch (prop_id) {
238     case PROP_DEBUG:
239       g_value_set_boolean (value, demux->debug);
240       break;
241     case PROP_TIMEOUT:
242       g_value_set_uint64 (value, demux->udp_timeout);
243       break;
244     case PROP_LATENCY:
245       g_value_set_uint (value, demux->latency);
246       break;
247     case PROP_REDIRECT:
248       g_value_set_boolean (value, demux->redirect);
249       break;
250     default:
251       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
252       break;
253   }
254 }
255 
256 static gint
find_stream_by_id(GstSDPStream * stream,gconstpointer a)257 find_stream_by_id (GstSDPStream * stream, gconstpointer a)
258 {
259   gint id = GPOINTER_TO_INT (a);
260 
261   if (stream->id == id)
262     return 0;
263 
264   return -1;
265 }
266 
267 static gint
find_stream_by_pt(GstSDPStream * stream,gconstpointer a)268 find_stream_by_pt (GstSDPStream * stream, gconstpointer a)
269 {
270   gint pt = GPOINTER_TO_INT (a);
271 
272   if (stream->pt == pt)
273     return 0;
274 
275   return -1;
276 }
277 
278 static gint
find_stream_by_udpsrc(GstSDPStream * stream,gconstpointer a)279 find_stream_by_udpsrc (GstSDPStream * stream, gconstpointer a)
280 {
281   GstElement *src = (GstElement *) a;
282 
283   if (stream->udpsrc[0] == src)
284     return 0;
285   if (stream->udpsrc[1] == src)
286     return 0;
287 
288   return -1;
289 }
290 
291 static GstSDPStream *
find_stream(GstSDPDemux * demux,gconstpointer data,gconstpointer func)292 find_stream (GstSDPDemux * demux, gconstpointer data, gconstpointer func)
293 {
294   GList *lstream;
295 
296   /* find and get stream */
297   if ((lstream =
298           g_list_find_custom (demux->streams, data, (GCompareFunc) func)))
299     return (GstSDPStream *) lstream->data;
300 
301   return NULL;
302 }
303 
304 static void
gst_sdp_demux_stream_free(GstSDPDemux * demux,GstSDPStream * stream)305 gst_sdp_demux_stream_free (GstSDPDemux * demux, GstSDPStream * stream)
306 {
307   gint i;
308 
309   GST_DEBUG_OBJECT (demux, "free stream %p", stream);
310 
311   if (stream->caps)
312     gst_caps_unref (stream->caps);
313 
314   for (i = 0; i < 2; i++) {
315     GstElement *udpsrc = stream->udpsrc[i];
316     GstPad *channelpad = stream->channelpad[i];
317 
318     if (udpsrc) {
319       gst_element_set_state (udpsrc, GST_STATE_NULL);
320       gst_bin_remove (GST_BIN_CAST (demux), udpsrc);
321       stream->udpsrc[i] = NULL;
322     }
323 
324     if (channelpad) {
325       if (demux->session) {
326         gst_element_release_request_pad (demux->session, channelpad);
327       }
328       gst_object_unref (channelpad);
329       stream->channelpad[i] = NULL;
330     }
331   }
332   if (stream->udpsink) {
333     gst_element_set_state (stream->udpsink, GST_STATE_NULL);
334     gst_bin_remove (GST_BIN_CAST (demux), stream->udpsink);
335     stream->udpsink = NULL;
336   }
337   if (stream->rtcppad) {
338     if (demux->session) {
339       gst_element_release_request_pad (demux->session, stream->rtcppad);
340     }
341     gst_object_unref (stream->rtcppad);
342     stream->rtcppad = NULL;
343   }
344   if (stream->srcpad) {
345     gst_pad_set_active (stream->srcpad, FALSE);
346     if (stream->added) {
347       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->srcpad);
348       stream->added = FALSE;
349     }
350     stream->srcpad = NULL;
351   }
352   g_free (stream);
353 }
354 
355 static gboolean
is_multicast_address(const gchar * host_name)356 is_multicast_address (const gchar * host_name)
357 {
358   GInetAddress *addr;
359   GResolver *resolver = NULL;
360   gboolean ret = FALSE;
361 
362   addr = g_inet_address_new_from_string (host_name);
363   if (!addr) {
364     GList *results;
365 
366     resolver = g_resolver_get_default ();
367     results = g_resolver_lookup_by_name (resolver, host_name, NULL, NULL);
368     if (!results)
369       goto out;
370     addr = G_INET_ADDRESS (g_object_ref (results->data));
371 
372     g_resolver_free_addresses (results);
373   }
374   g_assert (addr != NULL);
375 
376   ret = g_inet_address_get_is_multicast (addr);
377 
378 out:
379   if (resolver)
380     g_object_unref (resolver);
381   if (addr)
382     g_object_unref (addr);
383   return ret;
384 }
385 
386 static GstSDPStream *
gst_sdp_demux_create_stream(GstSDPDemux * demux,GstSDPMessage * sdp,gint idx)387 gst_sdp_demux_create_stream (GstSDPDemux * demux, GstSDPMessage * sdp, gint idx)
388 {
389   GstSDPStream *stream;
390   const gchar *payload;
391   const GstSDPMedia *media;
392   const GstSDPConnection *conn;
393 
394   /* get media, should not return NULL */
395   media = gst_sdp_message_get_media (sdp, idx);
396   if (media == NULL)
397     return NULL;
398 
399   stream = g_new0 (GstSDPStream, 1);
400   stream->parent = demux;
401   /* we mark the pad as not linked, we will mark it as OK when we add the pad to
402    * the element. */
403   stream->last_ret = GST_FLOW_OK;
404   stream->added = FALSE;
405   stream->disabled = FALSE;
406   stream->id = demux->numstreams++;
407   stream->eos = FALSE;
408 
409   /* we must have a payload. No payload means we cannot create caps */
410   /* FIXME, handle multiple formats. */
411   if ((payload = gst_sdp_media_get_format (media, 0))) {
412     GstStructure *s;
413 
414     stream->pt = atoi (payload);
415     /* convert caps */
416     stream->caps = gst_sdp_media_get_caps_from_media (media, stream->pt);
417 
418     s = gst_caps_get_structure (stream->caps, 0);
419     gst_structure_set_name (s, "application/x-rtp");
420 
421     gst_sdp_media_attributes_to_caps (media, stream->caps);
422 
423     if (stream->pt >= 96) {
424       /* If we have a dynamic payload type, see if we have a stream with the
425        * same payload number. If there is one, they are part of the same
426        * container and we only need to add one pad. */
427       if (find_stream (demux, GINT_TO_POINTER (stream->pt),
428               (gpointer) find_stream_by_pt)) {
429         stream->container = TRUE;
430       }
431     }
432   }
433 
434   if (gst_sdp_media_connections_len (media) > 0) {
435     if (!(conn = gst_sdp_media_get_connection (media, 0))) {
436       /* We should not reach this based on the check above */
437       goto no_connection;
438     }
439   } else {
440     if (!(conn = gst_sdp_message_get_connection (sdp))) {
441       goto no_connection;
442     }
443   }
444 
445   if (!conn->address)
446     goto no_connection;
447 
448   stream->destination = conn->address;
449   stream->ttl = conn->ttl;
450   stream->multicast = is_multicast_address (stream->destination);
451 
452   stream->rtp_port = gst_sdp_media_get_port (media);
453   if (gst_sdp_media_get_attribute_val (media, "rtcp")) {
454     /* FIXME, RFC 3605 */
455     stream->rtcp_port = stream->rtp_port + 1;
456   } else {
457     stream->rtcp_port = stream->rtp_port + 1;
458   }
459 
460   GST_DEBUG_OBJECT (demux, "stream %d, (%p)", stream->id, stream);
461   GST_DEBUG_OBJECT (demux, " pt: %d", stream->pt);
462   GST_DEBUG_OBJECT (demux, " container: %d", stream->container);
463   GST_DEBUG_OBJECT (demux, " caps: %" GST_PTR_FORMAT, stream->caps);
464 
465   /* we keep track of all streams */
466   demux->streams = g_list_append (demux->streams, stream);
467 
468   return stream;
469 
470   /* ERRORS */
471 no_connection:
472   {
473     gst_sdp_demux_stream_free (demux, stream);
474     return NULL;
475   }
476 }
477 
478 static void
gst_sdp_demux_cleanup(GstSDPDemux * demux)479 gst_sdp_demux_cleanup (GstSDPDemux * demux)
480 {
481   GList *walk;
482 
483   GST_DEBUG_OBJECT (demux, "cleanup");
484 
485   for (walk = demux->streams; walk; walk = g_list_next (walk)) {
486     GstSDPStream *stream = (GstSDPStream *) walk->data;
487 
488     gst_sdp_demux_stream_free (demux, stream);
489   }
490   g_list_free (demux->streams);
491   demux->streams = NULL;
492   if (demux->session) {
493     if (demux->session_sig_id) {
494       g_signal_handler_disconnect (demux->session, demux->session_sig_id);
495       demux->session_sig_id = 0;
496     }
497     if (demux->session_nmp_id) {
498       g_signal_handler_disconnect (demux->session, demux->session_nmp_id);
499       demux->session_nmp_id = 0;
500     }
501     if (demux->session_ptmap_id) {
502       g_signal_handler_disconnect (demux->session, demux->session_ptmap_id);
503       demux->session_ptmap_id = 0;
504     }
505     gst_element_set_state (demux->session, GST_STATE_NULL);
506     gst_bin_remove (GST_BIN_CAST (demux), demux->session);
507     demux->session = NULL;
508   }
509   demux->numstreams = 0;
510 }
511 
512 /* this callback is called when the session manager generated a new src pad with
513  * payloaded RTP packets. We simply ghost the pad here. */
514 static void
new_session_pad(GstElement * session,GstPad * pad,GstSDPDemux * demux)515 new_session_pad (GstElement * session, GstPad * pad, GstSDPDemux * demux)
516 {
517   gchar *name, *pad_name;
518   GstPadTemplate *template;
519   guint id, ssrc, pt;
520   GList *lstream;
521   GstSDPStream *stream;
522   gboolean all_added;
523 
524   GST_DEBUG_OBJECT (demux, "got new session pad %" GST_PTR_FORMAT, pad);
525 
526   GST_SDP_STREAM_LOCK (demux);
527   /* find stream */
528   name = gst_object_get_name (GST_OBJECT_CAST (pad));
529   if (sscanf (name, "recv_rtp_src_%u_%u_%u", &id, &ssrc, &pt) != 3)
530     goto unknown_stream;
531 
532   GST_DEBUG_OBJECT (demux, "stream: %u, SSRC %u, PT %u", id, ssrc, pt);
533 
534   stream =
535       find_stream (demux, GUINT_TO_POINTER (id), (gpointer) find_stream_by_id);
536   if (stream == NULL)
537     goto unknown_stream;
538 
539   stream->ssrc = ssrc;
540 
541   /* no need for a timeout anymore now */
542   g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout", (guint64) 0, NULL);
543 
544   pad_name = g_strdup_printf ("stream_%u", stream->id);
545   /* create a new pad we will use to stream to */
546   template = gst_static_pad_template_get (&rtptemplate);
547   stream->srcpad = gst_ghost_pad_new_from_template (pad_name, pad, template);
548   gst_object_unref (template);
549   g_free (name);
550   g_free (pad_name);
551 
552   stream->added = TRUE;
553   gst_pad_set_active (stream->srcpad, TRUE);
554   gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->srcpad);
555 
556   /* check if we added all streams */
557   all_added = TRUE;
558   for (lstream = demux->streams; lstream; lstream = g_list_next (lstream)) {
559     stream = (GstSDPStream *) lstream->data;
560     /* a container stream only needs one pad added. Also disabled streams don't
561      * count */
562     if (!stream->container && !stream->disabled && !stream->added) {
563       all_added = FALSE;
564       break;
565     }
566   }
567   GST_SDP_STREAM_UNLOCK (demux);
568 
569   if (all_added) {
570     GST_DEBUG_OBJECT (demux, "We added all streams");
571     /* when we get here, all stream are added and we can fire the no-more-pads
572      * signal. */
573     gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
574   }
575 
576   return;
577 
578   /* ERRORS */
579 unknown_stream:
580   {
581     GST_DEBUG_OBJECT (demux, "ignoring unknown stream");
582     GST_SDP_STREAM_UNLOCK (demux);
583     g_free (name);
584     return;
585   }
586 }
587 
588 static void
rtsp_session_pad_added(GstElement * session,GstPad * pad,GstSDPDemux * demux)589 rtsp_session_pad_added (GstElement * session, GstPad * pad, GstSDPDemux * demux)
590 {
591   GstPad *srcpad = NULL;
592   gchar *name;
593 
594   GST_DEBUG_OBJECT (demux, "got new session pad %" GST_PTR_FORMAT, pad);
595 
596   name = gst_pad_get_name (pad);
597   srcpad = gst_ghost_pad_new (name, pad);
598   g_free (name);
599 
600   gst_pad_set_active (srcpad, TRUE);
601   gst_element_add_pad (GST_ELEMENT_CAST (demux), srcpad);
602 }
603 
604 static void
rtsp_session_no_more_pads(GstElement * session,GstSDPDemux * demux)605 rtsp_session_no_more_pads (GstElement * session, GstSDPDemux * demux)
606 {
607   GST_DEBUG_OBJECT (demux, "got no-more-pads");
608   gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
609 }
610 
611 static GstCaps *
request_pt_map(GstElement * sess,guint session,guint pt,GstSDPDemux * demux)612 request_pt_map (GstElement * sess, guint session, guint pt, GstSDPDemux * demux)
613 {
614   GstSDPStream *stream;
615   GstCaps *caps;
616 
617   GST_DEBUG_OBJECT (demux, "getting pt map for pt %d in session %d", pt,
618       session);
619 
620   GST_SDP_STREAM_LOCK (demux);
621   stream =
622       find_stream (demux, GINT_TO_POINTER (session),
623       (gpointer) find_stream_by_id);
624   if (!stream)
625     goto unknown_stream;
626 
627   caps = stream->caps;
628   if (caps)
629     gst_caps_ref (caps);
630   GST_SDP_STREAM_UNLOCK (demux);
631 
632   return caps;
633 
634 unknown_stream:
635   {
636     GST_DEBUG_OBJECT (demux, "unknown stream %d", session);
637     GST_SDP_STREAM_UNLOCK (demux);
638     return NULL;
639   }
640 }
641 
642 static void
gst_sdp_demux_do_stream_eos(GstSDPDemux * demux,guint session,guint32 ssrc)643 gst_sdp_demux_do_stream_eos (GstSDPDemux * demux, guint session, guint32 ssrc)
644 {
645   GstSDPStream *stream;
646 
647   GST_DEBUG_OBJECT (demux, "setting stream for session %u to EOS", session);
648 
649   /* get stream for session */
650   stream =
651       find_stream (demux, GINT_TO_POINTER (session),
652       (gpointer) find_stream_by_id);
653   if (!stream)
654     goto unknown_stream;
655 
656   if (stream->eos)
657     goto was_eos;
658 
659   if (stream->ssrc != ssrc)
660     goto wrong_ssrc;
661 
662   stream->eos = TRUE;
663   gst_sdp_demux_stream_push_event (demux, stream, gst_event_new_eos ());
664   return;
665 
666   /* ERRORS */
667 unknown_stream:
668   {
669     GST_DEBUG_OBJECT (demux, "unknown stream for session %u", session);
670     return;
671   }
672 was_eos:
673   {
674     GST_DEBUG_OBJECT (demux, "stream for session %u was already EOS", session);
675     return;
676   }
677 wrong_ssrc:
678   {
679     GST_DEBUG_OBJECT (demux, "unkown SSRC %08x for session %u", ssrc, session);
680     return;
681   }
682 }
683 
684 static void
on_bye_ssrc(GstElement * manager,guint session,guint32 ssrc,GstSDPDemux * demux)685 on_bye_ssrc (GstElement * manager, guint session, guint32 ssrc,
686     GstSDPDemux * demux)
687 {
688   GST_DEBUG_OBJECT (demux, "SSRC %08x in session %u received BYE", ssrc,
689       session);
690 
691   gst_sdp_demux_do_stream_eos (demux, session, ssrc);
692 }
693 
694 static void
on_timeout(GstElement * manager,guint session,guint32 ssrc,GstSDPDemux * demux)695 on_timeout (GstElement * manager, guint session, guint32 ssrc,
696     GstSDPDemux * demux)
697 {
698   GST_DEBUG_OBJECT (demux, "SSRC %08x in session %u timed out", ssrc, session);
699 
700   gst_sdp_demux_do_stream_eos (demux, session, ssrc);
701 }
702 
703 /* try to get and configure a manager */
704 static gboolean
gst_sdp_demux_configure_manager(GstSDPDemux * demux,char * rtsp_sdp)705 gst_sdp_demux_configure_manager (GstSDPDemux * demux, char *rtsp_sdp)
706 {
707   /* configure the session manager */
708   if (rtsp_sdp != NULL) {
709     if (!(demux->session = gst_element_factory_make ("rtspsrc", NULL)))
710       goto rtspsrc_failed;
711 
712     g_object_set (demux->session, "location", rtsp_sdp, NULL);
713 
714     GST_DEBUG_OBJECT (demux, "connect to signals on rtspsrc");
715     demux->session_sig_id =
716         g_signal_connect (demux->session, "pad-added",
717         (GCallback) rtsp_session_pad_added, demux);
718     demux->session_nmp_id =
719         g_signal_connect (demux->session, "no-more-pads",
720         (GCallback) rtsp_session_no_more_pads, demux);
721   } else {
722     if (!(demux->session = gst_element_factory_make ("rtpbin", NULL)))
723       goto manager_failed;
724 
725     /* connect to signals if we did not already do so */
726     GST_DEBUG_OBJECT (demux, "connect to signals on session manager");
727     demux->session_sig_id =
728         g_signal_connect (demux->session, "pad-added",
729         (GCallback) new_session_pad, demux);
730     demux->session_ptmap_id =
731         g_signal_connect (demux->session, "request-pt-map",
732         (GCallback) request_pt_map, demux);
733     g_signal_connect (demux->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
734         demux);
735     g_signal_connect (demux->session, "on-bye-timeout", (GCallback) on_timeout,
736         demux);
737     g_signal_connect (demux->session, "on-timeout", (GCallback) on_timeout,
738         demux);
739   }
740 
741   g_object_set (demux->session, "latency", demux->latency, NULL);
742 
743   /* we manage this element */
744   gst_bin_add (GST_BIN_CAST (demux), demux->session);
745 
746   return TRUE;
747 
748   /* ERRORS */
749 manager_failed:
750   {
751     GST_DEBUG_OBJECT (demux, "no session manager element gstrtpbin found");
752     return FALSE;
753   }
754 rtspsrc_failed:
755   {
756     GST_DEBUG_OBJECT (demux, "no manager element rtspsrc found");
757     return FALSE;
758   }
759 }
760 
761 static gboolean
gst_sdp_demux_stream_configure_udp(GstSDPDemux * demux,GstSDPStream * stream)762 gst_sdp_demux_stream_configure_udp (GstSDPDemux * demux, GstSDPStream * stream)
763 {
764   gchar *uri, *name;
765   const gchar *destination;
766   GstPad *pad;
767 
768   GST_DEBUG_OBJECT (demux, "creating UDP sources for multicast");
769 
770   /* if the destination is not a multicast address, we just want to listen on
771    * our local ports */
772   if (!stream->multicast)
773     destination = "0.0.0.0";
774   else
775     destination = stream->destination;
776 
777   /* creating UDP source */
778   if (stream->rtp_port != -1) {
779     GST_DEBUG_OBJECT (demux, "receiving RTP from %s:%d", destination,
780         stream->rtp_port);
781 
782     uri = g_strdup_printf ("udp://%s:%d", destination, stream->rtp_port);
783     stream->udpsrc[0] =
784         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
785     g_free (uri);
786     if (stream->udpsrc[0] == NULL)
787       goto no_element;
788 
789     /* take ownership */
790     gst_bin_add (GST_BIN_CAST (demux), stream->udpsrc[0]);
791 
792     GST_DEBUG_OBJECT (demux,
793         "setting up UDP source with timeout %" G_GINT64_FORMAT,
794         demux->udp_timeout);
795 
796     /* configure a timeout on the UDP port. When the timeout message is
797      * posted, we assume UDP transport is not possible. */
798     g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout",
799         demux->udp_timeout * 1000, NULL);
800 
801     /* get output pad of the UDP source. */
802     pad = gst_element_get_static_pad (stream->udpsrc[0], "src");
803 
804     name = g_strdup_printf ("recv_rtp_sink_%u", stream->id);
805     stream->channelpad[0] =
806         gst_element_request_pad_simple (demux->session, name);
807     g_free (name);
808 
809     GST_DEBUG_OBJECT (demux, "connecting RTP source 0 to manager");
810     /* configure for UDP delivery, we need to connect the UDP pads to
811      * the session plugin. */
812     gst_pad_link (pad, stream->channelpad[0]);
813     gst_object_unref (pad);
814 
815     /* change state */
816     gst_element_set_state (stream->udpsrc[0], GST_STATE_PAUSED);
817   }
818 
819   /* creating another UDP source */
820   if (stream->rtcp_port != -1) {
821     GST_DEBUG_OBJECT (demux, "receiving RTCP from %s:%d", destination,
822         stream->rtcp_port);
823     uri = g_strdup_printf ("udp://%s:%d", destination, stream->rtcp_port);
824     stream->udpsrc[1] =
825         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
826     g_free (uri);
827     if (stream->udpsrc[1] == NULL)
828       goto no_element;
829 
830     /* take ownership */
831     gst_bin_add (GST_BIN_CAST (demux), stream->udpsrc[1]);
832 
833     GST_DEBUG_OBJECT (demux, "connecting RTCP source to manager");
834 
835     name = g_strdup_printf ("recv_rtcp_sink_%u", stream->id);
836     stream->channelpad[1] =
837         gst_element_request_pad_simple (demux->session, name);
838     g_free (name);
839 
840     pad = gst_element_get_static_pad (stream->udpsrc[1], "src");
841     gst_pad_link (pad, stream->channelpad[1]);
842     gst_object_unref (pad);
843 
844     gst_element_set_state (stream->udpsrc[1], GST_STATE_PAUSED);
845   }
846   return TRUE;
847 
848   /* ERRORS */
849 no_element:
850   {
851     GST_DEBUG_OBJECT (demux, "no UDP source element found");
852     return FALSE;
853   }
854 }
855 
856 /* configure the UDP sink back to the server for status reports */
857 static gboolean
gst_sdp_demux_stream_configure_udp_sink(GstSDPDemux * demux,GstSDPStream * stream)858 gst_sdp_demux_stream_configure_udp_sink (GstSDPDemux * demux,
859     GstSDPStream * stream)
860 {
861   GstPad *sinkpad;
862   gint port;
863   GSocket *socket;
864   gchar *destination, *uri, *name;
865 
866   /* get destination and port */
867   port = stream->rtcp_port;
868   destination = stream->destination;
869 
870   GST_DEBUG_OBJECT (demux, "configure UDP sink for %s:%d", destination, port);
871 
872   uri = g_strdup_printf ("udp://%s:%d", destination, port);
873   stream->udpsink = gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
874   g_free (uri);
875   if (stream->udpsink == NULL)
876     goto no_sink_element;
877 
878   /* we clear all destinations because we don't really know where to send the
879    * RTCP to and we want to avoid sending it to our own ports.
880    * FIXME when we get an RTCP packet from the sender, we could look at its
881    * source port and address and try to send RTCP there. */
882   if (!stream->multicast)
883     g_signal_emit_by_name (stream->udpsink, "clear");
884 
885   g_object_set (G_OBJECT (stream->udpsink), "auto-multicast", FALSE, NULL);
886   g_object_set (G_OBJECT (stream->udpsink), "loop", FALSE, NULL);
887   /* no sync needed */
888   g_object_set (G_OBJECT (stream->udpsink), "sync", FALSE, NULL);
889   /* no async state changes needed */
890   g_object_set (G_OBJECT (stream->udpsink), "async", FALSE, NULL);
891 
892   if (stream->udpsrc[1]) {
893     /* configure socket, we give it the same UDP socket as the udpsrc for RTCP
894      * because some servers check the port number of where it sends RTCP to identify
895      * the RTCP packets it receives */
896     g_object_get (G_OBJECT (stream->udpsrc[1]), "used_socket", &socket, NULL);
897     GST_DEBUG_OBJECT (demux, "UDP src has socket %p", socket);
898     /* configure socket and make sure udpsink does not close it when shutting
899      * down, it belongs to udpsrc after all. */
900     g_object_set (G_OBJECT (stream->udpsink), "socket", socket, NULL);
901     g_object_set (G_OBJECT (stream->udpsink), "close-socket", FALSE, NULL);
902     g_object_unref (socket);
903   }
904 
905   /* we keep this playing always */
906   gst_element_set_locked_state (stream->udpsink, TRUE);
907   gst_element_set_state (stream->udpsink, GST_STATE_PLAYING);
908 
909   gst_bin_add (GST_BIN_CAST (demux), stream->udpsink);
910 
911   /* get session RTCP pad */
912   name = g_strdup_printf ("send_rtcp_src_%u", stream->id);
913   stream->rtcppad = gst_element_request_pad_simple (demux->session, name);
914   g_free (name);
915 
916   /* and link */
917   if (stream->rtcppad) {
918     sinkpad = gst_element_get_static_pad (stream->udpsink, "sink");
919     gst_pad_link (stream->rtcppad, sinkpad);
920     gst_object_unref (sinkpad);
921   } else {
922     /* not very fatal, we just won't be able to send RTCP */
923     GST_WARNING_OBJECT (demux, "could not get session RTCP pad");
924   }
925 
926   return TRUE;
927 
928   /* ERRORS */
929 no_sink_element:
930   {
931     GST_DEBUG_OBJECT (demux, "no UDP sink element found");
932     return FALSE;
933   }
934 }
935 
936 static GstFlowReturn
gst_sdp_demux_combine_flows(GstSDPDemux * demux,GstSDPStream * stream,GstFlowReturn ret)937 gst_sdp_demux_combine_flows (GstSDPDemux * demux, GstSDPStream * stream,
938     GstFlowReturn ret)
939 {
940   GList *streams;
941 
942   /* store the value */
943   stream->last_ret = ret;
944 
945   /* if it's success we can return the value right away */
946   if (ret == GST_FLOW_OK)
947     goto done;
948 
949   /* any other error that is not-linked can be returned right
950    * away */
951   if (ret != GST_FLOW_NOT_LINKED)
952     goto done;
953 
954   /* only return NOT_LINKED if all other pads returned NOT_LINKED */
955   for (streams = demux->streams; streams; streams = g_list_next (streams)) {
956     GstSDPStream *ostream = (GstSDPStream *) streams->data;
957 
958     ret = ostream->last_ret;
959     /* some other return value (must be SUCCESS but we can return
960      * other values as well) */
961     if (ret != GST_FLOW_NOT_LINKED)
962       goto done;
963   }
964   /* if we get here, all other pads were unlinked and we return
965    * NOT_LINKED then */
966 done:
967   return ret;
968 }
969 
970 static void
gst_sdp_demux_stream_push_event(GstSDPDemux * demux,GstSDPStream * stream,GstEvent * event)971 gst_sdp_demux_stream_push_event (GstSDPDemux * demux, GstSDPStream * stream,
972     GstEvent * event)
973 {
974   /* only streams that have a connection to the outside world */
975   if (stream->srcpad == NULL)
976     goto done;
977 
978   if (stream->channelpad[0]) {
979     gst_event_ref (event);
980     gst_pad_send_event (stream->channelpad[0], event);
981   }
982 
983   if (stream->channelpad[1]) {
984     gst_event_ref (event);
985     gst_pad_send_event (stream->channelpad[1], event);
986   }
987 
988 done:
989   gst_event_unref (event);
990 }
991 
992 static void
gst_sdp_demux_handle_message(GstBin * bin,GstMessage * message)993 gst_sdp_demux_handle_message (GstBin * bin, GstMessage * message)
994 {
995   GstSDPDemux *demux;
996 
997   demux = GST_SDP_DEMUX (bin);
998 
999   switch (GST_MESSAGE_TYPE (message)) {
1000     case GST_MESSAGE_ELEMENT:
1001     {
1002       const GstStructure *s = gst_message_get_structure (message);
1003 
1004       if (gst_structure_has_name (s, "GstUDPSrcTimeout")) {
1005         gboolean ignore_timeout;
1006 
1007         GST_DEBUG_OBJECT (bin, "timeout on UDP port");
1008 
1009         GST_OBJECT_LOCK (demux);
1010         ignore_timeout = demux->ignore_timeout;
1011         demux->ignore_timeout = TRUE;
1012         GST_OBJECT_UNLOCK (demux);
1013 
1014         /* we only act on the first udp timeout message, others are irrelevant
1015          * and can be ignored. */
1016         if (ignore_timeout)
1017           gst_message_unref (message);
1018         else {
1019           GST_ELEMENT_ERROR (demux, RESOURCE, READ, (NULL),
1020               ("Could not receive any UDP packets for %.4f seconds, maybe your "
1021                   "firewall is blocking it.",
1022                   gst_guint64_to_gdouble (demux->udp_timeout / 1000000.0)));
1023         }
1024         return;
1025       }
1026       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
1027       break;
1028     }
1029     case GST_MESSAGE_ERROR:
1030     {
1031       GstObject *udpsrc;
1032       GstSDPStream *stream;
1033       GstFlowReturn ret;
1034 
1035       udpsrc = GST_MESSAGE_SRC (message);
1036 
1037       GST_DEBUG_OBJECT (demux, "got error from %s", GST_ELEMENT_NAME (udpsrc));
1038 
1039       stream = find_stream (demux, udpsrc, (gpointer) find_stream_by_udpsrc);
1040       /* fatal but not our message, forward */
1041       if (!stream)
1042         goto forward;
1043 
1044       /* we ignore the RTCP udpsrc */
1045       if (stream->udpsrc[1] == GST_ELEMENT_CAST (udpsrc))
1046         goto done;
1047 
1048       /* if we get error messages from the udp sources, that's not a problem as
1049        * long as not all of them error out. We also don't really know what the
1050        * problem is, the message does not give enough detail... */
1051       ret = gst_sdp_demux_combine_flows (demux, stream, GST_FLOW_NOT_LINKED);
1052       GST_DEBUG_OBJECT (demux, "combined flows: %s", gst_flow_get_name (ret));
1053       if (ret != GST_FLOW_OK)
1054         goto forward;
1055 
1056     done:
1057       gst_message_unref (message);
1058       break;
1059 
1060     forward:
1061       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
1062       break;
1063     }
1064     default:
1065     {
1066       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
1067       break;
1068     }
1069   }
1070 }
1071 
1072 static gboolean
gst_sdp_demux_start(GstSDPDemux * demux)1073 gst_sdp_demux_start (GstSDPDemux * demux)
1074 {
1075   guint8 *data = NULL;
1076   guint size;
1077   gint i, n_streams;
1078   GstSDPMessage sdp = { 0 };
1079   GstSDPStream *stream = NULL;
1080   GList *walk;
1081   gchar *uri = NULL;
1082   GstStateChangeReturn ret;
1083 
1084   /* grab the lock so that no state change can interfere */
1085   GST_SDP_STREAM_LOCK (demux);
1086 
1087   GST_DEBUG_OBJECT (demux, "parse SDP...");
1088 
1089   size = gst_adapter_available (demux->adapter);
1090   if (size == 0)
1091     goto no_data;
1092 
1093   data = gst_adapter_take (demux->adapter, size);
1094 
1095   gst_sdp_message_init (&sdp);
1096   if (gst_sdp_message_parse_buffer (data, size, &sdp) != GST_SDP_OK)
1097     goto could_not_parse;
1098 
1099   if (demux->debug)
1100     gst_sdp_message_dump (&sdp);
1101 
1102   /* maybe this is plain RTSP DESCRIBE rtsp and we should redirect */
1103   /* look for rtsp control url */
1104   {
1105     const gchar *control;
1106 
1107     for (i = 0;; i++) {
1108       control = gst_sdp_message_get_attribute_val_n (&sdp, "control", i);
1109       if (control == NULL)
1110         break;
1111 
1112       /* only take fully qualified urls */
1113       if (g_str_has_prefix (control, "rtsp://"))
1114         break;
1115     }
1116     if (!control) {
1117       gint idx;
1118 
1119       /* try to find non-aggragate control */
1120       n_streams = gst_sdp_message_medias_len (&sdp);
1121 
1122       for (idx = 0; idx < n_streams; idx++) {
1123         const GstSDPMedia *media;
1124 
1125         /* get media, should not return NULL */
1126         media = gst_sdp_message_get_media (&sdp, idx);
1127         if (media == NULL)
1128           break;
1129 
1130         for (i = 0;; i++) {
1131           control = gst_sdp_media_get_attribute_val_n (media, "control", i);
1132           if (control == NULL)
1133             break;
1134 
1135           /* only take fully qualified urls */
1136           if (g_str_has_prefix (control, "rtsp://"))
1137             break;
1138         }
1139         /* this media has no control, exit */
1140         if (!control)
1141           break;
1142       }
1143     }
1144 
1145     if (control) {
1146       /* we have RTSP now */
1147       uri = gst_sdp_message_as_uri ("rtsp-sdp", &sdp);
1148 
1149       if (demux->redirect) {
1150         GST_INFO_OBJECT (demux, "redirect to %s", uri);
1151 
1152         gst_element_post_message (GST_ELEMENT_CAST (demux),
1153             gst_message_new_element (GST_OBJECT_CAST (demux),
1154                 gst_structure_new ("redirect",
1155                     "new-location", G_TYPE_STRING, uri, NULL)));
1156         goto sent_redirect;
1157       }
1158     }
1159   }
1160 
1161   /* we get here when we didn't do a redirect */
1162 
1163   /* try to get and configure a manager */
1164   if (!gst_sdp_demux_configure_manager (demux, uri))
1165     goto no_manager;
1166   if (!uri) {
1167     /* create streams with UDP sources and sinks */
1168     n_streams = gst_sdp_message_medias_len (&sdp);
1169     for (i = 0; i < n_streams; i++) {
1170       stream = gst_sdp_demux_create_stream (demux, &sdp, i);
1171 
1172       if (!stream)
1173         continue;
1174 
1175       GST_DEBUG_OBJECT (demux, "configuring transport for stream %p", stream);
1176 
1177       if (!gst_sdp_demux_stream_configure_udp (demux, stream))
1178         goto transport_failed;
1179       if (!gst_sdp_demux_stream_configure_udp_sink (demux, stream))
1180         goto transport_failed;
1181     }
1182 
1183     if (!demux->streams)
1184       goto no_streams;
1185   }
1186 
1187   /* set target state on session manager */
1188   /* setting rtspsrc to PLAYING may cause it to loose it that target state
1189    * along the way due to no-preroll udpsrc elements, so ...
1190    * do it in two stages here (similar to other elements) */
1191   if (demux->target > GST_STATE_PAUSED) {
1192     ret = gst_element_set_state (demux->session, GST_STATE_PAUSED);
1193     if (ret == GST_STATE_CHANGE_FAILURE)
1194       goto start_session_failure;
1195   }
1196   ret = gst_element_set_state (demux->session, demux->target);
1197   if (ret == GST_STATE_CHANGE_FAILURE)
1198     goto start_session_failure;
1199 
1200   if (!uri) {
1201     /* activate all streams */
1202     for (walk = demux->streams; walk; walk = g_list_next (walk)) {
1203       stream = (GstSDPStream *) walk->data;
1204 
1205       /* configure target state on udp sources */
1206       gst_element_set_state (stream->udpsrc[0], demux->target);
1207       gst_element_set_state (stream->udpsrc[1], demux->target);
1208     }
1209   }
1210   GST_SDP_STREAM_UNLOCK (demux);
1211   gst_sdp_message_uninit (&sdp);
1212   g_free (data);
1213 
1214   return TRUE;
1215 
1216   /* ERRORS */
1217 done:
1218   {
1219     GST_SDP_STREAM_UNLOCK (demux);
1220     gst_sdp_message_uninit (&sdp);
1221     g_free (data);
1222     return FALSE;
1223   }
1224 transport_failed:
1225   {
1226     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1227         ("Could not create RTP stream transport."));
1228     goto done;
1229   }
1230 no_manager:
1231   {
1232     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1233         ("Could not create RTP session manager."));
1234     goto done;
1235   }
1236 no_data:
1237   {
1238     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1239         ("Empty SDP message."));
1240     goto done;
1241   }
1242 could_not_parse:
1243   {
1244     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1245         ("Could not parse SDP message."));
1246     goto done;
1247   }
1248 no_streams:
1249   {
1250     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1251         ("No streams in SDP message."));
1252     goto done;
1253   }
1254 sent_redirect:
1255   {
1256     /* avoid hanging if redirect not handled */
1257     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1258         ("Sent RTSP redirect."));
1259     goto done;
1260   }
1261 start_session_failure:
1262   {
1263     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
1264         ("Could not start RTP session manager."));
1265     gst_element_set_state (demux->session, GST_STATE_NULL);
1266     gst_bin_remove (GST_BIN_CAST (demux), demux->session);
1267     demux->session = NULL;
1268     goto done;
1269   }
1270 }
1271 
1272 static gboolean
gst_sdp_demux_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)1273 gst_sdp_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1274 {
1275   GstSDPDemux *demux;
1276   gboolean res = TRUE;
1277 
1278   demux = GST_SDP_DEMUX (parent);
1279 
1280   switch (GST_EVENT_TYPE (event)) {
1281     case GST_EVENT_EOS:
1282       /* when we get EOS, start parsing the SDP */
1283       res = gst_sdp_demux_start (demux);
1284       gst_event_unref (event);
1285       break;
1286     default:
1287       gst_event_unref (event);
1288       break;
1289   }
1290 
1291   return res;
1292 }
1293 
1294 static GstFlowReturn
gst_sdp_demux_sink_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)1295 gst_sdp_demux_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
1296 {
1297   GstSDPDemux *demux;
1298 
1299   demux = GST_SDP_DEMUX (parent);
1300 
1301   /* push the SDP message in an adapter, we start doing something with it when
1302    * we receive EOS */
1303   gst_adapter_push (demux->adapter, buffer);
1304 
1305   return GST_FLOW_OK;
1306 }
1307 
1308 static GstStateChangeReturn
gst_sdp_demux_change_state(GstElement * element,GstStateChange transition)1309 gst_sdp_demux_change_state (GstElement * element, GstStateChange transition)
1310 {
1311   GstSDPDemux *demux;
1312   GstStateChangeReturn ret;
1313 
1314   demux = GST_SDP_DEMUX (element);
1315 
1316   GST_SDP_STREAM_LOCK (demux);
1317 
1318   switch (transition) {
1319     case GST_STATE_CHANGE_NULL_TO_READY:
1320       break;
1321     case GST_STATE_CHANGE_READY_TO_PAUSED:
1322       /* first attempt, don't ignore timeouts */
1323       gst_adapter_clear (demux->adapter);
1324       demux->ignore_timeout = FALSE;
1325       demux->target = GST_STATE_PAUSED;
1326       break;
1327     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1328       demux->target = GST_STATE_PLAYING;
1329       break;
1330     default:
1331       break;
1332   }
1333 
1334   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1335   if (ret == GST_STATE_CHANGE_FAILURE)
1336     goto done;
1337 
1338   switch (transition) {
1339     case GST_STATE_CHANGE_READY_TO_PAUSED:
1340       ret = GST_STATE_CHANGE_NO_PREROLL;
1341       break;
1342     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1343       ret = GST_STATE_CHANGE_NO_PREROLL;
1344       demux->target = GST_STATE_PAUSED;
1345       break;
1346     case GST_STATE_CHANGE_PAUSED_TO_READY:
1347       gst_sdp_demux_cleanup (demux);
1348       break;
1349     case GST_STATE_CHANGE_READY_TO_NULL:
1350       break;
1351     default:
1352       break;
1353   }
1354 
1355 done:
1356   GST_SDP_STREAM_UNLOCK (demux);
1357 
1358   return ret;
1359 }
1360