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 DEFAULT_SHARED FALSE
29 #define DEFAULT_REUSABLE FALSE
30 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
31 //#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP_MCAST
32 #define DEFAULT_EOS_SHUTDOWN FALSE
33 #define DEFAULT_BUFFER_SIZE 0x80000
35 /* define to dump received RTCP packets */
57 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
58 #define GST_CAT_DEFAULT rtsp_media_debug
60 static void gst_rtsp_media_get_property (GObject * object, guint propid,
61 GValue * value, GParamSpec * pspec);
62 static void gst_rtsp_media_set_property (GObject * object, guint propid,
63 const GValue * value, GParamSpec * pspec);
64 static void gst_rtsp_media_finalize (GObject * obj);
66 static gpointer do_loop (GstRTSPMediaClass * klass);
67 static gboolean default_handle_message (GstRTSPMedia * media,
68 GstMessage * message);
69 static void finish_unprepare (GstRTSPMedia * media);
70 static gboolean default_unprepare (GstRTSPMedia * media);
72 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
74 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
77 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
79 GObjectClass *gobject_class;
81 gobject_class = G_OBJECT_CLASS (klass);
83 gobject_class->get_property = gst_rtsp_media_get_property;
84 gobject_class->set_property = gst_rtsp_media_set_property;
85 gobject_class->finalize = gst_rtsp_media_finalize;
87 g_object_class_install_property (gobject_class, PROP_SHARED,
88 g_param_spec_boolean ("shared", "Shared",
89 "If this media pipeline can be shared", DEFAULT_SHARED,
90 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
92 g_object_class_install_property (gobject_class, PROP_REUSABLE,
93 g_param_spec_boolean ("reusable", "Reusable",
94 "If this media pipeline can be reused after an unprepare",
95 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
97 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
98 g_param_spec_flags ("protocols", "Protocols",
99 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
100 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
102 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
103 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
104 "Send an EOS event to the pipeline before unpreparing",
105 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
107 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
108 g_param_spec_uint ("buffer-size", "Buffer Size",
109 "The kernel UDP buffer size to use", 0, G_MAXUINT,
110 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
112 gst_rtsp_media_signals[SIGNAL_PREPARED] =
113 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
114 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
115 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
117 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
118 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
119 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
120 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
122 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
123 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
124 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
125 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 0, G_TYPE_INT);
127 klass->context = g_main_context_new ();
128 klass->loop = g_main_loop_new (klass->context, TRUE);
130 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
132 klass->thread = g_thread_new ("Bus Thread", (GThreadFunc) do_loop, klass);
134 klass->handle_message = default_handle_message;
135 klass->unprepare = default_unprepare;
139 gst_rtsp_media_init (GstRTSPMedia * media)
141 media->streams = g_ptr_array_new_with_free_func (g_object_unref);
142 g_mutex_init (&media->lock);
143 g_cond_init (&media->cond);
144 g_rec_mutex_init (&media->state_lock);
146 media->shared = DEFAULT_SHARED;
147 media->reusable = DEFAULT_REUSABLE;
148 media->protocols = DEFAULT_PROTOCOLS;
149 media->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
150 media->buffer_size = DEFAULT_BUFFER_SIZE;
154 gst_rtsp_media_finalize (GObject * obj)
158 media = GST_RTSP_MEDIA (obj);
160 GST_INFO ("finalize media %p", media);
162 gst_rtsp_media_unprepare (media);
164 g_ptr_array_unref (media->streams);
166 g_list_free_full (media->dynamic, gst_object_unref);
169 g_source_destroy (media->source);
170 g_source_unref (media->source);
173 g_object_unref (media->auth);
175 g_object_unref (media->pool);
176 g_mutex_clear (&media->lock);
177 g_cond_clear (&media->cond);
178 g_rec_mutex_clear (&media->state_lock);
180 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
184 gst_rtsp_media_get_property (GObject * object, guint propid,
185 GValue * value, GParamSpec * pspec)
187 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
191 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
194 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
197 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
199 case PROP_EOS_SHUTDOWN:
200 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
202 case PROP_BUFFER_SIZE:
203 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
206 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
211 gst_rtsp_media_set_property (GObject * object, guint propid,
212 const GValue * value, GParamSpec * pspec)
214 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
218 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
221 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
224 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
226 case PROP_EOS_SHUTDOWN:
227 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
229 case PROP_BUFFER_SIZE:
230 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
233 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
238 do_loop (GstRTSPMediaClass * klass)
240 GST_INFO ("enter mainloop");
241 g_main_loop_run (klass->loop);
242 GST_INFO ("exit mainloop");
247 /* must be called with state lock */
249 collect_media_stats (GstRTSPMedia * media)
251 gint64 position, duration;
253 media->range.unit = GST_RTSP_RANGE_NPT;
255 GST_INFO ("collect media stats");
257 if (media->is_live) {
258 media->range.min.type = GST_RTSP_TIME_NOW;
259 media->range.min.seconds = -1;
260 media->range.max.type = GST_RTSP_TIME_END;
261 media->range.max.seconds = -1;
263 /* get the position */
264 if (!gst_element_query_position (media->pipeline, GST_FORMAT_TIME,
266 GST_INFO ("position query failed");
270 /* get the duration */
271 if (!gst_element_query_duration (media->pipeline, GST_FORMAT_TIME,
273 GST_INFO ("duration query failed");
277 GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
278 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
280 if (position == -1) {
281 media->range.min.type = GST_RTSP_TIME_NOW;
282 media->range.min.seconds = -1;
284 media->range.min.type = GST_RTSP_TIME_SECONDS;
285 media->range.min.seconds = ((gdouble) position) / GST_SECOND;
287 if (duration == -1) {
288 media->range.max.type = GST_RTSP_TIME_END;
289 media->range.max.seconds = -1;
291 media->range.max.type = GST_RTSP_TIME_SECONDS;
292 media->range.max.seconds = ((gdouble) duration) / GST_SECOND;
298 * gst_rtsp_media_new:
300 * Create a new #GstRTSPMedia instance. The #GstRTSPMedia object contains the
301 * element to produce RTP data for one or more related (audio/video/..)
304 * Returns: a new #GstRTSPMedia object.
307 gst_rtsp_media_new (void)
309 GstRTSPMedia *result;
311 result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
317 * gst_rtsp_media_set_shared:
318 * @media: a #GstRTSPMedia
319 * @shared: the new value
321 * Set or unset if the pipeline for @media can be shared will multiple clients.
322 * When @shared is %TRUE, client requests for this media will share the media
326 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
328 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
330 g_mutex_lock (&media->lock);
331 media->shared = shared;
332 g_mutex_unlock (&media->lock);
336 * gst_rtsp_media_is_shared:
337 * @media: a #GstRTSPMedia
339 * Check if the pipeline for @media can be shared between multiple clients.
341 * Returns: %TRUE if the media can be shared between clients.
344 gst_rtsp_media_is_shared (GstRTSPMedia * media)
348 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
350 g_mutex_lock (&media->lock);
352 g_mutex_unlock (&media->lock);
358 * gst_rtsp_media_set_reusable:
359 * @media: a #GstRTSPMedia
360 * @reusable: the new value
362 * Set or unset if the pipeline for @media can be reused after the pipeline has
366 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
368 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
370 g_mutex_lock (&media->lock);
371 media->reusable = reusable;
372 g_mutex_unlock (&media->lock);
376 * gst_rtsp_media_is_reusable:
377 * @media: a #GstRTSPMedia
379 * Check if the pipeline for @media can be reused after an unprepare.
381 * Returns: %TRUE if the media can be reused
384 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
388 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
390 g_mutex_lock (&media->lock);
391 res = media->reusable;
392 g_mutex_unlock (&media->lock);
398 * gst_rtsp_media_set_protocols:
399 * @media: a #GstRTSPMedia
400 * @protocols: the new flags
402 * Configure the allowed lower transport for @media.
405 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
407 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
409 g_mutex_lock (&media->lock);
410 media->protocols = protocols;
411 g_mutex_unlock (&media->lock);
415 * gst_rtsp_media_get_protocols:
416 * @media: a #GstRTSPMedia
418 * Get the allowed protocols of @media.
420 * Returns: a #GstRTSPLowerTrans
423 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
425 GstRTSPLowerTrans res;
427 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
428 GST_RTSP_LOWER_TRANS_UNKNOWN);
430 g_mutex_lock (&media->lock);
431 res = media->protocols;
432 g_mutex_unlock (&media->lock);
438 * gst_rtsp_media_set_eos_shutdown:
439 * @media: a #GstRTSPMedia
440 * @eos_shutdown: the new value
442 * Set or unset if an EOS event will be sent to the pipeline for @media before
446 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
448 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
450 g_mutex_lock (&media->lock);
451 media->eos_shutdown = eos_shutdown;
452 g_mutex_unlock (&media->lock);
456 * gst_rtsp_media_is_eos_shutdown:
457 * @media: a #GstRTSPMedia
459 * Check if the pipeline for @media will send an EOS down the pipeline before
462 * Returns: %TRUE if the media will send EOS before unpreparing.
465 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
469 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
471 g_mutex_lock (&media->lock);
472 res = media->eos_shutdown;
473 g_mutex_unlock (&media->lock);
479 * gst_rtsp_media_set_buffer_size:
480 * @media: a #GstRTSPMedia
481 * @size: the new value
483 * Set the kernel UDP buffer size.
486 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
488 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
490 g_mutex_lock (&media->lock);
491 media->buffer_size = size;
492 g_mutex_unlock (&media->lock);
496 * gst_rtsp_media_get_buffer_size:
497 * @media: a #GstRTSPMedia
499 * Get the kernel UDP buffer size.
501 * Returns: the kernel UDP buffer size.
504 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
508 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
510 g_mutex_unlock (&media->lock);
511 res = media->buffer_size;
512 g_mutex_unlock (&media->lock);
518 * gst_rtsp_media_set_auth:
519 * @media: a #GstRTSPMedia
520 * @auth: a #GstRTSPAuth
522 * configure @auth to be used as the authentication manager of @media.
525 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
529 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
531 g_mutex_lock (&media->lock);
532 if ((old = media->auth) != auth)
533 media->auth = auth ? g_object_ref (auth) : NULL;
536 g_mutex_unlock (&media->lock);
539 g_object_unref (old);
543 * gst_rtsp_media_get_auth:
544 * @media: a #GstRTSPMedia
546 * Get the #GstRTSPAuth used as the authentication manager of @media.
548 * Returns: (transfer full): the #GstRTSPAuth of @media. g_object_unref() after
552 gst_rtsp_media_get_auth (GstRTSPMedia * media)
556 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
558 g_mutex_lock (&media->lock);
559 if ((result = media->auth))
560 g_object_ref (result);
561 g_mutex_unlock (&media->lock);
567 * gst_rtsp_media_set_address_pool:
568 * @media: a #GstRTSPMedia
569 * @pool: a #GstRTSPAddressPool
571 * configure @pool to be used as the address pool of @media.
574 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
575 GstRTSPAddressPool * pool)
577 GstRTSPAddressPool *old;
579 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
581 g_mutex_lock (&media->lock);
582 if ((old = media->pool) != pool)
583 media->pool = pool ? g_object_ref (pool) : NULL;
586 g_mutex_unlock (&media->lock);
589 g_object_unref (old);
593 * gst_rtsp_media_get_address_pool:
594 * @media: a #GstRTSPMedia
596 * Get the #GstRTSPAddressPool used as the address pool of @media.
598 * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
602 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
604 GstRTSPAddressPool *result;
606 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
608 g_mutex_lock (&media->lock);
609 if ((result = media->pool))
610 g_object_ref (result);
611 g_mutex_unlock (&media->lock);
617 * gst_rtsp_media_collect_streams:
618 * @media: a #GstRTSPMedia
620 * Find all payloader elements, they should be named pay%d in the
621 * element of @media, and create #GstRTSPStreams for them.
623 * Collect all dynamic elements, named dynpay%d, and add them to
624 * the list of dynamic elements.
627 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
629 GstElement *element, *elem;
634 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
636 element = media->element;
639 for (i = 0; have_elem; i++) {
644 name = g_strdup_printf ("pay%d", i);
645 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
646 GST_INFO ("found stream %d with payloader %p", i, elem);
648 /* take the pad of the payloader */
649 pad = gst_element_get_static_pad (elem, "src");
650 /* create the stream */
651 gst_rtsp_media_create_stream (media, elem, pad);
652 g_object_unref (pad);
654 gst_object_unref (elem);
660 name = g_strdup_printf ("dynpay%d", i);
661 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
662 /* a stream that will dynamically create pads to provide RTP packets */
664 GST_INFO ("found dynamic element %d, %p", i, elem);
666 g_mutex_lock (&media->lock);
667 media->dynamic = g_list_prepend (media->dynamic, elem);
668 g_mutex_unlock (&media->lock);
677 * gst_rtsp_media_create_stream:
678 * @media: a #GstRTSPMedia
679 * @payloader: a #GstElement
680 * @srcpad: a source #GstPad
682 * Create a new stream in @media that provides RTP data on @srcpad.
683 * @srcpad should be a pad of an element inside @media->element.
685 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
689 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
692 GstRTSPStream *stream;
697 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
698 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
699 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
700 g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
702 g_mutex_lock (&media->lock);
703 idx = media->streams->len;
705 name = g_strdup_printf ("src_%u", idx);
706 srcpad = gst_ghost_pad_new (name, pad);
707 gst_pad_set_active (srcpad, TRUE);
708 gst_element_add_pad (media->element, srcpad);
711 stream = gst_rtsp_stream_new (idx, payloader, srcpad);
713 gst_rtsp_stream_set_address_pool (stream, media->pool);
715 g_ptr_array_add (media->streams, stream);
716 g_mutex_unlock (&media->lock);
722 * gst_rtsp_media_n_streams:
723 * @media: a #GstRTSPMedia
725 * Get the number of streams in this media.
727 * Returns: The number of streams.
730 gst_rtsp_media_n_streams (GstRTSPMedia * media)
734 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
736 g_mutex_lock (&media->lock);
737 res = media->streams->len;
738 g_mutex_unlock (&media->lock);
744 * gst_rtsp_media_get_stream:
745 * @media: a #GstRTSPMedia
746 * @idx: the stream index
748 * Retrieve the stream with index @idx from @media.
750 * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
751 * that index did not exist.
754 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
758 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
760 g_mutex_lock (&media->lock);
761 if (idx < media->streams->len)
762 res = g_ptr_array_index (media->streams, idx);
765 g_mutex_unlock (&media->lock);
771 * gst_rtsp_media_get_range_string:
772 * @media: a #GstRTSPMedia
773 * @play: for the PLAY request
775 * Get the current range as a string.
777 * Returns: The range as a string, g_free() after usage.
780 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
783 GstRTSPTimeRange range;
785 g_mutex_lock (&media->lock);
787 range = media->range;
789 if (!play && media->n_active > 0) {
790 range.min.type = GST_RTSP_TIME_NOW;
791 range.min.seconds = -1;
793 g_mutex_unlock (&media->lock);
795 result = gst_rtsp_range_to_string (&range);
801 * gst_rtsp_media_seek:
802 * @media: a #GstRTSPMedia
803 * @range: a #GstRTSPTimeRange
805 * Seek the pipeline to @range.
807 * Returns: %TRUE on success.
810 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
815 GstSeekType start_type, stop_type;
817 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
818 g_return_val_if_fail (range != NULL, FALSE);
820 g_rec_mutex_lock (&media->state_lock);
821 if (!media->seekable)
824 if (range->unit != GST_RTSP_RANGE_NPT)
827 /* depends on the current playing state of the pipeline. We might need to
828 * queue this until we get EOS. */
829 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
831 start_type = stop_type = GST_SEEK_TYPE_NONE;
833 switch (range->min.type) {
834 case GST_RTSP_TIME_NOW:
837 case GST_RTSP_TIME_SECONDS:
838 /* only seek when something changed */
839 if (media->range.min.seconds == range->min.seconds) {
842 start = range->min.seconds * GST_SECOND;
843 start_type = GST_SEEK_TYPE_SET;
846 case GST_RTSP_TIME_END:
850 switch (range->max.type) {
851 case GST_RTSP_TIME_SECONDS:
852 /* only seek when something changed */
853 if (media->range.max.seconds == range->max.seconds) {
856 stop = range->max.seconds * GST_SECOND;
857 stop_type = GST_SEEK_TYPE_SET;
860 case GST_RTSP_TIME_END:
862 stop_type = GST_SEEK_TYPE_SET;
864 case GST_RTSP_TIME_NOW:
869 if (start != -1 || stop != -1) {
870 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
871 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
873 res = gst_element_seek (media->pipeline, 1.0, GST_FORMAT_TIME,
874 flags, start_type, start, stop_type, stop);
876 /* and block for the seek to complete */
877 GST_INFO ("done seeking %d", res);
878 gst_element_get_state (media->pipeline, NULL, NULL, -1);
879 GST_INFO ("prerolled again");
881 collect_media_stats (media);
883 GST_INFO ("no seek needed");
886 g_rec_mutex_unlock (&media->state_lock);
893 g_rec_mutex_unlock (&media->state_lock);
894 GST_INFO ("pipeline is not seekable");
899 g_rec_mutex_unlock (&media->state_lock);
900 GST_WARNING ("seek unit %d not supported", range->unit);
905 g_rec_mutex_unlock (&media->state_lock);
906 GST_WARNING ("weird range type %d not supported", range->min.type);
912 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
914 g_mutex_lock (&media->lock);
915 /* never overwrite the error status */
916 if (media->status != GST_RTSP_MEDIA_STATUS_ERROR)
917 media->status = status;
918 GST_DEBUG ("setting new status to %d", status);
919 g_cond_broadcast (&media->cond);
920 g_mutex_unlock (&media->lock);
923 static GstRTSPMediaStatus
924 gst_rtsp_media_get_status (GstRTSPMedia * media)
926 GstRTSPMediaStatus result;
929 g_mutex_lock (&media->lock);
930 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
931 /* while we are preparing, wait */
932 while (media->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
933 GST_DEBUG ("waiting for status change");
934 if (!g_cond_wait_until (&media->cond, &media->lock, end_time)) {
935 GST_DEBUG ("timeout, assuming error status");
936 media->status = GST_RTSP_MEDIA_STATUS_ERROR;
939 /* could be success or error */
940 result = media->status;
941 GST_DEBUG ("got status %d", result);
942 g_mutex_unlock (&media->lock);
947 /* called with state-lock */
949 default_handle_message (GstRTSPMedia * media, GstMessage * message)
953 type = GST_MESSAGE_TYPE (message);
956 case GST_MESSAGE_STATE_CHANGED:
958 case GST_MESSAGE_BUFFERING:
962 gst_message_parse_buffering (message, &percent);
964 /* no state management needed for live pipelines */
968 if (percent == 100) {
969 /* a 100% message means buffering is done */
970 media->buffering = FALSE;
971 /* if the desired state is playing, go back */
972 if (media->target_state == GST_STATE_PLAYING) {
973 GST_INFO ("Buffering done, setting pipeline to PLAYING");
974 gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
976 GST_INFO ("Buffering done");
980 if (media->buffering == FALSE) {
981 if (media->target_state == GST_STATE_PLAYING) {
982 /* we were not buffering but PLAYING, PAUSE the pipeline. */
983 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
984 gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
986 GST_INFO ("Buffering ...");
989 media->buffering = TRUE;
993 case GST_MESSAGE_LATENCY:
995 gst_bin_recalculate_latency (GST_BIN_CAST (media->pipeline));
998 case GST_MESSAGE_ERROR:
1003 gst_message_parse_error (message, &gerror, &debug);
1004 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1005 g_error_free (gerror);
1008 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1011 case GST_MESSAGE_WARNING:
1016 gst_message_parse_warning (message, &gerror, &debug);
1017 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1018 g_error_free (gerror);
1022 case GST_MESSAGE_ELEMENT:
1024 case GST_MESSAGE_STREAM_STATUS:
1026 case GST_MESSAGE_ASYNC_DONE:
1027 if (!media->adding) {
1028 /* when we are dynamically adding pads, the addition of the udpsrc will
1029 * temporarily produce ASYNC_DONE messages. We have to ignore them and
1030 * wait for the final ASYNC_DONE after everything prerolled */
1031 GST_INFO ("%p: got ASYNC_DONE", media);
1032 collect_media_stats (media);
1034 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1036 GST_INFO ("%p: ignoring ASYNC_DONE", media);
1039 case GST_MESSAGE_EOS:
1040 GST_INFO ("%p: got EOS", media);
1042 if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
1043 GST_DEBUG ("shutting down after EOS");
1044 finish_unprepare (media);
1045 g_object_unref (media);
1049 GST_INFO ("%p: got message type %s", media,
1050 gst_message_type_get_name (type));
1057 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1059 GstRTSPMediaClass *klass;
1062 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1064 g_rec_mutex_lock (&media->state_lock);
1065 if (klass->handle_message)
1066 ret = klass->handle_message (media, message);
1069 g_rec_mutex_unlock (&media->state_lock);
1074 /* called from streaming threads */
1076 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1078 GstRTSPStream *stream;
1080 /* FIXME, element is likely not a payloader, find the payloader here */
1081 stream = gst_rtsp_media_create_stream (media, element, pad);
1083 GST_INFO ("pad added %s:%s, stream %d", GST_DEBUG_PAD_NAME (pad),
1086 g_rec_mutex_lock (&media->state_lock);
1087 /* we will be adding elements below that will cause ASYNC_DONE to be
1088 * posted in the bus. We want to ignore those messages until the
1089 * pipeline really prerolled. */
1090 media->adding = TRUE;
1092 /* join the element in the PAUSED state because this callback is
1093 * called from the streaming thread and it is PAUSED */
1094 gst_rtsp_stream_join_bin (stream, GST_BIN (media->pipeline),
1095 media->rtpbin, GST_STATE_PAUSED);
1097 media->adding = FALSE;
1098 g_rec_mutex_unlock (&media->state_lock);
1102 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1104 GstElement *fakesink;
1106 g_mutex_lock (&media->lock);
1107 GST_INFO ("no more pads");
1108 if ((fakesink = media->fakesink)) {
1109 gst_object_ref (fakesink);
1110 media->fakesink = NULL;
1111 g_mutex_unlock (&media->lock);
1113 gst_bin_remove (GST_BIN (media->pipeline), fakesink);
1114 gst_element_set_state (fakesink, GST_STATE_NULL);
1115 gst_object_unref (fakesink);
1116 GST_INFO ("removed fakesink");
1121 * gst_rtsp_media_prepare:
1122 * @media: a #GstRTSPMedia
1124 * Prepare @media for streaming. This function will create the pipeline and
1125 * other objects to manage the streaming.
1127 * It will preroll the pipeline and collect vital information about the streams
1128 * such as the duration.
1130 * Returns: %TRUE on success.
1133 gst_rtsp_media_prepare (GstRTSPMedia * media)
1135 GstStateChangeReturn ret;
1136 GstRTSPMediaStatus status;
1138 GstRTSPMediaClass *klass;
1142 g_rec_mutex_lock (&media->state_lock);
1143 if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1146 if (media->status == GST_RTSP_MEDIA_STATUS_PREPARING)
1149 if (media->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
1150 goto not_unprepared;
1152 if (!media->reusable && media->reused)
1155 media->rtpbin = gst_element_factory_make ("rtpbin", NULL);
1156 if (media->rtpbin == NULL)
1159 GST_INFO ("preparing media %p", media);
1161 /* reset some variables */
1162 media->is_live = FALSE;
1163 media->seekable = FALSE;
1164 media->buffering = FALSE;
1165 /* we're preparing now */
1166 media->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1168 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (media->pipeline));
1170 /* add the pipeline bus to our custom mainloop */
1171 media->source = gst_bus_create_watch (bus);
1172 gst_object_unref (bus);
1174 g_source_set_callback (media->source, (GSourceFunc) bus_message, media, NULL);
1176 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1177 media->id = g_source_attach (media->source, klass->context);
1179 /* add stuff to the bin */
1180 gst_bin_add (GST_BIN (media->pipeline), media->rtpbin);
1182 /* link streams we already have, other streams might appear when we have
1183 * dynamic elements */
1184 for (i = 0; i < media->streams->len; i++) {
1185 GstRTSPStream *stream;
1187 stream = g_ptr_array_index (media->streams, i);
1189 gst_rtsp_stream_join_bin (stream, GST_BIN (media->pipeline),
1190 media->rtpbin, GST_STATE_NULL);
1193 for (walk = media->dynamic; walk; walk = g_list_next (walk)) {
1194 GstElement *elem = walk->data;
1196 GST_INFO ("adding callbacks for dynamic element %p", elem);
1198 g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1199 g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1201 /* we add a fakesink here in order to make the state change async. We remove
1202 * the fakesink again in the no-more-pads callback. */
1203 media->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1204 gst_bin_add (GST_BIN (media->pipeline), media->fakesink);
1207 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1208 /* first go to PAUSED */
1209 ret = gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
1210 media->target_state = GST_STATE_PAUSED;
1213 case GST_STATE_CHANGE_SUCCESS:
1214 GST_INFO ("SUCCESS state change for media %p", media);
1215 media->seekable = TRUE;
1217 case GST_STATE_CHANGE_ASYNC:
1218 GST_INFO ("ASYNC state change for media %p", media);
1219 media->seekable = TRUE;
1221 case GST_STATE_CHANGE_NO_PREROLL:
1222 /* we need to go to PLAYING */
1223 GST_INFO ("NO_PREROLL state change: live media %p", media);
1224 /* FIXME we disable seeking for live streams for now. We should perform a
1225 * seeking query in preroll instead */
1226 media->seekable = FALSE;
1227 media->is_live = TRUE;
1228 ret = gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1229 if (ret == GST_STATE_CHANGE_FAILURE)
1232 case GST_STATE_CHANGE_FAILURE:
1236 g_rec_mutex_unlock (&media->state_lock);
1238 /* now wait for all pads to be prerolled, FIXME, we should somehow be
1239 * able to do this async so that we don't block the server thread. */
1240 status = gst_rtsp_media_get_status (media);
1241 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1244 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
1246 GST_INFO ("object %p is prerolled", media);
1253 GST_LOG ("media %p was prepared", media);
1254 g_rec_mutex_unlock (&media->state_lock);
1260 GST_WARNING ("media %p was not unprepared", media);
1261 g_rec_mutex_unlock (&media->state_lock);
1266 g_rec_mutex_unlock (&media->state_lock);
1267 GST_WARNING ("can not reuse media %p", media);
1272 g_rec_mutex_unlock (&media->state_lock);
1273 GST_WARNING ("no rtpbin element");
1274 g_warning ("failed to create element 'rtpbin', check your installation");
1279 GST_WARNING ("failed to preroll pipeline");
1280 gst_rtsp_media_unprepare (media);
1281 g_rec_mutex_unlock (&media->state_lock);
1286 /* must be called with state-lock */
1288 finish_unprepare (GstRTSPMedia * media)
1292 GST_DEBUG ("shutting down");
1294 gst_element_set_state (media->pipeline, GST_STATE_NULL);
1296 for (i = 0; i < media->streams->len; i++) {
1297 GstRTSPStream *stream;
1299 GST_INFO ("Removing elements of stream %d from pipeline", i);
1301 stream = g_ptr_array_index (media->streams, i);
1303 gst_rtsp_stream_leave_bin (stream, GST_BIN (media->pipeline),
1306 g_ptr_array_set_size (media->streams, 0);
1308 gst_bin_remove (GST_BIN (media->pipeline), media->rtpbin);
1309 media->rtpbin = NULL;
1311 gst_object_unref (media->pipeline);
1312 media->pipeline = NULL;
1314 media->reused = TRUE;
1315 media->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1317 /* when the media is not reusable, this will effectively unref the media and
1319 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1322 /* called with state-lock */
1324 default_unprepare (GstRTSPMedia * media)
1326 if (media->eos_shutdown) {
1327 GST_DEBUG ("sending EOS for shutdown");
1328 /* ref so that we don't disappear */
1329 g_object_ref (media);
1330 gst_element_send_event (media->pipeline, gst_event_new_eos ());
1331 /* we need to go to playing again for the EOS to propagate, normally in this
1332 * state, nothing is receiving data from us anymore so this is ok. */
1333 gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1334 media->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
1336 finish_unprepare (media);
1342 * gst_rtsp_media_unprepare:
1343 * @media: a #GstRTSPMedia
1345 * Unprepare @media. After this call, the media should be prepared again before
1346 * it can be used again. If the media is set to be non-reusable, a new instance
1349 * Returns: %TRUE on success.
1352 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1356 g_rec_mutex_lock (&media->state_lock);
1357 if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1358 goto was_unprepared;
1360 GST_INFO ("unprepare media %p", media);
1361 media->target_state = GST_STATE_NULL;
1364 if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
1365 GstRTSPMediaClass *klass;
1367 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1368 if (klass->unprepare)
1369 success = klass->unprepare (media);
1371 finish_unprepare (media);
1373 g_rec_mutex_unlock (&media->state_lock);
1379 g_rec_mutex_unlock (&media->state_lock);
1380 GST_INFO ("media %p was already unprepared", media);
1386 * gst_rtsp_media_set_state:
1387 * @media: a #GstRTSPMedia
1388 * @state: the target state of the media
1389 * @transports: a #GPtrArray of #GstRTSPStreamTransport pointers
1391 * Set the state of @media to @state and for the transports in @transports.
1393 * Returns: %TRUE on success.
1396 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1397 GPtrArray * transports)
1400 gboolean add, remove, do_state;
1403 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1404 g_return_val_if_fail (transports != NULL, FALSE);
1406 g_rec_mutex_lock (&media->state_lock);
1408 /* NULL and READY are the same */
1409 if (state == GST_STATE_READY)
1410 state = GST_STATE_NULL;
1412 add = remove = FALSE;
1414 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1418 case GST_STATE_NULL:
1419 case GST_STATE_PAUSED:
1420 /* we're going from PLAYING to PAUSED, READY or NULL, remove */
1421 if (media->target_state == GST_STATE_PLAYING)
1424 case GST_STATE_PLAYING:
1425 /* we're going to PLAYING, add */
1431 old_active = media->n_active;
1433 for (i = 0; i < transports->len; i++) {
1434 GstRTSPStreamTransport *trans;
1436 /* we need a non-NULL entry in the array */
1437 trans = g_ptr_array_index (transports, i);
1441 /* we need a transport */
1442 if (!trans->transport)
1446 if (gst_rtsp_stream_add_transport (trans->stream, trans))
1448 } else if (remove) {
1449 if (gst_rtsp_stream_remove_transport (trans->stream, trans))
1454 /* we just added the first media, do the playing state change */
1455 if (old_active == 0 && add)
1457 /* if we have no more active media, do the downward state changes */
1458 else if (media->n_active == 0)
1463 GST_INFO ("state %d active %d media %p do_state %d", state, media->n_active,
1466 if (media->target_state != state) {
1468 if (state == GST_STATE_NULL) {
1469 gst_rtsp_media_unprepare (media);
1471 GST_INFO ("state %s media %p", gst_element_state_get_name (state),
1473 media->target_state = state;
1474 gst_element_set_state (media->pipeline, state);
1477 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
1481 /* remember where we are */
1482 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
1483 old_active != media->n_active))
1484 collect_media_stats (media);
1486 g_rec_mutex_unlock (&media->state_lock);