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