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
962 * @unit: the unit to use for the string
964 * Get the current range as a string. @media must be prepared with
965 * gst_rtsp_media_prepare ().
967 * Returns: The range as a string, g_free() after usage.
970 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
971 GstRTSPRangeUnit unit)
973 GstRTSPMediaPrivate *priv;
975 GstRTSPTimeRange range;
977 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
981 g_rec_mutex_lock (&priv->state_lock);
982 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
985 g_mutex_lock (&priv->lock);
989 if (!play && priv->n_active > 0) {
990 range.min.type = GST_RTSP_TIME_NOW;
991 range.min.seconds = -1;
993 g_mutex_unlock (&priv->lock);
994 g_rec_mutex_unlock (&priv->state_lock);
996 gst_rtsp_range_convert_units (&range, unit);
998 result = gst_rtsp_range_to_string (&range);
1005 GST_WARNING ("media %p was not prepared", media);
1006 g_rec_mutex_unlock (&priv->state_lock);
1012 * gst_rtsp_media_seek:
1013 * @media: a #GstRTSPMedia
1014 * @range: a #GstRTSPTimeRange
1016 * Seek the pipeline of @media to @range. @media must be prepared with
1017 * gst_rtsp_media_prepare().
1019 * Returns: %TRUE on success.
1022 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1024 GstRTSPMediaPrivate *priv;
1027 GstClockTime start, stop;
1028 GstSeekType start_type, stop_type;
1030 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1031 g_return_val_if_fail (range != NULL, FALSE);
1035 g_rec_mutex_lock (&priv->state_lock);
1036 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1039 if (!priv->seekable)
1042 /* depends on the current playing state of the pipeline. We might need to
1043 * queue this until we get EOS. */
1044 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
1046 start_type = stop_type = GST_SEEK_TYPE_NONE;
1048 if (!gst_rtsp_range_get_times (range, &start, &stop))
1051 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1052 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1053 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1054 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1056 if (priv->range_start == start)
1057 start = GST_CLOCK_TIME_NONE;
1058 else if (start != GST_CLOCK_TIME_NONE)
1059 start_type = GST_SEEK_TYPE_SET;
1061 if (priv->range_stop == stop)
1062 stop = GST_CLOCK_TIME_NONE;
1063 else if (stop != GST_CLOCK_TIME_NONE)
1064 stop_type = GST_SEEK_TYPE_SET;
1066 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1067 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1068 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1070 res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1071 flags, start_type, start, stop_type, stop);
1073 /* and block for the seek to complete */
1074 GST_INFO ("done seeking %d", res);
1075 gst_element_get_state (priv->pipeline, NULL, NULL, -1);
1076 GST_INFO ("prerolled again");
1078 collect_media_stats (media);
1080 GST_INFO ("no seek needed");
1083 g_rec_mutex_unlock (&priv->state_lock);
1090 g_rec_mutex_unlock (&priv->state_lock);
1091 GST_INFO ("media %p is not prepared", media);
1096 g_rec_mutex_unlock (&priv->state_lock);
1097 GST_INFO ("pipeline is not seekable");
1102 g_rec_mutex_unlock (&priv->state_lock);
1103 GST_WARNING ("seek unit %d not supported", range->unit);
1109 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1111 GstRTSPMediaPrivate *priv = media->priv;
1113 g_mutex_lock (&priv->lock);
1114 priv->status = status;
1115 GST_DEBUG ("setting new status to %d", status);
1116 g_cond_broadcast (&priv->cond);
1117 g_mutex_unlock (&priv->lock);
1121 * gst_rtsp_media_get_status:
1122 * @media: a #GstRTSPMedia
1124 * Get the status of @media. When @media is busy preparing, this function waits
1125 * until @media is prepared or in error.
1127 * Returns: the status of @media.
1130 gst_rtsp_media_get_status (GstRTSPMedia * media)
1132 GstRTSPMediaPrivate *priv = media->priv;
1133 GstRTSPMediaStatus result;
1136 g_mutex_lock (&priv->lock);
1137 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1138 /* while we are preparing, wait */
1139 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1140 GST_DEBUG ("waiting for status change");
1141 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1142 GST_DEBUG ("timeout, assuming error status");
1143 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1146 /* could be success or error */
1147 result = priv->status;
1148 GST_DEBUG ("got status %d", result);
1149 g_mutex_unlock (&priv->lock);
1154 /* called with state-lock */
1156 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1158 GstRTSPMediaPrivate *priv = media->priv;
1159 GstMessageType type;
1161 type = GST_MESSAGE_TYPE (message);
1164 case GST_MESSAGE_STATE_CHANGED:
1166 case GST_MESSAGE_BUFFERING:
1170 gst_message_parse_buffering (message, &percent);
1172 /* no state management needed for live pipelines */
1176 if (percent == 100) {
1177 /* a 100% message means buffering is done */
1178 priv->buffering = FALSE;
1179 /* if the desired state is playing, go back */
1180 if (priv->target_state == GST_STATE_PLAYING) {
1181 GST_INFO ("Buffering done, setting pipeline to PLAYING");
1182 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1184 GST_INFO ("Buffering done");
1187 /* buffering busy */
1188 if (priv->buffering == FALSE) {
1189 if (priv->target_state == GST_STATE_PLAYING) {
1190 /* we were not buffering but PLAYING, PAUSE the pipeline. */
1191 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1192 gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1194 GST_INFO ("Buffering ...");
1197 priv->buffering = TRUE;
1201 case GST_MESSAGE_LATENCY:
1203 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1206 case GST_MESSAGE_ERROR:
1211 gst_message_parse_error (message, &gerror, &debug);
1212 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1213 g_error_free (gerror);
1216 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1219 case GST_MESSAGE_WARNING:
1224 gst_message_parse_warning (message, &gerror, &debug);
1225 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1226 g_error_free (gerror);
1230 case GST_MESSAGE_ELEMENT:
1232 case GST_MESSAGE_STREAM_STATUS:
1234 case GST_MESSAGE_ASYNC_DONE:
1235 if (!priv->adding) {
1236 /* when we are dynamically adding pads, the addition of the udpsrc will
1237 * temporarily produce ASYNC_DONE messages. We have to ignore them and
1238 * wait for the final ASYNC_DONE after everything prerolled */
1239 GST_INFO ("%p: got ASYNC_DONE", media);
1240 collect_media_stats (media);
1242 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1243 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1245 GST_INFO ("%p: ignoring ASYNC_DONE", media);
1248 case GST_MESSAGE_EOS:
1249 GST_INFO ("%p: got EOS", media);
1251 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1252 GST_DEBUG ("shutting down after EOS");
1253 finish_unprepare (media);
1257 GST_INFO ("%p: got message type %d (%s)", media, type,
1258 gst_message_type_get_name (type));
1265 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1267 GstRTSPMediaPrivate *priv = media->priv;
1268 GstRTSPMediaClass *klass;
1271 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1273 g_rec_mutex_lock (&priv->state_lock);
1274 if (klass->handle_message)
1275 ret = klass->handle_message (media, message);
1278 g_rec_mutex_unlock (&priv->state_lock);
1284 watch_destroyed (GstRTSPMedia * media)
1286 GST_DEBUG_OBJECT (media, "source destroyed");
1287 g_object_unref (media);
1290 /* called from streaming threads */
1292 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1294 GstRTSPMediaPrivate *priv = media->priv;
1295 GstRTSPStream *stream;
1297 /* FIXME, element is likely not a payloader, find the payloader here */
1298 stream = gst_rtsp_media_create_stream (media, element, pad);
1300 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1302 g_rec_mutex_lock (&priv->state_lock);
1303 /* we will be adding elements below that will cause ASYNC_DONE to be
1304 * posted in the bus. We want to ignore those messages until the
1305 * pipeline really prerolled. */
1306 priv->adding = TRUE;
1308 /* join the element in the PAUSED state because this callback is
1309 * called from the streaming thread and it is PAUSED */
1310 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1311 priv->rtpbin, GST_STATE_PAUSED);
1313 priv->adding = FALSE;
1314 g_rec_mutex_unlock (&priv->state_lock);
1318 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1320 GstRTSPMediaPrivate *priv = media->priv;
1321 GstElement *fakesink;
1323 g_mutex_lock (&priv->lock);
1324 GST_INFO ("no more pads");
1325 if ((fakesink = priv->fakesink)) {
1326 gst_object_ref (fakesink);
1327 priv->fakesink = NULL;
1328 g_mutex_unlock (&priv->lock);
1330 gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1331 gst_element_set_state (fakesink, GST_STATE_NULL);
1332 gst_object_unref (fakesink);
1333 GST_INFO ("removed fakesink");
1338 * gst_rtsp_media_prepare:
1339 * @media: a #GstRTSPMedia
1341 * Prepare @media for streaming. This function will create the pipeline and
1342 * other objects to manage the streaming.
1344 * It will preroll the pipeline and collect vital information about the streams
1345 * such as the duration.
1347 * Returns: %TRUE on success.
1350 gst_rtsp_media_prepare (GstRTSPMedia * media)
1352 GstRTSPMediaPrivate *priv;
1353 GstStateChangeReturn ret;
1354 GstRTSPMediaStatus status;
1356 GstRTSPMediaClass *klass;
1360 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1364 g_rec_mutex_lock (&priv->state_lock);
1365 priv->prepare_count++;
1367 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1370 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1373 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1374 goto not_unprepared;
1376 if (!priv->reusable && priv->reused)
1379 priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1380 if (priv->rtpbin == NULL)
1383 GST_INFO ("preparing media %p", media);
1385 /* reset some variables */
1386 priv->is_live = FALSE;
1387 priv->seekable = FALSE;
1388 priv->buffering = FALSE;
1389 /* we're preparing now */
1390 priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1392 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
1394 /* add the pipeline bus to our custom mainloop */
1395 priv->source = gst_bus_create_watch (bus);
1396 gst_object_unref (bus);
1398 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
1399 g_object_ref (media), (GDestroyNotify) watch_destroyed);
1401 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1402 priv->id = g_source_attach (priv->source, klass->context);
1404 /* add stuff to the bin */
1405 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
1407 /* link streams we already have, other streams might appear when we have
1408 * dynamic elements */
1409 for (i = 0; i < priv->streams->len; i++) {
1410 GstRTSPStream *stream;
1412 stream = g_ptr_array_index (priv->streams, i);
1414 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1415 priv->rtpbin, GST_STATE_NULL);
1418 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1419 GstElement *elem = walk->data;
1421 GST_INFO ("adding callbacks for dynamic element %p", elem);
1423 g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1424 g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1426 /* we add a fakesink here in order to make the state change async. We remove
1427 * the fakesink again in the no-more-pads callback. */
1428 priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1429 gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
1432 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1433 /* first go to PAUSED */
1434 ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1435 priv->target_state = GST_STATE_PAUSED;
1438 case GST_STATE_CHANGE_SUCCESS:
1439 GST_INFO ("SUCCESS state change for media %p", media);
1440 priv->seekable = TRUE;
1442 case GST_STATE_CHANGE_ASYNC:
1443 GST_INFO ("ASYNC state change for media %p", media);
1444 priv->seekable = TRUE;
1446 case GST_STATE_CHANGE_NO_PREROLL:
1447 /* we need to go to PLAYING */
1448 GST_INFO ("NO_PREROLL state change: live media %p", media);
1449 /* FIXME we disable seeking for live streams for now. We should perform a
1450 * seeking query in preroll instead */
1451 priv->seekable = FALSE;
1452 priv->is_live = TRUE;
1453 ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1454 if (ret == GST_STATE_CHANGE_FAILURE)
1457 case GST_STATE_CHANGE_FAILURE:
1461 g_rec_mutex_unlock (&priv->state_lock);
1463 /* now wait for all pads to be prerolled, FIXME, we should somehow be
1464 * able to do this async so that we don't block the server thread. */
1465 status = gst_rtsp_media_get_status (media);
1466 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1469 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1471 GST_INFO ("object %p is prerolled", media);
1478 GST_LOG ("media %p was prepared", media);
1479 g_rec_mutex_unlock (&priv->state_lock);
1485 GST_WARNING ("media %p was not unprepared", media);
1486 priv->prepare_count--;
1487 g_rec_mutex_unlock (&priv->state_lock);
1492 priv->prepare_count--;
1493 g_rec_mutex_unlock (&priv->state_lock);
1494 GST_WARNING ("can not reuse media %p", media);
1499 priv->prepare_count--;
1500 g_rec_mutex_unlock (&priv->state_lock);
1501 GST_WARNING ("no rtpbin element");
1502 g_warning ("failed to create element 'rtpbin', check your installation");
1507 GST_WARNING ("failed to preroll pipeline");
1508 gst_rtsp_media_unprepare (media);
1509 g_rec_mutex_unlock (&priv->state_lock);
1514 /* must be called with state-lock */
1516 finish_unprepare (GstRTSPMedia * media)
1518 GstRTSPMediaPrivate *priv = media->priv;
1521 GST_DEBUG ("shutting down");
1523 gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1525 for (i = 0; i < priv->streams->len; i++) {
1526 GstRTSPStream *stream;
1528 GST_INFO ("Removing elements of stream %d from pipeline", i);
1530 stream = g_ptr_array_index (priv->streams, i);
1532 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1534 g_ptr_array_set_size (priv->streams, 0);
1536 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
1537 priv->rtpbin = NULL;
1539 gst_object_unref (priv->pipeline);
1540 priv->pipeline = NULL;
1542 priv->reused = TRUE;
1543 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1545 /* when the media is not reusable, this will effectively unref the media and
1547 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1549 /* the source has the last ref to the media */
1551 GST_DEBUG ("destroy source");
1552 g_source_destroy (priv->source);
1553 g_source_unref (priv->source);
1557 /* called with state-lock */
1559 default_unprepare (GstRTSPMedia * media)
1561 GstRTSPMediaPrivate *priv = media->priv;
1563 if (priv->eos_shutdown) {
1564 GST_DEBUG ("sending EOS for shutdown");
1565 /* ref so that we don't disappear */
1566 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
1567 /* we need to go to playing again for the EOS to propagate, normally in this
1568 * state, nothing is receiving data from us anymore so this is ok. */
1569 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1570 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1572 finish_unprepare (media);
1578 * gst_rtsp_media_unprepare:
1579 * @media: a #GstRTSPMedia
1581 * Unprepare @media. After this call, the media should be prepared again before
1582 * it can be used again. If the media is set to be non-reusable, a new instance
1585 * Returns: %TRUE on success.
1588 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1590 GstRTSPMediaPrivate *priv;
1593 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1597 g_rec_mutex_lock (&priv->state_lock);
1598 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1599 goto was_unprepared;
1601 priv->prepare_count--;
1602 if (priv->prepare_count > 0)
1605 GST_INFO ("unprepare media %p", media);
1606 priv->target_state = GST_STATE_NULL;
1609 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1610 GstRTSPMediaClass *klass;
1612 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1613 if (klass->unprepare)
1614 success = klass->unprepare (media);
1616 finish_unprepare (media);
1618 g_rec_mutex_unlock (&priv->state_lock);
1624 g_rec_mutex_unlock (&priv->state_lock);
1625 GST_INFO ("media %p was already unprepared", media);
1630 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
1631 g_rec_mutex_unlock (&priv->state_lock);
1637 * gst_rtsp_media_set_state:
1638 * @media: a #GstRTSPMedia
1639 * @state: the target state of the media
1640 * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
1642 * Set the state of @media to @state and for the transports in @transports.
1644 * @media must be prepared with gst_rtsp_media_prepare();
1646 * Returns: %TRUE on success.
1649 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1650 GPtrArray * transports)
1652 GstRTSPMediaPrivate *priv;
1654 gboolean activate, deactivate, do_state;
1657 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1658 g_return_val_if_fail (transports != NULL, FALSE);
1662 g_rec_mutex_lock (&priv->state_lock);
1663 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1666 /* NULL and READY are the same */
1667 if (state == GST_STATE_READY)
1668 state = GST_STATE_NULL;
1670 activate = deactivate = FALSE;
1672 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1676 case GST_STATE_NULL:
1677 case GST_STATE_PAUSED:
1678 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
1679 if (priv->target_state == GST_STATE_PLAYING)
1682 case GST_STATE_PLAYING:
1683 /* we're going to PLAYING, activate */
1689 old_active = priv->n_active;
1691 for (i = 0; i < transports->len; i++) {
1692 GstRTSPStreamTransport *trans;
1694 /* we need a non-NULL entry in the array */
1695 trans = g_ptr_array_index (transports, i);
1700 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
1702 } else if (deactivate) {
1703 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
1708 /* we just activated the first media, do the playing state change */
1709 if (old_active == 0 && activate)
1711 /* if we have no more active media, do the downward state changes */
1712 else if (priv->n_active == 0)
1717 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
1720 if (priv->target_state != state) {
1722 if (state == GST_STATE_NULL) {
1723 gst_rtsp_media_unprepare (media);
1725 GST_INFO ("state %s media %p", gst_element_state_get_name (state),
1727 priv->target_state = state;
1728 gst_element_set_state (priv->pipeline, state);
1731 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
1735 /* remember where we are */
1736 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
1737 old_active != priv->n_active))
1738 collect_media_stats (media);
1740 g_rec_mutex_unlock (&priv->state_lock);
1747 GST_WARNING ("media %p was not prepared", media);
1748 g_rec_mutex_unlock (&priv->state_lock);