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