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