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