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