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