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