rtsp-media: Unblock blocked streams in unprepare
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * 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: (transfer full): 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: (transfer none): 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: (transfer none): 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_profiles (stream, priv->profiles);
1254   gst_rtsp_stream_set_protocols (stream, priv->protocols);
1255
1256   g_ptr_array_add (priv->streams, stream);
1257   g_mutex_unlock (&priv->lock);
1258
1259   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
1260       NULL);
1261
1262   return stream;
1263 }
1264
1265 static void
1266 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
1267 {
1268   GstRTSPMediaPrivate *priv;
1269   GstPad *srcpad;
1270
1271   priv = media->priv;
1272
1273   g_mutex_lock (&priv->lock);
1274   /* remove the ghostpad */
1275   srcpad = gst_rtsp_stream_get_srcpad (stream);
1276   gst_element_remove_pad (priv->element, srcpad);
1277   gst_object_unref (srcpad);
1278   /* now remove the stream */
1279   g_object_ref (stream);
1280   g_ptr_array_remove (priv->streams, stream);
1281   g_mutex_unlock (&priv->lock);
1282
1283   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1284       stream, NULL);
1285
1286   g_object_unref (stream);
1287 }
1288
1289 /**
1290  * gst_rtsp_media_n_streams:
1291  * @media: a #GstRTSPMedia
1292  *
1293  * Get the number of streams in this media.
1294  *
1295  * Returns: The number of streams.
1296  */
1297 guint
1298 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1299 {
1300   GstRTSPMediaPrivate *priv;
1301   guint res;
1302
1303   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1304
1305   priv = media->priv;
1306
1307   g_mutex_lock (&priv->lock);
1308   res = priv->streams->len;
1309   g_mutex_unlock (&priv->lock);
1310
1311   return res;
1312 }
1313
1314 /**
1315  * gst_rtsp_media_get_stream:
1316  * @media: a #GstRTSPMedia
1317  * @idx: the stream index
1318  *
1319  * Retrieve the stream with index @idx from @media.
1320  *
1321  * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
1322  * that index did not exist.
1323  */
1324 GstRTSPStream *
1325 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1326 {
1327   GstRTSPMediaPrivate *priv;
1328   GstRTSPStream *res;
1329
1330   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1331
1332   priv = media->priv;
1333
1334   g_mutex_lock (&priv->lock);
1335   if (idx < priv->streams->len)
1336     res = g_ptr_array_index (priv->streams, idx);
1337   else
1338     res = NULL;
1339   g_mutex_unlock (&priv->lock);
1340
1341   return res;
1342 }
1343
1344 /**
1345  * gst_rtsp_media_find_stream:
1346  * @media: a #GstRTSPMedia
1347  * @control: the control of the stream
1348  *
1349  * Find a stream in @media with @control as the control uri.
1350  *
1351  * Returns: (transfer none): the #GstRTSPStream with control uri @control
1352  * or %NULL when a stream with that control did not exist.
1353  */
1354 GstRTSPStream *
1355 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
1356 {
1357   GstRTSPMediaPrivate *priv;
1358   GstRTSPStream *res;
1359   gint i;
1360
1361   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1362   g_return_val_if_fail (control != NULL, NULL);
1363
1364   priv = media->priv;
1365
1366   res = NULL;
1367
1368   g_mutex_lock (&priv->lock);
1369   for (i = 0; i < priv->streams->len; i++) {
1370     GstRTSPStream *test;
1371
1372     test = g_ptr_array_index (priv->streams, i);
1373     if (gst_rtsp_stream_has_control (test, control)) {
1374       res = test;
1375       break;
1376     }
1377   }
1378   g_mutex_unlock (&priv->lock);
1379
1380   return res;
1381 }
1382
1383 /* called with state-lock */
1384 static gboolean
1385 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
1386     GstRTSPRangeUnit unit)
1387 {
1388   return gst_rtsp_range_convert_units (range, unit);
1389 }
1390
1391 /**
1392  * gst_rtsp_media_get_range_string:
1393  * @media: a #GstRTSPMedia
1394  * @play: for the PLAY request
1395  * @unit: the unit to use for the string
1396  *
1397  * Get the current range as a string. @media must be prepared with
1398  * gst_rtsp_media_prepare ().
1399  *
1400  * Returns: (transfer full): The range as a string, g_free() after usage.
1401  */
1402 gchar *
1403 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
1404     GstRTSPRangeUnit unit)
1405 {
1406   GstRTSPMediaClass *klass;
1407   GstRTSPMediaPrivate *priv;
1408   gchar *result;
1409   GstRTSPTimeRange range;
1410
1411   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1412   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1413   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1414
1415   priv = media->priv;
1416
1417   g_rec_mutex_lock (&priv->state_lock);
1418   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
1419       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
1420     goto not_prepared;
1421
1422   g_mutex_lock (&priv->lock);
1423
1424   /* Update the range value with current position/duration */
1425   collect_media_stats (media);
1426
1427   /* make copy */
1428   range = priv->range;
1429
1430   if (!play && priv->n_active > 0) {
1431     range.min.type = GST_RTSP_TIME_NOW;
1432     range.min.seconds = -1;
1433   }
1434   g_mutex_unlock (&priv->lock);
1435   g_rec_mutex_unlock (&priv->state_lock);
1436
1437   if (!klass->convert_range (media, &range, unit))
1438     goto conversion_failed;
1439
1440   result = gst_rtsp_range_to_string (&range);
1441
1442   return result;
1443
1444   /* ERRORS */
1445 not_prepared:
1446   {
1447     GST_WARNING ("media %p was not prepared", media);
1448     g_rec_mutex_unlock (&priv->state_lock);
1449     return NULL;
1450   }
1451 conversion_failed:
1452   {
1453     GST_WARNING ("range conversion to unit %d failed", unit);
1454     return NULL;
1455   }
1456 }
1457
1458 static void
1459 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
1460 {
1461   gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
1462 }
1463
1464 static void
1465 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
1466 {
1467   GstRTSPMediaPrivate *priv = media->priv;
1468
1469   GST_DEBUG ("media %p set blocked %d", media, blocked);
1470   priv->blocked = blocked;
1471   g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
1472 }
1473
1474 static void
1475 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1476 {
1477   GstRTSPMediaPrivate *priv = media->priv;
1478
1479   g_mutex_lock (&priv->lock);
1480   priv->status = status;
1481   GST_DEBUG ("setting new status to %d", status);
1482   g_cond_broadcast (&priv->cond);
1483   g_mutex_unlock (&priv->lock);
1484 }
1485
1486 /**
1487  * gst_rtsp_media_get_status:
1488  * @media: a #GstRTSPMedia
1489  *
1490  * Get the status of @media. When @media is busy preparing, this function waits
1491  * until @media is prepared or in error.
1492  *
1493  * Returns: the status of @media.
1494  */
1495 GstRTSPMediaStatus
1496 gst_rtsp_media_get_status (GstRTSPMedia * media)
1497 {
1498   GstRTSPMediaPrivate *priv = media->priv;
1499   GstRTSPMediaStatus result;
1500   gint64 end_time;
1501
1502   g_mutex_lock (&priv->lock);
1503   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1504   /* while we are preparing, wait */
1505   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1506     GST_DEBUG ("waiting for status change");
1507     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1508       GST_DEBUG ("timeout, assuming error status");
1509       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1510     }
1511   }
1512   /* could be success or error */
1513   result = priv->status;
1514   GST_DEBUG ("got status %d", result);
1515   g_mutex_unlock (&priv->lock);
1516
1517   return result;
1518 }
1519
1520 /**
1521  * gst_rtsp_media_seek:
1522  * @media: a #GstRTSPMedia
1523  * @range: (transfer none): a #GstRTSPTimeRange
1524  *
1525  * Seek the pipeline of @media to @range. @media must be prepared with
1526  * gst_rtsp_media_prepare().
1527  *
1528  * Returns: %TRUE on success.
1529  */
1530 gboolean
1531 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1532 {
1533   GstRTSPMediaClass *klass;
1534   GstRTSPMediaPrivate *priv;
1535   gboolean res;
1536   GstClockTime start, stop;
1537   GstSeekType start_type, stop_type;
1538   GstQuery *query;
1539
1540   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1541
1542   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1543   g_return_val_if_fail (range != NULL, FALSE);
1544   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1545
1546   priv = media->priv;
1547
1548   g_rec_mutex_lock (&priv->state_lock);
1549   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1550     goto not_prepared;
1551
1552   /* Update the seekable state of the pipeline in case it changed */
1553   query = gst_query_new_seeking (GST_FORMAT_TIME);
1554   if (gst_element_query (priv->pipeline, query)) {
1555     GstFormat format;
1556     gboolean seekable;
1557     gint64 start, end;
1558
1559     gst_query_parse_seeking (query, &format, &seekable, &start, &end);
1560     priv->seekable = seekable;
1561   }
1562   gst_query_unref (query);
1563
1564   if (!priv->seekable)
1565     goto not_seekable;
1566
1567   start_type = stop_type = GST_SEEK_TYPE_NONE;
1568
1569   if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
1570     goto not_supported;
1571   gst_rtsp_range_get_times (range, &start, &stop);
1572
1573   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1574       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1575   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1576       GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1577
1578   if (start != GST_CLOCK_TIME_NONE)
1579     start_type = GST_SEEK_TYPE_SET;
1580
1581   if (priv->range_stop == stop)
1582     stop = GST_CLOCK_TIME_NONE;
1583   else if (stop != GST_CLOCK_TIME_NONE)
1584     stop_type = GST_SEEK_TYPE_SET;
1585
1586   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1587     GstSeekFlags flags;
1588
1589     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1590         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1591
1592     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
1593     if (priv->blocked)
1594       media_streams_set_blocked (media, TRUE);
1595
1596     /* depends on the current playing state of the pipeline. We might need to
1597      * queue this until we get EOS. */
1598     flags = GST_SEEK_FLAG_FLUSH;
1599
1600     /* if range start was not supplied we must continue from current position.
1601      * but since we're doing a flushing seek, let us query the current position
1602      * so we end up at exactly the same position after the seek. */
1603     if (range->min.type == GST_RTSP_TIME_END) { /* Yepp, that's right! */
1604       gint64 position;
1605       gboolean ret = FALSE;
1606
1607       if (klass->query_position)
1608         ret = klass->query_position (media, &position);
1609
1610       if (!ret) {
1611         GST_WARNING ("position query failed");
1612       } else {
1613         GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
1614             GST_TIME_ARGS (position));
1615         start = position;
1616         start_type = GST_SEEK_TYPE_SET;
1617         flags |= GST_SEEK_FLAG_ACCURATE;
1618       }
1619     } else {
1620       /* only set keyframe flag when modifying start */
1621       if (start_type != GST_SEEK_TYPE_NONE)
1622         flags |= GST_SEEK_FLAG_KEY_UNIT;
1623     }
1624
1625     /* FIXME, we only do forwards */
1626     res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1627         flags, start_type, start, stop_type, stop);
1628
1629     /* and block for the seek to complete */
1630     GST_INFO ("done seeking %d", res);
1631     g_rec_mutex_unlock (&priv->state_lock);
1632
1633     /* wait until pipeline is prerolled again, this will also collect stats */
1634     if (!wait_preroll (media))
1635       goto preroll_failed;
1636
1637     g_rec_mutex_lock (&priv->state_lock);
1638     GST_INFO ("prerolled again");
1639   } else {
1640     GST_INFO ("no seek needed");
1641     res = TRUE;
1642   }
1643   g_rec_mutex_unlock (&priv->state_lock);
1644
1645   return res;
1646
1647   /* ERRORS */
1648 not_prepared:
1649   {
1650     g_rec_mutex_unlock (&priv->state_lock);
1651     GST_INFO ("media %p is not prepared", media);
1652     return FALSE;
1653   }
1654 not_seekable:
1655   {
1656     g_rec_mutex_unlock (&priv->state_lock);
1657     GST_INFO ("pipeline is not seekable");
1658     return FALSE;
1659   }
1660 not_supported:
1661   {
1662     g_rec_mutex_unlock (&priv->state_lock);
1663     GST_WARNING ("conversion to npt not supported");
1664     return FALSE;
1665   }
1666 preroll_failed:
1667   {
1668     GST_WARNING ("failed to preroll after seek");
1669     return FALSE;
1670   }
1671 }
1672
1673 static void
1674 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
1675 {
1676   *blocked &= gst_rtsp_stream_is_blocking (stream);
1677 }
1678
1679 static gboolean
1680 media_streams_blocking (GstRTSPMedia * media)
1681 {
1682   gboolean blocking = TRUE;
1683
1684   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
1685       &blocking);
1686
1687   return blocking;
1688 }
1689
1690 static GstStateChangeReturn
1691 set_state (GstRTSPMedia * media, GstState state)
1692 {
1693   GstRTSPMediaPrivate *priv = media->priv;
1694   GstStateChangeReturn ret;
1695
1696   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
1697       media);
1698   ret = gst_element_set_state (priv->pipeline, state);
1699
1700   return ret;
1701 }
1702
1703 static GstStateChangeReturn
1704 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
1705 {
1706   GstRTSPMediaPrivate *priv = media->priv;
1707   GstStateChangeReturn ret;
1708
1709   GST_INFO ("set target state to %s for media %p",
1710       gst_element_state_get_name (state), media);
1711   priv->target_state = state;
1712
1713   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
1714       priv->target_state, NULL);
1715
1716   if (do_state)
1717     ret = set_state (media, state);
1718   else
1719     ret = GST_STATE_CHANGE_SUCCESS;
1720
1721   return ret;
1722 }
1723
1724 /* called with state-lock */
1725 static gboolean
1726 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1727 {
1728   GstRTSPMediaPrivate *priv = media->priv;
1729   GstMessageType type;
1730
1731   type = GST_MESSAGE_TYPE (message);
1732
1733   switch (type) {
1734     case GST_MESSAGE_STATE_CHANGED:
1735       break;
1736     case GST_MESSAGE_BUFFERING:
1737     {
1738       gint percent;
1739
1740       gst_message_parse_buffering (message, &percent);
1741
1742       /* no state management needed for live pipelines */
1743       if (priv->is_live)
1744         break;
1745
1746       if (percent == 100) {
1747         /* a 100% message means buffering is done */
1748         priv->buffering = FALSE;
1749         /* if the desired state is playing, go back */
1750         if (priv->target_state == GST_STATE_PLAYING) {
1751           GST_INFO ("Buffering done, setting pipeline to PLAYING");
1752           set_state (media, GST_STATE_PLAYING);
1753         } else {
1754           GST_INFO ("Buffering done");
1755         }
1756       } else {
1757         /* buffering busy */
1758         if (priv->buffering == FALSE) {
1759           if (priv->target_state == GST_STATE_PLAYING) {
1760             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
1761             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1762             set_state (media, GST_STATE_PAUSED);
1763           } else {
1764             GST_INFO ("Buffering ...");
1765           }
1766         }
1767         priv->buffering = TRUE;
1768       }
1769       break;
1770     }
1771     case GST_MESSAGE_LATENCY:
1772     {
1773       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1774       break;
1775     }
1776     case GST_MESSAGE_ERROR:
1777     {
1778       GError *gerror;
1779       gchar *debug;
1780
1781       gst_message_parse_error (message, &gerror, &debug);
1782       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1783       g_error_free (gerror);
1784       g_free (debug);
1785
1786       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1787       break;
1788     }
1789     case GST_MESSAGE_WARNING:
1790     {
1791       GError *gerror;
1792       gchar *debug;
1793
1794       gst_message_parse_warning (message, &gerror, &debug);
1795       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1796       g_error_free (gerror);
1797       g_free (debug);
1798       break;
1799     }
1800     case GST_MESSAGE_ELEMENT:
1801     {
1802       const GstStructure *s;
1803
1804       s = gst_message_get_structure (message);
1805       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
1806         GST_DEBUG ("media received blocking message");
1807         if (priv->blocked && media_streams_blocking (media)) {
1808           GST_DEBUG ("media is blocking");
1809           collect_media_stats (media);
1810
1811           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1812             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1813         }
1814       }
1815       break;
1816     }
1817     case GST_MESSAGE_STREAM_STATUS:
1818       break;
1819     case GST_MESSAGE_ASYNC_DONE:
1820       if (priv->adding) {
1821         /* when we are dynamically adding pads, the addition of the udpsrc will
1822          * temporarily produce ASYNC_DONE messages. We have to ignore them and
1823          * wait for the final ASYNC_DONE after everything prerolled */
1824         GST_INFO ("%p: ignoring ASYNC_DONE", media);
1825       } else {
1826         GST_INFO ("%p: got ASYNC_DONE", media);
1827         collect_media_stats (media);
1828
1829         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1830           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1831       }
1832       break;
1833     case GST_MESSAGE_EOS:
1834       GST_INFO ("%p: got EOS", media);
1835
1836       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1837         GST_DEBUG ("shutting down after EOS");
1838         finish_unprepare (media);
1839       }
1840       break;
1841     default:
1842       GST_INFO ("%p: got message type %d (%s)", media, type,
1843           gst_message_type_get_name (type));
1844       break;
1845   }
1846   return TRUE;
1847 }
1848
1849 static gboolean
1850 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1851 {
1852   GstRTSPMediaPrivate *priv = media->priv;
1853   GstRTSPMediaClass *klass;
1854   gboolean ret;
1855
1856   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1857
1858   g_rec_mutex_lock (&priv->state_lock);
1859   if (klass->handle_message)
1860     ret = klass->handle_message (media, message);
1861   else
1862     ret = FALSE;
1863   g_rec_mutex_unlock (&priv->state_lock);
1864
1865   return ret;
1866 }
1867
1868 static void
1869 watch_destroyed (GstRTSPMedia * media)
1870 {
1871   GST_DEBUG_OBJECT (media, "source destroyed");
1872   g_object_unref (media);
1873 }
1874
1875 static GstElement *
1876 find_payload_element (GstElement * payloader)
1877 {
1878   GstElement *pay = NULL;
1879
1880   if (GST_IS_BIN (payloader)) {
1881     GstIterator *iter;
1882     GValue item = { 0 };
1883
1884     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
1885     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
1886       GstElement *element = (GstElement *) g_value_get_object (&item);
1887       GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
1888       const gchar *klass;
1889
1890       klass =
1891           gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
1892       if (klass == NULL)
1893         continue;
1894
1895       if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
1896         pay = gst_object_ref (element);
1897         g_value_unset (&item);
1898         break;
1899       }
1900       g_value_unset (&item);
1901     }
1902     gst_iterator_free (iter);
1903   } else {
1904     pay = g_object_ref (payloader);
1905   }
1906
1907   return pay;
1908 }
1909
1910 /* called from streaming threads */
1911 static void
1912 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1913 {
1914   GstRTSPMediaPrivate *priv = media->priv;
1915   GstRTSPStream *stream;
1916   GstElement *pay;
1917
1918   /* find the real payload element */
1919   pay = find_payload_element (element);
1920   stream = gst_rtsp_media_create_stream (media, pay, pad);
1921   gst_object_unref (pay);
1922
1923   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1924
1925   g_rec_mutex_lock (&priv->state_lock);
1926   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
1927     goto not_preparing;
1928
1929   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
1930
1931   /* we will be adding elements below that will cause ASYNC_DONE to be
1932    * posted in the bus. We want to ignore those messages until the
1933    * pipeline really prerolled. */
1934   priv->adding = TRUE;
1935
1936   /* join the element in the PAUSED state because this callback is
1937    * called from the streaming thread and it is PAUSED */
1938   gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1939       priv->rtpbin, GST_STATE_PAUSED);
1940
1941   priv->adding = FALSE;
1942   g_rec_mutex_unlock (&priv->state_lock);
1943
1944   return;
1945
1946   /* ERRORS */
1947 not_preparing:
1948   {
1949     gst_rtsp_media_remove_stream (media, stream);
1950     g_rec_mutex_unlock (&priv->state_lock);
1951     GST_INFO ("ignore pad because we are not preparing");
1952     return;
1953   }
1954 }
1955
1956 static void
1957 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1958 {
1959   GstRTSPMediaPrivate *priv = media->priv;
1960   GstRTSPStream *stream;
1961
1962   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
1963   if (stream == NULL)
1964     return;
1965
1966   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1967
1968   g_rec_mutex_lock (&priv->state_lock);
1969   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1970   g_rec_mutex_unlock (&priv->state_lock);
1971
1972   gst_rtsp_media_remove_stream (media, stream);
1973 }
1974
1975 static void
1976 remove_fakesink (GstRTSPMediaPrivate * priv)
1977 {
1978   GstElement *fakesink;
1979
1980   g_mutex_lock (&priv->lock);
1981   if ((fakesink = priv->fakesink))
1982     gst_object_ref (fakesink);
1983   priv->fakesink = NULL;
1984   g_mutex_unlock (&priv->lock);
1985
1986   if (fakesink) {
1987     gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1988     gst_element_set_state (fakesink, GST_STATE_NULL);
1989     gst_object_unref (fakesink);
1990     GST_INFO ("removed fakesink");
1991   }
1992 }
1993
1994 static void
1995 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1996 {
1997   GstRTSPMediaPrivate *priv = media->priv;
1998
1999   GST_INFO ("no more pads");
2000   remove_fakesink (priv);
2001 }
2002
2003 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
2004
2005 struct _DynPaySignalHandlers
2006 {
2007   gulong pad_added_handler;
2008   gulong pad_removed_handler;
2009   gulong no_more_pads_handler;
2010 };
2011
2012 static gboolean
2013 start_preroll (GstRTSPMedia * media)
2014 {
2015   GstRTSPMediaPrivate *priv = media->priv;
2016   GstStateChangeReturn ret;
2017
2018   GST_INFO ("setting pipeline to PAUSED for media %p", media);
2019   /* first go to PAUSED */
2020   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
2021
2022   switch (ret) {
2023     case GST_STATE_CHANGE_SUCCESS:
2024       GST_INFO ("SUCCESS state change for media %p", media);
2025       priv->seekable = TRUE;
2026       break;
2027     case GST_STATE_CHANGE_ASYNC:
2028       GST_INFO ("ASYNC state change for media %p", media);
2029       priv->seekable = TRUE;
2030       break;
2031     case GST_STATE_CHANGE_NO_PREROLL:
2032       /* we need to go to PLAYING */
2033       GST_INFO ("NO_PREROLL state change: live media %p", media);
2034       /* FIXME we disable seeking for live streams for now. We should perform a
2035        * seeking query in preroll instead */
2036       priv->seekable = FALSE;
2037       priv->is_live = TRUE;
2038       /* start blocked  to make sure nothing goes to the sink */
2039       media_streams_set_blocked (media, TRUE);
2040       ret = set_state (media, GST_STATE_PLAYING);
2041       if (ret == GST_STATE_CHANGE_FAILURE)
2042         goto state_failed;
2043       break;
2044     case GST_STATE_CHANGE_FAILURE:
2045       goto state_failed;
2046   }
2047
2048   return TRUE;
2049
2050 state_failed:
2051   {
2052     GST_WARNING ("failed to preroll pipeline");
2053     return FALSE;
2054   }
2055 }
2056
2057 static gboolean
2058 wait_preroll (GstRTSPMedia * media)
2059 {
2060   GstRTSPMediaStatus status;
2061
2062   GST_DEBUG ("wait to preroll pipeline");
2063
2064   /* wait until pipeline is prerolled */
2065   status = gst_rtsp_media_get_status (media);
2066   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
2067     goto preroll_failed;
2068
2069   return TRUE;
2070
2071 preroll_failed:
2072   {
2073     GST_WARNING ("failed to preroll pipeline");
2074     return FALSE;
2075   }
2076 }
2077
2078 static gboolean
2079 start_prepare (GstRTSPMedia * media)
2080 {
2081   GstRTSPMediaPrivate *priv = media->priv;
2082   guint i;
2083   GList *walk;
2084
2085   /* link streams we already have, other streams might appear when we have
2086    * dynamic elements */
2087   for (i = 0; i < priv->streams->len; i++) {
2088     GstRTSPStream *stream;
2089
2090     stream = g_ptr_array_index (priv->streams, i);
2091
2092     gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2093         priv->rtpbin, GST_STATE_NULL);
2094   }
2095
2096   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2097     GstElement *elem = walk->data;
2098     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
2099
2100     GST_INFO ("adding callbacks for dynamic element %p", elem);
2101
2102     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
2103         (GCallback) pad_added_cb, media);
2104     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
2105         (GCallback) pad_removed_cb, media);
2106     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
2107         (GCallback) no_more_pads_cb, media);
2108
2109     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
2110
2111     /* we add a fakesink here in order to make the state change async. We remove
2112      * the fakesink again in the no-more-pads callback. */
2113     priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
2114     gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
2115   }
2116
2117   if (!start_preroll (media))
2118     goto preroll_failed;
2119
2120   return FALSE;
2121
2122 preroll_failed:
2123   {
2124     GST_WARNING ("failed to preroll pipeline");
2125     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2126     return FALSE;
2127   }
2128 }
2129
2130 /**
2131  * gst_rtsp_media_prepare:
2132  * @media: a #GstRTSPMedia
2133  * @thread: (transfer full): a #GstRTSPThread to run the bus handler or %NULL
2134  *
2135  * Prepare @media for streaming. This function will create the objects
2136  * to manage the streaming. A pipeline must have been set on @media with
2137  * gst_rtsp_media_take_pipeline().
2138  *
2139  * It will preroll the pipeline and collect vital information about the streams
2140  * such as the duration.
2141  *
2142  * Returns: %TRUE on success.
2143  */
2144 gboolean
2145 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2146 {
2147   GstRTSPMediaPrivate *priv;
2148   GstBus *bus;
2149   GSource *source;
2150   GstRTSPMediaClass *klass;
2151
2152   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2153   g_return_val_if_fail (GST_IS_RTSP_THREAD (thread), FALSE);
2154
2155   priv = media->priv;
2156
2157   g_rec_mutex_lock (&priv->state_lock);
2158   priv->prepare_count++;
2159
2160   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
2161       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
2162     goto was_prepared;
2163
2164   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2165     goto wait_status;
2166
2167   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
2168     goto not_unprepared;
2169
2170   if (!priv->reusable && priv->reused)
2171     goto is_reused;
2172
2173   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2174
2175   if (!klass->create_rtpbin)
2176     goto no_create_rtpbin;
2177
2178   priv->rtpbin = klass->create_rtpbin (media);
2179   if (priv->rtpbin != NULL) {
2180     gboolean success = TRUE;
2181
2182     if (klass->setup_rtpbin)
2183       success = klass->setup_rtpbin (media, priv->rtpbin);
2184
2185     if (success == FALSE) {
2186       gst_object_unref (priv->rtpbin);
2187       priv->rtpbin = NULL;
2188     }
2189   }
2190   if (priv->rtpbin == NULL)
2191     goto no_rtpbin;
2192
2193   GST_INFO ("preparing media %p", media);
2194
2195   /* reset some variables */
2196   priv->is_live = FALSE;
2197   priv->seekable = FALSE;
2198   priv->buffering = FALSE;
2199   priv->thread = thread;
2200   /* we're preparing now */
2201   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2202
2203   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
2204
2205   /* add the pipeline bus to our custom mainloop */
2206   priv->source = gst_bus_create_watch (bus);
2207   gst_object_unref (bus);
2208
2209   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
2210       g_object_ref (media), (GDestroyNotify) watch_destroyed);
2211
2212   priv->id = g_source_attach (priv->source, thread->context);
2213
2214   /* add stuff to the bin */
2215   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
2216
2217   /* do remainder in context */
2218   source = g_idle_source_new ();
2219   g_source_set_callback (source, (GSourceFunc) start_prepare, media, NULL);
2220   g_source_attach (source, thread->context);
2221   g_source_unref (source);
2222
2223 wait_status:
2224   g_rec_mutex_unlock (&priv->state_lock);
2225
2226   /* now wait for all pads to be prerolled, FIXME, we should somehow be
2227    * able to do this async so that we don't block the server thread. */
2228   if (!wait_preroll (media))
2229     goto preroll_failed;
2230
2231   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
2232
2233   GST_INFO ("object %p is prerolled", media);
2234
2235   return TRUE;
2236
2237   /* OK */
2238 was_prepared:
2239   {
2240     GST_LOG ("media %p was prepared", media);
2241     /* we are not going to use the giving thread, so stop it. */
2242     gst_rtsp_thread_stop (thread);
2243     g_rec_mutex_unlock (&priv->state_lock);
2244     return TRUE;
2245   }
2246   /* ERRORS */
2247 not_unprepared:
2248   {
2249     GST_WARNING ("media %p was not unprepared", media);
2250     priv->prepare_count--;
2251     g_rec_mutex_unlock (&priv->state_lock);
2252     return FALSE;
2253   }
2254 is_reused:
2255   {
2256     priv->prepare_count--;
2257     g_rec_mutex_unlock (&priv->state_lock);
2258     GST_WARNING ("can not reuse media %p", media);
2259     return FALSE;
2260   }
2261 no_create_rtpbin:
2262   {
2263     priv->prepare_count--;
2264     g_rec_mutex_unlock (&priv->state_lock);
2265     GST_ERROR ("no create_rtpbin function");
2266     g_critical ("no create_rtpbin vmethod function set");
2267     return FALSE;
2268   }
2269 no_rtpbin:
2270   {
2271     priv->prepare_count--;
2272     g_rec_mutex_unlock (&priv->state_lock);
2273     GST_WARNING ("no rtpbin element");
2274     g_warning ("failed to create element 'rtpbin', check your installation");
2275     return FALSE;
2276   }
2277 preroll_failed:
2278   {
2279     GST_WARNING ("failed to preroll pipeline");
2280     gst_rtsp_media_unprepare (media);
2281     return FALSE;
2282   }
2283 }
2284
2285 /* must be called with state-lock */
2286 static void
2287 finish_unprepare (GstRTSPMedia * media)
2288 {
2289   GstRTSPMediaPrivate *priv = media->priv;
2290   gint i;
2291   GList *walk;
2292
2293   GST_DEBUG ("shutting down");
2294
2295   /* release the lock on shutdown, otherwise pad_added_cb might try to
2296    * acquire the lock and then we deadlock */
2297   g_rec_mutex_unlock (&priv->state_lock);
2298   set_state (media, GST_STATE_NULL);
2299   g_rec_mutex_lock (&priv->state_lock);
2300   remove_fakesink (priv);
2301
2302   for (i = 0; i < priv->streams->len; i++) {
2303     GstRTSPStream *stream;
2304
2305     GST_INFO ("Removing elements of stream %d from pipeline", i);
2306
2307     stream = g_ptr_array_index (priv->streams, i);
2308
2309     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
2310   }
2311
2312   /* remove the pad signal handlers */
2313   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2314     GstElement *elem = walk->data;
2315     DynPaySignalHandlers *handlers;
2316
2317     handlers =
2318         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
2319     g_assert (handlers != NULL);
2320
2321     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
2322     g_signal_handler_disconnect (G_OBJECT (elem),
2323         handlers->pad_removed_handler);
2324     g_signal_handler_disconnect (G_OBJECT (elem),
2325         handlers->no_more_pads_handler);
2326
2327     g_slice_free (DynPaySignalHandlers, handlers);
2328   }
2329
2330   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
2331   priv->rtpbin = NULL;
2332
2333   if (priv->nettime)
2334     gst_object_unref (priv->nettime);
2335   priv->nettime = NULL;
2336
2337   priv->reused = TRUE;
2338   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
2339
2340   /* when the media is not reusable, this will effectively unref the media and
2341    * recreate it */
2342   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
2343
2344   /* the source has the last ref to the media */
2345   if (priv->source) {
2346     GST_DEBUG ("destroy source");
2347     g_source_destroy (priv->source);
2348     g_source_unref (priv->source);
2349   }
2350   if (priv->thread) {
2351     GST_DEBUG ("stop thread");
2352     gst_rtsp_thread_stop (priv->thread);
2353   }
2354 }
2355
2356 /* called with state-lock */
2357 static gboolean
2358 default_unprepare (GstRTSPMedia * media)
2359 {
2360   GstRTSPMediaPrivate *priv = media->priv;
2361
2362   if (priv->eos_shutdown) {
2363     GST_DEBUG ("sending EOS for shutdown");
2364     /* ref so that we don't disappear */
2365     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
2366     /* we need to go to playing again for the EOS to propagate, normally in this
2367      * state, nothing is receiving data from us anymore so this is ok. */
2368     set_state (media, GST_STATE_PLAYING);
2369   } else {
2370     finish_unprepare (media);
2371   }
2372   return TRUE;
2373 }
2374
2375 /**
2376  * gst_rtsp_media_unprepare:
2377  * @media: a #GstRTSPMedia
2378  *
2379  * Unprepare @media. After this call, the media should be prepared again before
2380  * it can be used again. If the media is set to be non-reusable, a new instance
2381  * must be created.
2382  *
2383  * Returns: %TRUE on success.
2384  */
2385 gboolean
2386 gst_rtsp_media_unprepare (GstRTSPMedia * media)
2387 {
2388   GstRTSPMediaPrivate *priv;
2389   gboolean success;
2390
2391   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2392
2393   priv = media->priv;
2394
2395   g_rec_mutex_lock (&priv->state_lock);
2396   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
2397     goto was_unprepared;
2398
2399   priv->prepare_count--;
2400   if (priv->prepare_count > 0)
2401     goto is_busy;
2402
2403   GST_INFO ("unprepare media %p", media);
2404   if (priv->blocked)
2405     media_streams_set_blocked (media, FALSE);
2406   set_target_state (media, GST_STATE_NULL, FALSE);
2407   success = TRUE;
2408
2409   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
2410
2411   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
2412     GstRTSPMediaClass *klass;
2413
2414     klass = GST_RTSP_MEDIA_GET_CLASS (media);
2415     if (klass->unprepare)
2416       success = klass->unprepare (media);
2417   } else {
2418     finish_unprepare (media);
2419   }
2420   g_rec_mutex_unlock (&priv->state_lock);
2421
2422   return success;
2423
2424 was_unprepared:
2425   {
2426     g_rec_mutex_unlock (&priv->state_lock);
2427     GST_INFO ("media %p was already unprepared", media);
2428     return TRUE;
2429   }
2430 is_busy:
2431   {
2432     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
2433     g_rec_mutex_unlock (&priv->state_lock);
2434     return TRUE;
2435   }
2436 }
2437
2438 /* should be called with state-lock */
2439 static GstClock *
2440 get_clock_unlocked (GstRTSPMedia * media)
2441 {
2442   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
2443     GST_DEBUG_OBJECT (media, "media was not prepared");
2444     return NULL;
2445   }
2446   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
2447 }
2448
2449 /**
2450  * gst_rtsp_media_get_clock:
2451  * @media: a #GstRTSPMedia
2452  *
2453  * Get the clock that is used by the pipeline in @media.
2454  *
2455  * @media must be prepared before this method returns a valid clock object.
2456  *
2457  * Returns: (transfer full): the #GstClock used by @media. unref after usage.
2458  */
2459 GstClock *
2460 gst_rtsp_media_get_clock (GstRTSPMedia * media)
2461 {
2462   GstClock *clock;
2463   GstRTSPMediaPrivate *priv;
2464
2465   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2466
2467   priv = media->priv;
2468
2469   g_rec_mutex_lock (&priv->state_lock);
2470   clock = get_clock_unlocked (media);
2471   g_rec_mutex_unlock (&priv->state_lock);
2472
2473   return clock;
2474 }
2475
2476 /**
2477  * gst_rtsp_media_get_base_time:
2478  * @media: a #GstRTSPMedia
2479  *
2480  * Get the base_time that is used by the pipeline in @media.
2481  *
2482  * @media must be prepared before this method returns a valid base_time.
2483  *
2484  * Returns: the base_time used by @media.
2485  */
2486 GstClockTime
2487 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
2488 {
2489   GstClockTime result;
2490   GstRTSPMediaPrivate *priv;
2491
2492   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
2493
2494   priv = media->priv;
2495
2496   g_rec_mutex_lock (&priv->state_lock);
2497   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2498     goto not_prepared;
2499
2500   result = gst_element_get_base_time (media->priv->pipeline);
2501   g_rec_mutex_unlock (&priv->state_lock);
2502
2503   return result;
2504
2505   /* ERRORS */
2506 not_prepared:
2507   {
2508     g_rec_mutex_unlock (&priv->state_lock);
2509     GST_DEBUG_OBJECT (media, "media was not prepared");
2510     return GST_CLOCK_TIME_NONE;
2511   }
2512 }
2513
2514 /**
2515  * gst_rtsp_media_get_time_provider:
2516  * @media: a #GstRTSPMedia
2517  * @address: an address or %NULL
2518  * @port: a port or 0
2519  *
2520  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
2521  * will listen on @address and @port for client time requests.
2522  *
2523  * Returns: (transfer full): the #GstNetTimeProvider of @media.
2524  */
2525 GstNetTimeProvider *
2526 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
2527     guint16 port)
2528 {
2529   GstRTSPMediaPrivate *priv;
2530   GstNetTimeProvider *provider = NULL;
2531
2532   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2533
2534   priv = media->priv;
2535
2536   g_rec_mutex_lock (&priv->state_lock);
2537   if (priv->time_provider) {
2538     if ((provider = priv->nettime) == NULL) {
2539       GstClock *clock;
2540
2541       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
2542         provider = gst_net_time_provider_new (clock, address, port);
2543         gst_object_unref (clock);
2544
2545         priv->nettime = provider;
2546       }
2547     }
2548   }
2549   g_rec_mutex_unlock (&priv->state_lock);
2550
2551   if (provider)
2552     gst_object_ref (provider);
2553
2554   return provider;
2555 }
2556
2557 static gboolean
2558 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
2559 {
2560   return gst_rtsp_sdp_from_media (sdp, info, media);
2561 }
2562
2563 /**
2564  * gst_rtsp_media_setup_sdp:
2565  * @media: a #GstRTSPMedia
2566  * @sdp: (transfer none): a #GstSDPMessage
2567  * @info: (transfer none): a #GstSDPInfo
2568  *
2569  * Add @media specific info to @sdp. @info is used to configure the connection
2570  * information in the SDP.
2571  *
2572  * Returns: TRUE on success.
2573  */
2574 gboolean
2575 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
2576     GstSDPInfo * info)
2577 {
2578   GstRTSPMediaPrivate *priv;
2579   GstRTSPMediaClass *klass;
2580   gboolean res;
2581
2582   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2583   g_return_val_if_fail (sdp != NULL, FALSE);
2584   g_return_val_if_fail (info != NULL, FALSE);
2585
2586   priv = media->priv;
2587
2588   g_rec_mutex_lock (&priv->state_lock);
2589
2590   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2591
2592   if (!klass->setup_sdp)
2593     goto no_setup_sdp;
2594
2595   res = klass->setup_sdp (media, sdp, info);
2596
2597   g_rec_mutex_unlock (&priv->state_lock);
2598
2599   return res;
2600
2601   /* ERRORS */
2602 no_setup_sdp:
2603   {
2604     g_rec_mutex_unlock (&priv->state_lock);
2605     GST_ERROR ("no setup_sdp function");
2606     g_critical ("no setup_sdp vmethod function set");
2607     return FALSE;
2608   }
2609 }
2610
2611 /**
2612  * gst_rtsp_media_suspend:
2613  * @media: a #GstRTSPMedia
2614  *
2615  * Suspend @media. The state of the pipeline managed by @media is set to
2616  * GST_STATE_NULL but all streams are kept. @media can be prepared again
2617  * with gst_rtsp_media_unsuspend()
2618  *
2619  * @media must be prepared with gst_rtsp_media_prepare();
2620  *
2621  * Returns: %TRUE on success.
2622  */
2623 gboolean
2624 gst_rtsp_media_suspend (GstRTSPMedia * media)
2625 {
2626   GstRTSPMediaPrivate *priv = media->priv;
2627   GstStateChangeReturn ret;
2628
2629   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2630
2631   GST_FIXME ("suspend for dynamic pipelines needs fixing");
2632
2633   g_rec_mutex_lock (&priv->state_lock);
2634   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2635     goto not_prepared;
2636
2637   /* don't attempt to suspend when something is busy */
2638   if (priv->n_active > 0)
2639     goto done;
2640
2641   switch (priv->suspend_mode) {
2642     case GST_RTSP_SUSPEND_MODE_NONE:
2643       GST_DEBUG ("media %p no suspend", media);
2644       break;
2645     case GST_RTSP_SUSPEND_MODE_PAUSE:
2646       GST_DEBUG ("media %p suspend to PAUSED", media);
2647       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
2648       if (ret == GST_STATE_CHANGE_FAILURE)
2649         goto state_failed;
2650       break;
2651     case GST_RTSP_SUSPEND_MODE_RESET:
2652       GST_DEBUG ("media %p suspend to NULL", media);
2653       ret = set_target_state (media, GST_STATE_NULL, TRUE);
2654       if (ret == GST_STATE_CHANGE_FAILURE)
2655         goto state_failed;
2656       break;
2657     default:
2658       break;
2659   }
2660   /* let the streams do the state changes freely, if any */
2661   media_streams_set_blocked (media, FALSE);
2662   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
2663 done:
2664   g_rec_mutex_unlock (&priv->state_lock);
2665
2666   return TRUE;
2667
2668   /* ERRORS */
2669 not_prepared:
2670   {
2671     g_rec_mutex_unlock (&priv->state_lock);
2672     GST_WARNING ("media %p was not prepared", media);
2673     return FALSE;
2674   }
2675 state_failed:
2676   {
2677     g_rec_mutex_unlock (&priv->state_lock);
2678     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2679     GST_WARNING ("failed changing pipeline's state for media %p", media);
2680     return FALSE;
2681   }
2682 }
2683
2684 /**
2685  * gst_rtsp_media_unsuspend:
2686  * @media: a #GstRTSPMedia
2687  *
2688  * Unsuspend @media if it was in a suspended state. This method does nothing
2689  * when the media was not in the suspended state.
2690  *
2691  * Returns: %TRUE on success.
2692  */
2693 gboolean
2694 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
2695 {
2696   GstRTSPMediaPrivate *priv = media->priv;
2697
2698   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2699
2700   g_rec_mutex_lock (&priv->state_lock);
2701   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2702     goto done;
2703
2704   switch (priv->suspend_mode) {
2705     case GST_RTSP_SUSPEND_MODE_NONE:
2706       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2707       break;
2708     case GST_RTSP_SUSPEND_MODE_PAUSE:
2709       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2710       break;
2711     case GST_RTSP_SUSPEND_MODE_RESET:
2712     {
2713       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2714       if (!start_preroll (media))
2715         goto start_failed;
2716       g_rec_mutex_unlock (&priv->state_lock);
2717
2718       if (!wait_preroll (media))
2719         goto preroll_failed;
2720
2721       g_rec_mutex_lock (&priv->state_lock);
2722     }
2723     default:
2724       break;
2725   }
2726 done:
2727   g_rec_mutex_unlock (&priv->state_lock);
2728
2729   return TRUE;
2730
2731   /* ERRORS */
2732 start_failed:
2733   {
2734     g_rec_mutex_unlock (&priv->state_lock);
2735     GST_WARNING ("failed to preroll pipeline");
2736     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2737     return FALSE;
2738   }
2739 preroll_failed:
2740   {
2741     GST_WARNING ("failed to preroll pipeline");
2742     return FALSE;
2743   }
2744 }
2745
2746 /* must be called with state-lock */
2747 static void
2748 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
2749 {
2750   GstRTSPMediaPrivate *priv = media->priv;
2751
2752   if (state == GST_STATE_NULL) {
2753     gst_rtsp_media_unprepare (media);
2754   } else {
2755     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
2756     set_target_state (media, state, FALSE);
2757     /* when we are buffering, don't update the state yet, this will be done
2758      * when buffering finishes */
2759     if (priv->buffering) {
2760       GST_INFO ("Buffering busy, delay state change");
2761     } else {
2762       if (state == GST_STATE_PLAYING)
2763         /* make sure pads are not blocking anymore when going to PLAYING */
2764         media_streams_set_blocked (media, FALSE);
2765
2766       set_state (media, state);
2767
2768       /* and suspend after pause */
2769       if (state == GST_STATE_PAUSED)
2770         gst_rtsp_media_suspend (media);
2771     }
2772   }
2773 }
2774
2775 /**
2776  * gst_rtsp_media_set_pipeline_state:
2777  * @media: a #GstRTSPMedia
2778  * @state: the target state of the pipeline
2779  *
2780  * Set the state of the pipeline managed by @media to @state
2781  */
2782 void
2783 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
2784 {
2785   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2786
2787   g_rec_mutex_lock (&media->priv->state_lock);
2788   media_set_pipeline_state_locked (media, state);
2789   g_rec_mutex_unlock (&media->priv->state_lock);
2790 }
2791
2792 /**
2793  * gst_rtsp_media_set_state:
2794  * @media: a #GstRTSPMedia
2795  * @state: the target state of the media
2796  * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
2797  * a #GPtrArray of #GstRTSPStreamTransport pointers
2798  *
2799  * Set the state of @media to @state and for the transports in @transports.
2800  *
2801  * @media must be prepared with gst_rtsp_media_prepare();
2802  *
2803  * Returns: %TRUE on success.
2804  */
2805 gboolean
2806 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
2807     GPtrArray * transports)
2808 {
2809   GstRTSPMediaPrivate *priv;
2810   gint i;
2811   gboolean activate, deactivate, do_state;
2812   gint old_active;
2813
2814   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2815   g_return_val_if_fail (transports != NULL, FALSE);
2816
2817   priv = media->priv;
2818
2819   g_rec_mutex_lock (&priv->state_lock);
2820   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
2821     goto error_status;
2822   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2823       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2824     goto not_prepared;
2825
2826   /* NULL and READY are the same */
2827   if (state == GST_STATE_READY)
2828     state = GST_STATE_NULL;
2829
2830   activate = deactivate = FALSE;
2831
2832   GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
2833       media);
2834
2835   switch (state) {
2836     case GST_STATE_NULL:
2837     case GST_STATE_PAUSED:
2838       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
2839       if (priv->target_state == GST_STATE_PLAYING)
2840         deactivate = TRUE;
2841       break;
2842     case GST_STATE_PLAYING:
2843       /* we're going to PLAYING, activate */
2844       activate = TRUE;
2845       break;
2846     default:
2847       break;
2848   }
2849   old_active = priv->n_active;
2850
2851   for (i = 0; i < transports->len; i++) {
2852     GstRTSPStreamTransport *trans;
2853
2854     /* we need a non-NULL entry in the array */
2855     trans = g_ptr_array_index (transports, i);
2856     if (trans == NULL)
2857       continue;
2858
2859     if (activate) {
2860       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
2861         priv->n_active++;
2862     } else if (deactivate) {
2863       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
2864         priv->n_active--;
2865     }
2866   }
2867
2868   /* we just activated the first media, do the playing state change */
2869   if (old_active == 0 && activate)
2870     do_state = TRUE;
2871   /* if we have no more active media, do the downward state changes */
2872   else if (priv->n_active == 0)
2873     do_state = TRUE;
2874   else
2875     do_state = FALSE;
2876
2877   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
2878       media, do_state);
2879
2880   if (priv->target_state != state) {
2881     if (do_state)
2882       media_set_pipeline_state_locked (media, state);
2883
2884     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
2885         NULL);
2886   }
2887
2888   /* remember where we are */
2889   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
2890           old_active != priv->n_active))
2891     collect_media_stats (media);
2892
2893   g_rec_mutex_unlock (&priv->state_lock);
2894
2895   return TRUE;
2896
2897   /* ERRORS */
2898 not_prepared:
2899   {
2900     GST_WARNING ("media %p was not prepared", media);
2901     g_rec_mutex_unlock (&priv->state_lock);
2902     return FALSE;
2903   }
2904 error_status:
2905   {
2906     GST_WARNING ("media %p in error status while changing to state %d",
2907         media, state);
2908     if (state == GST_STATE_NULL) {
2909       for (i = 0; i < transports->len; i++) {
2910         GstRTSPStreamTransport *trans;
2911
2912         /* we need a non-NULL entry in the array */
2913         trans = g_ptr_array_index (transports, i);
2914         if (trans == NULL)
2915           continue;
2916
2917         gst_rtsp_stream_transport_set_active (trans, FALSE);
2918       }
2919       priv->n_active = 0;
2920     }
2921     g_rec_mutex_unlock (&priv->state_lock);
2922     return FALSE;
2923   }
2924 }