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