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