Updated to release 13 from tizendev
[platform/core/multimedia/gst-rtsp-server-wfd.git] / src / rtsp-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3
4 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21
22 * * Modifications by Samsung Electronics Co., Ltd.
23
24 * 1. Applied Miracast WFD Server function
25 */
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <netdb.h>
33
34 #include <gst/app/gstappsrc.h>
35 #include <gst/app/gstappsink.h>
36
37 #include "rtsp-funnel.h"
38 #include "rtsp-media.h"
39
40 #define DEFAULT_SHARED         FALSE
41 #define DEFAULT_REUSABLE       FALSE
42 #define DEFAULT_PROTOCOLS      GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
43 //#define DEFAULT_PROTOCOLS      GST_RTSP_LOWER_TRANS_UDP_MCAST
44 #define DEFAULT_EOS_SHUTDOWN   FALSE
45
46 /* define to dump received RTCP packets */
47 #undef DUMP_STATS
48
49 enum
50 {
51   PROP_0,
52   PROP_SHARED,
53   PROP_REUSABLE,
54   PROP_PROTOCOLS,
55   PROP_EOS_SHUTDOWN,
56   PROP_LAST
57 };
58
59 enum
60 {
61   SIGNAL_PREPARED,
62   SIGNAL_UNPREPARED,
63   SIGNAL_NEW_STATE,
64   SIGNAL_LAST
65 };
66
67 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
68 #define GST_CAT_DEFAULT rtsp_media_debug
69
70 static GQuark ssrc_stream_map_key;
71
72 static void gst_rtsp_media_get_property (GObject * object, guint propid,
73     GValue * value, GParamSpec * pspec);
74 static void gst_rtsp_media_set_property (GObject * object, guint propid,
75     const GValue * value, GParamSpec * pspec);
76 static void gst_rtsp_media_finalize (GObject * obj);
77
78 static gpointer do_loop (GstRTSPMediaClass * klass);
79 static gboolean default_handle_message (GstRTSPMedia * media,
80     GstMessage * message);
81 static gboolean default_unprepare (GstRTSPMedia * media);
82 static void unlock_streams (GstRTSPMedia * media);
83
84 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
85
86 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
87
88 static void
89 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
90 {
91   GObjectClass *gobject_class;
92   GError *error = NULL;
93
94   gobject_class = G_OBJECT_CLASS (klass);
95
96   gobject_class->get_property = gst_rtsp_media_get_property;
97   gobject_class->set_property = gst_rtsp_media_set_property;
98   gobject_class->finalize = gst_rtsp_media_finalize;
99
100   g_object_class_install_property (gobject_class, PROP_SHARED,
101       g_param_spec_boolean ("shared", "Shared",
102           "If this media pipeline can be shared", DEFAULT_SHARED,
103           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
104
105   g_object_class_install_property (gobject_class, PROP_REUSABLE,
106       g_param_spec_boolean ("reusable", "Reusable",
107           "If this media pipeline can be reused after an unprepare",
108           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
109
110   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
111       g_param_spec_flags ("protocols", "Protocols",
112           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
113           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
114
115   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
116       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
117           "Send an EOS event to the pipeline before unpreparing",
118           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
119
120   gst_rtsp_media_signals[SIGNAL_PREPARED] =
121       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
122       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
123       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
124
125   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
126       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
127       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
128       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
129
130   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
131       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
132       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
133       g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 0, G_TYPE_INT);
134
135   klass->context = g_main_context_new ();
136   klass->loop = g_main_loop_new (klass->context, TRUE);
137
138   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
139
140   klass->thread = g_thread_create ((GThreadFunc) do_loop, klass, TRUE, &error);
141   if (error != NULL) {
142     g_critical ("could not start bus thread: %s", error->message);
143   }
144   klass->handle_message = default_handle_message;
145   klass->unprepare = default_unprepare;
146
147   ssrc_stream_map_key = g_quark_from_static_string ("GstRTSPServer.stream");
148
149   gst_element_register (NULL, "rtspfunnel", GST_RANK_NONE, RTSP_TYPE_FUNNEL);
150
151 }
152
153 static void
154 gst_rtsp_media_init (GstRTSPMedia * media)
155 {
156   media->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
157   media->lock = g_mutex_new ();
158   media->cond = g_cond_new ();
159
160   media->shared = DEFAULT_SHARED;
161   media->reusable = DEFAULT_REUSABLE;
162   media->protocols = DEFAULT_PROTOCOLS;
163   media->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
164 }
165
166 /* FIXME. this should be done in multiudpsink */
167 typedef struct
168 {
169   gint count;
170   gchar *dest;
171   gint min, max;
172 } RTSPDestination;
173
174 static gint
175 dest_compare (RTSPDestination * a, RTSPDestination * b)
176 {
177   if ((a->min == b->min) && (a->max == b->max)
178       && (strcmp (a->dest, b->dest) == 0))
179     return 0;
180
181   return 1;
182 }
183
184 static RTSPDestination *
185 create_destination (const gchar * dest, gint min, gint max)
186 {
187   RTSPDestination *res;
188
189   res = g_slice_new (RTSPDestination);
190   res->count = 1;
191   res->dest = g_strdup (dest);
192   res->min = min;
193   res->max = max;
194
195   return res;
196 }
197
198 static void
199 free_destination (RTSPDestination * dest)
200 {
201   g_free (dest->dest);
202   g_slice_free (RTSPDestination, dest);
203 }
204
205 void
206 gst_rtsp_media_trans_cleanup (GstRTSPMediaTrans * trans)
207 {
208   if (trans->transport) {
209     gst_rtsp_transport_free (trans->transport);
210     trans->transport = NULL;
211   }
212   if (trans->rtpsource) {
213     g_object_set_qdata (trans->rtpsource, ssrc_stream_map_key, NULL);
214     trans->rtpsource = NULL;
215   }
216 }
217
218 static void
219 gst_rtsp_media_stream_free (GstRTSPMediaStream * stream)
220 {
221   if (stream->session)
222     g_object_unref (stream->session);
223
224   if (stream->caps)
225     gst_caps_unref (stream->caps);
226
227   if (stream->send_rtp_sink)
228     gst_object_unref (stream->send_rtp_sink);
229   if (stream->send_rtp_src)
230     gst_object_unref (stream->send_rtp_src);
231   if (stream->send_rtcp_src)
232     gst_object_unref (stream->send_rtcp_src);
233   if (stream->recv_rtcp_sink)
234     gst_object_unref (stream->recv_rtcp_sink);
235   if (stream->recv_rtp_sink)
236     gst_object_unref (stream->recv_rtp_sink);
237
238   g_list_free (stream->transports);
239
240   g_list_foreach (stream->destinations, (GFunc) free_destination, NULL);
241   g_list_free (stream->destinations);
242
243   g_free (stream);
244 }
245
246 static void
247 gst_rtsp_media_finalize (GObject * obj)
248 {
249   GstRTSPMedia *media;
250   guint i;
251
252   media = GST_RTSP_MEDIA (obj);
253
254   GST_INFO ("finalize media %p", media);
255
256   if (media->pipeline) {
257     unlock_streams (media);
258     gst_element_set_state (media->pipeline, GST_STATE_NULL);
259     gst_object_unref (media->pipeline);
260   }
261
262   for (i = 0; i < media->streams->len; i++) {
263     GstRTSPMediaStream *stream;
264
265     stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
266
267     gst_rtsp_media_stream_free (stream);
268   }
269   g_array_free (media->streams, TRUE);
270
271   g_list_foreach (media->dynamic, (GFunc) gst_object_unref, NULL);
272   g_list_free (media->dynamic);
273
274   if (media->source) {
275     g_source_destroy (media->source);
276     g_source_unref (media->source);
277   }
278   g_mutex_free (media->lock);
279   g_cond_free (media->cond);
280
281   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
282 }
283
284 static void
285 gst_rtsp_media_get_property (GObject * object, guint propid,
286     GValue * value, GParamSpec * pspec)
287 {
288   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
289
290   switch (propid) {
291     case PROP_SHARED:
292       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
293       break;
294     case PROP_REUSABLE:
295       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
296       break;
297     case PROP_PROTOCOLS:
298       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
299       break;
300     case PROP_EOS_SHUTDOWN:
301       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
302       break;
303     default:
304       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
305   }
306 }
307
308 static void
309 gst_rtsp_media_set_property (GObject * object, guint propid,
310     const GValue * value, GParamSpec * pspec)
311 {
312   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
313
314   switch (propid) {
315     case PROP_SHARED:
316       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
317       break;
318     case PROP_REUSABLE:
319       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
320       break;
321     case PROP_PROTOCOLS:
322       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
323       break;
324     case PROP_EOS_SHUTDOWN:
325       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
326       break;
327     default:
328       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
329   }
330 }
331
332 static gpointer
333 do_loop (GstRTSPMediaClass * klass)
334 {
335   GST_INFO ("enter mainloop");
336   g_main_loop_run (klass->loop);
337   GST_INFO ("exit mainloop");
338
339   return NULL;
340 }
341
342 static void
343 collect_media_stats (GstRTSPMedia * media)
344 {
345   GstFormat format;
346   gint64 position, duration;
347
348   media->range.unit = GST_RTSP_RANGE_NPT;
349
350   if (media->is_live) {
351     media->range.min.type = GST_RTSP_TIME_NOW;
352     media->range.min.seconds = -1;
353     media->range.max.type = GST_RTSP_TIME_END;
354     media->range.max.seconds = -1;
355   } else {
356     /* get the position */
357     format = GST_FORMAT_TIME;
358     if (!gst_element_query_position (media->pipeline, format, &position)) {
359       GST_INFO ("position query failed");
360       position = 0;
361     }
362
363     /* get the duration */
364     format = GST_FORMAT_TIME;
365     if (!gst_element_query_duration (media->pipeline, format, &duration)) {
366       GST_INFO ("duration query failed");
367       duration = -1;
368     }
369
370     GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
371         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
372
373     if (position == -1) {
374       media->range.min.type = GST_RTSP_TIME_NOW;
375       media->range.min.seconds = -1;
376     } else {
377       media->range.min.type = GST_RTSP_TIME_SECONDS;
378       media->range.min.seconds = ((gdouble) position) / GST_SECOND;
379     }
380     if (duration == -1) {
381       media->range.max.type = GST_RTSP_TIME_END;
382       media->range.max.seconds = -1;
383     } else {
384       media->range.max.type = GST_RTSP_TIME_SECONDS;
385       media->range.max.seconds = ((gdouble) duration) / GST_SECOND;
386     }
387   }
388 }
389
390 /**
391  * gst_rtsp_media_new:
392  *
393  * Create a new #GstRTSPMedia instance. The #GstRTSPMedia object contains the
394  * element to produde RTP data for one or more related (audio/video/..)
395  * streams.
396  *
397  * Returns: a new #GstRTSPMedia object.
398  */
399 GstRTSPMedia *
400 gst_rtsp_media_new (void)
401 {
402   GstRTSPMedia *result;
403
404   result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
405
406   return result;
407 }
408
409 /**
410  * gst_rtsp_media_set_shared:
411  * @media: a #GstRTSPMedia
412  * @shared: the new value
413  *
414  * Set or unset if the pipeline for @media can be shared will multiple clients.
415  * When @shared is %TRUE, client requests for this media will share the media
416  * pipeline.
417  */
418 void
419 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
420 {
421   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
422
423   media->shared = shared;
424 }
425
426 /**
427  * gst_rtsp_media_is_shared:
428  * @media: a #GstRTSPMedia
429  *
430  * Check if the pipeline for @media can be shared between multiple clients.
431  *
432  * Returns: %TRUE if the media can be shared between clients.
433  */
434 gboolean
435 gst_rtsp_media_is_shared (GstRTSPMedia * media)
436 {
437   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
438
439   return media->shared;
440 }
441
442 /**
443  * gst_rtsp_media_set_reusable:
444  * @media: a #GstRTSPMedia
445  * @reusable: the new value
446  *
447  * Set or unset if the pipeline for @media can be reused after the pipeline has
448  * been unprepared.
449  */
450 void
451 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
452 {
453   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
454
455   media->reusable = reusable;
456 }
457
458 /**
459  * gst_rtsp_media_is_reusable:
460  * @media: a #GstRTSPMedia
461  *
462  * Check if the pipeline for @media can be reused after an unprepare.
463  *
464  * Returns: %TRUE if the media can be reused
465  */
466 gboolean
467 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
468 {
469   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
470
471   return media->reusable;
472 }
473
474 /**
475  * gst_rtsp_media_set_protocols:
476  * @media: a #GstRTSPMedia
477  * @protocols: the new flags
478  *
479  * Configure the allowed lower transport for @media.
480  */
481 void
482 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
483 {
484   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
485
486   media->protocols = protocols;
487 }
488
489 /**
490  * gst_rtsp_media_get_protocols:
491  * @media: a #GstRTSPMedia
492  *
493  * Get the allowed protocols of @media.
494  *
495  * Returns: a #GstRTSPLowerTrans
496  */
497 GstRTSPLowerTrans
498 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
499 {
500   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
501       GST_RTSP_LOWER_TRANS_UNKNOWN);
502
503   return media->protocols;
504 }
505
506 /**
507  * gst_rtsp_media_set_eos_shutdown:
508  * @media: a #GstRTSPMedia
509  * @eos_shutdown: the new value
510  *
511  * Set or unset if an EOS event will be sent to the pipeline for @media before
512  * it is unprepared.
513  */
514 void
515 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
516 {
517   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
518
519   media->eos_shutdown = eos_shutdown;
520 }
521
522 /**
523  * gst_rtsp_media_is_eos_shutdown:
524  * @media: a #GstRTSPMedia
525  *
526  * Check if the pipeline for @media will send an EOS down the pipeline before
527  * unpreparing.
528  *
529  * Returns: %TRUE if the media will send EOS before unpreparing.
530  */
531 gboolean
532 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
533 {
534   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
535
536   return media->eos_shutdown;
537 }
538
539 /**
540  * gst_rtsp_media_set_auth:
541  * @media: a #GstRTSPMedia
542  * @auth: a #GstRTSPAuth
543  *
544  * configure @auth to be used as the authentication manager of @media.
545  */
546 void
547 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
548 {
549   GstRTSPAuth *old;
550
551   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
552
553   old = media->auth;
554
555   if (old != auth) {
556     if (auth)
557       g_object_ref (auth);
558     media->auth = auth;
559     if (old)
560       g_object_unref (old);
561   }
562 }
563
564 /**
565  * gst_rtsp_media_get_auth:
566  * @media: a #GstRTSPMedia
567  *
568  * Get the #GstRTSPAuth used as the authentication manager of @media.
569  *
570  * Returns: the #GstRTSPAuth of @media. g_object_unref() after
571  * usage.
572  */
573 GstRTSPAuth *
574 gst_rtsp_media_get_auth (GstRTSPMedia * media)
575 {
576   GstRTSPAuth *result;
577
578   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
579
580   if ((result = media->auth))
581     g_object_ref (result);
582
583   return result;
584 }
585
586
587 /**
588  * gst_rtsp_media_n_streams:
589  * @media: a #GstRTSPMedia
590  *
591  * Get the number of streams in this media.
592  *
593  * Returns: The number of streams.
594  */
595 guint
596 gst_rtsp_media_n_streams (GstRTSPMedia * media)
597 {
598   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
599
600   return media->streams->len;
601 }
602
603 /**
604  * gst_rtsp_media_get_stream:
605  * @media: a #GstRTSPMedia
606  * @idx: the stream index
607  *
608  * Retrieve the stream with index @idx from @media.
609  *
610  * Returns: the #GstRTSPMediaStream at index @idx or %NULL when a stream with
611  * that index did not exist.
612  */
613 GstRTSPMediaStream *
614 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
615 {
616   GstRTSPMediaStream *res;
617
618   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
619
620   if (idx < media->streams->len)
621     res = g_array_index (media->streams, GstRTSPMediaStream *, idx);
622   else
623     res = NULL;
624
625   return res;
626 }
627
628 /**
629  * gst_rtsp_media_get_range_string:
630  * @media: a #GstRTSPMedia
631  * @play: for the PLAY request
632  *
633  * Get the current range as a string.
634  *
635  * Returns: The range as a string, g_free() after usage.
636  */
637 gchar *
638 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
639 {
640   gchar *result;
641   GstRTSPTimeRange range;
642
643   /* make copy */
644   range = media->range;
645
646   if (!play && media->active > 0) {
647     range.min.type = GST_RTSP_TIME_NOW;
648     range.min.seconds = -1;
649   }
650
651   result = gst_rtsp_range_to_string (&range);
652
653   return result;
654 }
655
656 /**
657  * gst_rtsp_media_seek:
658  * @media: a #GstRTSPMedia
659  * @range: a #GstRTSPTimeRange
660  *
661  * Seek the pipeline to @range.
662  *
663  * Returns: %TRUE on success.
664  */
665 gboolean
666 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
667 {
668   GstSeekFlags flags;
669   gboolean res;
670   gint64 start, stop;
671   GstSeekType start_type, stop_type;
672
673   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
674   g_return_val_if_fail (range != NULL, FALSE);
675
676   if (range->unit != GST_RTSP_RANGE_NPT)
677     goto not_supported;
678
679   /* depends on the current playing state of the pipeline. We might need to
680    * queue this until we get EOS. */
681   flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
682
683   start_type = stop_type = GST_SEEK_TYPE_NONE;
684
685   switch (range->min.type) {
686     case GST_RTSP_TIME_NOW:
687       start = -1;
688       break;
689     case GST_RTSP_TIME_SECONDS:
690       /* only seek when something changed */
691       if (media->range.min.seconds == range->min.seconds) {
692         start = -1;
693       } else {
694         start = range->min.seconds * GST_SECOND;
695         start_type = GST_SEEK_TYPE_SET;
696       }
697       break;
698     case GST_RTSP_TIME_END:
699     default:
700       goto weird_type;
701   }
702   switch (range->max.type) {
703     case GST_RTSP_TIME_SECONDS:
704       /* only seek when something changed */
705       if (media->range.max.seconds == range->max.seconds) {
706         stop = -1;
707       } else {
708         stop = range->max.seconds * GST_SECOND;
709         stop_type = GST_SEEK_TYPE_SET;
710       }
711       break;
712     case GST_RTSP_TIME_END:
713       stop = -1;
714       stop_type = GST_SEEK_TYPE_SET;
715       break;
716     case GST_RTSP_TIME_NOW:
717     default:
718       goto weird_type;
719   }
720
721   if (start != -1 || stop != -1) {
722     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
723         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
724
725     res = gst_element_seek (media->pipeline, 1.0, GST_FORMAT_TIME,
726         flags, start_type, start, stop_type, stop);
727
728     /* and block for the seek to complete */
729     GST_INFO ("done seeking %d", res);
730     gst_element_get_state (media->pipeline, NULL, NULL, -1);
731     GST_INFO ("prerolled again");
732
733     collect_media_stats (media);
734   } else {
735     GST_INFO ("no seek needed");
736     res = TRUE;
737   }
738
739   return res;
740
741   /* ERRORS */
742 not_supported:
743   {
744     GST_WARNING ("seek unit %d not supported", range->unit);
745     return FALSE;
746   }
747 weird_type:
748   {
749     GST_WARNING ("weird range type %d not supported", range->min.type);
750     return FALSE;
751   }
752 }
753
754 /**
755  * gst_rtsp_media_stream_rtp:
756  * @stream: a #GstRTSPMediaStream
757  * @buffer: a #GstBuffer
758  *
759  * Handle an RTP buffer for the stream. This method is usually called when a
760  * message has been received from a client using the TCP transport.
761  *
762  * This function takes ownership of @buffer.
763  *
764  * Returns: a GstFlowReturn.
765  */
766 GstFlowReturn
767 gst_rtsp_media_stream_rtp (GstRTSPMediaStream * stream, GstBuffer * buffer)
768 {
769   GstFlowReturn ret;
770
771   ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (stream->appsrc[0]), buffer);
772
773   return ret;
774 }
775
776 /**
777  * gst_rtsp_media_stream_rtcp:
778  * @stream: a #GstRTSPMediaStream
779  * @buffer: a #GstBuffer
780  *
781  * Handle an RTCP buffer for the stream. This method is usually called when a
782  * message has been received from a client using the TCP transport.
783  *
784  * This function takes ownership of @buffer.
785  *
786  * Returns: a GstFlowReturn.
787  */
788 GstFlowReturn
789 gst_rtsp_media_stream_rtcp (GstRTSPMediaStream * stream, GstBuffer * buffer)
790 {
791   GstFlowReturn ret;
792
793   ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (stream->appsrc[1]), buffer);
794
795   return ret;
796 }
797
798 /* Allocate the udp ports and sockets */
799 static gboolean
800 alloc_udp_ports (GstRTSPMedia * media, GstRTSPMediaStream * stream)
801 {
802   GstStateChangeReturn ret;
803   GstElement *udpsrc0, *udpsrc1;
804   GstElement *udpsink0, *udpsink1;
805   gint tmp_rtp, tmp_rtcp;
806   guint count;
807   gint rtpport, rtcpport, sockfd;
808   const gchar *host;
809
810   udpsrc0 = NULL;
811   udpsrc1 = NULL;
812   udpsink0 = NULL;
813   udpsink1 = NULL;
814   count = 0;
815
816   /* Start with random port */
817 #if 0 //Changes for testing with dongle
818   tmp_rtp = 0;
819 #else
820   tmp_rtp = 19000;
821 #endif
822   if (media->is_ipv6)
823     host = "udp://[::0]";
824   else
825     host = "udp://0.0.0.0";
826
827   /* try to allocate 2 UDP ports, the RTP port should be an even
828    * number and the RTCP port should be the next (uneven) port */
829 again:
830   udpsrc0 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
831   if (udpsrc0 == NULL)
832     goto no_udp_protocol;
833   g_object_set (G_OBJECT (udpsrc0), "port", tmp_rtp, NULL);
834
835   ret = gst_element_set_state (udpsrc0, GST_STATE_PAUSED);
836   if (ret == GST_STATE_CHANGE_FAILURE) {
837     if (tmp_rtp != 0) {
838       tmp_rtp += 2;
839       if (++count > 20)
840         goto no_ports;
841
842       gst_element_set_state (udpsrc0, GST_STATE_NULL);
843       gst_object_unref (udpsrc0);
844
845       goto again;
846     }
847     goto no_udp_protocol;
848   }
849
850   g_object_get (G_OBJECT (udpsrc0), "port", &tmp_rtp, NULL);
851 #if 0 //Changes for testing with dongle
852   /* check if port is even */
853   if ((tmp_rtp & 1) != 0) {
854     /* port not even, close and allocate another */
855     if (++count > 20)
856       goto no_ports;
857
858     gst_element_set_state (udpsrc0, GST_STATE_NULL);
859     gst_object_unref (udpsrc0);
860
861     tmp_rtp++;
862     goto again;
863   }
864 #endif
865   /* allocate port+1 for RTCP now */
866   udpsrc1 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
867   if (udpsrc1 == NULL)
868     goto no_udp_rtcp_protocol;
869
870   /* set port */
871   tmp_rtcp = tmp_rtp + 1;
872   g_object_set (G_OBJECT (udpsrc1), "port", tmp_rtcp, NULL);
873
874   ret = gst_element_set_state (udpsrc1, GST_STATE_PAUSED);
875   /* tmp_rtcp port is busy already : retry to make rtp/rtcp pair */
876   if (ret == GST_STATE_CHANGE_FAILURE) {
877
878     if (++count > 20)
879       goto no_ports;
880
881     gst_element_set_state (udpsrc0, GST_STATE_NULL);
882     gst_object_unref (udpsrc0);
883
884     gst_element_set_state (udpsrc1, GST_STATE_NULL);
885     gst_object_unref (udpsrc1);
886
887     tmp_rtp += 2;
888     goto again;
889   }
890
891   /* all fine, do port check */
892   g_object_get (G_OBJECT (udpsrc0), "port", &rtpport, NULL);
893   g_object_get (G_OBJECT (udpsrc1), "port", &rtcpport, NULL);
894
895   /* this should not happen... */
896   if (rtpport != tmp_rtp || rtcpport != tmp_rtcp)
897     goto port_error;
898
899   udpsink0 = gst_element_factory_make ("multiudpsink", NULL);
900   if (!udpsink0)
901     goto no_udp_protocol;
902
903   g_object_get (G_OBJECT (udpsrc0), "sock", &sockfd, NULL);
904   g_object_set (G_OBJECT (udpsink0), "sockfd", sockfd, NULL);
905   g_object_set (G_OBJECT (udpsink0), "closefd", FALSE, NULL);
906
907   udpsink1 = gst_element_factory_make ("multiudpsink", NULL);
908   if (!udpsink1)
909     goto no_udp_protocol;
910
911   if (g_object_class_find_property (G_OBJECT_GET_CLASS (udpsink0),
912           "send-duplicates")) {
913     g_object_set (G_OBJECT (udpsink0), "send-duplicates", FALSE, NULL);
914     g_object_set (G_OBJECT (udpsink1), "send-duplicates", FALSE, NULL);
915     stream->filter_duplicates = FALSE;
916   } else {
917     GST_WARNING ("multiudpsink version found without send-duplicates property");
918     stream->filter_duplicates = TRUE;
919   }
920
921   if (g_object_class_find_property (G_OBJECT_GET_CLASS (udpsink0),
922           "buffer-size")) {
923     //g_object_set (G_OBJECT (udpsink0), "buffer-size", 0x80000, NULL);
924     g_object_set (G_OBJECT (udpsink0), "buffer-size", 200, NULL);
925   } else {
926     GST_WARNING ("multiudpsink version found without buffer-size property");
927   }
928
929   g_object_get (G_OBJECT (udpsrc1), "sock", &sockfd, NULL);
930   g_object_set (G_OBJECT (udpsink1), "sockfd", sockfd, NULL);
931   g_object_set (G_OBJECT (udpsink1), "closefd", FALSE, NULL);
932   g_object_set (G_OBJECT (udpsink1), "sync", FALSE, NULL);
933   g_object_set (G_OBJECT (udpsink1), "async", FALSE, NULL);
934
935   g_print ("\n\n\n\tsetting sync to false\n\n\n");
936   g_object_set (G_OBJECT (udpsink0), "sync", FALSE, NULL);
937
938
939   g_object_set (G_OBJECT (udpsink0), "auto-multicast", FALSE, NULL);
940   g_object_set (G_OBJECT (udpsink0), "loop", FALSE, NULL);
941   g_object_set (G_OBJECT (udpsink1), "auto-multicast", FALSE, NULL);
942   g_object_set (G_OBJECT (udpsink1), "loop", FALSE, NULL);
943
944   /* we keep these elements, we configure all in configure_transport when the
945    * server told us to really use the UDP ports. */
946   stream->udpsrc[0] = udpsrc0;
947   stream->udpsrc[1] = udpsrc1;
948   stream->udpsink[0] = udpsink0;
949   stream->udpsink[1] = udpsink1;
950   stream->server_port.min = rtpport;
951 #if 1 //Changes for testing with dongle
952   stream->server_port.max = rtcpport;
953 #else
954   stream->server_port.max = -1;
955 #endif
956   return TRUE;
957
958   /* ERRORS */
959 no_udp_protocol:
960   {
961     goto cleanup;
962   }
963 no_ports:
964   {
965     goto cleanup;
966   }
967 no_udp_rtcp_protocol:
968   {
969     goto cleanup;
970   }
971 port_error:
972   {
973     goto cleanup;
974   }
975 cleanup:
976   {
977     if (udpsrc0) {
978       gst_element_set_state (udpsrc0, GST_STATE_NULL);
979       gst_object_unref (udpsrc0);
980     }
981     if (udpsrc1) {
982       gst_element_set_state (udpsrc1, GST_STATE_NULL);
983       gst_object_unref (udpsrc1);
984     }
985     if (udpsink0) {
986       gst_element_set_state (udpsink0, GST_STATE_NULL);
987       gst_object_unref (udpsink0);
988     }
989     if (udpsink1) {
990       gst_element_set_state (udpsink1, GST_STATE_NULL);
991       gst_object_unref (udpsink1);
992     }
993     return FALSE;
994   }
995 }
996
997 /* executed from streaming thread */
998 static void
999 caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream)
1000 {
1001   gchar *capsstr;
1002   GstCaps *newcaps, *oldcaps;
1003
1004   if ((newcaps = gst_pad_get_current_caps (pad)))
1005     gst_caps_ref (newcaps);
1006
1007   oldcaps = stream->caps;
1008   stream->caps = newcaps;
1009
1010   if (oldcaps)
1011     gst_caps_unref (oldcaps);
1012
1013   capsstr = gst_caps_to_string (newcaps);
1014   GST_INFO ("stream %p received caps %p, %s", stream, newcaps, capsstr);
1015   g_free (capsstr);
1016 }
1017
1018 static void
1019 dump_structure (const GstStructure * s)
1020 {
1021   gchar *sstr;
1022
1023   sstr = gst_structure_to_string (s);
1024   GST_INFO ("structure: %s", sstr);
1025   g_free (sstr);
1026 }
1027
1028 static GstRTSPMediaTrans *
1029 find_transport (GstRTSPMediaStream * stream, const gchar * rtcp_from)
1030 {
1031   GList *walk;
1032   GstRTSPMediaTrans *result = NULL;
1033   const gchar *tmp;
1034   gchar *dest;
1035   guint port;
1036
1037   if (rtcp_from == NULL)
1038     return NULL;
1039
1040   tmp = g_strrstr (rtcp_from, ":");
1041   if (tmp == NULL)
1042     return NULL;
1043
1044   port = atoi (tmp + 1);
1045   dest = g_strndup (rtcp_from, tmp - rtcp_from);
1046
1047   GST_INFO ("finding %s:%d", dest, port);
1048
1049   for (walk = stream->transports; walk; walk = g_list_next (walk)) {
1050     GstRTSPMediaTrans *trans = walk->data;
1051     gint min, max;
1052
1053     min = trans->transport->client_port.min;
1054     max = trans->transport->client_port.max;
1055
1056     if ((strcmp (trans->transport->destination, dest) == 0) && (min == port
1057             || max == port)) {
1058       result = trans;
1059       break;
1060     }
1061   }
1062   g_free (dest);
1063
1064   return result;
1065 }
1066
1067 static void
1068 on_new_ssrc (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1069 {
1070   GstStructure *stats;
1071   GstRTSPMediaTrans *trans;
1072
1073   GST_INFO ("%p: new source %p", stream, source);
1074
1075   /* see if we have a stream to match with the origin of the RTCP packet */
1076   trans = g_object_get_qdata (source, ssrc_stream_map_key);
1077   if (trans == NULL) {
1078     g_object_get (source, "stats", &stats, NULL);
1079     if (stats) {
1080       const gchar *rtcp_from;
1081
1082       dump_structure (stats);
1083
1084       rtcp_from = gst_structure_get_string (stats, "rtcp-from");
1085       if ((trans = find_transport (stream, rtcp_from))) {
1086         GST_INFO ("%p: found transport %p for source  %p", stream, trans,
1087             source);
1088
1089         /* keep ref to the source */
1090         trans->rtpsource = source;
1091
1092         g_object_set_qdata (source, ssrc_stream_map_key, trans);
1093       }
1094       gst_structure_free (stats);
1095     }
1096   } else {
1097     GST_INFO ("%p: source %p for transport %p", stream, source, trans);
1098   }
1099 }
1100
1101 static void
1102 on_ssrc_sdes (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1103 {
1104   GST_INFO ("%p: new SDES %p", stream, source);
1105 }
1106
1107 static void
1108 on_ssrc_active (GObject * session, GObject * source,
1109     GstRTSPMediaStream * stream)
1110 {
1111   GstRTSPMediaTrans *trans;
1112
1113   trans = g_object_get_qdata (source, ssrc_stream_map_key);
1114
1115   GST_INFO ("%p: source %p in transport %p is active", stream, source, trans);
1116
1117   if (trans && trans->keep_alive)
1118     trans->keep_alive (trans->ka_user_data);
1119
1120 #ifdef DUMP_STATS
1121   {
1122     GstStructure *stats;
1123     g_object_get (source, "stats", &stats, NULL);
1124     if (stats) {
1125       dump_structure (stats);
1126       gst_structure_free (stats);
1127     }
1128   }
1129 #endif
1130 }
1131
1132 static void
1133 on_bye_ssrc (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1134 {
1135   GST_INFO ("%p: source %p bye", stream, source);
1136 }
1137
1138 static void
1139 on_bye_timeout (GObject * session, GObject * source,
1140     GstRTSPMediaStream * stream)
1141 {
1142   GstRTSPMediaTrans *trans;
1143
1144   GST_INFO ("%p: source %p bye timeout", stream, source);
1145
1146   if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
1147     trans->rtpsource = NULL;
1148     trans->timeout = TRUE;
1149   }
1150 }
1151
1152 static void
1153 on_timeout (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1154 {
1155   GstRTSPMediaTrans *trans;
1156
1157   GST_INFO ("%p: source %p timeout", stream, source);
1158
1159   if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
1160     trans->rtpsource = NULL;
1161     trans->timeout = TRUE;
1162   }
1163 }
1164
1165 static GstFlowReturn
1166 handle_new_sample (GstAppSink * sink, gpointer user_data)
1167 {
1168   GList *walk;
1169   GstSample *sample;
1170   GstBuffer *buffer;
1171   GstRTSPMediaStream *stream;
1172
1173   sample = gst_app_sink_pull_sample(sink);
1174   if (!sample)
1175     return GST_FLOW_OK;
1176
1177   buffer = gst_sample_get_buffer(sample);
1178   if(!buffer)
1179   {
1180       gst_sample_unref(sample);
1181       return GST_FLOW_OK;
1182   }
1183
1184   stream = (GstRTSPMediaStream *) user_data;
1185
1186   for (walk = stream->transports; walk; walk = g_list_next (walk)) {
1187     GstRTSPMediaTrans *tr = (GstRTSPMediaTrans *) walk->data;
1188
1189     if (GST_ELEMENT_CAST (sink) == stream->appsink[0]) { 
1190       if (tr->send_rtp) {
1191         tr->send_rtp (buffer, tr->transport->port.min, tr->user_data);
1192       }
1193     } else {
1194       if (tr->send_rtcp)
1195       tr->send_rtcp (buffer, tr->transport->port.max, tr->user_data);
1196     }
1197   }
1198   gst_buffer_unref (buffer);
1199   gst_sample_unref (sample);
1200
1201   return GST_FLOW_OK;
1202 }
1203
1204 static GstAppSinkCallbacks sink_cb = {
1205   NULL,                         /* not interested in EOS */
1206   NULL,                         /* not interested in preroll buffers */
1207   handle_new_sample,
1208 };
1209
1210 /* prepare the pipeline objects to handle @stream in @media */
1211 static gboolean
1212 setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media)
1213 {
1214   gchar *name;
1215   GstPad *pad, *teepad, *selpad;
1216   GstPadLinkReturn ret;
1217   gint i;
1218
1219   /* allocate udp ports, we will have 4 of them, 2 for receiving RTP/RTCP and 2
1220    * for sending RTP/RTCP. The sender and receiver ports are shared between the
1221    * elements */
1222   if (!alloc_udp_ports (media, stream))
1223     return FALSE;
1224
1225   /* add the ports to the pipeline */
1226   for (i = 0; i < 2; i++) {
1227     gst_bin_add (GST_BIN_CAST (media->pipeline), stream->udpsink[i]);
1228     gst_bin_add (GST_BIN_CAST (media->pipeline), stream->udpsrc[i]);
1229   }
1230
1231   /* create elements for the TCP transfer */
1232   for (i = 0; i < 2; i++) {
1233     stream->appsrc[i] = gst_element_factory_make ("appsrc", NULL);
1234     stream->appsink[i] = gst_element_factory_make ("appsink", NULL);
1235     g_object_set (stream->appsink[i], "async", FALSE, "sync", FALSE, NULL);
1236     g_object_set (stream->appsink[i], "emit-signals", FALSE, NULL);
1237     gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsink[i]);
1238     gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsrc[i]);
1239     gst_app_sink_set_callbacks (GST_APP_SINK_CAST (stream->appsink[i]),
1240         &sink_cb, stream, NULL);
1241   }
1242
1243   /* hook up the stream to the RTP session elements. */
1244   name = g_strdup_printf ("send_rtp_sink_%d", idx);
1245   stream->send_rtp_sink = gst_element_get_request_pad (media->rtpbin, name);
1246   g_free (name);
1247   name = g_strdup_printf ("send_rtp_src_%d", idx);
1248   stream->send_rtp_src = gst_element_get_static_pad (media->rtpbin, name);
1249   g_free (name);
1250   name = g_strdup_printf ("send_rtcp_src_%d", idx);
1251   stream->send_rtcp_src = gst_element_get_request_pad (media->rtpbin, name);
1252   g_free (name);
1253   name = g_strdup_printf ("recv_rtcp_sink_%d", idx);
1254   stream->recv_rtcp_sink = gst_element_get_request_pad (media->rtpbin, name);
1255   g_free (name);
1256   name = g_strdup_printf ("recv_rtp_sink_%d", idx);
1257   stream->recv_rtp_sink = gst_element_get_request_pad (media->rtpbin, name);
1258   g_free (name);
1259
1260   /* get the session */
1261   g_signal_emit_by_name (media->rtpbin, "get-internal-session", idx,
1262       &stream->session);
1263
1264   g_signal_connect (stream->session, "on-new-ssrc", (GCallback) on_new_ssrc,
1265       stream);
1266   g_signal_connect (stream->session, "on-ssrc-sdes", (GCallback) on_ssrc_sdes,
1267       stream);
1268   g_signal_connect (stream->session, "on-ssrc-active",
1269       (GCallback) on_ssrc_active, stream);
1270   g_signal_connect (stream->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
1271       stream);
1272   g_signal_connect (stream->session, "on-bye-timeout",
1273       (GCallback) on_bye_timeout, stream);
1274   g_signal_connect (stream->session, "on-timeout", (GCallback) on_timeout,
1275       stream);
1276
1277   /* link the RTP pad to the session manager */
1278   ret = gst_pad_link (stream->srcpad, stream->send_rtp_sink);
1279   if (ret != GST_PAD_LINK_OK)
1280     goto link_failed;
1281
1282   /* make tee for RTP and link to stream */
1283   stream->tee[0] = gst_element_factory_make ("tee", NULL);
1284   gst_bin_add (GST_BIN_CAST (media->pipeline), stream->tee[0]);
1285
1286   pad = gst_element_get_static_pad (stream->tee[0], "sink");
1287   gst_pad_link (stream->send_rtp_src, pad);
1288   gst_object_unref (pad);
1289
1290   /* link RTP sink, we're pretty sure this will work. */
1291   teepad = gst_element_get_request_pad (stream->tee[0], "src%d");
1292   pad = gst_element_get_static_pad (stream->udpsink[0], "sink");
1293   gst_pad_link (teepad, pad);
1294   gst_object_unref (pad);
1295   gst_object_unref (teepad);
1296
1297   teepad = gst_element_get_request_pad (stream->tee[0], "src%d");
1298   pad = gst_element_get_static_pad (stream->appsink[0], "sink");
1299   gst_pad_link (teepad, pad);
1300   gst_object_unref (pad);
1301   gst_object_unref (teepad);
1302
1303   /* make tee for RTCP */
1304   stream->tee[1] = gst_element_factory_make ("tee", NULL);
1305   gst_bin_add (GST_BIN_CAST (media->pipeline), stream->tee[1]);
1306
1307   pad = gst_element_get_static_pad (stream->tee[1], "sink");
1308   gst_pad_link (stream->send_rtcp_src, pad);
1309   gst_object_unref (pad);
1310
1311   /* link RTCP elements */
1312   teepad = gst_element_get_request_pad (stream->tee[1], "src%d");
1313   pad = gst_element_get_static_pad (stream->udpsink[1], "sink");
1314   gst_pad_link (teepad, pad);
1315   gst_object_unref (pad);
1316   gst_object_unref (teepad);
1317
1318   teepad = gst_element_get_request_pad (stream->tee[1], "src%d");
1319   pad = gst_element_get_static_pad (stream->appsink[1], "sink");
1320   gst_pad_link (teepad, pad);
1321   gst_object_unref (pad);
1322   gst_object_unref (teepad);
1323
1324   /* make selector for the RTP receivers */
1325   stream->selector[0] = gst_element_factory_make ("rtspfunnel", NULL);
1326   gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[0]);
1327
1328   pad = gst_element_get_static_pad (stream->selector[0], "src");
1329   gst_pad_link (pad, stream->recv_rtp_sink);
1330   gst_object_unref (pad);
1331
1332   selpad = gst_element_get_request_pad (stream->selector[0], "sink%d");
1333   pad = gst_element_get_static_pad (stream->udpsrc[0], "src");
1334   gst_pad_link (pad, selpad);
1335   gst_object_unref (pad);
1336   gst_object_unref (selpad);
1337
1338   selpad = gst_element_get_request_pad (stream->selector[0], "sink%d");
1339   pad = gst_element_get_static_pad (stream->appsrc[0], "src");
1340   gst_pad_link (pad, selpad);
1341   gst_object_unref (pad);
1342   gst_object_unref (selpad);
1343
1344   /* make selector for the RTCP receivers */
1345   stream->selector[1] = gst_element_factory_make ("rtspfunnel", NULL);
1346   gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[1]);
1347
1348   pad = gst_element_get_static_pad (stream->selector[1], "src");
1349   gst_pad_link (pad, stream->recv_rtcp_sink);
1350   gst_object_unref (pad);
1351
1352   selpad = gst_element_get_request_pad (stream->selector[1], "sink%d");
1353   pad = gst_element_get_static_pad (stream->udpsrc[1], "src");
1354   gst_pad_link (pad, selpad);
1355   gst_object_unref (pad);
1356   gst_object_unref (selpad);
1357
1358   selpad = gst_element_get_request_pad (stream->selector[1], "sink%d");
1359   pad = gst_element_get_static_pad (stream->appsrc[1], "src");
1360   gst_pad_link (pad, selpad);
1361   gst_object_unref (pad);
1362   gst_object_unref (selpad);
1363
1364   /* we set and keep these to playing so that they don't cause NO_PREROLL return
1365    * values */
1366   gst_element_set_state (stream->udpsrc[0], GST_STATE_PLAYING);
1367   gst_element_set_state (stream->udpsrc[1], GST_STATE_PLAYING);
1368   gst_element_set_locked_state (stream->udpsrc[0], TRUE);
1369   gst_element_set_locked_state (stream->udpsrc[1], TRUE);
1370
1371   /* be notified of caps changes */
1372   stream->caps_sig = g_signal_connect (stream->send_rtp_sink, "notify::caps",
1373       (GCallback) caps_notify, stream);
1374
1375   stream->prepared = TRUE;
1376
1377   return TRUE;
1378
1379   /* ERRORS */
1380 link_failed:
1381   {
1382     GST_WARNING ("failed to link stream %d", idx);
1383     return FALSE;
1384   }
1385 }
1386
1387 static void
1388 unlock_streams (GstRTSPMedia * media)
1389 {
1390   guint i, n_streams;
1391
1392   /* unlock the udp src elements */
1393   n_streams = gst_rtsp_media_n_streams (media);
1394   for (i = 0; i < n_streams; i++) {
1395     GstRTSPMediaStream *stream;
1396
1397     stream = gst_rtsp_media_get_stream (media, i);
1398
1399     gst_element_set_locked_state (stream->udpsrc[0], FALSE);
1400     gst_element_set_locked_state (stream->udpsrc[1], FALSE);
1401   }
1402 }
1403
1404 static void
1405 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1406 {
1407   g_mutex_lock (media->lock);
1408   /* never overwrite the error status */
1409   if (media->status != GST_RTSP_MEDIA_STATUS_ERROR)
1410     media->status = status;
1411   GST_DEBUG ("setting new status to %d", status);
1412   g_cond_broadcast (media->cond);
1413   g_mutex_unlock (media->lock);
1414 }
1415
1416 static GstRTSPMediaStatus
1417 gst_rtsp_media_get_status (GstRTSPMedia * media)
1418 {
1419   GstRTSPMediaStatus result;
1420   GTimeVal timeout;
1421
1422   g_mutex_lock (media->lock);
1423   g_get_current_time (&timeout);
1424   g_time_val_add (&timeout, 20 * G_USEC_PER_SEC);
1425   /* while we are preparing, wait */
1426   while (media->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1427     GST_DEBUG ("waiting for status change");
1428     if (!g_cond_timed_wait (media->cond, media->lock, &timeout)) {
1429       GST_DEBUG ("timeout, assuming error status");
1430       media->status = GST_RTSP_MEDIA_STATUS_ERROR;
1431     }
1432   }
1433   /* could be success or error */
1434   result = media->status;
1435   GST_DEBUG ("got status %d", result);
1436   g_mutex_unlock (media->lock);
1437
1438   return result;
1439 }
1440
1441 static gboolean
1442 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1443 {
1444   GstMessageType type;
1445
1446   type = GST_MESSAGE_TYPE (message);
1447
1448   switch (type) {
1449     case GST_MESSAGE_STATE_CHANGED:
1450       break;
1451     case GST_MESSAGE_BUFFERING:
1452     {
1453       gint percent;
1454
1455       gst_message_parse_buffering (message, &percent);
1456
1457       /* no state management needed for live pipelines */
1458       if (media->is_live)
1459         break;
1460
1461       if (percent == 100) {
1462         /* a 100% message means buffering is done */
1463         media->buffering = FALSE;
1464         /* if the desired state is playing, go back */
1465         if (media->target_state == GST_STATE_PLAYING) {
1466           GST_INFO ("Buffering done, setting pipeline to PLAYING");
1467           gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1468         } else {
1469           GST_INFO ("Buffering done");
1470         }
1471       } else {
1472         /* buffering busy */
1473         if (media->buffering == FALSE) {
1474           if (media->target_state == GST_STATE_PLAYING) {
1475             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
1476             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1477             gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
1478           } else {
1479             GST_INFO ("Buffering ...");
1480           }
1481         }
1482         media->buffering = TRUE;
1483       }
1484       break;
1485     }
1486     case GST_MESSAGE_LATENCY:
1487     {
1488       gst_bin_recalculate_latency (GST_BIN_CAST (media->pipeline));
1489       break;
1490     }
1491     case GST_MESSAGE_ERROR:
1492     {
1493       GError *gerror;
1494       gchar *debug;
1495
1496       //g_print ("\n\n\n\n\n++++++++++++++++Generating dot file ++++++++++++++\n\n\n\n");
1497
1498       GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN_CAST(media->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "wfd-error");
1499
1500       gst_message_parse_error (message, &gerror, &debug);
1501
1502       GST_ERROR ("%p: got error %s (%s)", media, gerror->message, debug);
1503       g_error_free (gerror);
1504       g_free (debug);
1505
1506       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1507       break;
1508     }
1509     case GST_MESSAGE_WARNING:
1510     {
1511       GError *gerror;
1512       gchar *debug;
1513
1514       gst_message_parse_warning (message, &gerror, &debug);
1515       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1516       g_error_free (gerror);
1517       g_free (debug);
1518       break;
1519     }
1520     case GST_MESSAGE_ELEMENT:
1521       break;
1522     case GST_MESSAGE_STREAM_STATUS:
1523       break;
1524     case GST_MESSAGE_ASYNC_DONE:
1525       if (!media->adding) {
1526         /* when we are dynamically adding pads, the addition of the udpsrc will
1527          * temporarily produce ASYNC_DONE messages. We have to ignore them and
1528          * wait for the final ASYNC_DONE after everything prerolled */
1529         GST_INFO ("%p: got ASYNC_DONE", media);
1530         collect_media_stats (media);
1531         //GST_INFO ("Setting again to PAUSED state....");
1532         //gst_element_set_state (media->pipeline, GST_STATE_PAUSED); // commented on 29/06/12 to test resume
1533         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1534       } else {
1535         GST_INFO ("%p: ignoring ASYNC_DONE", media);
1536       }
1537       break;
1538     case GST_MESSAGE_EOS:
1539       GST_INFO ("%p: got EOS", media);
1540       if (media->eos_pending) {
1541         GST_DEBUG ("shutting down after EOS");
1542         gst_element_set_state (media->pipeline, GST_STATE_NULL);
1543         media->eos_pending = FALSE;
1544         g_object_unref (media);
1545       }
1546       break;
1547     default:
1548       GST_INFO ("%p: got message type %s", media,
1549           gst_message_type_get_name (type));
1550       break;
1551   }
1552   return TRUE;
1553 }
1554
1555 static gboolean
1556 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1557 {
1558   GstRTSPMediaClass *klass;
1559   gboolean ret;
1560
1561   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1562
1563   if (klass->handle_message)
1564     ret = klass->handle_message (media, message);
1565   else
1566     ret = FALSE;
1567
1568   return ret;
1569 }
1570
1571 /* called from streaming threads */
1572 static void
1573 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1574 {
1575   GstRTSPMediaStream *stream;
1576   gchar *name;
1577   gint i;
1578
1579   i = media->streams->len + 1;
1580
1581   GST_INFO ("pad added %s:%s, stream %d", GST_DEBUG_PAD_NAME (pad), i);
1582
1583   stream = g_new0 (GstRTSPMediaStream, 1);
1584   stream->payloader = element;
1585
1586   name = g_strdup_printf ("dynpay%d", i);
1587
1588   media->adding = TRUE;
1589
1590   /* ghost the pad of the payloader to the element */
1591   stream->srcpad = gst_ghost_pad_new (name, pad);
1592   gst_pad_set_active (stream->srcpad, TRUE);
1593   gst_element_add_pad (media->element, stream->srcpad);
1594   g_free (name);
1595
1596   /* add stream now */
1597   g_array_append_val (media->streams, stream);
1598
1599   setup_stream (stream, i, media);
1600
1601   for (i = 0; i < 2; i++) {
1602     gst_element_set_state (stream->udpsink[i], GST_STATE_PAUSED);
1603     gst_element_set_state (stream->appsink[i], GST_STATE_PAUSED);
1604     gst_element_set_state (stream->tee[i], GST_STATE_PAUSED);
1605     gst_element_set_state (stream->selector[i], GST_STATE_PAUSED);
1606     gst_element_set_state (stream->appsrc[i], GST_STATE_PAUSED);
1607   }
1608   media->adding = FALSE;
1609 }
1610
1611 static void
1612 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1613 {
1614   GST_INFO ("no more pads");
1615   if (media->fakesink) {
1616     gst_object_ref (media->fakesink);
1617     gst_bin_remove (GST_BIN (media->pipeline), media->fakesink);
1618     gst_element_set_state (media->fakesink, GST_STATE_NULL);
1619     gst_object_unref (media->fakesink);
1620     media->fakesink = NULL;
1621     GST_INFO ("removed fakesink");
1622   }
1623 }
1624
1625 /**
1626  * gst_rtsp_media_prepare:
1627  * @media: a #GstRTSPMedia
1628  *
1629  * Prepare @media for streaming. This function will create the pipeline and
1630  * other objects to manage the streaming.
1631  *
1632  * It will preroll the pipeline and collect vital information about the streams
1633  * such as the duration.
1634  *
1635  * Returns: %TRUE on success.
1636  */
1637 gboolean
1638 gst_rtsp_media_prepare (GstRTSPMedia * media)
1639 {
1640   GstStateChangeReturn ret;
1641   GstRTSPMediaStatus status;
1642   guint i, n_streams;
1643   GstRTSPMediaClass *klass;
1644   GstBus *bus;
1645   GList *walk;
1646
1647   if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1648     goto was_prepared;
1649
1650   if (!media->reusable && media->reused)
1651     goto is_reused;
1652
1653   GST_INFO ("preparing media %p", media);
1654
1655   /* reset some variables */
1656   media->is_live = FALSE;
1657   media->buffering = FALSE;
1658   /* we're preparing now */
1659   media->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1660
1661   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (media->pipeline));
1662
1663   /* add the pipeline bus to our custom mainloop */
1664   media->source = gst_bus_create_watch (bus);
1665   gst_object_unref (bus);
1666
1667   g_source_set_callback (media->source, (GSourceFunc) bus_message, media, NULL);
1668
1669   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1670   media->id = g_source_attach (media->source, klass->context);
1671
1672   media->rtpbin = gst_element_factory_make ("gstrtpbin", NULL);
1673   g_object_set (media->rtpbin, "latency", 0, NULL);
1674
1675   g_print ("\n\nset latency to zero for rtpbin\n\n\n");
1676
1677   /* add stuff to the bin */
1678   gst_bin_add (GST_BIN (media->pipeline), media->rtpbin);
1679
1680   /* link streams we already have, other streams might appear when we have
1681    * dynamic elements */
1682   n_streams = gst_rtsp_media_n_streams (media);
1683   for (i = 0; i < n_streams; i++) {
1684     GstRTSPMediaStream *stream;
1685
1686     stream = gst_rtsp_media_get_stream (media, i);
1687
1688     setup_stream (stream, i, media);
1689   }
1690
1691   for (walk = media->dynamic; walk; walk = g_list_next (walk)) {
1692     GstElement *elem = walk->data;
1693
1694     GST_INFO ("adding callbacks for dynamic element %p", elem);
1695
1696     g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1697     g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1698
1699     /* we add a fakesink here in order to make the state change async. We remove
1700      * the fakesink again in the no-more-pads callback. */
1701     media->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1702     gst_bin_add (GST_BIN (media->pipeline), media->fakesink);
1703   }
1704
1705   GST_INFO ("setting pipeline to PAUSED for media %p", media);
1706   /* first go to PAUSED */
1707   ret = gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
1708   media->target_state = GST_STATE_PAUSED;
1709
1710   switch (ret) {
1711     case GST_STATE_CHANGE_SUCCESS:
1712       GST_INFO ("SUCCESS state change for media %p", media);
1713       break;
1714     case GST_STATE_CHANGE_ASYNC:
1715       GST_INFO ("ASYNC state change for media %p", media);
1716       break;
1717     case GST_STATE_CHANGE_NO_PREROLL:
1718       /* we need to go to PLAYING */
1719       GST_INFO ("NO_PREROLL state change: live media %p", media);
1720       media->is_live = TRUE;
1721       ret = gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1722       if (ret == GST_STATE_CHANGE_FAILURE)
1723         goto state_failed;
1724       break;
1725     case GST_STATE_CHANGE_FAILURE:
1726       goto state_failed;
1727   }
1728
1729   /* now wait for all pads to be prerolled */
1730   //GST_DEBUG_BIN_TO_DOT_FILE(media->pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "test-server-arch");
1731   
1732   status = gst_rtsp_media_get_status (media);
1733   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1734     goto state_failed;
1735
1736   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1737
1738   GST_INFO ("object %p is prerolled", media);
1739
1740   return TRUE;
1741
1742   /* OK */
1743 was_prepared:
1744   {
1745     return TRUE;
1746   }
1747   /* ERRORS */
1748 is_reused:
1749   {
1750     GST_WARNING ("can not reuse media %p", media);
1751     return FALSE;
1752   }
1753 state_failed:
1754   {
1755     GST_WARNING ("failed to preroll pipeline");
1756     unlock_streams (media);
1757     gst_element_set_state (media->pipeline, GST_STATE_NULL);
1758     gst_rtsp_media_unprepare (media);
1759     return FALSE;
1760   }
1761 }
1762
1763 /**
1764  * gst_rtsp_media_unprepare:
1765  * @media: a #GstRTSPMedia
1766  *
1767  * Unprepare @media. After this call, the media should be prepared again before
1768  * it can be used again. If the media is set to be non-reusable, a new instance
1769  * must be created.
1770  *
1771  * Returns: %TRUE on success.
1772  */
1773 gboolean
1774 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1775 {
1776   GstRTSPMediaClass *klass;
1777   gboolean success;
1778
1779   if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1780     return TRUE;
1781
1782   GST_INFO ("unprepare media %p", media);
1783   media->target_state = GST_STATE_NULL;
1784
1785   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1786   if (klass->unprepare)
1787     success = klass->unprepare (media);
1788   else
1789     success = TRUE;
1790
1791   media->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1792   media->reused = TRUE;
1793
1794   /* when the media is not reusable, this will effectively unref the media and
1795    * recreate it */
1796   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1797
1798   return success;
1799 }
1800
1801 static gboolean
1802 default_unprepare (GstRTSPMedia * media)
1803 {
1804   if (media->eos_shutdown) {
1805     GST_DEBUG ("sending EOS for shutdown");
1806     /* ref so that we don't disappear */
1807     g_object_ref (media);
1808     media->eos_pending = TRUE;
1809     gst_element_send_event (media->pipeline, gst_event_new_eos ());
1810     /* we need to go to playing again for the EOS to propagate, normally in this
1811      * state, nothing is receiving data from us anymore so this is ok. */
1812     gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1813   } else {
1814     GST_DEBUG ("shutting down");
1815     gst_element_set_state (media->pipeline, GST_STATE_NULL);
1816   }
1817   return TRUE;
1818 }
1819
1820 static void
1821 add_udp_destination (GstRTSPMedia * media, GstRTSPMediaStream * stream,
1822     gchar * dest, gint min, gint max)
1823 {
1824   gboolean do_add = TRUE;
1825   RTSPDestination *ndest;
1826
1827   if (stream->filter_duplicates) {
1828     RTSPDestination fdest;
1829     GList *find;
1830
1831     fdest.dest = dest;
1832     fdest.min = min;
1833     fdest.max = max;
1834
1835     /* first see if we already added this destination */
1836     find =
1837         g_list_find_custom (stream->destinations, &fdest,
1838         (GCompareFunc) dest_compare);
1839     if (find) {
1840       ndest = (RTSPDestination *) find->data;
1841
1842       GST_INFO ("already streaming to %s:%d-%d with %d clients", dest, min, max,
1843           ndest->count);
1844       ndest->count++;
1845       do_add = FALSE;
1846     }
1847   }
1848
1849   if (do_add) {
1850     GST_INFO ("adding %s:%d-%d", dest, min, max);
1851     g_signal_emit_by_name (stream->udpsink[0], "add", dest, min, NULL);
1852     g_signal_emit_by_name (stream->udpsink[1], "add", dest, max, NULL);
1853
1854     if (stream->filter_duplicates) {
1855       ndest = create_destination (dest, min, max);
1856       stream->destinations = g_list_prepend (stream->destinations, ndest);
1857     }
1858   }
1859 }
1860
1861 static void
1862 remove_udp_destination (GstRTSPMedia * media, GstRTSPMediaStream * stream,
1863     gchar * dest, gint min, gint max)
1864 {
1865   gboolean do_remove = TRUE;
1866   RTSPDestination *ndest = NULL;
1867   GList *find = NULL;
1868
1869   if (stream->filter_duplicates) {
1870     RTSPDestination fdest;
1871
1872     fdest.dest = dest;
1873     fdest.min = min;
1874     fdest.max = max;
1875
1876     /* first see if we already added this destination */
1877     find =
1878         g_list_find_custom (stream->destinations, &fdest,
1879         (GCompareFunc) dest_compare);
1880     if (!find)
1881       return;
1882
1883     ndest = (RTSPDestination *) find->data;
1884     if (--ndest->count > 0) {
1885       do_remove = FALSE;
1886       GST_INFO ("still streaming to %s:%d-%d with %d clients", dest, min, max,
1887           ndest->count);
1888     }
1889   }
1890
1891   if (do_remove) {
1892     GST_INFO ("removing %s:%d-%d", dest, min, max);
1893     g_signal_emit_by_name (stream->udpsink[0], "remove", dest, min, NULL);
1894     g_signal_emit_by_name (stream->udpsink[1], "remove", dest, max, NULL);
1895
1896     if (stream->filter_duplicates) {
1897       stream->destinations = g_list_delete_link (stream->destinations, find);
1898       if(ndest)
1899         free_destination (ndest);
1900     }
1901   }
1902 }
1903
1904 /**
1905  * gst_rtsp_media_set_state:
1906  * @media: a #GstRTSPMedia
1907  * @state: the target state of the media
1908  * @transports: a #GArray of #GstRTSPMediaTrans pointers
1909  *
1910  * Set the state of @media to @state and for the transports in @transports.
1911  *
1912  * Returns: %TRUE on success.
1913  */
1914 gboolean
1915 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1916     GArray * transports)
1917 {
1918   gint i;
1919   GstStateChangeReturn ret;
1920   gboolean add, remove, do_state;
1921   gint old_active;
1922
1923   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1924   g_return_val_if_fail (transports != NULL, FALSE);
1925
1926   /* NULL and READY are the same */
1927   if (state == GST_STATE_READY)
1928     state = GST_STATE_NULL;
1929
1930   add = remove = FALSE;
1931
1932   GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1933       media);
1934
1935   switch (state) {
1936     case GST_STATE_NULL:
1937       /* unlock the streams so that they follow the state changes from now on */
1938       unlock_streams (media);
1939       /* fallthrough */
1940     case GST_STATE_PAUSED:
1941       /* we're going from PLAYING to PAUSED, READY or NULL, remove */
1942       if (media->target_state == GST_STATE_PLAYING)
1943         remove = TRUE;
1944       break;
1945     case GST_STATE_PLAYING:
1946       /* we're going to PLAYING, add */
1947       add = TRUE;
1948       break;
1949     default:
1950       break;
1951   }
1952   old_active = media->active;
1953
1954   for (i = 0; i < transports->len; i++) {
1955     GstRTSPMediaTrans *tr;
1956     GstRTSPMediaStream *stream;
1957     GstRTSPTransport *trans;
1958
1959     /* we need a non-NULL entry in the array */
1960     tr = g_array_index (transports, GstRTSPMediaTrans *, i);
1961     if (tr == NULL)
1962       continue;
1963
1964     /* we need a transport */
1965     if (!(trans = tr->transport))
1966       continue;
1967
1968     /* get the stream and add the destinations */
1969     stream = gst_rtsp_media_get_stream (media, tr->idx);
1970     switch (trans->lower_transport) {
1971       case GST_RTSP_LOWER_TRANS_UDP:
1972       case GST_RTSP_LOWER_TRANS_UDP_MCAST:
1973       {
1974         gchar *dest;
1975         gint min, max;
1976
1977         dest = trans->destination;
1978         if (trans->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
1979           min = trans->port.min;
1980           max = trans->port.max;
1981         } else {
1982           min = trans->client_port.min;
1983           max = trans->client_port.max;
1984         }
1985
1986         if (add && !tr->active) {
1987           add_udp_destination (media, stream, dest, min, max);
1988           stream->transports = g_list_prepend (stream->transports, tr);
1989           tr->active = TRUE;
1990           media->active++;
1991         } else if (remove && tr->active) {
1992           remove_udp_destination (media, stream, dest, min, max);
1993           stream->transports = g_list_remove (stream->transports, tr);
1994           tr->active = FALSE;
1995           media->active--;
1996         }
1997         break;
1998       }
1999       case GST_RTSP_LOWER_TRANS_TCP:
2000         if (add && !tr->active) {
2001           GST_INFO ("adding TCP %s", trans->destination);
2002           stream->transports = g_list_prepend (stream->transports, tr);
2003           tr->active = TRUE;
2004           media->active++;
2005         } else if (remove && tr->active) {
2006           GST_INFO ("removing TCP %s", trans->destination);
2007           stream->transports = g_list_remove (stream->transports, tr);
2008           tr->active = FALSE;
2009           media->active--;
2010         }
2011         break;
2012       default:
2013         GST_INFO ("Unknown transport %d", trans->lower_transport);
2014         break;
2015     }
2016   }
2017
2018   /* we just added the first media, do the playing state change */
2019   if (old_active == 0 && add)
2020     do_state = TRUE;
2021   /* if we have no more active media, do the downward state changes */
2022   else if (media->active == 0)
2023     do_state = TRUE;
2024   else
2025     do_state = FALSE;
2026
2027   GST_INFO ("state %d active %d media %p do_state %d", state, media->active,
2028       media, do_state);
2029
2030   if (media->target_state != state) {
2031     if (do_state) {
2032       if (state == GST_STATE_NULL) {
2033         gst_rtsp_media_unprepare (media);
2034       } else {
2035         GST_INFO ("state %s media %p", gst_element_state_get_name (state),
2036             media);
2037         media->target_state = state;
2038         ret = gst_element_set_state (media->pipeline, state);
2039       }
2040     }
2041     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
2042         NULL);
2043   }
2044
2045   /* remember where we are */
2046   if (state == GST_STATE_PAUSED || old_active != media->active)
2047     collect_media_stats (media);
2048
2049   return TRUE;
2050 }
2051
2052 /**
2053  * gst_rtsp_media_remove_elements:
2054  * @media: a #GstRTSPMedia
2055  *
2056  * Remove all elements and the pipeline controlled by @media.
2057  */
2058 void
2059 gst_rtsp_media_remove_elements (GstRTSPMedia * media)
2060 {
2061   gint i, j;
2062
2063   unlock_streams (media);
2064
2065   for (i = 0; i < media->streams->len; i++) {
2066     GstRTSPMediaStream *stream;
2067
2068     GST_INFO ("Removing elements of stream %d from pipeline", i);
2069
2070     stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
2071
2072     gst_pad_unlink (stream->srcpad, stream->send_rtp_sink);
2073
2074     g_signal_handler_disconnect (stream->send_rtp_sink, stream->caps_sig);
2075
2076     for (j = 0; j < 2; j++) {
2077       gst_element_set_state (stream->udpsrc[j], GST_STATE_NULL);
2078       gst_element_set_state (stream->udpsink[j], GST_STATE_NULL);
2079       gst_element_set_state (stream->appsrc[j], GST_STATE_NULL);
2080       gst_element_set_state (stream->appsink[j], GST_STATE_NULL);
2081       gst_element_set_state (stream->tee[j], GST_STATE_NULL);
2082       gst_element_set_state (stream->selector[j], GST_STATE_NULL);
2083
2084       gst_bin_remove (GST_BIN (media->pipeline), stream->udpsrc[j]);
2085       gst_bin_remove (GST_BIN (media->pipeline), stream->udpsink[j]);
2086       gst_bin_remove (GST_BIN (media->pipeline), stream->appsrc[j]);
2087       gst_bin_remove (GST_BIN (media->pipeline), stream->appsink[j]);
2088       gst_bin_remove (GST_BIN (media->pipeline), stream->tee[j]);
2089       gst_bin_remove (GST_BIN (media->pipeline), stream->selector[j]);
2090     }
2091     if (stream->caps)
2092       gst_caps_unref (stream->caps);
2093     stream->caps = NULL;
2094     gst_rtsp_media_stream_free (stream);
2095   }
2096   g_array_remove_range (media->streams, 0, media->streams->len);
2097
2098   gst_element_set_state (media->rtpbin, GST_STATE_NULL);
2099   gst_bin_remove (GST_BIN (media->pipeline), media->rtpbin);
2100
2101   gst_object_unref (media->pipeline);
2102   media->pipeline = NULL;
2103 }