Revert "rtsp-server: support build against last stable release"
[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  * SECTION:rtsp-media
21  * @short_description: The media pipeline
22  * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession,
23  *     #GstRTSPSessionMedia
24  *
25  * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the
26  * streaming to the clients. The actual data transfer is done by the
27  * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia.
28  *
29  * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the
30  * client does a DESCRIBE or SETUP of a resource.
31  *
32  * A media is created with gst_rtsp_media_new() that takes the element that will
33  * provide the streaming elements. For each of the streams, a new #GstRTSPStream
34  * object needs to be made with the gst_rtsp_media_create_stream() which takes
35  * the payloader element and the source pad that produces the RTP stream.
36  *
37  * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The
38  * prepare method will add rtpbin and sinks and sources to send and receive RTP
39  * and RTCP packets from the clients. Each stream srcpad is connected to an
40  * input into the internal rtpbin.
41  *
42  * It is also possible to dynamically create #GstRTSPStream objects during the
43  * prepare phase. With gst_rtsp_media_get_status() you can check the status of
44  * the prepare phase.
45  *
46  * After the media is prepared, it is ready for streaming. It will usually be
47  * managed in a session with gst_rtsp_session_manage_media(). See
48  * #GstRTSPSession and #GstRTSPSessionMedia.
49  *
50  * The state of the media can be controlled with gst_rtsp_media_set_state ().
51  * Seeking can be done with gst_rtsp_media_seek().
52  *
53  * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
54  * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
55  * cleanly shut down.
56  *
57  * With gst_rtsp_media_set_shared(), the media can be shared between multiple
58  * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
59  * can be prepared again after an unprepare.
60  *
61  * Last reviewed on 2013-07-11 (1.0.0)
62  */
63
64 #include <string.h>
65 #include <stdlib.h>
66
67 #include <gst/app/gstappsrc.h>
68 #include <gst/app/gstappsink.h>
69
70 #include "rtsp-media.h"
71
72 #define GST_RTSP_MEDIA_GET_PRIVATE(obj)  \
73      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
74
75 struct _GstRTSPMediaPrivate
76 {
77   GMutex lock;
78   GCond cond;
79
80   /* protected by lock */
81   GstRTSPPermissions *permissions;
82   gboolean shared;
83   gboolean suspend_mode;
84   gboolean reusable;
85   GstRTSPProfile profiles;
86   GstRTSPLowerTrans protocols;
87   gboolean reused;
88   gboolean eos_shutdown;
89   guint buffer_size;
90   GstRTSPAddressPool *pool;
91   gboolean blocked;
92
93   GstElement *element;
94   GRecMutex state_lock;         /* locking order: state lock, lock */
95   GPtrArray *streams;           /* protected by lock */
96   GList *dynamic;               /* protected by lock */
97   GstRTSPMediaStatus status;    /* protected by lock */
98   gint prepare_count;
99   gint n_active;
100   gboolean adding;
101
102   /* the pipeline for the media */
103   GstElement *pipeline;
104   GstElement *fakesink;         /* protected by lock */
105   GSource *source;
106   guint id;
107   GstRTSPThread *thread;
108
109   gboolean time_provider;
110   GstNetTimeProvider *nettime;
111
112   gboolean is_live;
113   gboolean seekable;
114   gboolean buffering;
115   GstState target_state;
116
117   /* RTP session manager */
118   GstElement *rtpbin;
119
120   /* the range of media */
121   GstRTSPTimeRange range;       /* protected by lock */
122   GstClockTime range_start;
123   GstClockTime range_stop;
124 };
125
126 #define DEFAULT_SHARED          FALSE
127 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
128 #define DEFAULT_REUSABLE        FALSE
129 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
130 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
131                                         GST_RTSP_LOWER_TRANS_TCP
132 #define DEFAULT_EOS_SHUTDOWN    FALSE
133 #define DEFAULT_BUFFER_SIZE     0x80000
134 #define DEFAULT_TIME_PROVIDER   FALSE
135
136 /* define to dump received RTCP packets */
137 #undef DUMP_STATS
138
139 enum
140 {
141   PROP_0,
142   PROP_SHARED,
143   PROP_SUSPEND_MODE,
144   PROP_REUSABLE,
145   PROP_PROFILES,
146   PROP_PROTOCOLS,
147   PROP_EOS_SHUTDOWN,
148   PROP_BUFFER_SIZE,
149   PROP_ELEMENT,
150   PROP_TIME_PROVIDER,
151   PROP_LAST
152 };
153
154 enum
155 {
156   SIGNAL_NEW_STREAM,
157   SIGNAL_REMOVED_STREAM,
158   SIGNAL_PREPARED,
159   SIGNAL_UNPREPARED,
160   SIGNAL_TARGET_STATE,
161   SIGNAL_NEW_STATE,
162   SIGNAL_LAST
163 };
164
165 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
166 #define GST_CAT_DEFAULT rtsp_media_debug
167
168 static void gst_rtsp_media_get_property (GObject * object, guint propid,
169     GValue * value, GParamSpec * pspec);
170 static void gst_rtsp_media_set_property (GObject * object, guint propid,
171     const GValue * value, GParamSpec * pspec);
172 static void gst_rtsp_media_finalize (GObject * obj);
173
174 static gboolean default_handle_message (GstRTSPMedia * media,
175     GstMessage * message);
176 static void finish_unprepare (GstRTSPMedia * media);
177 static gboolean default_unprepare (GstRTSPMedia * media);
178 static gboolean default_convert_range (GstRTSPMedia * media,
179     GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
180 static gboolean default_query_position (GstRTSPMedia * media,
181     gint64 * position);
182 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
183 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
184 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
185     GstSDPInfo * info);
186
187 static gboolean wait_preroll (GstRTSPMedia * media);
188
189 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
190
191 #define C_ENUM(v) ((gint) v)
192
193 #define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type())
194 GType
195 gst_rtsp_suspend_mode_get_type (void)
196 {
197   static gsize id = 0;
198   static const GEnumValue values[] = {
199     {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
200     {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
201         "pause"},
202     {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
203         "reset"},
204     {0, NULL, NULL}
205   };
206
207   if (g_once_init_enter (&id)) {
208     GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
209     g_once_init_leave (&id, tmp);
210   }
211   return (GType) id;
212 }
213
214 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
215
216 static void
217 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
218 {
219   GObjectClass *gobject_class;
220
221   g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
222
223   gobject_class = G_OBJECT_CLASS (klass);
224
225   gobject_class->get_property = gst_rtsp_media_get_property;
226   gobject_class->set_property = gst_rtsp_media_set_property;
227   gobject_class->finalize = gst_rtsp_media_finalize;
228
229   g_object_class_install_property (gobject_class, PROP_SHARED,
230       g_param_spec_boolean ("shared", "Shared",
231           "If this media pipeline can be shared", DEFAULT_SHARED,
232           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233
234   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
235       g_param_spec_enum ("suspend-mode", "Suspend Mode",
236           "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
237           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
238
239   g_object_class_install_property (gobject_class, PROP_REUSABLE,
240       g_param_spec_boolean ("reusable", "Reusable",
241           "If this media pipeline can be reused after an unprepare",
242           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
243
244   g_object_class_install_property (gobject_class, PROP_PROFILES,
245       g_param_spec_flags ("profiles", "Profiles",
246           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
247           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
248
249   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
250       g_param_spec_flags ("protocols", "Protocols",
251           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
252           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
253
254   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
255       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
256           "Send an EOS event to the pipeline before unpreparing",
257           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
258
259   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
260       g_param_spec_uint ("buffer-size", "Buffer Size",
261           "The kernel UDP buffer size to use", 0, G_MAXUINT,
262           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
263
264   g_object_class_install_property (gobject_class, PROP_ELEMENT,
265       g_param_spec_object ("element", "The Element",
266           "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
267           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
268
269   g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
270       g_param_spec_boolean ("time-provider", "Time Provider",
271           "Use a NetTimeProvider for clients",
272           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
273
274   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
275       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
276       G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
277       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
278
279   gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
280       g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
281       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
282       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
283       GST_TYPE_RTSP_STREAM);
284
285   gst_rtsp_media_signals[SIGNAL_PREPARED] =
286       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
287       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
288       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
289
290   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
291       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
292       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
293       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
294
295   gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
296       g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
297       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL,
298       NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
299
300   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
301       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
302       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
303       g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
304
305   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
306
307   klass->handle_message = default_handle_message;
308   klass->unprepare = default_unprepare;
309   klass->convert_range = default_convert_range;
310   klass->query_position = default_query_position;
311   klass->query_stop = default_query_stop;
312   klass->create_rtpbin = default_create_rtpbin;
313   klass->setup_sdp = default_setup_sdp;
314 }
315
316 static void
317 gst_rtsp_media_init (GstRTSPMedia * media)
318 {
319   GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
320
321   media->priv = priv;
322
323   priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
324   g_mutex_init (&priv->lock);
325   g_cond_init (&priv->cond);
326   g_rec_mutex_init (&priv->state_lock);
327
328   priv->shared = DEFAULT_SHARED;
329   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
330   priv->reusable = DEFAULT_REUSABLE;
331   priv->profiles = DEFAULT_PROFILES;
332   priv->protocols = DEFAULT_PROTOCOLS;
333   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
334   priv->buffer_size = DEFAULT_BUFFER_SIZE;
335   priv->time_provider = DEFAULT_TIME_PROVIDER;
336 }
337
338 static void
339 gst_rtsp_media_finalize (GObject * obj)
340 {
341   GstRTSPMediaPrivate *priv;
342   GstRTSPMedia *media;
343
344   media = GST_RTSP_MEDIA (obj);
345   priv = media->priv;
346
347   GST_INFO ("finalize media %p", media);
348
349   if (priv->permissions)
350     gst_rtsp_permissions_unref (priv->permissions);
351
352   g_ptr_array_unref (priv->streams);
353
354   g_list_free_full (priv->dynamic, gst_object_unref);
355
356   if (priv->pipeline)
357     gst_object_unref (priv->pipeline);
358   if (priv->nettime)
359     gst_object_unref (priv->nettime);
360   gst_object_unref (priv->element);
361   if (priv->pool)
362     g_object_unref (priv->pool);
363   g_mutex_clear (&priv->lock);
364   g_cond_clear (&priv->cond);
365   g_rec_mutex_clear (&priv->state_lock);
366
367   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
368 }
369
370 static void
371 gst_rtsp_media_get_property (GObject * object, guint propid,
372     GValue * value, GParamSpec * pspec)
373 {
374   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
375
376   switch (propid) {
377     case PROP_ELEMENT:
378       g_value_set_object (value, media->priv->element);
379       break;
380     case PROP_SHARED:
381       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
382       break;
383     case PROP_SUSPEND_MODE:
384       g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
385       break;
386     case PROP_REUSABLE:
387       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
388       break;
389     case PROP_PROFILES:
390       g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
391       break;
392     case PROP_PROTOCOLS:
393       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
394       break;
395     case PROP_EOS_SHUTDOWN:
396       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
397       break;
398     case PROP_BUFFER_SIZE:
399       g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
400       break;
401     case PROP_TIME_PROVIDER:
402       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
403       break;
404     default:
405       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
406   }
407 }
408
409 static void
410 gst_rtsp_media_set_property (GObject * object, guint propid,
411     const GValue * value, GParamSpec * pspec)
412 {
413   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
414
415   switch (propid) {
416     case PROP_ELEMENT:
417       media->priv->element = g_value_get_object (value);
418       gst_object_ref_sink (media->priv->element);
419       break;
420     case PROP_SHARED:
421       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
422       break;
423     case PROP_SUSPEND_MODE:
424       gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
425       break;
426     case PROP_REUSABLE:
427       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
428       break;
429     case PROP_PROFILES:
430       gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
431       break;
432     case PROP_PROTOCOLS:
433       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
434       break;
435     case PROP_EOS_SHUTDOWN:
436       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
437       break;
438     case PROP_BUFFER_SIZE:
439       gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
440       break;
441     case PROP_TIME_PROVIDER:
442       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
443       break;
444     default:
445       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
446   }
447 }
448
449 static gboolean
450 default_query_position (GstRTSPMedia * media, gint64 * position)
451 {
452   return gst_element_query_position (media->priv->pipeline, GST_FORMAT_TIME,
453       position);
454 }
455
456 static gboolean
457 default_query_stop (GstRTSPMedia * media, gint64 * stop)
458 {
459   GstQuery *query;
460   gboolean res;
461
462   query = gst_query_new_segment (GST_FORMAT_TIME);
463   if ((res = gst_element_query (media->priv->pipeline, query))) {
464     GstFormat format;
465     gst_query_parse_segment (query, NULL, &format, NULL, stop);
466     if (format != GST_FORMAT_TIME)
467       *stop = -1;
468   }
469   gst_query_unref (query);
470   return res;
471 }
472
473 static GstElement *
474 default_create_rtpbin (GstRTSPMedia * media)
475 {
476   GstElement *rtpbin;
477
478   rtpbin = gst_element_factory_make ("rtpbin", NULL);
479
480   return rtpbin;
481 }
482
483 /* must be called with state lock */
484 static void
485 collect_media_stats (GstRTSPMedia * media)
486 {
487   GstRTSPMediaPrivate *priv = media->priv;
488   gint64 position, stop;
489
490   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
491       priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
492     return;
493
494   priv->range.unit = GST_RTSP_RANGE_NPT;
495
496   GST_INFO ("collect media stats");
497
498   if (priv->is_live) {
499     priv->range.min.type = GST_RTSP_TIME_NOW;
500     priv->range.min.seconds = -1;
501     priv->range_start = -1;
502     priv->range.max.type = GST_RTSP_TIME_END;
503     priv->range.max.seconds = -1;
504     priv->range_stop = -1;
505   } else {
506     GstRTSPMediaClass *klass;
507     gboolean ret;
508
509     klass = GST_RTSP_MEDIA_GET_CLASS (media);
510
511     /* get the position */
512     ret = FALSE;
513     if (klass->query_position)
514       ret = klass->query_position (media, &position);
515
516     if (!ret) {
517       GST_INFO ("position query failed");
518       position = 0;
519     }
520
521     /* get the current segment stop */
522     ret = FALSE;
523     if (klass->query_stop)
524       ret = klass->query_stop (media, &stop);
525
526     if (!ret) {
527       GST_INFO ("stop query failed");
528       stop = -1;
529     }
530
531     GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
532         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
533
534     if (position == -1) {
535       priv->range.min.type = GST_RTSP_TIME_NOW;
536       priv->range.min.seconds = -1;
537       priv->range_start = -1;
538     } else {
539       priv->range.min.type = GST_RTSP_TIME_SECONDS;
540       priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
541       priv->range_start = position;
542     }
543     if (stop == -1) {
544       priv->range.max.type = GST_RTSP_TIME_END;
545       priv->range.max.seconds = -1;
546       priv->range_stop = -1;
547     } else {
548       priv->range.max.type = GST_RTSP_TIME_SECONDS;
549       priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
550       priv->range_stop = stop;
551     }
552   }
553 }
554
555 /**
556  * gst_rtsp_media_new:
557  * @element: (transfer full): a #GstElement
558  *
559  * Create a new #GstRTSPMedia instance. @element is the bin element that
560  * provides the different streams. The #GstRTSPMedia object contains the
561  * element to produce RTP data for one or more related (audio/video/..)
562  * streams.
563  *
564  * Ownership is taken of @element.
565  *
566  * Returns: a new #GstRTSPMedia object.
567  */
568 GstRTSPMedia *
569 gst_rtsp_media_new (GstElement * element)
570 {
571   GstRTSPMedia *result;
572
573   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
574
575   result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
576
577   return result;
578 }
579
580 /**
581  * gst_rtsp_media_get_element:
582  * @media: a #GstRTSPMedia
583  *
584  * Get the element that was used when constructing @media.
585  *
586  * Returns: (transfer full): a #GstElement. Unref after usage.
587  */
588 GstElement *
589 gst_rtsp_media_get_element (GstRTSPMedia * media)
590 {
591   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
592
593   return gst_object_ref (media->priv->element);
594 }
595
596 /**
597  * gst_rtsp_media_take_pipeline:
598  * @media: a #GstRTSPMedia
599  * @pipeline: (transfer full): a #GstPipeline
600  *
601  * Set @pipeline as the #GstPipeline for @media. Ownership is
602  * taken of @pipeline.
603  */
604 void
605 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
606 {
607   GstRTSPMediaPrivate *priv;
608   GstElement *old;
609   GstNetTimeProvider *nettime;
610
611   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
612   g_return_if_fail (GST_IS_PIPELINE (pipeline));
613
614   priv = media->priv;
615
616   g_mutex_lock (&priv->lock);
617   old = priv->pipeline;
618   priv->pipeline = GST_ELEMENT_CAST (pipeline);
619   nettime = priv->nettime;
620   priv->nettime = NULL;
621   g_mutex_unlock (&priv->lock);
622
623   if (old)
624     gst_object_unref (old);
625
626   if (nettime)
627     gst_object_unref (nettime);
628
629   gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
630 }
631
632 /**
633  * gst_rtsp_media_set_permissions:
634  * @media: a #GstRTSPMedia
635  * @permissions: a #GstRTSPPermissions
636  *
637  * Set @permissions on @media.
638  */
639 void
640 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
641     GstRTSPPermissions * permissions)
642 {
643   GstRTSPMediaPrivate *priv;
644
645   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
646
647   priv = media->priv;
648
649   g_mutex_lock (&priv->lock);
650   if (priv->permissions)
651     gst_rtsp_permissions_unref (priv->permissions);
652   if ((priv->permissions = permissions))
653     gst_rtsp_permissions_ref (permissions);
654   g_mutex_unlock (&priv->lock);
655 }
656
657 /**
658  * gst_rtsp_media_get_permissions:
659  * @media: a #GstRTSPMedia
660  *
661  * Get the permissions object from @media.
662  *
663  * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage.
664  */
665 GstRTSPPermissions *
666 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
667 {
668   GstRTSPMediaPrivate *priv;
669   GstRTSPPermissions *result;
670
671   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
672
673   priv = media->priv;
674
675   g_mutex_lock (&priv->lock);
676   if ((result = priv->permissions))
677     gst_rtsp_permissions_ref (result);
678   g_mutex_unlock (&priv->lock);
679
680   return result;
681 }
682
683 /**
684  * gst_rtsp_media_set_suspend_mode:
685  * @media: a #GstRTSPMedia
686  * @mode: the new #GstRTSPSuspendMode
687  *
688  * Control how @ media will be suspended after the SDP has been generated and
689  * after a PAUSE request has been performed.
690  *
691  * Media must be unprepared when setting the suspend mode.
692  */
693 void
694 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
695 {
696   GstRTSPMediaPrivate *priv;
697
698   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
699
700   priv = media->priv;
701
702   g_rec_mutex_lock (&priv->state_lock);
703   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
704     goto was_prepared;
705   priv->suspend_mode = mode;
706   g_rec_mutex_unlock (&priv->state_lock);
707
708   return;
709
710   /* ERRORS */
711 was_prepared:
712   {
713     GST_WARNING ("media %p was prepared", media);
714     g_rec_mutex_unlock (&priv->state_lock);
715   }
716 }
717
718 /**
719  * gst_rtsp_media_get_suspend_mode:
720  * @media: a #GstRTSPMedia
721  *
722  * Get how @media will be suspended.
723  *
724  * Returns: #GstRTSPSuspendMode.
725  */
726 GstRTSPSuspendMode
727 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
728 {
729   GstRTSPMediaPrivate *priv;
730   GstRTSPSuspendMode res;
731
732   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
733
734   priv = media->priv;
735
736   g_rec_mutex_lock (&priv->state_lock);
737   res = priv->suspend_mode;
738   g_rec_mutex_unlock (&priv->state_lock);
739
740   return res;
741 }
742
743 /**
744  * gst_rtsp_media_set_shared:
745  * @media: a #GstRTSPMedia
746  * @shared: the new value
747  *
748  * Set or unset if the pipeline for @media can be shared will multiple clients.
749  * When @shared is %TRUE, client requests for this media will share the media
750  * pipeline.
751  */
752 void
753 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
754 {
755   GstRTSPMediaPrivate *priv;
756
757   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
758
759   priv = media->priv;
760
761   g_mutex_lock (&priv->lock);
762   priv->shared = shared;
763   g_mutex_unlock (&priv->lock);
764 }
765
766 /**
767  * gst_rtsp_media_is_shared:
768  * @media: a #GstRTSPMedia
769  *
770  * Check if the pipeline for @media can be shared between multiple clients.
771  *
772  * Returns: %TRUE if the media can be shared between clients.
773  */
774 gboolean
775 gst_rtsp_media_is_shared (GstRTSPMedia * media)
776 {
777   GstRTSPMediaPrivate *priv;
778   gboolean res;
779
780   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
781
782   priv = media->priv;
783
784   g_mutex_lock (&priv->lock);
785   res = priv->shared;
786   g_mutex_unlock (&priv->lock);
787
788   return res;
789 }
790
791 /**
792  * gst_rtsp_media_set_reusable:
793  * @media: a #GstRTSPMedia
794  * @reusable: the new value
795  *
796  * Set or unset if the pipeline for @media can be reused after the pipeline has
797  * been unprepared.
798  */
799 void
800 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
801 {
802   GstRTSPMediaPrivate *priv;
803
804   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
805
806   priv = media->priv;
807
808   g_mutex_lock (&priv->lock);
809   priv->reusable = reusable;
810   g_mutex_unlock (&priv->lock);
811 }
812
813 /**
814  * gst_rtsp_media_is_reusable:
815  * @media: a #GstRTSPMedia
816  *
817  * Check if the pipeline for @media can be reused after an unprepare.
818  *
819  * Returns: %TRUE if the media can be reused
820  */
821 gboolean
822 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
823 {
824   GstRTSPMediaPrivate *priv;
825   gboolean res;
826
827   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
828
829   priv = media->priv;
830
831   g_mutex_lock (&priv->lock);
832   res = priv->reusable;
833   g_mutex_unlock (&priv->lock);
834
835   return res;
836 }
837
838 static void
839 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
840 {
841   gst_rtsp_stream_set_profiles (stream, *profiles);
842 }
843
844 /**
845  * gst_rtsp_media_set_profiles:
846  * @media: a #GstRTSPMedia
847  * @profiles: the new flags
848  *
849  * Configure the allowed lower transport for @media.
850  */
851 void
852 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
853 {
854   GstRTSPMediaPrivate *priv;
855
856   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
857
858   priv = media->priv;
859
860   g_mutex_lock (&priv->lock);
861   priv->profiles = profiles;
862   g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
863   g_mutex_unlock (&priv->lock);
864 }
865
866 /**
867  * gst_rtsp_media_get_profiles:
868  * @media: a #GstRTSPMedia
869  *
870  * Get the allowed profiles of @media.
871  *
872  * Returns: a #GstRTSPProfile
873  */
874 GstRTSPProfile
875 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
876 {
877   GstRTSPMediaPrivate *priv;
878   GstRTSPProfile res;
879
880   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
881
882   priv = media->priv;
883
884   g_mutex_lock (&priv->lock);
885   res = priv->profiles;
886   g_mutex_unlock (&priv->lock);
887
888   return res;
889 }
890
891 static void
892 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
893 {
894   gst_rtsp_stream_set_protocols (stream, *protocols);
895 }
896
897 /**
898  * gst_rtsp_media_set_protocols:
899  * @media: a #GstRTSPMedia
900  * @protocols: the new flags
901  *
902  * Configure the allowed lower transport for @media.
903  */
904 void
905 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
906 {
907   GstRTSPMediaPrivate *priv;
908
909   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
910
911   priv = media->priv;
912
913   g_mutex_lock (&priv->lock);
914   priv->protocols = protocols;
915   g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
916   g_mutex_unlock (&priv->lock);
917 }
918
919 /**
920  * gst_rtsp_media_get_protocols:
921  * @media: a #GstRTSPMedia
922  *
923  * Get the allowed protocols of @media.
924  *
925  * Returns: a #GstRTSPLowerTrans
926  */
927 GstRTSPLowerTrans
928 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
929 {
930   GstRTSPMediaPrivate *priv;
931   GstRTSPLowerTrans res;
932
933   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
934       GST_RTSP_LOWER_TRANS_UNKNOWN);
935
936   priv = media->priv;
937
938   g_mutex_lock (&priv->lock);
939   res = priv->protocols;
940   g_mutex_unlock (&priv->lock);
941
942   return res;
943 }
944
945 /**
946  * gst_rtsp_media_set_eos_shutdown:
947  * @media: a #GstRTSPMedia
948  * @eos_shutdown: the new value
949  *
950  * Set or unset if an EOS event will be sent to the pipeline for @media before
951  * it is unprepared.
952  */
953 void
954 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
955 {
956   GstRTSPMediaPrivate *priv;
957
958   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
959
960   priv = media->priv;
961
962   g_mutex_lock (&priv->lock);
963   priv->eos_shutdown = eos_shutdown;
964   g_mutex_unlock (&priv->lock);
965 }
966
967 /**
968  * gst_rtsp_media_is_eos_shutdown:
969  * @media: a #GstRTSPMedia
970  *
971  * Check if the pipeline for @media will send an EOS down the pipeline before
972  * unpreparing.
973  *
974  * Returns: %TRUE if the media will send EOS before unpreparing.
975  */
976 gboolean
977 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
978 {
979   GstRTSPMediaPrivate *priv;
980   gboolean res;
981
982   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
983
984   priv = media->priv;
985
986   g_mutex_lock (&priv->lock);
987   res = priv->eos_shutdown;
988   g_mutex_unlock (&priv->lock);
989
990   return res;
991 }
992
993 /**
994  * gst_rtsp_media_set_buffer_size:
995  * @media: a #GstRTSPMedia
996  * @size: the new value
997  *
998  * Set the kernel UDP buffer size.
999  */
1000 void
1001 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1002 {
1003   GstRTSPMediaPrivate *priv;
1004
1005   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1006
1007   GST_LOG_OBJECT (media, "set buffer size %u", size);
1008
1009   priv = media->priv;
1010
1011   g_mutex_lock (&priv->lock);
1012   priv->buffer_size = size;
1013   g_mutex_unlock (&priv->lock);
1014 }
1015
1016 /**
1017  * gst_rtsp_media_get_buffer_size:
1018  * @media: a #GstRTSPMedia
1019  *
1020  * Get the kernel UDP buffer size.
1021  *
1022  * Returns: the kernel UDP buffer size.
1023  */
1024 guint
1025 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1026 {
1027   GstRTSPMediaPrivate *priv;
1028   guint res;
1029
1030   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1031
1032   priv = media->priv;
1033
1034   g_mutex_unlock (&priv->lock);
1035   res = priv->buffer_size;
1036   g_mutex_unlock (&priv->lock);
1037
1038   return res;
1039 }
1040
1041 /**
1042  * gst_rtsp_media_use_time_provider:
1043  * @media: a #GstRTSPMedia
1044  * @time_provider: if a #GstNetTimeProvider should be used
1045  *
1046  * Set @media to provide a #GstNetTimeProvider.
1047  */
1048 void
1049 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1050 {
1051   GstRTSPMediaPrivate *priv;
1052
1053   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1054
1055   priv = media->priv;
1056
1057   g_mutex_lock (&priv->lock);
1058   priv->time_provider = time_provider;
1059   g_mutex_unlock (&priv->lock);
1060 }
1061
1062 /**
1063  * gst_rtsp_media_is_time_provider:
1064  * @media: a #GstRTSPMedia
1065  *
1066  * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1067  *
1068  * Use gst_rtsp_media_get_time_provider() to get the network clock.
1069  *
1070  * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1071  */
1072 gboolean
1073 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1074 {
1075   GstRTSPMediaPrivate *priv;
1076   gboolean res;
1077
1078   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1079
1080   priv = media->priv;
1081
1082   g_mutex_unlock (&priv->lock);
1083   res = priv->time_provider;
1084   g_mutex_unlock (&priv->lock);
1085
1086   return res;
1087 }
1088
1089 /**
1090  * gst_rtsp_media_set_address_pool:
1091  * @media: a #GstRTSPMedia
1092  * @pool: a #GstRTSPAddressPool
1093  *
1094  * configure @pool to be used as the address pool of @media.
1095  */
1096 void
1097 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1098     GstRTSPAddressPool * pool)
1099 {
1100   GstRTSPMediaPrivate *priv;
1101   GstRTSPAddressPool *old;
1102
1103   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1104
1105   priv = media->priv;
1106
1107   GST_LOG_OBJECT (media, "set address pool %p", pool);
1108
1109   g_mutex_lock (&priv->lock);
1110   if ((old = priv->pool) != pool)
1111     priv->pool = pool ? g_object_ref (pool) : NULL;
1112   else
1113     old = NULL;
1114   g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1115       pool);
1116   g_mutex_unlock (&priv->lock);
1117
1118   if (old)
1119     g_object_unref (old);
1120 }
1121
1122 /**
1123  * gst_rtsp_media_get_address_pool:
1124  * @media: a #GstRTSPMedia
1125  *
1126  * Get the #GstRTSPAddressPool used as the address pool of @media.
1127  *
1128  * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
1129  * usage.
1130  */
1131 GstRTSPAddressPool *
1132 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1133 {
1134   GstRTSPMediaPrivate *priv;
1135   GstRTSPAddressPool *result;
1136
1137   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1138
1139   priv = media->priv;
1140
1141   g_mutex_lock (&priv->lock);
1142   if ((result = priv->pool))
1143     g_object_ref (result);
1144   g_mutex_unlock (&priv->lock);
1145
1146   return result;
1147 }
1148
1149 /**
1150  * gst_rtsp_media_collect_streams:
1151  * @media: a #GstRTSPMedia
1152  *
1153  * Find all payloader elements, they should be named pay\%d in the
1154  * element of @media, and create #GstRTSPStreams for them.
1155  *
1156  * Collect all dynamic elements, named dynpay\%d, and add them to
1157  * the list of dynamic elements.
1158  */
1159 void
1160 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
1161 {
1162   GstRTSPMediaPrivate *priv;
1163   GstElement *element, *elem;
1164   GstPad *pad;
1165   gint i;
1166   gboolean have_elem;
1167
1168   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1169
1170   priv = media->priv;
1171   element = priv->element;
1172
1173   have_elem = TRUE;
1174   for (i = 0; have_elem; i++) {
1175     gchar *name;
1176
1177     have_elem = FALSE;
1178
1179     name = g_strdup_printf ("pay%d", i);
1180     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1181       GST_INFO ("found stream %d with payloader %p", i, elem);
1182
1183       /* take the pad of the payloader */
1184       pad = gst_element_get_static_pad (elem, "src");
1185       /* create the stream */
1186       gst_rtsp_media_create_stream (media, elem, pad);
1187       gst_object_unref (pad);
1188       gst_object_unref (elem);
1189
1190       have_elem = TRUE;
1191     }
1192     g_free (name);
1193
1194     name = g_strdup_printf ("dynpay%d", i);
1195     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1196       /* a stream that will dynamically create pads to provide RTP packets */
1197
1198       GST_INFO ("found dynamic element %d, %p", i, elem);
1199
1200       g_mutex_lock (&priv->lock);
1201       priv->dynamic = g_list_prepend (priv->dynamic, elem);
1202       g_mutex_unlock (&priv->lock);
1203
1204       have_elem = TRUE;
1205     }
1206     g_free (name);
1207   }
1208 }
1209
1210 /**
1211  * gst_rtsp_media_create_stream:
1212  * @media: a #GstRTSPMedia
1213  * @payloader: a #GstElement
1214  * @srcpad: a source #GstPad
1215  *
1216  * Create a new stream in @media that provides RTP data on @srcpad.
1217  * @srcpad should be a pad of an element inside @media->element.
1218  *
1219  * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
1220  *          as @media exists.
1221  */
1222 GstRTSPStream *
1223 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
1224     GstPad * pad)
1225 {
1226   GstRTSPMediaPrivate *priv;
1227   GstRTSPStream *stream;
1228   GstPad *srcpad;
1229   gchar *name;
1230   gint idx;
1231
1232   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1233   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
1234   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1235   g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
1236
1237   priv = media->priv;
1238
1239   g_mutex_lock (&priv->lock);
1240   idx = priv->streams->len;
1241
1242   GST_DEBUG ("media %p: creating stream with index %d", media, idx);
1243
1244   name = g_strdup_printf ("src_%u", idx);
1245   srcpad = gst_ghost_pad_new (name, pad);
1246   gst_pad_set_active (srcpad, TRUE);
1247   gst_element_add_pad (priv->element, srcpad);
1248   g_free (name);
1249
1250   stream = gst_rtsp_stream_new (idx, payloader, srcpad);
1251   if (priv->pool)
1252     gst_rtsp_stream_set_address_pool (stream, priv->pool);
1253   gst_rtsp_stream_set_protocols (stream, priv->protocols);
1254
1255   g_ptr_array_add (priv->streams, stream);
1256   g_mutex_unlock (&priv->lock);
1257
1258   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
1259       NULL);
1260
1261   return stream;
1262 }
1263
1264 static void
1265 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
1266 {
1267   GstRTSPMediaPrivate *priv;
1268   GstPad *srcpad;
1269
1270   priv = media->priv;
1271
1272   g_mutex_lock (&priv->lock);
1273   /* remove the ghostpad */
1274   srcpad = gst_rtsp_stream_get_srcpad (stream);
1275   gst_element_remove_pad (priv->element, srcpad);
1276   gst_object_unref (srcpad);
1277   /* now remove the stream */
1278   g_object_ref (stream);
1279   g_ptr_array_remove (priv->streams, stream);
1280   g_mutex_unlock (&priv->lock);
1281
1282   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1283       stream, NULL);
1284
1285   g_object_unref (stream);
1286 }
1287
1288 /**
1289  * gst_rtsp_media_n_streams:
1290  * @media: a #GstRTSPMedia
1291  *
1292  * Get the number of streams in this media.
1293  *
1294  * Returns: The number of streams.
1295  */
1296 guint
1297 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1298 {
1299   GstRTSPMediaPrivate *priv;
1300   guint res;
1301
1302   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1303
1304   priv = media->priv;
1305
1306   g_mutex_lock (&priv->lock);
1307   res = priv->streams->len;
1308   g_mutex_unlock (&priv->lock);
1309
1310   return res;
1311 }
1312
1313 /**
1314  * gst_rtsp_media_get_stream:
1315  * @media: a #GstRTSPMedia
1316  * @idx: the stream index
1317  *
1318  * Retrieve the stream with index @idx from @media.
1319  *
1320  * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
1321  * that index did not exist.
1322  */
1323 GstRTSPStream *
1324 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1325 {
1326   GstRTSPMediaPrivate *priv;
1327   GstRTSPStream *res;
1328
1329   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1330
1331   priv = media->priv;
1332
1333   g_mutex_lock (&priv->lock);
1334   if (idx < priv->streams->len)
1335     res = g_ptr_array_index (priv->streams, idx);
1336   else
1337     res = NULL;
1338   g_mutex_unlock (&priv->lock);
1339
1340   return res;
1341 }
1342
1343 /**
1344  * gst_rtsp_media_find_stream:
1345  * @media: a #GstRTSPMedia
1346  * @control: the control of the stream
1347  *
1348  * Find a stream in @media with @control as the control uri.
1349  *
1350  * Returns: (transfer none): the #GstRTSPStream with control uri @control
1351  * or %NULL when a stream with that control did not exist.
1352  */
1353 GstRTSPStream *
1354 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
1355 {
1356   GstRTSPMediaPrivate *priv;
1357   GstRTSPStream *res;
1358   gint i;
1359
1360   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1361   g_return_val_if_fail (control != NULL, NULL);
1362
1363   priv = media->priv;
1364
1365   res = NULL;
1366
1367   g_mutex_lock (&priv->lock);
1368   for (i = 0; i < priv->streams->len; i++) {
1369     GstRTSPStream *test;
1370
1371     test = g_ptr_array_index (priv->streams, i);
1372     if (gst_rtsp_stream_has_control (test, control)) {
1373       res = test;
1374       break;
1375     }
1376   }
1377   g_mutex_unlock (&priv->lock);
1378
1379   return res;
1380 }
1381
1382 /* called with state-lock */
1383 static gboolean
1384 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
1385     GstRTSPRangeUnit unit)
1386 {
1387   return gst_rtsp_range_convert_units (range, unit);
1388 }
1389
1390 /**
1391  * gst_rtsp_media_get_range_string:
1392  * @media: a #GstRTSPMedia
1393  * @play: for the PLAY request
1394  * @unit: the unit to use for the string
1395  *
1396  * Get the current range as a string. @media must be prepared with
1397  * gst_rtsp_media_prepare ().
1398  *
1399  * Returns: The range as a string, g_free() after usage.
1400  */
1401 gchar *
1402 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
1403     GstRTSPRangeUnit unit)
1404 {
1405   GstRTSPMediaClass *klass;
1406   GstRTSPMediaPrivate *priv;
1407   gchar *result;
1408   GstRTSPTimeRange range;
1409
1410   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1411   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1412   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1413
1414   priv = media->priv;
1415
1416   g_rec_mutex_lock (&priv->state_lock);
1417   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
1418       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
1419     goto not_prepared;
1420
1421   g_mutex_lock (&priv->lock);
1422
1423   /* Update the range value with current position/duration */
1424   collect_media_stats (media);
1425
1426   /* make copy */
1427   range = priv->range;
1428
1429   if (!play && priv->n_active > 0) {
1430     range.min.type = GST_RTSP_TIME_NOW;
1431     range.min.seconds = -1;
1432   }
1433   g_mutex_unlock (&priv->lock);
1434   g_rec_mutex_unlock (&priv->state_lock);
1435
1436   if (!klass->convert_range (media, &range, unit))
1437     goto conversion_failed;
1438
1439   result = gst_rtsp_range_to_string (&range);
1440
1441   return result;
1442
1443   /* ERRORS */
1444 not_prepared:
1445   {
1446     GST_WARNING ("media %p was not prepared", media);
1447     g_rec_mutex_unlock (&priv->state_lock);
1448     return NULL;
1449   }
1450 conversion_failed:
1451   {
1452     GST_WARNING ("range conversion to unit %d failed", unit);
1453     return NULL;
1454   }
1455 }
1456
1457 static void
1458 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
1459 {
1460   gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
1461 }
1462
1463 static void
1464 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
1465 {
1466   GstRTSPMediaPrivate *priv = media->priv;
1467
1468   GST_DEBUG ("media %p set blocked %d", media, blocked);
1469   priv->blocked = blocked;
1470   g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
1471 }
1472
1473 /**
1474  * gst_rtsp_media_seek:
1475  * @media: a #GstRTSPMedia
1476  * @range: a #GstRTSPTimeRange
1477  *
1478  * Seek the pipeline of @media to @range. @media must be prepared with
1479  * gst_rtsp_media_prepare().
1480  *
1481  * Returns: %TRUE on success.
1482  */
1483 gboolean
1484 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1485 {
1486   GstRTSPMediaClass *klass;
1487   GstRTSPMediaPrivate *priv;
1488   gboolean res;
1489   GstClockTime start, stop;
1490   GstSeekType start_type, stop_type;
1491   GstQuery *query;
1492
1493   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1494
1495   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1496   g_return_val_if_fail (range != NULL, FALSE);
1497   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1498
1499   priv = media->priv;
1500
1501   g_rec_mutex_lock (&priv->state_lock);
1502   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1503     goto not_prepared;
1504
1505   /* Update the seekable state of the pipeline in case it changed */
1506   query = gst_query_new_seeking (GST_FORMAT_TIME);
1507   if (gst_element_query (priv->pipeline, query)) {
1508     GstFormat format;
1509     gboolean seekable;
1510     gint64 start, end;
1511
1512     gst_query_parse_seeking (query, &format, &seekable, &start, &end);
1513     priv->seekable = seekable;
1514   }
1515   gst_query_unref (query);
1516
1517   if (!priv->seekable)
1518     goto not_seekable;
1519
1520   start_type = stop_type = GST_SEEK_TYPE_NONE;
1521
1522   if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
1523     goto not_supported;
1524   gst_rtsp_range_get_times (range, &start, &stop);
1525
1526   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1527       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1528   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1529       GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1530
1531   if (priv->range_start == start)
1532     start = GST_CLOCK_TIME_NONE;
1533   else if (start != GST_CLOCK_TIME_NONE)
1534     start_type = GST_SEEK_TYPE_SET;
1535
1536   if (priv->range_stop == stop)
1537     stop = GST_CLOCK_TIME_NONE;
1538   else if (stop != GST_CLOCK_TIME_NONE)
1539     stop_type = GST_SEEK_TYPE_SET;
1540
1541   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1542     GstSeekFlags flags;
1543
1544     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1545         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1546
1547     priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1548     if (priv->blocked)
1549       media_streams_set_blocked (media, TRUE);
1550
1551     /* depends on the current playing state of the pipeline. We might need to
1552      * queue this until we get EOS. */
1553     flags = GST_SEEK_FLAG_FLUSH;
1554
1555     /* only set keyframe flag when modifying start */
1556     if (start_type != GST_SEEK_TYPE_NONE)
1557       flags |= GST_SEEK_FLAG_KEY_UNIT;
1558
1559     /* FIXME, we only do forwards */
1560     res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1561         flags, start_type, start, stop_type, stop);
1562
1563     /* and block for the seek to complete */
1564     GST_INFO ("done seeking %d", res);
1565     g_rec_mutex_unlock (&priv->state_lock);
1566
1567     /* wait until pipeline is prerolled again, this will also collect stats */
1568     if (!wait_preroll (media))
1569       goto preroll_failed;
1570
1571     g_rec_mutex_lock (&priv->state_lock);
1572     GST_INFO ("prerolled again");
1573   } else {
1574     GST_INFO ("no seek needed");
1575     res = TRUE;
1576   }
1577   g_rec_mutex_unlock (&priv->state_lock);
1578
1579   return res;
1580
1581   /* ERRORS */
1582 not_prepared:
1583   {
1584     g_rec_mutex_unlock (&priv->state_lock);
1585     GST_INFO ("media %p is not prepared", media);
1586     return FALSE;
1587   }
1588 not_seekable:
1589   {
1590     g_rec_mutex_unlock (&priv->state_lock);
1591     GST_INFO ("pipeline is not seekable");
1592     return FALSE;
1593   }
1594 not_supported:
1595   {
1596     g_rec_mutex_unlock (&priv->state_lock);
1597     GST_WARNING ("conversion to npt not supported");
1598     return FALSE;
1599   }
1600 preroll_failed:
1601   {
1602     GST_WARNING ("failed to preroll after seek");
1603     return FALSE;
1604   }
1605 }
1606
1607 static void
1608 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1609 {
1610   GstRTSPMediaPrivate *priv = media->priv;
1611
1612   g_mutex_lock (&priv->lock);
1613   priv->status = status;
1614   GST_DEBUG ("setting new status to %d", status);
1615   g_cond_broadcast (&priv->cond);
1616   g_mutex_unlock (&priv->lock);
1617 }
1618
1619 /**
1620  * gst_rtsp_media_get_status:
1621  * @media: a #GstRTSPMedia
1622  *
1623  * Get the status of @media. When @media is busy preparing, this function waits
1624  * until @media is prepared or in error.
1625  *
1626  * Returns: the status of @media.
1627  */
1628 GstRTSPMediaStatus
1629 gst_rtsp_media_get_status (GstRTSPMedia * media)
1630 {
1631   GstRTSPMediaPrivate *priv = media->priv;
1632   GstRTSPMediaStatus result;
1633   gint64 end_time;
1634
1635   g_mutex_lock (&priv->lock);
1636   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1637   /* while we are preparing, wait */
1638   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1639     GST_DEBUG ("waiting for status change");
1640     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1641       GST_DEBUG ("timeout, assuming error status");
1642       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1643     }
1644   }
1645   /* could be success or error */
1646   result = priv->status;
1647   GST_DEBUG ("got status %d", result);
1648   g_mutex_unlock (&priv->lock);
1649
1650   return result;
1651 }
1652
1653 static void
1654 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
1655 {
1656   *blocked &= gst_rtsp_stream_is_blocking (stream);
1657 }
1658
1659 static gboolean
1660 media_streams_blocking (GstRTSPMedia * media)
1661 {
1662   gboolean blocking = TRUE;
1663
1664   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
1665       &blocking);
1666
1667   return blocking;
1668 }
1669
1670 static GstStateChangeReturn
1671 set_state (GstRTSPMedia * media, GstState state)
1672 {
1673   GstRTSPMediaPrivate *priv = media->priv;
1674   GstStateChangeReturn ret;
1675
1676   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
1677       media);
1678   ret = gst_element_set_state (priv->pipeline, state);
1679
1680   return ret;
1681 }
1682
1683 static GstStateChangeReturn
1684 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
1685 {
1686   GstRTSPMediaPrivate *priv = media->priv;
1687   GstStateChangeReturn ret;
1688
1689   GST_INFO ("set target state to %s for media %p",
1690       gst_element_state_get_name (state), media);
1691   priv->target_state = state;
1692
1693   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
1694       priv->target_state, NULL);
1695
1696   if (do_state)
1697     ret = set_state (media, state);
1698   else
1699     ret = GST_STATE_CHANGE_SUCCESS;
1700
1701   return ret;
1702 }
1703
1704 /* called with state-lock */
1705 static gboolean
1706 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1707 {
1708   GstRTSPMediaPrivate *priv = media->priv;
1709   GstMessageType type;
1710
1711   type = GST_MESSAGE_TYPE (message);
1712
1713   switch (type) {
1714     case GST_MESSAGE_STATE_CHANGED:
1715       break;
1716     case GST_MESSAGE_BUFFERING:
1717     {
1718       gint percent;
1719
1720       gst_message_parse_buffering (message, &percent);
1721
1722       /* no state management needed for live pipelines */
1723       if (priv->is_live)
1724         break;
1725
1726       if (percent == 100) {
1727         /* a 100% message means buffering is done */
1728         priv->buffering = FALSE;
1729         /* if the desired state is playing, go back */
1730         if (priv->target_state == GST_STATE_PLAYING) {
1731           GST_INFO ("Buffering done, setting pipeline to PLAYING");
1732           set_state (media, GST_STATE_PLAYING);
1733         } else {
1734           GST_INFO ("Buffering done");
1735         }
1736       } else {
1737         /* buffering busy */
1738         if (priv->buffering == FALSE) {
1739           if (priv->target_state == GST_STATE_PLAYING) {
1740             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
1741             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1742             set_state (media, GST_STATE_PAUSED);
1743           } else {
1744             GST_INFO ("Buffering ...");
1745           }
1746         }
1747         priv->buffering = TRUE;
1748       }
1749       break;
1750     }
1751     case GST_MESSAGE_LATENCY:
1752     {
1753       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1754       break;
1755     }
1756     case GST_MESSAGE_ERROR:
1757     {
1758       GError *gerror;
1759       gchar *debug;
1760
1761       gst_message_parse_error (message, &gerror, &debug);
1762       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1763       g_error_free (gerror);
1764       g_free (debug);
1765
1766       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1767       break;
1768     }
1769     case GST_MESSAGE_WARNING:
1770     {
1771       GError *gerror;
1772       gchar *debug;
1773
1774       gst_message_parse_warning (message, &gerror, &debug);
1775       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1776       g_error_free (gerror);
1777       g_free (debug);
1778       break;
1779     }
1780     case GST_MESSAGE_ELEMENT:
1781     {
1782       const GstStructure *s;
1783
1784       s = gst_message_get_structure (message);
1785       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
1786         GST_DEBUG ("media received blocking message");
1787         if (priv->blocked && media_streams_blocking (media)) {
1788           GST_DEBUG ("media is blocking");
1789           collect_media_stats (media);
1790
1791           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1792             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1793         }
1794       }
1795       break;
1796     }
1797     case GST_MESSAGE_STREAM_STATUS:
1798       break;
1799     case GST_MESSAGE_ASYNC_DONE:
1800       if (priv->adding) {
1801         /* when we are dynamically adding pads, the addition of the udpsrc will
1802          * temporarily produce ASYNC_DONE messages. We have to ignore them and
1803          * wait for the final ASYNC_DONE after everything prerolled */
1804         GST_INFO ("%p: ignoring ASYNC_DONE", media);
1805       } else {
1806         GST_INFO ("%p: got ASYNC_DONE", media);
1807         collect_media_stats (media);
1808
1809         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1810           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1811       }
1812       break;
1813     case GST_MESSAGE_EOS:
1814       GST_INFO ("%p: got EOS", media);
1815
1816       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1817         GST_DEBUG ("shutting down after EOS");
1818         finish_unprepare (media);
1819       }
1820       break;
1821     default:
1822       GST_INFO ("%p: got message type %d (%s)", media, type,
1823           gst_message_type_get_name (type));
1824       break;
1825   }
1826   return TRUE;
1827 }
1828
1829 static gboolean
1830 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1831 {
1832   GstRTSPMediaPrivate *priv = media->priv;
1833   GstRTSPMediaClass *klass;
1834   gboolean ret;
1835
1836   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1837
1838   g_rec_mutex_lock (&priv->state_lock);
1839   if (klass->handle_message)
1840     ret = klass->handle_message (media, message);
1841   else
1842     ret = FALSE;
1843   g_rec_mutex_unlock (&priv->state_lock);
1844
1845   return ret;
1846 }
1847
1848 static void
1849 watch_destroyed (GstRTSPMedia * media)
1850 {
1851   GST_DEBUG_OBJECT (media, "source destroyed");
1852   g_object_unref (media);
1853 }
1854
1855 static GstElement *
1856 find_payload_element (GstElement * payloader)
1857 {
1858   GstElement *pay = NULL;
1859
1860   if (GST_IS_BIN (payloader)) {
1861     GstIterator *iter;
1862     GValue item = { 0 };
1863
1864     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
1865     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
1866       GstElement *element = (GstElement *) g_value_get_object (&item);
1867       GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
1868       const gchar *klass;
1869
1870       klass =
1871           gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
1872       if (klass == NULL)
1873         continue;
1874
1875       if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
1876         pay = gst_object_ref (element);
1877         g_value_unset (&item);
1878         break;
1879       }
1880       g_value_unset (&item);
1881     }
1882     gst_iterator_free (iter);
1883   } else {
1884     pay = g_object_ref (payloader);
1885   }
1886
1887   return pay;
1888 }
1889
1890 /* called from streaming threads */
1891 static void
1892 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1893 {
1894   GstRTSPMediaPrivate *priv = media->priv;
1895   GstRTSPStream *stream;
1896   GstElement *pay;
1897
1898   /* find the real payload element */
1899   pay = find_payload_element (element);
1900   stream = gst_rtsp_media_create_stream (media, pay, pad);
1901   gst_object_unref (pay);
1902
1903   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
1904
1905   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1906
1907   g_rec_mutex_lock (&priv->state_lock);
1908   /* we will be adding elements below that will cause ASYNC_DONE to be
1909    * posted in the bus. We want to ignore those messages until the
1910    * pipeline really prerolled. */
1911   priv->adding = TRUE;
1912
1913   /* join the element in the PAUSED state because this callback is
1914    * called from the streaming thread and it is PAUSED */
1915   gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1916       priv->rtpbin, GST_STATE_PAUSED);
1917
1918   priv->adding = FALSE;
1919   g_rec_mutex_unlock (&priv->state_lock);
1920 }
1921
1922 static void
1923 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1924 {
1925   GstRTSPMediaPrivate *priv = media->priv;
1926   GstRTSPStream *stream;
1927
1928   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
1929   if (stream == NULL)
1930     return;
1931
1932   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1933
1934   g_rec_mutex_lock (&priv->state_lock);
1935   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1936   g_rec_mutex_unlock (&priv->state_lock);
1937
1938   gst_rtsp_media_remove_stream (media, stream);
1939 }
1940
1941 static void
1942 remove_fakesink (GstRTSPMediaPrivate * priv)
1943 {
1944   GstElement *fakesink;
1945
1946   g_mutex_lock (&priv->lock);
1947   if ((fakesink = priv->fakesink))
1948     gst_object_ref (fakesink);
1949   priv->fakesink = NULL;
1950   g_mutex_unlock (&priv->lock);
1951
1952   if (fakesink) {
1953     gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1954     gst_element_set_state (fakesink, GST_STATE_NULL);
1955     gst_object_unref (fakesink);
1956     GST_INFO ("removed fakesink");
1957   }
1958 }
1959
1960 static void
1961 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1962 {
1963   GstRTSPMediaPrivate *priv = media->priv;
1964
1965   GST_INFO ("no more pads");
1966   remove_fakesink (priv);
1967 }
1968
1969 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
1970
1971 struct _DynPaySignalHandlers
1972 {
1973   gulong pad_added_handler;
1974   gulong pad_removed_handler;
1975   gulong no_more_pads_handler;
1976 };
1977
1978 static gboolean
1979 start_preroll (GstRTSPMedia * media)
1980 {
1981   GstRTSPMediaPrivate *priv = media->priv;
1982   GstStateChangeReturn ret;
1983
1984   GST_INFO ("setting pipeline to PAUSED for media %p", media);
1985   /* first go to PAUSED */
1986   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
1987
1988   switch (ret) {
1989     case GST_STATE_CHANGE_SUCCESS:
1990       GST_INFO ("SUCCESS state change for media %p", media);
1991       priv->seekable = TRUE;
1992       break;
1993     case GST_STATE_CHANGE_ASYNC:
1994       GST_INFO ("ASYNC state change for media %p", media);
1995       priv->seekable = TRUE;
1996       break;
1997     case GST_STATE_CHANGE_NO_PREROLL:
1998       /* we need to go to PLAYING */
1999       GST_INFO ("NO_PREROLL state change: live media %p", media);
2000       /* FIXME we disable seeking for live streams for now. We should perform a
2001        * seeking query in preroll instead */
2002       priv->seekable = FALSE;
2003       priv->is_live = TRUE;
2004       /* start blocked  to make sure nothing goes to the sink */
2005       media_streams_set_blocked (media, TRUE);
2006       ret = set_state (media, GST_STATE_PLAYING);
2007       if (ret == GST_STATE_CHANGE_FAILURE)
2008         goto state_failed;
2009       break;
2010     case GST_STATE_CHANGE_FAILURE:
2011       goto state_failed;
2012   }
2013
2014   return TRUE;
2015
2016 state_failed:
2017   {
2018     GST_WARNING ("failed to preroll pipeline");
2019     return FALSE;
2020   }
2021 }
2022
2023 static gboolean
2024 wait_preroll (GstRTSPMedia * media)
2025 {
2026   GstRTSPMediaStatus status;
2027
2028   GST_DEBUG ("wait to preroll pipeline");
2029
2030   /* wait until pipeline is prerolled */
2031   status = gst_rtsp_media_get_status (media);
2032   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
2033     goto preroll_failed;
2034
2035   return TRUE;
2036
2037 preroll_failed:
2038   {
2039     GST_WARNING ("failed to preroll pipeline");
2040     return FALSE;
2041   }
2042 }
2043
2044 static gboolean
2045 start_prepare (GstRTSPMedia * media)
2046 {
2047   GstRTSPMediaPrivate *priv = media->priv;
2048   guint i;
2049   GList *walk;
2050
2051   /* link streams we already have, other streams might appear when we have
2052    * dynamic elements */
2053   for (i = 0; i < priv->streams->len; i++) {
2054     GstRTSPStream *stream;
2055
2056     stream = g_ptr_array_index (priv->streams, i);
2057
2058     gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2059         priv->rtpbin, GST_STATE_NULL);
2060   }
2061
2062   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2063     GstElement *elem = walk->data;
2064     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
2065
2066     GST_INFO ("adding callbacks for dynamic element %p", elem);
2067
2068     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
2069         (GCallback) pad_added_cb, media);
2070     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
2071         (GCallback) pad_removed_cb, media);
2072     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
2073         (GCallback) no_more_pads_cb, media);
2074
2075     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
2076
2077     /* we add a fakesink here in order to make the state change async. We remove
2078      * the fakesink again in the no-more-pads callback. */
2079     priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
2080     gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
2081   }
2082
2083   if (!start_preroll (media))
2084     goto preroll_failed;
2085
2086   return FALSE;
2087
2088 preroll_failed:
2089   {
2090     GST_WARNING ("failed to preroll pipeline");
2091     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2092     return FALSE;
2093   }
2094 }
2095
2096 /**
2097  * gst_rtsp_media_prepare:
2098  * @media: a #GstRTSPMedia
2099  * @thread: a #GstRTSPThread to run the bus handler or %NULL
2100  *
2101  * Prepare @media for streaming. This function will create the objects
2102  * to manage the streaming. A pipeline must have been set on @media with
2103  * gst_rtsp_media_take_pipeline().
2104  *
2105  * It will preroll the pipeline and collect vital information about the streams
2106  * such as the duration.
2107  *
2108  * Returns: %TRUE on success.
2109  */
2110 gboolean
2111 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2112 {
2113   GstRTSPMediaPrivate *priv;
2114   GstBus *bus;
2115   GSource *source;
2116   GstRTSPMediaClass *klass;
2117
2118   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2119   g_return_val_if_fail (GST_IS_RTSP_THREAD (thread), FALSE);
2120
2121   priv = media->priv;
2122
2123   g_rec_mutex_lock (&priv->state_lock);
2124   priv->prepare_count++;
2125
2126   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
2127       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
2128     goto was_prepared;
2129
2130   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2131     goto wait_status;
2132
2133   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
2134     goto not_unprepared;
2135
2136   if (!priv->reusable && priv->reused)
2137     goto is_reused;
2138
2139   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2140
2141   if (!klass->create_rtpbin)
2142     goto no_create_rtpbin;
2143
2144   priv->rtpbin = klass->create_rtpbin (media);
2145   if (priv->rtpbin != NULL) {
2146     gboolean success = TRUE;
2147
2148     if (klass->setup_rtpbin)
2149       success = klass->setup_rtpbin (media, priv->rtpbin);
2150
2151     if (success == FALSE) {
2152       gst_object_unref (priv->rtpbin);
2153       priv->rtpbin = NULL;
2154     }
2155   }
2156   if (priv->rtpbin == NULL)
2157     goto no_rtpbin;
2158
2159   GST_INFO ("preparing media %p", media);
2160
2161   /* reset some variables */
2162   priv->is_live = FALSE;
2163   priv->seekable = FALSE;
2164   priv->buffering = FALSE;
2165   priv->thread = thread;
2166   /* we're preparing now */
2167   priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
2168
2169   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
2170
2171   /* add the pipeline bus to our custom mainloop */
2172   priv->source = gst_bus_create_watch (bus);
2173   gst_object_unref (bus);
2174
2175   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
2176       g_object_ref (media), (GDestroyNotify) watch_destroyed);
2177
2178   priv->id = g_source_attach (priv->source, thread->context);
2179
2180   /* add stuff to the bin */
2181   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
2182
2183   /* do remainder in context */
2184   source = g_idle_source_new ();
2185   g_source_set_callback (source, (GSourceFunc) start_prepare, media, NULL);
2186   g_source_attach (source, thread->context);
2187   g_source_unref (source);
2188
2189 wait_status:
2190   g_rec_mutex_unlock (&priv->state_lock);
2191
2192   /* now wait for all pads to be prerolled, FIXME, we should somehow be
2193    * able to do this async so that we don't block the server thread. */
2194   if (!wait_preroll (media))
2195     goto preroll_failed;
2196
2197   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
2198
2199   GST_INFO ("object %p is prerolled", media);
2200
2201   return TRUE;
2202
2203   /* OK */
2204 was_prepared:
2205   {
2206     GST_LOG ("media %p was prepared", media);
2207     g_rec_mutex_unlock (&priv->state_lock);
2208     return TRUE;
2209   }
2210   /* ERRORS */
2211 not_unprepared:
2212   {
2213     GST_WARNING ("media %p was not unprepared", media);
2214     priv->prepare_count--;
2215     g_rec_mutex_unlock (&priv->state_lock);
2216     return FALSE;
2217   }
2218 is_reused:
2219   {
2220     priv->prepare_count--;
2221     g_rec_mutex_unlock (&priv->state_lock);
2222     GST_WARNING ("can not reuse media %p", media);
2223     return FALSE;
2224   }
2225 no_create_rtpbin:
2226   {
2227     priv->prepare_count--;
2228     g_rec_mutex_unlock (&priv->state_lock);
2229     GST_ERROR ("no create_rtpbin function");
2230     g_critical ("no create_rtpbin vmethod function set");
2231     return FALSE;
2232   }
2233 no_rtpbin:
2234   {
2235     priv->prepare_count--;
2236     g_rec_mutex_unlock (&priv->state_lock);
2237     GST_WARNING ("no rtpbin element");
2238     g_warning ("failed to create element 'rtpbin', check your installation");
2239     return FALSE;
2240   }
2241 preroll_failed:
2242   {
2243     GST_WARNING ("failed to preroll pipeline");
2244     gst_rtsp_media_unprepare (media);
2245     return FALSE;
2246   }
2247 }
2248
2249 /* must be called with state-lock */
2250 static void
2251 finish_unprepare (GstRTSPMedia * media)
2252 {
2253   GstRTSPMediaPrivate *priv = media->priv;
2254   gint i;
2255   GList *walk;
2256
2257   GST_DEBUG ("shutting down");
2258
2259   set_state (media, GST_STATE_NULL);
2260   remove_fakesink (priv);
2261
2262   for (i = 0; i < priv->streams->len; i++) {
2263     GstRTSPStream *stream;
2264
2265     GST_INFO ("Removing elements of stream %d from pipeline", i);
2266
2267     stream = g_ptr_array_index (priv->streams, i);
2268
2269     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
2270   }
2271
2272   /* remove the pad signal handlers */
2273   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2274     GstElement *elem = walk->data;
2275     DynPaySignalHandlers *handlers;
2276
2277     handlers =
2278         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
2279     g_assert (handlers != NULL);
2280
2281     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
2282     g_signal_handler_disconnect (G_OBJECT (elem),
2283         handlers->pad_removed_handler);
2284     g_signal_handler_disconnect (G_OBJECT (elem),
2285         handlers->no_more_pads_handler);
2286
2287     g_slice_free (DynPaySignalHandlers, handlers);
2288   }
2289
2290   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
2291   priv->rtpbin = NULL;
2292
2293   if (priv->nettime)
2294     gst_object_unref (priv->nettime);
2295   priv->nettime = NULL;
2296
2297   priv->reused = TRUE;
2298   priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
2299
2300   /* when the media is not reusable, this will effectively unref the media and
2301    * recreate it */
2302   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
2303
2304   /* the source has the last ref to the media */
2305   if (priv->source) {
2306     GST_DEBUG ("destroy source");
2307     g_source_destroy (priv->source);
2308     g_source_unref (priv->source);
2309   }
2310   if (priv->thread) {
2311     GST_DEBUG ("stop thread");
2312     gst_rtsp_thread_stop (priv->thread);
2313   }
2314 }
2315
2316 /* called with state-lock */
2317 static gboolean
2318 default_unprepare (GstRTSPMedia * media)
2319 {
2320   GstRTSPMediaPrivate *priv = media->priv;
2321
2322   if (priv->eos_shutdown) {
2323     GST_DEBUG ("sending EOS for shutdown");
2324     /* ref so that we don't disappear */
2325     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
2326     /* we need to go to playing again for the EOS to propagate, normally in this
2327      * state, nothing is receiving data from us anymore so this is ok. */
2328     set_state (media, GST_STATE_PLAYING);
2329     priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
2330   } else {
2331     finish_unprepare (media);
2332   }
2333   return TRUE;
2334 }
2335
2336 /**
2337  * gst_rtsp_media_unprepare:
2338  * @media: a #GstRTSPMedia
2339  *
2340  * Unprepare @media. After this call, the media should be prepared again before
2341  * it can be used again. If the media is set to be non-reusable, a new instance
2342  * must be created.
2343  *
2344  * Returns: %TRUE on success.
2345  */
2346 gboolean
2347 gst_rtsp_media_unprepare (GstRTSPMedia * media)
2348 {
2349   GstRTSPMediaPrivate *priv;
2350   gboolean success;
2351
2352   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2353
2354   priv = media->priv;
2355
2356   g_rec_mutex_lock (&priv->state_lock);
2357   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
2358     goto was_unprepared;
2359
2360   priv->prepare_count--;
2361   if (priv->prepare_count > 0)
2362     goto is_busy;
2363
2364   GST_INFO ("unprepare media %p", media);
2365   set_target_state (media, GST_STATE_NULL, FALSE);
2366   success = TRUE;
2367
2368   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
2369     GstRTSPMediaClass *klass;
2370
2371     klass = GST_RTSP_MEDIA_GET_CLASS (media);
2372     if (klass->unprepare)
2373       success = klass->unprepare (media);
2374   } else {
2375     finish_unprepare (media);
2376   }
2377   g_rec_mutex_unlock (&priv->state_lock);
2378
2379   return success;
2380
2381 was_unprepared:
2382   {
2383     g_rec_mutex_unlock (&priv->state_lock);
2384     GST_INFO ("media %p was already unprepared", media);
2385     return TRUE;
2386   }
2387 is_busy:
2388   {
2389     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
2390     g_rec_mutex_unlock (&priv->state_lock);
2391     return TRUE;
2392   }
2393 }
2394
2395 /* should be called with state-lock */
2396 static GstClock *
2397 get_clock_unlocked (GstRTSPMedia * media)
2398 {
2399   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
2400     GST_DEBUG_OBJECT (media, "media was not prepared");
2401     return NULL;
2402   }
2403   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
2404 }
2405
2406 /**
2407  * gst_rtsp_media_get_clock:
2408  * @media: a #GstRTSPMedia
2409  *
2410  * Get the clock that is used by the pipeline in @media.
2411  *
2412  * @media must be prepared before this method returns a valid clock object.
2413  *
2414  * Returns: (transfer full): the #GstClock used by @media. unref after usage.
2415  */
2416 GstClock *
2417 gst_rtsp_media_get_clock (GstRTSPMedia * media)
2418 {
2419   GstClock *clock;
2420   GstRTSPMediaPrivate *priv;
2421
2422   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2423
2424   priv = media->priv;
2425
2426   g_rec_mutex_lock (&priv->state_lock);
2427   clock = get_clock_unlocked (media);
2428   g_rec_mutex_unlock (&priv->state_lock);
2429
2430   return clock;
2431 }
2432
2433 /**
2434  * gst_rtsp_media_get_base_time:
2435  * @media: a #GstRTSPMedia
2436  *
2437  * Get the base_time that is used by the pipeline in @media.
2438  *
2439  * @media must be prepared before this method returns a valid base_time.
2440  *
2441  * Returns: the base_time used by @media.
2442  */
2443 GstClockTime
2444 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
2445 {
2446   GstClockTime result;
2447   GstRTSPMediaPrivate *priv;
2448
2449   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
2450
2451   priv = media->priv;
2452
2453   g_rec_mutex_lock (&priv->state_lock);
2454   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2455     goto not_prepared;
2456
2457   result = gst_element_get_base_time (media->priv->pipeline);
2458   g_rec_mutex_unlock (&priv->state_lock);
2459
2460   return result;
2461
2462   /* ERRORS */
2463 not_prepared:
2464   {
2465     g_rec_mutex_unlock (&priv->state_lock);
2466     GST_DEBUG_OBJECT (media, "media was not prepared");
2467     return GST_CLOCK_TIME_NONE;
2468   }
2469 }
2470
2471 /**
2472  * gst_rtsp_media_get_time_provider:
2473  * @media: a #GstRTSPMedia
2474  * @address: an address or %NULL
2475  * @port: a port or 0
2476  *
2477  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
2478  * will listen on @address and @port for client time requests.
2479  *
2480  * Returns: (transfer full): the #GstNetTimeProvider of @media.
2481  */
2482 GstNetTimeProvider *
2483 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
2484     guint16 port)
2485 {
2486   GstRTSPMediaPrivate *priv;
2487   GstNetTimeProvider *provider = NULL;
2488
2489   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2490
2491   priv = media->priv;
2492
2493   g_rec_mutex_lock (&priv->state_lock);
2494   if (priv->time_provider) {
2495     if ((provider = priv->nettime) == NULL) {
2496       GstClock *clock;
2497
2498       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
2499         provider = gst_net_time_provider_new (clock, address, port);
2500         gst_object_unref (clock);
2501
2502         priv->nettime = provider;
2503       }
2504     }
2505   }
2506   g_rec_mutex_unlock (&priv->state_lock);
2507
2508   if (provider)
2509     gst_object_ref (provider);
2510
2511   return provider;
2512 }
2513
2514 static gboolean
2515 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
2516 {
2517   return gst_rtsp_sdp_from_media (sdp, info, media);
2518 }
2519
2520 /**
2521  * gst_rtsp_media_setup_sdp:
2522  * @sdp: a #GstSDPMessage
2523  * @info: info
2524  * @media: a #GstRTSPMedia
2525  *
2526  * Add @media specific info to @sdp. @info is used to configure the connection
2527  * information in the SDP.
2528  *
2529  * Returns: TRUE on success.
2530  */
2531 gboolean
2532 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
2533     GstSDPInfo * info)
2534 {
2535   GstRTSPMediaPrivate *priv;
2536   GstRTSPMediaClass *klass;
2537   gboolean res;
2538
2539   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2540   g_return_val_if_fail (sdp != NULL, FALSE);
2541   g_return_val_if_fail (info != NULL, FALSE);
2542
2543   priv = media->priv;
2544
2545   g_rec_mutex_lock (&priv->state_lock);
2546
2547   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2548
2549   if (!klass->setup_sdp)
2550     goto no_setup_sdp;
2551
2552   res = klass->setup_sdp (media, sdp, info);
2553
2554   g_rec_mutex_unlock (&priv->state_lock);
2555
2556   return res;
2557
2558   /* ERRORS */
2559 no_setup_sdp:
2560   {
2561     g_rec_mutex_unlock (&priv->state_lock);
2562     GST_ERROR ("no setup_sdp function");
2563     g_critical ("no setup_sdp vmethod function set");
2564     return FALSE;
2565   }
2566 }
2567
2568 /**
2569  * gst_rtsp_media_suspend:
2570  * @media: a #GstRTSPMedia
2571  *
2572  * Suspend @media. The state of the pipeline managed by @media is set to
2573  * GST_STATE_NULL but all streams are kept. @media can be prepared again
2574  * with gst_rtsp_media_undo_reset()
2575  *
2576  * @media must be prepared with gst_rtsp_media_prepare();
2577  *
2578  * Returns: %TRUE on success.
2579  */
2580 gboolean
2581 gst_rtsp_media_suspend (GstRTSPMedia * media)
2582 {
2583   GstRTSPMediaPrivate *priv = media->priv;
2584   GstStateChangeReturn ret;
2585
2586   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2587
2588   GST_FIXME ("suspend for dynamic pipelines needs fixing");
2589
2590   g_rec_mutex_lock (&priv->state_lock);
2591   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2592     goto not_prepared;
2593
2594   /* don't attempt to suspend when something is busy */
2595   if (priv->n_active > 0)
2596     goto done;
2597
2598   switch (priv->suspend_mode) {
2599     case GST_RTSP_SUSPEND_MODE_NONE:
2600       GST_DEBUG ("media %p no suspend", media);
2601       break;
2602     case GST_RTSP_SUSPEND_MODE_PAUSE:
2603       GST_DEBUG ("media %p suspend to PAUSED", media);
2604       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
2605       if (ret == GST_STATE_CHANGE_FAILURE)
2606         goto state_failed;
2607       break;
2608     case GST_RTSP_SUSPEND_MODE_RESET:
2609       GST_DEBUG ("media %p suspend to NULL", media);
2610       ret = set_target_state (media, GST_STATE_NULL, TRUE);
2611       if (ret == GST_STATE_CHANGE_FAILURE)
2612         goto state_failed;
2613       break;
2614     default:
2615       break;
2616   }
2617   /* let the streams do the state changes freely, if any */
2618   media_streams_set_blocked (media, FALSE);
2619   priv->status = GST_RTSP_MEDIA_STATUS_SUSPENDED;
2620 done:
2621   g_rec_mutex_unlock (&priv->state_lock);
2622
2623   return TRUE;
2624
2625   /* ERRORS */
2626 not_prepared:
2627   {
2628     g_rec_mutex_unlock (&priv->state_lock);
2629     GST_WARNING ("media %p was not prepared", media);
2630     return FALSE;
2631   }
2632 state_failed:
2633   {
2634     g_rec_mutex_unlock (&priv->state_lock);
2635     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2636     GST_WARNING ("failed changing pipeline's state for media %p", media);
2637     return FALSE;
2638   }
2639 }
2640
2641 /**
2642  * gst_rtsp_media_unsuspend:
2643  * @media: a #GstRTSPMedia
2644  *
2645  * Unsuspend @media if it was in a suspended state. This method does nothing
2646  * when the media was not in the suspended state.
2647  *
2648  * Returns: %TRUE on success.
2649  */
2650 gboolean
2651 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
2652 {
2653   GstRTSPMediaPrivate *priv = media->priv;
2654
2655   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2656
2657   g_rec_mutex_lock (&priv->state_lock);
2658   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2659     goto done;
2660
2661   switch (priv->suspend_mode) {
2662     case GST_RTSP_SUSPEND_MODE_NONE:
2663       priv->status = GST_RTSP_MEDIA_STATUS_PREPARED;
2664       break;
2665     case GST_RTSP_SUSPEND_MODE_PAUSE:
2666       priv->status = GST_RTSP_MEDIA_STATUS_PREPARED;
2667       break;
2668     case GST_RTSP_SUSPEND_MODE_RESET:
2669     {
2670       priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
2671       if (!start_preroll (media))
2672         goto start_failed;
2673       g_rec_mutex_unlock (&priv->state_lock);
2674
2675       if (!wait_preroll (media))
2676         goto preroll_failed;
2677
2678       g_rec_mutex_lock (&priv->state_lock);
2679     }
2680     default:
2681       break;
2682   }
2683 done:
2684   g_rec_mutex_unlock (&priv->state_lock);
2685
2686   return TRUE;
2687
2688   /* ERRORS */
2689 start_failed:
2690   {
2691     g_rec_mutex_unlock (&priv->state_lock);
2692     GST_WARNING ("failed to preroll pipeline");
2693     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2694     return FALSE;
2695   }
2696 preroll_failed:
2697   {
2698     GST_WARNING ("failed to preroll pipeline");
2699     return FALSE;
2700   }
2701 }
2702
2703 /* must be called with state-lock */
2704 static void
2705 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
2706 {
2707   GstRTSPMediaPrivate *priv = media->priv;
2708
2709   if (state == GST_STATE_NULL) {
2710     gst_rtsp_media_unprepare (media);
2711   } else {
2712     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
2713     set_target_state (media, state, FALSE);
2714     /* when we are buffering, don't update the state yet, this will be done
2715      * when buffering finishes */
2716     if (priv->buffering) {
2717       GST_INFO ("Buffering busy, delay state change");
2718     } else {
2719       if (state == GST_STATE_PLAYING)
2720         /* make sure pads are not blocking anymore when going to PLAYING */
2721         media_streams_set_blocked (media, FALSE);
2722
2723       set_state (media, state);
2724
2725       /* and suspend after pause */
2726       if (state == GST_STATE_PAUSED)
2727         gst_rtsp_media_suspend (media);
2728     }
2729   }
2730 }
2731
2732 /**
2733  * gst_rtsp_media_set_pipeline_state:
2734  * @media: a #GstRTSPMedia
2735  * @state: the target state of the pipeline
2736  *
2737  * Set the state of the pipeline managed by @media to @state
2738  */
2739 void
2740 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
2741 {
2742   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2743
2744   g_rec_mutex_lock (&media->priv->state_lock);
2745   media_set_pipeline_state_locked (media, state);
2746   g_rec_mutex_unlock (&media->priv->state_lock);
2747 }
2748
2749 /**
2750  * gst_rtsp_media_set_state:
2751  * @media: a #GstRTSPMedia
2752  * @state: the target state of the media
2753  * @transports: (element-type GstRtspServer.RTSPStreamTransport): a #GPtrArray
2754  * of #GstRTSPStreamTransport pointers
2755  *
2756  * Set the state of @media to @state and for the transports in @transports.
2757  *
2758  * @media must be prepared with gst_rtsp_media_prepare();
2759  *
2760  * Returns: %TRUE on success.
2761  */
2762 gboolean
2763 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
2764     GPtrArray * transports)
2765 {
2766   GstRTSPMediaPrivate *priv;
2767   gint i;
2768   gboolean activate, deactivate, do_state;
2769   gint old_active;
2770
2771   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2772   g_return_val_if_fail (transports != NULL, FALSE);
2773
2774   priv = media->priv;
2775
2776   g_rec_mutex_lock (&priv->state_lock);
2777   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
2778     goto error_status;
2779   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2780       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2781     goto not_prepared;
2782
2783   /* NULL and READY are the same */
2784   if (state == GST_STATE_READY)
2785     state = GST_STATE_NULL;
2786
2787   activate = deactivate = FALSE;
2788
2789   GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
2790       media);
2791
2792   switch (state) {
2793     case GST_STATE_NULL:
2794     case GST_STATE_PAUSED:
2795       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
2796       if (priv->target_state == GST_STATE_PLAYING)
2797         deactivate = TRUE;
2798       break;
2799     case GST_STATE_PLAYING:
2800       /* we're going to PLAYING, activate */
2801       activate = TRUE;
2802       break;
2803     default:
2804       break;
2805   }
2806   old_active = priv->n_active;
2807
2808   for (i = 0; i < transports->len; i++) {
2809     GstRTSPStreamTransport *trans;
2810
2811     /* we need a non-NULL entry in the array */
2812     trans = g_ptr_array_index (transports, i);
2813     if (trans == NULL)
2814       continue;
2815
2816     if (activate) {
2817       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
2818         priv->n_active++;
2819     } else if (deactivate) {
2820       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
2821         priv->n_active--;
2822     }
2823   }
2824
2825   /* we just activated the first media, do the playing state change */
2826   if (old_active == 0 && activate)
2827     do_state = TRUE;
2828   /* if we have no more active media, do the downward state changes */
2829   else if (priv->n_active == 0)
2830     do_state = TRUE;
2831   else
2832     do_state = FALSE;
2833
2834   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
2835       media, do_state);
2836
2837   if (priv->target_state != state) {
2838     if (do_state)
2839       media_set_pipeline_state_locked (media, state);
2840
2841     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
2842         NULL);
2843   }
2844
2845   /* remember where we are */
2846   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
2847           old_active != priv->n_active))
2848     collect_media_stats (media);
2849
2850   g_rec_mutex_unlock (&priv->state_lock);
2851
2852   return TRUE;
2853
2854   /* ERRORS */
2855 not_prepared:
2856   {
2857     GST_WARNING ("media %p was not prepared", media);
2858     g_rec_mutex_unlock (&priv->state_lock);
2859     return FALSE;
2860   }
2861 error_status:
2862   {
2863     GST_WARNING ("media %p in error status while changing to state %d",
2864         media, state);
2865     if (state == GST_STATE_NULL) {
2866       for (i = 0; i < transports->len; i++) {
2867         GstRTSPStreamTransport *trans;
2868
2869         /* we need a non-NULL entry in the array */
2870         trans = g_ptr_array_index (transports, i);
2871         if (trans == NULL)
2872           continue;
2873
2874         gst_rtsp_stream_transport_set_active (trans, FALSE);
2875       }
2876       priv->n_active = 0;
2877     }
2878     g_rec_mutex_unlock (&priv->state_lock);
2879     return FALSE;
2880   }
2881 }