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
38 GstRTSPLowerTrans protocols;
40 gboolean eos_shutdown;
43 GstRTSPAddressPool *pool;
49 GstRTSPMediaStatus status;
54 /* the pipeline for the media */
63 GstState target_state;
65 /* RTP session manager */
68 /* the range of media */
69 GstRTSPTimeRange range;
70 GstClockTime range_start;
71 GstClockTime range_stop;
74 #define DEFAULT_SHARED FALSE
75 #define DEFAULT_REUSABLE FALSE
76 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
77 //#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP_MCAST
78 #define DEFAULT_EOS_SHUTDOWN FALSE
79 #define DEFAULT_BUFFER_SIZE 0x80000
81 /* define to dump received RTCP packets */
105 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
106 #define GST_CAT_DEFAULT rtsp_media_debug
108 static void gst_rtsp_media_get_property (GObject * object, guint propid,
109 GValue * value, GParamSpec * pspec);
110 static void gst_rtsp_media_set_property (GObject * object, guint propid,
111 const GValue * value, GParamSpec * pspec);
112 static void gst_rtsp_media_finalize (GObject * obj);
114 static gpointer do_loop (GstRTSPMediaClass * klass);
115 static gboolean default_handle_message (GstRTSPMedia * media,
116 GstMessage * message);
117 static void finish_unprepare (GstRTSPMedia * media);
118 static gboolean default_unprepare (GstRTSPMedia * media);
120 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
122 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
125 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
127 GObjectClass *gobject_class;
129 g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
131 gobject_class = G_OBJECT_CLASS (klass);
133 gobject_class->get_property = gst_rtsp_media_get_property;
134 gobject_class->set_property = gst_rtsp_media_set_property;
135 gobject_class->finalize = gst_rtsp_media_finalize;
137 g_object_class_install_property (gobject_class, PROP_SHARED,
138 g_param_spec_boolean ("shared", "Shared",
139 "If this media pipeline can be shared", DEFAULT_SHARED,
140 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
142 g_object_class_install_property (gobject_class, PROP_REUSABLE,
143 g_param_spec_boolean ("reusable", "Reusable",
144 "If this media pipeline can be reused after an unprepare",
145 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
147 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
148 g_param_spec_flags ("protocols", "Protocols",
149 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
150 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
152 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
153 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
154 "Send an EOS event to the pipeline before unpreparing",
155 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
157 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
158 g_param_spec_uint ("buffer-size", "Buffer Size",
159 "The kernel UDP buffer size to use", 0, G_MAXUINT,
160 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162 g_object_class_install_property (gobject_class, PROP_ELEMENT,
163 g_param_spec_object ("element", "The Element",
164 "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
165 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
167 gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
168 g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
169 G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
170 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
172 gst_rtsp_media_signals[SIGNAL_PREPARED] =
173 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
174 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
175 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
177 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
178 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
179 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
180 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
182 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
183 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
184 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
185 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 0, G_TYPE_INT);
187 klass->context = g_main_context_new ();
188 klass->loop = g_main_loop_new (klass->context, TRUE);
190 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
192 klass->thread = g_thread_new ("Bus Thread", (GThreadFunc) do_loop, klass);
194 klass->handle_message = default_handle_message;
195 klass->unprepare = default_unprepare;
199 gst_rtsp_media_init (GstRTSPMedia * media)
201 GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
205 priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
206 g_mutex_init (&priv->lock);
207 g_cond_init (&priv->cond);
208 g_rec_mutex_init (&priv->state_lock);
210 priv->shared = DEFAULT_SHARED;
211 priv->reusable = DEFAULT_REUSABLE;
212 priv->protocols = DEFAULT_PROTOCOLS;
213 priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
214 priv->buffer_size = DEFAULT_BUFFER_SIZE;
218 gst_rtsp_media_finalize (GObject * obj)
220 GstRTSPMediaPrivate *priv;
223 media = GST_RTSP_MEDIA (obj);
226 GST_INFO ("finalize media %p", media);
228 g_ptr_array_unref (priv->streams);
230 g_list_free_full (priv->dynamic, gst_object_unref);
233 gst_object_unref (priv->pipeline);
234 gst_object_unref (priv->element);
236 g_object_unref (priv->auth);
238 g_object_unref (priv->pool);
239 g_mutex_clear (&priv->lock);
240 g_cond_clear (&priv->cond);
241 g_rec_mutex_clear (&priv->state_lock);
243 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
247 gst_rtsp_media_get_property (GObject * object, guint propid,
248 GValue * value, GParamSpec * pspec)
250 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
254 g_value_set_object (value, media->priv->element);
257 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
260 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
263 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
265 case PROP_EOS_SHUTDOWN:
266 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
268 case PROP_BUFFER_SIZE:
269 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
277 gst_rtsp_media_set_property (GObject * object, guint propid,
278 const GValue * value, GParamSpec * pspec)
280 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
284 media->priv->element = g_value_get_object (value);
287 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
290 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
293 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
295 case PROP_EOS_SHUTDOWN:
296 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
298 case PROP_BUFFER_SIZE:
299 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
302 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
307 do_loop (GstRTSPMediaClass * klass)
309 GST_INFO ("enter mainloop");
310 g_main_loop_run (klass->loop);
311 GST_INFO ("exit mainloop");
316 /* must be called with state lock */
318 collect_media_stats (GstRTSPMedia * media)
320 GstRTSPMediaPrivate *priv = media->priv;
321 gint64 position, duration;
323 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
324 priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
327 priv->range.unit = GST_RTSP_RANGE_NPT;
329 GST_INFO ("collect media stats");
332 priv->range.min.type = GST_RTSP_TIME_NOW;
333 priv->range.min.seconds = -1;
334 priv->range_start = -1;
335 priv->range.max.type = GST_RTSP_TIME_END;
336 priv->range.max.seconds = -1;
337 priv->range_stop = -1;
339 /* get the position */
340 if (!gst_element_query_position (priv->pipeline, GST_FORMAT_TIME,
342 GST_INFO ("position query failed");
346 /* get the duration */
347 if (!gst_element_query_duration (priv->pipeline, GST_FORMAT_TIME,
349 GST_INFO ("duration query failed");
353 GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
354 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
356 if (position == -1) {
357 priv->range.min.type = GST_RTSP_TIME_NOW;
358 priv->range.min.seconds = -1;
359 priv->range_start = -1;
361 priv->range.min.type = GST_RTSP_TIME_SECONDS;
362 priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
363 priv->range_start = position;
365 if (duration == -1) {
366 priv->range.max.type = GST_RTSP_TIME_END;
367 priv->range.max.seconds = -1;
368 priv->range_stop = -1;
370 priv->range.max.type = GST_RTSP_TIME_SECONDS;
371 priv->range.max.seconds = ((gdouble) duration) / GST_SECOND;
372 priv->range_stop = duration;
378 * gst_rtsp_media_new:
379 * @element: (transfer full): a #GstElement
381 * Create a new #GstRTSPMedia instance. @element is the bin element that
382 * provides the different streams. The #GstRTSPMedia object contains the
383 * element to produce RTP data for one or more related (audio/video/..)
386 * Ownership is taken of @element.
388 * Returns: a new #GstRTSPMedia object.
391 gst_rtsp_media_new (GstElement * element)
393 GstRTSPMedia *result;
395 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
397 result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
403 * gst_rtsp_media_take_element:
404 * @media: a #GstRTSPMedia
405 * @pipeline: (transfer full): a #GstPipeline
407 * Set @pipeline as the #GstPipeline for @media. Ownership is
408 * taken of @pipeline.
411 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
413 GstRTSPMediaPrivate *priv;
416 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
417 g_return_if_fail (GST_IS_PIPELINE (pipeline));
421 g_mutex_lock (&priv->lock);
422 old = priv->pipeline;
423 priv->pipeline = GST_ELEMENT_CAST (pipeline);
424 g_mutex_unlock (&priv->lock);
427 gst_object_unref (old);
429 gst_object_ref (priv->element);
430 gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
434 * gst_rtsp_media_set_shared:
435 * @media: a #GstRTSPMedia
436 * @shared: the new value
438 * Set or unset if the pipeline for @media can be shared will multiple clients.
439 * When @shared is %TRUE, client requests for this media will share the media
443 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
445 GstRTSPMediaPrivate *priv;
447 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
451 g_mutex_lock (&priv->lock);
452 priv->shared = shared;
453 g_mutex_unlock (&priv->lock);
457 * gst_rtsp_media_is_shared:
458 * @media: a #GstRTSPMedia
460 * Check if the pipeline for @media can be shared between multiple clients.
462 * Returns: %TRUE if the media can be shared between clients.
465 gst_rtsp_media_is_shared (GstRTSPMedia * media)
467 GstRTSPMediaPrivate *priv;
470 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
474 g_mutex_lock (&priv->lock);
476 g_mutex_unlock (&priv->lock);
482 * gst_rtsp_media_set_reusable:
483 * @media: a #GstRTSPMedia
484 * @reusable: the new value
486 * Set or unset if the pipeline for @media can be reused after the pipeline has
490 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
492 GstRTSPMediaPrivate *priv;
494 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
498 g_mutex_lock (&priv->lock);
499 priv->reusable = reusable;
500 g_mutex_unlock (&priv->lock);
504 * gst_rtsp_media_is_reusable:
505 * @media: a #GstRTSPMedia
507 * Check if the pipeline for @media can be reused after an unprepare.
509 * Returns: %TRUE if the media can be reused
512 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
514 GstRTSPMediaPrivate *priv;
517 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
521 g_mutex_lock (&priv->lock);
522 res = priv->reusable;
523 g_mutex_unlock (&priv->lock);
529 * gst_rtsp_media_set_protocols:
530 * @media: a #GstRTSPMedia
531 * @protocols: the new flags
533 * Configure the allowed lower transport for @media.
536 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
538 GstRTSPMediaPrivate *priv;
540 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
544 g_mutex_lock (&priv->lock);
545 priv->protocols = protocols;
546 g_mutex_unlock (&priv->lock);
550 * gst_rtsp_media_get_protocols:
551 * @media: a #GstRTSPMedia
553 * Get the allowed protocols of @media.
555 * Returns: a #GstRTSPLowerTrans
558 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
560 GstRTSPMediaPrivate *priv;
561 GstRTSPLowerTrans res;
563 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
564 GST_RTSP_LOWER_TRANS_UNKNOWN);
568 g_mutex_lock (&priv->lock);
569 res = priv->protocols;
570 g_mutex_unlock (&priv->lock);
576 * gst_rtsp_media_set_eos_shutdown:
577 * @media: a #GstRTSPMedia
578 * @eos_shutdown: the new value
580 * Set or unset if an EOS event will be sent to the pipeline for @media before
584 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
586 GstRTSPMediaPrivate *priv;
588 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
592 g_mutex_lock (&priv->lock);
593 priv->eos_shutdown = eos_shutdown;
594 g_mutex_unlock (&priv->lock);
598 * gst_rtsp_media_is_eos_shutdown:
599 * @media: a #GstRTSPMedia
601 * Check if the pipeline for @media will send an EOS down the pipeline before
604 * Returns: %TRUE if the media will send EOS before unpreparing.
607 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
609 GstRTSPMediaPrivate *priv;
612 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
616 g_mutex_lock (&priv->lock);
617 res = priv->eos_shutdown;
618 g_mutex_unlock (&priv->lock);
624 * gst_rtsp_media_set_buffer_size:
625 * @media: a #GstRTSPMedia
626 * @size: the new value
628 * Set the kernel UDP buffer size.
631 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
633 GstRTSPMediaPrivate *priv;
635 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
637 GST_LOG_OBJECT (media, "set buffer size %u", size);
641 g_mutex_lock (&priv->lock);
642 priv->buffer_size = size;
643 g_mutex_unlock (&priv->lock);
647 * gst_rtsp_media_get_buffer_size:
648 * @media: a #GstRTSPMedia
650 * Get the kernel UDP buffer size.
652 * Returns: the kernel UDP buffer size.
655 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
657 GstRTSPMediaPrivate *priv;
660 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
664 g_mutex_unlock (&priv->lock);
665 res = priv->buffer_size;
666 g_mutex_unlock (&priv->lock);
672 * gst_rtsp_media_set_auth:
673 * @media: a #GstRTSPMedia
674 * @auth: a #GstRTSPAuth
676 * configure @auth to be used as the authentication manager of @media.
679 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
681 GstRTSPMediaPrivate *priv;
684 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
688 GST_LOG_OBJECT (media, "set auth %p", auth);
690 g_mutex_lock (&priv->lock);
691 if ((old = priv->auth) != auth)
692 priv->auth = auth ? g_object_ref (auth) : NULL;
695 g_mutex_unlock (&priv->lock);
698 g_object_unref (old);
702 * gst_rtsp_media_get_auth:
703 * @media: a #GstRTSPMedia
705 * Get the #GstRTSPAuth used as the authentication manager of @media.
707 * Returns: (transfer full): the #GstRTSPAuth of @media. g_object_unref() after
711 gst_rtsp_media_get_auth (GstRTSPMedia * media)
713 GstRTSPMediaPrivate *priv;
716 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
720 g_mutex_lock (&priv->lock);
721 if ((result = priv->auth))
722 g_object_ref (result);
723 g_mutex_unlock (&priv->lock);
729 * gst_rtsp_media_set_address_pool:
730 * @media: a #GstRTSPMedia
731 * @pool: a #GstRTSPAddressPool
733 * configure @pool to be used as the address pool of @media.
736 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
737 GstRTSPAddressPool * pool)
739 GstRTSPMediaPrivate *priv;
740 GstRTSPAddressPool *old;
742 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
746 GST_LOG_OBJECT (media, "set address pool %p", pool);
748 g_mutex_lock (&priv->lock);
749 if ((old = priv->pool) != pool)
750 priv->pool = pool ? g_object_ref (pool) : NULL;
753 g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
755 g_mutex_unlock (&priv->lock);
758 g_object_unref (old);
762 * gst_rtsp_media_get_address_pool:
763 * @media: a #GstRTSPMedia
765 * Get the #GstRTSPAddressPool used as the address pool of @media.
767 * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
771 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
773 GstRTSPMediaPrivate *priv;
774 GstRTSPAddressPool *result;
776 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
780 g_mutex_lock (&priv->lock);
781 if ((result = priv->pool))
782 g_object_ref (result);
783 g_mutex_unlock (&priv->lock);
789 * gst_rtsp_media_collect_streams:
790 * @media: a #GstRTSPMedia
792 * Find all payloader elements, they should be named pay%d in the
793 * element of @media, and create #GstRTSPStreams for them.
795 * Collect all dynamic elements, named dynpay%d, and add them to
796 * the list of dynamic elements.
799 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
801 GstRTSPMediaPrivate *priv;
802 GstElement *element, *elem;
807 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
810 element = priv->element;
813 for (i = 0; have_elem; i++) {
818 name = g_strdup_printf ("pay%d", i);
819 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
820 GST_INFO ("found stream %d with payloader %p", i, elem);
822 /* take the pad of the payloader */
823 pad = gst_element_get_static_pad (elem, "src");
824 /* create the stream */
825 gst_rtsp_media_create_stream (media, elem, pad);
826 gst_object_unref (pad);
827 gst_object_unref (elem);
833 name = g_strdup_printf ("dynpay%d", i);
834 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
835 /* a stream that will dynamically create pads to provide RTP packets */
837 GST_INFO ("found dynamic element %d, %p", i, elem);
839 g_mutex_lock (&priv->lock);
840 priv->dynamic = g_list_prepend (priv->dynamic, elem);
841 g_mutex_unlock (&priv->lock);
850 * gst_rtsp_media_create_stream:
851 * @media: a #GstRTSPMedia
852 * @payloader: a #GstElement
853 * @srcpad: a source #GstPad
855 * Create a new stream in @media that provides RTP data on @srcpad.
856 * @srcpad should be a pad of an element inside @media->element.
858 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
862 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
865 GstRTSPMediaPrivate *priv;
866 GstRTSPStream *stream;
871 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
872 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
873 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
874 g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
878 g_mutex_lock (&priv->lock);
879 idx = priv->streams->len;
881 GST_DEBUG ("media %p: creating stream with index %d", media, idx);
883 name = g_strdup_printf ("src_%u", idx);
884 srcpad = gst_ghost_pad_new (name, pad);
885 gst_pad_set_active (srcpad, TRUE);
886 gst_element_add_pad (priv->element, srcpad);
889 stream = gst_rtsp_stream_new (idx, payloader, srcpad);
891 gst_rtsp_stream_set_address_pool (stream, priv->pool);
893 g_ptr_array_add (priv->streams, stream);
894 g_mutex_unlock (&priv->lock);
896 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
903 * gst_rtsp_media_n_streams:
904 * @media: a #GstRTSPMedia
906 * Get the number of streams in this media.
908 * Returns: The number of streams.
911 gst_rtsp_media_n_streams (GstRTSPMedia * media)
913 GstRTSPMediaPrivate *priv;
916 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
920 g_mutex_lock (&priv->lock);
921 res = priv->streams->len;
922 g_mutex_unlock (&priv->lock);
928 * gst_rtsp_media_get_stream:
929 * @media: a #GstRTSPMedia
930 * @idx: the stream index
932 * Retrieve the stream with index @idx from @media.
934 * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
935 * that index did not exist.
938 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
940 GstRTSPMediaPrivate *priv;
943 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
947 g_mutex_lock (&priv->lock);
948 if (idx < priv->streams->len)
949 res = g_ptr_array_index (priv->streams, idx);
952 g_mutex_unlock (&priv->lock);
958 * gst_rtsp_media_get_range_string:
959 * @media: a #GstRTSPMedia
960 * @play: for the PLAY request
962 * Get the current range as a string. @media must be prepared with
963 * gst_rtsp_media_prepare ().
965 * Returns: The range as a string, g_free() after usage.
968 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
970 GstRTSPMediaPrivate *priv;
972 GstRTSPTimeRange range;
974 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
978 g_rec_mutex_lock (&priv->state_lock);
979 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
982 g_mutex_lock (&priv->lock);
986 if (!play && priv->n_active > 0) {
987 range.min.type = GST_RTSP_TIME_NOW;
988 range.min.seconds = -1;
990 g_mutex_unlock (&priv->lock);
991 g_rec_mutex_unlock (&priv->state_lock);
993 result = gst_rtsp_range_to_string (&range);
1000 GST_WARNING ("media %p was not prepared", media);
1001 g_rec_mutex_unlock (&priv->state_lock);
1007 * gst_rtsp_media_seek:
1008 * @media: a #GstRTSPMedia
1009 * @range: a #GstRTSPTimeRange
1011 * Seek the pipeline of @media to @range. @media must be prepared with
1012 * gst_rtsp_media_prepare().
1014 * Returns: %TRUE on success.
1017 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
1019 GstRTSPMediaPrivate *priv;
1022 GstClockTime start, stop;
1023 GstSeekType start_type, stop_type;
1025 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1026 g_return_val_if_fail (range != NULL, FALSE);
1030 g_rec_mutex_lock (&priv->state_lock);
1031 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1034 if (!priv->seekable)
1037 /* depends on the current playing state of the pipeline. We might need to
1038 * queue this until we get EOS. */
1039 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
1041 start_type = stop_type = GST_SEEK_TYPE_NONE;
1043 if (!gst_rtsp_range_get_times (range, &start, &stop))
1046 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1047 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1048 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1049 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
1051 if (priv->range_start == start)
1052 start = GST_CLOCK_TIME_NONE;
1053 else if (start != GST_CLOCK_TIME_NONE)
1054 start_type = GST_SEEK_TYPE_SET;
1056 if (priv->range_stop == stop)
1057 stop = GST_CLOCK_TIME_NONE;
1058 else if (stop != GST_CLOCK_TIME_NONE)
1059 stop_type = GST_SEEK_TYPE_SET;
1061 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
1062 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1063 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1065 res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
1066 flags, start_type, start, stop_type, stop);
1068 /* and block for the seek to complete */
1069 GST_INFO ("done seeking %d", res);
1070 gst_element_get_state (priv->pipeline, NULL, NULL, -1);
1071 GST_INFO ("prerolled again");
1073 collect_media_stats (media);
1075 GST_INFO ("no seek needed");
1078 g_rec_mutex_unlock (&priv->state_lock);
1085 g_rec_mutex_unlock (&priv->state_lock);
1086 GST_INFO ("media %p is not prepared", media);
1091 g_rec_mutex_unlock (&priv->state_lock);
1092 GST_INFO ("pipeline is not seekable");
1097 g_rec_mutex_unlock (&priv->state_lock);
1098 GST_WARNING ("seek unit %d not supported", range->unit);
1104 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1106 GstRTSPMediaPrivate *priv = media->priv;
1108 g_mutex_lock (&priv->lock);
1109 priv->status = status;
1110 GST_DEBUG ("setting new status to %d", status);
1111 g_cond_broadcast (&priv->cond);
1112 g_mutex_unlock (&priv->lock);
1116 * gst_rtsp_media_get_status:
1117 * @media: a #GstRTSPMedia
1119 * Get the status of @media. When @media is busy preparing, this function waits
1120 * until @media is prepared or in error.
1122 * Returns: the status of @media.
1125 gst_rtsp_media_get_status (GstRTSPMedia * media)
1127 GstRTSPMediaPrivate *priv = media->priv;
1128 GstRTSPMediaStatus result;
1131 g_mutex_lock (&priv->lock);
1132 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
1133 /* while we are preparing, wait */
1134 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1135 GST_DEBUG ("waiting for status change");
1136 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
1137 GST_DEBUG ("timeout, assuming error status");
1138 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
1141 /* could be success or error */
1142 result = priv->status;
1143 GST_DEBUG ("got status %d", result);
1144 g_mutex_unlock (&priv->lock);
1149 /* called with state-lock */
1151 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1153 GstRTSPMediaPrivate *priv = media->priv;
1154 GstMessageType type;
1156 type = GST_MESSAGE_TYPE (message);
1159 case GST_MESSAGE_STATE_CHANGED:
1161 case GST_MESSAGE_BUFFERING:
1165 gst_message_parse_buffering (message, &percent);
1167 /* no state management needed for live pipelines */
1171 if (percent == 100) {
1172 /* a 100% message means buffering is done */
1173 priv->buffering = FALSE;
1174 /* if the desired state is playing, go back */
1175 if (priv->target_state == GST_STATE_PLAYING) {
1176 GST_INFO ("Buffering done, setting pipeline to PLAYING");
1177 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1179 GST_INFO ("Buffering done");
1182 /* buffering busy */
1183 if (priv->buffering == FALSE) {
1184 if (priv->target_state == GST_STATE_PLAYING) {
1185 /* we were not buffering but PLAYING, PAUSE the pipeline. */
1186 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1187 gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1189 GST_INFO ("Buffering ...");
1192 priv->buffering = TRUE;
1196 case GST_MESSAGE_LATENCY:
1198 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
1201 case GST_MESSAGE_ERROR:
1206 gst_message_parse_error (message, &gerror, &debug);
1207 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1208 g_error_free (gerror);
1211 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1214 case GST_MESSAGE_WARNING:
1219 gst_message_parse_warning (message, &gerror, &debug);
1220 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1221 g_error_free (gerror);
1225 case GST_MESSAGE_ELEMENT:
1227 case GST_MESSAGE_STREAM_STATUS:
1229 case GST_MESSAGE_ASYNC_DONE:
1230 if (!priv->adding) {
1231 /* when we are dynamically adding pads, the addition of the udpsrc will
1232 * temporarily produce ASYNC_DONE messages. We have to ignore them and
1233 * wait for the final ASYNC_DONE after everything prerolled */
1234 GST_INFO ("%p: got ASYNC_DONE", media);
1235 collect_media_stats (media);
1237 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1238 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1240 GST_INFO ("%p: ignoring ASYNC_DONE", media);
1243 case GST_MESSAGE_EOS:
1244 GST_INFO ("%p: got EOS", media);
1246 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1247 GST_DEBUG ("shutting down after EOS");
1248 finish_unprepare (media);
1252 GST_INFO ("%p: got message type %d (%s)", media, type,
1253 gst_message_type_get_name (type));
1260 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1262 GstRTSPMediaPrivate *priv = media->priv;
1263 GstRTSPMediaClass *klass;
1266 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1268 g_rec_mutex_lock (&priv->state_lock);
1269 if (klass->handle_message)
1270 ret = klass->handle_message (media, message);
1273 g_rec_mutex_unlock (&priv->state_lock);
1279 watch_destroyed (GstRTSPMedia * media)
1281 GST_DEBUG_OBJECT (media, "source destroyed");
1282 g_object_unref (media);
1285 /* called from streaming threads */
1287 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1289 GstRTSPMediaPrivate *priv = media->priv;
1290 GstRTSPStream *stream;
1292 /* FIXME, element is likely not a payloader, find the payloader here */
1293 stream = gst_rtsp_media_create_stream (media, element, pad);
1295 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
1297 g_rec_mutex_lock (&priv->state_lock);
1298 /* we will be adding elements below that will cause ASYNC_DONE to be
1299 * posted in the bus. We want to ignore those messages until the
1300 * pipeline really prerolled. */
1301 priv->adding = TRUE;
1303 /* join the element in the PAUSED state because this callback is
1304 * called from the streaming thread and it is PAUSED */
1305 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1306 priv->rtpbin, GST_STATE_PAUSED);
1308 priv->adding = FALSE;
1309 g_rec_mutex_unlock (&priv->state_lock);
1313 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1315 GstRTSPMediaPrivate *priv = media->priv;
1316 GstElement *fakesink;
1318 g_mutex_lock (&priv->lock);
1319 GST_INFO ("no more pads");
1320 if ((fakesink = priv->fakesink)) {
1321 gst_object_ref (fakesink);
1322 priv->fakesink = NULL;
1323 g_mutex_unlock (&priv->lock);
1325 gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
1326 gst_element_set_state (fakesink, GST_STATE_NULL);
1327 gst_object_unref (fakesink);
1328 GST_INFO ("removed fakesink");
1333 * gst_rtsp_media_prepare:
1334 * @media: a #GstRTSPMedia
1336 * Prepare @media for streaming. This function will create the pipeline and
1337 * other objects to manage the streaming.
1339 * It will preroll the pipeline and collect vital information about the streams
1340 * such as the duration.
1342 * Returns: %TRUE on success.
1345 gst_rtsp_media_prepare (GstRTSPMedia * media)
1347 GstRTSPMediaPrivate *priv;
1348 GstStateChangeReturn ret;
1349 GstRTSPMediaStatus status;
1351 GstRTSPMediaClass *klass;
1355 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1359 g_rec_mutex_lock (&priv->state_lock);
1360 priv->prepare_count++;
1362 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1365 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1368 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1369 goto not_unprepared;
1371 if (!priv->reusable && priv->reused)
1374 priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1375 if (priv->rtpbin == NULL)
1378 GST_INFO ("preparing media %p", media);
1380 /* reset some variables */
1381 priv->is_live = FALSE;
1382 priv->seekable = FALSE;
1383 priv->buffering = FALSE;
1384 /* we're preparing now */
1385 priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1387 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
1389 /* add the pipeline bus to our custom mainloop */
1390 priv->source = gst_bus_create_watch (bus);
1391 gst_object_unref (bus);
1393 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
1394 g_object_ref (media), (GDestroyNotify) watch_destroyed);
1396 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1397 priv->id = g_source_attach (priv->source, klass->context);
1399 /* add stuff to the bin */
1400 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
1402 /* link streams we already have, other streams might appear when we have
1403 * dynamic elements */
1404 for (i = 0; i < priv->streams->len; i++) {
1405 GstRTSPStream *stream;
1407 stream = g_ptr_array_index (priv->streams, i);
1409 gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
1410 priv->rtpbin, GST_STATE_NULL);
1413 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
1414 GstElement *elem = walk->data;
1416 GST_INFO ("adding callbacks for dynamic element %p", elem);
1418 g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1419 g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1421 /* we add a fakesink here in order to make the state change async. We remove
1422 * the fakesink again in the no-more-pads callback. */
1423 priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1424 gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
1427 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1428 /* first go to PAUSED */
1429 ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1430 priv->target_state = GST_STATE_PAUSED;
1433 case GST_STATE_CHANGE_SUCCESS:
1434 GST_INFO ("SUCCESS state change for media %p", media);
1435 priv->seekable = TRUE;
1437 case GST_STATE_CHANGE_ASYNC:
1438 GST_INFO ("ASYNC state change for media %p", media);
1439 priv->seekable = TRUE;
1441 case GST_STATE_CHANGE_NO_PREROLL:
1442 /* we need to go to PLAYING */
1443 GST_INFO ("NO_PREROLL state change: live media %p", media);
1444 /* FIXME we disable seeking for live streams for now. We should perform a
1445 * seeking query in preroll instead */
1446 priv->seekable = FALSE;
1447 priv->is_live = TRUE;
1448 ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1449 if (ret == GST_STATE_CHANGE_FAILURE)
1452 case GST_STATE_CHANGE_FAILURE:
1456 g_rec_mutex_unlock (&priv->state_lock);
1458 /* now wait for all pads to be prerolled, FIXME, we should somehow be
1459 * able to do this async so that we don't block the server thread. */
1460 status = gst_rtsp_media_get_status (media);
1461 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1464 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1466 GST_INFO ("object %p is prerolled", media);
1473 GST_LOG ("media %p was prepared", media);
1474 g_rec_mutex_unlock (&priv->state_lock);
1480 GST_WARNING ("media %p was not unprepared", media);
1481 priv->prepare_count--;
1482 g_rec_mutex_unlock (&priv->state_lock);
1487 priv->prepare_count--;
1488 g_rec_mutex_unlock (&priv->state_lock);
1489 GST_WARNING ("can not reuse media %p", media);
1494 priv->prepare_count--;
1495 g_rec_mutex_unlock (&priv->state_lock);
1496 GST_WARNING ("no rtpbin element");
1497 g_warning ("failed to create element 'rtpbin', check your installation");
1502 GST_WARNING ("failed to preroll pipeline");
1503 gst_rtsp_media_unprepare (media);
1504 g_rec_mutex_unlock (&priv->state_lock);
1509 /* must be called with state-lock */
1511 finish_unprepare (GstRTSPMedia * media)
1513 GstRTSPMediaPrivate *priv = media->priv;
1516 GST_DEBUG ("shutting down");
1518 gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1520 for (i = 0; i < priv->streams->len; i++) {
1521 GstRTSPStream *stream;
1523 GST_INFO ("Removing elements of stream %d from pipeline", i);
1525 stream = g_ptr_array_index (priv->streams, i);
1527 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
1529 g_ptr_array_set_size (priv->streams, 0);
1531 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
1532 priv->rtpbin = NULL;
1534 gst_object_unref (priv->pipeline);
1535 priv->pipeline = NULL;
1537 priv->reused = TRUE;
1538 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1540 /* when the media is not reusable, this will effectively unref the media and
1542 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1544 /* the source has the last ref to the media */
1546 GST_DEBUG ("destroy source");
1547 g_source_destroy (priv->source);
1548 g_source_unref (priv->source);
1552 /* called with state-lock */
1554 default_unprepare (GstRTSPMedia * media)
1556 GstRTSPMediaPrivate *priv = media->priv;
1558 if (priv->eos_shutdown) {
1559 GST_DEBUG ("sending EOS for shutdown");
1560 /* ref so that we don't disappear */
1561 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
1562 /* we need to go to playing again for the EOS to propagate, normally in this
1563 * state, nothing is receiving data from us anymore so this is ok. */
1564 gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1565 priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1567 finish_unprepare (media);
1573 * gst_rtsp_media_unprepare:
1574 * @media: a #GstRTSPMedia
1576 * Unprepare @media. After this call, the media should be prepared again before
1577 * it can be used again. If the media is set to be non-reusable, a new instance
1580 * Returns: %TRUE on success.
1583 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1585 GstRTSPMediaPrivate *priv;
1588 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1592 g_rec_mutex_lock (&priv->state_lock);
1593 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1594 goto was_unprepared;
1596 priv->prepare_count--;
1597 if (priv->prepare_count > 0)
1600 GST_INFO ("unprepare media %p", media);
1601 priv->target_state = GST_STATE_NULL;
1604 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1605 GstRTSPMediaClass *klass;
1607 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1608 if (klass->unprepare)
1609 success = klass->unprepare (media);
1611 finish_unprepare (media);
1613 g_rec_mutex_unlock (&priv->state_lock);
1619 g_rec_mutex_unlock (&priv->state_lock);
1620 GST_INFO ("media %p was already unprepared", media);
1625 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
1626 g_rec_mutex_unlock (&priv->state_lock);
1632 * gst_rtsp_media_set_state:
1633 * @media: a #GstRTSPMedia
1634 * @state: the target state of the media
1635 * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
1637 * Set the state of @media to @state and for the transports in @transports.
1639 * @media must be prepared with gst_rtsp_media_prepare();
1641 * Returns: %TRUE on success.
1644 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1645 GPtrArray * transports)
1647 GstRTSPMediaPrivate *priv;
1649 gboolean activate, deactivate, do_state;
1652 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1653 g_return_val_if_fail (transports != NULL, FALSE);
1657 g_rec_mutex_lock (&priv->state_lock);
1658 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
1661 /* NULL and READY are the same */
1662 if (state == GST_STATE_READY)
1663 state = GST_STATE_NULL;
1665 activate = deactivate = FALSE;
1667 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1671 case GST_STATE_NULL:
1672 case GST_STATE_PAUSED:
1673 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
1674 if (priv->target_state == GST_STATE_PLAYING)
1677 case GST_STATE_PLAYING:
1678 /* we're going to PLAYING, activate */
1684 old_active = priv->n_active;
1686 for (i = 0; i < transports->len; i++) {
1687 GstRTSPStreamTransport *trans;
1689 /* we need a non-NULL entry in the array */
1690 trans = g_ptr_array_index (transports, i);
1695 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
1697 } else if (deactivate) {
1698 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
1703 /* we just activated the first media, do the playing state change */
1704 if (old_active == 0 && activate)
1706 /* if we have no more active media, do the downward state changes */
1707 else if (priv->n_active == 0)
1712 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
1715 if (priv->target_state != state) {
1717 if (state == GST_STATE_NULL) {
1718 gst_rtsp_media_unprepare (media);
1720 GST_INFO ("state %s media %p", gst_element_state_get_name (state),
1722 priv->target_state = state;
1723 gst_element_set_state (priv->pipeline, state);
1726 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
1730 /* remember where we are */
1731 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
1732 old_active != priv->n_active))
1733 collect_media_stats (media);
1735 g_rec_mutex_unlock (&priv->state_lock);
1742 GST_WARNING ("media %p was not prepared", media);
1743 g_rec_mutex_unlock (&priv->state_lock);