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