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