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