rtsp-stream: obtain stream position from pad
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  * Copyright (C) 2015 Centricular Ltd
4  *     Author: Sebastian Dröge <sebastian@centricular.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 /**
22  * SECTION:rtsp-media
23  * @short_description: The media pipeline
24  * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession,
25  *     #GstRTSPSessionMedia
26  *
27  * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the
28  * streaming to the clients. The actual data transfer is done by the
29  * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia.
30  *
31  * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the
32  * client does a DESCRIBE or SETUP of a resource.
33  *
34  * A media is created with gst_rtsp_media_new() that takes the element that will
35  * provide the streaming elements. For each of the streams, a new #GstRTSPStream
36  * object needs to be made with the gst_rtsp_media_create_stream() which takes
37  * the payloader element and the source pad that produces the RTP stream.
38  *
39  * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The
40  * prepare method will add rtpbin and sinks and sources to send and receive RTP
41  * and RTCP packets from the clients. Each stream srcpad is connected to an
42  * input into the internal rtpbin.
43  *
44  * It is also possible to dynamically create #GstRTSPStream objects during the
45  * prepare phase. With gst_rtsp_media_get_status() you can check the status of
46  * the prepare phase.
47  *
48  * After the media is prepared, it is ready for streaming. It will usually be
49  * managed in a session with gst_rtsp_session_manage_media(). See
50  * #GstRTSPSession and #GstRTSPSessionMedia.
51  *
52  * The state of the media can be controlled with gst_rtsp_media_set_state ().
53  * Seeking can be done with gst_rtsp_media_seek().
54  *
55  * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
56  * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
57  * cleanly shut down.
58  *
59  * With gst_rtsp_media_set_shared(), the media can be shared between multiple
60  * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
61  * can be prepared again after an unprepare.
62  *
63  * Last reviewed on 2013-07-11 (1.0.0)
64  */
65
66 #include <stdio.h>
67 #include <string.h>
68 #include <stdlib.h>
69
70 #include <gst/app/gstappsrc.h>
71 #include <gst/app/gstappsink.h>
72
73 #include <gst/sdp/gstmikey.h>
74 #include <gst/rtp/gstrtppayloads.h>
75
76 #define AES_128_KEY_LEN 16
77 #define AES_256_KEY_LEN 32
78
79 #define HMAC_32_KEY_LEN 4
80 #define HMAC_80_KEY_LEN 10
81
82 #include "rtsp-media.h"
83
84 #define GST_RTSP_MEDIA_GET_PRIVATE(obj)  \
85      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
86
87 struct _GstRTSPMediaPrivate
88 {
89   GMutex lock;
90   GCond cond;
91
92   /* protected by lock */
93   GstRTSPPermissions *permissions;
94   gboolean shared;
95   gboolean suspend_mode;
96   gboolean reusable;
97   GstRTSPProfile profiles;
98   GstRTSPLowerTrans protocols;
99   gboolean reused;
100   gboolean eos_shutdown;
101   guint buffer_size;
102   GstRTSPAddressPool *pool;
103   gchar *multicast_iface;
104   gboolean blocked;
105   GstRTSPTransportMode transport_mode;
106   gboolean stop_on_disconnect;
107
108   GstElement *element;
109   GRecMutex state_lock;         /* locking order: state lock, lock */
110   GPtrArray *streams;           /* protected by lock */
111   GList *dynamic;               /* protected by lock */
112   GstRTSPMediaStatus status;    /* protected by lock */
113   gint prepare_count;
114   gint n_active;
115   gboolean adding;
116
117   /* the pipeline for the media */
118   GstElement *pipeline;
119   GstElement *fakesink;         /* protected by lock */
120   GSource *source;
121   guint id;
122   GstRTSPThread *thread;
123
124   gboolean time_provider;
125   GstNetTimeProvider *nettime;
126
127   gboolean is_live;
128   GstClockTimeDiff seekable;
129   gboolean buffering;
130   GstState target_state;
131
132   /* RTP session manager */
133   GstElement *rtpbin;
134
135   /* the range of media */
136   GstRTSPTimeRange range;       /* protected by lock */
137   GstClockTime range_start;
138   GstClockTime range_stop;
139
140   GList *payloads;              /* protected by lock */
141   GstClockTime rtx_time;        /* protected by lock */
142   guint latency;                /* protected by lock */
143   GstClock *clock;              /* protected by lock */
144   GstRTSPPublishClockMode publish_clock_mode;
145 };
146
147 #define DEFAULT_SHARED          FALSE
148 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
149 #define DEFAULT_REUSABLE        FALSE
150 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
151 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
152                                         GST_RTSP_LOWER_TRANS_TCP
153 #define DEFAULT_EOS_SHUTDOWN    FALSE
154 #define DEFAULT_BUFFER_SIZE     0x80000
155 #define DEFAULT_TIME_PROVIDER   FALSE
156 #define DEFAULT_LATENCY         200
157 #define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
158 #define DEFAULT_STOP_ON_DISCONNECT TRUE
159
160 /* define to dump received RTCP packets */
161 #undef DUMP_STATS
162
163 enum
164 {
165   PROP_0,
166   PROP_SHARED,
167   PROP_SUSPEND_MODE,
168   PROP_REUSABLE,
169   PROP_PROFILES,
170   PROP_PROTOCOLS,
171   PROP_EOS_SHUTDOWN,
172   PROP_BUFFER_SIZE,
173   PROP_ELEMENT,
174   PROP_TIME_PROVIDER,
175   PROP_LATENCY,
176   PROP_TRANSPORT_MODE,
177   PROP_STOP_ON_DISCONNECT,
178   PROP_CLOCK,
179   PROP_LAST
180 };
181
182 enum
183 {
184   SIGNAL_NEW_STREAM,
185   SIGNAL_REMOVED_STREAM,
186   SIGNAL_PREPARED,
187   SIGNAL_UNPREPARED,
188   SIGNAL_TARGET_STATE,
189   SIGNAL_NEW_STATE,
190   SIGNAL_LAST
191 };
192
193 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
194 #define GST_CAT_DEFAULT rtsp_media_debug
195
196 static void gst_rtsp_media_get_property (GObject * object, guint propid,
197     GValue * value, GParamSpec * pspec);
198 static void gst_rtsp_media_set_property (GObject * object, guint propid,
199     const GValue * value, GParamSpec * pspec);
200 static void gst_rtsp_media_finalize (GObject * obj);
201
202 static gboolean default_handle_message (GstRTSPMedia * media,
203     GstMessage * message);
204 static void finish_unprepare (GstRTSPMedia * media);
205 static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread);
206 static gboolean default_unprepare (GstRTSPMedia * media);
207 static gboolean default_suspend (GstRTSPMedia * media);
208 static gboolean default_unsuspend (GstRTSPMedia * media);
209 static gboolean default_convert_range (GstRTSPMedia * media,
210     GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
211 static gboolean default_query_position (GstRTSPMedia * media,
212     gint64 * position);
213 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
214 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
215 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
216     GstSDPInfo * info);
217 static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
218
219 static gboolean wait_preroll (GstRTSPMedia * media);
220
221 static GstElement *find_payload_element (GstElement * payloader);
222
223 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
224
225 #define C_ENUM(v) ((gint) v)
226
227 GType
228 gst_rtsp_suspend_mode_get_type (void)
229 {
230   static gsize id = 0;
231   static const GEnumValue values[] = {
232     {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
233     {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
234         "pause"},
235     {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
236         "reset"},
237     {0, NULL, NULL}
238   };
239
240   if (g_once_init_enter (&id)) {
241     GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
242     g_once_init_leave (&id, tmp);
243   }
244   return (GType) id;
245 }
246
247 #define C_FLAGS(v) ((guint) v)
248
249 GType
250 gst_rtsp_transport_mode_get_type (void)
251 {
252   static gsize id = 0;
253   static const GFlagsValue values[] = {
254     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
255         "play"},
256     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
257         "record"},
258     {0, NULL, NULL}
259   };
260
261   if (g_once_init_enter (&id)) {
262     GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
263     g_once_init_leave (&id, tmp);
264   }
265   return (GType) id;
266 }
267
268 GType
269 gst_rtsp_publish_clock_mode_get_type (void)
270 {
271   static gsize id = 0;
272   static const GEnumValue values[] = {
273     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
274         "GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
275     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
276           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
277         "clock"},
278     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
279           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
280         "clock-and-offset"},
281     {0, NULL, NULL}
282   };
283
284   if (g_once_init_enter (&id)) {
285     GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
286     g_once_init_leave (&id, tmp);
287   }
288   return (GType) id;
289 }
290
291 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
292
293 static void
294 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
295 {
296   GObjectClass *gobject_class;
297
298   g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
299
300   gobject_class = G_OBJECT_CLASS (klass);
301
302   gobject_class->get_property = gst_rtsp_media_get_property;
303   gobject_class->set_property = gst_rtsp_media_set_property;
304   gobject_class->finalize = gst_rtsp_media_finalize;
305
306   g_object_class_install_property (gobject_class, PROP_SHARED,
307       g_param_spec_boolean ("shared", "Shared",
308           "If this media pipeline can be shared", DEFAULT_SHARED,
309           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
310
311   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
312       g_param_spec_enum ("suspend-mode", "Suspend Mode",
313           "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
314           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
315
316   g_object_class_install_property (gobject_class, PROP_REUSABLE,
317       g_param_spec_boolean ("reusable", "Reusable",
318           "If this media pipeline can be reused after an unprepare",
319           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
320
321   g_object_class_install_property (gobject_class, PROP_PROFILES,
322       g_param_spec_flags ("profiles", "Profiles",
323           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
324           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
325
326   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
327       g_param_spec_flags ("protocols", "Protocols",
328           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
329           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
330
331   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
332       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
333           "Send an EOS event to the pipeline before unpreparing",
334           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
335
336   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
337       g_param_spec_uint ("buffer-size", "Buffer Size",
338           "The kernel UDP buffer size to use", 0, G_MAXUINT,
339           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
340
341   g_object_class_install_property (gobject_class, PROP_ELEMENT,
342       g_param_spec_object ("element", "The Element",
343           "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
344           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
345
346   g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
347       g_param_spec_boolean ("time-provider", "Time Provider",
348           "Use a NetTimeProvider for clients",
349           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
350
351   g_object_class_install_property (gobject_class, PROP_LATENCY,
352       g_param_spec_uint ("latency", "Latency",
353           "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
354           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
355
356   g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
357       g_param_spec_flags ("transport-mode", "Transport Mode",
358           "If this media pipeline can be used for PLAY or RECORD",
359           GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
360           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361
362   g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
363       g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
364           "If this media pipeline should be stopped "
365           "when a client disconnects without TEARDOWN",
366           DEFAULT_STOP_ON_DISCONNECT,
367           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
368
369   g_object_class_install_property (gobject_class, PROP_CLOCK,
370       g_param_spec_object ("clock", "Clock",
371           "Clock to be used by the media pipeline",
372           GST_TYPE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
373
374   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
375       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
376       G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
377       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
378
379   gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
380       g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
381       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
382       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
383       GST_TYPE_RTSP_STREAM);
384
385   gst_rtsp_media_signals[SIGNAL_PREPARED] =
386       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
387       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
388       g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
389
390   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
391       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
392       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
393       g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
394
395   gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
396       g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
397       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
398       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
399
400   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
401       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
402       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
403       g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
404
405   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
406
407   klass->handle_message = default_handle_message;
408   klass->prepare = default_prepare;
409   klass->unprepare = default_unprepare;
410   klass->suspend = default_suspend;
411   klass->unsuspend = default_unsuspend;
412   klass->convert_range = default_convert_range;
413   klass->query_position = default_query_position;
414   klass->query_stop = default_query_stop;
415   klass->create_rtpbin = default_create_rtpbin;
416   klass->setup_sdp = default_setup_sdp;
417   klass->handle_sdp = default_handle_sdp;
418 }
419
420 static void
421 gst_rtsp_media_init (GstRTSPMedia * media)
422 {
423   GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
424
425   media->priv = priv;
426
427   priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
428   g_mutex_init (&priv->lock);
429   g_cond_init (&priv->cond);
430   g_rec_mutex_init (&priv->state_lock);
431
432   priv->shared = DEFAULT_SHARED;
433   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
434   priv->reusable = DEFAULT_REUSABLE;
435   priv->profiles = DEFAULT_PROFILES;
436   priv->protocols = DEFAULT_PROTOCOLS;
437   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
438   priv->buffer_size = DEFAULT_BUFFER_SIZE;
439   priv->time_provider = DEFAULT_TIME_PROVIDER;
440   priv->transport_mode = DEFAULT_TRANSPORT_MODE;
441   priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
442   priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
443 }
444
445 static void
446 gst_rtsp_media_finalize (GObject * obj)
447 {
448   GstRTSPMediaPrivate *priv;
449   GstRTSPMedia *media;
450
451   media = GST_RTSP_MEDIA (obj);
452   priv = media->priv;
453
454   GST_INFO ("finalize media %p", media);
455
456   if (priv->permissions)
457     gst_rtsp_permissions_unref (priv->permissions);
458
459   g_ptr_array_unref (priv->streams);
460
461   g_list_free_full (priv->dynamic, gst_object_unref);
462
463   if (priv->pipeline)
464     gst_object_unref (priv->pipeline);
465   if (priv->nettime)
466     gst_object_unref (priv->nettime);
467   gst_object_unref (priv->element);
468   if (priv->pool)
469     g_object_unref (priv->pool);
470   if (priv->payloads)
471     g_list_free (priv->payloads);
472   g_free (priv->multicast_iface);
473   g_mutex_clear (&priv->lock);
474   g_cond_clear (&priv->cond);
475   g_rec_mutex_clear (&priv->state_lock);
476
477   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
478 }
479
480 static void
481 gst_rtsp_media_get_property (GObject * object, guint propid,
482     GValue * value, GParamSpec * pspec)
483 {
484   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
485
486   switch (propid) {
487     case PROP_ELEMENT:
488       g_value_set_object (value, media->priv->element);
489       break;
490     case PROP_SHARED:
491       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
492       break;
493     case PROP_SUSPEND_MODE:
494       g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
495       break;
496     case PROP_REUSABLE:
497       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
498       break;
499     case PROP_PROFILES:
500       g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
501       break;
502     case PROP_PROTOCOLS:
503       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
504       break;
505     case PROP_EOS_SHUTDOWN:
506       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
507       break;
508     case PROP_BUFFER_SIZE:
509       g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
510       break;
511     case PROP_TIME_PROVIDER:
512       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
513       break;
514     case PROP_LATENCY:
515       g_value_set_uint (value, gst_rtsp_media_get_latency (media));
516       break;
517     case PROP_TRANSPORT_MODE:
518       g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
519       break;
520     case PROP_STOP_ON_DISCONNECT:
521       g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
522       break;
523     case PROP_CLOCK:
524       g_value_take_object (value, gst_rtsp_media_get_clock (media));
525       break;
526     default:
527       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
528   }
529 }
530
531 static void
532 gst_rtsp_media_set_property (GObject * object, guint propid,
533     const GValue * value, GParamSpec * pspec)
534 {
535   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
536
537   switch (propid) {
538     case PROP_ELEMENT:
539       media->priv->element = g_value_get_object (value);
540       gst_object_ref_sink (media->priv->element);
541       break;
542     case PROP_SHARED:
543       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
544       break;
545     case PROP_SUSPEND_MODE:
546       gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
547       break;
548     case PROP_REUSABLE:
549       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
550       break;
551     case PROP_PROFILES:
552       gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
553       break;
554     case PROP_PROTOCOLS:
555       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
556       break;
557     case PROP_EOS_SHUTDOWN:
558       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
559       break;
560     case PROP_BUFFER_SIZE:
561       gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
562       break;
563     case PROP_TIME_PROVIDER:
564       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
565       break;
566     case PROP_LATENCY:
567       gst_rtsp_media_set_latency (media, g_value_get_uint (value));
568       break;
569     case PROP_TRANSPORT_MODE:
570       gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
571       break;
572     case PROP_STOP_ON_DISCONNECT:
573       gst_rtsp_media_set_stop_on_disconnect (media,
574           g_value_get_boolean (value));
575       break;
576     case PROP_CLOCK:
577       gst_rtsp_media_set_clock (media, g_value_get_object (value));
578       break;
579     default:
580       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
581   }
582 }
583
584 typedef struct
585 {
586   gint64 position;
587   gboolean ret;
588 } DoQueryPositionData;
589
590 static void
591 do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
592 {
593   gint64 tmp;
594
595   if (gst_rtsp_stream_query_position (stream, &tmp)) {
596     data->position = MIN (data->position, tmp);
597     data->ret = TRUE;
598   }
599
600   GST_INFO_OBJECT (stream, "media position: %" GST_TIME_FORMAT,
601       GST_TIME_ARGS (data->position));
602 }
603
604 static gboolean
605 default_query_position (GstRTSPMedia * media, gint64 * position)
606 {
607   GstRTSPMediaPrivate *priv;
608   DoQueryPositionData data;
609
610   priv = media->priv;
611
612   data.position = G_MAXINT64;
613   data.ret = FALSE;
614
615   g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
616
617   if (!data.ret)
618     *position = GST_CLOCK_TIME_NONE;
619   else
620     *position = data.position;
621
622   return data.ret;
623 }
624
625 typedef struct
626 {
627   gint64 stop;
628   gboolean ret;
629 } DoQueryStopData;
630
631 static void
632 do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
633 {
634   gint64 tmp = 0;
635
636   if (gst_rtsp_stream_query_stop (stream, &tmp)) {
637     data->stop = MAX (data->stop, tmp);
638     data->ret = TRUE;
639   }
640 }
641
642 static gboolean
643 default_query_stop (GstRTSPMedia * media, gint64 * stop)
644 {
645   GstRTSPMediaPrivate *priv;
646   DoQueryStopData data;
647
648   priv = media->priv;
649
650   data.stop = -1;
651   data.ret = FALSE;
652
653   g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
654
655   *stop = data.stop;
656
657   return data.ret;
658 }
659
660 static GstElement *
661 default_create_rtpbin (GstRTSPMedia * media)
662 {
663   GstElement *rtpbin;
664
665   rtpbin = gst_element_factory_make ("rtpbin", NULL);
666
667   return rtpbin;
668 }
669
670 /* must be called with state lock */
671 static void
672 check_seekable (GstRTSPMedia * media)
673 {
674   GstQuery *query;
675   GstRTSPMediaPrivate *priv = media->priv;
676
677   /* Update the seekable state of the pipeline in case it changed */
678   if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
679     /* TODO: Seeking for RECORD? */
680     priv->seekable = -1;
681   } else {
682     guint i, n = priv->streams->len;
683
684     for (i = 0; i < n; i++) {
685       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
686
687       if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
688           GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
689         priv->seekable = -1;
690         return;
691       }
692     }
693   }
694
695   query = gst_query_new_seeking (GST_FORMAT_TIME);
696   if (gst_element_query (priv->pipeline, query)) {
697     GstFormat format;
698     gboolean seekable;
699     gint64 start, end;
700
701     gst_query_parse_seeking (query, &format, &seekable, &start, &end);
702     priv->seekable = seekable ? G_MAXINT64 : 0.0;
703   }
704
705   gst_query_unref (query);
706 }
707
708
709 /* must be called with state lock */
710 static void
711 collect_media_stats (GstRTSPMedia * media)
712 {
713   GstRTSPMediaPrivate *priv = media->priv;
714   gint64 position = 0, stop = -1;
715
716   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
717       priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
718     return;
719
720   priv->range.unit = GST_RTSP_RANGE_NPT;
721
722   GST_INFO ("collect media stats");
723
724   if (priv->is_live) {
725     priv->range.min.type = GST_RTSP_TIME_NOW;
726     priv->range.min.seconds = -1;
727     priv->range_start = -1;
728     priv->range.max.type = GST_RTSP_TIME_END;
729     priv->range.max.seconds = -1;
730     priv->range_stop = -1;
731   } else {
732     GstRTSPMediaClass *klass;
733     gboolean ret;
734
735     klass = GST_RTSP_MEDIA_GET_CLASS (media);
736
737     /* get the position */
738     ret = FALSE;
739     if (klass->query_position)
740       ret = klass->query_position (media, &position);
741
742     if (!ret) {
743       GST_INFO ("position query failed");
744       position = 0;
745     }
746
747     /* get the current segment stop */
748     ret = FALSE;
749     if (klass->query_stop)
750       ret = klass->query_stop (media, &stop);
751
752     if (!ret) {
753       GST_INFO ("stop query failed");
754       stop = -1;
755     }
756
757     GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
758         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
759
760     if (position == -1) {
761       priv->range.min.type = GST_RTSP_TIME_NOW;
762       priv->range.min.seconds = -1;
763       priv->range_start = -1;
764     } else {
765       priv->range.min.type = GST_RTSP_TIME_SECONDS;
766       priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
767       priv->range_start = position;
768     }
769     if (stop == -1) {
770       priv->range.max.type = GST_RTSP_TIME_END;
771       priv->range.max.seconds = -1;
772       priv->range_stop = -1;
773     } else {
774       priv->range.max.type = GST_RTSP_TIME_SECONDS;
775       priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
776       priv->range_stop = stop;
777     }
778
779     check_seekable (media);
780   }
781 }
782
783 /**
784  * gst_rtsp_media_new:
785  * @element: (transfer full): a #GstElement
786  *
787  * Create a new #GstRTSPMedia instance. @element is the bin element that
788  * provides the different streams. The #GstRTSPMedia object contains the
789  * element to produce RTP data for one or more related (audio/video/..)
790  * streams.
791  *
792  * Ownership is taken of @element.
793  *
794  * Returns: (transfer full): a new #GstRTSPMedia object.
795  */
796 GstRTSPMedia *
797 gst_rtsp_media_new (GstElement * element)
798 {
799   GstRTSPMedia *result;
800
801   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
802
803   result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
804
805   return result;
806 }
807
808 /**
809  * gst_rtsp_media_get_element:
810  * @media: a #GstRTSPMedia
811  *
812  * Get the element that was used when constructing @media.
813  *
814  * Returns: (transfer full): a #GstElement. Unref after usage.
815  */
816 GstElement *
817 gst_rtsp_media_get_element (GstRTSPMedia * media)
818 {
819   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
820
821   return gst_object_ref (media->priv->element);
822 }
823
824 /**
825  * gst_rtsp_media_take_pipeline:
826  * @media: a #GstRTSPMedia
827  * @pipeline: (transfer full): a #GstPipeline
828  *
829  * Set @pipeline as the #GstPipeline for @media. Ownership is
830  * taken of @pipeline.
831  */
832 void
833 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
834 {
835   GstRTSPMediaPrivate *priv;
836   GstElement *old;
837   GstNetTimeProvider *nettime;
838
839   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
840   g_return_if_fail (GST_IS_PIPELINE (pipeline));
841
842   priv = media->priv;
843
844   g_mutex_lock (&priv->lock);
845   old = priv->pipeline;
846   priv->pipeline = GST_ELEMENT_CAST (pipeline);
847   nettime = priv->nettime;
848   priv->nettime = NULL;
849   g_mutex_unlock (&priv->lock);
850
851   if (old)
852     gst_object_unref (old);
853
854   if (nettime)
855     gst_object_unref (nettime);
856
857   gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
858 }
859
860 /**
861  * gst_rtsp_media_set_permissions:
862  * @media: a #GstRTSPMedia
863  * @permissions: (transfer none): a #GstRTSPPermissions
864  *
865  * Set @permissions on @media.
866  */
867 void
868 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
869     GstRTSPPermissions * permissions)
870 {
871   GstRTSPMediaPrivate *priv;
872
873   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
874
875   priv = media->priv;
876
877   g_mutex_lock (&priv->lock);
878   if (priv->permissions)
879     gst_rtsp_permissions_unref (priv->permissions);
880   if ((priv->permissions = permissions))
881     gst_rtsp_permissions_ref (permissions);
882   g_mutex_unlock (&priv->lock);
883 }
884
885 /**
886  * gst_rtsp_media_get_permissions:
887  * @media: a #GstRTSPMedia
888  *
889  * Get the permissions object from @media.
890  *
891  * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage.
892  */
893 GstRTSPPermissions *
894 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
895 {
896   GstRTSPMediaPrivate *priv;
897   GstRTSPPermissions *result;
898
899   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
900
901   priv = media->priv;
902
903   g_mutex_lock (&priv->lock);
904   if ((result = priv->permissions))
905     gst_rtsp_permissions_ref (result);
906   g_mutex_unlock (&priv->lock);
907
908   return result;
909 }
910
911 /**
912  * gst_rtsp_media_set_suspend_mode:
913  * @media: a #GstRTSPMedia
914  * @mode: the new #GstRTSPSuspendMode
915  *
916  * Control how @ media will be suspended after the SDP has been generated and
917  * after a PAUSE request has been performed.
918  *
919  * Media must be unprepared when setting the suspend mode.
920  */
921 void
922 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
923 {
924   GstRTSPMediaPrivate *priv;
925
926   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
927
928   priv = media->priv;
929
930   g_rec_mutex_lock (&priv->state_lock);
931   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
932     goto was_prepared;
933   priv->suspend_mode = mode;
934   g_rec_mutex_unlock (&priv->state_lock);
935
936   return;
937
938   /* ERRORS */
939 was_prepared:
940   {
941     GST_WARNING ("media %p was prepared", media);
942     g_rec_mutex_unlock (&priv->state_lock);
943   }
944 }
945
946 /**
947  * gst_rtsp_media_get_suspend_mode:
948  * @media: a #GstRTSPMedia
949  *
950  * Get how @media will be suspended.
951  *
952  * Returns: #GstRTSPSuspendMode.
953  */
954 GstRTSPSuspendMode
955 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
956 {
957   GstRTSPMediaPrivate *priv;
958   GstRTSPSuspendMode res;
959
960   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
961
962   priv = media->priv;
963
964   g_rec_mutex_lock (&priv->state_lock);
965   res = priv->suspend_mode;
966   g_rec_mutex_unlock (&priv->state_lock);
967
968   return res;
969 }
970
971 /**
972  * gst_rtsp_media_set_shared:
973  * @media: a #GstRTSPMedia
974  * @shared: the new value
975  *
976  * Set or unset if the pipeline for @media can be shared will multiple clients.
977  * When @shared is %TRUE, client requests for this media will share the media
978  * pipeline.
979  */
980 void
981 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
982 {
983   GstRTSPMediaPrivate *priv;
984
985   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
986
987   priv = media->priv;
988
989   g_mutex_lock (&priv->lock);
990   priv->shared = shared;
991   g_mutex_unlock (&priv->lock);
992 }
993
994 /**
995  * gst_rtsp_media_is_shared:
996  * @media: a #GstRTSPMedia
997  *
998  * Check if the pipeline for @media can be shared between multiple clients.
999  *
1000  * Returns: %TRUE if the media can be shared between clients.
1001  */
1002 gboolean
1003 gst_rtsp_media_is_shared (GstRTSPMedia * media)
1004 {
1005   GstRTSPMediaPrivate *priv;
1006   gboolean res;
1007
1008   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1009
1010   priv = media->priv;
1011
1012   g_mutex_lock (&priv->lock);
1013   res = priv->shared;
1014   g_mutex_unlock (&priv->lock);
1015
1016   return res;
1017 }
1018
1019 /**
1020  * gst_rtsp_media_set_reusable:
1021  * @media: a #GstRTSPMedia
1022  * @reusable: the new value
1023  *
1024  * Set or unset if the pipeline for @media can be reused after the pipeline has
1025  * been unprepared.
1026  */
1027 void
1028 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
1029 {
1030   GstRTSPMediaPrivate *priv;
1031
1032   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1033
1034   priv = media->priv;
1035
1036   g_mutex_lock (&priv->lock);
1037   priv->reusable = reusable;
1038   g_mutex_unlock (&priv->lock);
1039 }
1040
1041 /**
1042  * gst_rtsp_media_is_reusable:
1043  * @media: a #GstRTSPMedia
1044  *
1045  * Check if the pipeline for @media can be reused after an unprepare.
1046  *
1047  * Returns: %TRUE if the media can be reused
1048  */
1049 gboolean
1050 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
1051 {
1052   GstRTSPMediaPrivate *priv;
1053   gboolean res;
1054
1055   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1056
1057   priv = media->priv;
1058
1059   g_mutex_lock (&priv->lock);
1060   res = priv->reusable;
1061   g_mutex_unlock (&priv->lock);
1062
1063   return res;
1064 }
1065
1066 static void
1067 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
1068 {
1069   gst_rtsp_stream_set_profiles (stream, *profiles);
1070 }
1071
1072 /**
1073  * gst_rtsp_media_set_profiles:
1074  * @media: a #GstRTSPMedia
1075  * @profiles: the new flags
1076  *
1077  * Configure the allowed lower transport for @media.
1078  */
1079 void
1080 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
1081 {
1082   GstRTSPMediaPrivate *priv;
1083
1084   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1085
1086   priv = media->priv;
1087
1088   g_mutex_lock (&priv->lock);
1089   priv->profiles = profiles;
1090   g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
1091   g_mutex_unlock (&priv->lock);
1092 }
1093
1094 /**
1095  * gst_rtsp_media_get_profiles:
1096  * @media: a #GstRTSPMedia
1097  *
1098  * Get the allowed profiles of @media.
1099  *
1100  * Returns: a #GstRTSPProfile
1101  */
1102 GstRTSPProfile
1103 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
1104 {
1105   GstRTSPMediaPrivate *priv;
1106   GstRTSPProfile res;
1107
1108   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
1109
1110   priv = media->priv;
1111
1112   g_mutex_lock (&priv->lock);
1113   res = priv->profiles;
1114   g_mutex_unlock (&priv->lock);
1115
1116   return res;
1117 }
1118
1119 static void
1120 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
1121 {
1122   gst_rtsp_stream_set_protocols (stream, *protocols);
1123 }
1124
1125 /**
1126  * gst_rtsp_media_set_protocols:
1127  * @media: a #GstRTSPMedia
1128  * @protocols: the new flags
1129  *
1130  * Configure the allowed lower transport for @media.
1131  */
1132 void
1133 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
1134 {
1135   GstRTSPMediaPrivate *priv;
1136
1137   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1138
1139   priv = media->priv;
1140
1141   g_mutex_lock (&priv->lock);
1142   priv->protocols = protocols;
1143   g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
1144   g_mutex_unlock (&priv->lock);
1145 }
1146
1147 /**
1148  * gst_rtsp_media_get_protocols:
1149  * @media: a #GstRTSPMedia
1150  *
1151  * Get the allowed protocols of @media.
1152  *
1153  * Returns: a #GstRTSPLowerTrans
1154  */
1155 GstRTSPLowerTrans
1156 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
1157 {
1158   GstRTSPMediaPrivate *priv;
1159   GstRTSPLowerTrans res;
1160
1161   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
1162       GST_RTSP_LOWER_TRANS_UNKNOWN);
1163
1164   priv = media->priv;
1165
1166   g_mutex_lock (&priv->lock);
1167   res = priv->protocols;
1168   g_mutex_unlock (&priv->lock);
1169
1170   return res;
1171 }
1172
1173 /**
1174  * gst_rtsp_media_set_eos_shutdown:
1175  * @media: a #GstRTSPMedia
1176  * @eos_shutdown: the new value
1177  *
1178  * Set or unset if an EOS event will be sent to the pipeline for @media before
1179  * it is unprepared.
1180  */
1181 void
1182 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
1183 {
1184   GstRTSPMediaPrivate *priv;
1185
1186   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1187
1188   priv = media->priv;
1189
1190   g_mutex_lock (&priv->lock);
1191   priv->eos_shutdown = eos_shutdown;
1192   g_mutex_unlock (&priv->lock);
1193 }
1194
1195 /**
1196  * gst_rtsp_media_is_eos_shutdown:
1197  * @media: a #GstRTSPMedia
1198  *
1199  * Check if the pipeline for @media will send an EOS down the pipeline before
1200  * unpreparing.
1201  *
1202  * Returns: %TRUE if the media will send EOS before unpreparing.
1203  */
1204 gboolean
1205 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
1206 {
1207   GstRTSPMediaPrivate *priv;
1208   gboolean res;
1209
1210   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1211
1212   priv = media->priv;
1213
1214   g_mutex_lock (&priv->lock);
1215   res = priv->eos_shutdown;
1216   g_mutex_unlock (&priv->lock);
1217
1218   return res;
1219 }
1220
1221 /**
1222  * gst_rtsp_media_set_buffer_size:
1223  * @media: a #GstRTSPMedia
1224  * @size: the new value
1225  *
1226  * Set the kernel UDP buffer size.
1227  */
1228 void
1229 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1230 {
1231   GstRTSPMediaPrivate *priv;
1232   guint i;
1233
1234   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1235
1236   GST_LOG_OBJECT (media, "set buffer size %u", size);
1237
1238   priv = media->priv;
1239
1240   g_mutex_lock (&priv->lock);
1241   priv->buffer_size = size;
1242
1243   for (i = 0; i < priv->streams->len; i++) {
1244     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1245     gst_rtsp_stream_set_buffer_size (stream, size);
1246   }
1247   g_mutex_unlock (&priv->lock);
1248 }
1249
1250 /**
1251  * gst_rtsp_media_get_buffer_size:
1252  * @media: a #GstRTSPMedia
1253  *
1254  * Get the kernel UDP buffer size.
1255  *
1256  * Returns: the kernel UDP buffer size.
1257  */
1258 guint
1259 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1260 {
1261   GstRTSPMediaPrivate *priv;
1262   guint res;
1263
1264   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1265
1266   priv = media->priv;
1267
1268   g_mutex_lock (&priv->lock);
1269   res = priv->buffer_size;
1270   g_mutex_unlock (&priv->lock);
1271
1272   return res;
1273 }
1274
1275 /**
1276  * gst_rtsp_media_set_stop_on_disconnect:
1277  * @media: a #GstRTSPMedia
1278  * @stop_on_disconnect: the new value
1279  *
1280  * Set or unset if the pipeline for @media should be stopped when a
1281  * client disconnects without sending TEARDOWN.
1282  */
1283 void
1284 gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
1285     gboolean stop_on_disconnect)
1286 {
1287   GstRTSPMediaPrivate *priv;
1288
1289   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1290
1291   priv = media->priv;
1292
1293   g_mutex_lock (&priv->lock);
1294   priv->stop_on_disconnect = stop_on_disconnect;
1295   g_mutex_unlock (&priv->lock);
1296 }
1297
1298 /**
1299  * gst_rtsp_media_is_stop_on_disconnect:
1300  * @media: a #GstRTSPMedia
1301  *
1302  * Check if the pipeline for @media will be stopped when a client disconnects
1303  * without sending TEARDOWN.
1304  *
1305  * Returns: %TRUE if the media will be stopped when a client disconnects
1306  *     without sending TEARDOWN.
1307  */
1308 gboolean
1309 gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
1310 {
1311   GstRTSPMediaPrivate *priv;
1312   gboolean res;
1313
1314   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
1315
1316   priv = media->priv;
1317
1318   g_mutex_lock (&priv->lock);
1319   res = priv->stop_on_disconnect;
1320   g_mutex_unlock (&priv->lock);
1321
1322   return res;
1323 }
1324
1325 /**
1326  * gst_rtsp_media_set_retransmission_time:
1327  * @media: a #GstRTSPMedia
1328  * @time: the new value
1329  *
1330  * Set the amount of time to store retransmission packets.
1331  */
1332 void
1333 gst_rtsp_media_set_retransmission_time (GstRTSPMedia * media, GstClockTime time)
1334 {
1335   GstRTSPMediaPrivate *priv;
1336   guint i;
1337
1338   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1339
1340   GST_LOG_OBJECT (media, "set retransmission time %" G_GUINT64_FORMAT, time);
1341
1342   priv = media->priv;
1343
1344   g_mutex_lock (&priv->lock);
1345   priv->rtx_time = time;
1346   for (i = 0; i < priv->streams->len; i++) {
1347     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1348
1349     gst_rtsp_stream_set_retransmission_time (stream, time);
1350   }
1351
1352   if (priv->rtpbin)
1353     g_object_set (priv->rtpbin, "do-retransmission", time > 0, NULL);
1354   g_mutex_unlock (&priv->lock);
1355 }
1356
1357 /**
1358  * gst_rtsp_media_get_retransmission_time:
1359  * @media: a #GstRTSPMedia
1360  *
1361  * Get the amount of time to store retransmission data.
1362  *
1363  * Returns: the amount of time to store retransmission data.
1364  */
1365 GstClockTime
1366 gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
1367 {
1368   GstRTSPMediaPrivate *priv;
1369   GstClockTime res;
1370
1371   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1372
1373   priv = media->priv;
1374
1375   g_mutex_lock (&priv->lock);
1376   res = priv->rtx_time;
1377   g_mutex_unlock (&priv->lock);
1378
1379   return res;
1380 }
1381
1382 /**
1383  * gst_rtsp_media_set_latency:
1384  * @media: a #GstRTSPMedia
1385  * @latency: latency in milliseconds
1386  *
1387  * Configure the latency used for receiving media.
1388  */
1389 void
1390 gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
1391 {
1392   GstRTSPMediaPrivate *priv;
1393
1394   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1395
1396   GST_LOG_OBJECT (media, "set latency %ums", latency);
1397
1398   priv = media->priv;
1399
1400   g_mutex_lock (&priv->lock);
1401   priv->latency = latency;
1402   if (priv->rtpbin)
1403     g_object_set (priv->rtpbin, "latency", latency, NULL);
1404   g_mutex_unlock (&priv->lock);
1405 }
1406
1407 /**
1408  * gst_rtsp_media_get_latency:
1409  * @media: a #GstRTSPMedia
1410  *
1411  * Get the latency that is used for receiving media.
1412  *
1413  * Returns: latency in milliseconds
1414  */
1415 guint
1416 gst_rtsp_media_get_latency (GstRTSPMedia * media)
1417 {
1418   GstRTSPMediaPrivate *priv;
1419   guint res;
1420
1421   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1422
1423   priv = media->priv;
1424
1425   g_mutex_lock (&priv->lock);
1426   res = priv->latency;
1427   g_mutex_unlock (&priv->lock);
1428
1429   return res;
1430 }
1431
1432 /**
1433  * gst_rtsp_media_use_time_provider:
1434  * @media: a #GstRTSPMedia
1435  * @time_provider: if a #GstNetTimeProvider should be used
1436  *
1437  * Set @media to provide a #GstNetTimeProvider.
1438  */
1439 void
1440 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1441 {
1442   GstRTSPMediaPrivate *priv;
1443
1444   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1445
1446   priv = media->priv;
1447
1448   g_mutex_lock (&priv->lock);
1449   priv->time_provider = time_provider;
1450   g_mutex_unlock (&priv->lock);
1451 }
1452
1453 /**
1454  * gst_rtsp_media_is_time_provider:
1455  * @media: a #GstRTSPMedia
1456  *
1457  * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1458  *
1459  * Use gst_rtsp_media_get_time_provider() to get the network clock.
1460  *
1461  * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1462  */
1463 gboolean
1464 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1465 {
1466   GstRTSPMediaPrivate *priv;
1467   gboolean res;
1468
1469   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1470
1471   priv = media->priv;
1472
1473   g_mutex_lock (&priv->lock);
1474   res = priv->time_provider;
1475   g_mutex_unlock (&priv->lock);
1476
1477   return res;
1478 }
1479
1480 /**
1481  * gst_rtsp_media_set_clock:
1482  * @media: a #GstRTSPMedia
1483  * @clock: #GstClock to be used
1484  *
1485  * Configure the clock used for the media.
1486  */
1487 void
1488 gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
1489 {
1490   GstRTSPMediaPrivate *priv;
1491
1492   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1493   g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1494
1495   GST_LOG_OBJECT (media, "setting clock %" GST_PTR_FORMAT, clock);
1496
1497   priv = media->priv;
1498
1499   g_mutex_lock (&priv->lock);
1500   if (priv->clock)
1501     gst_object_unref (priv->clock);
1502   priv->clock = clock ? gst_object_ref (clock) : NULL;
1503   if (priv->pipeline) {
1504     if (clock)
1505       gst_pipeline_use_clock (GST_PIPELINE_CAST (priv->pipeline), clock);
1506     else
1507       gst_pipeline_auto_clock (GST_PIPELINE_CAST (priv->pipeline));
1508   }
1509
1510   g_mutex_unlock (&priv->lock);
1511 }
1512
1513 /**
1514  * gst_rtsp_media_set_publish_clock_mode:
1515  * @media: a #GstRTSPMedia
1516  * @mode: the clock publish mode
1517  *
1518  * Sets if and how the media clock should be published according to RFC7273.
1519  *
1520  * Since: 1.8
1521  */
1522 void
1523 gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
1524     GstRTSPPublishClockMode mode)
1525 {
1526   GstRTSPMediaPrivate *priv;
1527   guint i, n;
1528
1529   priv = media->priv;
1530   g_mutex_lock (&priv->lock);
1531   priv->publish_clock_mode = mode;
1532
1533   n = priv->streams->len;
1534   for (i = 0; i < n; i++) {
1535     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1536
1537     gst_rtsp_stream_set_publish_clock_mode (stream, mode);
1538   }
1539   g_mutex_unlock (&priv->lock);
1540 }
1541
1542 /**
1543  * gst_rtsp_media_get_publish_clock_mode:
1544  * @media: a #GstRTSPMedia
1545  *
1546  * Gets if and how the media clock should be published according to RFC7273.
1547  *
1548  * Returns: The GstRTSPPublishClockMode
1549  *
1550  * Since: 1.8
1551  */
1552 GstRTSPPublishClockMode
1553 gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
1554 {
1555   GstRTSPMediaPrivate *priv;
1556   GstRTSPPublishClockMode ret;
1557
1558   priv = media->priv;
1559   g_mutex_lock (&priv->lock);
1560   ret = priv->publish_clock_mode;
1561   g_mutex_unlock (&priv->lock);
1562
1563   return ret;
1564 }
1565
1566 /**
1567  * gst_rtsp_media_set_address_pool:
1568  * @media: a #GstRTSPMedia
1569  * @pool: (transfer none): a #GstRTSPAddressPool
1570  *
1571  * configure @pool to be used as the address pool of @media.
1572  */
1573 void
1574 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1575     GstRTSPAddressPool * pool)
1576 {
1577   GstRTSPMediaPrivate *priv;
1578   GstRTSPAddressPool *old;
1579
1580   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1581
1582   priv = media->priv;
1583
1584   GST_LOG_OBJECT (media, "set address pool %p", pool);
1585
1586   g_mutex_lock (&priv->lock);
1587   if ((old = priv->pool) != pool)
1588     priv->pool = pool ? g_object_ref (pool) : NULL;
1589   else
1590     old = NULL;
1591   g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1592       pool);
1593   g_mutex_unlock (&priv->lock);
1594
1595   if (old)
1596     g_object_unref (old);
1597 }
1598
1599 /**
1600  * gst_rtsp_media_get_address_pool:
1601  * @media: a #GstRTSPMedia
1602  *
1603  * Get the #GstRTSPAddressPool used as the address pool of @media.
1604  *
1605  * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
1606  * usage.
1607  */
1608 GstRTSPAddressPool *
1609 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1610 {
1611   GstRTSPMediaPrivate *priv;
1612   GstRTSPAddressPool *result;
1613
1614   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1615
1616   priv = media->priv;
1617
1618   g_mutex_lock (&priv->lock);
1619   if ((result = priv->pool))
1620     g_object_ref (result);
1621   g_mutex_unlock (&priv->lock);
1622
1623   return result;
1624 }
1625
1626 /**
1627  * gst_rtsp_media_set_multicast_iface:
1628  * @media: a #GstRTSPMedia
1629  * @multicast_iface: (transfer none): a multicast interface name
1630  *
1631  * configure @multicast_iface to be used for @media.
1632  */
1633 void
1634 gst_rtsp_media_set_multicast_iface (GstRTSPMedia * media,
1635     const gchar * multicast_iface)
1636 {
1637   GstRTSPMediaPrivate *priv;
1638   gchar *old;
1639
1640   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1641
1642   priv = media->priv;
1643
1644   GST_LOG_OBJECT (media, "set multicast interface %s", multicast_iface);
1645
1646   g_mutex_lock (&priv->lock);
1647   if ((old = priv->multicast_iface) != multicast_iface)
1648     priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
1649   else
1650     old = NULL;
1651   g_ptr_array_foreach (priv->streams,
1652       (GFunc) gst_rtsp_stream_set_multicast_iface, (gchar *) multicast_iface);
1653   g_mutex_unlock (&priv->lock);
1654
1655   if (old)
1656     g_free (old);
1657 }
1658
1659 /**
1660  * gst_rtsp_media_get_multicast_iface:
1661  * @media: a #GstRTSPMedia
1662  *
1663  * Get the multicast interface used for @media.
1664  *
1665  * Returns: (transfer full): the multicast interface for @media. g_free() after
1666  * usage.
1667  */
1668 gchar *
1669 gst_rtsp_media_get_multicast_iface (GstRTSPMedia * media)
1670 {
1671   GstRTSPMediaPrivate *priv;
1672   gchar *result;
1673
1674   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1675
1676   priv = media->priv;
1677
1678   g_mutex_lock (&priv->lock);
1679   if ((result = priv->multicast_iface))
1680     result = g_strdup (result);
1681   g_mutex_unlock (&priv->lock);
1682
1683   return result;
1684 }
1685
1686 static GList *
1687 _find_payload_types (GstRTSPMedia * media)
1688 {
1689   gint i, n;
1690   GQueue queue = G_QUEUE_INIT;
1691
1692   n = media->priv->streams->len;
1693   for (i = 0; i < n; i++) {
1694     GstRTSPStream *stream = g_ptr_array_index (media->priv->streams, i);
1695     guint pt = gst_rtsp_stream_get_pt (stream);
1696
1697     g_queue_push_tail (&queue, GUINT_TO_POINTER (pt));
1698   }
1699
1700   return queue.head;
1701 }
1702
1703 static guint
1704 _next_available_pt (GList * payloads)
1705 {
1706   guint i;
1707
1708   for (i = 96; i <= 127; i++) {
1709     GList *iter = g_list_find (payloads, GINT_TO_POINTER (i));
1710     if (!iter)
1711       return GPOINTER_TO_UINT (i);
1712   }
1713
1714   return 0;
1715 }
1716
1717 /**
1718  * gst_rtsp_media_collect_streams:
1719  * @media: a #GstRTSPMedia
1720  *
1721  * Find all payloader elements, they should be named pay\%d in the
1722  * element of @media, and create #GstRTSPStreams for them.
1723  *
1724  * Collect all dynamic elements, named dynpay\%d, and add them to
1725  * the list of dynamic elements.
1726  *
1727  * Find all depayloader elements, they should be named depay\%d in the
1728  * element of @media, and create #GstRTSPStreams for them.
1729  */
1730 void
1731 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
1732 {
1733   GstRTSPMediaPrivate *priv;
1734   GstElement *element, *elem;
1735   GstPad *pad;
1736   gint i;
1737   gboolean have_elem;
1738   gboolean more_elem_remaining = TRUE;
1739   GstRTSPTransportMode mode = 0;
1740
1741   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1742
1743   priv = media->priv;
1744   element = priv->element;
1745
1746   have_elem = FALSE;
1747   for (i = 0; more_elem_remaining; i++) {
1748     gchar *name;
1749
1750     more_elem_remaining = FALSE;
1751
1752     name = g_strdup_printf ("pay%d", i);
1753     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1754       GstElement *pay;
1755       GST_INFO ("found stream %d with payloader %p", i, elem);
1756
1757       /* take the pad of the payloader */
1758       pad = gst_element_get_static_pad (elem, "src");
1759
1760       /* find the real payload element in case elem is a GstBin */
1761       pay = find_payload_element (elem);
1762
1763       /* create the stream */
1764       if (pay == NULL) {
1765         GST_WARNING ("could not find real payloader, using bin");
1766         gst_rtsp_media_create_stream (media, elem, pad);
1767       } else {
1768         gst_rtsp_media_create_stream (media, pay, pad);
1769         gst_object_unref (pay);
1770       }
1771
1772       gst_object_unref (pad);
1773       gst_object_unref (elem);
1774
1775       have_elem = TRUE;
1776       more_elem_remaining = TRUE;
1777       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
1778     }
1779     g_free (name);
1780
1781     name = g_strdup_printf ("dynpay%d", i);
1782     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1783       /* a stream that will dynamically create pads to provide RTP packets */
1784       GST_INFO ("found dynamic element %d, %p", i, elem);
1785
1786       g_mutex_lock (&priv->lock);
1787       priv->dynamic = g_list_prepend (priv->dynamic, elem);
1788       g_mutex_unlock (&priv->lock);
1789
1790       have_elem = TRUE;
1791       more_elem_remaining = TRUE;
1792       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
1793     }
1794     g_free (name);
1795
1796     name = g_strdup_printf ("depay%d", i);
1797     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1798       GST_INFO ("found stream %d with depayloader %p", i, elem);
1799
1800       /* take the pad of the payloader */
1801       pad = gst_element_get_static_pad (elem, "sink");
1802       /* create the stream */
1803       gst_rtsp_media_create_stream (media, elem, pad);
1804       gst_object_unref (pad);
1805       gst_object_unref (elem);
1806
1807       have_elem = TRUE;
1808       more_elem_remaining = TRUE;
1809       mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
1810     }
1811     g_free (name);
1812   }
1813
1814   if (have_elem) {
1815     if (priv->transport_mode != mode)
1816       GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
1817           priv->transport_mode, mode);
1818   }
1819 }
1820
1821 /**
1822  * gst_rtsp_media_create_stream:
1823  * @media: a #GstRTSPMedia
1824  * @payloader: a #GstElement
1825  * @pad: a #GstPad
1826  *
1827  * Create a new stream in @media that provides RTP data on @pad.
1828  * @pad should be a pad of an element inside @media->element.
1829  *
1830  * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
1831  * as @media exists.
1832  */
1833 GstRTSPStream *
1834 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
1835     GstPad * pad)
1836 {
1837   GstRTSPMediaPrivate *priv;
1838   GstRTSPStream *stream;
1839   GstPad *ghostpad;
1840   gchar *name;
1841   gint idx;
1842
1843   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1844   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
1845   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1846
1847   priv = media->priv;
1848
1849   g_mutex_lock (&priv->lock);
1850   idx = priv->streams->len;
1851
1852   GST_DEBUG ("media %p: creating stream with index %d", media, idx);
1853
1854   if (GST_PAD_IS_SRC (pad))
1855     name = g_strdup_printf ("src_%u", idx);
1856   else
1857     name = g_strdup_printf ("sink_%u", idx);
1858
1859   ghostpad = gst_ghost_pad_new (name, pad);
1860   gst_pad_set_active (ghostpad, TRUE);
1861   gst_element_add_pad (priv->element, ghostpad);
1862   g_free (name);
1863
1864   stream = gst_rtsp_stream_new (idx, payloader, ghostpad);
1865   if (priv->pool)
1866     gst_rtsp_stream_set_address_pool (stream, priv->pool);
1867   gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface);
1868   gst_rtsp_stream_set_profiles (stream, priv->profiles);
1869   gst_rtsp_stream_set_protocols (stream, priv->protocols);
1870   gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
1871   gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
1872   gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
1873
1874   g_ptr_array_add (priv->streams, stream);
1875
1876   if (GST_PAD_IS_SRC (pad)) {
1877     gint i, n;
1878
1879     if (priv->payloads)
1880       g_list_free (priv->payloads);
1881     priv->payloads = _find_payload_types (media);
1882
1883     n = priv->streams->len;
1884     for (i = 0; i < n; i++) {
1885       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1886       guint rtx_pt = _next_available_pt (priv->payloads);
1887
1888       if (rtx_pt == 0) {
1889         GST_WARNING ("Ran out of space of dynamic payload types");
1890         break;
1891       }
1892
1893       gst_rtsp_stream_set_retransmission_pt (stream, rtx_pt);
1894
1895       priv->payloads =
1896           g_list_append (priv->payloads, GUINT_TO_POINTER (rtx_pt));
1897     }
1898   }
1899   g_mutex_unlock (&priv->lock);
1900
1901   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
1902       NULL);
1903
1904   return stream;
1905 }
1906
1907 static void
1908 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
1909 {
1910   GstRTSPMediaPrivate *priv;
1911   GstPad *srcpad;
1912
1913   priv = media->priv;
1914
1915   g_mutex_lock (&priv->lock);
1916   /* remove the ghostpad */
1917   srcpad = gst_rtsp_stream_get_srcpad (stream);
1918   gst_element_remove_pad (priv->element, srcpad);
1919   gst_object_unref (srcpad);
1920   /* now remove the stream */
1921   g_object_ref (stream);
1922   g_ptr_array_remove (priv->streams, stream);
1923   g_mutex_unlock (&priv->lock);
1924
1925   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1926       stream, NULL);
1927
1928   g_object_unref (stream);
1929 }
1930
1931 /**
1932  * gst_rtsp_media_n_streams:
1933  * @media: a #GstRTSPMedia
1934  *
1935  * Get the number of streams in this media.
1936  *
1937  * Returns: The number of streams.
1938  */
1939 guint
1940 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1941 {
1942   GstRTSPMediaPrivate *priv;
1943   guint res;
1944
1945   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1946
1947   priv = media->priv;
1948
1949   g_mutex_lock (&priv->lock);
1950   res = priv->streams->len;
1951   g_mutex_unlock (&priv->lock);
1952
1953   return res;
1954 }
1955
1956 /**
1957  * gst_rtsp_media_get_stream:
1958  * @media: a #GstRTSPMedia
1959  * @idx: the stream index
1960  *
1961  * Retrieve the stream with index @idx from @media.
1962  *
1963  * Returns: (nullable) (transfer none): the #GstRTSPStream at index
1964  * @idx or %NULL when a stream with that index did not exist.
1965  */
1966 GstRTSPStream *
1967 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1968 {
1969   GstRTSPMediaPrivate *priv;
1970   GstRTSPStream *res;
1971
1972   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1973
1974   priv = media->priv;
1975
1976   g_mutex_lock (&priv->lock);
1977   if (idx < priv->streams->len)
1978     res = g_ptr_array_index (priv->streams, idx);
1979   else
1980     res = NULL;
1981   g_mutex_unlock (&priv->lock);
1982
1983   return res;
1984 }
1985
1986 /**
1987  * gst_rtsp_media_find_stream:
1988  * @media: a #GstRTSPMedia
1989  * @control: the control of the stream
1990  *
1991  * Find a stream in @media with @control as the control uri.
1992  *
1993  * Returns: (nullable) (transfer none): the #GstRTSPStream with
1994  * control uri @control or %NULL when a stream with that control did
1995  * not exist.
1996  */
1997 GstRTSPStream *
1998 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
1999 {
2000   GstRTSPMediaPrivate *priv;
2001   GstRTSPStream *res;
2002   gint i;
2003
2004   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2005   g_return_val_if_fail (control != NULL, NULL);
2006
2007   priv = media->priv;
2008
2009   res = NULL;
2010
2011   g_mutex_lock (&priv->lock);
2012   for (i = 0; i < priv->streams->len; i++) {
2013     GstRTSPStream *test;
2014
2015     test = g_ptr_array_index (priv->streams, i);
2016     if (gst_rtsp_stream_has_control (test, control)) {
2017       res = test;
2018       break;
2019     }
2020   }
2021   g_mutex_unlock (&priv->lock);
2022
2023   return res;
2024 }
2025
2026 /* called with state-lock */
2027 static gboolean
2028 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
2029     GstRTSPRangeUnit unit)
2030 {
2031   return gst_rtsp_range_convert_units (range, unit);
2032 }
2033
2034 /**
2035  * gst_rtsp_media_get_range_string:
2036  * @media: a #GstRTSPMedia
2037  * @play: for the PLAY request
2038  * @unit: the unit to use for the string
2039  *
2040  * Get the current range as a string. @media must be prepared with
2041  * gst_rtsp_media_prepare ().
2042  *
2043  * Returns: (transfer full): The range as a string, g_free() after usage.
2044  */
2045 gchar *
2046 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
2047     GstRTSPRangeUnit unit)
2048 {
2049   GstRTSPMediaClass *klass;
2050   GstRTSPMediaPrivate *priv;
2051   gchar *result;
2052   GstRTSPTimeRange range;
2053
2054   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2055   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2056   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2057
2058   priv = media->priv;
2059
2060   g_rec_mutex_lock (&priv->state_lock);
2061   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2062       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2063     goto not_prepared;
2064
2065   g_mutex_lock (&priv->lock);
2066
2067   /* Update the range value with current position/duration */
2068   collect_media_stats (media);
2069
2070   /* make copy */
2071   range = priv->range;
2072
2073   if (!play && priv->n_active > 0) {
2074     range.min.type = GST_RTSP_TIME_NOW;
2075     range.min.seconds = -1;
2076   }
2077   g_mutex_unlock (&priv->lock);
2078   g_rec_mutex_unlock (&priv->state_lock);
2079
2080   if (!klass->convert_range (media, &range, unit))
2081     goto conversion_failed;
2082
2083   result = gst_rtsp_range_to_string (&range);
2084
2085   return result;
2086
2087   /* ERRORS */
2088 not_prepared:
2089   {
2090     GST_WARNING ("media %p was not prepared", media);
2091     g_rec_mutex_unlock (&priv->state_lock);
2092     return NULL;
2093   }
2094 conversion_failed:
2095   {
2096     GST_WARNING ("range conversion to unit %d failed", unit);
2097     return NULL;
2098   }
2099 }
2100
2101 static void
2102 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
2103 {
2104   gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
2105 }
2106
2107 static void
2108 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
2109 {
2110   GstRTSPMediaPrivate *priv = media->priv;
2111
2112   GST_DEBUG ("media %p set blocked %d", media, blocked);
2113   priv->blocked = blocked;
2114   g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
2115 }
2116
2117 static void
2118 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
2119 {
2120   GstRTSPMediaPrivate *priv = media->priv;
2121
2122   g_mutex_lock (&priv->lock);
2123   priv->status = status;
2124   GST_DEBUG ("setting new status to %d", status);
2125   g_cond_broadcast (&priv->cond);
2126   g_mutex_unlock (&priv->lock);
2127 }
2128
2129 /**
2130  * gst_rtsp_media_get_status:
2131  * @media: a #GstRTSPMedia
2132  *
2133  * Get the status of @media. When @media is busy preparing, this function waits
2134  * until @media is prepared or in error.
2135  *
2136  * Returns: the status of @media.
2137  */
2138 GstRTSPMediaStatus
2139 gst_rtsp_media_get_status (GstRTSPMedia * media)
2140 {
2141   GstRTSPMediaPrivate *priv = media->priv;
2142   GstRTSPMediaStatus result;
2143   gint64 end_time;
2144
2145   g_mutex_lock (&priv->lock);
2146   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
2147   /* while we are preparing, wait */
2148   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
2149     GST_DEBUG ("waiting for status change");
2150     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
2151       GST_DEBUG ("timeout, assuming error status");
2152       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
2153     }
2154   }
2155   /* could be success or error */
2156   result = priv->status;
2157   GST_DEBUG ("got status %d", result);
2158   g_mutex_unlock (&priv->lock);
2159
2160   return result;
2161 }
2162
2163 /**
2164  * gst_rtsp_media_seek_full:
2165  * @media: a #GstRTSPMedia
2166  * @range: (transfer none): a #GstRTSPTimeRange
2167  * @flags: The minimal set of #GstSeekFlags to use
2168  *
2169  * Seek the pipeline of @media to @range. @media must be prepared with
2170  * gst_rtsp_media_prepare().
2171  *
2172  * Returns: %TRUE on success.
2173  */
2174 gboolean
2175 gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
2176     GstSeekFlags flags)
2177 {
2178   GstRTSPMediaClass *klass;
2179   GstRTSPMediaPrivate *priv;
2180   gboolean res;
2181   GstClockTime start, stop;
2182   GstSeekType start_type, stop_type;
2183   gint64 current_position;
2184
2185   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2186
2187   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2188   g_return_val_if_fail (range != NULL, FALSE);
2189   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2190
2191   priv = media->priv;
2192
2193   g_rec_mutex_lock (&priv->state_lock);
2194   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2195     goto not_prepared;
2196
2197   /* Update the seekable state of the pipeline in case it changed */
2198   check_seekable (media);
2199
2200   if (priv->seekable == 0) {
2201     GST_FIXME_OBJECT (media, "Handle going back to 0 for none live"
2202         " not seekable streams.");
2203
2204     goto not_seekable;
2205   } else if (priv->seekable < 0) {
2206     goto not_seekable;
2207   }
2208
2209   start_type = stop_type = GST_SEEK_TYPE_NONE;
2210
2211   if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
2212     goto not_supported;
2213   gst_rtsp_range_get_times (range, &start, &stop);
2214
2215   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2216       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2217   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2218       GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
2219
2220   current_position = -1;
2221   if (klass->query_position)
2222     klass->query_position (media, &current_position);
2223   GST_INFO ("current media position %" GST_TIME_FORMAT,
2224       GST_TIME_ARGS (current_position));
2225
2226   if (start != GST_CLOCK_TIME_NONE)
2227     start_type = GST_SEEK_TYPE_SET;
2228
2229   if (priv->range_stop == stop)
2230     stop = GST_CLOCK_TIME_NONE;
2231   else if (stop != GST_CLOCK_TIME_NONE)
2232     stop_type = GST_SEEK_TYPE_SET;
2233
2234   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
2235     gboolean had_flags = flags != 0;
2236
2237     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2238         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2239
2240     /* depends on the current playing state of the pipeline. We might need to
2241      * queue this until we get EOS. */
2242     if (had_flags)
2243       flags |= GST_SEEK_FLAG_FLUSH;
2244     else
2245       flags = GST_SEEK_FLAG_FLUSH;
2246
2247
2248     /* if range start was not supplied we must continue from current position.
2249      * but since we're doing a flushing seek, let us query the current position
2250      * so we end up at exactly the same position after the seek. */
2251     if (range->min.type == GST_RTSP_TIME_END) { /* Yepp, that's right! */
2252       if (current_position == -1) {
2253         GST_WARNING ("current position unknown");
2254       } else {
2255         GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
2256             GST_TIME_ARGS (current_position));
2257         start = current_position;
2258         start_type = GST_SEEK_TYPE_SET;
2259         if (!had_flags)
2260           flags |= GST_SEEK_FLAG_ACCURATE;
2261       }
2262     } else {
2263       /* only set keyframe flag when modifying start */
2264       if (start_type != GST_SEEK_TYPE_NONE)
2265         if (!had_flags)
2266           flags |= GST_SEEK_FLAG_KEY_UNIT;
2267     }
2268
2269     if (start == current_position && stop_type == GST_SEEK_TYPE_NONE) {
2270       GST_DEBUG ("not seeking because no position change");
2271       res = TRUE;
2272     } else {
2273       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2274       if (priv->blocked)
2275         media_streams_set_blocked (media, TRUE);
2276
2277       /* FIXME, we only do forwards playback, no trick modes yet */
2278       res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
2279           flags, start_type, start, stop_type, stop);
2280
2281       /* and block for the seek to complete */
2282       GST_INFO ("done seeking %d", res);
2283       if (!res)
2284         goto seek_failed;
2285
2286       g_rec_mutex_unlock (&priv->state_lock);
2287
2288       /* wait until pipeline is prerolled again, this will also collect stats */
2289       if (!wait_preroll (media))
2290         goto preroll_failed;
2291
2292       g_rec_mutex_lock (&priv->state_lock);
2293       GST_INFO ("prerolled again");
2294     }
2295   } else {
2296     GST_INFO ("no seek needed");
2297     res = TRUE;
2298   }
2299   g_rec_mutex_unlock (&priv->state_lock);
2300
2301   return res;
2302
2303   /* ERRORS */
2304 not_prepared:
2305   {
2306     g_rec_mutex_unlock (&priv->state_lock);
2307     GST_INFO ("media %p is not prepared", media);
2308     return FALSE;
2309   }
2310 not_seekable:
2311   {
2312     g_rec_mutex_unlock (&priv->state_lock);
2313     GST_INFO ("pipeline is not seekable");
2314     return FALSE;
2315   }
2316 not_supported:
2317   {
2318     g_rec_mutex_unlock (&priv->state_lock);
2319     GST_WARNING ("conversion to npt not supported");
2320     return FALSE;
2321   }
2322 seek_failed:
2323   {
2324     g_rec_mutex_unlock (&priv->state_lock);
2325     GST_INFO ("seeking failed");
2326     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2327     return FALSE;
2328   }
2329 preroll_failed:
2330   {
2331     GST_WARNING ("failed to preroll after seek");
2332     return FALSE;
2333   }
2334 }
2335
2336
2337 /**
2338  * gst_rtsp_media_seek:
2339  * @media: a #GstRTSPMedia
2340  * @range: (transfer none): a #GstRTSPTimeRange
2341  *
2342  * Seek the pipeline of @media to @range. @media must be prepared with
2343  * gst_rtsp_media_prepare().
2344  *
2345  * Returns: %TRUE on success.
2346  */
2347 gboolean
2348 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
2349 {
2350   return gst_rtsp_media_seek_full (media, range, 0);
2351 }
2352
2353
2354 static void
2355 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
2356 {
2357   *blocked &= gst_rtsp_stream_is_blocking (stream);
2358 }
2359
2360 static gboolean
2361 media_streams_blocking (GstRTSPMedia * media)
2362 {
2363   gboolean blocking = TRUE;
2364
2365   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
2366       &blocking);
2367
2368   return blocking;
2369 }
2370
2371 static GstStateChangeReturn
2372 set_state (GstRTSPMedia * media, GstState state)
2373 {
2374   GstRTSPMediaPrivate *priv = media->priv;
2375   GstStateChangeReturn ret;
2376
2377   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
2378       media);
2379   ret = gst_element_set_state (priv->pipeline, state);
2380
2381   return ret;
2382 }
2383
2384 static GstStateChangeReturn
2385 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
2386 {
2387   GstRTSPMediaPrivate *priv = media->priv;
2388   GstStateChangeReturn ret;
2389
2390   GST_INFO ("set target state to %s for media %p",
2391       gst_element_state_get_name (state), media);
2392   priv->target_state = state;
2393
2394   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
2395       priv->target_state, NULL);
2396
2397   if (do_state)
2398     ret = set_state (media, state);
2399   else
2400     ret = GST_STATE_CHANGE_SUCCESS;
2401
2402   return ret;
2403 }
2404
2405 /* called with state-lock */
2406 static gboolean
2407 default_handle_message (GstRTSPMedia * media, GstMessage * message)
2408 {
2409   GstRTSPMediaPrivate *priv = media->priv;
2410   GstMessageType type;
2411
2412   type = GST_MESSAGE_TYPE (message);
2413
2414   switch (type) {
2415     case GST_MESSAGE_STATE_CHANGED:
2416     {
2417       GstState old, new, pending;
2418
2419       if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
2420         break;
2421
2422       gst_message_parse_state_changed (message, &old, &new, &pending);
2423
2424       GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
2425           gst_element_state_get_name (old), gst_element_state_get_name (new),
2426           gst_element_state_get_name (pending));
2427       if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)
2428           && old == GST_STATE_READY && new == GST_STATE_PAUSED) {
2429         GST_INFO ("%p: went to PAUSED, prepared now", media);
2430         collect_media_stats (media);
2431
2432         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2433           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2434       }
2435
2436       break;
2437     }
2438     case GST_MESSAGE_BUFFERING:
2439     {
2440       gint percent;
2441
2442       gst_message_parse_buffering (message, &percent);
2443
2444       /* no state management needed for live pipelines */
2445       if (priv->is_live)
2446         break;
2447
2448       if (percent == 100) {
2449         /* a 100% message means buffering is done */
2450         priv->buffering = FALSE;
2451         /* if the desired state is playing, go back */
2452         if (priv->target_state == GST_STATE_PLAYING) {
2453           GST_INFO ("Buffering done, setting pipeline to PLAYING");
2454           set_state (media, GST_STATE_PLAYING);
2455         } else {
2456           GST_INFO ("Buffering done");
2457         }
2458       } else {
2459         /* buffering busy */
2460         if (priv->buffering == FALSE) {
2461           if (priv->target_state == GST_STATE_PLAYING) {
2462             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
2463             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
2464             set_state (media, GST_STATE_PAUSED);
2465           } else {
2466             GST_INFO ("Buffering ...");
2467           }
2468         }
2469         priv->buffering = TRUE;
2470       }
2471       break;
2472     }
2473     case GST_MESSAGE_LATENCY:
2474     {
2475       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
2476       break;
2477     }
2478     case GST_MESSAGE_ERROR:
2479     {
2480       GError *gerror;
2481       gchar *debug;
2482
2483       gst_message_parse_error (message, &gerror, &debug);
2484       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
2485       g_error_free (gerror);
2486       g_free (debug);
2487
2488       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2489       break;
2490     }
2491     case GST_MESSAGE_WARNING:
2492     {
2493       GError *gerror;
2494       gchar *debug;
2495
2496       gst_message_parse_warning (message, &gerror, &debug);
2497       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
2498       g_error_free (gerror);
2499       g_free (debug);
2500       break;
2501     }
2502     case GST_MESSAGE_ELEMENT:
2503     {
2504       const GstStructure *s;
2505
2506       s = gst_message_get_structure (message);
2507       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
2508         GST_DEBUG ("media received blocking message");
2509         if (priv->blocked && media_streams_blocking (media)) {
2510           GST_DEBUG ("media is blocking");
2511           collect_media_stats (media);
2512
2513           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2514             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2515         }
2516       }
2517       break;
2518     }
2519     case GST_MESSAGE_STREAM_STATUS:
2520       break;
2521     case GST_MESSAGE_ASYNC_DONE:
2522       if (priv->adding) {
2523         /* when we are dynamically adding pads, the addition of the udpsrc will
2524          * temporarily produce ASYNC_DONE messages. We have to ignore them and
2525          * wait for the final ASYNC_DONE after everything prerolled */
2526         GST_INFO ("%p: ignoring ASYNC_DONE", media);
2527       } else {
2528         GST_INFO ("%p: got ASYNC_DONE", media);
2529         collect_media_stats (media);
2530
2531         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2532           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2533       }
2534       break;
2535     case GST_MESSAGE_EOS:
2536       GST_INFO ("%p: got EOS", media);
2537
2538       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
2539         GST_DEBUG ("shutting down after EOS");
2540         finish_unprepare (media);
2541       }
2542       break;
2543     default:
2544       GST_INFO ("%p: got message type %d (%s)", media, type,
2545           gst_message_type_get_name (type));
2546       break;
2547   }
2548   return TRUE;
2549 }
2550
2551 static gboolean
2552 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
2553 {
2554   GstRTSPMediaPrivate *priv = media->priv;
2555   GstRTSPMediaClass *klass;
2556   gboolean ret;
2557
2558   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2559
2560   g_rec_mutex_lock (&priv->state_lock);
2561   if (klass->handle_message)
2562     ret = klass->handle_message (media, message);
2563   else
2564     ret = FALSE;
2565   g_rec_mutex_unlock (&priv->state_lock);
2566
2567   return ret;
2568 }
2569
2570 static void
2571 watch_destroyed (GstRTSPMedia * media)
2572 {
2573   GST_DEBUG_OBJECT (media, "source destroyed");
2574   g_object_unref (media);
2575 }
2576
2577 static GstElement *
2578 find_payload_element (GstElement * payloader)
2579 {
2580   GstElement *pay = NULL;
2581
2582   if (GST_IS_BIN (payloader)) {
2583     GstIterator *iter;
2584     GValue item = { 0 };
2585
2586     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
2587     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
2588       GstElement *element = (GstElement *) g_value_get_object (&item);
2589       GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
2590       const gchar *klass;
2591
2592       klass =
2593           gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
2594       if (klass == NULL)
2595         continue;
2596
2597       if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
2598         pay = gst_object_ref (element);
2599         g_value_unset (&item);
2600         break;
2601       }
2602       g_value_unset (&item);
2603     }
2604     gst_iterator_free (iter);
2605   } else {
2606     pay = g_object_ref (payloader);
2607   }
2608
2609   return pay;
2610 }
2611
2612 /* called from streaming threads */
2613 static void
2614 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
2615 {
2616   GstRTSPMediaPrivate *priv = media->priv;
2617   GstRTSPStream *stream;
2618   GstElement *pay;
2619
2620   /* find the real payload element */
2621   pay = find_payload_element (element);
2622   stream = gst_rtsp_media_create_stream (media, pay, pad);
2623   gst_object_unref (pay);
2624
2625   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
2626
2627   g_rec_mutex_lock (&priv->state_lock);
2628   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
2629     goto not_preparing;
2630
2631   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
2632
2633   /* we will be adding elements below that will cause ASYNC_DONE to be
2634    * posted in the bus. We want to ignore those messages until the
2635    * pipeline really prerolled. */
2636   priv->adding = TRUE;
2637
2638   /* join the element in the PAUSED state because this callback is
2639    * called from the streaming thread and it is PAUSED */
2640   if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2641           priv->rtpbin, GST_STATE_PAUSED)) {
2642     GST_WARNING ("failed to join bin element");
2643   }
2644
2645   priv->adding = FALSE;
2646   g_rec_mutex_unlock (&priv->state_lock);
2647
2648   return;
2649
2650   /* ERRORS */
2651 not_preparing:
2652   {
2653     gst_rtsp_media_remove_stream (media, stream);
2654     g_rec_mutex_unlock (&priv->state_lock);
2655     GST_INFO ("ignore pad because we are not preparing");
2656     return;
2657   }
2658 }
2659
2660 static void
2661 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
2662 {
2663   GstRTSPMediaPrivate *priv = media->priv;
2664   GstRTSPStream *stream;
2665
2666   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
2667   if (stream == NULL)
2668     return;
2669
2670   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
2671
2672   g_rec_mutex_lock (&priv->state_lock);
2673   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
2674   g_rec_mutex_unlock (&priv->state_lock);
2675
2676   gst_rtsp_media_remove_stream (media, stream);
2677 }
2678
2679 static void
2680 remove_fakesink (GstRTSPMediaPrivate * priv)
2681 {
2682   GstElement *fakesink;
2683
2684   g_mutex_lock (&priv->lock);
2685   if ((fakesink = priv->fakesink))
2686     gst_object_ref (fakesink);
2687   priv->fakesink = NULL;
2688   g_mutex_unlock (&priv->lock);
2689
2690   if (fakesink) {
2691     gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
2692     gst_element_set_state (fakesink, GST_STATE_NULL);
2693     gst_object_unref (fakesink);
2694     GST_INFO ("removed fakesink");
2695   }
2696 }
2697
2698 static void
2699 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
2700 {
2701   GstRTSPMediaPrivate *priv = media->priv;
2702
2703   GST_INFO ("no more pads");
2704   remove_fakesink (priv);
2705 }
2706
2707 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
2708
2709 struct _DynPaySignalHandlers
2710 {
2711   gulong pad_added_handler;
2712   gulong pad_removed_handler;
2713   gulong no_more_pads_handler;
2714 };
2715
2716 static gboolean
2717 start_preroll (GstRTSPMedia * media)
2718 {
2719   GstRTSPMediaPrivate *priv = media->priv;
2720   GstStateChangeReturn ret;
2721
2722   GST_INFO ("setting pipeline to PAUSED for media %p", media);
2723   /* first go to PAUSED */
2724   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
2725
2726   switch (ret) {
2727     case GST_STATE_CHANGE_SUCCESS:
2728       GST_INFO ("SUCCESS state change for media %p", media);
2729       break;
2730     case GST_STATE_CHANGE_ASYNC:
2731       GST_INFO ("ASYNC state change for media %p", media);
2732       break;
2733     case GST_STATE_CHANGE_NO_PREROLL:
2734       /* we need to go to PLAYING */
2735       GST_INFO ("NO_PREROLL state change: live media %p", media);
2736       /* FIXME we disable seeking for live streams for now. We should perform a
2737        * seeking query in preroll instead */
2738       priv->seekable = -1;
2739       priv->is_live = TRUE;
2740       if (!(priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
2741         /* start blocked  to make sure nothing goes to the sink */
2742         media_streams_set_blocked (media, TRUE);
2743       }
2744       ret = set_state (media, GST_STATE_PLAYING);
2745       if (ret == GST_STATE_CHANGE_FAILURE)
2746         goto state_failed;
2747       break;
2748     case GST_STATE_CHANGE_FAILURE:
2749       goto state_failed;
2750   }
2751
2752   return TRUE;
2753
2754 state_failed:
2755   {
2756     GST_WARNING ("failed to preroll pipeline");
2757     return FALSE;
2758   }
2759 }
2760
2761 static gboolean
2762 wait_preroll (GstRTSPMedia * media)
2763 {
2764   GstRTSPMediaStatus status;
2765
2766   GST_DEBUG ("wait to preroll pipeline");
2767
2768   /* wait until pipeline is prerolled */
2769   status = gst_rtsp_media_get_status (media);
2770   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
2771     goto preroll_failed;
2772
2773   return TRUE;
2774
2775 preroll_failed:
2776   {
2777     GST_WARNING ("failed to preroll pipeline");
2778     return FALSE;
2779   }
2780 }
2781
2782 static GstElement *
2783 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
2784 {
2785   GstRTSPMediaPrivate *priv = media->priv;
2786   GstRTSPStream *stream = NULL;
2787   guint i;
2788
2789   g_mutex_lock (&priv->lock);
2790   for (i = 0; i < priv->streams->len; i++) {
2791     stream = g_ptr_array_index (priv->streams, i);
2792
2793     if (sessid == gst_rtsp_stream_get_index (stream))
2794       break;
2795   }
2796   g_mutex_unlock (&priv->lock);
2797
2798   return gst_rtsp_stream_request_aux_sender (stream, sessid);
2799 }
2800
2801 static gboolean
2802 start_prepare (GstRTSPMedia * media)
2803 {
2804   GstRTSPMediaPrivate *priv = media->priv;
2805   guint i;
2806   GList *walk;
2807
2808   g_rec_mutex_lock (&priv->state_lock);
2809   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
2810     goto no_longer_preparing;
2811
2812   /* link streams we already have, other streams might appear when we have
2813    * dynamic elements */
2814   for (i = 0; i < priv->streams->len; i++) {
2815     GstRTSPStream *stream;
2816
2817     stream = g_ptr_array_index (priv->streams, i);
2818
2819     if (priv->rtx_time > 0) {
2820       /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
2821       g_signal_connect (priv->rtpbin, "request-aux-sender",
2822           (GCallback) request_aux_sender, media);
2823     }
2824
2825     if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2826             priv->rtpbin, GST_STATE_NULL)) {
2827       goto join_bin_failed;
2828     }
2829   }
2830
2831   if (priv->rtpbin)
2832     g_object_set (priv->rtpbin, "do-retransmission", priv->rtx_time > 0, NULL);
2833
2834   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2835     GstElement *elem = walk->data;
2836     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
2837
2838     GST_INFO ("adding callbacks for dynamic element %p", elem);
2839
2840     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
2841         (GCallback) pad_added_cb, media);
2842     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
2843         (GCallback) pad_removed_cb, media);
2844     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
2845         (GCallback) no_more_pads_cb, media);
2846
2847     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
2848
2849     if (!priv->fakesink) {
2850       /* we add a fakesink here in order to make the state change async. We remove
2851        * the fakesink again in the no-more-pads callback. */
2852       priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
2853       gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
2854     }
2855   }
2856
2857   if (!start_preroll (media))
2858     goto preroll_failed;
2859
2860   g_rec_mutex_unlock (&priv->state_lock);
2861
2862   return FALSE;
2863
2864 no_longer_preparing:
2865   {
2866     GST_INFO ("media is no longer preparing");
2867     g_rec_mutex_unlock (&priv->state_lock);
2868     return FALSE;
2869   }
2870 join_bin_failed:
2871   {
2872     GST_WARNING ("failed to join bin element");
2873     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2874     g_rec_mutex_unlock (&priv->state_lock);
2875     return FALSE;
2876   }
2877 preroll_failed:
2878   {
2879     GST_WARNING ("failed to preroll pipeline");
2880     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2881     g_rec_mutex_unlock (&priv->state_lock);
2882     return FALSE;
2883   }
2884 }
2885
2886 static gboolean
2887 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2888 {
2889   GstRTSPMediaPrivate *priv;
2890   GstRTSPMediaClass *klass;
2891   GstBus *bus;
2892   GMainContext *context;
2893   GSource *source;
2894
2895   priv = media->priv;
2896
2897   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2898
2899   if (!klass->create_rtpbin)
2900     goto no_create_rtpbin;
2901
2902   priv->rtpbin = klass->create_rtpbin (media);
2903   if (priv->rtpbin != NULL) {
2904     gboolean success = TRUE;
2905
2906     g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
2907
2908     if (klass->setup_rtpbin)
2909       success = klass->setup_rtpbin (media, priv->rtpbin);
2910
2911     if (success == FALSE) {
2912       gst_object_unref (priv->rtpbin);
2913       priv->rtpbin = NULL;
2914     }
2915   }
2916   if (priv->rtpbin == NULL)
2917     goto no_rtpbin;
2918
2919   priv->thread = thread;
2920   context = (thread != NULL) ? (thread->context) : NULL;
2921
2922   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
2923
2924   /* add the pipeline bus to our custom mainloop */
2925   priv->source = gst_bus_create_watch (bus);
2926   gst_object_unref (bus);
2927
2928   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
2929       g_object_ref (media), (GDestroyNotify) watch_destroyed);
2930
2931   priv->id = g_source_attach (priv->source, context);
2932
2933   /* add stuff to the bin */
2934   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
2935
2936   /* do remainder in context */
2937   source = g_idle_source_new ();
2938   g_source_set_callback (source, (GSourceFunc) start_prepare,
2939       g_object_ref (media), (GDestroyNotify) g_object_unref);
2940   g_source_attach (source, context);
2941   g_source_unref (source);
2942
2943   return TRUE;
2944
2945   /* ERRORS */
2946 no_create_rtpbin:
2947   {
2948     GST_ERROR ("no create_rtpbin function");
2949     g_critical ("no create_rtpbin vmethod function set");
2950     return FALSE;
2951   }
2952 no_rtpbin:
2953   {
2954     GST_WARNING ("no rtpbin element");
2955     g_warning ("failed to create element 'rtpbin', check your installation");
2956     return FALSE;
2957   }
2958 }
2959
2960 /**
2961  * gst_rtsp_media_prepare:
2962  * @media: a #GstRTSPMedia
2963  * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
2964  *   bus handler or %NULL
2965  *
2966  * Prepare @media for streaming. This function will create the objects
2967  * to manage the streaming. A pipeline must have been set on @media with
2968  * gst_rtsp_media_take_pipeline().
2969  *
2970  * It will preroll the pipeline and collect vital information about the streams
2971  * such as the duration.
2972  *
2973  * Returns: %TRUE on success.
2974  */
2975 gboolean
2976 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2977 {
2978   GstRTSPMediaPrivate *priv;
2979   GstRTSPMediaClass *klass;
2980
2981   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2982
2983   priv = media->priv;
2984
2985   g_rec_mutex_lock (&priv->state_lock);
2986   priv->prepare_count++;
2987
2988   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
2989       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
2990     goto was_prepared;
2991
2992   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2993     goto is_preparing;
2994
2995   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
2996     goto not_unprepared;
2997
2998   if (!priv->reusable && priv->reused)
2999     goto is_reused;
3000
3001   GST_INFO ("preparing media %p", media);
3002
3003   /* reset some variables */
3004   priv->is_live = FALSE;
3005   priv->seekable = -1;
3006   priv->buffering = FALSE;
3007
3008   /* we're preparing now */
3009   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3010
3011   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3012   if (klass->prepare) {
3013     if (!klass->prepare (media, thread))
3014       goto prepare_failed;
3015   }
3016
3017 wait_status:
3018   g_rec_mutex_unlock (&priv->state_lock);
3019
3020   /* now wait for all pads to be prerolled, FIXME, we should somehow be
3021    * able to do this async so that we don't block the server thread. */
3022   if (!wait_preroll (media))
3023     goto preroll_failed;
3024
3025   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
3026
3027   GST_INFO ("object %p is prerolled", media);
3028
3029   return TRUE;
3030
3031   /* OK */
3032 is_preparing:
3033   {
3034     /* we are not going to use the giving thread, so stop it. */
3035     if (thread)
3036       gst_rtsp_thread_stop (thread);
3037     goto wait_status;
3038   }
3039 was_prepared:
3040   {
3041     GST_LOG ("media %p was prepared", media);
3042     /* we are not going to use the giving thread, so stop it. */
3043     if (thread)
3044       gst_rtsp_thread_stop (thread);
3045     g_rec_mutex_unlock (&priv->state_lock);
3046     return TRUE;
3047   }
3048   /* ERRORS */
3049 not_unprepared:
3050   {
3051     /* we are not going to use the giving thread, so stop it. */
3052     if (thread)
3053       gst_rtsp_thread_stop (thread);
3054     GST_WARNING ("media %p was not unprepared", media);
3055     priv->prepare_count--;
3056     g_rec_mutex_unlock (&priv->state_lock);
3057     return FALSE;
3058   }
3059 is_reused:
3060   {
3061     /* we are not going to use the giving thread, so stop it. */
3062     if (thread)
3063       gst_rtsp_thread_stop (thread);
3064     priv->prepare_count--;
3065     g_rec_mutex_unlock (&priv->state_lock);
3066     GST_WARNING ("can not reuse media %p", media);
3067     return FALSE;
3068   }
3069 prepare_failed:
3070   {
3071     /* we are not going to use the giving thread, so stop it. */
3072     if (thread)
3073       gst_rtsp_thread_stop (thread);
3074     priv->prepare_count--;
3075     g_rec_mutex_unlock (&priv->state_lock);
3076     GST_ERROR ("failed to prepare media");
3077     return FALSE;
3078   }
3079 preroll_failed:
3080   {
3081     GST_WARNING ("failed to preroll pipeline");
3082     gst_rtsp_media_unprepare (media);
3083     return FALSE;
3084   }
3085 }
3086
3087 /* must be called with state-lock */
3088 static void
3089 finish_unprepare (GstRTSPMedia * media)
3090 {
3091   GstRTSPMediaPrivate *priv = media->priv;
3092   gint i;
3093   GList *walk;
3094
3095   GST_DEBUG ("shutting down");
3096
3097   /* release the lock on shutdown, otherwise pad_added_cb might try to
3098    * acquire the lock and then we deadlock */
3099   g_rec_mutex_unlock (&priv->state_lock);
3100   set_state (media, GST_STATE_NULL);
3101   g_rec_mutex_lock (&priv->state_lock);
3102
3103   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARING)
3104     return;
3105
3106   remove_fakesink (priv);
3107
3108   for (i = 0; i < priv->streams->len; i++) {
3109     GstRTSPStream *stream;
3110
3111     GST_INFO ("Removing elements of stream %d from pipeline", i);
3112
3113     stream = g_ptr_array_index (priv->streams, i);
3114
3115     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3116   }
3117
3118   /* remove the pad signal handlers */
3119   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3120     GstElement *elem = walk->data;
3121     DynPaySignalHandlers *handlers;
3122
3123     handlers =
3124         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3125     g_assert (handlers != NULL);
3126
3127     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3128     g_signal_handler_disconnect (G_OBJECT (elem),
3129         handlers->pad_removed_handler);
3130     g_signal_handler_disconnect (G_OBJECT (elem),
3131         handlers->no_more_pads_handler);
3132
3133     g_slice_free (DynPaySignalHandlers, handlers);
3134   }
3135
3136   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3137   priv->rtpbin = NULL;
3138
3139   if (priv->nettime)
3140     gst_object_unref (priv->nettime);
3141   priv->nettime = NULL;
3142
3143   priv->reused = TRUE;
3144   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3145
3146   /* when the media is not reusable, this will effectively unref the media and
3147    * recreate it */
3148   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3149
3150   /* the source has the last ref to the media */
3151   if (priv->source) {
3152     GST_DEBUG ("destroy source");
3153     g_source_destroy (priv->source);
3154     g_source_unref (priv->source);
3155   }
3156   if (priv->thread) {
3157     GST_DEBUG ("stop thread");
3158     gst_rtsp_thread_stop (priv->thread);
3159   }
3160 }
3161
3162 /* called with state-lock */
3163 static gboolean
3164 default_unprepare (GstRTSPMedia * media)
3165 {
3166   GstRTSPMediaPrivate *priv = media->priv;
3167
3168   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3169
3170   if (priv->eos_shutdown) {
3171     GST_DEBUG ("sending EOS for shutdown");
3172     /* ref so that we don't disappear */
3173     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
3174     /* we need to go to playing again for the EOS to propagate, normally in this
3175      * state, nothing is receiving data from us anymore so this is ok. */
3176     set_state (media, GST_STATE_PLAYING);
3177   } else {
3178     finish_unprepare (media);
3179   }
3180   return TRUE;
3181 }
3182
3183 /**
3184  * gst_rtsp_media_unprepare:
3185  * @media: a #GstRTSPMedia
3186  *
3187  * Unprepare @media. After this call, the media should be prepared again before
3188  * it can be used again. If the media is set to be non-reusable, a new instance
3189  * must be created.
3190  *
3191  * Returns: %TRUE on success.
3192  */
3193 gboolean
3194 gst_rtsp_media_unprepare (GstRTSPMedia * media)
3195 {
3196   GstRTSPMediaPrivate *priv;
3197   gboolean success;
3198
3199   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3200
3201   priv = media->priv;
3202
3203   g_rec_mutex_lock (&priv->state_lock);
3204   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
3205     goto was_unprepared;
3206
3207   priv->prepare_count--;
3208   if (priv->prepare_count > 0)
3209     goto is_busy;
3210
3211   GST_INFO ("unprepare media %p", media);
3212   if (priv->blocked)
3213     media_streams_set_blocked (media, FALSE);
3214   set_target_state (media, GST_STATE_NULL, FALSE);
3215   success = TRUE;
3216
3217   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
3218     GstRTSPMediaClass *klass;
3219
3220     klass = GST_RTSP_MEDIA_GET_CLASS (media);
3221     if (klass->unprepare)
3222       success = klass->unprepare (media);
3223   } else {
3224     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3225     finish_unprepare (media);
3226   }
3227   g_rec_mutex_unlock (&priv->state_lock);
3228
3229   return success;
3230
3231 was_unprepared:
3232   {
3233     g_rec_mutex_unlock (&priv->state_lock);
3234     GST_INFO ("media %p was already unprepared", media);
3235     return TRUE;
3236   }
3237 is_busy:
3238   {
3239     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
3240     g_rec_mutex_unlock (&priv->state_lock);
3241     return TRUE;
3242   }
3243 }
3244
3245 /* should be called with state-lock */
3246 static GstClock *
3247 get_clock_unlocked (GstRTSPMedia * media)
3248 {
3249   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
3250     GST_DEBUG_OBJECT (media, "media was not prepared");
3251     return NULL;
3252   }
3253   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
3254 }
3255
3256 /**
3257  * gst_rtsp_media_get_clock:
3258  * @media: a #GstRTSPMedia
3259  *
3260  * Get the clock that is used by the pipeline in @media.
3261  *
3262  * @media must be prepared before this method returns a valid clock object.
3263  *
3264  * Returns: (transfer full): the #GstClock used by @media. unref after usage.
3265  */
3266 GstClock *
3267 gst_rtsp_media_get_clock (GstRTSPMedia * media)
3268 {
3269   GstClock *clock;
3270   GstRTSPMediaPrivate *priv;
3271
3272   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3273
3274   priv = media->priv;
3275
3276   g_rec_mutex_lock (&priv->state_lock);
3277   clock = get_clock_unlocked (media);
3278   g_rec_mutex_unlock (&priv->state_lock);
3279
3280   return clock;
3281 }
3282
3283 /**
3284  * gst_rtsp_media_get_base_time:
3285  * @media: a #GstRTSPMedia
3286  *
3287  * Get the base_time that is used by the pipeline in @media.
3288  *
3289  * @media must be prepared before this method returns a valid base_time.
3290  *
3291  * Returns: the base_time used by @media.
3292  */
3293 GstClockTime
3294 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
3295 {
3296   GstClockTime result;
3297   GstRTSPMediaPrivate *priv;
3298
3299   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
3300
3301   priv = media->priv;
3302
3303   g_rec_mutex_lock (&priv->state_lock);
3304   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3305     goto not_prepared;
3306
3307   result = gst_element_get_base_time (media->priv->pipeline);
3308   g_rec_mutex_unlock (&priv->state_lock);
3309
3310   return result;
3311
3312   /* ERRORS */
3313 not_prepared:
3314   {
3315     g_rec_mutex_unlock (&priv->state_lock);
3316     GST_DEBUG_OBJECT (media, "media was not prepared");
3317     return GST_CLOCK_TIME_NONE;
3318   }
3319 }
3320
3321 /**
3322  * gst_rtsp_media_get_time_provider:
3323  * @media: a #GstRTSPMedia
3324  * @address: (allow-none): an address or %NULL
3325  * @port: a port or 0
3326  *
3327  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
3328  * will listen on @address and @port for client time requests.
3329  *
3330  * Returns: (transfer full): the #GstNetTimeProvider of @media.
3331  */
3332 GstNetTimeProvider *
3333 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
3334     guint16 port)
3335 {
3336   GstRTSPMediaPrivate *priv;
3337   GstNetTimeProvider *provider = NULL;
3338
3339   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3340
3341   priv = media->priv;
3342
3343   g_rec_mutex_lock (&priv->state_lock);
3344   if (priv->time_provider) {
3345     if ((provider = priv->nettime) == NULL) {
3346       GstClock *clock;
3347
3348       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
3349         provider = gst_net_time_provider_new (clock, address, port);
3350         gst_object_unref (clock);
3351
3352         priv->nettime = provider;
3353       }
3354     }
3355   }
3356   g_rec_mutex_unlock (&priv->state_lock);
3357
3358   if (provider)
3359     gst_object_ref (provider);
3360
3361   return provider;
3362 }
3363
3364 static gboolean
3365 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
3366 {
3367   return gst_rtsp_sdp_from_media (sdp, info, media);
3368 }
3369
3370 /**
3371  * gst_rtsp_media_setup_sdp:
3372  * @media: a #GstRTSPMedia
3373  * @sdp: (transfer none): a #GstSDPMessage
3374  * @info: (transfer none): a #GstSDPInfo
3375  *
3376  * Add @media specific info to @sdp. @info is used to configure the connection
3377  * information in the SDP.
3378  *
3379  * Returns: TRUE on success.
3380  */
3381 gboolean
3382 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
3383     GstSDPInfo * info)
3384 {
3385   GstRTSPMediaPrivate *priv;
3386   GstRTSPMediaClass *klass;
3387   gboolean res;
3388
3389   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3390   g_return_val_if_fail (sdp != NULL, FALSE);
3391   g_return_val_if_fail (info != NULL, FALSE);
3392
3393   priv = media->priv;
3394
3395   g_rec_mutex_lock (&priv->state_lock);
3396
3397   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3398
3399   if (!klass->setup_sdp)
3400     goto no_setup_sdp;
3401
3402   res = klass->setup_sdp (media, sdp, info);
3403
3404   g_rec_mutex_unlock (&priv->state_lock);
3405
3406   return res;
3407
3408   /* ERRORS */
3409 no_setup_sdp:
3410   {
3411     g_rec_mutex_unlock (&priv->state_lock);
3412     GST_ERROR ("no setup_sdp function");
3413     g_critical ("no setup_sdp vmethod function set");
3414     return FALSE;
3415   }
3416 }
3417
3418 static gboolean
3419 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
3420 {
3421   GstRTSPMediaPrivate *priv = media->priv;
3422   gint i, medias_len;
3423
3424   medias_len = gst_sdp_message_medias_len (sdp);
3425   if (medias_len != priv->streams->len) {
3426     GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
3427         priv->streams->len, medias_len);
3428     return FALSE;
3429   }
3430
3431   for (i = 0; i < medias_len; i++) {
3432     const gchar *proto;
3433     const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
3434     GstRTSPStream *stream;
3435     gint j, formats_len;
3436     const gchar *control;
3437     GstRTSPProfile profile, profiles;
3438
3439     stream = g_ptr_array_index (priv->streams, i);
3440
3441     /* TODO: Should we do something with the other SDP information? */
3442
3443     /* get proto */
3444     proto = gst_sdp_media_get_proto (sdp_media);
3445     if (proto == NULL) {
3446       GST_ERROR ("%p: SDP media %d has no proto", media, i);
3447       return FALSE;
3448     }
3449
3450     if (g_str_equal (proto, "RTP/AVP")) {
3451       profile = GST_RTSP_PROFILE_AVP;
3452     } else if (g_str_equal (proto, "RTP/SAVP")) {
3453       profile = GST_RTSP_PROFILE_SAVP;
3454     } else if (g_str_equal (proto, "RTP/AVPF")) {
3455       profile = GST_RTSP_PROFILE_AVPF;
3456     } else if (g_str_equal (proto, "RTP/SAVPF")) {
3457       profile = GST_RTSP_PROFILE_SAVPF;
3458     } else {
3459       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
3460       return FALSE;
3461     }
3462
3463     profiles = gst_rtsp_stream_get_profiles (stream);
3464     if ((profiles & profile) == 0) {
3465       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
3466       return FALSE;
3467     }
3468
3469     formats_len = gst_sdp_media_formats_len (sdp_media);
3470     for (j = 0; j < formats_len; j++) {
3471       gint pt;
3472       GstCaps *caps;
3473       GstStructure *s;
3474
3475       pt = atoi (gst_sdp_media_get_format (sdp_media, j));
3476
3477       GST_DEBUG (" looking at %d pt: %d", j, pt);
3478
3479       /* convert caps */
3480       caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
3481       if (caps == NULL) {
3482         GST_WARNING (" skipping pt %d without caps", pt);
3483         continue;
3484       }
3485
3486       /* do some tweaks */
3487       GST_DEBUG ("mapping sdp session level attributes to caps");
3488       gst_sdp_message_attributes_to_caps (sdp, caps);
3489       GST_DEBUG ("mapping sdp media level attributes to caps");
3490       gst_sdp_media_attributes_to_caps (sdp_media, caps);
3491
3492       s = gst_caps_get_structure (caps, 0);
3493       gst_structure_set_name (s, "application/x-rtp");
3494
3495       gst_rtsp_stream_set_pt_map (stream, pt, caps);
3496       gst_caps_unref (caps);
3497     }
3498
3499     control = gst_sdp_media_get_attribute_val (sdp_media, "control");
3500     if (control)
3501       gst_rtsp_stream_set_control (stream, control);
3502
3503   }
3504
3505   return TRUE;
3506 }
3507
3508 /**
3509  * gst_rtsp_media_handle_sdp:
3510  * @media: a #GstRTSPMedia
3511  * @sdp: (transfer none): a #GstSDPMessage
3512  *
3513  * Configure an SDP on @media for receiving streams
3514  *
3515  * Returns: TRUE on success.
3516  */
3517 gboolean
3518 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
3519 {
3520   GstRTSPMediaPrivate *priv;
3521   GstRTSPMediaClass *klass;
3522   gboolean res;
3523
3524   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3525   g_return_val_if_fail (sdp != NULL, FALSE);
3526
3527   priv = media->priv;
3528
3529   g_rec_mutex_lock (&priv->state_lock);
3530
3531   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3532
3533   if (!klass->handle_sdp)
3534     goto no_handle_sdp;
3535
3536   res = klass->handle_sdp (media, sdp);
3537
3538   g_rec_mutex_unlock (&priv->state_lock);
3539
3540   return res;
3541
3542   /* ERRORS */
3543 no_handle_sdp:
3544   {
3545     g_rec_mutex_unlock (&priv->state_lock);
3546     GST_ERROR ("no handle_sdp function");
3547     g_critical ("no handle_sdp vmethod function set");
3548     return FALSE;
3549   }
3550 }
3551
3552 static void
3553 do_set_seqnum (GstRTSPStream * stream)
3554 {
3555   guint16 seq_num;
3556   seq_num = gst_rtsp_stream_get_current_seqnum (stream);
3557   gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
3558 }
3559
3560 /* call with state_lock */
3561 static gboolean
3562 default_suspend (GstRTSPMedia * media)
3563 {
3564   GstRTSPMediaPrivate *priv = media->priv;
3565   GstStateChangeReturn ret;
3566   gboolean unblock = FALSE;
3567
3568   switch (priv->suspend_mode) {
3569     case GST_RTSP_SUSPEND_MODE_NONE:
3570       GST_DEBUG ("media %p no suspend", media);
3571       break;
3572     case GST_RTSP_SUSPEND_MODE_PAUSE:
3573       GST_DEBUG ("media %p suspend to PAUSED", media);
3574       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3575       if (ret == GST_STATE_CHANGE_FAILURE)
3576         goto state_failed;
3577       unblock = TRUE;
3578       break;
3579     case GST_RTSP_SUSPEND_MODE_RESET:
3580       GST_DEBUG ("media %p suspend to NULL", media);
3581       ret = set_target_state (media, GST_STATE_NULL, TRUE);
3582       if (ret == GST_STATE_CHANGE_FAILURE)
3583         goto state_failed;
3584       /* Because payloader needs to set the sequence number as
3585        * monotonic, we need to preserve the sequence number
3586        * after pause. (otherwise going from pause to play,  which
3587        * is actually from NULL to PLAY will create a new sequence
3588        * number. */
3589       g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
3590       unblock = TRUE;
3591       break;
3592     default:
3593       break;
3594   }
3595
3596   /* let the streams do the state changes freely, if any */
3597   if (unblock)
3598     media_streams_set_blocked (media, FALSE);
3599
3600   return TRUE;
3601
3602   /* ERRORS */
3603 state_failed:
3604   {
3605     GST_WARNING ("failed changing pipeline's state for media %p", media);
3606     return FALSE;
3607   }
3608 }
3609
3610 /**
3611  * gst_rtsp_media_suspend:
3612  * @media: a #GstRTSPMedia
3613  *
3614  * Suspend @media. The state of the pipeline managed by @media is set to
3615  * GST_STATE_NULL but all streams are kept. @media can be prepared again
3616  * with gst_rtsp_media_unsuspend()
3617  *
3618  * @media must be prepared with gst_rtsp_media_prepare();
3619  *
3620  * Returns: %TRUE on success.
3621  */
3622 gboolean
3623 gst_rtsp_media_suspend (GstRTSPMedia * media)
3624 {
3625   GstRTSPMediaPrivate *priv = media->priv;
3626   GstRTSPMediaClass *klass;
3627
3628   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3629
3630   GST_FIXME ("suspend for dynamic pipelines needs fixing");
3631
3632   g_rec_mutex_lock (&priv->state_lock);
3633   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3634     goto not_prepared;
3635
3636   /* don't attempt to suspend when something is busy */
3637   if (priv->n_active > 0)
3638     goto done;
3639
3640   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3641   if (klass->suspend) {
3642     if (!klass->suspend (media))
3643       goto suspend_failed;
3644   }
3645
3646   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
3647 done:
3648   g_rec_mutex_unlock (&priv->state_lock);
3649
3650   return TRUE;
3651
3652   /* ERRORS */
3653 not_prepared:
3654   {
3655     g_rec_mutex_unlock (&priv->state_lock);
3656     GST_WARNING ("media %p was not prepared", media);
3657     return FALSE;
3658   }
3659 suspend_failed:
3660   {
3661     g_rec_mutex_unlock (&priv->state_lock);
3662     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3663     GST_WARNING ("failed to suspend media %p", media);
3664     return FALSE;
3665   }
3666 }
3667
3668 /* call with state_lock */
3669 static gboolean
3670 default_unsuspend (GstRTSPMedia * media)
3671 {
3672   GstRTSPMediaPrivate *priv = media->priv;
3673   gboolean preroll_ok;
3674
3675   switch (priv->suspend_mode) {
3676     case GST_RTSP_SUSPEND_MODE_NONE:
3677       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3678       break;
3679     case GST_RTSP_SUSPEND_MODE_PAUSE:
3680       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3681       break;
3682     case GST_RTSP_SUSPEND_MODE_RESET:
3683     {
3684       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3685       if (!start_preroll (media))
3686         goto start_failed;
3687
3688       g_rec_mutex_unlock (&priv->state_lock);
3689       preroll_ok = wait_preroll (media);
3690       g_rec_mutex_lock (&priv->state_lock);
3691
3692       if (!preroll_ok)
3693         goto preroll_failed;
3694     }
3695     default:
3696       break;
3697   }
3698
3699   return TRUE;
3700
3701   /* ERRORS */
3702 start_failed:
3703   {
3704     GST_WARNING ("failed to preroll pipeline");
3705     return FALSE;
3706   }
3707 preroll_failed:
3708   {
3709     GST_WARNING ("failed to preroll pipeline");
3710     return FALSE;
3711   }
3712 }
3713
3714 /**
3715  * gst_rtsp_media_unsuspend:
3716  * @media: a #GstRTSPMedia
3717  *
3718  * Unsuspend @media if it was in a suspended state. This method does nothing
3719  * when the media was not in the suspended state.
3720  *
3721  * Returns: %TRUE on success.
3722  */
3723 gboolean
3724 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
3725 {
3726   GstRTSPMediaPrivate *priv = media->priv;
3727   GstRTSPMediaClass *klass;
3728
3729   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3730
3731   g_rec_mutex_lock (&priv->state_lock);
3732   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
3733     goto done;
3734
3735   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3736   if (klass->unsuspend) {
3737     if (!klass->unsuspend (media))
3738       goto unsuspend_failed;
3739   }
3740
3741 done:
3742   g_rec_mutex_unlock (&priv->state_lock);
3743
3744   return TRUE;
3745
3746   /* ERRORS */
3747 unsuspend_failed:
3748   {
3749     g_rec_mutex_unlock (&priv->state_lock);
3750     GST_WARNING ("failed to unsuspend media %p", media);
3751     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3752     return FALSE;
3753   }
3754 }
3755
3756 /* must be called with state-lock */
3757 static void
3758 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
3759 {
3760   GstRTSPMediaPrivate *priv = media->priv;
3761
3762   if (state == GST_STATE_NULL) {
3763     gst_rtsp_media_unprepare (media);
3764   } else {
3765     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
3766     set_target_state (media, state, FALSE);
3767     /* when we are buffering, don't update the state yet, this will be done
3768      * when buffering finishes */
3769     if (priv->buffering) {
3770       GST_INFO ("Buffering busy, delay state change");
3771     } else {
3772       if (state == GST_STATE_PLAYING)
3773         /* make sure pads are not blocking anymore when going to PLAYING */
3774         media_streams_set_blocked (media, FALSE);
3775
3776       set_state (media, state);
3777
3778       /* and suspend after pause */
3779       if (state == GST_STATE_PAUSED)
3780         gst_rtsp_media_suspend (media);
3781     }
3782   }
3783 }
3784
3785 /**
3786  * gst_rtsp_media_set_pipeline_state:
3787  * @media: a #GstRTSPMedia
3788  * @state: the target state of the pipeline
3789  *
3790  * Set the state of the pipeline managed by @media to @state
3791  */
3792 void
3793 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
3794 {
3795   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
3796
3797   g_rec_mutex_lock (&media->priv->state_lock);
3798   media_set_pipeline_state_locked (media, state);
3799   g_rec_mutex_unlock (&media->priv->state_lock);
3800 }
3801
3802 /**
3803  * gst_rtsp_media_set_state:
3804  * @media: a #GstRTSPMedia
3805  * @state: the target state of the media
3806  * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
3807  * a #GPtrArray of #GstRTSPStreamTransport pointers
3808  *
3809  * Set the state of @media to @state and for the transports in @transports.
3810  *
3811  * @media must be prepared with gst_rtsp_media_prepare();
3812  *
3813  * Returns: %TRUE on success.
3814  */
3815 gboolean
3816 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
3817     GPtrArray * transports)
3818 {
3819   GstRTSPMediaPrivate *priv;
3820   gint i;
3821   gboolean activate, deactivate, do_state;
3822   gint old_active;
3823
3824   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3825   g_return_val_if_fail (transports != NULL, FALSE);
3826
3827   priv = media->priv;
3828
3829   g_rec_mutex_lock (&priv->state_lock);
3830   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
3831     goto error_status;
3832   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
3833       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
3834     goto not_prepared;
3835
3836   /* NULL and READY are the same */
3837   if (state == GST_STATE_READY)
3838     state = GST_STATE_NULL;
3839
3840   activate = deactivate = FALSE;
3841
3842   GST_INFO ("going to state %s media %p, target state %s",
3843       gst_element_state_get_name (state), media,
3844       gst_element_state_get_name (priv->target_state));
3845
3846   switch (state) {
3847     case GST_STATE_NULL:
3848       /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
3849       if (priv->target_state >= GST_STATE_PAUSED)
3850         deactivate = TRUE;
3851       break;
3852     case GST_STATE_PAUSED:
3853       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
3854       if (priv->target_state == GST_STATE_PLAYING)
3855         deactivate = TRUE;
3856       break;
3857     case GST_STATE_PLAYING:
3858       /* we're going to PLAYING, activate */
3859       activate = TRUE;
3860       break;
3861     default:
3862       break;
3863   }
3864   old_active = priv->n_active;
3865
3866   GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
3867       activate, deactivate);
3868   for (i = 0; i < transports->len; i++) {
3869     GstRTSPStreamTransport *trans;
3870
3871     /* we need a non-NULL entry in the array */
3872     trans = g_ptr_array_index (transports, i);
3873     if (trans == NULL)
3874       continue;
3875
3876     if (activate) {
3877       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
3878         priv->n_active++;
3879     } else if (deactivate) {
3880       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
3881         priv->n_active--;
3882     }
3883   }
3884
3885   /* we just activated the first media, do the playing state change */
3886   if (old_active == 0 && activate)
3887     do_state = TRUE;
3888   /* if we have no more active media, do the downward state changes */
3889   else if (priv->n_active == 0)
3890     do_state = TRUE;
3891   else
3892     do_state = FALSE;
3893
3894   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
3895       media, do_state);
3896
3897   if (priv->target_state != state) {
3898     if (do_state) {
3899       media_set_pipeline_state_locked (media, state);
3900       g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
3901           NULL);
3902     }
3903   }
3904
3905   /* remember where we are */
3906   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
3907           old_active != priv->n_active))
3908     collect_media_stats (media);
3909
3910   g_rec_mutex_unlock (&priv->state_lock);
3911
3912   return TRUE;
3913
3914   /* ERRORS */
3915 not_prepared:
3916   {
3917     GST_WARNING ("media %p was not prepared", media);
3918     g_rec_mutex_unlock (&priv->state_lock);
3919     return FALSE;
3920   }
3921 error_status:
3922   {
3923     GST_WARNING ("media %p in error status while changing to state %d",
3924         media, state);
3925     if (state == GST_STATE_NULL) {
3926       for (i = 0; i < transports->len; i++) {
3927         GstRTSPStreamTransport *trans;
3928
3929         /* we need a non-NULL entry in the array */
3930         trans = g_ptr_array_index (transports, i);
3931         if (trans == NULL)
3932           continue;
3933
3934         gst_rtsp_stream_transport_set_active (trans, FALSE);
3935       }
3936       priv->n_active = 0;
3937     }
3938     g_rec_mutex_unlock (&priv->state_lock);
3939     return FALSE;
3940   }
3941 }
3942
3943 /**
3944  * gst_rtsp_media_set_transport_mode:
3945  * @media: a #GstRTSPMedia
3946  * @mode: the new value
3947  *
3948  * Sets if the media pipeline can work in PLAY or RECORD mode
3949  */
3950 void
3951 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
3952     GstRTSPTransportMode mode)
3953 {
3954   GstRTSPMediaPrivate *priv;
3955
3956   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
3957
3958   priv = media->priv;
3959
3960   g_mutex_lock (&priv->lock);
3961   priv->transport_mode = mode;
3962   g_mutex_unlock (&priv->lock);
3963 }
3964
3965 /**
3966  * gst_rtsp_media_get_transport_mode:
3967  * @media: a #GstRTSPMedia
3968  *
3969  * Check if the pipeline for @media can be used for PLAY or RECORD methods.
3970  *
3971  * Returns: The transport mode.
3972  */
3973 GstRTSPTransportMode
3974 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
3975 {
3976   GstRTSPMediaPrivate *priv;
3977   GstRTSPTransportMode res;
3978
3979   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3980
3981   priv = media->priv;
3982
3983   g_mutex_lock (&priv->lock);
3984   res = priv->transport_mode;
3985   g_mutex_unlock (&priv->lock);
3986
3987   return res;
3988 }
3989
3990 /**
3991  * gst_rtsp_media_get_seekbale:
3992  * @media: a #GstRTSPMedia
3993  *
3994  * Check if the pipeline for @media seek and up to what point in time,
3995  * it can seek.
3996  *
3997  * Returns: -1 if the stream is not seekable, 0 if seekable only to the beginning
3998  * and > 0 to indicate the longest duration between any two random access points.
3999  * G_MAXINT64 means any value is possible.
4000  */
4001 GstClockTimeDiff
4002 gst_rtsp_media_seekable (GstRTSPMedia * media)
4003 {
4004   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4005
4006   /* Currently we are not able to seek on live streams,
4007    * and no stream is seekable only to the beginning */
4008   return media->priv->seekable;
4009 }