c6004b988b179cab94033a60412cf9786fd9833b
[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(), or gst_rtsp_media_seek_full()
54  * or gst_rtsp_media_seek_trickmode() for finer control of the seek.
55  *
56  * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
57  * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
58  * cleanly shut down.
59  *
60  * With gst_rtsp_media_set_shared(), the media can be shared between multiple
61  * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
62  * can be prepared again after an unprepare.
63  *
64  * Last reviewed on 2013-07-11 (1.0.0)
65  */
66 #ifdef HAVE_CONFIG_H
67 #include "config.h"
68 #endif
69
70 #include <stdio.h>
71 #include <string.h>
72 #include <stdlib.h>
73
74 #include <gst/app/gstappsrc.h>
75 #include <gst/app/gstappsink.h>
76
77 #include <gst/sdp/gstmikey.h>
78 #include <gst/rtp/gstrtppayloads.h>
79
80 #define AES_128_KEY_LEN 16
81 #define AES_256_KEY_LEN 32
82
83 #define HMAC_32_KEY_LEN 4
84 #define HMAC_80_KEY_LEN 10
85
86 #include "rtsp-media.h"
87
88 struct _GstRTSPMediaPrivate
89 {
90   GMutex lock;
91   GCond cond;
92
93   /* the global lock is used to lock the entire media. This is needed by callers
94      such as rtsp_client to protect the media when it is shared by many clients.
95      The lock prevents that concurrenting clients messes up media.
96      Typically the lock is taken in external API calls such as SETUP */
97   GMutex global_lock;
98
99   /* protected by lock */
100   GstRTSPPermissions *permissions;
101   gboolean shared;
102   gboolean suspend_mode;
103   gboolean reusable;
104   GstRTSPProfile profiles;
105   GstRTSPLowerTrans protocols;
106   gboolean reused;
107   gboolean eos_shutdown;
108   guint buffer_size;
109   gint dscp_qos;
110   GstRTSPAddressPool *pool;
111   gchar *multicast_iface;
112   guint max_mcast_ttl;
113   gboolean bind_mcast_address;
114   gboolean blocked;
115   GstRTSPTransportMode transport_mode;
116   gboolean stop_on_disconnect;
117   guint blocking_msg_received;
118
119   GstElement *element;
120   GRecMutex state_lock;         /* locking order: state lock, lock */
121   GPtrArray *streams;           /* protected by lock */
122   GList *dynamic;               /* protected by lock */
123   GstRTSPMediaStatus status;    /* protected by lock */
124   gint prepare_count;
125   gint n_active;
126   gboolean complete;
127   gboolean finishing_unprepare;
128
129   /* the pipeline for the media */
130   GstElement *pipeline;
131   GSource *source;
132   guint id;
133   GstRTSPThread *thread;
134   GList *pending_pipeline_elements;
135
136   gboolean time_provider;
137   GstNetTimeProvider *nettime;
138
139   gboolean is_live;
140   GstClockTimeDiff seekable;
141   gboolean buffering;
142   GstState target_state;
143
144   /* RTP session manager */
145   GstElement *rtpbin;
146
147   /* the range of media */
148   GstRTSPTimeRange range;       /* protected by lock */
149   GstClockTime range_start;
150   GstClockTime range_stop;
151
152   GList *payloads;              /* protected by lock */
153   GstClockTime rtx_time;        /* protected by lock */
154   gboolean do_retransmission;   /* protected by lock */
155   guint latency;                /* protected by lock */
156   GstClock *clock;              /* protected by lock */
157   gboolean do_rate_control;     /* protected by lock */
158   GstRTSPPublishClockMode publish_clock_mode;
159
160   /* Dynamic element handling */
161   guint nb_dynamic_elements;
162   guint no_more_pads_pending;
163   gboolean expected_async_done;
164 };
165
166 #define DEFAULT_SHARED          FALSE
167 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
168 #define DEFAULT_REUSABLE        FALSE
169 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
170 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
171                                         GST_RTSP_LOWER_TRANS_TCP
172 #define DEFAULT_EOS_SHUTDOWN    FALSE
173 #define DEFAULT_BUFFER_SIZE     0x80000
174 #define DEFAULT_DSCP_QOS        (-1)
175 #define DEFAULT_TIME_PROVIDER   FALSE
176 #define DEFAULT_LATENCY         200
177 #define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
178 #define DEFAULT_STOP_ON_DISCONNECT TRUE
179 #define DEFAULT_MAX_MCAST_TTL   255
180 #define DEFAULT_BIND_MCAST_ADDRESS FALSE
181 #define DEFAULT_DO_RATE_CONTROL TRUE
182
183 #define DEFAULT_DO_RETRANSMISSION FALSE
184
185 /* define to dump received RTCP packets */
186 #undef DUMP_STATS
187
188 enum
189 {
190   PROP_0,
191   PROP_SHARED,
192   PROP_SUSPEND_MODE,
193   PROP_REUSABLE,
194   PROP_PROFILES,
195   PROP_PROTOCOLS,
196   PROP_EOS_SHUTDOWN,
197   PROP_BUFFER_SIZE,
198   PROP_ELEMENT,
199   PROP_TIME_PROVIDER,
200   PROP_LATENCY,
201   PROP_TRANSPORT_MODE,
202   PROP_STOP_ON_DISCONNECT,
203   PROP_CLOCK,
204   PROP_MAX_MCAST_TTL,
205   PROP_BIND_MCAST_ADDRESS,
206   PROP_DSCP_QOS,
207   PROP_LAST
208 };
209
210 enum
211 {
212   SIGNAL_NEW_STREAM,
213   SIGNAL_REMOVED_STREAM,
214   SIGNAL_PREPARED,
215   SIGNAL_UNPREPARED,
216   SIGNAL_TARGET_STATE,
217   SIGNAL_NEW_STATE,
218   SIGNAL_LAST
219 };
220
221 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
222 #define GST_CAT_DEFAULT rtsp_media_debug
223
224 static void gst_rtsp_media_get_property (GObject * object, guint propid,
225     GValue * value, GParamSpec * pspec);
226 static void gst_rtsp_media_set_property (GObject * object, guint propid,
227     const GValue * value, GParamSpec * pspec);
228 static void gst_rtsp_media_finalize (GObject * obj);
229
230 static gboolean default_handle_message (GstRTSPMedia * media,
231     GstMessage * message);
232 static void finish_unprepare (GstRTSPMedia * media);
233 static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread);
234 static gboolean default_unprepare (GstRTSPMedia * media);
235 static gboolean default_suspend (GstRTSPMedia * media);
236 static gboolean default_unsuspend (GstRTSPMedia * media);
237 static gboolean default_convert_range (GstRTSPMedia * media,
238     GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
239 static gboolean default_query_position (GstRTSPMedia * media,
240     gint64 * position);
241 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
242 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
243 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
244     GstSDPInfo * info);
245 static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
246
247 static gboolean wait_preroll (GstRTSPMedia * media);
248
249 static GstElement *find_payload_element (GstElement * payloader, GstPad * pad);
250
251 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
252
253 static gboolean check_complete (GstRTSPMedia * media);
254
255 #define C_ENUM(v) ((gint) v)
256
257 #define TRICKMODE_FLAGS (GST_SEEK_FLAG_TRICKMODE | GST_SEEK_FLAG_TRICKMODE_KEY_UNITS | GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED)
258
259 GType
260 gst_rtsp_suspend_mode_get_type (void)
261 {
262   static gsize id = 0;
263   static const GEnumValue values[] = {
264     {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
265     {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
266         "pause"},
267     {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
268         "reset"},
269     {0, NULL, NULL}
270   };
271
272   if (g_once_init_enter (&id)) {
273     GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
274     g_once_init_leave (&id, tmp);
275   }
276   return (GType) id;
277 }
278
279 #define C_FLAGS(v) ((guint) v)
280
281 GType
282 gst_rtsp_transport_mode_get_type (void)
283 {
284   static gsize id = 0;
285   static const GFlagsValue values[] = {
286     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
287         "play"},
288     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
289         "record"},
290     {0, NULL, NULL}
291   };
292
293   if (g_once_init_enter (&id)) {
294     GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
295     g_once_init_leave (&id, tmp);
296   }
297   return (GType) id;
298 }
299
300 GType
301 gst_rtsp_publish_clock_mode_get_type (void)
302 {
303   static gsize id = 0;
304   static const GEnumValue values[] = {
305     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
306         "GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
307     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
308           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
309         "clock"},
310     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
311           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
312         "clock-and-offset"},
313     {0, NULL, NULL}
314   };
315
316   if (g_once_init_enter (&id)) {
317     GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
318     g_once_init_leave (&id, tmp);
319   }
320   return (GType) id;
321 }
322
323 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
324
325 static void
326 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
327 {
328   GObjectClass *gobject_class;
329
330   gobject_class = G_OBJECT_CLASS (klass);
331
332   gobject_class->get_property = gst_rtsp_media_get_property;
333   gobject_class->set_property = gst_rtsp_media_set_property;
334   gobject_class->finalize = gst_rtsp_media_finalize;
335
336   g_object_class_install_property (gobject_class, PROP_SHARED,
337       g_param_spec_boolean ("shared", "Shared",
338           "If this media pipeline can be shared", DEFAULT_SHARED,
339           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
340
341   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
342       g_param_spec_enum ("suspend-mode", "Suspend Mode",
343           "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
344           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
345
346   g_object_class_install_property (gobject_class, PROP_REUSABLE,
347       g_param_spec_boolean ("reusable", "Reusable",
348           "If this media pipeline can be reused after an unprepare",
349           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
350
351   g_object_class_install_property (gobject_class, PROP_PROFILES,
352       g_param_spec_flags ("profiles", "Profiles",
353           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
354           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
355
356   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
357       g_param_spec_flags ("protocols", "Protocols",
358           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
359           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
360
361   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
362       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
363           "Send an EOS event to the pipeline before unpreparing",
364           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
365
366   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
367       g_param_spec_uint ("buffer-size", "Buffer Size",
368           "The kernel UDP buffer size to use", 0, G_MAXUINT,
369           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
370
371   g_object_class_install_property (gobject_class, PROP_ELEMENT,
372       g_param_spec_object ("element", "The Element",
373           "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
374           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
375
376   g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
377       g_param_spec_boolean ("time-provider", "Time Provider",
378           "Use a NetTimeProvider for clients",
379           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
380
381   g_object_class_install_property (gobject_class, PROP_LATENCY,
382       g_param_spec_uint ("latency", "Latency",
383           "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
384           DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
385
386   g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
387       g_param_spec_flags ("transport-mode", "Transport Mode",
388           "If this media pipeline can be used for PLAY or RECORD",
389           GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
390           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
391
392   g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
393       g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
394           "If this media pipeline should be stopped "
395           "when a client disconnects without TEARDOWN",
396           DEFAULT_STOP_ON_DISCONNECT,
397           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
398
399   g_object_class_install_property (gobject_class, PROP_CLOCK,
400       g_param_spec_object ("clock", "Clock",
401           "Clock to be used by the media pipeline",
402           GST_TYPE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
403
404   g_object_class_install_property (gobject_class, PROP_MAX_MCAST_TTL,
405       g_param_spec_uint ("max-mcast-ttl", "Maximum multicast ttl",
406           "The maximum time-to-live value of outgoing multicast packets", 1,
407           255, DEFAULT_MAX_MCAST_TTL,
408           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
409
410   g_object_class_install_property (gobject_class, PROP_BIND_MCAST_ADDRESS,
411       g_param_spec_boolean ("bind-mcast-address", "Bind mcast address",
412           "Whether the multicast sockets should be bound to multicast addresses "
413           "or INADDR_ANY",
414           DEFAULT_BIND_MCAST_ADDRESS,
415           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
416
417   g_object_class_install_property (gobject_class, PROP_DSCP_QOS,
418       g_param_spec_int ("dscp-qos", "DSCP QoS",
419           "The IP DSCP field to use for each related stream", -1, 63,
420           DEFAULT_DSCP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
421
422   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
423       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
424       G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL, NULL,
425       G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
426
427   gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
428       g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
429       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
430       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
431
432   gst_rtsp_media_signals[SIGNAL_PREPARED] =
433       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
434       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL, NULL,
435       G_TYPE_NONE, 0, G_TYPE_NONE);
436
437   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
438       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
439       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL, NULL,
440       G_TYPE_NONE, 0, G_TYPE_NONE);
441
442   gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
443       g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
444       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
445       NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
446
447   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
448       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
449       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL, NULL,
450       G_TYPE_NONE, 1, G_TYPE_INT);
451
452   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
453
454   klass->handle_message = default_handle_message;
455   klass->prepare = default_prepare;
456   klass->unprepare = default_unprepare;
457   klass->suspend = default_suspend;
458   klass->unsuspend = default_unsuspend;
459   klass->convert_range = default_convert_range;
460   klass->query_position = default_query_position;
461   klass->query_stop = default_query_stop;
462   klass->create_rtpbin = default_create_rtpbin;
463   klass->setup_sdp = default_setup_sdp;
464   klass->handle_sdp = default_handle_sdp;
465 }
466
467 static void
468 gst_rtsp_media_init (GstRTSPMedia * media)
469 {
470   GstRTSPMediaPrivate *priv = gst_rtsp_media_get_instance_private (media);
471
472   media->priv = priv;
473
474   priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
475   g_mutex_init (&priv->lock);
476   g_mutex_init (&priv->global_lock);
477   g_cond_init (&priv->cond);
478   g_rec_mutex_init (&priv->state_lock);
479
480   priv->shared = DEFAULT_SHARED;
481   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
482   priv->reusable = DEFAULT_REUSABLE;
483   priv->profiles = DEFAULT_PROFILES;
484   priv->protocols = DEFAULT_PROTOCOLS;
485   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
486   priv->buffer_size = DEFAULT_BUFFER_SIZE;
487   priv->time_provider = DEFAULT_TIME_PROVIDER;
488   priv->transport_mode = DEFAULT_TRANSPORT_MODE;
489   priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
490   priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
491   priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
492   priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
493   priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
494   priv->do_rate_control = DEFAULT_DO_RATE_CONTROL;
495   priv->dscp_qos = DEFAULT_DSCP_QOS;
496   priv->expected_async_done = FALSE;
497   priv->blocking_msg_received = 0;
498 }
499
500 static void
501 gst_rtsp_media_finalize (GObject * obj)
502 {
503   GstRTSPMediaPrivate *priv;
504   GstRTSPMedia *media;
505
506   media = GST_RTSP_MEDIA (obj);
507   priv = media->priv;
508
509   GST_INFO ("finalize media %p", media);
510
511   if (priv->permissions)
512     gst_rtsp_permissions_unref (priv->permissions);
513
514   g_ptr_array_unref (priv->streams);
515
516   g_list_free_full (priv->dynamic, gst_object_unref);
517   g_list_free_full (priv->pending_pipeline_elements, gst_object_unref);
518
519   if (priv->pipeline)
520     gst_object_unref (priv->pipeline);
521   if (priv->nettime)
522     gst_object_unref (priv->nettime);
523   gst_object_unref (priv->element);
524   if (priv->pool)
525     g_object_unref (priv->pool);
526   if (priv->payloads)
527     g_list_free (priv->payloads);
528   if (priv->clock)
529     gst_object_unref (priv->clock);
530   g_free (priv->multicast_iface);
531   g_mutex_clear (&priv->lock);
532   g_mutex_clear (&priv->global_lock);
533   g_cond_clear (&priv->cond);
534   g_rec_mutex_clear (&priv->state_lock);
535
536   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
537 }
538
539 static void
540 gst_rtsp_media_get_property (GObject * object, guint propid,
541     GValue * value, GParamSpec * pspec)
542 {
543   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
544
545   switch (propid) {
546     case PROP_ELEMENT:
547       g_value_set_object (value, media->priv->element);
548       break;
549     case PROP_SHARED:
550       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
551       break;
552     case PROP_SUSPEND_MODE:
553       g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
554       break;
555     case PROP_REUSABLE:
556       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
557       break;
558     case PROP_PROFILES:
559       g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
560       break;
561     case PROP_PROTOCOLS:
562       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
563       break;
564     case PROP_EOS_SHUTDOWN:
565       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
566       break;
567     case PROP_BUFFER_SIZE:
568       g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
569       break;
570     case PROP_TIME_PROVIDER:
571       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
572       break;
573     case PROP_LATENCY:
574       g_value_set_uint (value, gst_rtsp_media_get_latency (media));
575       break;
576     case PROP_TRANSPORT_MODE:
577       g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
578       break;
579     case PROP_STOP_ON_DISCONNECT:
580       g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
581       break;
582     case PROP_CLOCK:
583       g_value_take_object (value, gst_rtsp_media_get_clock (media));
584       break;
585     case PROP_MAX_MCAST_TTL:
586       g_value_set_uint (value, gst_rtsp_media_get_max_mcast_ttl (media));
587       break;
588     case PROP_BIND_MCAST_ADDRESS:
589       g_value_set_boolean (value, gst_rtsp_media_is_bind_mcast_address (media));
590       break;
591     case PROP_DSCP_QOS:
592       g_value_set_int (value, gst_rtsp_media_get_dscp_qos (media));
593       break;
594     default:
595       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
596   }
597 }
598
599 static void
600 gst_rtsp_media_set_property (GObject * object, guint propid,
601     const GValue * value, GParamSpec * pspec)
602 {
603   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
604
605   switch (propid) {
606     case PROP_ELEMENT:
607       media->priv->element = g_value_get_object (value);
608       gst_object_ref_sink (media->priv->element);
609       break;
610     case PROP_SHARED:
611       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
612       break;
613     case PROP_SUSPEND_MODE:
614       gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
615       break;
616     case PROP_REUSABLE:
617       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
618       break;
619     case PROP_PROFILES:
620       gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
621       break;
622     case PROP_PROTOCOLS:
623       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
624       break;
625     case PROP_EOS_SHUTDOWN:
626       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
627       break;
628     case PROP_BUFFER_SIZE:
629       gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
630       break;
631     case PROP_TIME_PROVIDER:
632       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
633       break;
634     case PROP_LATENCY:
635       gst_rtsp_media_set_latency (media, g_value_get_uint (value));
636       break;
637     case PROP_TRANSPORT_MODE:
638       gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
639       break;
640     case PROP_STOP_ON_DISCONNECT:
641       gst_rtsp_media_set_stop_on_disconnect (media,
642           g_value_get_boolean (value));
643       break;
644     case PROP_CLOCK:
645       gst_rtsp_media_set_clock (media, g_value_get_object (value));
646       break;
647     case PROP_MAX_MCAST_TTL:
648       gst_rtsp_media_set_max_mcast_ttl (media, g_value_get_uint (value));
649       break;
650     case PROP_BIND_MCAST_ADDRESS:
651       gst_rtsp_media_set_bind_mcast_address (media,
652           g_value_get_boolean (value));
653       break;
654     case PROP_DSCP_QOS:
655       gst_rtsp_media_set_dscp_qos (media, g_value_get_int (value));
656       break;
657     default:
658       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
659   }
660 }
661
662 typedef struct
663 {
664   gint64 position;
665   gboolean complete_streams_only;
666   gboolean ret;
667 } DoQueryPositionData;
668
669 static void
670 do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
671 {
672   gint64 tmp;
673
674   if (!gst_rtsp_stream_is_sender (stream))
675     return;
676
677   if (data->complete_streams_only && !gst_rtsp_stream_is_complete (stream)) {
678     GST_DEBUG_OBJECT (stream, "stream not complete, do not query position");
679     return;
680   }
681
682   if (gst_rtsp_stream_query_position (stream, &tmp)) {
683     data->position = MIN (data->position, tmp);
684     data->ret = TRUE;
685   }
686
687   GST_INFO_OBJECT (stream, "media position: %" GST_TIME_FORMAT,
688       GST_TIME_ARGS (data->position));
689 }
690
691 static gboolean
692 default_query_position (GstRTSPMedia * media, gint64 * position)
693 {
694   GstRTSPMediaPrivate *priv;
695   DoQueryPositionData data;
696
697   priv = media->priv;
698
699   data.position = G_MAXINT64;
700   data.ret = FALSE;
701
702   /* if the media is complete, i.e. one or more streams have been configured
703    * with sinks, then we want to query the position on those streams only.
704    * a query on an incmplete stream may return a position that originates from
705    * an earlier preroll */
706   if (check_complete (media))
707     data.complete_streams_only = TRUE;
708   else
709     data.complete_streams_only = FALSE;
710
711   g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
712
713   if (!data.ret)
714     *position = GST_CLOCK_TIME_NONE;
715   else
716     *position = data.position;
717
718   return data.ret;
719 }
720
721 typedef struct
722 {
723   gint64 stop;
724   gboolean ret;
725 } DoQueryStopData;
726
727 static void
728 do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
729 {
730   gint64 tmp = 0;
731
732   if (gst_rtsp_stream_query_stop (stream, &tmp)) {
733     data->stop = MAX (data->stop, tmp);
734     data->ret = TRUE;
735   }
736 }
737
738 static gboolean
739 default_query_stop (GstRTSPMedia * media, gint64 * stop)
740 {
741   GstRTSPMediaPrivate *priv;
742   DoQueryStopData data;
743
744   priv = media->priv;
745
746   data.stop = -1;
747   data.ret = FALSE;
748
749   g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
750
751   *stop = data.stop;
752
753   return data.ret;
754 }
755
756 static GstElement *
757 default_create_rtpbin (GstRTSPMedia * media)
758 {
759   GstElement *rtpbin;
760
761   rtpbin = gst_element_factory_make ("rtpbin", NULL);
762
763   return rtpbin;
764 }
765
766 /* Must be called with priv->lock */
767 static gboolean
768 is_receive_only (GstRTSPMedia * media)
769 {
770   GstRTSPMediaPrivate *priv = media->priv;
771   gboolean receive_only = TRUE;
772   guint i;
773
774   for (i = 0; i < priv->streams->len; i++) {
775     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
776     if (gst_rtsp_stream_is_sender (stream) ||
777         !gst_rtsp_stream_is_receiver (stream)) {
778       receive_only = FALSE;
779       break;
780     }
781   }
782
783   return receive_only;
784 }
785
786 /* must be called with state lock */
787 static void
788 check_seekable (GstRTSPMedia * media)
789 {
790   GstQuery *query;
791   GstRTSPMediaPrivate *priv = media->priv;
792
793   g_mutex_lock (&priv->lock);
794   /* Update the seekable state of the pipeline in case it changed */
795   if (is_receive_only (media)) {
796     /* TODO: Seeking for "receive-only"? */
797     priv->seekable = -1;
798   } else {
799     guint i, n = priv->streams->len;
800
801     for (i = 0; i < n; i++) {
802       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
803
804       if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
805           GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
806         priv->seekable = -1;
807         g_mutex_unlock (&priv->lock);
808         return;
809       }
810     }
811   }
812
813   query = gst_query_new_seeking (GST_FORMAT_TIME);
814   if (gst_element_query (priv->pipeline, query)) {
815     GstFormat format;
816     gboolean seekable;
817     gint64 start, end;
818
819     gst_query_parse_seeking (query, &format, &seekable, &start, &end);
820     priv->seekable = seekable ? G_MAXINT64 : 0;
821   } else if (priv->streams->len) {
822     gboolean seekable = TRUE;
823     guint i, n = priv->streams->len;
824
825     GST_DEBUG_OBJECT (media, "Checking %d streams", n);
826     for (i = 0; i < n; i++) {
827       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
828       seekable &= gst_rtsp_stream_seekable (stream);
829     }
830     priv->seekable = seekable ? G_MAXINT64 : -1;
831   }
832
833   GST_DEBUG_OBJECT (media, "seekable:%" G_GINT64_FORMAT, priv->seekable);
834   g_mutex_unlock (&priv->lock);
835   gst_query_unref (query);
836 }
837
838 /* must be called with state lock */
839 static gboolean
840 check_complete (GstRTSPMedia * media)
841 {
842   GstRTSPMediaPrivate *priv = media->priv;
843
844   guint i, n = priv->streams->len;
845
846   for (i = 0; i < n; i++) {
847     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
848
849     if (gst_rtsp_stream_is_complete (stream))
850       return TRUE;
851   }
852
853   return FALSE;
854 }
855
856 /* must be called with state lock and private lock */
857 static void
858 collect_media_stats (GstRTSPMedia * media)
859 {
860   GstRTSPMediaPrivate *priv = media->priv;
861   gint64 position = 0, stop = -1;
862
863   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
864       priv->status != GST_RTSP_MEDIA_STATUS_PREPARING) {
865     return;
866   }
867
868   priv->range.unit = GST_RTSP_RANGE_NPT;
869
870   GST_INFO ("collect media stats");
871
872   if (priv->is_live) {
873     priv->range.min.type = GST_RTSP_TIME_NOW;
874     priv->range.min.seconds = -1;
875     priv->range_start = -1;
876     priv->range.max.type = GST_RTSP_TIME_END;
877     priv->range.max.seconds = -1;
878     priv->range_stop = -1;
879   } else {
880     GstRTSPMediaClass *klass;
881     gboolean ret;
882
883     klass = GST_RTSP_MEDIA_GET_CLASS (media);
884
885     /* get the position */
886     ret = FALSE;
887     if (klass->query_position)
888       ret = klass->query_position (media, &position);
889
890     if (!ret) {
891       GST_INFO ("position query failed");
892       position = 0;
893     }
894
895     /* get the current segment stop */
896     ret = FALSE;
897     if (klass->query_stop)
898       ret = klass->query_stop (media, &stop);
899
900     if (!ret) {
901       GST_INFO ("stop query failed");
902       stop = -1;
903     }
904
905     GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
906         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
907
908     if (position == -1) {
909       priv->range.min.type = GST_RTSP_TIME_NOW;
910       priv->range.min.seconds = -1;
911       priv->range_start = -1;
912     } else {
913       priv->range.min.type = GST_RTSP_TIME_SECONDS;
914       priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
915       priv->range_start = position;
916     }
917     if (stop == -1) {
918       priv->range.max.type = GST_RTSP_TIME_END;
919       priv->range.max.seconds = -1;
920       priv->range_stop = -1;
921     } else {
922       priv->range.max.type = GST_RTSP_TIME_SECONDS;
923       priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
924       priv->range_stop = stop;
925     }
926     g_mutex_unlock (&priv->lock);
927     check_seekable (media);
928     g_mutex_lock (&priv->lock);
929   }
930 }
931
932 /**
933  * gst_rtsp_media_new:
934  * @element: (transfer full): a #GstElement
935  *
936  * Create a new #GstRTSPMedia instance. @element is the bin element that
937  * provides the different streams. The #GstRTSPMedia object contains the
938  * element to produce RTP data for one or more related (audio/video/..)
939  * streams.
940  *
941  * Ownership is taken of @element.
942  *
943  * Returns: (transfer full): a new #GstRTSPMedia object.
944  */
945 GstRTSPMedia *
946 gst_rtsp_media_new (GstElement * element)
947 {
948   GstRTSPMedia *result;
949
950   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
951
952   result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
953
954   return result;
955 }
956
957 /**
958  * gst_rtsp_media_get_element:
959  * @media: a #GstRTSPMedia
960  *
961  * Get the element that was used when constructing @media.
962  *
963  * Returns: (transfer full): a #GstElement. Unref after usage.
964  */
965 GstElement *
966 gst_rtsp_media_get_element (GstRTSPMedia * media)
967 {
968   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
969
970   return gst_object_ref (media->priv->element);
971 }
972
973 /**
974  * gst_rtsp_media_take_pipeline:
975  * @media: a #GstRTSPMedia
976  * @pipeline: (transfer floating): a #GstPipeline
977  *
978  * Set @pipeline as the #GstPipeline for @media. Ownership is
979  * taken of @pipeline.
980  */
981 void
982 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
983 {
984   GstRTSPMediaPrivate *priv;
985   GstElement *old;
986   GstNetTimeProvider *nettime;
987   GList *l;
988
989   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
990   g_return_if_fail (GST_IS_PIPELINE (pipeline));
991
992   priv = media->priv;
993
994   g_mutex_lock (&priv->lock);
995   old = priv->pipeline;
996   priv->pipeline = gst_object_ref_sink (GST_ELEMENT_CAST (pipeline));
997   nettime = priv->nettime;
998   priv->nettime = NULL;
999   g_mutex_unlock (&priv->lock);
1000
1001   if (old)
1002     gst_object_unref (old);
1003
1004   if (nettime)
1005     gst_object_unref (nettime);
1006
1007   gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
1008
1009   for (l = priv->pending_pipeline_elements; l; l = l->next) {
1010     gst_bin_add (GST_BIN_CAST (pipeline), l->data);
1011   }
1012   g_list_free (priv->pending_pipeline_elements);
1013   priv->pending_pipeline_elements = NULL;
1014 }
1015
1016 /**
1017  * gst_rtsp_media_set_permissions:
1018  * @media: a #GstRTSPMedia
1019  * @permissions: (transfer none) (nullable): a #GstRTSPPermissions
1020  *
1021  * Set @permissions on @media.
1022  */
1023 void
1024 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
1025     GstRTSPPermissions * permissions)
1026 {
1027   GstRTSPMediaPrivate *priv;
1028
1029   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1030
1031   priv = media->priv;
1032
1033   g_mutex_lock (&priv->lock);
1034   if (priv->permissions)
1035     gst_rtsp_permissions_unref (priv->permissions);
1036   if ((priv->permissions = permissions))
1037     gst_rtsp_permissions_ref (permissions);
1038   g_mutex_unlock (&priv->lock);
1039 }
1040
1041 /**
1042  * gst_rtsp_media_get_permissions:
1043  * @media: a #GstRTSPMedia
1044  *
1045  * Get the permissions object from @media.
1046  *
1047  * Returns: (transfer full) (nullable): a #GstRTSPPermissions object, unref after usage.
1048  */
1049 GstRTSPPermissions *
1050 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
1051 {
1052   GstRTSPMediaPrivate *priv;
1053   GstRTSPPermissions *result;
1054
1055   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1056
1057   priv = media->priv;
1058
1059   g_mutex_lock (&priv->lock);
1060   if ((result = priv->permissions))
1061     gst_rtsp_permissions_ref (result);
1062   g_mutex_unlock (&priv->lock);
1063
1064   return result;
1065 }
1066
1067 /**
1068  * gst_rtsp_media_set_suspend_mode:
1069  * @media: a #GstRTSPMedia
1070  * @mode: the new #GstRTSPSuspendMode
1071  *
1072  * Control how @ media will be suspended after the SDP has been generated and
1073  * after a PAUSE request has been performed.
1074  *
1075  * Media must be unprepared when setting the suspend mode.
1076  */
1077 void
1078 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
1079 {
1080   GstRTSPMediaPrivate *priv;
1081
1082   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1083
1084   priv = media->priv;
1085
1086   g_rec_mutex_lock (&priv->state_lock);
1087   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1088     goto was_prepared;
1089   priv->suspend_mode = mode;
1090   g_rec_mutex_unlock (&priv->state_lock);
1091
1092   return;
1093
1094   /* ERRORS */
1095 was_prepared:
1096   {
1097     GST_WARNING ("media %p was prepared", media);
1098     g_rec_mutex_unlock (&priv->state_lock);
1099   }
1100 }
1101
1102 /**
1103  * gst_rtsp_media_get_suspend_mode:
1104  * @media: a #GstRTSPMedia
1105  *
1106  * Get how @media will be suspended.
1107  *
1108  * Returns: #GstRTSPSuspendMode.
1109  */
1110 GstRTSPSuspendMode
1111 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
1112 {
1113   GstRTSPMediaPrivate *priv;
1114   GstRTSPSuspendMode res;
1115
1116   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
1117
1118   priv = media->priv;
1119
1120   g_rec_mutex_lock (&priv->state_lock);
1121   res = priv->suspend_mode;
1122   g_rec_mutex_unlock (&priv->state_lock);
1123
1124   return res;
1125 }
1126
1127 /**
1128  * gst_rtsp_media_set_shared:
1129  * @media: a #GstRTSPMedia
1130  * @shared: the new value
1131  *
1132  * Set or unset if the pipeline for @media can be shared will multiple clients.
1133  * When @shared is %TRUE, client requests for this media will share the media
1134  * pipeline.
1135  */
1136 void
1137 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
1138 {
1139   GstRTSPMediaPrivate *priv;
1140
1141   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1142
1143   priv = media->priv;
1144
1145   g_mutex_lock (&priv->lock);
1146   priv->shared = shared;
1147   g_mutex_unlock (&priv->lock);
1148 }
1149
1150 /**
1151  * gst_rtsp_media_is_shared:
1152  * @media: a #GstRTSPMedia
1153  *
1154  * Check if the pipeline for @media can be shared between multiple clients.
1155  *
1156  * Returns: %TRUE if the media can be shared between clients.
1157  */
1158 gboolean
1159 gst_rtsp_media_is_shared (GstRTSPMedia * media)
1160 {
1161   GstRTSPMediaPrivate *priv;
1162   gboolean res;
1163
1164   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1165
1166   priv = media->priv;
1167
1168   g_mutex_lock (&priv->lock);
1169   res = priv->shared;
1170   g_mutex_unlock (&priv->lock);
1171
1172   return res;
1173 }
1174
1175 /**
1176  * gst_rtsp_media_set_reusable:
1177  * @media: a #GstRTSPMedia
1178  * @reusable: the new value
1179  *
1180  * Set or unset if the pipeline for @media can be reused after the pipeline has
1181  * been unprepared.
1182  */
1183 void
1184 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
1185 {
1186   GstRTSPMediaPrivate *priv;
1187
1188   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1189
1190   priv = media->priv;
1191
1192   g_mutex_lock (&priv->lock);
1193   priv->reusable = reusable;
1194   g_mutex_unlock (&priv->lock);
1195 }
1196
1197 /**
1198  * gst_rtsp_media_is_reusable:
1199  * @media: a #GstRTSPMedia
1200  *
1201  * Check if the pipeline for @media can be reused after an unprepare.
1202  *
1203  * Returns: %TRUE if the media can be reused
1204  */
1205 gboolean
1206 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
1207 {
1208   GstRTSPMediaPrivate *priv;
1209   gboolean res;
1210
1211   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1212
1213   priv = media->priv;
1214
1215   g_mutex_lock (&priv->lock);
1216   res = priv->reusable;
1217   g_mutex_unlock (&priv->lock);
1218
1219   return res;
1220 }
1221
1222 static void
1223 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
1224 {
1225   gst_rtsp_stream_set_profiles (stream, *profiles);
1226 }
1227
1228 /**
1229  * gst_rtsp_media_set_profiles:
1230  * @media: a #GstRTSPMedia
1231  * @profiles: the new flags
1232  *
1233  * Configure the allowed lower transport for @media.
1234  */
1235 void
1236 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
1237 {
1238   GstRTSPMediaPrivate *priv;
1239
1240   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1241
1242   priv = media->priv;
1243
1244   g_mutex_lock (&priv->lock);
1245   priv->profiles = profiles;
1246   g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
1247   g_mutex_unlock (&priv->lock);
1248 }
1249
1250 /**
1251  * gst_rtsp_media_get_profiles:
1252  * @media: a #GstRTSPMedia
1253  *
1254  * Get the allowed profiles of @media.
1255  *
1256  * Returns: a #GstRTSPProfile
1257  */
1258 GstRTSPProfile
1259 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
1260 {
1261   GstRTSPMediaPrivate *priv;
1262   GstRTSPProfile res;
1263
1264   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
1265
1266   priv = media->priv;
1267
1268   g_mutex_lock (&priv->lock);
1269   res = priv->profiles;
1270   g_mutex_unlock (&priv->lock);
1271
1272   return res;
1273 }
1274
1275 static void
1276 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
1277 {
1278   gst_rtsp_stream_set_protocols (stream, *protocols);
1279 }
1280
1281 /**
1282  * gst_rtsp_media_set_protocols:
1283  * @media: a #GstRTSPMedia
1284  * @protocols: the new flags
1285  *
1286  * Configure the allowed lower transport for @media.
1287  */
1288 void
1289 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
1290 {
1291   GstRTSPMediaPrivate *priv;
1292
1293   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1294
1295   priv = media->priv;
1296
1297   g_mutex_lock (&priv->lock);
1298   priv->protocols = protocols;
1299   g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
1300   g_mutex_unlock (&priv->lock);
1301 }
1302
1303 /**
1304  * gst_rtsp_media_get_protocols:
1305  * @media: a #GstRTSPMedia
1306  *
1307  * Get the allowed protocols of @media.
1308  *
1309  * Returns: a #GstRTSPLowerTrans
1310  */
1311 GstRTSPLowerTrans
1312 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
1313 {
1314   GstRTSPMediaPrivate *priv;
1315   GstRTSPLowerTrans res;
1316
1317   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
1318       GST_RTSP_LOWER_TRANS_UNKNOWN);
1319
1320   priv = media->priv;
1321
1322   g_mutex_lock (&priv->lock);
1323   res = priv->protocols;
1324   g_mutex_unlock (&priv->lock);
1325
1326   return res;
1327 }
1328
1329 /**
1330  * gst_rtsp_media_set_eos_shutdown:
1331  * @media: a #GstRTSPMedia
1332  * @eos_shutdown: the new value
1333  *
1334  * Set or unset if an EOS event will be sent to the pipeline for @media before
1335  * it is unprepared.
1336  */
1337 void
1338 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
1339 {
1340   GstRTSPMediaPrivate *priv;
1341
1342   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1343
1344   priv = media->priv;
1345
1346   g_mutex_lock (&priv->lock);
1347   priv->eos_shutdown = eos_shutdown;
1348   g_mutex_unlock (&priv->lock);
1349 }
1350
1351 /**
1352  * gst_rtsp_media_is_eos_shutdown:
1353  * @media: a #GstRTSPMedia
1354  *
1355  * Check if the pipeline for @media will send an EOS down the pipeline before
1356  * unpreparing.
1357  *
1358  * Returns: %TRUE if the media will send EOS before unpreparing.
1359  */
1360 gboolean
1361 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
1362 {
1363   GstRTSPMediaPrivate *priv;
1364   gboolean res;
1365
1366   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1367
1368   priv = media->priv;
1369
1370   g_mutex_lock (&priv->lock);
1371   res = priv->eos_shutdown;
1372   g_mutex_unlock (&priv->lock);
1373
1374   return res;
1375 }
1376
1377 /**
1378  * gst_rtsp_media_set_buffer_size:
1379  * @media: a #GstRTSPMedia
1380  * @size: the new value
1381  *
1382  * Set the kernel UDP buffer size.
1383  */
1384 void
1385 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1386 {
1387   GstRTSPMediaPrivate *priv;
1388   guint i;
1389
1390   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1391
1392   GST_LOG_OBJECT (media, "set buffer size %u", size);
1393
1394   priv = media->priv;
1395
1396   g_mutex_lock (&priv->lock);
1397   priv->buffer_size = size;
1398
1399   for (i = 0; i < priv->streams->len; i++) {
1400     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1401     gst_rtsp_stream_set_buffer_size (stream, size);
1402   }
1403   g_mutex_unlock (&priv->lock);
1404 }
1405
1406 /**
1407  * gst_rtsp_media_get_buffer_size:
1408  * @media: a #GstRTSPMedia
1409  *
1410  * Get the kernel UDP buffer size.
1411  *
1412  * Returns: the kernel UDP buffer size.
1413  */
1414 guint
1415 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1416 {
1417   GstRTSPMediaPrivate *priv;
1418   guint res;
1419
1420   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1421
1422   priv = media->priv;
1423
1424   g_mutex_lock (&priv->lock);
1425   res = priv->buffer_size;
1426   g_mutex_unlock (&priv->lock);
1427
1428   return res;
1429 }
1430
1431 static void
1432 do_set_dscp_qos (GstRTSPStream * stream, gint * dscp_qos)
1433 {
1434   gst_rtsp_stream_set_dscp_qos (stream, *dscp_qos);
1435 }
1436
1437 /**
1438  * gst_rtsp_media_set_dscp_qos:
1439  * @media: a #GstRTSPMedia
1440  * @dscp_qos: a new dscp qos value (0-63, or -1 to disable)
1441  *
1442  * Configure the dscp qos of attached streams to @dscp_qos.
1443  *
1444  * Since: 1.18
1445  */
1446 void
1447 gst_rtsp_media_set_dscp_qos (GstRTSPMedia * media, gint dscp_qos)
1448 {
1449   GstRTSPMediaPrivate *priv;
1450
1451   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1452
1453   GST_LOG_OBJECT (media, "set DSCP QoS %d", dscp_qos);
1454
1455   if (dscp_qos < -1 || dscp_qos > 63) {
1456     GST_WARNING_OBJECT (media, "trying to set illegal dscp qos %d", dscp_qos);
1457     return;
1458   }
1459
1460   priv = media->priv;
1461
1462   g_mutex_lock (&priv->lock);
1463   priv->dscp_qos = dscp_qos;
1464   g_ptr_array_foreach (priv->streams, (GFunc) do_set_dscp_qos, &dscp_qos);
1465   g_mutex_unlock (&priv->lock);
1466 }
1467
1468 /**
1469  * gst_rtsp_media_get_dscp_qos:
1470  * @media: a #GstRTSPMedia
1471  *
1472  * Get the configured DSCP QoS of attached media.
1473  *
1474  * Returns: the DSCP QoS value of attached streams or -1 if disabled.
1475  *
1476  * Since: 1.18
1477  */
1478 gint
1479 gst_rtsp_media_get_dscp_qos (GstRTSPMedia * media)
1480 {
1481   GstRTSPMediaPrivate *priv;
1482   gint res;
1483
1484   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1485
1486   priv = media->priv;
1487
1488   g_mutex_unlock (&priv->lock);
1489   res = priv->dscp_qos;
1490   g_mutex_unlock (&priv->lock);
1491
1492   return res;
1493 }
1494
1495 /**
1496  * gst_rtsp_media_set_stop_on_disconnect:
1497  * @media: a #GstRTSPMedia
1498  * @stop_on_disconnect: the new value
1499  *
1500  * Set or unset if the pipeline for @media should be stopped when a
1501  * client disconnects without sending TEARDOWN.
1502  */
1503 void
1504 gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
1505     gboolean stop_on_disconnect)
1506 {
1507   GstRTSPMediaPrivate *priv;
1508
1509   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1510
1511   priv = media->priv;
1512
1513   g_mutex_lock (&priv->lock);
1514   priv->stop_on_disconnect = stop_on_disconnect;
1515   g_mutex_unlock (&priv->lock);
1516 }
1517
1518 /**
1519  * gst_rtsp_media_is_stop_on_disconnect:
1520  * @media: a #GstRTSPMedia
1521  *
1522  * Check if the pipeline for @media will be stopped when a client disconnects
1523  * without sending TEARDOWN.
1524  *
1525  * Returns: %TRUE if the media will be stopped when a client disconnects
1526  *     without sending TEARDOWN.
1527  */
1528 gboolean
1529 gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
1530 {
1531   GstRTSPMediaPrivate *priv;
1532   gboolean res;
1533
1534   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
1535
1536   priv = media->priv;
1537
1538   g_mutex_lock (&priv->lock);
1539   res = priv->stop_on_disconnect;
1540   g_mutex_unlock (&priv->lock);
1541
1542   return res;
1543 }
1544
1545 /**
1546  * gst_rtsp_media_set_retransmission_time:
1547  * @media: a #GstRTSPMedia
1548  * @time: the new value
1549  *
1550  * Set the amount of time to store retransmission packets.
1551  */
1552 void
1553 gst_rtsp_media_set_retransmission_time (GstRTSPMedia * media, GstClockTime time)
1554 {
1555   GstRTSPMediaPrivate *priv;
1556   guint i;
1557
1558   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1559
1560   GST_LOG_OBJECT (media, "set retransmission time %" G_GUINT64_FORMAT, time);
1561
1562   priv = media->priv;
1563
1564   g_mutex_lock (&priv->lock);
1565   priv->rtx_time = time;
1566   for (i = 0; i < priv->streams->len; i++) {
1567     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1568
1569     gst_rtsp_stream_set_retransmission_time (stream, time);
1570   }
1571   g_mutex_unlock (&priv->lock);
1572 }
1573
1574 /**
1575  * gst_rtsp_media_get_retransmission_time:
1576  * @media: a #GstRTSPMedia
1577  *
1578  * Get the amount of time to store retransmission data.
1579  *
1580  * Returns: the amount of time to store retransmission data.
1581  */
1582 GstClockTime
1583 gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
1584 {
1585   GstRTSPMediaPrivate *priv;
1586   GstClockTime res;
1587
1588   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1589
1590   priv = media->priv;
1591
1592   g_mutex_lock (&priv->lock);
1593   res = priv->rtx_time;
1594   g_mutex_unlock (&priv->lock);
1595
1596   return res;
1597 }
1598
1599 /**
1600  * gst_rtsp_media_set_do_retransmission:
1601  *
1602  * Set whether retransmission requests will be sent
1603  *
1604  * Since: 1.16
1605  */
1606 void
1607 gst_rtsp_media_set_do_retransmission (GstRTSPMedia * media,
1608     gboolean do_retransmission)
1609 {
1610   GstRTSPMediaPrivate *priv;
1611
1612   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1613
1614   priv = media->priv;
1615
1616   g_mutex_lock (&priv->lock);
1617   priv->do_retransmission = do_retransmission;
1618
1619   if (priv->rtpbin)
1620     g_object_set (priv->rtpbin, "do-retransmission", do_retransmission, NULL);
1621   g_mutex_unlock (&priv->lock);
1622 }
1623
1624 /**
1625  * gst_rtsp_media_get_do_retransmission:
1626  *
1627  * Returns: Whether retransmission requests will be sent
1628  *
1629  * Since: 1.16
1630  */
1631 gboolean
1632 gst_rtsp_media_get_do_retransmission (GstRTSPMedia * media)
1633 {
1634   GstRTSPMediaPrivate *priv;
1635   gboolean res;
1636
1637   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1638
1639   priv = media->priv;
1640
1641   g_mutex_lock (&priv->lock);
1642   res = priv->do_retransmission;
1643   g_mutex_unlock (&priv->lock);
1644
1645   return res;
1646 }
1647
1648 /**
1649  * gst_rtsp_media_set_latency:
1650  * @media: a #GstRTSPMedia
1651  * @latency: latency in milliseconds
1652  *
1653  * Configure the latency used for receiving media.
1654  */
1655 void
1656 gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
1657 {
1658   GstRTSPMediaPrivate *priv;
1659   guint i;
1660
1661   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1662
1663   GST_LOG_OBJECT (media, "set latency %ums", latency);
1664
1665   priv = media->priv;
1666
1667   g_mutex_lock (&priv->lock);
1668   priv->latency = latency;
1669   if (priv->rtpbin) {
1670     g_object_set (priv->rtpbin, "latency", latency, NULL);
1671
1672     for (i = 0; i < media->priv->streams->len; i++) {
1673       GObject *storage = NULL;
1674
1675       g_signal_emit_by_name (G_OBJECT (media->priv->rtpbin), "get-storage",
1676           i, &storage);
1677       if (storage)
1678         g_object_set (storage, "size-time",
1679             (media->priv->latency + 50) * GST_MSECOND, NULL);
1680     }
1681   }
1682
1683   g_mutex_unlock (&priv->lock);
1684 }
1685
1686 /**
1687  * gst_rtsp_media_get_latency:
1688  * @media: a #GstRTSPMedia
1689  *
1690  * Get the latency that is used for receiving media.
1691  *
1692  * Returns: latency in milliseconds
1693  */
1694 guint
1695 gst_rtsp_media_get_latency (GstRTSPMedia * media)
1696 {
1697   GstRTSPMediaPrivate *priv;
1698   guint res;
1699
1700   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1701
1702   priv = media->priv;
1703
1704   g_mutex_lock (&priv->lock);
1705   res = priv->latency;
1706   g_mutex_unlock (&priv->lock);
1707
1708   return res;
1709 }
1710
1711 /**
1712  * gst_rtsp_media_use_time_provider:
1713  * @media: a #GstRTSPMedia
1714  * @time_provider: if a #GstNetTimeProvider should be used
1715  *
1716  * Set @media to provide a #GstNetTimeProvider.
1717  */
1718 void
1719 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1720 {
1721   GstRTSPMediaPrivate *priv;
1722
1723   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1724
1725   priv = media->priv;
1726
1727   g_mutex_lock (&priv->lock);
1728   priv->time_provider = time_provider;
1729   g_mutex_unlock (&priv->lock);
1730 }
1731
1732 /**
1733  * gst_rtsp_media_is_time_provider:
1734  * @media: a #GstRTSPMedia
1735  *
1736  * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1737  *
1738  * Use gst_rtsp_media_get_time_provider() to get the network clock.
1739  *
1740  * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1741  */
1742 gboolean
1743 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1744 {
1745   GstRTSPMediaPrivate *priv;
1746   gboolean res;
1747
1748   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1749
1750   priv = media->priv;
1751
1752   g_mutex_lock (&priv->lock);
1753   res = priv->time_provider;
1754   g_mutex_unlock (&priv->lock);
1755
1756   return res;
1757 }
1758
1759 /**
1760  * gst_rtsp_media_set_clock:
1761  * @media: a #GstRTSPMedia
1762  * @clock: (nullable): #GstClock to be used
1763  *
1764  * Configure the clock used for the media.
1765  */
1766 void
1767 gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
1768 {
1769   GstRTSPMediaPrivate *priv;
1770
1771   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1772   g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1773
1774   GST_LOG_OBJECT (media, "setting clock %" GST_PTR_FORMAT, clock);
1775
1776   priv = media->priv;
1777
1778   g_mutex_lock (&priv->lock);
1779   if (priv->clock)
1780     gst_object_unref (priv->clock);
1781   priv->clock = clock ? gst_object_ref (clock) : NULL;
1782   if (priv->pipeline) {
1783     if (clock)
1784       gst_pipeline_use_clock (GST_PIPELINE_CAST (priv->pipeline), clock);
1785     else
1786       gst_pipeline_auto_clock (GST_PIPELINE_CAST (priv->pipeline));
1787   }
1788
1789   g_mutex_unlock (&priv->lock);
1790 }
1791
1792 /**
1793  * gst_rtsp_media_set_publish_clock_mode:
1794  * @media: a #GstRTSPMedia
1795  * @mode: the clock publish mode
1796  *
1797  * Sets if and how the media clock should be published according to RFC7273.
1798  *
1799  * Since: 1.8
1800  */
1801 void
1802 gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
1803     GstRTSPPublishClockMode mode)
1804 {
1805   GstRTSPMediaPrivate *priv;
1806   guint i, n;
1807
1808   priv = media->priv;
1809   g_mutex_lock (&priv->lock);
1810   priv->publish_clock_mode = mode;
1811
1812   n = priv->streams->len;
1813   for (i = 0; i < n; i++) {
1814     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1815
1816     gst_rtsp_stream_set_publish_clock_mode (stream, mode);
1817   }
1818   g_mutex_unlock (&priv->lock);
1819 }
1820
1821 /**
1822  * gst_rtsp_media_get_publish_clock_mode:
1823  * @media: a #GstRTSPMedia
1824  *
1825  * Gets if and how the media clock should be published according to RFC7273.
1826  *
1827  * Returns: The GstRTSPPublishClockMode
1828  *
1829  * Since: 1.8
1830  */
1831 GstRTSPPublishClockMode
1832 gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
1833 {
1834   GstRTSPMediaPrivate *priv;
1835   GstRTSPPublishClockMode ret;
1836
1837   priv = media->priv;
1838   g_mutex_lock (&priv->lock);
1839   ret = priv->publish_clock_mode;
1840   g_mutex_unlock (&priv->lock);
1841
1842   return ret;
1843 }
1844
1845 /**
1846  * gst_rtsp_media_set_address_pool:
1847  * @media: a #GstRTSPMedia
1848  * @pool: (transfer none) (nullable): a #GstRTSPAddressPool
1849  *
1850  * configure @pool to be used as the address pool of @media.
1851  */
1852 void
1853 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1854     GstRTSPAddressPool * pool)
1855 {
1856   GstRTSPMediaPrivate *priv;
1857   GstRTSPAddressPool *old;
1858
1859   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1860
1861   priv = media->priv;
1862
1863   GST_LOG_OBJECT (media, "set address pool %p", pool);
1864
1865   g_mutex_lock (&priv->lock);
1866   if ((old = priv->pool) != pool)
1867     priv->pool = pool ? g_object_ref (pool) : NULL;
1868   else
1869     old = NULL;
1870   g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1871       pool);
1872   g_mutex_unlock (&priv->lock);
1873
1874   if (old)
1875     g_object_unref (old);
1876 }
1877
1878 /**
1879  * gst_rtsp_media_get_address_pool:
1880  * @media: a #GstRTSPMedia
1881  *
1882  * Get the #GstRTSPAddressPool used as the address pool of @media.
1883  *
1884  * Returns: (transfer full) (nullable): the #GstRTSPAddressPool of @media.
1885  * g_object_unref() after usage.
1886  */
1887 GstRTSPAddressPool *
1888 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1889 {
1890   GstRTSPMediaPrivate *priv;
1891   GstRTSPAddressPool *result;
1892
1893   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1894
1895   priv = media->priv;
1896
1897   g_mutex_lock (&priv->lock);
1898   if ((result = priv->pool))
1899     g_object_ref (result);
1900   g_mutex_unlock (&priv->lock);
1901
1902   return result;
1903 }
1904
1905 /**
1906  * gst_rtsp_media_set_multicast_iface:
1907  * @media: a #GstRTSPMedia
1908  * @multicast_iface: (transfer none) (nullable): a multicast interface name
1909  *
1910  * configure @multicast_iface to be used for @media.
1911  */
1912 void
1913 gst_rtsp_media_set_multicast_iface (GstRTSPMedia * media,
1914     const gchar * multicast_iface)
1915 {
1916   GstRTSPMediaPrivate *priv;
1917   gchar *old;
1918
1919   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1920
1921   priv = media->priv;
1922
1923   GST_LOG_OBJECT (media, "set multicast interface %s", multicast_iface);
1924
1925   g_mutex_lock (&priv->lock);
1926   if ((old = priv->multicast_iface) != multicast_iface)
1927     priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
1928   else
1929     old = NULL;
1930   g_ptr_array_foreach (priv->streams,
1931       (GFunc) gst_rtsp_stream_set_multicast_iface, (gchar *) multicast_iface);
1932   g_mutex_unlock (&priv->lock);
1933
1934   if (old)
1935     g_free (old);
1936 }
1937
1938 /**
1939  * gst_rtsp_media_get_multicast_iface:
1940  * @media: a #GstRTSPMedia
1941  *
1942  * Get the multicast interface used for @media.
1943  *
1944  * Returns: (transfer full) (nullable): the multicast interface for @media.
1945  * g_free() after usage.
1946  */
1947 gchar *
1948 gst_rtsp_media_get_multicast_iface (GstRTSPMedia * media)
1949 {
1950   GstRTSPMediaPrivate *priv;
1951   gchar *result;
1952
1953   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1954
1955   priv = media->priv;
1956
1957   g_mutex_lock (&priv->lock);
1958   if ((result = priv->multicast_iface))
1959     result = g_strdup (result);
1960   g_mutex_unlock (&priv->lock);
1961
1962   return result;
1963 }
1964
1965 /**
1966  * gst_rtsp_media_set_max_mcast_ttl:
1967  * @media: a #GstRTSPMedia
1968  * @ttl: the new multicast ttl value
1969  *
1970  * Set the maximum time-to-live value of outgoing multicast packets.
1971  *
1972  * Returns: %TRUE if the requested ttl has been set successfully.
1973  *
1974  * Since: 1.16
1975  */
1976 gboolean
1977 gst_rtsp_media_set_max_mcast_ttl (GstRTSPMedia * media, guint ttl)
1978 {
1979   GstRTSPMediaPrivate *priv;
1980   guint i;
1981
1982   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1983
1984   GST_LOG_OBJECT (media, "set max mcast ttl %u", ttl);
1985
1986   priv = media->priv;
1987
1988   g_mutex_lock (&priv->lock);
1989
1990   if (ttl == 0 || ttl > DEFAULT_MAX_MCAST_TTL) {
1991     GST_WARNING_OBJECT (media, "The reqested mcast TTL value is not valid.");
1992     g_mutex_unlock (&priv->lock);
1993     return FALSE;
1994   }
1995   priv->max_mcast_ttl = ttl;
1996
1997   for (i = 0; i < priv->streams->len; i++) {
1998     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1999     gst_rtsp_stream_set_max_mcast_ttl (stream, ttl);
2000   }
2001   g_mutex_unlock (&priv->lock);
2002
2003   return TRUE;
2004 }
2005
2006 /**
2007  * gst_rtsp_media_get_max_mcast_ttl:
2008  * @media: a #GstRTSPMedia
2009  *
2010  * Get the the maximum time-to-live value of outgoing multicast packets.
2011  *
2012  * Returns: the maximum time-to-live value of outgoing multicast packets.
2013  *
2014  * Since: 1.16
2015  */
2016 guint
2017 gst_rtsp_media_get_max_mcast_ttl (GstRTSPMedia * media)
2018 {
2019   GstRTSPMediaPrivate *priv;
2020   guint res;
2021
2022   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2023
2024   priv = media->priv;
2025
2026   g_mutex_lock (&priv->lock);
2027   res = priv->max_mcast_ttl;
2028   g_mutex_unlock (&priv->lock);
2029
2030   return res;
2031 }
2032
2033 /**
2034  * gst_rtsp_media_set_bind_mcast_address:
2035  * @media: a #GstRTSPMedia
2036  * @bind_mcast_addr: the new value
2037  *
2038  * Decide whether the multicast socket should be bound to a multicast address or
2039  * INADDR_ANY.
2040  *
2041  * Since: 1.16
2042  */
2043 void
2044 gst_rtsp_media_set_bind_mcast_address (GstRTSPMedia * media,
2045     gboolean bind_mcast_addr)
2046 {
2047   GstRTSPMediaPrivate *priv;
2048   guint i;
2049
2050   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2051
2052   priv = media->priv;
2053
2054   g_mutex_lock (&priv->lock);
2055   priv->bind_mcast_address = bind_mcast_addr;
2056   for (i = 0; i < priv->streams->len; i++) {
2057     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2058     gst_rtsp_stream_set_bind_mcast_address (stream, bind_mcast_addr);
2059   }
2060   g_mutex_unlock (&priv->lock);
2061 }
2062
2063 /**
2064  * gst_rtsp_media_is_bind_mcast_address:
2065  * @media: a #GstRTSPMedia
2066  *
2067  * Check if multicast sockets are configured to be bound to multicast addresses.
2068  *
2069  * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
2070  *
2071  * Since: 1.16
2072  */
2073 gboolean
2074 gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia * media)
2075 {
2076   GstRTSPMediaPrivate *priv;
2077   gboolean result;
2078
2079   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2080
2081   priv = media->priv;
2082
2083   g_mutex_lock (&priv->lock);
2084   result = priv->bind_mcast_address;
2085   g_mutex_unlock (&priv->lock);
2086
2087   return result;
2088 }
2089
2090 static GList *
2091 _find_payload_types (GstRTSPMedia * media)
2092 {
2093   gint i, n;
2094   GQueue queue = G_QUEUE_INIT;
2095
2096   n = media->priv->streams->len;
2097   for (i = 0; i < n; i++) {
2098     GstRTSPStream *stream = g_ptr_array_index (media->priv->streams, i);
2099     guint pt = gst_rtsp_stream_get_pt (stream);
2100
2101     g_queue_push_tail (&queue, GUINT_TO_POINTER (pt));
2102   }
2103
2104   return queue.head;
2105 }
2106
2107 static guint
2108 _next_available_pt (GList * payloads)
2109 {
2110   guint i;
2111
2112   for (i = 96; i <= 127; i++) {
2113     GList *iter = g_list_find (payloads, GINT_TO_POINTER (i));
2114     if (!iter)
2115       return GPOINTER_TO_UINT (i);
2116   }
2117
2118   return 0;
2119 }
2120
2121 /**
2122  * gst_rtsp_media_collect_streams:
2123  * @media: a #GstRTSPMedia
2124  *
2125  * Find all payloader elements, they should be named pay\%d in the
2126  * element of @media, and create #GstRTSPStreams for them.
2127  *
2128  * Collect all dynamic elements, named dynpay\%d, and add them to
2129  * the list of dynamic elements.
2130  *
2131  * Find all depayloader elements, they should be named depay\%d in the
2132  * element of @media, and create #GstRTSPStreams for them.
2133  */
2134 void
2135 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
2136 {
2137   GstRTSPMediaPrivate *priv;
2138   GstElement *element, *elem;
2139   GstPad *pad;
2140   gint i;
2141   gboolean have_elem;
2142   gboolean more_elem_remaining = TRUE;
2143   GstRTSPTransportMode mode = 0;
2144
2145   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2146
2147   priv = media->priv;
2148   element = priv->element;
2149
2150   have_elem = FALSE;
2151   for (i = 0; more_elem_remaining; i++) {
2152     gchar *name;
2153
2154     more_elem_remaining = FALSE;
2155
2156     name = g_strdup_printf ("pay%d", i);
2157     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2158       GstElement *pay;
2159       GST_INFO ("found stream %d with payloader %p", i, elem);
2160
2161       /* take the pad of the payloader */
2162       pad = gst_element_get_static_pad (elem, "src");
2163
2164       /* find the real payload element in case elem is a GstBin */
2165       pay = find_payload_element (elem, pad);
2166
2167       /* create the stream */
2168       if (pay == NULL) {
2169         GST_WARNING ("could not find real payloader, using bin");
2170         gst_rtsp_media_create_stream (media, elem, pad);
2171       } else {
2172         gst_rtsp_media_create_stream (media, pay, pad);
2173         gst_object_unref (pay);
2174       }
2175
2176       gst_object_unref (pad);
2177       gst_object_unref (elem);
2178
2179       have_elem = TRUE;
2180       more_elem_remaining = TRUE;
2181       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2182     }
2183     g_free (name);
2184
2185     name = g_strdup_printf ("dynpay%d", i);
2186     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2187       /* a stream that will dynamically create pads to provide RTP packets */
2188       GST_INFO ("found dynamic element %d, %p", i, elem);
2189
2190       g_mutex_lock (&priv->lock);
2191       priv->dynamic = g_list_prepend (priv->dynamic, elem);
2192       g_mutex_unlock (&priv->lock);
2193
2194       priv->nb_dynamic_elements++;
2195
2196       have_elem = TRUE;
2197       more_elem_remaining = TRUE;
2198       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2199     }
2200     g_free (name);
2201
2202     name = g_strdup_printf ("depay%d", i);
2203     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2204       GST_INFO ("found stream %d with depayloader %p", i, elem);
2205
2206       /* take the pad of the payloader */
2207       pad = gst_element_get_static_pad (elem, "sink");
2208       /* create the stream */
2209       gst_rtsp_media_create_stream (media, elem, pad);
2210       gst_object_unref (pad);
2211       gst_object_unref (elem);
2212
2213       have_elem = TRUE;
2214       more_elem_remaining = TRUE;
2215       mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
2216     }
2217     g_free (name);
2218   }
2219
2220   if (have_elem) {
2221     if (priv->transport_mode != mode)
2222       GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
2223           priv->transport_mode, mode);
2224   }
2225 }
2226
2227 typedef struct
2228 {
2229   GstElement *appsink, *appsrc;
2230   GstRTSPStream *stream;
2231 } AppSinkSrcData;
2232
2233 static GstFlowReturn
2234 appsink_new_sample (GstAppSink * appsink, gpointer user_data)
2235 {
2236   AppSinkSrcData *data = user_data;
2237   GstSample *sample;
2238   GstFlowReturn ret;
2239
2240   sample = gst_app_sink_pull_sample (appsink);
2241   if (!sample)
2242     return GST_FLOW_FLUSHING;
2243
2244
2245   ret = gst_app_src_push_sample (GST_APP_SRC (data->appsrc), sample);
2246   gst_sample_unref (sample);
2247   return ret;
2248 }
2249
2250 static GstAppSinkCallbacks appsink_callbacks = {
2251   NULL,
2252   NULL,
2253   appsink_new_sample,
2254 };
2255
2256 static GstPadProbeReturn
2257 appsink_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2258 {
2259   AppSinkSrcData *data = user_data;
2260
2261   if (GST_IS_EVENT (info->data)
2262       && GST_EVENT_TYPE (info->data) == GST_EVENT_LATENCY) {
2263     GstClockTime min, max;
2264
2265     if (gst_base_sink_query_latency (GST_BASE_SINK (data->appsink), NULL, NULL,
2266             &min, &max)) {
2267       g_object_set (data->appsrc, "min-latency", min, "max-latency", max, NULL);
2268       GST_DEBUG ("setting latency to min %" GST_TIME_FORMAT " max %"
2269           GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
2270     }
2271   } else if (GST_IS_QUERY (info->data)) {
2272     GstPad *srcpad = gst_element_get_static_pad (data->appsrc, "src");
2273     if (gst_pad_peer_query (srcpad, GST_QUERY_CAST (info->data))) {
2274       gst_object_unref (srcpad);
2275       return GST_PAD_PROBE_HANDLED;
2276     }
2277     gst_object_unref (srcpad);
2278   }
2279
2280   return GST_PAD_PROBE_OK;
2281 }
2282
2283 static GstPadProbeReturn
2284 appsrc_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2285 {
2286   AppSinkSrcData *data = user_data;
2287
2288   if (GST_IS_QUERY (info->data)) {
2289     GstPad *sinkpad = gst_element_get_static_pad (data->appsink, "sink");
2290     if (gst_pad_peer_query (sinkpad, GST_QUERY_CAST (info->data))) {
2291       gst_object_unref (sinkpad);
2292       return GST_PAD_PROBE_HANDLED;
2293     }
2294     gst_object_unref (sinkpad);
2295   }
2296
2297   return GST_PAD_PROBE_OK;
2298 }
2299
2300 /**
2301  * gst_rtsp_media_create_stream:
2302  * @media: a #GstRTSPMedia
2303  * @payloader: a #GstElement
2304  * @pad: a #GstPad
2305  *
2306  * Create a new stream in @media that provides RTP data on @pad.
2307  * @pad should be a pad of an element inside @media->element.
2308  *
2309  * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
2310  * as @media exists.
2311  */
2312 GstRTSPStream *
2313 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
2314     GstPad * pad)
2315 {
2316   GstRTSPMediaPrivate *priv;
2317   GstRTSPStream *stream;
2318   GstPad *streampad;
2319   gchar *name;
2320   gint idx;
2321   AppSinkSrcData *data = NULL;
2322
2323   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2324   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
2325   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2326
2327   priv = media->priv;
2328
2329   g_mutex_lock (&priv->lock);
2330   idx = priv->streams->len;
2331
2332   GST_DEBUG ("media %p: creating stream with index %d and payloader %"
2333       GST_PTR_FORMAT, media, idx, payloader);
2334
2335   if (GST_PAD_IS_SRC (pad))
2336     name = g_strdup_printf ("src_%u", idx);
2337   else
2338     name = g_strdup_printf ("sink_%u", idx);
2339
2340   if ((GST_PAD_IS_SRC (pad) && priv->element->numsinkpads > 0) ||
2341       (GST_PAD_IS_SINK (pad) && priv->element->numsrcpads > 0)) {
2342     GstElement *appsink, *appsrc;
2343     GstPad *sinkpad, *srcpad;
2344
2345     appsink = gst_element_factory_make ("appsink", NULL);
2346     appsrc = gst_element_factory_make ("appsrc", NULL);
2347
2348     if (GST_PAD_IS_SINK (pad)) {
2349       srcpad = gst_element_get_static_pad (appsrc, "src");
2350
2351       gst_bin_add (GST_BIN (priv->element), appsrc);
2352
2353       gst_pad_link (srcpad, pad);
2354       gst_object_unref (srcpad);
2355
2356       streampad = gst_element_get_static_pad (appsink, "sink");
2357
2358       priv->pending_pipeline_elements =
2359           g_list_prepend (priv->pending_pipeline_elements, appsink);
2360     } else {
2361       sinkpad = gst_element_get_static_pad (appsink, "sink");
2362
2363       gst_pad_link (pad, sinkpad);
2364       gst_object_unref (sinkpad);
2365
2366       streampad = gst_element_get_static_pad (appsrc, "src");
2367
2368       priv->pending_pipeline_elements =
2369           g_list_prepend (priv->pending_pipeline_elements, appsrc);
2370     }
2371
2372     g_object_set (appsrc, "block", TRUE, "format", GST_FORMAT_TIME, "is-live",
2373         TRUE, "emit-signals", FALSE, NULL);
2374     g_object_set (appsink, "sync", FALSE, "async", FALSE, "emit-signals",
2375         FALSE, "buffer-list", TRUE, NULL);
2376
2377     data = g_new0 (AppSinkSrcData, 1);
2378     data->appsink = appsink;
2379     data->appsrc = appsrc;
2380
2381     sinkpad = gst_element_get_static_pad (appsink, "sink");
2382     gst_pad_add_probe (sinkpad,
2383         GST_PAD_PROBE_TYPE_EVENT_UPSTREAM | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM,
2384         appsink_pad_probe, data, NULL);
2385     gst_object_unref (sinkpad);
2386
2387     srcpad = gst_element_get_static_pad (appsrc, "src");
2388     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_QUERY_UPSTREAM,
2389         appsrc_pad_probe, data, NULL);
2390     gst_object_unref (srcpad);
2391
2392     gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &appsink_callbacks,
2393         data, NULL);
2394     g_object_set_data_full (G_OBJECT (streampad), "media-appsink-appsrc", data,
2395         g_free);
2396   } else {
2397     streampad = gst_ghost_pad_new (name, pad);
2398     gst_pad_set_active (streampad, TRUE);
2399     gst_element_add_pad (priv->element, streampad);
2400   }
2401   g_free (name);
2402
2403   stream = gst_rtsp_stream_new (idx, payloader, streampad);
2404   if (data)
2405     data->stream = stream;
2406   if (priv->pool)
2407     gst_rtsp_stream_set_address_pool (stream, priv->pool);
2408   gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface);
2409   gst_rtsp_stream_set_max_mcast_ttl (stream, priv->max_mcast_ttl);
2410   gst_rtsp_stream_set_bind_mcast_address (stream, priv->bind_mcast_address);
2411   gst_rtsp_stream_set_profiles (stream, priv->profiles);
2412   gst_rtsp_stream_set_protocols (stream, priv->protocols);
2413   gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
2414   gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
2415   gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
2416   gst_rtsp_stream_set_rate_control (stream, priv->do_rate_control);
2417
2418   g_ptr_array_add (priv->streams, stream);
2419
2420   if (GST_PAD_IS_SRC (pad)) {
2421     gint i, n;
2422
2423     if (priv->payloads)
2424       g_list_free (priv->payloads);
2425     priv->payloads = _find_payload_types (media);
2426
2427     n = priv->streams->len;
2428     for (i = 0; i < n; i++) {
2429       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2430       guint rtx_pt = _next_available_pt (priv->payloads);
2431
2432       if (rtx_pt == 0) {
2433         GST_WARNING ("Ran out of space of dynamic payload types");
2434         break;
2435       }
2436
2437       gst_rtsp_stream_set_retransmission_pt (stream, rtx_pt);
2438
2439       priv->payloads =
2440           g_list_append (priv->payloads, GUINT_TO_POINTER (rtx_pt));
2441     }
2442   }
2443   g_mutex_unlock (&priv->lock);
2444
2445   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
2446       NULL);
2447
2448   return stream;
2449 }
2450
2451 static void
2452 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
2453 {
2454   GstRTSPMediaPrivate *priv;
2455   GstPad *srcpad;
2456   AppSinkSrcData *data;
2457
2458   priv = media->priv;
2459
2460   g_mutex_lock (&priv->lock);
2461   /* remove the ghostpad */
2462   srcpad = gst_rtsp_stream_get_srcpad (stream);
2463   data = g_object_get_data (G_OBJECT (srcpad), "media-appsink-appsrc");
2464   if (data) {
2465     if (GST_OBJECT_PARENT (data->appsrc) == GST_OBJECT_CAST (priv->pipeline))
2466       gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsrc);
2467     else if (GST_OBJECT_PARENT (data->appsrc) ==
2468         GST_OBJECT_CAST (priv->element))
2469       gst_bin_remove (GST_BIN_CAST (priv->element), data->appsrc);
2470     if (GST_OBJECT_PARENT (data->appsink) == GST_OBJECT_CAST (priv->pipeline))
2471       gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsink);
2472     else if (GST_OBJECT_PARENT (data->appsink) ==
2473         GST_OBJECT_CAST (priv->element))
2474       gst_bin_remove (GST_BIN_CAST (priv->element), data->appsink);
2475   } else {
2476     gst_element_remove_pad (priv->element, srcpad);
2477   }
2478   gst_object_unref (srcpad);
2479   /* now remove the stream */
2480   g_object_ref (stream);
2481   g_ptr_array_remove (priv->streams, stream);
2482   g_mutex_unlock (&priv->lock);
2483
2484   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
2485       stream, NULL);
2486
2487   g_object_unref (stream);
2488 }
2489
2490 /**
2491  * gst_rtsp_media_n_streams:
2492  * @media: a #GstRTSPMedia
2493  *
2494  * Get the number of streams in this media.
2495  *
2496  * Returns: The number of streams.
2497  */
2498 guint
2499 gst_rtsp_media_n_streams (GstRTSPMedia * media)
2500 {
2501   GstRTSPMediaPrivate *priv;
2502   guint res;
2503
2504   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
2505
2506   priv = media->priv;
2507
2508   g_mutex_lock (&priv->lock);
2509   res = priv->streams->len;
2510   g_mutex_unlock (&priv->lock);
2511
2512   return res;
2513 }
2514
2515 /**
2516  * gst_rtsp_media_get_stream:
2517  * @media: a #GstRTSPMedia
2518  * @idx: the stream index
2519  *
2520  * Retrieve the stream with index @idx from @media.
2521  *
2522  * Returns: (nullable) (transfer none): the #GstRTSPStream at index
2523  * @idx or %NULL when a stream with that index did not exist.
2524  */
2525 GstRTSPStream *
2526 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
2527 {
2528   GstRTSPMediaPrivate *priv;
2529   GstRTSPStream *res;
2530
2531   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2532
2533   priv = media->priv;
2534
2535   g_mutex_lock (&priv->lock);
2536   if (idx < priv->streams->len)
2537     res = g_ptr_array_index (priv->streams, idx);
2538   else
2539     res = NULL;
2540   g_mutex_unlock (&priv->lock);
2541
2542   return res;
2543 }
2544
2545 /**
2546  * gst_rtsp_media_find_stream:
2547  * @media: a #GstRTSPMedia
2548  * @control: the control of the stream
2549  *
2550  * Find a stream in @media with @control as the control uri.
2551  *
2552  * Returns: (nullable) (transfer none): the #GstRTSPStream with
2553  * control uri @control or %NULL when a stream with that control did
2554  * not exist.
2555  */
2556 GstRTSPStream *
2557 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
2558 {
2559   GstRTSPMediaPrivate *priv;
2560   GstRTSPStream *res;
2561   gint i;
2562
2563   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2564   g_return_val_if_fail (control != NULL, NULL);
2565
2566   priv = media->priv;
2567
2568   res = NULL;
2569
2570   g_mutex_lock (&priv->lock);
2571   for (i = 0; i < priv->streams->len; i++) {
2572     GstRTSPStream *test;
2573
2574     test = g_ptr_array_index (priv->streams, i);
2575     if (gst_rtsp_stream_has_control (test, control)) {
2576       res = test;
2577       break;
2578     }
2579   }
2580   g_mutex_unlock (&priv->lock);
2581
2582   return res;
2583 }
2584
2585 /* called with state-lock */
2586 static gboolean
2587 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
2588     GstRTSPRangeUnit unit)
2589 {
2590   return gst_rtsp_range_convert_units (range, unit);
2591 }
2592
2593 /**
2594  * gst_rtsp_media_get_range_string:
2595  * @media: a #GstRTSPMedia
2596  * @play: for the PLAY request
2597  * @unit: the unit to use for the string
2598  *
2599  * Get the current range as a string. @media must be prepared with
2600  * gst_rtsp_media_prepare ().
2601  *
2602  * Returns: (transfer full) (nullable): The range as a string, g_free() after usage.
2603  */
2604 gchar *
2605 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
2606     GstRTSPRangeUnit unit)
2607 {
2608   GstRTSPMediaClass *klass;
2609   GstRTSPMediaPrivate *priv;
2610   gchar *result;
2611   GstRTSPTimeRange range;
2612
2613   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2614   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2615   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2616
2617   priv = media->priv;
2618
2619   g_rec_mutex_lock (&priv->state_lock);
2620   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2621       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2622     goto not_prepared;
2623
2624   /* Update the range value with current position/duration */
2625   g_mutex_lock (&priv->lock);
2626   collect_media_stats (media);
2627
2628   /* make copy */
2629   range = priv->range;
2630
2631   if (!play && priv->n_active > 0) {
2632     range.min.type = GST_RTSP_TIME_NOW;
2633     range.min.seconds = -1;
2634   }
2635   g_mutex_unlock (&priv->lock);
2636   g_rec_mutex_unlock (&priv->state_lock);
2637
2638   if (!klass->convert_range (media, &range, unit))
2639     goto conversion_failed;
2640
2641   result = gst_rtsp_range_to_string (&range);
2642
2643   return result;
2644
2645   /* ERRORS */
2646 not_prepared:
2647   {
2648     GST_WARNING ("media %p was not prepared", media);
2649     g_rec_mutex_unlock (&priv->state_lock);
2650     return NULL;
2651   }
2652 conversion_failed:
2653   {
2654     GST_WARNING ("range conversion to unit %d failed", unit);
2655     return NULL;
2656   }
2657 }
2658
2659 /**
2660  * gst_rtsp_media_get_rates:
2661  * @media: a #GstRTSPMedia
2662  * @rate: (optional) (out caller-allocates): the rate of the current segment
2663  * @applied_rate: (optional) (out caller-allocates): the applied_rate of the current segment
2664  *
2665  * Get the rate and applied_rate of the current segment.
2666  *
2667  * Returns: %FALSE if looking up the rate and applied rate failed. Otherwise
2668  * %TRUE is returned and @rate and @applied_rate are set to the rate and
2669  * applied_rate of the current segment.
2670  * Since: 1.18
2671  */
2672 gboolean
2673 gst_rtsp_media_get_rates (GstRTSPMedia * media, gdouble * rate,
2674     gdouble * applied_rate)
2675 {
2676   GstRTSPMediaPrivate *priv;
2677   GstRTSPStream *stream;
2678   gdouble save_rate, save_applied_rate;
2679   gboolean result = TRUE;
2680   gboolean first_stream = TRUE;
2681   gint i;
2682
2683   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2684
2685   if (!rate && !applied_rate) {
2686     GST_WARNING_OBJECT (media, "rate and applied_rate are both NULL");
2687     return FALSE;
2688   }
2689
2690   priv = media->priv;
2691
2692   g_mutex_lock (&priv->lock);
2693
2694   g_assert (priv->streams->len > 0);
2695   for (i = 0; i < priv->streams->len; i++) {
2696     stream = g_ptr_array_index (priv->streams, i);
2697     if (gst_rtsp_stream_is_complete (stream)) {
2698       if (gst_rtsp_stream_get_rates (stream, rate, applied_rate)) {
2699         if (first_stream) {
2700           save_rate = *rate;
2701           save_applied_rate = *applied_rate;
2702           first_stream = FALSE;
2703         } else {
2704           if (save_rate != *rate || save_applied_rate != *applied_rate) {
2705             /* diffrent rate or applied_rate, weird */
2706             g_assert (FALSE);
2707             result = FALSE;
2708             break;
2709           }
2710         }
2711       } else {
2712         /* complete stream withot rate and applied_rate, weird */
2713         g_assert (FALSE);
2714         result = FALSE;
2715         break;
2716       }
2717     }
2718   }
2719
2720   if (!result) {
2721     GST_WARNING_OBJECT (media,
2722         "failed to obtain consistent rate and applied_rate");
2723   }
2724
2725   g_mutex_unlock (&priv->lock);
2726
2727   return result;
2728 }
2729
2730 static void
2731 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
2732 {
2733   gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
2734 }
2735
2736 static void
2737 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
2738 {
2739   GstRTSPMediaPrivate *priv = media->priv;
2740
2741   GST_DEBUG ("media %p set blocked %d", media, blocked);
2742   priv->blocked = blocked;
2743   g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
2744
2745   if (!blocked)
2746     priv->blocking_msg_received = 0;
2747 }
2748
2749 static void
2750 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
2751 {
2752   GstRTSPMediaPrivate *priv = media->priv;
2753
2754   g_mutex_lock (&priv->lock);
2755   priv->status = status;
2756   GST_DEBUG ("setting new status to %d", status);
2757   g_cond_broadcast (&priv->cond);
2758   g_mutex_unlock (&priv->lock);
2759 }
2760
2761 /**
2762  * gst_rtsp_media_get_status:
2763  * @media: a #GstRTSPMedia
2764  *
2765  * Get the status of @media. When @media is busy preparing, this function waits
2766  * until @media is prepared or in error.
2767  *
2768  * Returns: the status of @media.
2769  */
2770 GstRTSPMediaStatus
2771 gst_rtsp_media_get_status (GstRTSPMedia * media)
2772 {
2773   GstRTSPMediaPrivate *priv = media->priv;
2774   GstRTSPMediaStatus result;
2775   gint64 end_time;
2776
2777   g_mutex_lock (&priv->lock);
2778   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
2779   /* while we are preparing, wait */
2780   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
2781     GST_DEBUG ("waiting for status change");
2782     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
2783       GST_DEBUG ("timeout, assuming error status");
2784       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
2785     }
2786   }
2787   /* could be success or error */
2788   result = priv->status;
2789   GST_DEBUG ("got status %d", result);
2790   g_mutex_unlock (&priv->lock);
2791
2792   return result;
2793 }
2794
2795 /**
2796  * gst_rtsp_media_seek_trickmode:
2797  * @media: a #GstRTSPMedia
2798  * @range: (transfer none): a #GstRTSPTimeRange
2799  * @flags: The minimal set of #GstSeekFlags to use
2800  * @rate: the rate to use in the seek
2801  * @trickmode_interval: The trickmode interval to use for KEY_UNITS trick mode
2802  *
2803  * Seek the pipeline of @media to @range with the given @flags and @rate,
2804  * and @trickmode_interval.
2805  * @media must be prepared with gst_rtsp_media_prepare().
2806  * In order to perform the seek operation, the pipeline must contain all
2807  * needed transport parts (transport sinks).
2808  *
2809  * Returns: %TRUE on success.
2810  *
2811  * Since: 1.18
2812  */
2813 gboolean
2814 gst_rtsp_media_seek_trickmode (GstRTSPMedia * media,
2815     GstRTSPTimeRange * range, GstSeekFlags flags, gdouble rate,
2816     GstClockTime trickmode_interval)
2817 {
2818   GstRTSPMediaClass *klass;
2819   GstRTSPMediaPrivate *priv;
2820   gboolean res;
2821   GstClockTime start, stop;
2822   GstSeekType start_type, stop_type;
2823   gint64 current_position;
2824   gboolean force_seek;
2825
2826   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2827
2828   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2829   /* if there's a range then klass->convert_range must be set */
2830   g_return_val_if_fail (range == NULL || klass->convert_range != NULL, FALSE);
2831
2832   GST_DEBUG ("flags=%x  rate=%f", flags, rate);
2833
2834   priv = media->priv;
2835
2836   g_rec_mutex_lock (&priv->state_lock);
2837   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2838     goto not_prepared;
2839
2840   /* check if the media pipeline is complete in order to perform a
2841    * seek operation on it */
2842   if (!check_complete (media))
2843     goto not_complete;
2844
2845   /* Update the seekable state of the pipeline in case it changed */
2846   check_seekable (media);
2847
2848   if (priv->seekable == 0) {
2849     GST_FIXME_OBJECT (media, "Handle going back to 0 for none live"
2850         " not seekable streams.");
2851
2852     goto not_seekable;
2853   } else if (priv->seekable < 0) {
2854     goto not_seekable;
2855   }
2856
2857   start_type = stop_type = GST_SEEK_TYPE_NONE;
2858   start = stop = GST_CLOCK_TIME_NONE;
2859
2860   /* if caller provided a range convert it to NPT format
2861    * if no range provided the seek is assumed to be the same position but with
2862    * e.g. the rate changed */
2863   if (range != NULL) {
2864     if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
2865       goto not_supported;
2866     gst_rtsp_range_get_times (range, &start, &stop);
2867
2868     GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2869         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2870     GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2871         GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
2872   }
2873
2874   current_position = -1;
2875   if (klass->query_position)
2876     klass->query_position (media, &current_position);
2877   GST_INFO ("current media position %" GST_TIME_FORMAT,
2878       GST_TIME_ARGS (current_position));
2879
2880   if (start != GST_CLOCK_TIME_NONE)
2881     start_type = GST_SEEK_TYPE_SET;
2882
2883   if (stop != GST_CLOCK_TIME_NONE)
2884     stop_type = GST_SEEK_TYPE_SET;
2885
2886   /* we force a seek if any trickmode flag is set, or if the flush flag is set or
2887    * the rate is non-standard, i.e. not 1.0 */
2888   force_seek = (flags & TRICKMODE_FLAGS) || (flags & GST_SEEK_FLAG_FLUSH) ||
2889       rate != 1.0;
2890
2891   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE || force_seek) {
2892     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2893         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2894
2895     /* depends on the current playing state of the pipeline. We might need to
2896      * queue this until we get EOS. */
2897     flags |= GST_SEEK_FLAG_FLUSH;
2898
2899     /* if range start was not supplied we must continue from current position.
2900      * but since we're doing a flushing seek, let us query the current position
2901      * so we end up at exactly the same position after the seek. */
2902     if (range == NULL || range->min.type == GST_RTSP_TIME_END) {
2903       if (current_position == -1) {
2904         GST_WARNING ("current position unknown");
2905       } else {
2906         GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
2907             GST_TIME_ARGS (current_position));
2908         start = current_position;
2909         start_type = GST_SEEK_TYPE_SET;
2910       }
2911     }
2912
2913     if (start == current_position && stop_type == GST_SEEK_TYPE_NONE &&
2914         !force_seek) {
2915       GST_DEBUG ("no position change, no flags set by caller, so not seeking");
2916       res = TRUE;
2917     } else {
2918       GstEvent *seek_event;
2919       gboolean unblock = FALSE;
2920
2921       /* Handle expected async-done before waiting on next async-done.
2922        *
2923        * Since the seek further down in code will cause a preroll and
2924        * a async-done will be generated it's important to wait on async-done
2925        * if that is expected. Otherwise there is the risk that the waiting
2926        * for async-done after the seek is detecting the expected async-done
2927        * instead of the one that corresponds to the seek. Then execution
2928        * continue and act as if the pipeline is prerolled, but it's not.
2929        *
2930        * During wait_preroll message GST_MESSAGE_ASYNC_DONE will come
2931        * and then the state will change from preparing to prepared */
2932       if (priv->expected_async_done) {
2933         GST_DEBUG (" expected to get async-done, waiting ");
2934         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2935         g_rec_mutex_unlock (&priv->state_lock);
2936
2937         /* wait until pipeline is prerolled  */
2938         if (!wait_preroll (media))
2939           goto preroll_failed_expected_async_done;
2940
2941         g_rec_mutex_lock (&priv->state_lock);
2942         GST_DEBUG (" got expected async-done");
2943       }
2944
2945       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2946
2947       if (rate < 0.0) {
2948         GstClockTime temp_time = start;
2949         GstSeekType temp_type = start_type;
2950
2951         start = stop;
2952         start_type = stop_type;
2953         stop = temp_time;
2954         stop_type = temp_type;
2955       }
2956
2957       seek_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type,
2958           start, stop_type, stop);
2959
2960       gst_event_set_seek_trickmode_interval (seek_event, trickmode_interval);
2961
2962       if (!media->priv->blocked) {
2963         /* Prevent a race condition with multiple streams,
2964          * where one stream may have time to preroll before others
2965          * have even started flushing, causing async-done to be
2966          * posted too early.
2967          */
2968         media_streams_set_blocked (media, TRUE);
2969         unblock = TRUE;
2970       }
2971
2972       res = gst_element_send_event (priv->pipeline, seek_event);
2973
2974       if (unblock)
2975         media_streams_set_blocked (media, FALSE);
2976
2977       /* and block for the seek to complete */
2978       GST_INFO ("done seeking %d", res);
2979       if (!res)
2980         goto seek_failed;
2981
2982       g_rec_mutex_unlock (&priv->state_lock);
2983
2984       /* wait until pipeline is prerolled again, this will also collect stats */
2985       if (!wait_preroll (media))
2986         goto preroll_failed;
2987
2988       g_rec_mutex_lock (&priv->state_lock);
2989       GST_INFO ("prerolled again");
2990     }
2991   } else {
2992     GST_INFO ("no seek needed");
2993     res = TRUE;
2994   }
2995   g_rec_mutex_unlock (&priv->state_lock);
2996
2997   return res;
2998
2999   /* ERRORS */
3000 not_prepared:
3001   {
3002     g_rec_mutex_unlock (&priv->state_lock);
3003     GST_INFO ("media %p is not prepared", media);
3004     return FALSE;
3005   }
3006 not_complete:
3007   {
3008     g_rec_mutex_unlock (&priv->state_lock);
3009     GST_INFO ("pipeline is not complete");
3010     return FALSE;
3011   }
3012 not_seekable:
3013   {
3014     g_rec_mutex_unlock (&priv->state_lock);
3015     GST_INFO ("pipeline is not seekable");
3016     return FALSE;
3017   }
3018 not_supported:
3019   {
3020     g_rec_mutex_unlock (&priv->state_lock);
3021     GST_WARNING ("conversion to npt not supported");
3022     return FALSE;
3023   }
3024 seek_failed:
3025   {
3026     g_rec_mutex_unlock (&priv->state_lock);
3027     GST_INFO ("seeking failed");
3028     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3029     return FALSE;
3030   }
3031 preroll_failed:
3032   {
3033     GST_WARNING ("failed to preroll after seek");
3034     return FALSE;
3035   }
3036 preroll_failed_expected_async_done:
3037   {
3038     GST_WARNING ("failed to preroll");
3039     return FALSE;
3040   }
3041 }
3042
3043 /**
3044  * gst_rtsp_media_seek_full:
3045  * @media: a #GstRTSPMedia
3046  * @range: (transfer none): a #GstRTSPTimeRange
3047  * @flags: The minimal set of #GstSeekFlags to use
3048  *
3049  * Seek the pipeline of @media to @range with the given @flags.
3050  * @media must be prepared with gst_rtsp_media_prepare().
3051  *
3052  * Returns: %TRUE on success.
3053  * Since: 1.18
3054  */
3055 gboolean
3056 gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
3057     GstSeekFlags flags)
3058 {
3059   return gst_rtsp_media_seek_trickmode (media, range, flags, 1.0, 0);
3060 }
3061
3062 /**
3063  * gst_rtsp_media_seek:
3064  * @media: a #GstRTSPMedia
3065  * @range: (transfer none): a #GstRTSPTimeRange
3066  *
3067  * Seek the pipeline of @media to @range. @media must be prepared with
3068  * gst_rtsp_media_prepare().
3069  *
3070  * Returns: %TRUE on success.
3071  */
3072 gboolean
3073 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
3074 {
3075   return gst_rtsp_media_seek_trickmode (media, range, GST_SEEK_FLAG_NONE,
3076       1.0, 0);
3077 }
3078
3079 static void
3080 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
3081 {
3082   *blocked &= gst_rtsp_stream_is_blocking (stream);
3083 }
3084
3085 static gboolean
3086 media_streams_blocking (GstRTSPMedia * media)
3087 {
3088   gboolean blocking = TRUE;
3089
3090   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
3091       &blocking);
3092
3093   return blocking;
3094 }
3095
3096 static GstStateChangeReturn
3097 set_state (GstRTSPMedia * media, GstState state)
3098 {
3099   GstRTSPMediaPrivate *priv = media->priv;
3100   GstStateChangeReturn ret;
3101
3102   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
3103       media);
3104   ret = gst_element_set_state (priv->pipeline, state);
3105
3106   return ret;
3107 }
3108
3109 static GstStateChangeReturn
3110 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
3111 {
3112   GstRTSPMediaPrivate *priv = media->priv;
3113   GstStateChangeReturn ret;
3114
3115   GST_INFO ("set target state to %s for media %p",
3116       gst_element_state_get_name (state), media);
3117   priv->target_state = state;
3118
3119   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
3120       priv->target_state, NULL);
3121
3122   if (do_state)
3123     ret = set_state (media, state);
3124   else
3125     ret = GST_STATE_CHANGE_SUCCESS;
3126
3127   return ret;
3128 }
3129
3130 static void
3131 stream_collect_active (GstRTSPStream * stream, guint * active_streams)
3132 {
3133   if (gst_rtsp_stream_is_complete (stream))
3134     (*active_streams)++;
3135 }
3136
3137 static guint
3138 nbr_active_streams (GstRTSPMedia * media)
3139 {
3140   guint ret = 0;
3141
3142   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_active,
3143       &ret);
3144
3145   return ret;
3146 }
3147
3148  /* called with state-lock */
3149 /* called with state-lock */
3150 static gboolean
3151 default_handle_message (GstRTSPMedia * media, GstMessage * message)
3152 {
3153   GstRTSPMediaPrivate *priv = media->priv;
3154   GstMessageType type;
3155
3156   type = GST_MESSAGE_TYPE (message);
3157
3158   switch (type) {
3159     case GST_MESSAGE_STATE_CHANGED:
3160     {
3161       GstState old, new, pending;
3162
3163       if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
3164         break;
3165
3166       gst_message_parse_state_changed (message, &old, &new, &pending);
3167
3168       GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
3169           gst_element_state_get_name (old), gst_element_state_get_name (new),
3170           gst_element_state_get_name (pending));
3171       if (priv->no_more_pads_pending == 0
3172           && gst_rtsp_media_is_receive_only (media) && old == GST_STATE_READY
3173           && new == GST_STATE_PAUSED) {
3174         GST_INFO ("%p: went to PAUSED, prepared now", media);
3175         g_mutex_lock (&priv->lock);
3176         collect_media_stats (media);
3177         g_mutex_unlock (&priv->lock);
3178
3179         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3180           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3181       }
3182
3183       break;
3184     }
3185     case GST_MESSAGE_BUFFERING:
3186     {
3187       gint percent;
3188
3189       gst_message_parse_buffering (message, &percent);
3190
3191       /* no state management needed for live pipelines */
3192       if (priv->is_live)
3193         break;
3194
3195       if (percent == 100) {
3196         /* a 100% message means buffering is done */
3197         priv->buffering = FALSE;
3198         /* if the desired state is playing, go back */
3199         if (priv->target_state == GST_STATE_PLAYING) {
3200           GST_INFO ("Buffering done, setting pipeline to PLAYING");
3201           set_state (media, GST_STATE_PLAYING);
3202         } else {
3203           GST_INFO ("Buffering done");
3204         }
3205       } else {
3206         /* buffering busy */
3207         if (priv->buffering == FALSE) {
3208           if (priv->target_state == GST_STATE_PLAYING) {
3209             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
3210             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
3211             set_state (media, GST_STATE_PAUSED);
3212           } else {
3213             GST_INFO ("Buffering ...");
3214           }
3215         }
3216         priv->buffering = TRUE;
3217       }
3218       break;
3219     }
3220     case GST_MESSAGE_LATENCY:
3221     {
3222       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
3223       break;
3224     }
3225     case GST_MESSAGE_ERROR:
3226     {
3227       GError *gerror;
3228       gchar *debug;
3229
3230       gst_message_parse_error (message, &gerror, &debug);
3231       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
3232       g_error_free (gerror);
3233       g_free (debug);
3234
3235       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3236       break;
3237     }
3238     case GST_MESSAGE_WARNING:
3239     {
3240       GError *gerror;
3241       gchar *debug;
3242
3243       gst_message_parse_warning (message, &gerror, &debug);
3244       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
3245       g_error_free (gerror);
3246       g_free (debug);
3247       break;
3248     }
3249     case GST_MESSAGE_ELEMENT:
3250     {
3251       const GstStructure *s;
3252
3253       s = gst_message_get_structure (message);
3254       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
3255         GST_DEBUG ("media received blocking message");
3256         priv->blocking_msg_received++;
3257         if (priv->blocked && media_streams_blocking (media) &&
3258             priv->no_more_pads_pending == 0 &&
3259             (priv->blocking_msg_received == nbr_active_streams (media) ||
3260                 priv->blocking_msg_received == priv->streams->len)) {
3261           GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "media is blocking");
3262           g_mutex_lock (&priv->lock);
3263           collect_media_stats (media);
3264           g_mutex_unlock (&priv->lock);
3265
3266           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3267             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3268
3269           priv->blocking_msg_received = 0;
3270         }
3271       }
3272       break;
3273     }
3274     case GST_MESSAGE_STREAM_STATUS:
3275       break;
3276     case GST_MESSAGE_ASYNC_DONE:
3277       if (priv->expected_async_done)
3278         priv->expected_async_done = FALSE;
3279       if (priv->complete) {
3280         /* receive the final ASYNC_DONE, that is posted by the media pipeline
3281          * after all the transport parts have been successfully added to
3282          * the media streams. */
3283         GST_DEBUG_OBJECT (media, "got async-done");
3284         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3285           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3286       }
3287       break;
3288     case GST_MESSAGE_EOS:
3289       GST_INFO ("%p: got EOS", media);
3290
3291       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
3292         GST_DEBUG ("shutting down after EOS");
3293         finish_unprepare (media);
3294       }
3295       break;
3296     default:
3297       GST_INFO ("%p: got message type %d (%s)", media, type,
3298           gst_message_type_get_name (type));
3299       break;
3300   }
3301   return TRUE;
3302 }
3303
3304 static gboolean
3305 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
3306 {
3307   GstRTSPMediaPrivate *priv = media->priv;
3308   GstRTSPMediaClass *klass;
3309   gboolean ret;
3310
3311   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3312
3313   g_rec_mutex_lock (&priv->state_lock);
3314   if (klass->handle_message)
3315     ret = klass->handle_message (media, message);
3316   else
3317     ret = FALSE;
3318   g_rec_mutex_unlock (&priv->state_lock);
3319
3320   return ret;
3321 }
3322
3323 static void
3324 watch_destroyed (GstRTSPMedia * media)
3325 {
3326   GST_DEBUG_OBJECT (media, "source destroyed");
3327   g_object_unref (media);
3328 }
3329
3330 static gboolean
3331 is_payloader (GstElement * element)
3332 {
3333   GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
3334   const gchar *klass;
3335
3336   klass = gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
3337   if (klass == NULL)
3338     return FALSE;
3339
3340   if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
3341     return TRUE;
3342   }
3343
3344   return FALSE;
3345 }
3346
3347 static GstElement *
3348 find_payload_element (GstElement * payloader, GstPad * pad)
3349 {
3350   GstElement *pay = NULL;
3351
3352   if (GST_IS_BIN (payloader)) {
3353     GstIterator *iter;
3354     GValue item = { 0 };
3355     gchar *pad_name, *payloader_name;
3356     GstElement *element;
3357
3358     if ((element = gst_bin_get_by_name (GST_BIN (payloader), "pay"))) {
3359       if (is_payloader (element))
3360         return element;
3361       gst_object_unref (element);
3362     }
3363
3364     pad_name = gst_object_get_name (GST_OBJECT (pad));
3365     payloader_name = g_strdup_printf ("pay_%s", pad_name);
3366     g_free (pad_name);
3367     if ((element = gst_bin_get_by_name (GST_BIN (payloader), payloader_name))) {
3368       g_free (payloader_name);
3369       if (is_payloader (element))
3370         return element;
3371       gst_object_unref (element);
3372     } else {
3373       g_free (payloader_name);
3374     }
3375
3376     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
3377     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
3378       element = (GstElement *) g_value_get_object (&item);
3379
3380       if (is_payloader (element)) {
3381         pay = gst_object_ref (element);
3382         g_value_unset (&item);
3383         break;
3384       }
3385       g_value_unset (&item);
3386     }
3387     gst_iterator_free (iter);
3388   } else {
3389     pay = g_object_ref (payloader);
3390   }
3391
3392   return pay;
3393 }
3394
3395 /* called from streaming threads */
3396 static void
3397 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3398 {
3399   GstRTSPMediaPrivate *priv = media->priv;
3400   GstRTSPStream *stream;
3401   GstElement *pay;
3402
3403   /* find the real payload element */
3404   pay = find_payload_element (element, pad);
3405   stream = gst_rtsp_media_create_stream (media, pay, pad);
3406   gst_object_unref (pay);
3407
3408   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3409
3410   g_rec_mutex_lock (&priv->state_lock);
3411   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3412     goto not_preparing;
3413
3414   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
3415
3416   /* join the element in the PAUSED state because this callback is
3417    * called from the streaming thread and it is PAUSED */
3418   if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3419           priv->rtpbin, GST_STATE_PAUSED)) {
3420     GST_WARNING ("failed to join bin element");
3421   }
3422
3423   if (priv->blocked)
3424     gst_rtsp_stream_set_blocked (stream, TRUE);
3425
3426   g_rec_mutex_unlock (&priv->state_lock);
3427
3428   return;
3429
3430   /* ERRORS */
3431 not_preparing:
3432   {
3433     gst_rtsp_media_remove_stream (media, stream);
3434     g_rec_mutex_unlock (&priv->state_lock);
3435     GST_INFO ("ignore pad because we are not preparing");
3436     return;
3437   }
3438 }
3439
3440 static void
3441 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3442 {
3443   GstRTSPMediaPrivate *priv = media->priv;
3444   GstRTSPStream *stream;
3445
3446   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
3447   if (stream == NULL)
3448     return;
3449
3450   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3451
3452   g_rec_mutex_lock (&priv->state_lock);
3453   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3454   g_rec_mutex_unlock (&priv->state_lock);
3455
3456   gst_rtsp_media_remove_stream (media, stream);
3457 }
3458
3459 static void
3460 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
3461 {
3462   GstRTSPMediaPrivate *priv = media->priv;
3463
3464   GST_INFO_OBJECT (element, "no more pads");
3465   g_mutex_lock (&priv->lock);
3466   priv->no_more_pads_pending--;
3467   g_mutex_unlock (&priv->lock);
3468 }
3469
3470 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
3471
3472 struct _DynPaySignalHandlers
3473 {
3474   gulong pad_added_handler;
3475   gulong pad_removed_handler;
3476   gulong no_more_pads_handler;
3477 };
3478
3479 static gboolean
3480 start_preroll (GstRTSPMedia * media)
3481 {
3482   GstRTSPMediaPrivate *priv = media->priv;
3483   GstStateChangeReturn ret;
3484
3485   GST_INFO ("setting pipeline to PAUSED for media %p", media);
3486
3487   /* start blocked since it is possible that there are no sink elements yet */
3488   media_streams_set_blocked (media, TRUE);
3489   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3490
3491   switch (ret) {
3492     case GST_STATE_CHANGE_SUCCESS:
3493       GST_INFO ("SUCCESS state change for media %p", media);
3494       break;
3495     case GST_STATE_CHANGE_ASYNC:
3496       GST_INFO ("ASYNC state change for media %p", media);
3497       break;
3498     case GST_STATE_CHANGE_NO_PREROLL:
3499       /* we need to go to PLAYING */
3500       GST_INFO ("NO_PREROLL state change: live media %p", media);
3501       /* FIXME we disable seeking for live streams for now. We should perform a
3502        * seeking query in preroll instead */
3503       priv->seekable = -1;
3504       priv->is_live = TRUE;
3505
3506       ret = set_state (media, GST_STATE_PLAYING);
3507       if (ret == GST_STATE_CHANGE_FAILURE)
3508         goto state_failed;
3509       break;
3510     case GST_STATE_CHANGE_FAILURE:
3511       goto state_failed;
3512   }
3513
3514   return TRUE;
3515
3516 state_failed:
3517   {
3518     GST_WARNING ("failed to preroll pipeline");
3519     return FALSE;
3520   }
3521 }
3522
3523 static gboolean
3524 wait_preroll (GstRTSPMedia * media)
3525 {
3526   GstRTSPMediaStatus status;
3527
3528   GST_DEBUG ("wait to preroll pipeline");
3529
3530   /* wait until pipeline is prerolled */
3531   status = gst_rtsp_media_get_status (media);
3532   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
3533     goto preroll_failed;
3534
3535   return TRUE;
3536
3537 preroll_failed:
3538   {
3539     GST_WARNING ("failed to preroll pipeline");
3540     return FALSE;
3541   }
3542 }
3543
3544 static GstElement *
3545 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3546 {
3547   GstRTSPMediaPrivate *priv = media->priv;
3548   GstRTSPStream *stream = NULL;
3549   guint i;
3550   GstElement *res = NULL;
3551
3552   g_mutex_lock (&priv->lock);
3553   for (i = 0; i < priv->streams->len; i++) {
3554     stream = g_ptr_array_index (priv->streams, i);
3555
3556     if (sessid == gst_rtsp_stream_get_index (stream))
3557       break;
3558
3559     stream = NULL;
3560   }
3561   g_mutex_unlock (&priv->lock);
3562
3563   if (stream)
3564     res = gst_rtsp_stream_request_aux_sender (stream, sessid);
3565
3566   return res;
3567 }
3568
3569 static GstElement *
3570 request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3571 {
3572   GstRTSPMediaPrivate *priv = media->priv;
3573   GstRTSPStream *stream = NULL;
3574   guint i;
3575   GstElement *res = NULL;
3576
3577   g_mutex_lock (&priv->lock);
3578   for (i = 0; i < priv->streams->len; i++) {
3579     stream = g_ptr_array_index (priv->streams, i);
3580
3581     if (sessid == gst_rtsp_stream_get_index (stream))
3582       break;
3583
3584     stream = NULL;
3585   }
3586   g_mutex_unlock (&priv->lock);
3587
3588   if (stream)
3589     res = gst_rtsp_stream_request_aux_receiver (stream, sessid);
3590
3591   return res;
3592 }
3593
3594 static GstElement *
3595 request_fec_decoder (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3596 {
3597   GstRTSPMediaPrivate *priv = media->priv;
3598   GstRTSPStream *stream = NULL;
3599   guint i;
3600   GstElement *res = NULL;
3601
3602   g_mutex_lock (&priv->lock);
3603   for (i = 0; i < priv->streams->len; i++) {
3604     stream = g_ptr_array_index (priv->streams, i);
3605
3606     if (sessid == gst_rtsp_stream_get_index (stream))
3607       break;
3608
3609     stream = NULL;
3610   }
3611   g_mutex_unlock (&priv->lock);
3612
3613   if (stream) {
3614     res = gst_rtsp_stream_request_ulpfec_decoder (stream, rtpbin, sessid);
3615   }
3616
3617   return res;
3618 }
3619
3620 static void
3621 new_storage_cb (GstElement * rtpbin, GObject * storage, guint sessid,
3622     GstRTSPMedia * media)
3623 {
3624   g_object_set (storage, "size-time", (media->priv->latency + 50) * GST_MSECOND,
3625       NULL);
3626 }
3627
3628 static gboolean
3629 start_prepare (GstRTSPMedia * media)
3630 {
3631   GstRTSPMediaPrivate *priv = media->priv;
3632   guint i;
3633   GList *walk;
3634
3635   g_rec_mutex_lock (&priv->state_lock);
3636   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3637     goto no_longer_preparing;
3638
3639   g_signal_connect (priv->rtpbin, "new-storage", G_CALLBACK (new_storage_cb),
3640       media);
3641   g_signal_connect (priv->rtpbin, "request-fec-decoder",
3642       G_CALLBACK (request_fec_decoder), media);
3643
3644   /* link streams we already have, other streams might appear when we have
3645    * dynamic elements */
3646   for (i = 0; i < priv->streams->len; i++) {
3647     GstRTSPStream *stream;
3648
3649     stream = g_ptr_array_index (priv->streams, i);
3650
3651     if (priv->rtx_time > 0) {
3652       /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
3653       g_signal_connect (priv->rtpbin, "request-aux-sender",
3654           (GCallback) request_aux_sender, media);
3655     }
3656
3657     if (priv->do_retransmission) {
3658       g_signal_connect (priv->rtpbin, "request-aux-receiver",
3659           (GCallback) request_aux_receiver, media);
3660     }
3661
3662     if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3663             priv->rtpbin, GST_STATE_NULL)) {
3664       goto join_bin_failed;
3665     }
3666   }
3667
3668   if (priv->rtpbin)
3669     g_object_set (priv->rtpbin, "do-retransmission", priv->do_retransmission,
3670         "do-lost", TRUE, NULL);
3671
3672   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3673     GstElement *elem = walk->data;
3674     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
3675
3676     GST_INFO ("adding callbacks for dynamic element %p", elem);
3677
3678     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
3679         (GCallback) pad_added_cb, media);
3680     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
3681         (GCallback) pad_removed_cb, media);
3682     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
3683         (GCallback) no_more_pads_cb, media);
3684
3685     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
3686   }
3687
3688   if (priv->nb_dynamic_elements == 0 && gst_rtsp_media_is_receive_only (media)) {
3689     /* If we are receive_only (RECORD), do not try to preroll, to avoid
3690      * a second ASYNC state change failing */
3691     priv->is_live = TRUE;
3692     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3693   } else if (!start_preroll (media)) {
3694     goto preroll_failed;
3695   }
3696
3697   g_rec_mutex_unlock (&priv->state_lock);
3698
3699   return FALSE;
3700
3701 no_longer_preparing:
3702   {
3703     GST_INFO ("media is no longer preparing");
3704     g_rec_mutex_unlock (&priv->state_lock);
3705     return FALSE;
3706   }
3707 join_bin_failed:
3708   {
3709     GST_WARNING ("failed to join bin element");
3710     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3711     g_rec_mutex_unlock (&priv->state_lock);
3712     return FALSE;
3713   }
3714 preroll_failed:
3715   {
3716     GST_WARNING ("failed to preroll pipeline");
3717     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3718     g_rec_mutex_unlock (&priv->state_lock);
3719     return FALSE;
3720   }
3721 }
3722
3723 static gboolean
3724 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3725 {
3726   GstRTSPMediaPrivate *priv;
3727   GstRTSPMediaClass *klass;
3728   GstBus *bus;
3729   GMainContext *context;
3730   GSource *source;
3731
3732   priv = media->priv;
3733
3734   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3735
3736   if (!klass->create_rtpbin)
3737     goto no_create_rtpbin;
3738
3739   priv->rtpbin = klass->create_rtpbin (media);
3740   if (priv->rtpbin != NULL) {
3741     gboolean success = TRUE;
3742
3743     g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
3744
3745     if (klass->setup_rtpbin)
3746       success = klass->setup_rtpbin (media, priv->rtpbin);
3747
3748     if (success == FALSE) {
3749       gst_object_unref (priv->rtpbin);
3750       priv->rtpbin = NULL;
3751     }
3752   }
3753   if (priv->rtpbin == NULL)
3754     goto no_rtpbin;
3755
3756   priv->thread = thread;
3757   context = (thread != NULL) ? (thread->context) : NULL;
3758
3759   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
3760
3761   /* add the pipeline bus to our custom mainloop */
3762   priv->source = gst_bus_create_watch (bus);
3763   gst_object_unref (bus);
3764
3765   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
3766       g_object_ref (media), (GDestroyNotify) watch_destroyed);
3767
3768   priv->id = g_source_attach (priv->source, context);
3769
3770   /* add stuff to the bin */
3771   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
3772
3773   /* do remainder in context */
3774   source = g_idle_source_new ();
3775   g_source_set_callback (source, (GSourceFunc) start_prepare,
3776       g_object_ref (media), (GDestroyNotify) g_object_unref);
3777   g_source_attach (source, context);
3778   g_source_unref (source);
3779
3780   return TRUE;
3781
3782   /* ERRORS */
3783 no_create_rtpbin:
3784   {
3785     GST_ERROR ("no create_rtpbin function");
3786     g_critical ("no create_rtpbin vmethod function set");
3787     return FALSE;
3788   }
3789 no_rtpbin:
3790   {
3791     GST_WARNING ("no rtpbin element");
3792     g_warning ("failed to create element 'rtpbin', check your installation");
3793     return FALSE;
3794   }
3795 }
3796
3797 /**
3798  * gst_rtsp_media_prepare:
3799  * @media: a #GstRTSPMedia
3800  * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
3801  *   bus handler or %NULL
3802  *
3803  * Prepare @media for streaming. This function will create the objects
3804  * to manage the streaming. A pipeline must have been set on @media with
3805  * gst_rtsp_media_take_pipeline().
3806  *
3807  * It will preroll the pipeline and collect vital information about the streams
3808  * such as the duration.
3809  *
3810  * Returns: %TRUE on success.
3811  */
3812 gboolean
3813 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3814 {
3815   GstRTSPMediaPrivate *priv;
3816   GstRTSPMediaClass *klass;
3817
3818   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3819
3820   priv = media->priv;
3821
3822   g_rec_mutex_lock (&priv->state_lock);
3823   priv->prepare_count++;
3824
3825   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
3826       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
3827     goto was_prepared;
3828
3829   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3830     goto is_preparing;
3831
3832   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
3833     goto not_unprepared;
3834
3835   if (!priv->reusable && priv->reused)
3836     goto is_reused;
3837
3838   GST_INFO ("preparing media %p", media);
3839
3840   /* reset some variables */
3841   priv->is_live = FALSE;
3842   priv->seekable = -1;
3843   priv->buffering = FALSE;
3844   priv->no_more_pads_pending = priv->nb_dynamic_elements;
3845
3846   /* we're preparing now */
3847   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3848
3849   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3850   if (klass->prepare) {
3851     if (!klass->prepare (media, thread))
3852       goto prepare_failed;
3853   }
3854
3855 wait_status:
3856   g_rec_mutex_unlock (&priv->state_lock);
3857
3858   /* now wait for all pads to be prerolled, FIXME, we should somehow be
3859    * able to do this async so that we don't block the server thread. */
3860   if (!wait_preroll (media))
3861     goto preroll_failed;
3862
3863   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
3864
3865   GST_INFO ("object %p is prerolled", media);
3866
3867   return TRUE;
3868
3869   /* OK */
3870 is_preparing:
3871   {
3872     /* we are not going to use the giving thread, so stop it. */
3873     if (thread)
3874       gst_rtsp_thread_stop (thread);
3875     goto wait_status;
3876   }
3877 was_prepared:
3878   {
3879     GST_LOG ("media %p was prepared", media);
3880     /* we are not going to use the giving thread, so stop it. */
3881     if (thread)
3882       gst_rtsp_thread_stop (thread);
3883     g_rec_mutex_unlock (&priv->state_lock);
3884     return TRUE;
3885   }
3886   /* ERRORS */
3887 not_unprepared:
3888   {
3889     /* we are not going to use the giving thread, so stop it. */
3890     if (thread)
3891       gst_rtsp_thread_stop (thread);
3892     GST_WARNING ("media %p was not unprepared", media);
3893     priv->prepare_count--;
3894     g_rec_mutex_unlock (&priv->state_lock);
3895     return FALSE;
3896   }
3897 is_reused:
3898   {
3899     /* we are not going to use the giving thread, so stop it. */
3900     if (thread)
3901       gst_rtsp_thread_stop (thread);
3902     priv->prepare_count--;
3903     g_rec_mutex_unlock (&priv->state_lock);
3904     GST_WARNING ("can not reuse media %p", media);
3905     return FALSE;
3906   }
3907 prepare_failed:
3908   {
3909     /* we are not going to use the giving thread, so stop it. */
3910     if (thread)
3911       gst_rtsp_thread_stop (thread);
3912     priv->prepare_count--;
3913     g_rec_mutex_unlock (&priv->state_lock);
3914     GST_ERROR ("failed to prepare media");
3915     return FALSE;
3916   }
3917 preroll_failed:
3918   {
3919     GST_WARNING ("failed to preroll pipeline");
3920     gst_rtsp_media_unprepare (media);
3921     return FALSE;
3922   }
3923 }
3924
3925 /* must be called with state-lock */
3926 static void
3927 finish_unprepare (GstRTSPMedia * media)
3928 {
3929   GstRTSPMediaPrivate *priv = media->priv;
3930   gint i;
3931   GList *walk;
3932
3933   if (priv->finishing_unprepare)
3934     return;
3935   priv->finishing_unprepare = TRUE;
3936
3937   GST_DEBUG ("shutting down");
3938
3939   /* release the lock on shutdown, otherwise pad_added_cb might try to
3940    * acquire the lock and then we deadlock */
3941   g_rec_mutex_unlock (&priv->state_lock);
3942   set_state (media, GST_STATE_NULL);
3943   g_rec_mutex_lock (&priv->state_lock);
3944
3945   media_streams_set_blocked (media, FALSE);
3946
3947   for (i = 0; i < priv->streams->len; i++) {
3948     GstRTSPStream *stream;
3949
3950     GST_INFO ("Removing elements of stream %d from pipeline", i);
3951
3952     stream = g_ptr_array_index (priv->streams, i);
3953
3954     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3955   }
3956
3957   /* remove the pad signal handlers */
3958   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3959     GstElement *elem = walk->data;
3960     DynPaySignalHandlers *handlers;
3961
3962     handlers =
3963         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3964     g_assert (handlers != NULL);
3965
3966     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3967     g_signal_handler_disconnect (G_OBJECT (elem),
3968         handlers->pad_removed_handler);
3969     g_signal_handler_disconnect (G_OBJECT (elem),
3970         handlers->no_more_pads_handler);
3971
3972     g_slice_free (DynPaySignalHandlers, handlers);
3973   }
3974
3975   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3976   priv->rtpbin = NULL;
3977
3978   if (priv->nettime)
3979     gst_object_unref (priv->nettime);
3980   priv->nettime = NULL;
3981
3982   priv->reused = TRUE;
3983   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3984
3985   /* when the media is not reusable, this will effectively unref the media and
3986    * recreate it */
3987   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3988
3989   /* the source has the last ref to the media */
3990   if (priv->source) {
3991     GST_DEBUG ("destroy source");
3992     g_source_destroy (priv->source);
3993     g_source_unref (priv->source);
3994   }
3995   if (priv->thread) {
3996     GST_DEBUG ("stop thread");
3997     gst_rtsp_thread_stop (priv->thread);
3998   }
3999
4000   priv->finishing_unprepare = FALSE;
4001 }
4002
4003 /* called with state-lock */
4004 static gboolean
4005 default_unprepare (GstRTSPMedia * media)
4006 {
4007   GstRTSPMediaPrivate *priv = media->priv;
4008
4009   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
4010
4011   if (priv->eos_shutdown) {
4012     GST_DEBUG ("sending EOS for shutdown");
4013     /* ref so that we don't disappear */
4014     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
4015     /* we need to go to playing again for the EOS to propagate, normally in this
4016      * state, nothing is receiving data from us anymore so this is ok. */
4017     set_state (media, GST_STATE_PLAYING);
4018   } else {
4019     finish_unprepare (media);
4020   }
4021   return TRUE;
4022 }
4023
4024 /**
4025  * gst_rtsp_media_unprepare:
4026  * @media: a #GstRTSPMedia
4027  *
4028  * Unprepare @media. After this call, the media should be prepared again before
4029  * it can be used again. If the media is set to be non-reusable, a new instance
4030  * must be created.
4031  *
4032  * Returns: %TRUE on success.
4033  */
4034 gboolean
4035 gst_rtsp_media_unprepare (GstRTSPMedia * media)
4036 {
4037   GstRTSPMediaPrivate *priv;
4038   gboolean success;
4039
4040   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4041
4042   priv = media->priv;
4043
4044   g_rec_mutex_lock (&priv->state_lock);
4045   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
4046     goto was_unprepared;
4047
4048   priv->prepare_count--;
4049   if (priv->prepare_count > 0)
4050     goto is_busy;
4051
4052   GST_INFO ("unprepare media %p", media);
4053   set_target_state (media, GST_STATE_NULL, FALSE);
4054   success = TRUE;
4055
4056   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
4057     GstRTSPMediaClass *klass;
4058
4059     klass = GST_RTSP_MEDIA_GET_CLASS (media);
4060     if (klass->unprepare)
4061       success = klass->unprepare (media);
4062   } else {
4063     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
4064     finish_unprepare (media);
4065   }
4066   g_rec_mutex_unlock (&priv->state_lock);
4067
4068   return success;
4069
4070 was_unprepared:
4071   {
4072     g_rec_mutex_unlock (&priv->state_lock);
4073     GST_INFO ("media %p was already unprepared", media);
4074     return TRUE;
4075   }
4076 is_busy:
4077   {
4078     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
4079     g_rec_mutex_unlock (&priv->state_lock);
4080     return TRUE;
4081   }
4082 }
4083
4084 /* should be called with state-lock */
4085 static GstClock *
4086 get_clock_unlocked (GstRTSPMedia * media)
4087 {
4088   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
4089     GST_DEBUG_OBJECT (media, "media was not prepared");
4090     return NULL;
4091   }
4092   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
4093 }
4094
4095 /**
4096  * gst_rtsp_media_lock:
4097  * @media: a #GstRTSPMedia
4098  *
4099  * Lock the entire media. This is needed by callers such as rtsp_client to
4100  * protect the media when it is shared by many clients.
4101  * The lock prevents that concurrent clients alters the shared media,
4102  * while one client already is working with it.
4103  * Typically the lock is taken in external RTSP API calls that uses shared media
4104  * such as DESCRIBE, SETUP, ANNOUNCE, TEARDOWN, PLAY, PAUSE.
4105  *
4106  * As best practice take the lock as soon as the function get hold of a shared
4107  * media object. Release the lock right before the function returns.
4108  *
4109  * Since: 1.18
4110  */
4111 void
4112 gst_rtsp_media_lock (GstRTSPMedia * media)
4113 {
4114   GstRTSPMediaPrivate *priv;
4115
4116   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4117
4118   priv = media->priv;
4119
4120   g_mutex_lock (&priv->global_lock);
4121 }
4122
4123 /**
4124  * gst_rtsp_media_unlock:
4125  * @media: a #GstRTSPMedia
4126  *
4127  * Unlock the media.
4128  *
4129  * Since: 1.18
4130  */
4131 void
4132 gst_rtsp_media_unlock (GstRTSPMedia * media)
4133 {
4134   GstRTSPMediaPrivate *priv;
4135
4136   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4137
4138   priv = media->priv;
4139
4140   g_mutex_unlock (&priv->global_lock);
4141 }
4142
4143 /**
4144  * gst_rtsp_media_get_clock:
4145  * @media: a #GstRTSPMedia
4146  *
4147  * Get the clock that is used by the pipeline in @media.
4148  *
4149  * @media must be prepared before this method returns a valid clock object.
4150  *
4151  * Returns: (transfer full) (nullable): the #GstClock used by @media. unref after usage.
4152  */
4153 GstClock *
4154 gst_rtsp_media_get_clock (GstRTSPMedia * media)
4155 {
4156   GstClock *clock;
4157   GstRTSPMediaPrivate *priv;
4158
4159   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4160
4161   priv = media->priv;
4162
4163   g_rec_mutex_lock (&priv->state_lock);
4164   clock = get_clock_unlocked (media);
4165   g_rec_mutex_unlock (&priv->state_lock);
4166
4167   return clock;
4168 }
4169
4170 /**
4171  * gst_rtsp_media_get_base_time:
4172  * @media: a #GstRTSPMedia
4173  *
4174  * Get the base_time that is used by the pipeline in @media.
4175  *
4176  * @media must be prepared before this method returns a valid base_time.
4177  *
4178  * Returns: the base_time used by @media.
4179  */
4180 GstClockTime
4181 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
4182 {
4183   GstClockTime result;
4184   GstRTSPMediaPrivate *priv;
4185
4186   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
4187
4188   priv = media->priv;
4189
4190   g_rec_mutex_lock (&priv->state_lock);
4191   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4192     goto not_prepared;
4193
4194   result = gst_element_get_base_time (media->priv->pipeline);
4195   g_rec_mutex_unlock (&priv->state_lock);
4196
4197   return result;
4198
4199   /* ERRORS */
4200 not_prepared:
4201   {
4202     g_rec_mutex_unlock (&priv->state_lock);
4203     GST_DEBUG_OBJECT (media, "media was not prepared");
4204     return GST_CLOCK_TIME_NONE;
4205   }
4206 }
4207
4208 /**
4209  * gst_rtsp_media_get_time_provider:
4210  * @media: a #GstRTSPMedia
4211  * @address: (allow-none): an address or %NULL
4212  * @port: a port or 0
4213  *
4214  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
4215  * will listen on @address and @port for client time requests.
4216  *
4217  * Returns: (transfer full): the #GstNetTimeProvider of @media.
4218  */
4219 GstNetTimeProvider *
4220 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
4221     guint16 port)
4222 {
4223   GstRTSPMediaPrivate *priv;
4224   GstNetTimeProvider *provider = NULL;
4225
4226   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4227
4228   priv = media->priv;
4229
4230   g_rec_mutex_lock (&priv->state_lock);
4231   if (priv->time_provider) {
4232     if ((provider = priv->nettime) == NULL) {
4233       GstClock *clock;
4234
4235       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
4236         provider = gst_net_time_provider_new (clock, address, port);
4237         gst_object_unref (clock);
4238
4239         priv->nettime = provider;
4240       }
4241     }
4242   }
4243   g_rec_mutex_unlock (&priv->state_lock);
4244
4245   if (provider)
4246     gst_object_ref (provider);
4247
4248   return provider;
4249 }
4250
4251 static gboolean
4252 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
4253 {
4254   return gst_rtsp_sdp_from_media (sdp, info, media);
4255 }
4256
4257 /**
4258  * gst_rtsp_media_setup_sdp:
4259  * @media: a #GstRTSPMedia
4260  * @sdp: (transfer none): a #GstSDPMessage
4261  * @info: (transfer none): a #GstSDPInfo
4262  *
4263  * Add @media specific info to @sdp. @info is used to configure the connection
4264  * information in the SDP.
4265  *
4266  * Returns: TRUE on success.
4267  */
4268 gboolean
4269 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
4270     GstSDPInfo * info)
4271 {
4272   GstRTSPMediaPrivate *priv;
4273   GstRTSPMediaClass *klass;
4274   gboolean res;
4275
4276   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4277   g_return_val_if_fail (sdp != NULL, FALSE);
4278   g_return_val_if_fail (info != NULL, FALSE);
4279
4280   priv = media->priv;
4281
4282   g_rec_mutex_lock (&priv->state_lock);
4283
4284   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4285
4286   if (!klass->setup_sdp)
4287     goto no_setup_sdp;
4288
4289   res = klass->setup_sdp (media, sdp, info);
4290
4291   g_rec_mutex_unlock (&priv->state_lock);
4292
4293   return res;
4294
4295   /* ERRORS */
4296 no_setup_sdp:
4297   {
4298     g_rec_mutex_unlock (&priv->state_lock);
4299     GST_ERROR ("no setup_sdp function");
4300     g_critical ("no setup_sdp vmethod function set");
4301     return FALSE;
4302   }
4303 }
4304
4305 static gboolean
4306 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4307 {
4308   GstRTSPMediaPrivate *priv = media->priv;
4309   gint i, medias_len;
4310
4311   medias_len = gst_sdp_message_medias_len (sdp);
4312   if (medias_len != priv->streams->len) {
4313     GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
4314         priv->streams->len, medias_len);
4315     return FALSE;
4316   }
4317
4318   for (i = 0; i < medias_len; i++) {
4319     const gchar *proto;
4320     const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
4321     GstRTSPStream *stream;
4322     gint j, formats_len;
4323     const gchar *control;
4324     GstRTSPProfile profile, profiles;
4325
4326     stream = g_ptr_array_index (priv->streams, i);
4327
4328     /* TODO: Should we do something with the other SDP information? */
4329
4330     /* get proto */
4331     proto = gst_sdp_media_get_proto (sdp_media);
4332     if (proto == NULL) {
4333       GST_ERROR ("%p: SDP media %d has no proto", media, i);
4334       return FALSE;
4335     }
4336
4337     if (g_str_equal (proto, "RTP/AVP")) {
4338       profile = GST_RTSP_PROFILE_AVP;
4339     } else if (g_str_equal (proto, "RTP/SAVP")) {
4340       profile = GST_RTSP_PROFILE_SAVP;
4341     } else if (g_str_equal (proto, "RTP/AVPF")) {
4342       profile = GST_RTSP_PROFILE_AVPF;
4343     } else if (g_str_equal (proto, "RTP/SAVPF")) {
4344       profile = GST_RTSP_PROFILE_SAVPF;
4345     } else {
4346       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4347       return FALSE;
4348     }
4349
4350     profiles = gst_rtsp_stream_get_profiles (stream);
4351     if ((profiles & profile) == 0) {
4352       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4353       return FALSE;
4354     }
4355
4356     formats_len = gst_sdp_media_formats_len (sdp_media);
4357     for (j = 0; j < formats_len; j++) {
4358       gint pt;
4359       GstCaps *caps;
4360       GstStructure *s;
4361
4362       pt = atoi (gst_sdp_media_get_format (sdp_media, j));
4363
4364       GST_DEBUG (" looking at %d pt: %d", j, pt);
4365
4366       /* convert caps */
4367       caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
4368       if (caps == NULL) {
4369         GST_WARNING (" skipping pt %d without caps", pt);
4370         continue;
4371       }
4372
4373       /* do some tweaks */
4374       GST_DEBUG ("mapping sdp session level attributes to caps");
4375       gst_sdp_message_attributes_to_caps (sdp, caps);
4376       GST_DEBUG ("mapping sdp media level attributes to caps");
4377       gst_sdp_media_attributes_to_caps (sdp_media, caps);
4378
4379       s = gst_caps_get_structure (caps, 0);
4380       gst_structure_set_name (s, "application/x-rtp");
4381
4382       if (!g_strcmp0 (gst_structure_get_string (s, "encoding-name"), "ULPFEC"))
4383         gst_structure_set (s, "is-fec", G_TYPE_BOOLEAN, TRUE, NULL);
4384
4385       gst_rtsp_stream_set_pt_map (stream, pt, caps);
4386       gst_caps_unref (caps);
4387     }
4388
4389     control = gst_sdp_media_get_attribute_val (sdp_media, "control");
4390     if (control)
4391       gst_rtsp_stream_set_control (stream, control);
4392
4393   }
4394
4395   return TRUE;
4396 }
4397
4398 /**
4399  * gst_rtsp_media_handle_sdp:
4400  * @media: a #GstRTSPMedia
4401  * @sdp: (transfer none): a #GstSDPMessage
4402  *
4403  * Configure an SDP on @media for receiving streams
4404  *
4405  * Returns: TRUE on success.
4406  */
4407 gboolean
4408 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4409 {
4410   GstRTSPMediaPrivate *priv;
4411   GstRTSPMediaClass *klass;
4412   gboolean res;
4413
4414   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4415   g_return_val_if_fail (sdp != NULL, FALSE);
4416
4417   priv = media->priv;
4418
4419   g_rec_mutex_lock (&priv->state_lock);
4420
4421   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4422
4423   if (!klass->handle_sdp)
4424     goto no_handle_sdp;
4425
4426   res = klass->handle_sdp (media, sdp);
4427
4428   g_rec_mutex_unlock (&priv->state_lock);
4429
4430   return res;
4431
4432   /* ERRORS */
4433 no_handle_sdp:
4434   {
4435     g_rec_mutex_unlock (&priv->state_lock);
4436     GST_ERROR ("no handle_sdp function");
4437     g_critical ("no handle_sdp vmethod function set");
4438     return FALSE;
4439   }
4440 }
4441
4442 static void
4443 do_set_seqnum (GstRTSPStream * stream)
4444 {
4445   guint16 seq_num;
4446
4447   if (gst_rtsp_stream_is_sender (stream)) {
4448     seq_num = gst_rtsp_stream_get_current_seqnum (stream);
4449     gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
4450   }
4451 }
4452
4453 /* call with state_lock */
4454 static gboolean
4455 default_suspend (GstRTSPMedia * media)
4456 {
4457   GstRTSPMediaPrivate *priv = media->priv;
4458   GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
4459
4460   switch (priv->suspend_mode) {
4461     case GST_RTSP_SUSPEND_MODE_NONE:
4462       GST_DEBUG ("media %p no suspend", media);
4463       break;
4464     case GST_RTSP_SUSPEND_MODE_PAUSE:
4465       GST_DEBUG ("media %p suspend to PAUSED", media);
4466       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
4467       if (ret == GST_STATE_CHANGE_FAILURE)
4468         goto state_failed;
4469       break;
4470     case GST_RTSP_SUSPEND_MODE_RESET:
4471       GST_DEBUG ("media %p suspend to NULL", media);
4472       ret = set_target_state (media, GST_STATE_NULL, TRUE);
4473       if (ret == GST_STATE_CHANGE_FAILURE)
4474         goto state_failed;
4475       /* Because payloader needs to set the sequence number as
4476        * monotonic, we need to preserve the sequence number
4477        * after pause. (otherwise going from pause to play,  which
4478        * is actually from NULL to PLAY will create a new sequence
4479        * number. */
4480       g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
4481       break;
4482     default:
4483       break;
4484   }
4485
4486   /* If we use any suspend mode that changes the state then we must update
4487    * expected_async_done, since we might not be doing an asyncronous state
4488    * change anymore. */
4489   if (ret != GST_STATE_CHANGE_FAILURE && ret != GST_STATE_CHANGE_ASYNC)
4490     priv->expected_async_done = FALSE;
4491
4492   return TRUE;
4493
4494   /* ERRORS */
4495 state_failed:
4496   {
4497     GST_WARNING ("failed changing pipeline's state for media %p", media);
4498     return FALSE;
4499   }
4500 }
4501
4502 /**
4503  * gst_rtsp_media_suspend:
4504  * @media: a #GstRTSPMedia
4505  *
4506  * Suspend @media. The state of the pipeline managed by @media is set to
4507  * GST_STATE_NULL but all streams are kept. @media can be prepared again
4508  * with gst_rtsp_media_unsuspend()
4509  *
4510  * @media must be prepared with gst_rtsp_media_prepare();
4511  *
4512  * Returns: %TRUE on success.
4513  */
4514 gboolean
4515 gst_rtsp_media_suspend (GstRTSPMedia * media)
4516 {
4517   GstRTSPMediaPrivate *priv = media->priv;
4518   GstRTSPMediaClass *klass;
4519
4520   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4521
4522   GST_FIXME ("suspend for dynamic pipelines needs fixing");
4523
4524   /* this typically can happen for shared media. */
4525   if (priv->prepare_count > 1 &&
4526       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED) {
4527     goto done;
4528   } else if (priv->prepare_count > 1) {
4529     goto prepared_by_other_client;
4530   }
4531
4532   g_rec_mutex_lock (&priv->state_lock);
4533   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4534     goto not_prepared;
4535
4536   /* don't attempt to suspend when something is busy */
4537   if (priv->n_active > 0)
4538     goto done;
4539
4540   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4541   if (klass->suspend) {
4542     if (!klass->suspend (media))
4543       goto suspend_failed;
4544   }
4545
4546   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
4547 done:
4548   g_rec_mutex_unlock (&priv->state_lock);
4549
4550   return TRUE;
4551
4552   /* ERRORS */
4553 prepared_by_other_client:
4554   {
4555     GST_WARNING ("media %p was prepared by other client", media);
4556     return FALSE;
4557   }
4558 not_prepared:
4559   {
4560     g_rec_mutex_unlock (&priv->state_lock);
4561     GST_WARNING ("media %p was not prepared", media);
4562     return FALSE;
4563   }
4564 suspend_failed:
4565   {
4566     g_rec_mutex_unlock (&priv->state_lock);
4567     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4568     GST_WARNING ("failed to suspend media %p", media);
4569     return FALSE;
4570   }
4571 }
4572
4573 /* call with state_lock */
4574 static gboolean
4575 default_unsuspend (GstRTSPMedia * media)
4576 {
4577   GstRTSPMediaPrivate *priv = media->priv;
4578   gboolean preroll_ok;
4579
4580   switch (priv->suspend_mode) {
4581     case GST_RTSP_SUSPEND_MODE_NONE:
4582       if (gst_rtsp_media_is_receive_only (media))
4583         break;
4584       if (media_streams_blocking (media)) {
4585         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4586         /* at this point the media pipeline has been updated and contain all
4587          * specific transport parts: all active streams contain at least one sink
4588          * element and it's safe to unblock all blocked streams */
4589         media_streams_set_blocked (media, FALSE);
4590       } else {
4591         /* streams are not blocked and media is suspended from PAUSED */
4592         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4593       }
4594       g_rec_mutex_unlock (&priv->state_lock);
4595       if (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_ERROR) {
4596         g_rec_mutex_lock (&priv->state_lock);
4597         goto preroll_failed;
4598       }
4599       g_rec_mutex_lock (&priv->state_lock);
4600       break;
4601     case GST_RTSP_SUSPEND_MODE_PAUSE:
4602       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4603       break;
4604     case GST_RTSP_SUSPEND_MODE_RESET:
4605     {
4606       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4607       /* at this point the media pipeline has been updated and contain all
4608        * specific transport parts: all active streams contain at least one sink
4609        * element and it's safe to unblock all blocked streams */
4610       media_streams_set_blocked (media, FALSE);
4611       if (!start_preroll (media))
4612         goto start_failed;
4613
4614       g_rec_mutex_unlock (&priv->state_lock);
4615       preroll_ok = wait_preroll (media);
4616       g_rec_mutex_lock (&priv->state_lock);
4617
4618       if (!preroll_ok)
4619         goto preroll_failed;
4620     }
4621     default:
4622       break;
4623   }
4624
4625   return TRUE;
4626
4627   /* ERRORS */
4628 start_failed:
4629   {
4630     GST_WARNING ("failed to preroll pipeline");
4631     return FALSE;
4632   }
4633 preroll_failed:
4634   {
4635     GST_WARNING ("failed to preroll pipeline");
4636     return FALSE;
4637   }
4638 }
4639
4640 /**
4641  * gst_rtsp_media_unsuspend:
4642  * @media: a #GstRTSPMedia
4643  *
4644  * Unsuspend @media if it was in a suspended state. This method does nothing
4645  * when the media was not in the suspended state.
4646  *
4647  * Returns: %TRUE on success.
4648  */
4649 gboolean
4650 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
4651 {
4652   GstRTSPMediaPrivate *priv = media->priv;
4653   GstRTSPMediaClass *klass;
4654
4655   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4656
4657   g_rec_mutex_lock (&priv->state_lock);
4658   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4659     goto done;
4660
4661   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4662   if (klass->unsuspend) {
4663     if (!klass->unsuspend (media))
4664       goto unsuspend_failed;
4665   }
4666
4667 done:
4668   g_rec_mutex_unlock (&priv->state_lock);
4669
4670   return TRUE;
4671
4672   /* ERRORS */
4673 unsuspend_failed:
4674   {
4675     g_rec_mutex_unlock (&priv->state_lock);
4676     GST_WARNING ("failed to unsuspend media %p", media);
4677     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4678     return FALSE;
4679   }
4680 }
4681
4682 /* must be called with state-lock */
4683 static void
4684 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
4685 {
4686   GstRTSPMediaPrivate *priv = media->priv;
4687   GstStateChangeReturn set_state_ret;
4688   priv->expected_async_done = FALSE;
4689
4690   if (state == GST_STATE_NULL) {
4691     gst_rtsp_media_unprepare (media);
4692   } else {
4693     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
4694     set_target_state (media, state, FALSE);
4695
4696     if (state == GST_STATE_PLAYING) {
4697       /* make sure pads are not blocking anymore when going to PLAYING */
4698       media_streams_set_blocked (media, FALSE);
4699     }
4700
4701     /* when we are buffering, don't update the state yet, this will be done
4702      * when buffering finishes */
4703     if (priv->buffering) {
4704       GST_INFO ("Buffering busy, delay state change");
4705     } else {
4706       if (state == GST_STATE_PAUSED) {
4707         set_state_ret = set_state (media, state);
4708         if (set_state_ret == GST_STATE_CHANGE_ASYNC)
4709           priv->expected_async_done = TRUE;
4710         /* and suspend after pause */
4711         gst_rtsp_media_suspend (media);
4712       } else {
4713         set_state (media, state);
4714       }
4715     }
4716   }
4717 }
4718
4719 /**
4720  * gst_rtsp_media_set_pipeline_state:
4721  * @media: a #GstRTSPMedia
4722  * @state: the target state of the pipeline
4723  *
4724  * Set the state of the pipeline managed by @media to @state
4725  */
4726 void
4727 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
4728 {
4729   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4730
4731   g_rec_mutex_lock (&media->priv->state_lock);
4732   media_set_pipeline_state_locked (media, state);
4733   g_rec_mutex_unlock (&media->priv->state_lock);
4734 }
4735
4736 /**
4737  * gst_rtsp_media_set_state:
4738  * @media: a #GstRTSPMedia
4739  * @state: the target state of the media
4740  * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
4741  * a #GPtrArray of #GstRTSPStreamTransport pointers
4742  *
4743  * Set the state of @media to @state and for the transports in @transports.
4744  *
4745  * @media must be prepared with gst_rtsp_media_prepare();
4746  *
4747  * Returns: %TRUE on success.
4748  */
4749 gboolean
4750 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
4751     GPtrArray * transports)
4752 {
4753   GstRTSPMediaPrivate *priv;
4754   gint i;
4755   gboolean activate, deactivate, do_state;
4756   gint old_active;
4757
4758   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4759   g_return_val_if_fail (transports != NULL, FALSE);
4760
4761   priv = media->priv;
4762
4763   g_rec_mutex_lock (&priv->state_lock);
4764
4765   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING
4766       && gst_rtsp_media_is_shared (media)) {
4767     g_rec_mutex_unlock (&priv->state_lock);
4768     gst_rtsp_media_get_status (media);
4769     g_rec_mutex_lock (&priv->state_lock);
4770   }
4771   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
4772     goto error_status;
4773   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
4774       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4775     goto not_prepared;
4776
4777   /* NULL and READY are the same */
4778   if (state == GST_STATE_READY)
4779     state = GST_STATE_NULL;
4780
4781   activate = deactivate = FALSE;
4782
4783   GST_INFO ("going to state %s media %p, target state %s",
4784       gst_element_state_get_name (state), media,
4785       gst_element_state_get_name (priv->target_state));
4786
4787   switch (state) {
4788     case GST_STATE_NULL:
4789       /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
4790       if (priv->target_state >= GST_STATE_PAUSED)
4791         deactivate = TRUE;
4792       break;
4793     case GST_STATE_PAUSED:
4794       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
4795       if (priv->target_state == GST_STATE_PLAYING)
4796         deactivate = TRUE;
4797       break;
4798     case GST_STATE_PLAYING:
4799       /* we're going to PLAYING, activate */
4800       activate = TRUE;
4801       break;
4802     default:
4803       break;
4804   }
4805   old_active = priv->n_active;
4806
4807   GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
4808       activate, deactivate);
4809   for (i = 0; i < transports->len; i++) {
4810     GstRTSPStreamTransport *trans;
4811
4812     /* we need a non-NULL entry in the array */
4813     trans = g_ptr_array_index (transports, i);
4814     if (trans == NULL)
4815       continue;
4816
4817     if (activate) {
4818       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
4819         priv->n_active++;
4820     } else if (deactivate) {
4821       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
4822         priv->n_active--;
4823     }
4824   }
4825
4826   if (activate)
4827     media_streams_set_blocked (media, FALSE);
4828
4829   /* we just activated the first media, do the playing state change */
4830   if (old_active == 0 && activate)
4831     do_state = TRUE;
4832   /* if we have no more active media and prepare count is not indicate
4833    * that there are new session/sessions ongoing,
4834    * do the downward state changes */
4835   else if (priv->n_active == 0 && priv->prepare_count <= 1)
4836     do_state = TRUE;
4837   else
4838     do_state = FALSE;
4839
4840   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
4841       media, do_state);
4842
4843   if (priv->target_state != state) {
4844     if (do_state) {
4845       media_set_pipeline_state_locked (media, state);
4846       g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
4847           NULL);
4848     }
4849   }
4850
4851   /* remember where we are */
4852   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
4853           old_active != priv->n_active)) {
4854     g_mutex_lock (&priv->lock);
4855     collect_media_stats (media);
4856     g_mutex_unlock (&priv->lock);
4857   }
4858   g_rec_mutex_unlock (&priv->state_lock);
4859
4860   return TRUE;
4861
4862   /* ERRORS */
4863 not_prepared:
4864   {
4865     GST_WARNING ("media %p was not prepared", media);
4866     g_rec_mutex_unlock (&priv->state_lock);
4867     return FALSE;
4868   }
4869 error_status:
4870   {
4871     GST_WARNING ("media %p in error status while changing to state %d",
4872         media, state);
4873     if (state == GST_STATE_NULL) {
4874       for (i = 0; i < transports->len; i++) {
4875         GstRTSPStreamTransport *trans;
4876
4877         /* we need a non-NULL entry in the array */
4878         trans = g_ptr_array_index (transports, i);
4879         if (trans == NULL)
4880           continue;
4881
4882         gst_rtsp_stream_transport_set_active (trans, FALSE);
4883       }
4884       priv->n_active = 0;
4885     }
4886     g_rec_mutex_unlock (&priv->state_lock);
4887     return FALSE;
4888   }
4889 }
4890
4891 /**
4892  * gst_rtsp_media_set_transport_mode:
4893  * @media: a #GstRTSPMedia
4894  * @mode: the new value
4895  *
4896  * Sets if the media pipeline can work in PLAY or RECORD mode
4897  */
4898 void
4899 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
4900     GstRTSPTransportMode mode)
4901 {
4902   GstRTSPMediaPrivate *priv;
4903
4904   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4905
4906   priv = media->priv;
4907
4908   g_mutex_lock (&priv->lock);
4909   priv->transport_mode = mode;
4910   g_mutex_unlock (&priv->lock);
4911 }
4912
4913 /**
4914  * gst_rtsp_media_get_transport_mode:
4915  * @media: a #GstRTSPMedia
4916  *
4917  * Check if the pipeline for @media can be used for PLAY or RECORD methods.
4918  *
4919  * Returns: The transport mode.
4920  */
4921 GstRTSPTransportMode
4922 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
4923 {
4924   GstRTSPMediaPrivate *priv;
4925   GstRTSPTransportMode res;
4926
4927   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4928
4929   priv = media->priv;
4930
4931   g_mutex_lock (&priv->lock);
4932   res = priv->transport_mode;
4933   g_mutex_unlock (&priv->lock);
4934
4935   return res;
4936 }
4937
4938 /**
4939  * gst_rtsp_media_seekable:
4940  * @media: a #GstRTSPMedia
4941  *
4942  * Check if the pipeline for @media seek and up to what point in time,
4943  * it can seek.
4944  *
4945  * Returns: -1 if the stream is not seekable, 0 if seekable only to the beginning
4946  * and > 0 to indicate the longest duration between any two random access points.
4947  * %G_MAXINT64 means any value is possible.
4948  *
4949  * Since: 1.14
4950  */
4951 GstClockTimeDiff
4952 gst_rtsp_media_seekable (GstRTSPMedia * media)
4953 {
4954   GstRTSPMediaPrivate *priv;
4955   GstClockTimeDiff res;
4956
4957   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4958
4959   priv = media->priv;
4960
4961   /* Currently we are not able to seek on live streams,
4962    * and no stream is seekable only to the beginning */
4963   g_mutex_lock (&priv->lock);
4964   res = priv->seekable;
4965   g_mutex_unlock (&priv->lock);
4966
4967   return res;
4968 }
4969
4970 /**
4971  * gst_rtsp_media_complete_pipeline:
4972  * @media: a #GstRTSPMedia
4973  * @transports: (element-type GstRTSPTransport): a list of #GstRTSPTransport
4974  *
4975  * Add a receiver and sender parts to the pipeline based on the transport from
4976  * SETUP.
4977  *
4978  * Returns: %TRUE if the media pipeline has been sucessfully updated.
4979  *
4980  * Since: 1.14
4981  */
4982 gboolean
4983 gst_rtsp_media_complete_pipeline (GstRTSPMedia * media, GPtrArray * transports)
4984 {
4985   GstRTSPMediaPrivate *priv;
4986   guint i;
4987
4988   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4989   g_return_val_if_fail (transports, FALSE);
4990
4991   GST_DEBUG_OBJECT (media, "complete pipeline");
4992
4993   priv = media->priv;
4994
4995   g_mutex_lock (&priv->lock);
4996   for (i = 0; i < priv->streams->len; i++) {
4997     GstRTSPStreamTransport *transport;
4998     GstRTSPStream *stream;
4999     const GstRTSPTransport *rtsp_transport;
5000
5001     transport = g_ptr_array_index (transports, i);
5002     if (!transport)
5003       continue;
5004
5005     stream = gst_rtsp_stream_transport_get_stream (transport);
5006     if (!stream)
5007       continue;
5008
5009     rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
5010
5011     if (!gst_rtsp_stream_complete_stream (stream, rtsp_transport)) {
5012       g_mutex_unlock (&priv->lock);
5013       return FALSE;
5014     }
5015   }
5016
5017   priv->complete = TRUE;
5018   g_mutex_unlock (&priv->lock);
5019
5020   return TRUE;
5021 }
5022
5023 /**
5024  * gst_rtsp_media_is_receive_only:
5025  *
5026  * Returns: %TRUE if @media is receive-only, %FALSE otherwise.
5027  * Since: 1.18
5028  */
5029 gboolean
5030 gst_rtsp_media_is_receive_only (GstRTSPMedia * media)
5031 {
5032   GstRTSPMediaPrivate *priv = media->priv;
5033   gboolean receive_only;
5034
5035   g_mutex_lock (&priv->lock);
5036   receive_only = is_receive_only (media);
5037   g_mutex_unlock (&priv->lock);
5038
5039   return receive_only;
5040 }
5041
5042 /**
5043  * gst_rtsp_media_has_completed_sender:
5044  *
5045  * See gst_rtsp_stream_is_complete(), gst_rtsp_stream_is_sender().
5046  *
5047  * Returns: whether @media has at least one complete sender stream.
5048  * Since: 1.18
5049  */
5050 gboolean
5051 gst_rtsp_media_has_completed_sender (GstRTSPMedia * media)
5052 {
5053   GstRTSPMediaPrivate *priv = media->priv;
5054   gboolean sender = FALSE;
5055   guint i;
5056
5057   g_mutex_lock (&priv->lock);
5058   for (i = 0; i < priv->streams->len; i++) {
5059     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
5060     if (gst_rtsp_stream_is_complete (stream))
5061       if (gst_rtsp_stream_is_sender (stream) ||
5062           !gst_rtsp_stream_is_receiver (stream)) {
5063         sender = TRUE;
5064         break;
5065       }
5066   }
5067   g_mutex_unlock (&priv->lock);
5068
5069   return sender;
5070 }
5071
5072 /**
5073  * gst_rtsp_media_set_rate_control:
5074  *
5075  * Define whether @media will follow the Rate-Control=no behaviour as specified
5076  * in the ONVIF replay spec.
5077  *
5078  * Since: 1.18
5079  */
5080 void
5081 gst_rtsp_media_set_rate_control (GstRTSPMedia * media, gboolean enabled)
5082 {
5083   GstRTSPMediaPrivate *priv;
5084   guint i;
5085
5086   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
5087
5088   GST_LOG_OBJECT (media, "%s rate control", enabled ? "Enabling" : "Disabling");
5089
5090   priv = media->priv;
5091
5092   g_mutex_lock (&priv->lock);
5093   priv->do_rate_control = enabled;
5094   for (i = 0; i < priv->streams->len; i++) {
5095     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
5096
5097     gst_rtsp_stream_set_rate_control (stream, enabled);
5098
5099   }
5100   g_mutex_unlock (&priv->lock);
5101 }
5102
5103 /**
5104  * gst_rtsp_media_get_rate_control:
5105  *
5106  * Returns: whether @media will follow the Rate-Control=no behaviour as specified
5107  * in the ONVIF replay spec.
5108  *
5109  * Since: 1.18
5110  */
5111 gboolean
5112 gst_rtsp_media_get_rate_control (GstRTSPMedia * media)
5113 {
5114   GstRTSPMediaPrivate *priv;
5115   gboolean res;
5116
5117   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
5118
5119   priv = media->priv;
5120
5121   g_mutex_lock (&priv->lock);
5122   res = priv->do_rate_control;
5123   g_mutex_unlock (&priv->lock);
5124
5125   return res;
5126 }