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