onvif: Implement and test the Streaming Specification
[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
2801       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2802
2803       if (rate < 0.0) {
2804         GstClockTime temp_time = start;
2805         GstSeekType temp_type = start_type;
2806
2807         start = stop;
2808         start_type = stop_type;
2809         stop = temp_time;
2810         stop_type = temp_type;
2811       }
2812
2813       seek_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type,
2814           start, stop_type, stop);
2815
2816       gst_event_set_seek_trickmode_interval (seek_event, trickmode_interval);
2817
2818       res = gst_element_send_event (priv->pipeline, seek_event);
2819
2820       /* and block for the seek to complete */
2821       GST_INFO ("done seeking %d", res);
2822       if (!res)
2823         goto seek_failed;
2824
2825       g_rec_mutex_unlock (&priv->state_lock);
2826
2827       /* wait until pipeline is prerolled again, this will also collect stats */
2828       if (!wait_preroll (media))
2829         goto preroll_failed;
2830
2831       g_rec_mutex_lock (&priv->state_lock);
2832       GST_INFO ("prerolled again");
2833     }
2834   } else {
2835     GST_INFO ("no seek needed");
2836     res = TRUE;
2837   }
2838   g_rec_mutex_unlock (&priv->state_lock);
2839
2840   return res;
2841
2842   /* ERRORS */
2843 not_prepared:
2844   {
2845     g_rec_mutex_unlock (&priv->state_lock);
2846     GST_INFO ("media %p is not prepared", media);
2847     return FALSE;
2848   }
2849 not_complete:
2850   {
2851     g_rec_mutex_unlock (&priv->state_lock);
2852     GST_INFO ("pipeline is not complete");
2853     return FALSE;
2854   }
2855 not_seekable:
2856   {
2857     g_rec_mutex_unlock (&priv->state_lock);
2858     GST_INFO ("pipeline is not seekable");
2859     return FALSE;
2860   }
2861 not_supported:
2862   {
2863     g_rec_mutex_unlock (&priv->state_lock);
2864     GST_WARNING ("conversion to npt not supported");
2865     return FALSE;
2866   }
2867 seek_failed:
2868   {
2869     g_rec_mutex_unlock (&priv->state_lock);
2870     GST_INFO ("seeking failed");
2871     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2872     return FALSE;
2873   }
2874 preroll_failed:
2875   {
2876     GST_WARNING ("failed to preroll after seek");
2877     return FALSE;
2878   }
2879 }
2880
2881 /**
2882  * gst_rtsp_media_seek_full:
2883  * @media: a #GstRTSPMedia
2884  * @range: (transfer none): a #GstRTSPTimeRange
2885  * @flags: The minimal set of #GstSeekFlags to use
2886  *
2887  * Seek the pipeline of @media to @range with the given @flags.
2888  * @media must be prepared with gst_rtsp_media_prepare().
2889  *
2890  * Returns: %TRUE on success.
2891  */
2892 gboolean
2893 gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
2894     GstSeekFlags flags)
2895 {
2896   return gst_rtsp_media_seek_trickmode (media, range, flags, 1.0, 0);
2897 }
2898
2899 /**
2900  * gst_rtsp_media_seek:
2901  * @media: a #GstRTSPMedia
2902  * @range: (transfer none): a #GstRTSPTimeRange
2903  *
2904  * Seek the pipeline of @media to @range. @media must be prepared with
2905  * gst_rtsp_media_prepare().
2906  *
2907  * Returns: %TRUE on success.
2908  */
2909 gboolean
2910 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
2911 {
2912   return gst_rtsp_media_seek_trickmode (media, range, GST_SEEK_FLAG_NONE,
2913       1.0, 0);
2914 }
2915
2916 static void
2917 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
2918 {
2919   *blocked &= gst_rtsp_stream_is_blocking (stream);
2920 }
2921
2922 static gboolean
2923 media_streams_blocking (GstRTSPMedia * media)
2924 {
2925   gboolean blocking = TRUE;
2926
2927   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
2928       &blocking);
2929
2930   return blocking;
2931 }
2932
2933 static GstStateChangeReturn
2934 set_state (GstRTSPMedia * media, GstState state)
2935 {
2936   GstRTSPMediaPrivate *priv = media->priv;
2937   GstStateChangeReturn ret;
2938
2939   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
2940       media);
2941   ret = gst_element_set_state (priv->pipeline, state);
2942
2943   return ret;
2944 }
2945
2946 static GstStateChangeReturn
2947 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
2948 {
2949   GstRTSPMediaPrivate *priv = media->priv;
2950   GstStateChangeReturn ret;
2951
2952   GST_INFO ("set target state to %s for media %p",
2953       gst_element_state_get_name (state), media);
2954   priv->target_state = state;
2955
2956   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
2957       priv->target_state, NULL);
2958
2959   if (do_state)
2960     ret = set_state (media, state);
2961   else
2962     ret = GST_STATE_CHANGE_SUCCESS;
2963
2964   return ret;
2965 }
2966
2967 /* called with state-lock */
2968 static gboolean
2969 default_handle_message (GstRTSPMedia * media, GstMessage * message)
2970 {
2971   GstRTSPMediaPrivate *priv = media->priv;
2972   GstMessageType type;
2973
2974   type = GST_MESSAGE_TYPE (message);
2975
2976   switch (type) {
2977     case GST_MESSAGE_STATE_CHANGED:
2978     {
2979       GstState old, new, pending;
2980
2981       if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
2982         break;
2983
2984       gst_message_parse_state_changed (message, &old, &new, &pending);
2985
2986       GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
2987           gst_element_state_get_name (old), gst_element_state_get_name (new),
2988           gst_element_state_get_name (pending));
2989       if (priv->no_more_pads_pending == 0
2990           && gst_rtsp_media_is_receive_only (media) && old == GST_STATE_READY
2991           && new == GST_STATE_PAUSED) {
2992         GST_INFO ("%p: went to PAUSED, prepared now", media);
2993         collect_media_stats (media);
2994
2995         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2996           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2997       }
2998
2999       break;
3000     }
3001     case GST_MESSAGE_BUFFERING:
3002     {
3003       gint percent;
3004
3005       gst_message_parse_buffering (message, &percent);
3006
3007       /* no state management needed for live pipelines */
3008       if (priv->is_live)
3009         break;
3010
3011       if (percent == 100) {
3012         /* a 100% message means buffering is done */
3013         priv->buffering = FALSE;
3014         /* if the desired state is playing, go back */
3015         if (priv->target_state == GST_STATE_PLAYING) {
3016           GST_INFO ("Buffering done, setting pipeline to PLAYING");
3017           set_state (media, GST_STATE_PLAYING);
3018         } else {
3019           GST_INFO ("Buffering done");
3020         }
3021       } else {
3022         /* buffering busy */
3023         if (priv->buffering == FALSE) {
3024           if (priv->target_state == GST_STATE_PLAYING) {
3025             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
3026             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
3027             set_state (media, GST_STATE_PAUSED);
3028           } else {
3029             GST_INFO ("Buffering ...");
3030           }
3031         }
3032         priv->buffering = TRUE;
3033       }
3034       break;
3035     }
3036     case GST_MESSAGE_LATENCY:
3037     {
3038       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
3039       break;
3040     }
3041     case GST_MESSAGE_ERROR:
3042     {
3043       GError *gerror;
3044       gchar *debug;
3045
3046       gst_message_parse_error (message, &gerror, &debug);
3047       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
3048       g_error_free (gerror);
3049       g_free (debug);
3050
3051       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3052       break;
3053     }
3054     case GST_MESSAGE_WARNING:
3055     {
3056       GError *gerror;
3057       gchar *debug;
3058
3059       gst_message_parse_warning (message, &gerror, &debug);
3060       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
3061       g_error_free (gerror);
3062       g_free (debug);
3063       break;
3064     }
3065     case GST_MESSAGE_ELEMENT:
3066     {
3067       const GstStructure *s;
3068
3069       s = gst_message_get_structure (message);
3070       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
3071         GST_DEBUG ("media received blocking message");
3072         if (priv->blocked && media_streams_blocking (media) &&
3073             priv->no_more_pads_pending == 0) {
3074           GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "media is blocking");
3075           collect_media_stats (media);
3076
3077           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3078             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3079         }
3080       }
3081       break;
3082     }
3083     case GST_MESSAGE_STREAM_STATUS:
3084       break;
3085     case GST_MESSAGE_ASYNC_DONE:
3086       if (priv->complete) {
3087         /* receive the final ASYNC_DONE, that is posted by the media pipeline
3088          * after all the transport parts have been successfully added to
3089          * the media streams. */
3090         GST_DEBUG_OBJECT (media, "got async-done");
3091         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3092           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3093       }
3094       break;
3095     case GST_MESSAGE_EOS:
3096       GST_INFO ("%p: got EOS", media);
3097
3098       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
3099         GST_DEBUG ("shutting down after EOS");
3100         finish_unprepare (media);
3101       }
3102       break;
3103     default:
3104       GST_INFO ("%p: got message type %d (%s)", media, type,
3105           gst_message_type_get_name (type));
3106       break;
3107   }
3108   return TRUE;
3109 }
3110
3111 static gboolean
3112 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
3113 {
3114   GstRTSPMediaPrivate *priv = media->priv;
3115   GstRTSPMediaClass *klass;
3116   gboolean ret;
3117
3118   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3119
3120   g_rec_mutex_lock (&priv->state_lock);
3121   if (klass->handle_message)
3122     ret = klass->handle_message (media, message);
3123   else
3124     ret = FALSE;
3125   g_rec_mutex_unlock (&priv->state_lock);
3126
3127   return ret;
3128 }
3129
3130 static void
3131 watch_destroyed (GstRTSPMedia * media)
3132 {
3133   GST_DEBUG_OBJECT (media, "source destroyed");
3134   g_object_unref (media);
3135 }
3136
3137 static GstElement *
3138 find_payload_element (GstElement * payloader)
3139 {
3140   GstElement *pay = NULL;
3141
3142   if (GST_IS_BIN (payloader)) {
3143     GstIterator *iter;
3144     GValue item = { 0 };
3145
3146     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
3147     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
3148       GstElement *element = (GstElement *) g_value_get_object (&item);
3149       GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
3150       const gchar *klass;
3151
3152       klass =
3153           gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
3154       if (klass == NULL)
3155         continue;
3156
3157       if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
3158         pay = gst_object_ref (element);
3159         g_value_unset (&item);
3160         break;
3161       }
3162       g_value_unset (&item);
3163     }
3164     gst_iterator_free (iter);
3165   } else {
3166     pay = g_object_ref (payloader);
3167   }
3168
3169   return pay;
3170 }
3171
3172 /* called from streaming threads */
3173 static void
3174 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3175 {
3176   GstRTSPMediaPrivate *priv = media->priv;
3177   GstRTSPStream *stream;
3178   GstElement *pay;
3179
3180   /* find the real payload element */
3181   pay = find_payload_element (element);
3182   stream = gst_rtsp_media_create_stream (media, pay, pad);
3183   gst_object_unref (pay);
3184
3185   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3186
3187   g_rec_mutex_lock (&priv->state_lock);
3188   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3189     goto not_preparing;
3190
3191   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
3192
3193   /* join the element in the PAUSED state because this callback is
3194    * called from the streaming thread and it is PAUSED */
3195   if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3196           priv->rtpbin, GST_STATE_PAUSED)) {
3197     GST_WARNING ("failed to join bin element");
3198   }
3199
3200   if (priv->blocked)
3201     gst_rtsp_stream_set_blocked (stream, TRUE);
3202
3203   g_rec_mutex_unlock (&priv->state_lock);
3204
3205   return;
3206
3207   /* ERRORS */
3208 not_preparing:
3209   {
3210     gst_rtsp_media_remove_stream (media, stream);
3211     g_rec_mutex_unlock (&priv->state_lock);
3212     GST_INFO ("ignore pad because we are not preparing");
3213     return;
3214   }
3215 }
3216
3217 static void
3218 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3219 {
3220   GstRTSPMediaPrivate *priv = media->priv;
3221   GstRTSPStream *stream;
3222
3223   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
3224   if (stream == NULL)
3225     return;
3226
3227   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3228
3229   g_rec_mutex_lock (&priv->state_lock);
3230   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3231   g_rec_mutex_unlock (&priv->state_lock);
3232
3233   gst_rtsp_media_remove_stream (media, stream);
3234 }
3235
3236 static void
3237 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
3238 {
3239   GstRTSPMediaPrivate *priv = media->priv;
3240
3241   GST_INFO_OBJECT (element, "no more pads");
3242   g_mutex_lock (&priv->lock);
3243   priv->no_more_pads_pending--;
3244   g_mutex_unlock (&priv->lock);
3245 }
3246
3247 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
3248
3249 struct _DynPaySignalHandlers
3250 {
3251   gulong pad_added_handler;
3252   gulong pad_removed_handler;
3253   gulong no_more_pads_handler;
3254 };
3255
3256 static gboolean
3257 start_preroll (GstRTSPMedia * media)
3258 {
3259   GstRTSPMediaPrivate *priv = media->priv;
3260   GstStateChangeReturn ret;
3261
3262   GST_INFO ("setting pipeline to PAUSED for media %p", media);
3263
3264   /* start blocked since it is possible that there are no sink elements yet */
3265   media_streams_set_blocked (media, TRUE);
3266   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3267
3268   switch (ret) {
3269     case GST_STATE_CHANGE_SUCCESS:
3270       GST_INFO ("SUCCESS state change for media %p", media);
3271       break;
3272     case GST_STATE_CHANGE_ASYNC:
3273       GST_INFO ("ASYNC state change for media %p", media);
3274       break;
3275     case GST_STATE_CHANGE_NO_PREROLL:
3276       /* we need to go to PLAYING */
3277       GST_INFO ("NO_PREROLL state change: live media %p", media);
3278       /* FIXME we disable seeking for live streams for now. We should perform a
3279        * seeking query in preroll instead */
3280       priv->seekable = -1;
3281       priv->is_live = TRUE;
3282
3283       ret = set_state (media, GST_STATE_PLAYING);
3284       if (ret == GST_STATE_CHANGE_FAILURE)
3285         goto state_failed;
3286       break;
3287     case GST_STATE_CHANGE_FAILURE:
3288       goto state_failed;
3289   }
3290
3291   return TRUE;
3292
3293 state_failed:
3294   {
3295     GST_WARNING ("failed to preroll pipeline");
3296     return FALSE;
3297   }
3298 }
3299
3300 static gboolean
3301 wait_preroll (GstRTSPMedia * media)
3302 {
3303   GstRTSPMediaStatus status;
3304
3305   GST_DEBUG ("wait to preroll pipeline");
3306
3307   /* wait until pipeline is prerolled */
3308   status = gst_rtsp_media_get_status (media);
3309   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
3310     goto preroll_failed;
3311
3312   return TRUE;
3313
3314 preroll_failed:
3315   {
3316     GST_WARNING ("failed to preroll pipeline");
3317     return FALSE;
3318   }
3319 }
3320
3321 static GstElement *
3322 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3323 {
3324   GstRTSPMediaPrivate *priv = media->priv;
3325   GstRTSPStream *stream = NULL;
3326   guint i;
3327   GstElement *res = NULL;
3328
3329   g_mutex_lock (&priv->lock);
3330   for (i = 0; i < priv->streams->len; i++) {
3331     stream = g_ptr_array_index (priv->streams, i);
3332
3333     if (sessid == gst_rtsp_stream_get_index (stream))
3334       break;
3335
3336     stream = NULL;
3337   }
3338   g_mutex_unlock (&priv->lock);
3339
3340   if (stream)
3341     res = gst_rtsp_stream_request_aux_sender (stream, sessid);
3342
3343   return res;
3344 }
3345
3346 static GstElement *
3347 request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3348 {
3349   GstRTSPMediaPrivate *priv = media->priv;
3350   GstRTSPStream *stream = NULL;
3351   guint i;
3352   GstElement *res = NULL;
3353
3354   g_mutex_lock (&priv->lock);
3355   for (i = 0; i < priv->streams->len; i++) {
3356     stream = g_ptr_array_index (priv->streams, i);
3357
3358     if (sessid == gst_rtsp_stream_get_index (stream))
3359       break;
3360
3361     stream = NULL;
3362   }
3363   g_mutex_unlock (&priv->lock);
3364
3365   if (stream)
3366     res = gst_rtsp_stream_request_aux_receiver (stream, sessid);
3367
3368   return res;
3369 }
3370
3371 static GstElement *
3372 request_fec_decoder (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3373 {
3374   GstRTSPMediaPrivate *priv = media->priv;
3375   GstRTSPStream *stream = NULL;
3376   guint i;
3377   GstElement *res = NULL;
3378
3379   g_mutex_lock (&priv->lock);
3380   for (i = 0; i < priv->streams->len; i++) {
3381     stream = g_ptr_array_index (priv->streams, i);
3382
3383     if (sessid == gst_rtsp_stream_get_index (stream))
3384       break;
3385
3386     stream = NULL;
3387   }
3388   g_mutex_unlock (&priv->lock);
3389
3390   if (stream) {
3391     res = gst_rtsp_stream_request_ulpfec_decoder (stream, rtpbin, sessid);
3392   }
3393
3394   return res;
3395 }
3396
3397 static void
3398 new_storage_cb (GstElement * rtpbin, GObject * storage, guint sessid,
3399     GstRTSPMedia * media)
3400 {
3401   g_object_set (storage, "size-time", (media->priv->latency + 50) * GST_MSECOND,
3402       NULL);
3403 }
3404
3405 static gboolean
3406 start_prepare (GstRTSPMedia * media)
3407 {
3408   GstRTSPMediaPrivate *priv = media->priv;
3409   guint i;
3410   GList *walk;
3411
3412   g_rec_mutex_lock (&priv->state_lock);
3413   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3414     goto no_longer_preparing;
3415
3416   g_signal_connect (priv->rtpbin, "new-storage", G_CALLBACK (new_storage_cb),
3417       media);
3418   g_signal_connect (priv->rtpbin, "request-fec-decoder",
3419       G_CALLBACK (request_fec_decoder), media);
3420
3421   /* link streams we already have, other streams might appear when we have
3422    * dynamic elements */
3423   for (i = 0; i < priv->streams->len; i++) {
3424     GstRTSPStream *stream;
3425
3426     stream = g_ptr_array_index (priv->streams, i);
3427
3428     if (priv->rtx_time > 0) {
3429       /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
3430       g_signal_connect (priv->rtpbin, "request-aux-sender",
3431           (GCallback) request_aux_sender, media);
3432     }
3433
3434     if (priv->do_retransmission) {
3435       g_signal_connect (priv->rtpbin, "request-aux-receiver",
3436           (GCallback) request_aux_receiver, media);
3437     }
3438
3439     if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3440             priv->rtpbin, GST_STATE_NULL)) {
3441       goto join_bin_failed;
3442     }
3443   }
3444
3445   if (priv->rtpbin)
3446     g_object_set (priv->rtpbin, "do-retransmission", priv->do_retransmission,
3447         "do-lost", TRUE, NULL);
3448
3449   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3450     GstElement *elem = walk->data;
3451     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
3452
3453     GST_INFO ("adding callbacks for dynamic element %p", elem);
3454
3455     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
3456         (GCallback) pad_added_cb, media);
3457     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
3458         (GCallback) pad_removed_cb, media);
3459     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
3460         (GCallback) no_more_pads_cb, media);
3461
3462     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
3463   }
3464
3465   if (priv->nb_dynamic_elements == 0 && gst_rtsp_media_is_receive_only (media)) {
3466     /* If we are receive_only (RECORD), do not try to preroll, to avoid
3467      * a second ASYNC state change failing */
3468     priv->is_live = TRUE;
3469     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3470   } else if (!start_preroll (media)) {
3471     goto preroll_failed;
3472   }
3473
3474   g_rec_mutex_unlock (&priv->state_lock);
3475
3476   return FALSE;
3477
3478 no_longer_preparing:
3479   {
3480     GST_INFO ("media is no longer preparing");
3481     g_rec_mutex_unlock (&priv->state_lock);
3482     return FALSE;
3483   }
3484 join_bin_failed:
3485   {
3486     GST_WARNING ("failed to join bin element");
3487     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3488     g_rec_mutex_unlock (&priv->state_lock);
3489     return FALSE;
3490   }
3491 preroll_failed:
3492   {
3493     GST_WARNING ("failed to preroll pipeline");
3494     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3495     g_rec_mutex_unlock (&priv->state_lock);
3496     return FALSE;
3497   }
3498 }
3499
3500 static gboolean
3501 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3502 {
3503   GstRTSPMediaPrivate *priv;
3504   GstRTSPMediaClass *klass;
3505   GstBus *bus;
3506   GMainContext *context;
3507   GSource *source;
3508
3509   priv = media->priv;
3510
3511   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3512
3513   if (!klass->create_rtpbin)
3514     goto no_create_rtpbin;
3515
3516   priv->rtpbin = klass->create_rtpbin (media);
3517   if (priv->rtpbin != NULL) {
3518     gboolean success = TRUE;
3519
3520     g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
3521
3522     if (klass->setup_rtpbin)
3523       success = klass->setup_rtpbin (media, priv->rtpbin);
3524
3525     if (success == FALSE) {
3526       gst_object_unref (priv->rtpbin);
3527       priv->rtpbin = NULL;
3528     }
3529   }
3530   if (priv->rtpbin == NULL)
3531     goto no_rtpbin;
3532
3533   priv->thread = thread;
3534   context = (thread != NULL) ? (thread->context) : NULL;
3535
3536   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
3537
3538   /* add the pipeline bus to our custom mainloop */
3539   priv->source = gst_bus_create_watch (bus);
3540   gst_object_unref (bus);
3541
3542   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
3543       g_object_ref (media), (GDestroyNotify) watch_destroyed);
3544
3545   priv->id = g_source_attach (priv->source, context);
3546
3547   /* add stuff to the bin */
3548   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
3549
3550   /* do remainder in context */
3551   source = g_idle_source_new ();
3552   g_source_set_callback (source, (GSourceFunc) start_prepare,
3553       g_object_ref (media), (GDestroyNotify) g_object_unref);
3554   g_source_attach (source, context);
3555   g_source_unref (source);
3556
3557   return TRUE;
3558
3559   /* ERRORS */
3560 no_create_rtpbin:
3561   {
3562     GST_ERROR ("no create_rtpbin function");
3563     g_critical ("no create_rtpbin vmethod function set");
3564     return FALSE;
3565   }
3566 no_rtpbin:
3567   {
3568     GST_WARNING ("no rtpbin element");
3569     g_warning ("failed to create element 'rtpbin', check your installation");
3570     return FALSE;
3571   }
3572 }
3573
3574 /**
3575  * gst_rtsp_media_prepare:
3576  * @media: a #GstRTSPMedia
3577  * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
3578  *   bus handler or %NULL
3579  *
3580  * Prepare @media for streaming. This function will create the objects
3581  * to manage the streaming. A pipeline must have been set on @media with
3582  * gst_rtsp_media_take_pipeline().
3583  *
3584  * It will preroll the pipeline and collect vital information about the streams
3585  * such as the duration.
3586  *
3587  * Returns: %TRUE on success.
3588  */
3589 gboolean
3590 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3591 {
3592   GstRTSPMediaPrivate *priv;
3593   GstRTSPMediaClass *klass;
3594
3595   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3596
3597   priv = media->priv;
3598
3599   g_rec_mutex_lock (&priv->state_lock);
3600   priv->prepare_count++;
3601
3602   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
3603       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
3604     goto was_prepared;
3605
3606   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3607     goto is_preparing;
3608
3609   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
3610     goto not_unprepared;
3611
3612   if (!priv->reusable && priv->reused)
3613     goto is_reused;
3614
3615   GST_INFO ("preparing media %p", media);
3616
3617   /* reset some variables */
3618   priv->is_live = FALSE;
3619   priv->seekable = -1;
3620   priv->buffering = FALSE;
3621   priv->no_more_pads_pending = priv->nb_dynamic_elements;
3622
3623   /* we're preparing now */
3624   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3625
3626   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3627   if (klass->prepare) {
3628     if (!klass->prepare (media, thread))
3629       goto prepare_failed;
3630   }
3631
3632 wait_status:
3633   g_rec_mutex_unlock (&priv->state_lock);
3634
3635   /* now wait for all pads to be prerolled, FIXME, we should somehow be
3636    * able to do this async so that we don't block the server thread. */
3637   if (!wait_preroll (media))
3638     goto preroll_failed;
3639
3640   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
3641
3642   GST_INFO ("object %p is prerolled", media);
3643
3644   return TRUE;
3645
3646   /* OK */
3647 is_preparing:
3648   {
3649     /* we are not going to use the giving thread, so stop it. */
3650     if (thread)
3651       gst_rtsp_thread_stop (thread);
3652     goto wait_status;
3653   }
3654 was_prepared:
3655   {
3656     GST_LOG ("media %p was prepared", media);
3657     /* we are not going to use the giving thread, so stop it. */
3658     if (thread)
3659       gst_rtsp_thread_stop (thread);
3660     g_rec_mutex_unlock (&priv->state_lock);
3661     return TRUE;
3662   }
3663   /* ERRORS */
3664 not_unprepared:
3665   {
3666     /* we are not going to use the giving thread, so stop it. */
3667     if (thread)
3668       gst_rtsp_thread_stop (thread);
3669     GST_WARNING ("media %p was not unprepared", media);
3670     priv->prepare_count--;
3671     g_rec_mutex_unlock (&priv->state_lock);
3672     return FALSE;
3673   }
3674 is_reused:
3675   {
3676     /* we are not going to use the giving thread, so stop it. */
3677     if (thread)
3678       gst_rtsp_thread_stop (thread);
3679     priv->prepare_count--;
3680     g_rec_mutex_unlock (&priv->state_lock);
3681     GST_WARNING ("can not reuse media %p", media);
3682     return FALSE;
3683   }
3684 prepare_failed:
3685   {
3686     /* we are not going to use the giving thread, so stop it. */
3687     if (thread)
3688       gst_rtsp_thread_stop (thread);
3689     priv->prepare_count--;
3690     g_rec_mutex_unlock (&priv->state_lock);
3691     GST_ERROR ("failed to prepare media");
3692     return FALSE;
3693   }
3694 preroll_failed:
3695   {
3696     GST_WARNING ("failed to preroll pipeline");
3697     gst_rtsp_media_unprepare (media);
3698     return FALSE;
3699   }
3700 }
3701
3702 /* must be called with state-lock */
3703 static void
3704 finish_unprepare (GstRTSPMedia * media)
3705 {
3706   GstRTSPMediaPrivate *priv = media->priv;
3707   gint i;
3708   GList *walk;
3709
3710   if (priv->finishing_unprepare)
3711     return;
3712   priv->finishing_unprepare = TRUE;
3713
3714   GST_DEBUG ("shutting down");
3715
3716   /* release the lock on shutdown, otherwise pad_added_cb might try to
3717    * acquire the lock and then we deadlock */
3718   g_rec_mutex_unlock (&priv->state_lock);
3719   set_state (media, GST_STATE_NULL);
3720   g_rec_mutex_lock (&priv->state_lock);
3721
3722   media_streams_set_blocked (media, FALSE);
3723
3724   for (i = 0; i < priv->streams->len; i++) {
3725     GstRTSPStream *stream;
3726
3727     GST_INFO ("Removing elements of stream %d from pipeline", i);
3728
3729     stream = g_ptr_array_index (priv->streams, i);
3730
3731     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3732   }
3733
3734   /* remove the pad signal handlers */
3735   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3736     GstElement *elem = walk->data;
3737     DynPaySignalHandlers *handlers;
3738
3739     handlers =
3740         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3741     g_assert (handlers != NULL);
3742
3743     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3744     g_signal_handler_disconnect (G_OBJECT (elem),
3745         handlers->pad_removed_handler);
3746     g_signal_handler_disconnect (G_OBJECT (elem),
3747         handlers->no_more_pads_handler);
3748
3749     g_slice_free (DynPaySignalHandlers, handlers);
3750   }
3751
3752   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3753   priv->rtpbin = NULL;
3754
3755   if (priv->nettime)
3756     gst_object_unref (priv->nettime);
3757   priv->nettime = NULL;
3758
3759   priv->reused = TRUE;
3760   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3761
3762   /* when the media is not reusable, this will effectively unref the media and
3763    * recreate it */
3764   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3765
3766   /* the source has the last ref to the media */
3767   if (priv->source) {
3768     GST_DEBUG ("destroy source");
3769     g_source_destroy (priv->source);
3770     g_source_unref (priv->source);
3771   }
3772   if (priv->thread) {
3773     GST_DEBUG ("stop thread");
3774     gst_rtsp_thread_stop (priv->thread);
3775   }
3776
3777   priv->finishing_unprepare = FALSE;
3778 }
3779
3780 /* called with state-lock */
3781 static gboolean
3782 default_unprepare (GstRTSPMedia * media)
3783 {
3784   GstRTSPMediaPrivate *priv = media->priv;
3785
3786   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3787
3788   if (priv->eos_shutdown) {
3789     GST_DEBUG ("sending EOS for shutdown");
3790     /* ref so that we don't disappear */
3791     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
3792     /* we need to go to playing again for the EOS to propagate, normally in this
3793      * state, nothing is receiving data from us anymore so this is ok. */
3794     set_state (media, GST_STATE_PLAYING);
3795   } else {
3796     finish_unprepare (media);
3797   }
3798   return TRUE;
3799 }
3800
3801 /**
3802  * gst_rtsp_media_unprepare:
3803  * @media: a #GstRTSPMedia
3804  *
3805  * Unprepare @media. After this call, the media should be prepared again before
3806  * it can be used again. If the media is set to be non-reusable, a new instance
3807  * must be created.
3808  *
3809  * Returns: %TRUE on success.
3810  */
3811 gboolean
3812 gst_rtsp_media_unprepare (GstRTSPMedia * media)
3813 {
3814   GstRTSPMediaPrivate *priv;
3815   gboolean success;
3816
3817   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3818
3819   priv = media->priv;
3820
3821   g_rec_mutex_lock (&priv->state_lock);
3822   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
3823     goto was_unprepared;
3824
3825   priv->prepare_count--;
3826   if (priv->prepare_count > 0)
3827     goto is_busy;
3828
3829   GST_INFO ("unprepare media %p", media);
3830   set_target_state (media, GST_STATE_NULL, FALSE);
3831   success = TRUE;
3832
3833   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
3834     GstRTSPMediaClass *klass;
3835
3836     klass = GST_RTSP_MEDIA_GET_CLASS (media);
3837     if (klass->unprepare)
3838       success = klass->unprepare (media);
3839   } else {
3840     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3841     finish_unprepare (media);
3842   }
3843   g_rec_mutex_unlock (&priv->state_lock);
3844
3845   return success;
3846
3847 was_unprepared:
3848   {
3849     g_rec_mutex_unlock (&priv->state_lock);
3850     GST_INFO ("media %p was already unprepared", media);
3851     return TRUE;
3852   }
3853 is_busy:
3854   {
3855     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
3856     g_rec_mutex_unlock (&priv->state_lock);
3857     return TRUE;
3858   }
3859 }
3860
3861 /* should be called with state-lock */
3862 static GstClock *
3863 get_clock_unlocked (GstRTSPMedia * media)
3864 {
3865   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
3866     GST_DEBUG_OBJECT (media, "media was not prepared");
3867     return NULL;
3868   }
3869   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
3870 }
3871
3872 /**
3873  * gst_rtsp_media_get_clock:
3874  * @media: a #GstRTSPMedia
3875  *
3876  * Get the clock that is used by the pipeline in @media.
3877  *
3878  * @media must be prepared before this method returns a valid clock object.
3879  *
3880  * Returns: (transfer full) (nullable): the #GstClock used by @media. unref after usage.
3881  */
3882 GstClock *
3883 gst_rtsp_media_get_clock (GstRTSPMedia * media)
3884 {
3885   GstClock *clock;
3886   GstRTSPMediaPrivate *priv;
3887
3888   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3889
3890   priv = media->priv;
3891
3892   g_rec_mutex_lock (&priv->state_lock);
3893   clock = get_clock_unlocked (media);
3894   g_rec_mutex_unlock (&priv->state_lock);
3895
3896   return clock;
3897 }
3898
3899 /**
3900  * gst_rtsp_media_get_base_time:
3901  * @media: a #GstRTSPMedia
3902  *
3903  * Get the base_time that is used by the pipeline in @media.
3904  *
3905  * @media must be prepared before this method returns a valid base_time.
3906  *
3907  * Returns: the base_time used by @media.
3908  */
3909 GstClockTime
3910 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
3911 {
3912   GstClockTime result;
3913   GstRTSPMediaPrivate *priv;
3914
3915   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
3916
3917   priv = media->priv;
3918
3919   g_rec_mutex_lock (&priv->state_lock);
3920   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3921     goto not_prepared;
3922
3923   result = gst_element_get_base_time (media->priv->pipeline);
3924   g_rec_mutex_unlock (&priv->state_lock);
3925
3926   return result;
3927
3928   /* ERRORS */
3929 not_prepared:
3930   {
3931     g_rec_mutex_unlock (&priv->state_lock);
3932     GST_DEBUG_OBJECT (media, "media was not prepared");
3933     return GST_CLOCK_TIME_NONE;
3934   }
3935 }
3936
3937 /**
3938  * gst_rtsp_media_get_time_provider:
3939  * @media: a #GstRTSPMedia
3940  * @address: (allow-none): an address or %NULL
3941  * @port: a port or 0
3942  *
3943  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
3944  * will listen on @address and @port for client time requests.
3945  *
3946  * Returns: (transfer full): the #GstNetTimeProvider of @media.
3947  */
3948 GstNetTimeProvider *
3949 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
3950     guint16 port)
3951 {
3952   GstRTSPMediaPrivate *priv;
3953   GstNetTimeProvider *provider = NULL;
3954
3955   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3956
3957   priv = media->priv;
3958
3959   g_rec_mutex_lock (&priv->state_lock);
3960   if (priv->time_provider) {
3961     if ((provider = priv->nettime) == NULL) {
3962       GstClock *clock;
3963
3964       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
3965         provider = gst_net_time_provider_new (clock, address, port);
3966         gst_object_unref (clock);
3967
3968         priv->nettime = provider;
3969       }
3970     }
3971   }
3972   g_rec_mutex_unlock (&priv->state_lock);
3973
3974   if (provider)
3975     gst_object_ref (provider);
3976
3977   return provider;
3978 }
3979
3980 static gboolean
3981 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
3982 {
3983   return gst_rtsp_sdp_from_media (sdp, info, media);
3984 }
3985
3986 /**
3987  * gst_rtsp_media_setup_sdp:
3988  * @media: a #GstRTSPMedia
3989  * @sdp: (transfer none): a #GstSDPMessage
3990  * @info: (transfer none): a #GstSDPInfo
3991  *
3992  * Add @media specific info to @sdp. @info is used to configure the connection
3993  * information in the SDP.
3994  *
3995  * Returns: TRUE on success.
3996  */
3997 gboolean
3998 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
3999     GstSDPInfo * info)
4000 {
4001   GstRTSPMediaPrivate *priv;
4002   GstRTSPMediaClass *klass;
4003   gboolean res;
4004
4005   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4006   g_return_val_if_fail (sdp != NULL, FALSE);
4007   g_return_val_if_fail (info != NULL, FALSE);
4008
4009   priv = media->priv;
4010
4011   g_rec_mutex_lock (&priv->state_lock);
4012
4013   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4014
4015   if (!klass->setup_sdp)
4016     goto no_setup_sdp;
4017
4018   res = klass->setup_sdp (media, sdp, info);
4019
4020   g_rec_mutex_unlock (&priv->state_lock);
4021
4022   return res;
4023
4024   /* ERRORS */
4025 no_setup_sdp:
4026   {
4027     g_rec_mutex_unlock (&priv->state_lock);
4028     GST_ERROR ("no setup_sdp function");
4029     g_critical ("no setup_sdp vmethod function set");
4030     return FALSE;
4031   }
4032 }
4033
4034 static gboolean
4035 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4036 {
4037   GstRTSPMediaPrivate *priv = media->priv;
4038   gint i, medias_len;
4039
4040   medias_len = gst_sdp_message_medias_len (sdp);
4041   if (medias_len != priv->streams->len) {
4042     GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
4043         priv->streams->len, medias_len);
4044     return FALSE;
4045   }
4046
4047   for (i = 0; i < medias_len; i++) {
4048     const gchar *proto;
4049     const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
4050     GstRTSPStream *stream;
4051     gint j, formats_len;
4052     const gchar *control;
4053     GstRTSPProfile profile, profiles;
4054
4055     stream = g_ptr_array_index (priv->streams, i);
4056
4057     /* TODO: Should we do something with the other SDP information? */
4058
4059     /* get proto */
4060     proto = gst_sdp_media_get_proto (sdp_media);
4061     if (proto == NULL) {
4062       GST_ERROR ("%p: SDP media %d has no proto", media, i);
4063       return FALSE;
4064     }
4065
4066     if (g_str_equal (proto, "RTP/AVP")) {
4067       profile = GST_RTSP_PROFILE_AVP;
4068     } else if (g_str_equal (proto, "RTP/SAVP")) {
4069       profile = GST_RTSP_PROFILE_SAVP;
4070     } else if (g_str_equal (proto, "RTP/AVPF")) {
4071       profile = GST_RTSP_PROFILE_AVPF;
4072     } else if (g_str_equal (proto, "RTP/SAVPF")) {
4073       profile = GST_RTSP_PROFILE_SAVPF;
4074     } else {
4075       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4076       return FALSE;
4077     }
4078
4079     profiles = gst_rtsp_stream_get_profiles (stream);
4080     if ((profiles & profile) == 0) {
4081       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4082       return FALSE;
4083     }
4084
4085     formats_len = gst_sdp_media_formats_len (sdp_media);
4086     for (j = 0; j < formats_len; j++) {
4087       gint pt;
4088       GstCaps *caps;
4089       GstStructure *s;
4090
4091       pt = atoi (gst_sdp_media_get_format (sdp_media, j));
4092
4093       GST_DEBUG (" looking at %d pt: %d", j, pt);
4094
4095       /* convert caps */
4096       caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
4097       if (caps == NULL) {
4098         GST_WARNING (" skipping pt %d without caps", pt);
4099         continue;
4100       }
4101
4102       /* do some tweaks */
4103       GST_DEBUG ("mapping sdp session level attributes to caps");
4104       gst_sdp_message_attributes_to_caps (sdp, caps);
4105       GST_DEBUG ("mapping sdp media level attributes to caps");
4106       gst_sdp_media_attributes_to_caps (sdp_media, caps);
4107
4108       s = gst_caps_get_structure (caps, 0);
4109       gst_structure_set_name (s, "application/x-rtp");
4110
4111       if (!g_strcmp0 (gst_structure_get_string (s, "encoding-name"), "ULPFEC"))
4112         gst_structure_set (s, "is-fec", G_TYPE_BOOLEAN, TRUE, NULL);
4113
4114       gst_rtsp_stream_set_pt_map (stream, pt, caps);
4115       gst_caps_unref (caps);
4116     }
4117
4118     control = gst_sdp_media_get_attribute_val (sdp_media, "control");
4119     if (control)
4120       gst_rtsp_stream_set_control (stream, control);
4121
4122   }
4123
4124   return TRUE;
4125 }
4126
4127 /**
4128  * gst_rtsp_media_handle_sdp:
4129  * @media: a #GstRTSPMedia
4130  * @sdp: (transfer none): a #GstSDPMessage
4131  *
4132  * Configure an SDP on @media for receiving streams
4133  *
4134  * Returns: TRUE on success.
4135  */
4136 gboolean
4137 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4138 {
4139   GstRTSPMediaPrivate *priv;
4140   GstRTSPMediaClass *klass;
4141   gboolean res;
4142
4143   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4144   g_return_val_if_fail (sdp != NULL, FALSE);
4145
4146   priv = media->priv;
4147
4148   g_rec_mutex_lock (&priv->state_lock);
4149
4150   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4151
4152   if (!klass->handle_sdp)
4153     goto no_handle_sdp;
4154
4155   res = klass->handle_sdp (media, sdp);
4156
4157   g_rec_mutex_unlock (&priv->state_lock);
4158
4159   return res;
4160
4161   /* ERRORS */
4162 no_handle_sdp:
4163   {
4164     g_rec_mutex_unlock (&priv->state_lock);
4165     GST_ERROR ("no handle_sdp function");
4166     g_critical ("no handle_sdp vmethod function set");
4167     return FALSE;
4168   }
4169 }
4170
4171 static void
4172 do_set_seqnum (GstRTSPStream * stream)
4173 {
4174   guint16 seq_num;
4175
4176   if (gst_rtsp_stream_is_sender (stream)) {
4177     seq_num = gst_rtsp_stream_get_current_seqnum (stream);
4178     gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
4179   }
4180 }
4181
4182 /* call with state_lock */
4183 static gboolean
4184 default_suspend (GstRTSPMedia * media)
4185 {
4186   GstRTSPMediaPrivate *priv = media->priv;
4187   GstStateChangeReturn ret;
4188
4189   switch (priv->suspend_mode) {
4190     case GST_RTSP_SUSPEND_MODE_NONE:
4191       GST_DEBUG ("media %p no suspend", media);
4192       break;
4193     case GST_RTSP_SUSPEND_MODE_PAUSE:
4194       GST_DEBUG ("media %p suspend to PAUSED", media);
4195       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
4196       if (ret == GST_STATE_CHANGE_FAILURE)
4197         goto state_failed;
4198       break;
4199     case GST_RTSP_SUSPEND_MODE_RESET:
4200       GST_DEBUG ("media %p suspend to NULL", media);
4201       ret = set_target_state (media, GST_STATE_NULL, TRUE);
4202       if (ret == GST_STATE_CHANGE_FAILURE)
4203         goto state_failed;
4204       /* Because payloader needs to set the sequence number as
4205        * monotonic, we need to preserve the sequence number
4206        * after pause. (otherwise going from pause to play,  which
4207        * is actually from NULL to PLAY will create a new sequence
4208        * number. */
4209       g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
4210       break;
4211     default:
4212       break;
4213   }
4214
4215   return TRUE;
4216
4217   /* ERRORS */
4218 state_failed:
4219   {
4220     GST_WARNING ("failed changing pipeline's state for media %p", media);
4221     return FALSE;
4222   }
4223 }
4224
4225 /**
4226  * gst_rtsp_media_suspend:
4227  * @media: a #GstRTSPMedia
4228  *
4229  * Suspend @media. The state of the pipeline managed by @media is set to
4230  * GST_STATE_NULL but all streams are kept. @media can be prepared again
4231  * with gst_rtsp_media_unsuspend()
4232  *
4233  * @media must be prepared with gst_rtsp_media_prepare();
4234  *
4235  * Returns: %TRUE on success.
4236  */
4237 gboolean
4238 gst_rtsp_media_suspend (GstRTSPMedia * media)
4239 {
4240   GstRTSPMediaPrivate *priv = media->priv;
4241   GstRTSPMediaClass *klass;
4242
4243   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4244
4245   GST_FIXME ("suspend for dynamic pipelines needs fixing");
4246
4247   g_rec_mutex_lock (&priv->state_lock);
4248   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4249     goto not_prepared;
4250
4251   /* don't attempt to suspend when something is busy */
4252   if (priv->n_active > 0)
4253     goto done;
4254
4255   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4256   if (klass->suspend) {
4257     if (!klass->suspend (media))
4258       goto suspend_failed;
4259   }
4260
4261   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
4262 done:
4263   g_rec_mutex_unlock (&priv->state_lock);
4264
4265   return TRUE;
4266
4267   /* ERRORS */
4268 not_prepared:
4269   {
4270     g_rec_mutex_unlock (&priv->state_lock);
4271     GST_WARNING ("media %p was not prepared", media);
4272     return FALSE;
4273   }
4274 suspend_failed:
4275   {
4276     g_rec_mutex_unlock (&priv->state_lock);
4277     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4278     GST_WARNING ("failed to suspend media %p", media);
4279     return FALSE;
4280   }
4281 }
4282
4283 /* call with state_lock */
4284 static gboolean
4285 default_unsuspend (GstRTSPMedia * media)
4286 {
4287   GstRTSPMediaPrivate *priv = media->priv;
4288   gboolean preroll_ok;
4289
4290   switch (priv->suspend_mode) {
4291     case GST_RTSP_SUSPEND_MODE_NONE:
4292       if (gst_rtsp_media_is_receive_only (media))
4293         break;
4294       if (media_streams_blocking (media)) {
4295         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4296         /* at this point the media pipeline has been updated and contain all
4297          * specific transport parts: all active streams contain at least one sink
4298          * element and it's safe to unblock any blocked streams that are active */
4299         media_unblock_linked (media);
4300       } else {
4301         /* streams are not blocked and media is suspended from PAUSED */
4302         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4303       }
4304       g_rec_mutex_unlock (&priv->state_lock);
4305       if (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_ERROR) {
4306         g_rec_mutex_lock (&priv->state_lock);
4307         goto preroll_failed;
4308       }
4309       g_rec_mutex_lock (&priv->state_lock);
4310       break;
4311     case GST_RTSP_SUSPEND_MODE_PAUSE:
4312       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4313       break;
4314     case GST_RTSP_SUSPEND_MODE_RESET:
4315     {
4316       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4317       /* at this point the media pipeline has been updated and contain all
4318        * specific transport parts: all active streams contain at least one sink
4319        * element and it's safe to unblock any blocked streams that are active */
4320       media_unblock_linked (media);
4321       if (!start_preroll (media))
4322         goto start_failed;
4323
4324       g_rec_mutex_unlock (&priv->state_lock);
4325       preroll_ok = wait_preroll (media);
4326       g_rec_mutex_lock (&priv->state_lock);
4327
4328       if (!preroll_ok)
4329         goto preroll_failed;
4330     }
4331     default:
4332       break;
4333   }
4334
4335   return TRUE;
4336
4337   /* ERRORS */
4338 start_failed:
4339   {
4340     GST_WARNING ("failed to preroll pipeline");
4341     return FALSE;
4342   }
4343 preroll_failed:
4344   {
4345     GST_WARNING ("failed to preroll pipeline");
4346     return FALSE;
4347   }
4348 }
4349
4350 /**
4351  * gst_rtsp_media_unsuspend:
4352  * @media: a #GstRTSPMedia
4353  *
4354  * Unsuspend @media if it was in a suspended state. This method does nothing
4355  * when the media was not in the suspended state.
4356  *
4357  * Returns: %TRUE on success.
4358  */
4359 gboolean
4360 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
4361 {
4362   GstRTSPMediaPrivate *priv = media->priv;
4363   GstRTSPMediaClass *klass;
4364
4365   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4366
4367   g_rec_mutex_lock (&priv->state_lock);
4368   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4369     goto done;
4370
4371   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4372   if (klass->unsuspend) {
4373     if (!klass->unsuspend (media))
4374       goto unsuspend_failed;
4375   }
4376
4377 done:
4378   g_rec_mutex_unlock (&priv->state_lock);
4379
4380   return TRUE;
4381
4382   /* ERRORS */
4383 unsuspend_failed:
4384   {
4385     g_rec_mutex_unlock (&priv->state_lock);
4386     GST_WARNING ("failed to unsuspend media %p", media);
4387     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4388     return FALSE;
4389   }
4390 }
4391
4392 /* must be called with state-lock */
4393 static void
4394 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
4395 {
4396   GstRTSPMediaPrivate *priv = media->priv;
4397
4398   if (state == GST_STATE_NULL) {
4399     gst_rtsp_media_unprepare (media);
4400   } else {
4401     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
4402     set_target_state (media, state, FALSE);
4403     /* when we are buffering, don't update the state yet, this will be done
4404      * when buffering finishes */
4405     if (priv->buffering) {
4406       GST_INFO ("Buffering busy, delay state change");
4407     } else {
4408       if (state == GST_STATE_PLAYING)
4409         /* make sure pads are not blocking anymore when going to PLAYING */
4410         media_unblock_linked (media);
4411
4412       set_state (media, state);
4413
4414       /* and suspend after pause */
4415       if (state == GST_STATE_PAUSED)
4416         gst_rtsp_media_suspend (media);
4417     }
4418   }
4419 }
4420
4421 /**
4422  * gst_rtsp_media_set_pipeline_state:
4423  * @media: a #GstRTSPMedia
4424  * @state: the target state of the pipeline
4425  *
4426  * Set the state of the pipeline managed by @media to @state
4427  */
4428 void
4429 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
4430 {
4431   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4432
4433   g_rec_mutex_lock (&media->priv->state_lock);
4434   media_set_pipeline_state_locked (media, state);
4435   g_rec_mutex_unlock (&media->priv->state_lock);
4436 }
4437
4438 /**
4439  * gst_rtsp_media_set_state:
4440  * @media: a #GstRTSPMedia
4441  * @state: the target state of the media
4442  * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
4443  * a #GPtrArray of #GstRTSPStreamTransport pointers
4444  *
4445  * Set the state of @media to @state and for the transports in @transports.
4446  *
4447  * @media must be prepared with gst_rtsp_media_prepare();
4448  *
4449  * Returns: %TRUE on success.
4450  */
4451 gboolean
4452 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
4453     GPtrArray * transports)
4454 {
4455   GstRTSPMediaPrivate *priv;
4456   gint i;
4457   gboolean activate, deactivate, do_state;
4458   gint old_active;
4459
4460   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4461   g_return_val_if_fail (transports != NULL, FALSE);
4462
4463   priv = media->priv;
4464
4465   g_rec_mutex_lock (&priv->state_lock);
4466
4467   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING
4468       && gst_rtsp_media_is_shared (media)) {
4469     g_rec_mutex_unlock (&priv->state_lock);
4470     gst_rtsp_media_get_status (media);
4471     g_rec_mutex_lock (&priv->state_lock);
4472   }
4473   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
4474     goto error_status;
4475   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
4476       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4477     goto not_prepared;
4478
4479   /* NULL and READY are the same */
4480   if (state == GST_STATE_READY)
4481     state = GST_STATE_NULL;
4482
4483   activate = deactivate = FALSE;
4484
4485   GST_INFO ("going to state %s media %p, target state %s",
4486       gst_element_state_get_name (state), media,
4487       gst_element_state_get_name (priv->target_state));
4488
4489   switch (state) {
4490     case GST_STATE_NULL:
4491       /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
4492       if (priv->target_state >= GST_STATE_PAUSED)
4493         deactivate = TRUE;
4494       break;
4495     case GST_STATE_PAUSED:
4496       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
4497       if (priv->target_state == GST_STATE_PLAYING)
4498         deactivate = TRUE;
4499       break;
4500     case GST_STATE_PLAYING:
4501       /* we're going to PLAYING, activate */
4502       activate = TRUE;
4503       break;
4504     default:
4505       break;
4506   }
4507   old_active = priv->n_active;
4508
4509   GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
4510       activate, deactivate);
4511   for (i = 0; i < transports->len; i++) {
4512     GstRTSPStreamTransport *trans;
4513
4514     /* we need a non-NULL entry in the array */
4515     trans = g_ptr_array_index (transports, i);
4516     if (trans == NULL)
4517       continue;
4518
4519     if (activate) {
4520       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
4521         priv->n_active++;
4522     } else if (deactivate) {
4523       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
4524         priv->n_active--;
4525     }
4526   }
4527
4528   /* we just activated the first media, do the playing state change */
4529   if (old_active == 0 && activate)
4530     do_state = TRUE;
4531   /* if we have no more active media and prepare count is not indicate 
4532    * that there are new session/sessions ongoing,
4533    * do the downward state changes */
4534   else if (priv->n_active == 0 && priv->prepare_count <= 1)
4535     do_state = TRUE;
4536   else
4537     do_state = FALSE;
4538
4539   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
4540       media, do_state);
4541
4542   if (priv->target_state != state) {
4543     if (do_state) {
4544       media_set_pipeline_state_locked (media, state);
4545       g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
4546           NULL);
4547     }
4548   }
4549
4550   /* remember where we are */
4551   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
4552           old_active != priv->n_active))
4553     collect_media_stats (media);
4554
4555   g_rec_mutex_unlock (&priv->state_lock);
4556
4557   return TRUE;
4558
4559   /* ERRORS */
4560 not_prepared:
4561   {
4562     GST_WARNING ("media %p was not prepared", media);
4563     g_rec_mutex_unlock (&priv->state_lock);
4564     return FALSE;
4565   }
4566 error_status:
4567   {
4568     GST_WARNING ("media %p in error status while changing to state %d",
4569         media, state);
4570     if (state == GST_STATE_NULL) {
4571       for (i = 0; i < transports->len; i++) {
4572         GstRTSPStreamTransport *trans;
4573
4574         /* we need a non-NULL entry in the array */
4575         trans = g_ptr_array_index (transports, i);
4576         if (trans == NULL)
4577           continue;
4578
4579         gst_rtsp_stream_transport_set_active (trans, FALSE);
4580       }
4581       priv->n_active = 0;
4582     }
4583     g_rec_mutex_unlock (&priv->state_lock);
4584     return FALSE;
4585   }
4586 }
4587
4588 /**
4589  * gst_rtsp_media_set_transport_mode:
4590  * @media: a #GstRTSPMedia
4591  * @mode: the new value
4592  *
4593  * Sets if the media pipeline can work in PLAY or RECORD mode
4594  */
4595 void
4596 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
4597     GstRTSPTransportMode mode)
4598 {
4599   GstRTSPMediaPrivate *priv;
4600
4601   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4602
4603   priv = media->priv;
4604
4605   g_mutex_lock (&priv->lock);
4606   priv->transport_mode = mode;
4607   g_mutex_unlock (&priv->lock);
4608 }
4609
4610 /**
4611  * gst_rtsp_media_get_transport_mode:
4612  * @media: a #GstRTSPMedia
4613  *
4614  * Check if the pipeline for @media can be used for PLAY or RECORD methods.
4615  *
4616  * Returns: The transport mode.
4617  */
4618 GstRTSPTransportMode
4619 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
4620 {
4621   GstRTSPMediaPrivate *priv;
4622   GstRTSPTransportMode res;
4623
4624   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4625
4626   priv = media->priv;
4627
4628   g_mutex_lock (&priv->lock);
4629   res = priv->transport_mode;
4630   g_mutex_unlock (&priv->lock);
4631
4632   return res;
4633 }
4634
4635 /**
4636  * gst_rtsp_media_seekable:
4637  * @media: a #GstRTSPMedia
4638  *
4639  * Check if the pipeline for @media seek and up to what point in time,
4640  * it can seek.
4641  *
4642  * Returns: -1 if the stream is not seekable, 0 if seekable only to the beginning
4643  * and > 0 to indicate the longest duration between any two random access points.
4644  * %G_MAXINT64 means any value is possible.
4645  *
4646  * Since: 1.14
4647  */
4648 GstClockTimeDiff
4649 gst_rtsp_media_seekable (GstRTSPMedia * media)
4650 {
4651   GstRTSPMediaPrivate *priv;
4652   GstClockTimeDiff res;
4653
4654   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4655
4656   priv = media->priv;
4657
4658   /* Currently we are not able to seek on live streams,
4659    * and no stream is seekable only to the beginning */
4660   g_mutex_lock (&priv->lock);
4661   res = priv->seekable;
4662   g_mutex_unlock (&priv->lock);
4663
4664   return res;
4665 }
4666
4667 /**
4668  * gst_rtsp_media_complete_pipeline:
4669  * @media: a #GstRTSPMedia
4670  * @transports: (element-type GstRTSPTransport): a list of #GstRTSPTransport
4671  *
4672  * Add a receiver and sender parts to the pipeline based on the transport from
4673  * SETUP.
4674  *
4675  * Returns: %TRUE if the media pipeline has been sucessfully updated.
4676  *
4677  * Since: 1.14
4678  */
4679 gboolean
4680 gst_rtsp_media_complete_pipeline (GstRTSPMedia * media, GPtrArray * transports)
4681 {
4682   GstRTSPMediaPrivate *priv;
4683   guint i;
4684
4685   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4686   g_return_val_if_fail (transports, FALSE);
4687
4688   GST_DEBUG_OBJECT (media, "complete pipeline");
4689
4690   priv = media->priv;
4691
4692   g_mutex_lock (&priv->lock);
4693   for (i = 0; i < priv->streams->len; i++) {
4694     GstRTSPStreamTransport *transport;
4695     GstRTSPStream *stream;
4696     const GstRTSPTransport *rtsp_transport;
4697
4698     transport = g_ptr_array_index (transports, i);
4699     if (!transport)
4700       continue;
4701
4702     stream = gst_rtsp_stream_transport_get_stream (transport);
4703     if (!stream)
4704       continue;
4705
4706     rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
4707
4708     if (!gst_rtsp_stream_complete_stream (stream, rtsp_transport)) {
4709       g_mutex_unlock (&priv->lock);
4710       return FALSE;
4711     }
4712   }
4713
4714   priv->complete = TRUE;
4715   g_mutex_unlock (&priv->lock);
4716
4717   return TRUE;
4718 }
4719
4720 /**
4721  * gst_rtsp_media_is_receive_only:
4722  *
4723  * Returns: %TRUE if @media is receive-only, %FALSE otherwise.
4724  * Since: 1.18
4725  */
4726 gboolean
4727 gst_rtsp_media_is_receive_only (GstRTSPMedia * media)
4728 {
4729   GstRTSPMediaPrivate *priv = media->priv;
4730   gboolean receive_only = TRUE;
4731   guint i;
4732
4733   for (i = 0; i < priv->streams->len; i++) {
4734     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
4735     if (gst_rtsp_stream_is_sender (stream) ||
4736         !gst_rtsp_stream_is_receiver (stream)) {
4737       receive_only = FALSE;
4738       break;
4739     }
4740   }
4741
4742   return receive_only;
4743 }
4744
4745 /**
4746  * gst_rtsp_media_set_rate_control:
4747  *
4748  * Define whether @media will follow the Rate-Control=no behaviour as specified
4749  * in the ONVIF replay spec.
4750  *
4751  * Since: 1.18
4752  */
4753 void
4754 gst_rtsp_media_set_rate_control (GstRTSPMedia * media, gboolean enabled)
4755 {
4756   GstRTSPMediaPrivate *priv;
4757   guint i;
4758
4759   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4760
4761   GST_LOG_OBJECT (media, "%s rate control", enabled ? "Enabling" : "Disabling");
4762
4763   priv = media->priv;
4764
4765   g_mutex_lock (&priv->lock);
4766   priv->do_rate_control = enabled;
4767   for (i = 0; i < priv->streams->len; i++) {
4768     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
4769
4770     gst_rtsp_stream_set_rate_control (stream, enabled);
4771
4772   }
4773   g_mutex_unlock (&priv->lock);
4774 }
4775
4776 /**
4777  * gst_rtsp_media_get_rate_control:
4778  *
4779  * Returns: whether @media will follow the Rate-Control=no behaviour as specified
4780  * in the ONVIF replay spec.
4781  *
4782  * Since: 1.18
4783  */
4784 gboolean
4785 gst_rtsp_media_get_rate_control (GstRTSPMedia * media)
4786 {
4787   GstRTSPMediaPrivate *priv;
4788   gboolean res;
4789
4790   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4791
4792   priv = media->priv;
4793
4794   g_mutex_lock (&priv->lock);
4795   res = priv->do_rate_control;
4796   g_mutex_unlock (&priv->lock);
4797
4798   return res;
4799 }