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