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