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