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 */
64 GstState target_state;
66 /* RTP session manager */
69 /* the range of media */
70 GstRTSPTimeRange range; /* protected by lock */
71 GstClockTime range_start;
72 GstClockTime range_stop;
75 #define DEFAULT_SHARED FALSE
76 #define DEFAULT_REUSABLE FALSE
77 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
78 //#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP_MCAST
79 #define DEFAULT_EOS_SHUTDOWN FALSE
80 #define DEFAULT_BUFFER_SIZE 0x80000
82 /* define to dump received RTCP packets */
106 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
107 #define GST_CAT_DEFAULT rtsp_media_debug
109 static void gst_rtsp_media_get_property (GObject * object, guint propid,
110 GValue * value, GParamSpec * pspec);
111 static void gst_rtsp_media_set_property (GObject * object, guint propid,
112 const GValue * value, GParamSpec * pspec);
113 static void gst_rtsp_media_finalize (GObject * obj);
115 static gpointer do_loop (GstRTSPMediaClass * klass);
116 static gboolean default_handle_message (GstRTSPMedia * media,
117 GstMessage * message);
118 static void finish_unprepare (GstRTSPMedia * media);
119 static gboolean default_unprepare (GstRTSPMedia * media);
121 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
123 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
126 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
128 GObjectClass *gobject_class;
130 g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
132 gobject_class = G_OBJECT_CLASS (klass);
134 gobject_class->get_property = gst_rtsp_media_get_property;
135 gobject_class->set_property = gst_rtsp_media_set_property;
136 gobject_class->finalize = gst_rtsp_media_finalize;
138 g_object_class_install_property (gobject_class, PROP_SHARED,
139 g_param_spec_boolean ("shared", "Shared",
140 "If this media pipeline can be shared", DEFAULT_SHARED,
141 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
143 g_object_class_install_property (gobject_class, PROP_REUSABLE,
144 g_param_spec_boolean ("reusable", "Reusable",
145 "If this media pipeline can be reused after an unprepare",
146 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
148 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
149 g_param_spec_flags ("protocols", "Protocols",
150 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
151 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
154 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
155 "Send an EOS event to the pipeline before unpreparing",
156 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
158 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
159 g_param_spec_uint ("buffer-size", "Buffer Size",
160 "The kernel UDP buffer size to use", 0, G_MAXUINT,
161 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
163 g_object_class_install_property (gobject_class, PROP_ELEMENT,
164 g_param_spec_object ("element", "The Element",
165 "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
166 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
168 gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
169 g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
170 G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
171 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
173 gst_rtsp_media_signals[SIGNAL_PREPARED] =
174 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
175 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
176 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
178 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
179 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
180 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
181 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
183 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
184 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
185 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
186 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 0, G_TYPE_INT);
188 klass->context = g_main_context_new ();
189 klass->loop = g_main_loop_new (klass->context, TRUE);
191 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
193 klass->thread = g_thread_new ("Bus Thread", (GThreadFunc) do_loop, klass);
195 klass->handle_message = default_handle_message;
196 klass->unprepare = default_unprepare;
200 gst_rtsp_media_init (GstRTSPMedia * media)
202 GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
206 priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
207 g_mutex_init (&priv->lock);
208 g_cond_init (&priv->cond);
209 g_rec_mutex_init (&priv->state_lock);
211 priv->shared = DEFAULT_SHARED;
212 priv->reusable = DEFAULT_REUSABLE;
213 priv->protocols = DEFAULT_PROTOCOLS;
214 priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
215 priv->buffer_size = DEFAULT_BUFFER_SIZE;
219 gst_rtsp_media_finalize (GObject * obj)
221 GstRTSPMediaPrivate *priv;
224 media = GST_RTSP_MEDIA (obj);
227 GST_INFO ("finalize media %p", media);
229 g_ptr_array_unref (priv->streams);
231 g_list_free_full (priv->dynamic, gst_object_unref);
234 gst_object_unref (priv->pipeline);
235 gst_object_unref (priv->element);
237 g_object_unref (priv->auth);
239 g_object_unref (priv->pool);
240 g_mutex_clear (&priv->lock);
241 g_cond_clear (&priv->cond);
242 g_rec_mutex_clear (&priv->state_lock);
244 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
248 gst_rtsp_media_get_property (GObject * object, guint propid,
249 GValue * value, GParamSpec * pspec)
251 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
255 g_value_set_object (value, media->priv->element);
258 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
261 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
264 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
266 case PROP_EOS_SHUTDOWN:
267 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
269 case PROP_BUFFER_SIZE:
270 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
273 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
278 gst_rtsp_media_set_property (GObject * object, guint propid,
279 const GValue * value, GParamSpec * pspec)
281 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
285 media->priv->element = g_value_get_object (value);
288 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
291 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
294 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
296 case PROP_EOS_SHUTDOWN:
297 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
299 case PROP_BUFFER_SIZE:
300 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
303 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
308 do_loop (GstRTSPMediaClass * klass)
310 GST_INFO ("enter mainloop");
311 g_main_loop_run (klass->loop);
312 GST_INFO ("exit mainloop");
317 /* must be called with state lock */
319 collect_media_stats (GstRTSPMedia * media)
321 GstRTSPMediaPrivate *priv = media->priv;
322 gint64 position, duration;
324 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
325 priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
328 priv->range.unit = GST_RTSP_RANGE_NPT;
330 GST_INFO ("collect media stats");
333 priv->range.min.type = GST_RTSP_TIME_NOW;
334 priv->range.min.seconds = -1;
335 priv->range_start = -1;
336 priv->range.max.type = GST_RTSP_TIME_END;
337 priv->range.max.seconds = -1;
338 priv->range_stop = -1;
340 /* get the position */
341 if (!gst_element_query_position (priv->pipeline, GST_FORMAT_TIME,
343 GST_INFO ("position query failed");
347 /* get the duration */
348 if (!gst_element_query_duration (priv->pipeline, GST_FORMAT_TIME,
350 GST_INFO ("duration query failed");
354 GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
355 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
357 if (position == -1) {
358 priv->range.min.type = GST_RTSP_TIME_NOW;
359 priv->range.min.seconds = -1;
360 priv->range_start = -1;
362 priv->range.min.type = GST_RTSP_TIME_SECONDS;
363 priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
364 priv->range_start = position;
366 if (duration == -1) {
367 priv->range.max.type = GST_RTSP_TIME_END;
368 priv->range.max.seconds = -1;
369 priv->range_stop = -1;
371 priv->range.max.type = GST_RTSP_TIME_SECONDS;
372 priv->range.max.seconds = ((gdouble) duration) / GST_SECOND;
373 priv->range_stop = duration;
379 * gst_rtsp_media_new:
380 * @element: (transfer full): a #GstElement
382 * Create a new #GstRTSPMedia instance. @element is the bin element that
383 * provides the different streams. The #GstRTSPMedia object contains the
384 * element to produce RTP data for one or more related (audio/video/..)
387 * Ownership is taken of @element.
389 * Returns: a new #GstRTSPMedia object.
392 gst_rtsp_media_new (GstElement * element)
394 GstRTSPMedia *result;
396 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
398 result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
404 * gst_rtsp_media_take_element:
405 * @media: a #GstRTSPMedia
406 * @pipeline: (transfer full): a #GstPipeline
408 * Set @pipeline as the #GstPipeline for @media. Ownership is
409 * taken of @pipeline.
412 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
414 GstRTSPMediaPrivate *priv;
417 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
418 g_return_if_fail (GST_IS_PIPELINE (pipeline));
422 g_mutex_lock (&priv->lock);
423 old = priv->pipeline;
424 priv->pipeline = GST_ELEMENT_CAST (pipeline);
425 g_mutex_unlock (&priv->lock);
428 gst_object_unref (old);
430 gst_object_ref (priv->element);
431 gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
435 * gst_rtsp_media_set_shared:
436 * @media: a #GstRTSPMedia
437 * @shared: the new value
439 * Set or unset if the pipeline for @media can be shared will multiple clients.
440 * When @shared is %TRUE, client requests for this media will share the media
444 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
446 GstRTSPMediaPrivate *priv;
448 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
452 g_mutex_lock (&priv->lock);
453 priv->shared = shared;
454 g_mutex_unlock (&priv->lock);
458 * gst_rtsp_media_is_shared:
459 * @media: a #GstRTSPMedia
461 * Check if the pipeline for @media can be shared between multiple clients.
463 * Returns: %TRUE if the media can be shared between clients.
466 gst_rtsp_media_is_shared (GstRTSPMedia * media)
468 GstRTSPMediaPrivate *priv;
471 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
475 g_mutex_lock (&priv->lock);
477 g_mutex_unlock (&priv->lock);
483 * gst_rtsp_media_set_reusable:
484 * @media: a #GstRTSPMedia
485 * @reusable: the new value
487 * Set or unset if the pipeline for @media can be reused after the pipeline has
491 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
493 GstRTSPMediaPrivate *priv;
495 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
499 g_mutex_lock (&priv->lock);
500 priv->reusable = reusable;
501 g_mutex_unlock (&priv->lock);
505 * gst_rtsp_media_is_reusable:
506 * @media: a #GstRTSPMedia
508 * Check if the pipeline for @media can be reused after an unprepare.
510 * Returns: %TRUE if the media can be reused
513 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
515 GstRTSPMediaPrivate *priv;
518 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
522 g_mutex_lock (&priv->lock);
523 res = priv->reusable;
524 g_mutex_unlock (&priv->lock);
530 * gst_rtsp_media_set_protocols:
531 * @media: a #GstRTSPMedia
532 * @protocols: the new flags
534 * Configure the allowed lower transport for @media.
537 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
539 GstRTSPMediaPrivate *priv;
541 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
545 g_mutex_lock (&priv->lock);
546 priv->protocols = protocols;
547 g_mutex_unlock (&priv->lock);
551 * gst_rtsp_media_get_protocols:
552 * @media: a #GstRTSPMedia
554 * Get the allowed protocols of @media.
556 * Returns: a #GstRTSPLowerTrans
559 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
561 GstRTSPMediaPrivate *priv;
562 GstRTSPLowerTrans res;
564 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
565 GST_RTSP_LOWER_TRANS_UNKNOWN);
569 g_mutex_lock (&priv->lock);
570 res = priv->protocols;
571 g_mutex_unlock (&priv->lock);
577 * gst_rtsp_media_set_eos_shutdown:
578 * @media: a #GstRTSPMedia
579 * @eos_shutdown: the new value
581 * Set or unset if an EOS event will be sent to the pipeline for @media before
585 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
587 GstRTSPMediaPrivate *priv;
589 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
593 g_mutex_lock (&priv->lock);
594 priv->eos_shutdown = eos_shutdown;
595 g_mutex_unlock (&priv->lock);
599 * gst_rtsp_media_is_eos_shutdown:
600 * @media: a #GstRTSPMedia
602 * Check if the pipeline for @media will send an EOS down the pipeline before
605 * Returns: %TRUE if the media will send EOS before unpreparing.
608 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
610 GstRTSPMediaPrivate *priv;
613 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
617 g_mutex_lock (&priv->lock);
618 res = priv->eos_shutdown;
619 g_mutex_unlock (&priv->lock);
625 * gst_rtsp_media_set_buffer_size:
626 * @media: a #GstRTSPMedia
627 * @size: the new value
629 * Set the kernel UDP buffer size.
632 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
634 GstRTSPMediaPrivate *priv;
636 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
638 GST_LOG_OBJECT (media, "set buffer size %u", size);
642 g_mutex_lock (&priv->lock);
643 priv->buffer_size = size;
644 g_mutex_unlock (&priv->lock);
648 * gst_rtsp_media_get_buffer_size:
649 * @media: a #GstRTSPMedia
651 * Get the kernel UDP buffer size.
653 * Returns: the kernel UDP buffer size.
656 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
658 GstRTSPMediaPrivate *priv;
661 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
665 g_mutex_unlock (&priv->lock);
666 res = priv->buffer_size;
667 g_mutex_unlock (&priv->lock);
673 * gst_rtsp_media_set_auth:
674 * @media: a #GstRTSPMedia
675 * @auth: a #GstRTSPAuth
677 * configure @auth to be used as the authentication manager of @media.
680 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
682 GstRTSPMediaPrivate *priv;
685 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
689 GST_LOG_OBJECT (media, "set auth %p", auth);
691 g_mutex_lock (&priv->lock);
692 if ((old = priv->auth) != auth)
693 priv->auth = auth ? g_object_ref (auth) : NULL;
696 g_mutex_unlock (&priv->lock);
699 g_object_unref (old);
703 * gst_rtsp_media_get_auth:
704 * @media: a #GstRTSPMedia
706 * Get the #GstRTSPAuth used as the authentication manager of @media.
708 * Returns: (transfer full): the #GstRTSPAuth of @media. g_object_unref() after
712 gst_rtsp_media_get_auth (GstRTSPMedia * media)
714 GstRTSPMediaPrivate *priv;
717 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
721 g_mutex_lock (&priv->lock);
722 if ((result = priv->auth))
723 g_object_ref (result);
724 g_mutex_unlock (&priv->lock);
730 * gst_rtsp_media_set_address_pool:
731 * @media: a #GstRTSPMedia
732 * @pool: a #GstRTSPAddressPool
734 * configure @pool to be used as the address pool of @media.
737 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
738 GstRTSPAddressPool * pool)
740 GstRTSPMediaPrivate *priv;
741 GstRTSPAddressPool *old;
743 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
747 GST_LOG_OBJECT (media, "set address pool %p", pool);
749 g_mutex_lock (&priv->lock);
750 if ((old = priv->pool) != pool)
751 priv->pool = pool ? g_object_ref (pool) : NULL;
754 g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
756 g_mutex_unlock (&priv->lock);
759 g_object_unref (old);
763 * gst_rtsp_media_get_address_pool:
764 * @media: a #GstRTSPMedia
766 * Get the #GstRTSPAddressPool used as the address pool of @media.
768 * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
772 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
774 GstRTSPMediaPrivate *priv;
775 GstRTSPAddressPool *result;
777 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
781 g_mutex_lock (&priv->lock);
782 if ((result = priv->pool))
783 g_object_ref (result);
784 g_mutex_unlock (&priv->lock);
790 * gst_rtsp_media_collect_streams:
791 * @media: a #GstRTSPMedia
793 * Find all payloader elements, they should be named pay%d in the
794 * element of @media, and create #GstRTSPStreams for them.
796 * Collect all dynamic elements, named dynpay%d, and add them to
797 * the list of dynamic elements.
800 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
802 GstRTSPMediaPrivate *priv;
803 GstElement *element, *elem;
808 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
811 element = priv->element;
814 for (i = 0; have_elem; i++) {
819 name = g_strdup_printf ("pay%d", i);
820 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
821 GST_INFO ("found stream %d with payloader %p", i, elem);
823 /* take the pad of the payloader */
824 pad = gst_element_get_static_pad (elem, "src");
825 /* create the stream */
826 gst_rtsp_media_create_stream (media, elem, pad);
827 gst_object_unref (pad);
828 gst_object_unref (elem);
834 name = g_strdup_printf ("dynpay%d", i);
835 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
836 /* a stream that will dynamically create pads to provide RTP packets */
838 GST_INFO ("found dynamic element %d, %p", i, elem);
840 g_mutex_lock (&priv->lock);
841 priv->dynamic = g_list_prepend (priv->dynamic, elem);
842 g_mutex_unlock (&priv->lock);
851 * gst_rtsp_media_create_stream:
852 * @media: a #GstRTSPMedia
853 * @payloader: a #GstElement
854 * @srcpad: a source #GstPad
856 * Create a new stream in @media that provides RTP data on @srcpad.
857 * @srcpad should be a pad of an element inside @media->element.
859 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
863 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
866 GstRTSPMediaPrivate *priv;
867 GstRTSPStream *stream;
872 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
873 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
874 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
875 g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
879 g_mutex_lock (&priv->lock);
880 idx = priv->streams->len;
882 GST_DEBUG ("media %p: creating stream with index %d", media, idx);
884 name = g_strdup_printf ("src_%u", idx);
885 srcpad = gst_ghost_pad_new (name, pad);
886 gst_pad_set_active (srcpad, TRUE);
887 gst_element_add_pad (priv->element, srcpad);
890 stream = gst_rtsp_stream_new (idx, payloader, srcpad);
892 gst_rtsp_stream_set_address_pool (stream, priv->pool);
894 g_ptr_array_add (priv->streams, stream);
895 g_mutex_unlock (&priv->lock);
897 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
904 * gst_rtsp_media_n_streams:
905 * @media: a #GstRTSPMedia
907 * Get the number of streams in this media.
909 * Returns: The number of streams.
912 gst_rtsp_media_n_streams (GstRTSPMedia * media)
914 GstRTSPMediaPrivate *priv;
917 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
921 g_mutex_lock (&priv->lock);
922 res = priv->streams->len;
923 g_mutex_unlock (&priv->lock);
929 * gst_rtsp_media_get_stream:
930 * @media: a #GstRTSPMedia
931 * @idx: the stream index
933 * Retrieve the stream with index @idx from @media.
935 * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
936 * that index did not exist.
939 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
941 GstRTSPMediaPrivate *priv;
944 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
948 g_mutex_lock (&priv->lock);
949 if (idx < priv->streams->len)
950 res = g_ptr_array_index (priv->streams, idx);
953 g_mutex_unlock (&priv->lock);
959 * gst_rtsp_media_get_range_string:
960 * @media: a #GstRTSPMedia
961 * @play: for the PLAY request
963 * Get the current range as a string. @media must be prepared with
964 * gst_rtsp_media_prepare ().
966 * Returns: The range as a string, g_free() after usage.
969 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
971 GstRTSPMediaPrivate *priv;
973 GstRTSPTimeRange range;
975 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
979 g_rec_mutex_lock (&priv->state_lock);
980 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
983 g_mutex_lock (&priv->lock);
987 if (!play && priv->n_active > 0) {
988 range.min.type = GST_RTSP_TIME_NOW;
989 range.min.seconds = -1;
991 g_mutex_unlock (&priv->lock);
992 g_rec_mutex_unlock (&priv->state_lock);
994 result = gst_rtsp_range_to_string (&range);
1001 GST_WARNING ("media %p was not prepared", media);
1002 g_rec_mutex_unlock (&priv->state_lock);
1008 * gst_rtsp_media_seek:
1009 * @media: a #GstRTSPMedia
1010 * @range: a #GstRTSPTimeRange
1012 * Seek the pipeline of @media to @range. @media must be prepared with
1013 * gst_rtsp_media_prepare().
1015 * Returns: %TRUE on success.
1018 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1020 GstRTSPMediaPrivate *priv;
1023 GstClockTime start, stop;
1024 GstSeekType start_type, stop_type;
1026 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1027 g_return_val_if_fail (range != NULL, FALSE);
1031 g_rec_mutex_lock (&priv->state_lock);
1032 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1035 if (!priv->seekable)
1038 /* depends on the current playing state of the pipeline. We might need to
1039 * queue this until we get EOS. */
1040 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
1042 start_type = stop_type = GST_SEEK_TYPE_NONE;
1044 if (!gst_rtsp_range_get_times (range, &start, &stop))
1047 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1048 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1049 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1050 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1052 if (priv->range_start == start)
1053 start = GST_CLOCK_TIME_NONE;
1054 else if (start != GST_CLOCK_TIME_NONE)
1055 start_type = GST_SEEK_TYPE_SET;
1057 if (priv->range_stop == stop)
1058 stop = GST_CLOCK_TIME_NONE;
1059 else if (stop != GST_CLOCK_TIME_NONE)
1060 stop_type = GST_SEEK_TYPE_SET;
1062 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1063 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1064 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1066 res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1067 flags, start_type, start, stop_type, stop);
1069 /* and block for the seek to complete */
1070 GST_INFO ("done seeking %d", res);
1071 gst_element_get_state (priv->pipeline, NULL, NULL, -1);
1072 GST_INFO ("prerolled again");
1074 collect_media_stats (media);
1076 GST_INFO ("no seek needed");
1079 g_rec_mutex_unlock (&priv->state_lock);
1086 g_rec_mutex_unlock (&priv->state_lock);
1087 GST_INFO ("media %p is not prepared", media);
1092 g_rec_mutex_unlock (&priv->state_lock);
1093 GST_INFO ("pipeline is not seekable");
1098 g_rec_mutex_unlock (&priv->state_lock);
1099 GST_WARNING ("seek unit %d not supported", range->unit);
1105 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1107 GstRTSPMediaPrivate *priv = media->priv;
1109 g_mutex_lock (&priv->lock);
1110 priv->status = status;
1111 GST_DEBUG ("setting new status to %d", status);
1112 g_cond_broadcast (&priv->cond);
1113 g_mutex_unlock (&priv->lock);
1117 * gst_rtsp_media_get_status:
1118 * @media: a #GstRTSPMedia
1120 * Get the status of @media. When @media is busy preparing, this function waits
1121 * until @media is prepared or in error.
1123 * Returns: the status of @media.
1126 gst_rtsp_media_get_status (GstRTSPMedia * media)
1128 GstRTSPMediaPrivate *priv = media->priv;
1129 GstRTSPMediaStatus result;
1132 g_mutex_lock (&priv->lock);
1133 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1134 /* while we are preparing, wait */
1135 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1136 GST_DEBUG ("waiting for status change");
1137 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1138 GST_DEBUG ("timeout, assuming error status");
1139 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1142 /* could be success or error */
1143 result = priv->status;
1144 GST_DEBUG ("got status %d", result);
1145 g_mutex_unlock (&priv->lock);
1150 /* called with state-lock */
1152 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1154 GstRTSPMediaPrivate *priv = media->priv;
1155 GstMessageType type;
1157 type = GST_MESSAGE_TYPE (message);
1160 case GST_MESSAGE_STATE_CHANGED:
1162 case GST_MESSAGE_BUFFERING:
1166 gst_message_parse_buffering (message, &percent);
1168 /* no state management needed for live pipelines */
1172 if (percent == 100) {
1173 /* a 100% message means buffering is done */
1174 priv->buffering = FALSE;
1175 /* if the desired state is playing, go back */
1176 if (priv->target_state == GST_STATE_PLAYING) {
1177 GST_INFO ("Buffering done, setting pipeline to PLAYING");
1178 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1180 GST_INFO ("Buffering done");
1183 /* buffering busy */
1184 if (priv->buffering == FALSE) {
1185 if (priv->target_state == GST_STATE_PLAYING) {
1186 /* we were not buffering but PLAYING, PAUSE the pipeline. */
1187 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1188 gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1190 GST_INFO ("Buffering ...");
1193 priv->buffering = TRUE;
1197 case GST_MESSAGE_LATENCY:
1199 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1202 case GST_MESSAGE_ERROR:
1207 gst_message_parse_error (message, &gerror, &debug);
1208 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1209 g_error_free (gerror);
1212 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1215 case GST_MESSAGE_WARNING:
1220 gst_message_parse_warning (message, &gerror, &debug);
1221 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1222 g_error_free (gerror);
1226 case GST_MESSAGE_ELEMENT:
1228 case GST_MESSAGE_STREAM_STATUS:
1230 case GST_MESSAGE_ASYNC_DONE:
1231 if (!priv->adding) {
1232 /* when we are dynamically adding pads, the addition of the udpsrc will
1233 * temporarily produce ASYNC_DONE messages. We have to ignore them and
1234 * wait for the final ASYNC_DONE after everything prerolled */
1235 GST_INFO ("%p: got ASYNC_DONE", media);
1236 collect_media_stats (media);
1238 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1239 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1241 GST_INFO ("%p: ignoring ASYNC_DONE", media);
1244 case GST_MESSAGE_EOS:
1245 GST_INFO ("%p: got EOS", media);
1247 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1248 GST_DEBUG ("shutting down after EOS");
1249 finish_unprepare (media);
1253 GST_INFO ("%p: got message type %d (%s)", media, type,
1254 gst_message_type_get_name (type));
1261 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1263 GstRTSPMediaPrivate *priv = media->priv;
1264 GstRTSPMediaClass *klass;
1267 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1269 g_rec_mutex_lock (&priv->state_lock);
1270 if (klass->handle_message)
1271 ret = klass->handle_message (media, message);
1274 g_rec_mutex_unlock (&priv->state_lock);
1280 watch_destroyed (GstRTSPMedia * media)
1282 GST_DEBUG_OBJECT (media, "source destroyed");
1283 g_object_unref (media);
1286 /* called from streaming threads */
1288 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1290 GstRTSPMediaPrivate *priv = media->priv;
1291 GstRTSPStream *stream;
1293 /* FIXME, element is likely not a payloader, find the payloader here */
1294 stream = gst_rtsp_media_create_stream (media, element, pad);
1296 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1298 g_rec_mutex_lock (&priv->state_lock);
1299 /* we will be adding elements below that will cause ASYNC_DONE to be
1300 * posted in the bus. We want to ignore those messages until the
1301 * pipeline really prerolled. */
1302 priv->adding = TRUE;
1304 /* join the element in the PAUSED state because this callback is
1305 * called from the streaming thread and it is PAUSED */
1306 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1307 priv->rtpbin, GST_STATE_PAUSED);
1309 priv->adding = FALSE;
1310 g_rec_mutex_unlock (&priv->state_lock);
1314 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1316 GstRTSPMediaPrivate *priv = media->priv;
1317 GstElement *fakesink;
1319 g_mutex_lock (&priv->lock);
1320 GST_INFO ("no more pads");
1321 if ((fakesink = priv->fakesink)) {
1322 gst_object_ref (fakesink);
1323 priv->fakesink = NULL;
1324 g_mutex_unlock (&priv->lock);
1326 gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1327 gst_element_set_state (fakesink, GST_STATE_NULL);
1328 gst_object_unref (fakesink);
1329 GST_INFO ("removed fakesink");
1334 * gst_rtsp_media_prepare:
1335 * @media: a #GstRTSPMedia
1337 * Prepare @media for streaming. This function will create the pipeline and
1338 * other objects to manage the streaming.
1340 * It will preroll the pipeline and collect vital information about the streams
1341 * such as the duration.
1343 * Returns: %TRUE on success.
1346 gst_rtsp_media_prepare (GstRTSPMedia * media)
1348 GstRTSPMediaPrivate *priv;
1349 GstStateChangeReturn ret;
1350 GstRTSPMediaStatus status;
1352 GstRTSPMediaClass *klass;
1356 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1360 g_rec_mutex_lock (&priv->state_lock);
1361 priv->prepare_count++;
1363 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1366 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1369 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1370 goto not_unprepared;
1372 if (!priv->reusable && priv->reused)
1375 priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1376 if (priv->rtpbin == NULL)
1379 GST_INFO ("preparing media %p", media);
1381 /* reset some variables */
1382 priv->is_live = FALSE;
1383 priv->seekable = FALSE;
1384 priv->buffering = FALSE;
1385 /* we're preparing now */
1386 priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1388 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
1390 /* add the pipeline bus to our custom mainloop */
1391 priv->source = gst_bus_create_watch (bus);
1392 gst_object_unref (bus);
1394 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
1395 g_object_ref (media), (GDestroyNotify) watch_destroyed);
1397 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1398 priv->id = g_source_attach (priv->source, klass->context);
1400 /* add stuff to the bin */
1401 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
1403 /* link streams we already have, other streams might appear when we have
1404 * dynamic elements */
1405 for (i = 0; i < priv->streams->len; i++) {
1406 GstRTSPStream *stream;
1408 stream = g_ptr_array_index (priv->streams, i);
1410 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1411 priv->rtpbin, GST_STATE_NULL);
1414 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1415 GstElement *elem = walk->data;
1417 GST_INFO ("adding callbacks for dynamic element %p", elem);
1419 g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1420 g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1422 /* we add a fakesink here in order to make the state change async. We remove
1423 * the fakesink again in the no-more-pads callback. */
1424 priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1425 gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
1428 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1429 /* first go to PAUSED */
1430 ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1431 priv->target_state = GST_STATE_PAUSED;
1434 case GST_STATE_CHANGE_SUCCESS:
1435 GST_INFO ("SUCCESS state change for media %p", media);
1436 priv->seekable = TRUE;
1438 case GST_STATE_CHANGE_ASYNC:
1439 GST_INFO ("ASYNC state change for media %p", media);
1440 priv->seekable = TRUE;
1442 case GST_STATE_CHANGE_NO_PREROLL:
1443 /* we need to go to PLAYING */
1444 GST_INFO ("NO_PREROLL state change: live media %p", media);
1445 /* FIXME we disable seeking for live streams for now. We should perform a
1446 * seeking query in preroll instead */
1447 priv->seekable = FALSE;
1448 priv->is_live = TRUE;
1449 ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1450 if (ret == GST_STATE_CHANGE_FAILURE)
1453 case GST_STATE_CHANGE_FAILURE:
1457 g_rec_mutex_unlock (&priv->state_lock);
1459 /* now wait for all pads to be prerolled, FIXME, we should somehow be
1460 * able to do this async so that we don't block the server thread. */
1461 status = gst_rtsp_media_get_status (media);
1462 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1465 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1467 GST_INFO ("object %p is prerolled", media);
1474 GST_LOG ("media %p was prepared", media);
1475 g_rec_mutex_unlock (&priv->state_lock);
1481 GST_WARNING ("media %p was not unprepared", media);
1482 priv->prepare_count--;
1483 g_rec_mutex_unlock (&priv->state_lock);
1488 priv->prepare_count--;
1489 g_rec_mutex_unlock (&priv->state_lock);
1490 GST_WARNING ("can not reuse media %p", media);
1495 priv->prepare_count--;
1496 g_rec_mutex_unlock (&priv->state_lock);
1497 GST_WARNING ("no rtpbin element");
1498 g_warning ("failed to create element 'rtpbin', check your installation");
1503 GST_WARNING ("failed to preroll pipeline");
1504 gst_rtsp_media_unprepare (media);
1505 g_rec_mutex_unlock (&priv->state_lock);
1510 /* must be called with state-lock */
1512 finish_unprepare (GstRTSPMedia * media)
1514 GstRTSPMediaPrivate *priv = media->priv;
1517 GST_DEBUG ("shutting down");
1519 gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1521 for (i = 0; i < priv->streams->len; i++) {
1522 GstRTSPStream *stream;
1524 GST_INFO ("Removing elements of stream %d from pipeline", i);
1526 stream = g_ptr_array_index (priv->streams, i);
1528 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1530 g_ptr_array_set_size (priv->streams, 0);
1532 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
1533 priv->rtpbin = NULL;
1535 gst_object_unref (priv->pipeline);
1536 priv->pipeline = NULL;
1538 priv->reused = TRUE;
1539 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1541 /* when the media is not reusable, this will effectively unref the media and
1543 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1545 /* the source has the last ref to the media */
1547 GST_DEBUG ("destroy source");
1548 g_source_destroy (priv->source);
1549 g_source_unref (priv->source);
1553 /* called with state-lock */
1555 default_unprepare (GstRTSPMedia * media)
1557 GstRTSPMediaPrivate *priv = media->priv;
1559 if (priv->eos_shutdown) {
1560 GST_DEBUG ("sending EOS for shutdown");
1561 /* ref so that we don't disappear */
1562 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
1563 /* we need to go to playing again for the EOS to propagate, normally in this
1564 * state, nothing is receiving data from us anymore so this is ok. */
1565 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1566 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1568 finish_unprepare (media);
1574 * gst_rtsp_media_unprepare:
1575 * @media: a #GstRTSPMedia
1577 * Unprepare @media. After this call, the media should be prepared again before
1578 * it can be used again. If the media is set to be non-reusable, a new instance
1581 * Returns: %TRUE on success.
1584 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1586 GstRTSPMediaPrivate *priv;
1589 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1593 g_rec_mutex_lock (&priv->state_lock);
1594 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1595 goto was_unprepared;
1597 priv->prepare_count--;
1598 if (priv->prepare_count > 0)
1601 GST_INFO ("unprepare media %p", media);
1602 priv->target_state = GST_STATE_NULL;
1605 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1606 GstRTSPMediaClass *klass;
1608 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1609 if (klass->unprepare)
1610 success = klass->unprepare (media);
1612 finish_unprepare (media);
1614 g_rec_mutex_unlock (&priv->state_lock);
1620 g_rec_mutex_unlock (&priv->state_lock);
1621 GST_INFO ("media %p was already unprepared", media);
1626 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
1627 g_rec_mutex_unlock (&priv->state_lock);
1633 * gst_rtsp_media_set_state:
1634 * @media: a #GstRTSPMedia
1635 * @state: the target state of the media
1636 * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
1638 * Set the state of @media to @state and for the transports in @transports.
1640 * @media must be prepared with gst_rtsp_media_prepare();
1642 * Returns: %TRUE on success.
1645 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1646 GPtrArray * transports)
1648 GstRTSPMediaPrivate *priv;
1650 gboolean activate, deactivate, do_state;
1653 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1654 g_return_val_if_fail (transports != NULL, FALSE);
1658 g_rec_mutex_lock (&priv->state_lock);
1659 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1662 /* NULL and READY are the same */
1663 if (state == GST_STATE_READY)
1664 state = GST_STATE_NULL;
1666 activate = deactivate = FALSE;
1668 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1672 case GST_STATE_NULL:
1673 case GST_STATE_PAUSED:
1674 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
1675 if (priv->target_state == GST_STATE_PLAYING)
1678 case GST_STATE_PLAYING:
1679 /* we're going to PLAYING, activate */
1685 old_active = priv->n_active;
1687 for (i = 0; i < transports->len; i++) {
1688 GstRTSPStreamTransport *trans;
1690 /* we need a non-NULL entry in the array */
1691 trans = g_ptr_array_index (transports, i);
1696 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
1698 } else if (deactivate) {
1699 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
1704 /* we just activated the first media, do the playing state change */
1705 if (old_active == 0 && activate)
1707 /* if we have no more active media, do the downward state changes */
1708 else if (priv->n_active == 0)
1713 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
1716 if (priv->target_state != state) {
1718 if (state == GST_STATE_NULL) {
1719 gst_rtsp_media_unprepare (media);
1721 GST_INFO ("state %s media %p", gst_element_state_get_name (state),
1723 priv->target_state = state;
1724 gst_element_set_state (priv->pipeline, state);
1727 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
1731 /* remember where we are */
1732 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
1733 old_active != priv->n_active))
1734 collect_media_stats (media);
1736 g_rec_mutex_unlock (&priv->state_lock);
1743 GST_WARNING ("media %p was not prepared", media);
1744 g_rec_mutex_unlock (&priv->state_lock);