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