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