media-factory: allow all protocols
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:rtsp-media
21  * @short_description: The media pipeline
22  * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession,
23  *     #GstRTSPSessionMedia
24  *
25  * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the
26  * streaming to the clients. The actual data transfer is done by the
27  * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia.
28  *
29  * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the
30  * client does a DESCRIBE or SETUP of a resource.
31  *
32  * A media is created with gst_rtsp_media_new() that takes the element that will
33  * provide the streaming elements. For each of the streams, a new #GstRTSPStream
34  * object needs to be made with the gst_rtsp_media_create_stream() which takes
35  * the payloader element and the source pad that produces the RTP stream.
36  *
37  * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The
38  * prepare method will add rtpbin and sinks and sources to send and receive RTP
39  * and RTCP packets from the clients. Each stream srcpad is connected to an
40  * input into the internal rtpbin.
41  *
42  * It is also possible to dynamically create #GstRTSPStream objects during the
43  * prepare phase. With gst_rtsp_media_get_status() you can check the status of
44  * the prepare phase.
45  *
46  * After the media is prepared, it is ready for streaming. It will usually be
47  * managed in a session with gst_rtsp_session_manage_media(). See
48  * #GstRTSPSession and #GstRTSPSessionMedia.
49  *
50  * The state of the media can be controlled with gst_rtsp_media_set_state ().
51  * Seeking can be done with gst_rtsp_media_seek().
52  *
53  * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
54  * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
55  * cleanly shut down.
56  *
57  * With gst_rtsp_media_set_shared(), the media can be shared between multiple
58  * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
59  * can be prepared again after an unprepare.
60  *
61  * Last reviewed on 2013-07-11 (1.0.0)
62  */
63
64 #include <string.h>
65 #include <stdlib.h>
66
67 #include <gst/app/gstappsrc.h>
68 #include <gst/app/gstappsink.h>
69
70 #include "rtsp-media.h"
71
72 #define GST_RTSP_MEDIA_GET_PRIVATE(obj)  \
73      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
74
75 struct _GstRTSPMediaPrivate
76 {
77   GMutex lock;
78   GCond cond;
79
80   /* protected by lock */
81   GstRTSPPermissions *permissions;
82   gboolean shared;
83   gboolean reusable;
84   GstRTSPLowerTrans protocols;
85   gboolean reused;
86   gboolean eos_shutdown;
87   guint buffer_size;
88   GstRTSPAddressPool *pool;
89
90   GstElement *element;
91   GRecMutex state_lock;         /* locking order: state lock, lock */
92   GPtrArray *streams;           /* protected by lock */
93   GList *dynamic;               /* protected by lock */
94   GstRTSPMediaStatus status;    /* protected by lock */
95   gint prepare_count;
96   gint n_active;
97   gboolean adding;
98
99   /* the pipeline for the media */
100   GstElement *pipeline;
101   GstElement *fakesink;         /* protected by lock */
102   GSource *source;
103   guint id;
104   GstRTSPThread *thread;
105
106   gboolean time_provider;
107   GstNetTimeProvider *nettime;
108
109   gboolean is_live;
110   gboolean seekable;
111   gboolean buffering;
112   GstState target_state;
113
114   /* RTP session manager */
115   GstElement *rtpbin;
116
117   /* the range of media */
118   GstRTSPTimeRange range;       /* protected by lock */
119   GstClockTime range_start;
120   GstClockTime range_stop;
121 };
122
123 #define DEFAULT_SHARED          FALSE
124 #define DEFAULT_REUSABLE        FALSE
125 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
126                                         GST_RTSP_LOWER_TRANS_TCP
127 #define DEFAULT_EOS_SHUTDOWN    FALSE
128 #define DEFAULT_BUFFER_SIZE     0x80000
129 #define DEFAULT_TIME_PROVIDER   FALSE
130
131 /* define to dump received RTCP packets */
132 #undef DUMP_STATS
133
134 enum
135 {
136   PROP_0,
137   PROP_SHARED,
138   PROP_REUSABLE,
139   PROP_PROTOCOLS,
140   PROP_EOS_SHUTDOWN,
141   PROP_BUFFER_SIZE,
142   PROP_ELEMENT,
143   PROP_TIME_PROVIDER,
144   PROP_LAST
145 };
146
147 enum
148 {
149   SIGNAL_NEW_STREAM,
150   SIGNAL_REMOVED_STREAM,
151   SIGNAL_PREPARED,
152   SIGNAL_UNPREPARED,
153   SIGNAL_NEW_STATE,
154   SIGNAL_LAST
155 };
156
157 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
158 #define GST_CAT_DEFAULT rtsp_media_debug
159
160 static void gst_rtsp_media_get_property (GObject * object, guint propid,
161     GValue * value, GParamSpec * pspec);
162 static void gst_rtsp_media_set_property (GObject * object, guint propid,
163     const GValue * value, GParamSpec * pspec);
164 static void gst_rtsp_media_finalize (GObject * obj);
165
166 static gboolean default_handle_message (GstRTSPMedia * media,
167     GstMessage * message);
168 static void finish_unprepare (GstRTSPMedia * media);
169 static gboolean default_unprepare (GstRTSPMedia * media);
170 static gboolean
171 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
172     GstRTSPRangeUnit unit);
173 static gboolean default_query_position (GstRTSPMedia * media,
174     gint64 * position);
175 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
176
177 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
178
179 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
180
181 static void
182 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
183 {
184   GObjectClass *gobject_class;
185
186   g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
187
188   gobject_class = G_OBJECT_CLASS (klass);
189
190   gobject_class->get_property = gst_rtsp_media_get_property;
191   gobject_class->set_property = gst_rtsp_media_set_property;
192   gobject_class->finalize = gst_rtsp_media_finalize;
193
194   g_object_class_install_property (gobject_class, PROP_SHARED,
195       g_param_spec_boolean ("shared", "Shared",
196           "If this media pipeline can be shared", DEFAULT_SHARED,
197           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198
199   g_object_class_install_property (gobject_class, PROP_REUSABLE,
200       g_param_spec_boolean ("reusable", "Reusable",
201           "If this media pipeline can be reused after an unprepare",
202           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
203
204   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
205       g_param_spec_flags ("protocols", "Protocols",
206           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
207           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
208
209   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
210       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
211           "Send an EOS event to the pipeline before unpreparing",
212           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213
214   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
215       g_param_spec_uint ("buffer-size", "Buffer Size",
216           "The kernel UDP buffer size to use", 0, G_MAXUINT,
217           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218
219   g_object_class_install_property (gobject_class, PROP_ELEMENT,
220       g_param_spec_object ("element", "The Element",
221           "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
222           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
223
224   g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
225       g_param_spec_boolean ("time-provider", "Time Provider",
226           "Use a NetTimeProvider for clients",
227           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
228
229   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
230       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
231       G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
232       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
233
234   gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
235       g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
236       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
237       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
238       GST_TYPE_RTSP_STREAM);
239
240   gst_rtsp_media_signals[SIGNAL_PREPARED] =
241       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
242       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
243       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
244
245   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
246       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
247       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
248       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
249
250   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
251       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
252       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
253       g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
254
255   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
256
257   klass->handle_message = default_handle_message;
258   klass->unprepare = default_unprepare;
259   klass->convert_range = default_convert_range;
260   klass->query_position = default_query_position;
261   klass->query_stop = default_query_stop;
262 }
263
264 static void
265 gst_rtsp_media_init (GstRTSPMedia * media)
266 {
267   GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
268
269   media->priv = priv;
270
271   priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
272   g_mutex_init (&priv->lock);
273   g_cond_init (&priv->cond);
274   g_rec_mutex_init (&priv->state_lock);
275
276   priv->shared = DEFAULT_SHARED;
277   priv->reusable = DEFAULT_REUSABLE;
278   priv->protocols = DEFAULT_PROTOCOLS;
279   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
280   priv->buffer_size = DEFAULT_BUFFER_SIZE;
281   priv->time_provider = DEFAULT_TIME_PROVIDER;
282 }
283
284 static void
285 gst_rtsp_media_finalize (GObject * obj)
286 {
287   GstRTSPMediaPrivate *priv;
288   GstRTSPMedia *media;
289
290   media = GST_RTSP_MEDIA (obj);
291   priv = media->priv;
292
293   GST_INFO ("finalize media %p", media);
294
295   g_ptr_array_unref (priv->streams);
296
297   g_list_free_full (priv->dynamic, gst_object_unref);
298
299   if (priv->pipeline)
300     gst_object_unref (priv->pipeline);
301   if (priv->nettime)
302     gst_object_unref (priv->nettime);
303   gst_object_unref (priv->element);
304   if (priv->pool)
305     g_object_unref (priv->pool);
306   g_mutex_clear (&priv->lock);
307   g_cond_clear (&priv->cond);
308   g_rec_mutex_clear (&priv->state_lock);
309
310   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
311 }
312
313 static void
314 gst_rtsp_media_get_property (GObject * object, guint propid,
315     GValue * value, GParamSpec * pspec)
316 {
317   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
318
319   switch (propid) {
320     case PROP_ELEMENT:
321       g_value_set_object (value, media->priv->element);
322       break;
323     case PROP_SHARED:
324       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
325       break;
326     case PROP_REUSABLE:
327       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
328       break;
329     case PROP_PROTOCOLS:
330       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
331       break;
332     case PROP_EOS_SHUTDOWN:
333       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
334       break;
335     case PROP_BUFFER_SIZE:
336       g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
337       break;
338     case PROP_TIME_PROVIDER:
339       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
340       break;
341     default:
342       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
343   }
344 }
345
346 static void
347 gst_rtsp_media_set_property (GObject * object, guint propid,
348     const GValue * value, GParamSpec * pspec)
349 {
350   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
351
352   switch (propid) {
353     case PROP_ELEMENT:
354       media->priv->element = g_value_get_object (value);
355       gst_object_ref_sink (media->priv->element);
356       break;
357     case PROP_SHARED:
358       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
359       break;
360     case PROP_REUSABLE:
361       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
362       break;
363     case PROP_PROTOCOLS:
364       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
365       break;
366     case PROP_EOS_SHUTDOWN:
367       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
368       break;
369     case PROP_BUFFER_SIZE:
370       gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
371       break;
372     case PROP_TIME_PROVIDER:
373       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
374       break;
375     default:
376       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
377   }
378 }
379
380 /* must be called with state lock */
381 static void
382 collect_media_stats (GstRTSPMedia * media)
383 {
384   GstRTSPMediaPrivate *priv = media->priv;
385   gint64 position, stop;
386
387   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
388       priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
389     return;
390
391   priv->range.unit = GST_RTSP_RANGE_NPT;
392
393   GST_INFO ("collect media stats");
394
395   if (priv->is_live) {
396     priv->range.min.type = GST_RTSP_TIME_NOW;
397     priv->range.min.seconds = -1;
398     priv->range_start = -1;
399     priv->range.max.type = GST_RTSP_TIME_END;
400     priv->range.max.seconds = -1;
401     priv->range_stop = -1;
402   } else {
403     GstRTSPMediaClass *klass;
404     gboolean ret;
405
406     klass = GST_RTSP_MEDIA_GET_CLASS (media);
407
408     /* get the position */
409     ret = FALSE;
410     if (klass->query_position)
411       ret = klass->query_position (media, &position);
412
413     if (!ret) {
414       GST_INFO ("position query failed");
415       position = 0;
416     }
417
418     /* get the current segment stop */
419     ret = FALSE;
420     if (klass->query_stop)
421       ret = klass->query_stop (media, &stop);
422
423     if (!ret) {
424       GST_INFO ("stop query failed");
425       stop = -1;
426     }
427
428     GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
429         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
430
431     if (position == -1) {
432       priv->range.min.type = GST_RTSP_TIME_NOW;
433       priv->range.min.seconds = -1;
434       priv->range_start = -1;
435     } else {
436       priv->range.min.type = GST_RTSP_TIME_SECONDS;
437       priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
438       priv->range_start = position;
439     }
440     if (stop == -1) {
441       priv->range.max.type = GST_RTSP_TIME_END;
442       priv->range.max.seconds = -1;
443       priv->range_stop = -1;
444     } else {
445       priv->range.max.type = GST_RTSP_TIME_SECONDS;
446       priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
447       priv->range_stop = stop;
448     }
449   }
450 }
451
452 /**
453  * gst_rtsp_media_new:
454  * @element: (transfer full): a #GstElement
455  *
456  * Create a new #GstRTSPMedia instance. @element is the bin element that
457  * provides the different streams. The #GstRTSPMedia object contains the
458  * element to produce RTP data for one or more related (audio/video/..)
459  * streams.
460  *
461  * Ownership is taken of @element.
462  *
463  * Returns: a new #GstRTSPMedia object.
464  */
465 GstRTSPMedia *
466 gst_rtsp_media_new (GstElement * element)
467 {
468   GstRTSPMedia *result;
469
470   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
471
472   result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
473
474   return result;
475 }
476
477 /**
478  * gst_rtsp_media_get_element:
479  * @media: a #GstRTSPMedia
480  *
481  * Get the element that was used when constructing @media.
482  *
483  * Returns: a #GstElement. Unref after usage.
484  */
485 GstElement *
486 gst_rtsp_media_get_element (GstRTSPMedia * media)
487 {
488   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
489
490   return gst_object_ref (media->priv->element);
491 }
492
493 /**
494  * gst_rtsp_media_take_pipeline:
495  * @media: a #GstRTSPMedia
496  * @pipeline: (transfer full): a #GstPipeline
497  *
498  * Set @pipeline as the #GstPipeline for @media. Ownership is
499  * taken of @pipeline.
500  */
501 void
502 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
503 {
504   GstRTSPMediaPrivate *priv;
505   GstElement *old;
506   GstNetTimeProvider *nettime;
507
508   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
509   g_return_if_fail (GST_IS_PIPELINE (pipeline));
510
511   priv = media->priv;
512
513   g_mutex_lock (&priv->lock);
514   old = priv->pipeline;
515   priv->pipeline = GST_ELEMENT_CAST (pipeline);
516   nettime = priv->nettime;
517   priv->nettime = NULL;
518   g_mutex_unlock (&priv->lock);
519
520   if (old)
521     gst_object_unref (old);
522
523   if (nettime)
524     gst_object_unref (nettime);
525
526   gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
527 }
528
529 /**
530  * gst_rtsp_media_set_permissions:
531  * @media: a #GstRTSPMedia
532  * @permissions: a #GstRTSPPermissions
533  *
534  * Set @permissions on @media.
535  */
536 void
537 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
538     GstRTSPPermissions * permissions)
539 {
540   GstRTSPMediaPrivate *priv;
541
542   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
543
544   priv = media->priv;
545
546   g_mutex_lock (&priv->lock);
547   if (priv->permissions)
548     gst_rtsp_permissions_unref (priv->permissions);
549   if ((priv->permissions = permissions))
550     gst_rtsp_permissions_ref (permissions);
551   g_mutex_unlock (&priv->lock);
552 }
553
554 /**
555  * gst_rtsp_media_get_permissions:
556  * @media: a #GstRTSPMedia
557  *
558  * Get the permissions object from @media.
559  *
560  * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage.
561  */
562 GstRTSPPermissions *
563 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
564 {
565   GstRTSPMediaPrivate *priv;
566   GstRTSPPermissions *result;
567
568   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
569
570   priv = media->priv;
571
572   g_mutex_lock (&priv->lock);
573   if ((result = priv->permissions))
574     gst_rtsp_permissions_ref (result);
575   g_mutex_unlock (&priv->lock);
576
577   return result;
578 }
579
580 /**
581  * gst_rtsp_media_set_shared:
582  * @media: a #GstRTSPMedia
583  * @shared: the new value
584  *
585  * Set or unset if the pipeline for @media can be shared will multiple clients.
586  * When @shared is %TRUE, client requests for this media will share the media
587  * pipeline.
588  */
589 void
590 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
591 {
592   GstRTSPMediaPrivate *priv;
593
594   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
595
596   priv = media->priv;
597
598   g_mutex_lock (&priv->lock);
599   priv->shared = shared;
600   g_mutex_unlock (&priv->lock);
601 }
602
603 /**
604  * gst_rtsp_media_is_shared:
605  * @media: a #GstRTSPMedia
606  *
607  * Check if the pipeline for @media can be shared between multiple clients.
608  *
609  * Returns: %TRUE if the media can be shared between clients.
610  */
611 gboolean
612 gst_rtsp_media_is_shared (GstRTSPMedia * media)
613 {
614   GstRTSPMediaPrivate *priv;
615   gboolean res;
616
617   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
618
619   priv = media->priv;
620
621   g_mutex_lock (&priv->lock);
622   res = priv->shared;
623   g_mutex_unlock (&priv->lock);
624
625   return res;
626 }
627
628 /**
629  * gst_rtsp_media_set_reusable:
630  * @media: a #GstRTSPMedia
631  * @reusable: the new value
632  *
633  * Set or unset if the pipeline for @media can be reused after the pipeline has
634  * been unprepared.
635  */
636 void
637 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
638 {
639   GstRTSPMediaPrivate *priv;
640
641   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
642
643   priv = media->priv;
644
645   g_mutex_lock (&priv->lock);
646   priv->reusable = reusable;
647   g_mutex_unlock (&priv->lock);
648 }
649
650 /**
651  * gst_rtsp_media_is_reusable:
652  * @media: a #GstRTSPMedia
653  *
654  * Check if the pipeline for @media can be reused after an unprepare.
655  *
656  * Returns: %TRUE if the media can be reused
657  */
658 gboolean
659 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
660 {
661   GstRTSPMediaPrivate *priv;
662   gboolean res;
663
664   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
665
666   priv = media->priv;
667
668   g_mutex_lock (&priv->lock);
669   res = priv->reusable;
670   g_mutex_unlock (&priv->lock);
671
672   return res;
673 }
674
675 /**
676  * gst_rtsp_media_set_protocols:
677  * @media: a #GstRTSPMedia
678  * @protocols: the new flags
679  *
680  * Configure the allowed lower transport for @media.
681  */
682 void
683 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
684 {
685   GstRTSPMediaPrivate *priv;
686
687   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
688
689   priv = media->priv;
690
691   g_mutex_lock (&priv->lock);
692   priv->protocols = protocols;
693   g_mutex_unlock (&priv->lock);
694 }
695
696 /**
697  * gst_rtsp_media_get_protocols:
698  * @media: a #GstRTSPMedia
699  *
700  * Get the allowed protocols of @media.
701  *
702  * Returns: a #GstRTSPLowerTrans
703  */
704 GstRTSPLowerTrans
705 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
706 {
707   GstRTSPMediaPrivate *priv;
708   GstRTSPLowerTrans res;
709
710   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
711       GST_RTSP_LOWER_TRANS_UNKNOWN);
712
713   priv = media->priv;
714
715   g_mutex_lock (&priv->lock);
716   res = priv->protocols;
717   g_mutex_unlock (&priv->lock);
718
719   return res;
720 }
721
722 /**
723  * gst_rtsp_media_set_eos_shutdown:
724  * @media: a #GstRTSPMedia
725  * @eos_shutdown: the new value
726  *
727  * Set or unset if an EOS event will be sent to the pipeline for @media before
728  * it is unprepared.
729  */
730 void
731 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
732 {
733   GstRTSPMediaPrivate *priv;
734
735   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
736
737   priv = media->priv;
738
739   g_mutex_lock (&priv->lock);
740   priv->eos_shutdown = eos_shutdown;
741   g_mutex_unlock (&priv->lock);
742 }
743
744 /**
745  * gst_rtsp_media_is_eos_shutdown:
746  * @media: a #GstRTSPMedia
747  *
748  * Check if the pipeline for @media will send an EOS down the pipeline before
749  * unpreparing.
750  *
751  * Returns: %TRUE if the media will send EOS before unpreparing.
752  */
753 gboolean
754 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
755 {
756   GstRTSPMediaPrivate *priv;
757   gboolean res;
758
759   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
760
761   priv = media->priv;
762
763   g_mutex_lock (&priv->lock);
764   res = priv->eos_shutdown;
765   g_mutex_unlock (&priv->lock);
766
767   return res;
768 }
769
770 /**
771  * gst_rtsp_media_set_buffer_size:
772  * @media: a #GstRTSPMedia
773  * @size: the new value
774  *
775  * Set the kernel UDP buffer size.
776  */
777 void
778 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
779 {
780   GstRTSPMediaPrivate *priv;
781
782   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
783
784   GST_LOG_OBJECT (media, "set buffer size %u", size);
785
786   priv = media->priv;
787
788   g_mutex_lock (&priv->lock);
789   priv->buffer_size = size;
790   g_mutex_unlock (&priv->lock);
791 }
792
793 /**
794  * gst_rtsp_media_get_buffer_size:
795  * @media: a #GstRTSPMedia
796  *
797  * Get the kernel UDP buffer size.
798  *
799  * Returns: the kernel UDP buffer size.
800  */
801 guint
802 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
803 {
804   GstRTSPMediaPrivate *priv;
805   guint res;
806
807   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
808
809   priv = media->priv;
810
811   g_mutex_unlock (&priv->lock);
812   res = priv->buffer_size;
813   g_mutex_unlock (&priv->lock);
814
815   return res;
816 }
817
818 /**
819  * gst_rtsp_media_use_time_provider:
820  * @media: a #GstRTSPMedia
821  * @time_provider: if a #GstNetTimeProvider should be used
822  *
823  * Set @media to provide a #GstNetTimeProvider.
824  */
825 void
826 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
827 {
828   GstRTSPMediaPrivate *priv;
829
830   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
831
832   priv = media->priv;
833
834   g_mutex_lock (&priv->lock);
835   priv->time_provider = time_provider;
836   g_mutex_unlock (&priv->lock);
837 }
838
839 /**
840  * gst_rtsp_media_is_time_provider:
841  * @media: a #GstRTSPMedia
842  *
843  * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
844  *
845  * Use gst_rtsp_media_get_time_provider() to get the network clock.
846  *
847  * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
848  */
849 gboolean
850 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
851 {
852   GstRTSPMediaPrivate *priv;
853   gboolean res;
854
855   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
856
857   priv = media->priv;
858
859   g_mutex_unlock (&priv->lock);
860   res = priv->time_provider;
861   g_mutex_unlock (&priv->lock);
862
863   return res;
864 }
865
866 /**
867  * gst_rtsp_media_set_address_pool:
868  * @media: a #GstRTSPMedia
869  * @pool: a #GstRTSPAddressPool
870  *
871  * configure @pool to be used as the address pool of @media.
872  */
873 void
874 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
875     GstRTSPAddressPool * pool)
876 {
877   GstRTSPMediaPrivate *priv;
878   GstRTSPAddressPool *old;
879
880   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
881
882   priv = media->priv;
883
884   GST_LOG_OBJECT (media, "set address pool %p", pool);
885
886   g_mutex_lock (&priv->lock);
887   if ((old = priv->pool) != pool)
888     priv->pool = pool ? g_object_ref (pool) : NULL;
889   else
890     old = NULL;
891   g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
892       pool);
893   g_mutex_unlock (&priv->lock);
894
895   if (old)
896     g_object_unref (old);
897 }
898
899 /**
900  * gst_rtsp_media_get_address_pool:
901  * @media: a #GstRTSPMedia
902  *
903  * Get the #GstRTSPAddressPool used as the address pool of @media.
904  *
905  * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
906  * usage.
907  */
908 GstRTSPAddressPool *
909 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
910 {
911   GstRTSPMediaPrivate *priv;
912   GstRTSPAddressPool *result;
913
914   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
915
916   priv = media->priv;
917
918   g_mutex_lock (&priv->lock);
919   if ((result = priv->pool))
920     g_object_ref (result);
921   g_mutex_unlock (&priv->lock);
922
923   return result;
924 }
925
926 /**
927  * gst_rtsp_media_collect_streams:
928  * @media: a #GstRTSPMedia
929  *
930  * Find all payloader elements, they should be named pay%d in the
931  * element of @media, and create #GstRTSPStreams for them.
932  *
933  * Collect all dynamic elements, named dynpay%d, and add them to
934  * the list of dynamic elements.
935  */
936 void
937 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
938 {
939   GstRTSPMediaPrivate *priv;
940   GstElement *element, *elem;
941   GstPad *pad;
942   gint i;
943   gboolean have_elem;
944
945   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
946
947   priv = media->priv;
948   element = priv->element;
949
950   have_elem = TRUE;
951   for (i = 0; have_elem; i++) {
952     gchar *name;
953
954     have_elem = FALSE;
955
956     name = g_strdup_printf ("pay%d", i);
957     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
958       GST_INFO ("found stream %d with payloader %p", i, elem);
959
960       /* take the pad of the payloader */
961       pad = gst_element_get_static_pad (elem, "src");
962       /* create the stream */
963       gst_rtsp_media_create_stream (media, elem, pad);
964       gst_object_unref (pad);
965       gst_object_unref (elem);
966
967       have_elem = TRUE;
968     }
969     g_free (name);
970
971     name = g_strdup_printf ("dynpay%d", i);
972     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
973       /* a stream that will dynamically create pads to provide RTP packets */
974
975       GST_INFO ("found dynamic element %d, %p", i, elem);
976
977       g_mutex_lock (&priv->lock);
978       priv->dynamic = g_list_prepend (priv->dynamic, elem);
979       g_mutex_unlock (&priv->lock);
980
981       have_elem = TRUE;
982     }
983     g_free (name);
984   }
985 }
986
987 /**
988  * gst_rtsp_media_create_stream:
989  * @media: a #GstRTSPMedia
990  * @payloader: a #GstElement
991  * @srcpad: a source #GstPad
992  *
993  * Create a new stream in @media that provides RTP data on @srcpad.
994  * @srcpad should be a pad of an element inside @media->element.
995  *
996  * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
997  *          as @media exists.
998  */
999 GstRTSPStream *
1000 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
1001     GstPad * pad)
1002 {
1003   GstRTSPMediaPrivate *priv;
1004   GstRTSPStream *stream;
1005   GstPad *srcpad;
1006   gchar *name;
1007   gint idx;
1008
1009   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1010   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
1011   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1012   g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
1013
1014   priv = media->priv;
1015
1016   g_mutex_lock (&priv->lock);
1017   idx = priv->streams->len;
1018
1019   GST_DEBUG ("media %p: creating stream with index %d", media, idx);
1020
1021   name = g_strdup_printf ("src_%u", idx);
1022   srcpad = gst_ghost_pad_new (name, pad);
1023   gst_pad_set_active (srcpad, TRUE);
1024   gst_element_add_pad (priv->element, srcpad);
1025   g_free (name);
1026
1027   stream = gst_rtsp_stream_new (idx, payloader, srcpad);
1028   if (priv->pool)
1029     gst_rtsp_stream_set_address_pool (stream, priv->pool);
1030   gst_rtsp_stream_set_protocols (stream, priv->protocols);
1031
1032   g_ptr_array_add (priv->streams, stream);
1033   g_mutex_unlock (&priv->lock);
1034
1035   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
1036       NULL);
1037
1038   return stream;
1039 }
1040
1041 static void
1042 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
1043 {
1044   GstRTSPMediaPrivate *priv;
1045   GstPad *srcpad;
1046
1047   priv = media->priv;
1048
1049   g_mutex_lock (&priv->lock);
1050   /* remove the ghostpad */
1051   srcpad = gst_rtsp_stream_get_srcpad (stream);
1052   gst_element_remove_pad (priv->element, srcpad);
1053   gst_object_unref (srcpad);
1054   /* now remove the stream */
1055   g_object_ref (stream);
1056   g_ptr_array_remove (priv->streams, stream);
1057   g_mutex_unlock (&priv->lock);
1058
1059   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1060       stream, NULL);
1061
1062   g_object_unref (stream);
1063 }
1064
1065 /**
1066  * gst_rtsp_media_n_streams:
1067  * @media: a #GstRTSPMedia
1068  *
1069  * Get the number of streams in this media.
1070  *
1071  * Returns: The number of streams.
1072  */
1073 guint
1074 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1075 {
1076   GstRTSPMediaPrivate *priv;
1077   guint res;
1078
1079   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1080
1081   priv = media->priv;
1082
1083   g_mutex_lock (&priv->lock);
1084   res = priv->streams->len;
1085   g_mutex_unlock (&priv->lock);
1086
1087   return res;
1088 }
1089
1090 /**
1091  * gst_rtsp_media_get_stream:
1092  * @media: a #GstRTSPMedia
1093  * @idx: the stream index
1094  *
1095  * Retrieve the stream with index @idx from @media.
1096  *
1097  * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
1098  * that index did not exist.
1099  */
1100 GstRTSPStream *
1101 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1102 {
1103   GstRTSPMediaPrivate *priv;
1104   GstRTSPStream *res;
1105
1106   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1107
1108   priv = media->priv;
1109
1110   g_mutex_lock (&priv->lock);
1111   if (idx < priv->streams->len)
1112     res = g_ptr_array_index (priv->streams, idx);
1113   else
1114     res = NULL;
1115   g_mutex_unlock (&priv->lock);
1116
1117   return res;
1118 }
1119
1120 /**
1121  * gst_rtsp_media_find_stream:
1122  * @media: a #GstRTSPMedia
1123  * @control: the control of the stream
1124  *
1125  * Find a stream in @media with @control as the control uri.
1126  *
1127  * Returns: (transfer none): the #GstRTSPStream with control uri @control
1128  * or %NULL when a stream with that control did not exist.
1129  */
1130 GstRTSPStream *
1131 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
1132 {
1133   GstRTSPMediaPrivate *priv;
1134   GstRTSPStream *res;
1135   gint i;
1136
1137   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1138   g_return_val_if_fail (control != NULL, NULL);
1139
1140   priv = media->priv;
1141
1142   res = NULL;
1143
1144   g_mutex_lock (&priv->lock);
1145   for (i = 0; i < priv->streams->len; i++) {
1146     GstRTSPStream *test;
1147
1148     test = g_ptr_array_index (priv->streams, i);
1149     if (gst_rtsp_stream_has_control (test, control)) {
1150       res = test;
1151       break;
1152     }
1153   }
1154   g_mutex_unlock (&priv->lock);
1155
1156   return res;
1157 }
1158
1159 /**
1160  * gst_rtsp_media_get_range_string:
1161  * @media: a #GstRTSPMedia
1162  * @play: for the PLAY request
1163  * @unit: the unit to use for the string
1164  *
1165  * Get the current range as a string. @media must be prepared with
1166  * gst_rtsp_media_prepare ().
1167  *
1168  * Returns: The range as a string, g_free() after usage.
1169  */
1170 gchar *
1171 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
1172     GstRTSPRangeUnit unit)
1173 {
1174   GstRTSPMediaClass *klass;
1175   GstRTSPMediaPrivate *priv;
1176   gchar *result;
1177   GstRTSPTimeRange range;
1178
1179   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1180   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1181   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1182
1183   priv = media->priv;
1184
1185   g_rec_mutex_lock (&priv->state_lock);
1186   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1187     goto not_prepared;
1188
1189   g_mutex_lock (&priv->lock);
1190
1191   /* Update the range value with current position/duration */
1192   collect_media_stats (media);
1193
1194   /* make copy */
1195   range = priv->range;
1196
1197   if (!play && priv->n_active > 0) {
1198     range.min.type = GST_RTSP_TIME_NOW;
1199     range.min.seconds = -1;
1200   }
1201   g_mutex_unlock (&priv->lock);
1202   g_rec_mutex_unlock (&priv->state_lock);
1203
1204   if (!klass->convert_range (media, &range, unit))
1205     goto conversion_failed;
1206
1207   result = gst_rtsp_range_to_string (&range);
1208
1209   return result;
1210
1211   /* ERRORS */
1212 not_prepared:
1213   {
1214     GST_WARNING ("media %p was not prepared", media);
1215     g_rec_mutex_unlock (&priv->state_lock);
1216     return NULL;
1217   }
1218 conversion_failed:
1219   {
1220     GST_WARNING ("range conversion to unit %d failed", unit);
1221     return NULL;
1222   }
1223 }
1224
1225 /**
1226  * gst_rtsp_media_seek:
1227  * @media: a #GstRTSPMedia
1228  * @range: a #GstRTSPTimeRange
1229  *
1230  * Seek the pipeline of @media to @range. @media must be prepared with
1231  * gst_rtsp_media_prepare().
1232  *
1233  * Returns: %TRUE on success.
1234  */
1235 gboolean
1236 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1237 {
1238   GstRTSPMediaClass *klass;
1239   GstRTSPMediaPrivate *priv;
1240   GstSeekFlags flags;
1241   gboolean res;
1242   GstClockTime start, stop;
1243   GstSeekType start_type, stop_type;
1244
1245   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1246
1247   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1248   g_return_val_if_fail (range != NULL, FALSE);
1249   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
1250
1251   priv = media->priv;
1252
1253   g_rec_mutex_lock (&priv->state_lock);
1254   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1255     goto not_prepared;
1256
1257   if (!priv->seekable)
1258     goto not_seekable;
1259
1260   /* depends on the current playing state of the pipeline. We might need to
1261    * queue this until we get EOS. */
1262   flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
1263
1264   start_type = stop_type = GST_SEEK_TYPE_NONE;
1265
1266   if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
1267     goto not_supported;
1268   gst_rtsp_range_get_times (range, &start, &stop);
1269
1270   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1271       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1272   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1273       GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1274
1275   if (priv->range_start == start)
1276     start = GST_CLOCK_TIME_NONE;
1277   else if (start != GST_CLOCK_TIME_NONE)
1278     start_type = GST_SEEK_TYPE_SET;
1279
1280   if (priv->range_stop == stop)
1281     stop = GST_CLOCK_TIME_NONE;
1282   else if (stop != GST_CLOCK_TIME_NONE)
1283     stop_type = GST_SEEK_TYPE_SET;
1284
1285   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1286     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1287         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1288
1289     res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1290         flags, start_type, start, stop_type, stop);
1291
1292     /* and block for the seek to complete */
1293     GST_INFO ("done seeking %d", res);
1294     gst_element_get_state (priv->pipeline, NULL, NULL, -1);
1295     GST_INFO ("prerolled again");
1296
1297     collect_media_stats (media);
1298   } else {
1299     GST_INFO ("no seek needed");
1300     res = TRUE;
1301   }
1302   g_rec_mutex_unlock (&priv->state_lock);
1303
1304   return res;
1305
1306   /* ERRORS */
1307 not_prepared:
1308   {
1309     g_rec_mutex_unlock (&priv->state_lock);
1310     GST_INFO ("media %p is not prepared", media);
1311     return FALSE;
1312   }
1313 not_seekable:
1314   {
1315     g_rec_mutex_unlock (&priv->state_lock);
1316     GST_INFO ("pipeline is not seekable");
1317     return TRUE;
1318   }
1319 not_supported:
1320   {
1321     g_rec_mutex_unlock (&priv->state_lock);
1322     GST_WARNING ("conversion to npt not supported");
1323     return FALSE;
1324   }
1325 }
1326
1327 static void
1328 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1329 {
1330   GstRTSPMediaPrivate *priv = media->priv;
1331
1332   g_mutex_lock (&priv->lock);
1333   priv->status = status;
1334   GST_DEBUG ("setting new status to %d", status);
1335   g_cond_broadcast (&priv->cond);
1336   g_mutex_unlock (&priv->lock);
1337 }
1338
1339 /**
1340  * gst_rtsp_media_get_status:
1341  * @media: a #GstRTSPMedia
1342  *
1343  * Get the status of @media. When @media is busy preparing, this function waits
1344  * until @media is prepared or in error.
1345  *
1346  * Returns: the status of @media.
1347  */
1348 GstRTSPMediaStatus
1349 gst_rtsp_media_get_status (GstRTSPMedia * media)
1350 {
1351   GstRTSPMediaPrivate *priv = media->priv;
1352   GstRTSPMediaStatus result;
1353   gint64 end_time;
1354
1355   g_mutex_lock (&priv->lock);
1356   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1357   /* while we are preparing, wait */
1358   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1359     GST_DEBUG ("waiting for status change");
1360     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1361       GST_DEBUG ("timeout, assuming error status");
1362       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1363     }
1364   }
1365   /* could be success or error */
1366   result = priv->status;
1367   GST_DEBUG ("got status %d", result);
1368   g_mutex_unlock (&priv->lock);
1369
1370   return result;
1371 }
1372
1373 /* called with state-lock */
1374 static gboolean
1375 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1376 {
1377   GstRTSPMediaPrivate *priv = media->priv;
1378   GstMessageType type;
1379
1380   type = GST_MESSAGE_TYPE (message);
1381
1382   switch (type) {
1383     case GST_MESSAGE_STATE_CHANGED:
1384       break;
1385     case GST_MESSAGE_BUFFERING:
1386     {
1387       gint percent;
1388
1389       gst_message_parse_buffering (message, &percent);
1390
1391       /* no state management needed for live pipelines */
1392       if (priv->is_live)
1393         break;
1394
1395       if (percent == 100) {
1396         /* a 100% message means buffering is done */
1397         priv->buffering = FALSE;
1398         /* if the desired state is playing, go back */
1399         if (priv->target_state == GST_STATE_PLAYING) {
1400           GST_INFO ("Buffering done, setting pipeline to PLAYING");
1401           gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1402         } else {
1403           GST_INFO ("Buffering done");
1404         }
1405       } else {
1406         /* buffering busy */
1407         if (priv->buffering == FALSE) {
1408           if (priv->target_state == GST_STATE_PLAYING) {
1409             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
1410             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1411             gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1412           } else {
1413             GST_INFO ("Buffering ...");
1414           }
1415         }
1416         priv->buffering = TRUE;
1417       }
1418       break;
1419     }
1420     case GST_MESSAGE_LATENCY:
1421     {
1422       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1423       break;
1424     }
1425     case GST_MESSAGE_ERROR:
1426     {
1427       GError *gerror;
1428       gchar *debug;
1429
1430       gst_message_parse_error (message, &gerror, &debug);
1431       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1432       g_error_free (gerror);
1433       g_free (debug);
1434
1435       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1436       break;
1437     }
1438     case GST_MESSAGE_WARNING:
1439     {
1440       GError *gerror;
1441       gchar *debug;
1442
1443       gst_message_parse_warning (message, &gerror, &debug);
1444       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1445       g_error_free (gerror);
1446       g_free (debug);
1447       break;
1448     }
1449     case GST_MESSAGE_ELEMENT:
1450       break;
1451     case GST_MESSAGE_STREAM_STATUS:
1452       break;
1453     case GST_MESSAGE_ASYNC_DONE:
1454       if (priv->adding) {
1455         /* when we are dynamically adding pads, the addition of the udpsrc will
1456          * temporarily produce ASYNC_DONE messages. We have to ignore them and
1457          * wait for the final ASYNC_DONE after everything prerolled */
1458         GST_INFO ("%p: ignoring ASYNC_DONE", media);
1459       } else {
1460         GST_INFO ("%p: got ASYNC_DONE", media);
1461         collect_media_stats (media);
1462
1463         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1464           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1465       }
1466       break;
1467     case GST_MESSAGE_EOS:
1468       GST_INFO ("%p: got EOS", media);
1469
1470       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1471         GST_DEBUG ("shutting down after EOS");
1472         finish_unprepare (media);
1473       }
1474       break;
1475     default:
1476       GST_INFO ("%p: got message type %d (%s)", media, type,
1477           gst_message_type_get_name (type));
1478       break;
1479   }
1480   return TRUE;
1481 }
1482
1483 static gboolean
1484 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1485 {
1486   GstRTSPMediaPrivate *priv = media->priv;
1487   GstRTSPMediaClass *klass;
1488   gboolean ret;
1489
1490   klass = GST_RTSP_MEDIA_GET_CLASS (media);
1491
1492   g_rec_mutex_lock (&priv->state_lock);
1493   if (klass->handle_message)
1494     ret = klass->handle_message (media, message);
1495   else
1496     ret = FALSE;
1497   g_rec_mutex_unlock (&priv->state_lock);
1498
1499   return ret;
1500 }
1501
1502 static void
1503 watch_destroyed (GstRTSPMedia * media)
1504 {
1505   GST_DEBUG_OBJECT (media, "source destroyed");
1506   g_object_unref (media);
1507 }
1508
1509 /* called from streaming threads */
1510 static void
1511 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1512 {
1513   GstRTSPMediaPrivate *priv = media->priv;
1514   GstRTSPStream *stream;
1515
1516   /* FIXME, element is likely not a payloader, find the payloader here */
1517   stream = gst_rtsp_media_create_stream (media, element, pad);
1518
1519   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
1520
1521   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1522
1523   g_rec_mutex_lock (&priv->state_lock);
1524   /* we will be adding elements below that will cause ASYNC_DONE to be
1525    * posted in the bus. We want to ignore those messages until the
1526    * pipeline really prerolled. */
1527   priv->adding = TRUE;
1528
1529   /* join the element in the PAUSED state because this callback is
1530    * called from the streaming thread and it is PAUSED */
1531   gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1532       priv->rtpbin, GST_STATE_PAUSED);
1533
1534   priv->adding = FALSE;
1535   g_rec_mutex_unlock (&priv->state_lock);
1536 }
1537
1538 static void
1539 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1540 {
1541   GstRTSPMediaPrivate *priv = media->priv;
1542   GstRTSPStream *stream;
1543
1544   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
1545   if (stream == NULL)
1546     return;
1547
1548   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1549
1550   g_rec_mutex_lock (&priv->state_lock);
1551   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1552   g_rec_mutex_unlock (&priv->state_lock);
1553
1554   gst_rtsp_media_remove_stream (media, stream);
1555 }
1556
1557 static void
1558 remove_fakesink (GstRTSPMediaPrivate * priv)
1559 {
1560   GstElement *fakesink;
1561
1562   g_mutex_lock (&priv->lock);
1563   if ((fakesink = priv->fakesink))
1564     gst_object_ref (fakesink);
1565   priv->fakesink = NULL;
1566   g_mutex_unlock (&priv->lock);
1567
1568   if (fakesink) {
1569     gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1570     gst_element_set_state (fakesink, GST_STATE_NULL);
1571     gst_object_unref (fakesink);
1572     GST_INFO ("removed fakesink");
1573   }
1574 }
1575
1576 static void
1577 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1578 {
1579   GstRTSPMediaPrivate *priv = media->priv;
1580
1581   GST_INFO ("no more pads");
1582   remove_fakesink (priv);
1583 }
1584
1585 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
1586
1587 struct _DynPaySignalHandlers
1588 {
1589   gulong pad_added_handler;
1590   gulong pad_removed_handler;
1591   gulong no_more_pads_handler;
1592 };
1593
1594 static gboolean
1595 start_prepare (GstRTSPMedia * media)
1596 {
1597   GstRTSPMediaPrivate *priv = media->priv;
1598   GstStateChangeReturn ret;
1599   guint i;
1600   GList *walk;
1601
1602   /* link streams we already have, other streams might appear when we have
1603    * dynamic elements */
1604   for (i = 0; i < priv->streams->len; i++) {
1605     GstRTSPStream *stream;
1606
1607     stream = g_ptr_array_index (priv->streams, i);
1608
1609     gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1610         priv->rtpbin, GST_STATE_NULL);
1611   }
1612
1613   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1614     GstElement *elem = walk->data;
1615     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
1616
1617     GST_INFO ("adding callbacks for dynamic element %p", elem);
1618
1619     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
1620         (GCallback) pad_added_cb, media);
1621     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
1622         (GCallback) pad_removed_cb, media);
1623     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
1624         (GCallback) no_more_pads_cb, media);
1625
1626     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
1627
1628     /* we add a fakesink here in order to make the state change async. We remove
1629      * the fakesink again in the no-more-pads callback. */
1630     priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1631     gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
1632   }
1633
1634   GST_INFO ("setting pipeline to PAUSED for media %p", media);
1635   /* first go to PAUSED */
1636   ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1637   priv->target_state = GST_STATE_PAUSED;
1638
1639   switch (ret) {
1640     case GST_STATE_CHANGE_SUCCESS:
1641       GST_INFO ("SUCCESS state change for media %p", media);
1642       priv->seekable = TRUE;
1643       break;
1644     case GST_STATE_CHANGE_ASYNC:
1645       GST_INFO ("ASYNC state change for media %p", media);
1646       priv->seekable = TRUE;
1647       break;
1648     case GST_STATE_CHANGE_NO_PREROLL:
1649       /* we need to go to PLAYING */
1650       GST_INFO ("NO_PREROLL state change: live media %p", media);
1651       /* FIXME we disable seeking for live streams for now. We should perform a
1652        * seeking query in preroll instead */
1653       priv->seekable = FALSE;
1654       priv->is_live = TRUE;
1655       ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1656       if (ret == GST_STATE_CHANGE_FAILURE)
1657         goto state_failed;
1658       break;
1659     case GST_STATE_CHANGE_FAILURE:
1660       goto state_failed;
1661   }
1662
1663   return FALSE;
1664
1665 state_failed:
1666   {
1667     GST_WARNING ("failed to preroll pipeline");
1668     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1669     return FALSE;
1670   }
1671 }
1672
1673 /**
1674  * gst_rtsp_media_prepare:
1675  * @media: a #GstRTSPMedia
1676  * @thread: a #GstRTSPThread to run the bus handler or %NULL
1677  *
1678  * Prepare @media for streaming. This function will create the objects
1679  * to manage the streaming. A pipeline must have been set on @media with
1680  * gst_rtsp_media_take_pipeline().
1681  *
1682  * It will preroll the pipeline and collect vital information about the streams
1683  * such as the duration.
1684  *
1685  * Returns: %TRUE on success.
1686  */
1687 gboolean
1688 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
1689 {
1690   GstRTSPMediaPrivate *priv;
1691   GstRTSPMediaStatus status;
1692   GstBus *bus;
1693   GSource *source;
1694
1695   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1696   g_return_val_if_fail (GST_IS_RTSP_THREAD (thread), FALSE);
1697
1698   priv = media->priv;
1699
1700   g_rec_mutex_lock (&priv->state_lock);
1701   priv->prepare_count++;
1702
1703   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1704     goto was_prepared;
1705
1706   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1707     goto wait_status;
1708
1709   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1710     goto not_unprepared;
1711
1712   if (!priv->reusable && priv->reused)
1713     goto is_reused;
1714
1715   priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1716   if (priv->rtpbin != NULL) {
1717     GstRTSPMediaClass *klass;
1718     gboolean success = TRUE;
1719
1720     klass = GST_RTSP_MEDIA_GET_CLASS (media);
1721     if (klass->setup_rtpbin)
1722       success = klass->setup_rtpbin (media, priv->rtpbin);
1723
1724     if (success == FALSE) {
1725       gst_object_unref (priv->rtpbin);
1726       priv->rtpbin = NULL;
1727     }
1728   }
1729   if (priv->rtpbin == NULL)
1730     goto no_rtpbin;
1731
1732   GST_INFO ("preparing media %p", media);
1733
1734   /* reset some variables */
1735   priv->is_live = FALSE;
1736   priv->seekable = FALSE;
1737   priv->buffering = FALSE;
1738   priv->thread = thread;
1739   /* we're preparing now */
1740   priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1741
1742   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
1743
1744   /* add the pipeline bus to our custom mainloop */
1745   priv->source = gst_bus_create_watch (bus);
1746   gst_object_unref (bus);
1747
1748   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
1749       g_object_ref (media), (GDestroyNotify) watch_destroyed);
1750
1751   priv->id = g_source_attach (priv->source, thread->context);
1752
1753   /* add stuff to the bin */
1754   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
1755
1756   /* do remainder in context */
1757   source = g_idle_source_new ();
1758   g_source_set_callback (source, (GSourceFunc) start_prepare, media, NULL);
1759   g_source_attach (source, thread->context);
1760   g_source_unref (source);
1761
1762 wait_status:
1763   g_rec_mutex_unlock (&priv->state_lock);
1764
1765   /* now wait for all pads to be prerolled, FIXME, we should somehow be
1766    * able to do this async so that we don't block the server thread. */
1767   status = gst_rtsp_media_get_status (media);
1768   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1769     goto state_failed;
1770
1771   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1772
1773   GST_INFO ("object %p is prerolled", media);
1774
1775   return TRUE;
1776
1777   /* OK */
1778 was_prepared:
1779   {
1780     GST_LOG ("media %p was prepared", media);
1781     g_rec_mutex_unlock (&priv->state_lock);
1782     return TRUE;
1783   }
1784   /* ERRORS */
1785 not_unprepared:
1786   {
1787     GST_WARNING ("media %p was not unprepared", media);
1788     priv->prepare_count--;
1789     g_rec_mutex_unlock (&priv->state_lock);
1790     return FALSE;
1791   }
1792 is_reused:
1793   {
1794     priv->prepare_count--;
1795     g_rec_mutex_unlock (&priv->state_lock);
1796     GST_WARNING ("can not reuse media %p", media);
1797     return FALSE;
1798   }
1799 no_rtpbin:
1800   {
1801     priv->prepare_count--;
1802     g_rec_mutex_unlock (&priv->state_lock);
1803     GST_WARNING ("no rtpbin element");
1804     g_warning ("failed to create element 'rtpbin', check your installation");
1805     return FALSE;
1806   }
1807 state_failed:
1808   {
1809     GST_WARNING ("failed to preroll pipeline");
1810     gst_rtsp_media_unprepare (media);
1811     return FALSE;
1812   }
1813 }
1814
1815 /* must be called with state-lock */
1816 static void
1817 finish_unprepare (GstRTSPMedia * media)
1818 {
1819   GstRTSPMediaPrivate *priv = media->priv;
1820   gint i;
1821   GList *walk;
1822
1823   GST_DEBUG ("shutting down");
1824
1825   gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1826   remove_fakesink (priv);
1827
1828   for (i = 0; i < priv->streams->len; i++) {
1829     GstRTSPStream *stream;
1830
1831     GST_INFO ("Removing elements of stream %d from pipeline", i);
1832
1833     stream = g_ptr_array_index (priv->streams, i);
1834
1835     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1836   }
1837
1838   /* remove the pad signal handlers */
1839   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1840     GstElement *elem = walk->data;
1841     DynPaySignalHandlers *handlers;
1842
1843     handlers =
1844         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
1845     g_assert (handlers != NULL);
1846
1847     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
1848     g_signal_handler_disconnect (G_OBJECT (elem),
1849         handlers->pad_removed_handler);
1850     g_signal_handler_disconnect (G_OBJECT (elem),
1851         handlers->no_more_pads_handler);
1852
1853     g_slice_free (DynPaySignalHandlers, handlers);
1854   }
1855
1856   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
1857   priv->rtpbin = NULL;
1858
1859   if (priv->nettime)
1860     gst_object_unref (priv->nettime);
1861   priv->nettime = NULL;
1862
1863   priv->reused = TRUE;
1864   priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1865
1866   /* when the media is not reusable, this will effectively unref the media and
1867    * recreate it */
1868   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1869
1870   /* the source has the last ref to the media */
1871   if (priv->source) {
1872     GST_DEBUG ("destroy source");
1873     g_source_destroy (priv->source);
1874     g_source_unref (priv->source);
1875   }
1876   if (priv->thread) {
1877     GST_DEBUG ("stop thread");
1878     gst_rtsp_thread_stop (priv->thread);
1879   }
1880 }
1881
1882 /* called with state-lock */
1883 static gboolean
1884 default_unprepare (GstRTSPMedia * media)
1885 {
1886   GstRTSPMediaPrivate *priv = media->priv;
1887
1888   if (priv->eos_shutdown) {
1889     GST_DEBUG ("sending EOS for shutdown");
1890     /* ref so that we don't disappear */
1891     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
1892     /* we need to go to playing again for the EOS to propagate, normally in this
1893      * state, nothing is receiving data from us anymore so this is ok. */
1894     gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1895     priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1896   } else {
1897     finish_unprepare (media);
1898   }
1899   return TRUE;
1900 }
1901
1902 /**
1903  * gst_rtsp_media_unprepare:
1904  * @media: a #GstRTSPMedia
1905  *
1906  * Unprepare @media. After this call, the media should be prepared again before
1907  * it can be used again. If the media is set to be non-reusable, a new instance
1908  * must be created.
1909  *
1910  * Returns: %TRUE on success.
1911  */
1912 gboolean
1913 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1914 {
1915   GstRTSPMediaPrivate *priv;
1916   gboolean success;
1917
1918   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1919
1920   priv = media->priv;
1921
1922   g_rec_mutex_lock (&priv->state_lock);
1923   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1924     goto was_unprepared;
1925
1926   priv->prepare_count--;
1927   if (priv->prepare_count > 0)
1928     goto is_busy;
1929
1930   GST_INFO ("unprepare media %p", media);
1931   priv->target_state = GST_STATE_NULL;
1932   success = TRUE;
1933
1934   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1935     GstRTSPMediaClass *klass;
1936
1937     klass = GST_RTSP_MEDIA_GET_CLASS (media);
1938     if (klass->unprepare)
1939       success = klass->unprepare (media);
1940   } else {
1941     finish_unprepare (media);
1942   }
1943   g_rec_mutex_unlock (&priv->state_lock);
1944
1945   return success;
1946
1947 was_unprepared:
1948   {
1949     g_rec_mutex_unlock (&priv->state_lock);
1950     GST_INFO ("media %p was already unprepared", media);
1951     return TRUE;
1952   }
1953 is_busy:
1954   {
1955     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
1956     g_rec_mutex_unlock (&priv->state_lock);
1957     return TRUE;
1958   }
1959 }
1960
1961 /* should be called with state-lock */
1962 static GstClock *
1963 get_clock_unlocked (GstRTSPMedia * media)
1964 {
1965   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
1966     GST_DEBUG_OBJECT (media, "media was not prepared");
1967     return NULL;
1968   }
1969   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
1970 }
1971
1972 /**
1973  * gst_rtsp_media_get_clock:
1974  * @media: a #GstRTSPMedia
1975  *
1976  * Get the clock that is used by the pipeline in @media.
1977  *
1978  * @media must be prepared before this method returns a valid clock object.
1979  *
1980  * Returns: the #GstClock used by @media. unref after usage.
1981  */
1982 GstClock *
1983 gst_rtsp_media_get_clock (GstRTSPMedia * media)
1984 {
1985   GstClock *clock;
1986   GstRTSPMediaPrivate *priv;
1987
1988   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1989
1990   priv = media->priv;
1991
1992   g_rec_mutex_lock (&priv->state_lock);
1993   clock = get_clock_unlocked (media);
1994   g_rec_mutex_unlock (&priv->state_lock);
1995
1996   return clock;
1997 }
1998
1999 /**
2000  * gst_rtsp_media_get_base_time:
2001  * @media: a #GstRTSPMedia
2002  *
2003  * Get the base_time that is used by the pipeline in @media.
2004  *
2005  * @media must be prepared before this method returns a valid base_time.
2006  *
2007  * Returns: the base_time used by @media.
2008  */
2009 GstClockTime
2010 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
2011 {
2012   GstClockTime result;
2013   GstRTSPMediaPrivate *priv;
2014
2015   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
2016
2017   priv = media->priv;
2018
2019   g_rec_mutex_lock (&priv->state_lock);
2020   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2021     goto not_prepared;
2022
2023   result = gst_element_get_base_time (media->priv->pipeline);
2024   g_rec_mutex_unlock (&priv->state_lock);
2025
2026   return result;
2027
2028   /* ERRORS */
2029 not_prepared:
2030   {
2031     g_rec_mutex_unlock (&priv->state_lock);
2032     GST_DEBUG_OBJECT (media, "media was not prepared");
2033     return GST_CLOCK_TIME_NONE;
2034   }
2035 }
2036
2037 /**
2038  * gst_rtsp_media_get_time_provider:
2039  * @media: a #GstRTSPMedia
2040  * @address: an address or NULL
2041  * @port: a port or 0
2042  *
2043  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
2044  * will listen on @address and @port for client time requests.
2045  *
2046  * Returns: the #GstNetTimeProvider of @media.
2047  */
2048 GstNetTimeProvider *
2049 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
2050     guint16 port)
2051 {
2052   GstRTSPMediaPrivate *priv;
2053   GstNetTimeProvider *provider = NULL;
2054
2055   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2056
2057   priv = media->priv;
2058
2059   g_rec_mutex_lock (&priv->state_lock);
2060   if (priv->time_provider) {
2061     if ((provider = priv->nettime) == NULL) {
2062       GstClock *clock;
2063
2064       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
2065         provider = gst_net_time_provider_new (clock, address, port);
2066         gst_object_unref (clock);
2067
2068         priv->nettime = provider;
2069       }
2070     }
2071   }
2072   g_rec_mutex_unlock (&priv->state_lock);
2073
2074   if (provider)
2075     gst_object_ref (provider);
2076
2077   return provider;
2078 }
2079
2080 /**
2081  * gst_rtsp_media_set_pipeline_state:
2082  * @media: a #GstRTSPMedia
2083  * @state: the target state of the pipeline
2084  *
2085  * Set the state of the pipeline managed by @media to @state
2086  */
2087 void
2088 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
2089 {
2090   GstRTSPMediaPrivate *priv = media->priv;
2091
2092   if (state == GST_STATE_NULL) {
2093     gst_rtsp_media_unprepare (media);
2094   } else {
2095     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
2096     priv->target_state = state;
2097     /* when we are buffering, don't update the state yet, this will be done
2098      * when buffering finishes */
2099     if (priv->buffering) {
2100       GST_INFO ("Buffering busy, delay state change");
2101     } else {
2102       gst_element_set_state (priv->pipeline, state);
2103     }
2104   }
2105 }
2106
2107 /**
2108  * gst_rtsp_media_set_state:
2109  * @media: a #GstRTSPMedia
2110  * @state: the target state of the media
2111  * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
2112  *
2113  * Set the state of @media to @state and for the transports in @transports.
2114  *
2115  * @media must be prepared with gst_rtsp_media_prepare();
2116  *
2117  * Returns: %TRUE on success.
2118  */
2119 gboolean
2120 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
2121     GPtrArray * transports)
2122 {
2123   GstRTSPMediaPrivate *priv;
2124   gint i;
2125   gboolean activate, deactivate, do_state;
2126   gint old_active;
2127
2128   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2129   g_return_val_if_fail (transports != NULL, FALSE);
2130
2131   priv = media->priv;
2132
2133   g_rec_mutex_lock (&priv->state_lock);
2134   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2135     goto not_prepared;
2136
2137   /* NULL and READY are the same */
2138   if (state == GST_STATE_READY)
2139     state = GST_STATE_NULL;
2140
2141   activate = deactivate = FALSE;
2142
2143   GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
2144       media);
2145
2146   switch (state) {
2147     case GST_STATE_NULL:
2148     case GST_STATE_PAUSED:
2149       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
2150       if (priv->target_state == GST_STATE_PLAYING)
2151         deactivate = TRUE;
2152       break;
2153     case GST_STATE_PLAYING:
2154       /* we're going to PLAYING, activate */
2155       activate = TRUE;
2156       break;
2157     default:
2158       break;
2159   }
2160   old_active = priv->n_active;
2161
2162   for (i = 0; i < transports->len; i++) {
2163     GstRTSPStreamTransport *trans;
2164
2165     /* we need a non-NULL entry in the array */
2166     trans = g_ptr_array_index (transports, i);
2167     if (trans == NULL)
2168       continue;
2169
2170     if (activate) {
2171       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
2172         priv->n_active++;
2173     } else if (deactivate) {
2174       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
2175         priv->n_active--;
2176     }
2177   }
2178
2179   /* we just activated the first media, do the playing state change */
2180   if (old_active == 0 && activate)
2181     do_state = TRUE;
2182   /* if we have no more active media, do the downward state changes */
2183   else if (priv->n_active == 0)
2184     do_state = TRUE;
2185   else
2186     do_state = FALSE;
2187
2188   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
2189       media, do_state);
2190
2191   if (priv->target_state != state) {
2192     if (do_state)
2193       gst_rtsp_media_set_pipeline_state (media, state);
2194
2195     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
2196         NULL);
2197   }
2198
2199   /* remember where we are */
2200   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
2201           old_active != priv->n_active))
2202     collect_media_stats (media);
2203
2204   g_rec_mutex_unlock (&priv->state_lock);
2205
2206   return TRUE;
2207
2208   /* ERRORS */
2209 not_prepared:
2210   {
2211     GST_WARNING ("media %p was not prepared", media);
2212     g_rec_mutex_unlock (&priv->state_lock);
2213     return FALSE;
2214   }
2215 }
2216
2217 /* called with state-lock */
2218 static gboolean
2219 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
2220     GstRTSPRangeUnit unit)
2221 {
2222   return gst_rtsp_range_convert_units (range, unit);
2223 }
2224
2225 static gboolean
2226 default_query_position (GstRTSPMedia * media, gint64 * position)
2227 {
2228   return gst_element_query_position (media->priv->pipeline, GST_FORMAT_TIME,
2229       position);
2230 }
2231
2232 static gboolean
2233 default_query_stop (GstRTSPMedia * media, gint64 * stop)
2234 {
2235   GstQuery *query;
2236   gboolean res;
2237
2238   query = gst_query_new_segment (GST_FORMAT_TIME);
2239   if ((res = gst_element_query (media->priv->pipeline, query))) {
2240     GstFormat format;
2241     gst_query_parse_segment (query, NULL, &format, NULL, stop);
2242     if (format != GST_FORMAT_TIME)
2243       *stop = -1;
2244   }
2245   gst_query_unref (query);
2246   return res;
2247 }