2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
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.
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.
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.
23 #include <gst/app/gstappsrc.h>
24 #include <gst/app/gstappsink.h>
26 #include "rtsp-media.h"
28 #define GST_RTSP_MEDIA_GET_PRIVATE(obj) \
29 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
31 struct _GstRTSPMediaPrivate
36 /* protected by lock */
39 GstRTSPLowerTrans protocols;
41 gboolean eos_shutdown;
44 GstRTSPAddressPool *pool;
47 GRecMutex state_lock; /* locking order: state lock, lock */
48 GPtrArray *streams; /* protected by lock */
49 GList *dynamic; /* protected by lock */
50 GstRTSPMediaStatus status; /* protected by lock */
55 /* the pipeline for the media */
57 GstElement *fakesink; /* protected by lock */
61 gboolean time_provider;
62 GstNetTimeProvider *nettime;
67 GstState target_state;
69 /* RTP session manager */
72 /* the range of media */
73 GstRTSPTimeRange range; /* protected by lock */
74 GstClockTime range_start;
75 GstClockTime range_stop;
78 #define DEFAULT_SHARED FALSE
79 #define DEFAULT_REUSABLE FALSE
80 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
81 //#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP_MCAST
82 #define DEFAULT_EOS_SHUTDOWN FALSE
83 #define DEFAULT_BUFFER_SIZE 0x80000
84 #define DEFAULT_TIME_PROVIDER FALSE
86 /* define to dump received RTCP packets */
105 SIGNAL_REMOVED_STREAM,
112 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
113 #define GST_CAT_DEFAULT rtsp_media_debug
115 static void gst_rtsp_media_get_property (GObject * object, guint propid,
116 GValue * value, GParamSpec * pspec);
117 static void gst_rtsp_media_set_property (GObject * object, guint propid,
118 const GValue * value, GParamSpec * pspec);
119 static void gst_rtsp_media_finalize (GObject * obj);
121 static gpointer do_loop (GstRTSPMediaClass * klass);
122 static gboolean default_handle_message (GstRTSPMedia * media,
123 GstMessage * message);
124 static void finish_unprepare (GstRTSPMedia * media);
125 static gboolean default_unprepare (GstRTSPMedia * media);
127 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
129 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
132 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
134 GObjectClass *gobject_class;
136 g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
138 gobject_class = G_OBJECT_CLASS (klass);
140 gobject_class->get_property = gst_rtsp_media_get_property;
141 gobject_class->set_property = gst_rtsp_media_set_property;
142 gobject_class->finalize = gst_rtsp_media_finalize;
144 g_object_class_install_property (gobject_class, PROP_SHARED,
145 g_param_spec_boolean ("shared", "Shared",
146 "If this media pipeline can be shared", DEFAULT_SHARED,
147 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
149 g_object_class_install_property (gobject_class, PROP_REUSABLE,
150 g_param_spec_boolean ("reusable", "Reusable",
151 "If this media pipeline can be reused after an unprepare",
152 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
154 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
155 g_param_spec_flags ("protocols", "Protocols",
156 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
157 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
159 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
160 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
161 "Send an EOS event to the pipeline before unpreparing",
162 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
165 g_param_spec_uint ("buffer-size", "Buffer Size",
166 "The kernel UDP buffer size to use", 0, G_MAXUINT,
167 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
169 g_object_class_install_property (gobject_class, PROP_ELEMENT,
170 g_param_spec_object ("element", "The Element",
171 "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
172 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
174 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
175 g_param_spec_boolean ("time-provider", "Time Provider",
176 "Use a NetTimeProvider for clients",
177 DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
179 gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
180 g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
181 G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
182 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
184 gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
185 g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
186 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
187 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
188 GST_TYPE_RTSP_STREAM);
190 gst_rtsp_media_signals[SIGNAL_PREPARED] =
191 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
192 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
193 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
195 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
196 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
197 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
198 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
200 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
201 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
202 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
203 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 0, G_TYPE_INT);
205 klass->context = g_main_context_new ();
206 klass->loop = g_main_loop_new (klass->context, TRUE);
208 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
210 klass->thread = g_thread_new ("Bus Thread", (GThreadFunc) do_loop, klass);
212 klass->handle_message = default_handle_message;
213 klass->unprepare = default_unprepare;
217 gst_rtsp_media_init (GstRTSPMedia * media)
219 GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
223 priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
224 g_mutex_init (&priv->lock);
225 g_cond_init (&priv->cond);
226 g_rec_mutex_init (&priv->state_lock);
228 priv->shared = DEFAULT_SHARED;
229 priv->reusable = DEFAULT_REUSABLE;
230 priv->protocols = DEFAULT_PROTOCOLS;
231 priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
232 priv->buffer_size = DEFAULT_BUFFER_SIZE;
233 priv->time_provider = DEFAULT_TIME_PROVIDER;
237 gst_rtsp_media_finalize (GObject * obj)
239 GstRTSPMediaPrivate *priv;
242 media = GST_RTSP_MEDIA (obj);
245 GST_INFO ("finalize media %p", media);
247 g_ptr_array_unref (priv->streams);
249 g_list_free_full (priv->dynamic, gst_object_unref);
252 gst_object_unref (priv->pipeline);
254 gst_object_unref (priv->nettime);
255 gst_object_unref (priv->element);
257 g_object_unref (priv->auth);
259 g_object_unref (priv->pool);
260 g_mutex_clear (&priv->lock);
261 g_cond_clear (&priv->cond);
262 g_rec_mutex_clear (&priv->state_lock);
264 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
268 gst_rtsp_media_get_property (GObject * object, guint propid,
269 GValue * value, GParamSpec * pspec)
271 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
275 g_value_set_object (value, media->priv->element);
278 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
281 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
284 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
286 case PROP_EOS_SHUTDOWN:
287 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
289 case PROP_BUFFER_SIZE:
290 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
292 case PROP_TIME_PROVIDER:
293 g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
296 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
301 gst_rtsp_media_set_property (GObject * object, guint propid,
302 const GValue * value, GParamSpec * pspec)
304 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
308 media->priv->element = g_value_get_object (value);
311 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
314 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
317 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
319 case PROP_EOS_SHUTDOWN:
320 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
322 case PROP_BUFFER_SIZE:
323 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
325 case PROP_TIME_PROVIDER:
326 gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
329 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
334 do_loop (GstRTSPMediaClass * klass)
336 GST_INFO ("enter mainloop");
337 g_main_loop_run (klass->loop);
338 GST_INFO ("exit mainloop");
343 /* must be called with state lock */
345 collect_media_stats (GstRTSPMedia * media)
347 GstRTSPMediaPrivate *priv = media->priv;
348 gint64 position, duration;
350 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
351 priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
354 priv->range.unit = GST_RTSP_RANGE_NPT;
356 GST_INFO ("collect media stats");
359 priv->range.min.type = GST_RTSP_TIME_NOW;
360 priv->range.min.seconds = -1;
361 priv->range_start = -1;
362 priv->range.max.type = GST_RTSP_TIME_END;
363 priv->range.max.seconds = -1;
364 priv->range_stop = -1;
366 /* get the position */
367 if (!gst_element_query_position (priv->pipeline, GST_FORMAT_TIME,
369 GST_INFO ("position query failed");
373 /* get the duration */
374 if (!gst_element_query_duration (priv->pipeline, GST_FORMAT_TIME,
376 GST_INFO ("duration query failed");
380 GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
381 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
383 if (position == -1) {
384 priv->range.min.type = GST_RTSP_TIME_NOW;
385 priv->range.min.seconds = -1;
386 priv->range_start = -1;
388 priv->range.min.type = GST_RTSP_TIME_SECONDS;
389 priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
390 priv->range_start = position;
392 if (duration == -1) {
393 priv->range.max.type = GST_RTSP_TIME_END;
394 priv->range.max.seconds = -1;
395 priv->range_stop = -1;
397 priv->range.max.type = GST_RTSP_TIME_SECONDS;
398 priv->range.max.seconds = ((gdouble) duration) / GST_SECOND;
399 priv->range_stop = duration;
405 * gst_rtsp_media_new:
406 * @element: (transfer full): a #GstElement
408 * Create a new #GstRTSPMedia instance. @element is the bin element that
409 * provides the different streams. The #GstRTSPMedia object contains the
410 * element to produce RTP data for one or more related (audio/video/..)
413 * Ownership is taken of @element.
415 * Returns: a new #GstRTSPMedia object.
418 gst_rtsp_media_new (GstElement * element)
420 GstRTSPMedia *result;
422 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
424 result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
430 * gst_rtsp_media_take_element:
431 * @media: a #GstRTSPMedia
432 * @pipeline: (transfer full): a #GstPipeline
434 * Set @pipeline as the #GstPipeline for @media. Ownership is
435 * taken of @pipeline.
438 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
440 GstRTSPMediaPrivate *priv;
442 GstNetTimeProvider *nettime;
444 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
445 g_return_if_fail (GST_IS_PIPELINE (pipeline));
449 g_mutex_lock (&priv->lock);
450 old = priv->pipeline;
451 priv->pipeline = GST_ELEMENT_CAST (pipeline);
452 nettime = priv->nettime;
453 priv->nettime = NULL;
454 g_mutex_unlock (&priv->lock);
457 gst_object_unref (old);
460 gst_object_unref (nettime);
462 gst_object_ref (priv->element);
463 gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
467 * gst_rtsp_media_set_shared:
468 * @media: a #GstRTSPMedia
469 * @shared: the new value
471 * Set or unset if the pipeline for @media can be shared will multiple clients.
472 * When @shared is %TRUE, client requests for this media will share the media
476 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
478 GstRTSPMediaPrivate *priv;
480 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
484 g_mutex_lock (&priv->lock);
485 priv->shared = shared;
486 g_mutex_unlock (&priv->lock);
490 * gst_rtsp_media_is_shared:
491 * @media: a #GstRTSPMedia
493 * Check if the pipeline for @media can be shared between multiple clients.
495 * Returns: %TRUE if the media can be shared between clients.
498 gst_rtsp_media_is_shared (GstRTSPMedia * media)
500 GstRTSPMediaPrivate *priv;
503 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
507 g_mutex_lock (&priv->lock);
509 g_mutex_unlock (&priv->lock);
515 * gst_rtsp_media_set_reusable:
516 * @media: a #GstRTSPMedia
517 * @reusable: the new value
519 * Set or unset if the pipeline for @media can be reused after the pipeline has
523 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
525 GstRTSPMediaPrivate *priv;
527 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
531 g_mutex_lock (&priv->lock);
532 priv->reusable = reusable;
533 g_mutex_unlock (&priv->lock);
537 * gst_rtsp_media_is_reusable:
538 * @media: a #GstRTSPMedia
540 * Check if the pipeline for @media can be reused after an unprepare.
542 * Returns: %TRUE if the media can be reused
545 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
547 GstRTSPMediaPrivate *priv;
550 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
554 g_mutex_lock (&priv->lock);
555 res = priv->reusable;
556 g_mutex_unlock (&priv->lock);
562 * gst_rtsp_media_set_protocols:
563 * @media: a #GstRTSPMedia
564 * @protocols: the new flags
566 * Configure the allowed lower transport for @media.
569 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
571 GstRTSPMediaPrivate *priv;
573 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
577 g_mutex_lock (&priv->lock);
578 priv->protocols = protocols;
579 g_mutex_unlock (&priv->lock);
583 * gst_rtsp_media_get_protocols:
584 * @media: a #GstRTSPMedia
586 * Get the allowed protocols of @media.
588 * Returns: a #GstRTSPLowerTrans
591 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
593 GstRTSPMediaPrivate *priv;
594 GstRTSPLowerTrans res;
596 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
597 GST_RTSP_LOWER_TRANS_UNKNOWN);
601 g_mutex_lock (&priv->lock);
602 res = priv->protocols;
603 g_mutex_unlock (&priv->lock);
609 * gst_rtsp_media_set_eos_shutdown:
610 * @media: a #GstRTSPMedia
611 * @eos_shutdown: the new value
613 * Set or unset if an EOS event will be sent to the pipeline for @media before
617 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
619 GstRTSPMediaPrivate *priv;
621 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
625 g_mutex_lock (&priv->lock);
626 priv->eos_shutdown = eos_shutdown;
627 g_mutex_unlock (&priv->lock);
631 * gst_rtsp_media_is_eos_shutdown:
632 * @media: a #GstRTSPMedia
634 * Check if the pipeline for @media will send an EOS down the pipeline before
637 * Returns: %TRUE if the media will send EOS before unpreparing.
640 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
642 GstRTSPMediaPrivate *priv;
645 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
649 g_mutex_lock (&priv->lock);
650 res = priv->eos_shutdown;
651 g_mutex_unlock (&priv->lock);
657 * gst_rtsp_media_set_buffer_size:
658 * @media: a #GstRTSPMedia
659 * @size: the new value
661 * Set the kernel UDP buffer size.
664 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
666 GstRTSPMediaPrivate *priv;
668 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
670 GST_LOG_OBJECT (media, "set buffer size %u", size);
674 g_mutex_lock (&priv->lock);
675 priv->buffer_size = size;
676 g_mutex_unlock (&priv->lock);
680 * gst_rtsp_media_get_buffer_size:
681 * @media: a #GstRTSPMedia
683 * Get the kernel UDP buffer size.
685 * Returns: the kernel UDP buffer size.
688 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
690 GstRTSPMediaPrivate *priv;
693 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
697 g_mutex_unlock (&priv->lock);
698 res = priv->buffer_size;
699 g_mutex_unlock (&priv->lock);
705 * gst_rtsp_media_use_time_provider:
706 * @media: a #GstRTSPMedia
708 * Set @media to provide a GstNetTimeProvider.
711 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
713 GstRTSPMediaPrivate *priv;
715 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
719 g_mutex_lock (&priv->lock);
720 priv->time_provider = time_provider;
721 g_mutex_unlock (&priv->lock);
725 * gst_rtsp_media_is_time_provider:
726 * @media: a #GstRTSPMedia
728 * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
730 * Use gst_rtsp_media_get_time_provider() to get the network clock.
732 * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
735 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
737 GstRTSPMediaPrivate *priv;
740 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
744 g_mutex_unlock (&priv->lock);
745 res = priv->time_provider;
746 g_mutex_unlock (&priv->lock);
752 * gst_rtsp_media_set_auth:
753 * @media: a #GstRTSPMedia
754 * @auth: a #GstRTSPAuth
756 * configure @auth to be used as the authentication manager of @media.
759 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
761 GstRTSPMediaPrivate *priv;
764 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
768 GST_LOG_OBJECT (media, "set auth %p", auth);
770 g_mutex_lock (&priv->lock);
771 if ((old = priv->auth) != auth)
772 priv->auth = auth ? g_object_ref (auth) : NULL;
775 g_mutex_unlock (&priv->lock);
778 g_object_unref (old);
782 * gst_rtsp_media_get_auth:
783 * @media: a #GstRTSPMedia
785 * Get the #GstRTSPAuth used as the authentication manager of @media.
787 * Returns: (transfer full): the #GstRTSPAuth of @media. g_object_unref() after
791 gst_rtsp_media_get_auth (GstRTSPMedia * media)
793 GstRTSPMediaPrivate *priv;
796 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
800 g_mutex_lock (&priv->lock);
801 if ((result = priv->auth))
802 g_object_ref (result);
803 g_mutex_unlock (&priv->lock);
809 * gst_rtsp_media_set_address_pool:
810 * @media: a #GstRTSPMedia
811 * @pool: a #GstRTSPAddressPool
813 * configure @pool to be used as the address pool of @media.
816 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
817 GstRTSPAddressPool * pool)
819 GstRTSPMediaPrivate *priv;
820 GstRTSPAddressPool *old;
822 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
826 GST_LOG_OBJECT (media, "set address pool %p", pool);
828 g_mutex_lock (&priv->lock);
829 if ((old = priv->pool) != pool)
830 priv->pool = pool ? g_object_ref (pool) : NULL;
833 g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
835 g_mutex_unlock (&priv->lock);
838 g_object_unref (old);
842 * gst_rtsp_media_get_address_pool:
843 * @media: a #GstRTSPMedia
845 * Get the #GstRTSPAddressPool used as the address pool of @media.
847 * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
851 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
853 GstRTSPMediaPrivate *priv;
854 GstRTSPAddressPool *result;
856 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
860 g_mutex_lock (&priv->lock);
861 if ((result = priv->pool))
862 g_object_ref (result);
863 g_mutex_unlock (&priv->lock);
869 * gst_rtsp_media_collect_streams:
870 * @media: a #GstRTSPMedia
872 * Find all payloader elements, they should be named pay%d in the
873 * element of @media, and create #GstRTSPStreams for them.
875 * Collect all dynamic elements, named dynpay%d, and add them to
876 * the list of dynamic elements.
879 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
881 GstRTSPMediaPrivate *priv;
882 GstElement *element, *elem;
887 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
890 element = priv->element;
893 for (i = 0; have_elem; i++) {
898 name = g_strdup_printf ("pay%d", i);
899 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
900 GST_INFO ("found stream %d with payloader %p", i, elem);
902 /* take the pad of the payloader */
903 pad = gst_element_get_static_pad (elem, "src");
904 /* create the stream */
905 gst_rtsp_media_create_stream (media, elem, pad);
906 gst_object_unref (pad);
907 gst_object_unref (elem);
913 name = g_strdup_printf ("dynpay%d", i);
914 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
915 /* a stream that will dynamically create pads to provide RTP packets */
917 GST_INFO ("found dynamic element %d, %p", i, elem);
919 g_mutex_lock (&priv->lock);
920 priv->dynamic = g_list_prepend (priv->dynamic, elem);
921 g_mutex_unlock (&priv->lock);
930 * gst_rtsp_media_create_stream:
931 * @media: a #GstRTSPMedia
932 * @payloader: a #GstElement
933 * @srcpad: a source #GstPad
935 * Create a new stream in @media that provides RTP data on @srcpad.
936 * @srcpad should be a pad of an element inside @media->element.
938 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
942 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
945 GstRTSPMediaPrivate *priv;
946 GstRTSPStream *stream;
951 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
952 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
953 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
954 g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
958 g_mutex_lock (&priv->lock);
959 idx = priv->streams->len;
961 GST_DEBUG ("media %p: creating stream with index %d", media, idx);
963 name = g_strdup_printf ("src_%u", idx);
964 srcpad = gst_ghost_pad_new (name, pad);
965 gst_pad_set_active (srcpad, TRUE);
966 gst_element_add_pad (priv->element, srcpad);
969 stream = gst_rtsp_stream_new (idx, payloader, srcpad);
971 gst_rtsp_stream_set_address_pool (stream, priv->pool);
973 g_ptr_array_add (priv->streams, stream);
974 g_mutex_unlock (&priv->lock);
976 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
983 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
985 GstRTSPMediaPrivate *priv;
990 g_mutex_lock (&priv->lock);
991 /* remove the ghostpad */
992 srcpad = gst_rtsp_stream_get_srcpad (stream);
993 gst_element_remove_pad (priv->element, srcpad);
994 gst_object_unref (srcpad);
995 /* now remove the stream */
996 g_object_ref (stream);
997 g_ptr_array_remove (priv->streams, stream);
998 g_mutex_unlock (&priv->lock);
1000 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1003 g_object_unref (stream);
1007 * gst_rtsp_media_n_streams:
1008 * @media: a #GstRTSPMedia
1010 * Get the number of streams in this media.
1012 * Returns: The number of streams.
1015 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1017 GstRTSPMediaPrivate *priv;
1020 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1024 g_mutex_lock (&priv->lock);
1025 res = priv->streams->len;
1026 g_mutex_unlock (&priv->lock);
1032 * gst_rtsp_media_get_stream:
1033 * @media: a #GstRTSPMedia
1034 * @idx: the stream index
1036 * Retrieve the stream with index @idx from @media.
1038 * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
1039 * that index did not exist.
1042 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1044 GstRTSPMediaPrivate *priv;
1047 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1051 g_mutex_lock (&priv->lock);
1052 if (idx < priv->streams->len)
1053 res = g_ptr_array_index (priv->streams, idx);
1056 g_mutex_unlock (&priv->lock);
1062 * gst_rtsp_media_get_range_string:
1063 * @media: a #GstRTSPMedia
1064 * @play: for the PLAY request
1065 * @unit: the unit to use for the string
1067 * Get the current range as a string. @media must be prepared with
1068 * gst_rtsp_media_prepare ().
1070 * Returns: The range as a string, g_free() after usage.
1073 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
1074 GstRTSPRangeUnit unit)
1076 GstRTSPMediaPrivate *priv;
1078 GstRTSPTimeRange range;
1080 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1084 g_rec_mutex_lock (&priv->state_lock);
1085 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1088 g_mutex_lock (&priv->lock);
1090 range = priv->range;
1092 if (!play && priv->n_active > 0) {
1093 range.min.type = GST_RTSP_TIME_NOW;
1094 range.min.seconds = -1;
1096 g_mutex_unlock (&priv->lock);
1097 g_rec_mutex_unlock (&priv->state_lock);
1099 gst_rtsp_range_convert_units (&range, unit);
1101 result = gst_rtsp_range_to_string (&range);
1108 GST_WARNING ("media %p was not prepared", media);
1109 g_rec_mutex_unlock (&priv->state_lock);
1115 * gst_rtsp_media_seek:
1116 * @media: a #GstRTSPMedia
1117 * @range: a #GstRTSPTimeRange
1119 * Seek the pipeline of @media to @range. @media must be prepared with
1120 * gst_rtsp_media_prepare().
1122 * Returns: %TRUE on success.
1125 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1127 GstRTSPMediaPrivate *priv;
1130 GstClockTime start, stop;
1131 GstSeekType start_type, stop_type;
1133 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1134 g_return_val_if_fail (range != NULL, FALSE);
1138 g_rec_mutex_lock (&priv->state_lock);
1139 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1142 if (!priv->seekable)
1145 /* depends on the current playing state of the pipeline. We might need to
1146 * queue this until we get EOS. */
1147 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
1149 start_type = stop_type = GST_SEEK_TYPE_NONE;
1151 if (!gst_rtsp_range_get_times (range, &start, &stop))
1154 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1155 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1156 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1157 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1159 if (priv->range_start == start)
1160 start = GST_CLOCK_TIME_NONE;
1161 else if (start != GST_CLOCK_TIME_NONE)
1162 start_type = GST_SEEK_TYPE_SET;
1164 if (priv->range_stop == stop)
1165 stop = GST_CLOCK_TIME_NONE;
1166 else if (stop != GST_CLOCK_TIME_NONE)
1167 stop_type = GST_SEEK_TYPE_SET;
1169 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1170 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1171 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1173 res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1174 flags, start_type, start, stop_type, stop);
1176 /* and block for the seek to complete */
1177 GST_INFO ("done seeking %d", res);
1178 gst_element_get_state (priv->pipeline, NULL, NULL, -1);
1179 GST_INFO ("prerolled again");
1181 collect_media_stats (media);
1183 GST_INFO ("no seek needed");
1186 g_rec_mutex_unlock (&priv->state_lock);
1193 g_rec_mutex_unlock (&priv->state_lock);
1194 GST_INFO ("media %p is not prepared", media);
1199 g_rec_mutex_unlock (&priv->state_lock);
1200 GST_INFO ("pipeline is not seekable");
1205 g_rec_mutex_unlock (&priv->state_lock);
1206 GST_WARNING ("seek unit %d not supported", range->unit);
1212 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1214 GstRTSPMediaPrivate *priv = media->priv;
1216 g_mutex_lock (&priv->lock);
1217 priv->status = status;
1218 GST_DEBUG ("setting new status to %d", status);
1219 g_cond_broadcast (&priv->cond);
1220 g_mutex_unlock (&priv->lock);
1224 * gst_rtsp_media_get_status:
1225 * @media: a #GstRTSPMedia
1227 * Get the status of @media. When @media is busy preparing, this function waits
1228 * until @media is prepared or in error.
1230 * Returns: the status of @media.
1233 gst_rtsp_media_get_status (GstRTSPMedia * media)
1235 GstRTSPMediaPrivate *priv = media->priv;
1236 GstRTSPMediaStatus result;
1239 g_mutex_lock (&priv->lock);
1240 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1241 /* while we are preparing, wait */
1242 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1243 GST_DEBUG ("waiting for status change");
1244 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1245 GST_DEBUG ("timeout, assuming error status");
1246 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1249 /* could be success or error */
1250 result = priv->status;
1251 GST_DEBUG ("got status %d", result);
1252 g_mutex_unlock (&priv->lock);
1257 /* called with state-lock */
1259 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1261 GstRTSPMediaPrivate *priv = media->priv;
1262 GstMessageType type;
1264 type = GST_MESSAGE_TYPE (message);
1267 case GST_MESSAGE_STATE_CHANGED:
1269 case GST_MESSAGE_BUFFERING:
1273 gst_message_parse_buffering (message, &percent);
1275 /* no state management needed for live pipelines */
1279 if (percent == 100) {
1280 /* a 100% message means buffering is done */
1281 priv->buffering = FALSE;
1282 /* if the desired state is playing, go back */
1283 if (priv->target_state == GST_STATE_PLAYING) {
1284 GST_INFO ("Buffering done, setting pipeline to PLAYING");
1285 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1287 GST_INFO ("Buffering done");
1290 /* buffering busy */
1291 if (priv->buffering == FALSE) {
1292 if (priv->target_state == GST_STATE_PLAYING) {
1293 /* we were not buffering but PLAYING, PAUSE the pipeline. */
1294 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1295 gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1297 GST_INFO ("Buffering ...");
1300 priv->buffering = TRUE;
1304 case GST_MESSAGE_LATENCY:
1306 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1309 case GST_MESSAGE_ERROR:
1314 gst_message_parse_error (message, &gerror, &debug);
1315 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1316 g_error_free (gerror);
1319 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1322 case GST_MESSAGE_WARNING:
1327 gst_message_parse_warning (message, &gerror, &debug);
1328 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1329 g_error_free (gerror);
1333 case GST_MESSAGE_ELEMENT:
1335 case GST_MESSAGE_STREAM_STATUS:
1337 case GST_MESSAGE_ASYNC_DONE:
1339 /* when we are dynamically adding pads, the addition of the udpsrc will
1340 * temporarily produce ASYNC_DONE messages. We have to ignore them and
1341 * wait for the final ASYNC_DONE after everything prerolled */
1342 GST_INFO ("%p: ignoring ASYNC_DONE", media);
1344 GST_INFO ("%p: got ASYNC_DONE", media);
1345 collect_media_stats (media);
1347 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1348 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1351 case GST_MESSAGE_EOS:
1352 GST_INFO ("%p: got EOS", media);
1354 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1355 GST_DEBUG ("shutting down after EOS");
1356 finish_unprepare (media);
1360 GST_INFO ("%p: got message type %d (%s)", media, type,
1361 gst_message_type_get_name (type));
1368 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1370 GstRTSPMediaPrivate *priv = media->priv;
1371 GstRTSPMediaClass *klass;
1374 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1376 g_rec_mutex_lock (&priv->state_lock);
1377 if (klass->handle_message)
1378 ret = klass->handle_message (media, message);
1381 g_rec_mutex_unlock (&priv->state_lock);
1387 watch_destroyed (GstRTSPMedia * media)
1389 GST_DEBUG_OBJECT (media, "source destroyed");
1390 g_object_unref (media);
1393 /* called from streaming threads */
1395 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1397 GstRTSPMediaPrivate *priv = media->priv;
1398 GstRTSPStream *stream;
1400 /* FIXME, element is likely not a payloader, find the payloader here */
1401 stream = gst_rtsp_media_create_stream (media, element, pad);
1403 g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
1405 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1407 g_rec_mutex_lock (&priv->state_lock);
1408 /* we will be adding elements below that will cause ASYNC_DONE to be
1409 * posted in the bus. We want to ignore those messages until the
1410 * pipeline really prerolled. */
1411 priv->adding = TRUE;
1413 /* join the element in the PAUSED state because this callback is
1414 * called from the streaming thread and it is PAUSED */
1415 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1416 priv->rtpbin, GST_STATE_PAUSED);
1418 priv->adding = FALSE;
1419 g_rec_mutex_unlock (&priv->state_lock);
1423 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1425 GstRTSPMediaPrivate *priv = media->priv;
1426 GstRTSPStream *stream;
1428 stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
1432 GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1434 g_rec_mutex_lock (&priv->state_lock);
1435 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1436 g_rec_mutex_unlock (&priv->state_lock);
1438 gst_rtsp_media_remove_stream (media, stream);
1442 remove_fakesink (GstRTSPMediaPrivate * priv)
1444 GstElement *fakesink;
1446 g_mutex_lock (&priv->lock);
1447 if ((fakesink = priv->fakesink))
1448 gst_object_ref (fakesink);
1449 priv->fakesink = NULL;
1450 g_mutex_unlock (&priv->lock);
1453 gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1454 gst_element_set_state (fakesink, GST_STATE_NULL);
1455 gst_object_unref (fakesink);
1456 GST_INFO ("removed fakesink");
1461 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1463 GstRTSPMediaPrivate *priv = media->priv;
1465 GST_INFO ("no more pads");
1466 remove_fakesink (priv);
1469 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
1471 struct _DynPaySignalHandlers
1473 gulong pad_added_handler;
1474 gulong pad_removed_handler;
1475 gulong no_more_pads_handler;
1479 * gst_rtsp_media_prepare:
1480 * @media: a #GstRTSPMedia
1482 * Prepare @media for streaming. This function will create the objects
1483 * to manage the streaming. A pipeline must have been set on @media with
1484 * gst_rtsp_media_take_pipeline().
1486 * It will preroll the pipeline and collect vital information about the streams
1487 * such as the duration.
1489 * Returns: %TRUE on success.
1492 gst_rtsp_media_prepare (GstRTSPMedia * media)
1494 GstRTSPMediaPrivate *priv;
1495 GstStateChangeReturn ret;
1496 GstRTSPMediaStatus status;
1498 GstRTSPMediaClass *klass;
1502 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1506 g_rec_mutex_lock (&priv->state_lock);
1507 priv->prepare_count++;
1509 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1512 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1515 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1516 goto not_unprepared;
1518 if (!priv->reusable && priv->reused)
1521 priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1522 if (priv->rtpbin == NULL)
1525 GST_INFO ("preparing media %p", media);
1527 /* reset some variables */
1528 priv->is_live = FALSE;
1529 priv->seekable = FALSE;
1530 priv->buffering = FALSE;
1531 /* we're preparing now */
1532 priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1534 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
1536 /* add the pipeline bus to our custom mainloop */
1537 priv->source = gst_bus_create_watch (bus);
1538 gst_object_unref (bus);
1540 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
1541 g_object_ref (media), (GDestroyNotify) watch_destroyed);
1543 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1544 priv->id = g_source_attach (priv->source, klass->context);
1546 /* add stuff to the bin */
1547 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
1549 /* link streams we already have, other streams might appear when we have
1550 * dynamic elements */
1551 for (i = 0; i < priv->streams->len; i++) {
1552 GstRTSPStream *stream;
1554 stream = g_ptr_array_index (priv->streams, i);
1556 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1557 priv->rtpbin, GST_STATE_NULL);
1560 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1561 GstElement *elem = walk->data;
1562 DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
1564 GST_INFO ("adding callbacks for dynamic element %p", elem);
1566 handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
1567 (GCallback) pad_added_cb, media);
1568 handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
1569 (GCallback) pad_removed_cb, media);
1570 handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
1571 (GCallback) no_more_pads_cb, media);
1573 g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
1575 /* we add a fakesink here in order to make the state change async. We remove
1576 * the fakesink again in the no-more-pads callback. */
1577 priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1578 gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
1581 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1582 /* first go to PAUSED */
1583 ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1584 priv->target_state = GST_STATE_PAUSED;
1587 case GST_STATE_CHANGE_SUCCESS:
1588 GST_INFO ("SUCCESS state change for media %p", media);
1589 priv->seekable = TRUE;
1591 case GST_STATE_CHANGE_ASYNC:
1592 GST_INFO ("ASYNC state change for media %p", media);
1593 priv->seekable = TRUE;
1595 case GST_STATE_CHANGE_NO_PREROLL:
1596 /* we need to go to PLAYING */
1597 GST_INFO ("NO_PREROLL state change: live media %p", media);
1598 /* FIXME we disable seeking for live streams for now. We should perform a
1599 * seeking query in preroll instead */
1600 priv->seekable = FALSE;
1601 priv->is_live = TRUE;
1602 ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1603 if (ret == GST_STATE_CHANGE_FAILURE)
1606 case GST_STATE_CHANGE_FAILURE:
1610 g_rec_mutex_unlock (&priv->state_lock);
1612 /* now wait for all pads to be prerolled, FIXME, we should somehow be
1613 * able to do this async so that we don't block the server thread. */
1614 status = gst_rtsp_media_get_status (media);
1615 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1618 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1620 GST_INFO ("object %p is prerolled", media);
1627 GST_LOG ("media %p was prepared", media);
1628 g_rec_mutex_unlock (&priv->state_lock);
1634 GST_WARNING ("media %p was not unprepared", media);
1635 priv->prepare_count--;
1636 g_rec_mutex_unlock (&priv->state_lock);
1641 priv->prepare_count--;
1642 g_rec_mutex_unlock (&priv->state_lock);
1643 GST_WARNING ("can not reuse media %p", media);
1648 priv->prepare_count--;
1649 g_rec_mutex_unlock (&priv->state_lock);
1650 GST_WARNING ("no rtpbin element");
1651 g_warning ("failed to create element 'rtpbin', check your installation");
1656 GST_WARNING ("failed to preroll pipeline");
1657 gst_rtsp_media_unprepare (media);
1658 g_rec_mutex_unlock (&priv->state_lock);
1663 /* must be called with state-lock */
1665 finish_unprepare (GstRTSPMedia * media)
1667 GstRTSPMediaPrivate *priv = media->priv;
1671 GST_DEBUG ("shutting down");
1673 gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1674 remove_fakesink (priv);
1676 for (i = 0; i < priv->streams->len; i++) {
1677 GstRTSPStream *stream;
1679 GST_INFO ("Removing elements of stream %d from pipeline", i);
1681 stream = g_ptr_array_index (priv->streams, i);
1683 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1686 /* remove the pad signal handlers */
1687 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1688 GstElement *elem = walk->data;
1689 DynPaySignalHandlers *handlers;
1692 g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
1693 g_assert (handlers != NULL);
1695 g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
1696 g_signal_handler_disconnect (G_OBJECT (elem),
1697 handlers->pad_removed_handler);
1698 g_signal_handler_disconnect (G_OBJECT (elem),
1699 handlers->no_more_pads_handler);
1701 g_slice_free (DynPaySignalHandlers, handlers);
1704 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
1705 priv->rtpbin = NULL;
1708 gst_object_unref (priv->nettime);
1709 priv->nettime = NULL;
1711 priv->reused = TRUE;
1712 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1714 /* when the media is not reusable, this will effectively unref the media and
1716 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1718 /* the source has the last ref to the media */
1720 GST_DEBUG ("destroy source");
1721 g_source_destroy (priv->source);
1722 g_source_unref (priv->source);
1726 /* called with state-lock */
1728 default_unprepare (GstRTSPMedia * media)
1730 GstRTSPMediaPrivate *priv = media->priv;
1732 if (priv->eos_shutdown) {
1733 GST_DEBUG ("sending EOS for shutdown");
1734 /* ref so that we don't disappear */
1735 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
1736 /* we need to go to playing again for the EOS to propagate, normally in this
1737 * state, nothing is receiving data from us anymore so this is ok. */
1738 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1739 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1741 finish_unprepare (media);
1747 * gst_rtsp_media_unprepare:
1748 * @media: a #GstRTSPMedia
1750 * Unprepare @media. After this call, the media should be prepared again before
1751 * it can be used again. If the media is set to be non-reusable, a new instance
1754 * Returns: %TRUE on success.
1757 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1759 GstRTSPMediaPrivate *priv;
1762 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1766 g_rec_mutex_lock (&priv->state_lock);
1767 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1768 goto was_unprepared;
1770 priv->prepare_count--;
1771 if (priv->prepare_count > 0)
1774 GST_INFO ("unprepare media %p", media);
1775 priv->target_state = GST_STATE_NULL;
1778 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1779 GstRTSPMediaClass *klass;
1781 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1782 if (klass->unprepare)
1783 success = klass->unprepare (media);
1785 finish_unprepare (media);
1787 g_rec_mutex_unlock (&priv->state_lock);
1793 g_rec_mutex_unlock (&priv->state_lock);
1794 GST_INFO ("media %p was already unprepared", media);
1799 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
1800 g_rec_mutex_unlock (&priv->state_lock);
1805 /* should be called with state-lock */
1807 get_clock_unlocked (GstRTSPMedia * media)
1809 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
1810 GST_DEBUG_OBJECT (media, "media was not prepared");
1813 return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
1817 * gst_rtsp_media_get_clock:
1818 * @media: a #GstRTSPMedia
1820 * Get the clock that is used by the pipeline in @media.
1822 * @media must be prepared before this method returns a valid clock object.
1824 * Returns: the #GstClock used by @media. unref after usage.
1827 gst_rtsp_media_get_clock (GstRTSPMedia * media)
1830 GstRTSPMediaPrivate *priv;
1832 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1836 g_rec_mutex_lock (&priv->state_lock);
1837 clock = get_clock_unlocked (media);
1838 g_rec_mutex_unlock (&priv->state_lock);
1844 * gst_rtsp_media_get_base_time:
1845 * @media: a #GstRTSPMedia
1847 * Get the base_time that is used by the pipeline in @media.
1849 * @media must be prepared before this method returns a valid base_time.
1851 * Returns: the base_time used by @media.
1854 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
1856 GstClockTime result;
1857 GstRTSPMediaPrivate *priv;
1859 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
1863 g_rec_mutex_lock (&priv->state_lock);
1864 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1867 result = gst_element_get_base_time (media->priv->pipeline);
1868 g_rec_mutex_unlock (&priv->state_lock);
1875 g_rec_mutex_unlock (&priv->state_lock);
1876 GST_DEBUG_OBJECT (media, "media was not prepared");
1877 return GST_CLOCK_TIME_NONE;
1882 * gst_rtsp_media_get_time_provider:
1883 * @media: a #GstRTSPMedia
1884 * @address: an address or NULL
1885 * @port: a port or 0
1887 * Get the #GstNetTimeProvider for the clock used by @media. The time provider
1888 * will listen on @address and @port for client time requests.
1890 * Returns: the #GstNetTimeProvider of @media.
1892 GstNetTimeProvider *
1893 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
1896 GstRTSPMediaPrivate *priv;
1897 GstNetTimeProvider *provider = NULL;
1899 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1903 g_rec_mutex_lock (&priv->state_lock);
1904 if (priv->time_provider) {
1905 if ((provider = priv->nettime) == NULL) {
1908 if (priv->time_provider && (clock = get_clock_unlocked (media))) {
1909 provider = gst_net_time_provider_new (clock, address, port);
1910 gst_object_unref (clock);
1912 priv->nettime = provider;
1916 g_rec_mutex_unlock (&priv->state_lock);
1919 gst_object_ref (provider);
1925 * gst_rtsp_media_set_state:
1926 * @media: a #GstRTSPMedia
1927 * @state: the target state of the media
1928 * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
1930 * Set the state of @media to @state and for the transports in @transports.
1932 * @media must be prepared with gst_rtsp_media_prepare();
1934 * Returns: %TRUE on success.
1937 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1938 GPtrArray * transports)
1940 GstRTSPMediaPrivate *priv;
1942 gboolean activate, deactivate, do_state;
1945 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1946 g_return_val_if_fail (transports != NULL, FALSE);
1950 g_rec_mutex_lock (&priv->state_lock);
1951 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1954 /* NULL and READY are the same */
1955 if (state == GST_STATE_READY)
1956 state = GST_STATE_NULL;
1958 activate = deactivate = FALSE;
1960 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1964 case GST_STATE_NULL:
1965 case GST_STATE_PAUSED:
1966 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
1967 if (priv->target_state == GST_STATE_PLAYING)
1970 case GST_STATE_PLAYING:
1971 /* we're going to PLAYING, activate */
1977 old_active = priv->n_active;
1979 for (i = 0; i < transports->len; i++) {
1980 GstRTSPStreamTransport *trans;
1982 /* we need a non-NULL entry in the array */
1983 trans = g_ptr_array_index (transports, i);
1988 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
1990 } else if (deactivate) {
1991 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
1996 /* we just activated the first media, do the playing state change */
1997 if (old_active == 0 && activate)
1999 /* if we have no more active media, do the downward state changes */
2000 else if (priv->n_active == 0)
2005 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
2008 if (priv->target_state != state) {
2010 if (state == GST_STATE_NULL) {
2011 gst_rtsp_media_unprepare (media);
2013 GST_INFO ("state %s media %p", gst_element_state_get_name (state),
2015 priv->target_state = state;
2016 /* when we are buffering, don't update the state yet, this will be done
2017 * when buffering finishes */
2018 if (priv->buffering) {
2019 GST_INFO ("Buffering busy, delay state change");
2021 gst_element_set_state (priv->pipeline, state);
2025 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
2029 /* remember where we are */
2030 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
2031 old_active != priv->n_active))
2032 collect_media_stats (media);
2034 g_rec_mutex_unlock (&priv->state_lock);
2041 GST_WARNING ("media %p was not prepared", media);
2042 g_rec_mutex_unlock (&priv->state_lock);