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