2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3 * Copyright (C) 2015 Centricular Ltd
4 * Author: Sebastian Dröge <sebastian@centricular.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 * @short_description: The media pipeline
24 * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession,
25 * #GstRTSPSessionMedia
27 * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the
28 * streaming to the clients. The actual data transfer is done by the
29 * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia.
31 * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the
32 * client does a DESCRIBE or SETUP of a resource.
34 * A media is created with gst_rtsp_media_new() that takes the element that will
35 * provide the streaming elements. For each of the streams, a new #GstRTSPStream
36 * object needs to be made with the gst_rtsp_media_create_stream() which takes
37 * the payloader element and the source pad that produces the RTP stream.
39 * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The
40 * prepare method will add rtpbin and sinks and sources to send and receive RTP
41 * and RTCP packets from the clients. Each stream srcpad is connected to an
42 * input into the internal rtpbin.
44 * It is also possible to dynamically create #GstRTSPStream objects during the
45 * prepare phase. With gst_rtsp_media_get_status() you can check the status of
48 * After the media is prepared, it is ready for streaming. It will usually be
49 * managed in a session with gst_rtsp_session_manage_media(). See
50 * #GstRTSPSession and #GstRTSPSessionMedia.
52 * The state of the media can be controlled with gst_rtsp_media_set_state ().
53 * Seeking can be done with gst_rtsp_media_seek().
55 * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
56 * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
59 * With gst_rtsp_media_set_shared(), the media can be shared between multiple
60 * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
61 * can be prepared again after an unprepare.
63 * Last reviewed on 2013-07-11 (1.0.0)
70 #include <gst/app/gstappsrc.h>
71 #include <gst/app/gstappsink.h>
73 #include <gst/sdp/gstmikey.h>
74 #include <gst/rtp/gstrtppayloads.h>
76 #define AES_128_KEY_LEN 16
77 #define AES_256_KEY_LEN 32
79 #define HMAC_32_KEY_LEN 4
80 #define HMAC_80_KEY_LEN 10
82 #include "rtsp-media.h"
84 #define GST_RTSP_MEDIA_GET_PRIVATE(obj) \
85 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
87 struct _GstRTSPMediaPrivate
92 /* protected by lock */
93 GstRTSPPermissions *permissions;
95 gboolean suspend_mode;
97 GstRTSPProfile profiles;
98 GstRTSPLowerTrans protocols;
100 gboolean eos_shutdown;
102 GstRTSPAddressPool *pool;
103 gchar *multicast_iface;
105 GstRTSPTransportMode transport_mode;
106 gboolean stop_on_disconnect;
109 GRecMutex state_lock; /* locking order: state lock, lock */
110 GPtrArray *streams; /* protected by lock */
111 GList *dynamic; /* protected by lock */
112 GstRTSPMediaStatus status; /* protected by lock */
117 /* the pipeline for the media */
118 GstElement *pipeline;
119 GstElement *fakesink; /* protected by lock */
122 GstRTSPThread *thread;
124 gboolean time_provider;
125 GstNetTimeProvider *nettime;
130 GstState target_state;
132 /* RTP session manager */
135 /* the range of media */
136 GstRTSPTimeRange range; /* protected by lock */
137 GstClockTime range_start;
138 GstClockTime range_stop;
140 GList *payloads; /* protected by lock */
141 GstClockTime rtx_time; /* protected by lock */
142 guint latency; /* protected by lock */
143 GstClock *clock; /* protected by lock */
144 GstRTSPPublishClockMode publish_clock_mode;
147 #define DEFAULT_SHARED FALSE
148 #define DEFAULT_SUSPEND_MODE GST_RTSP_SUSPEND_MODE_NONE
149 #define DEFAULT_REUSABLE FALSE
150 #define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP
151 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
152 GST_RTSP_LOWER_TRANS_TCP
153 #define DEFAULT_EOS_SHUTDOWN FALSE
154 #define DEFAULT_BUFFER_SIZE 0x80000
155 #define DEFAULT_TIME_PROVIDER FALSE
156 #define DEFAULT_LATENCY 200
157 #define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
158 #define DEFAULT_STOP_ON_DISCONNECT TRUE
160 /* define to dump received RTCP packets */
177 PROP_STOP_ON_DISCONNECT,
185 SIGNAL_REMOVED_STREAM,
193 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
194 #define GST_CAT_DEFAULT rtsp_media_debug
196 static void gst_rtsp_media_get_property (GObject * object, guint propid,
197 GValue * value, GParamSpec * pspec);
198 static void gst_rtsp_media_set_property (GObject * object, guint propid,
199 const GValue * value, GParamSpec * pspec);
200 static void gst_rtsp_media_finalize (GObject * obj);
202 static gboolean default_handle_message (GstRTSPMedia * media,
203 GstMessage * message);
204 static void finish_unprepare (GstRTSPMedia * media);
205 static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread);
206 static gboolean default_unprepare (GstRTSPMedia * media);
207 static gboolean default_suspend (GstRTSPMedia * media);
208 static gboolean default_unsuspend (GstRTSPMedia * media);
209 static gboolean default_convert_range (GstRTSPMedia * media,
210 GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
211 static gboolean default_query_position (GstRTSPMedia * media,
213 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
214 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
215 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
217 static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
219 static gboolean wait_preroll (GstRTSPMedia * media);
221 static GstElement *find_payload_element (GstElement * payloader);
223 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
225 #define C_ENUM(v) ((gint) v)
228 gst_rtsp_suspend_mode_get_type (void)
231 static const GEnumValue values[] = {
232 {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
233 {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
235 {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
240 if (g_once_init_enter (&id)) {
241 GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
242 g_once_init_leave (&id, tmp);
247 #define C_FLAGS(v) ((guint) v)
250 gst_rtsp_transport_mode_get_type (void)
253 static const GFlagsValue values[] = {
254 {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
256 {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
261 if (g_once_init_enter (&id)) {
262 GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
263 g_once_init_leave (&id, tmp);
269 gst_rtsp_publish_clock_mode_get_type (void)
272 static const GEnumValue values[] = {
273 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
274 "GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
275 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
276 "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
278 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
279 "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
284 if (g_once_init_enter (&id)) {
285 GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
286 g_once_init_leave (&id, tmp);
291 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
294 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
296 GObjectClass *gobject_class;
298 g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
300 gobject_class = G_OBJECT_CLASS (klass);
302 gobject_class->get_property = gst_rtsp_media_get_property;
303 gobject_class->set_property = gst_rtsp_media_set_property;
304 gobject_class->finalize = gst_rtsp_media_finalize;
306 g_object_class_install_property (gobject_class, PROP_SHARED,
307 g_param_spec_boolean ("shared", "Shared",
308 "If this media pipeline can be shared", DEFAULT_SHARED,
309 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
311 g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
312 g_param_spec_enum ("suspend-mode", "Suspend Mode",
313 "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
314 DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
316 g_object_class_install_property (gobject_class, PROP_REUSABLE,
317 g_param_spec_boolean ("reusable", "Reusable",
318 "If this media pipeline can be reused after an unprepare",
319 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
321 g_object_class_install_property (gobject_class, PROP_PROFILES,
322 g_param_spec_flags ("profiles", "Profiles",
323 "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
324 DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
326 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
327 g_param_spec_flags ("protocols", "Protocols",
328 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
329 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
331 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
332 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
333 "Send an EOS event to the pipeline before unpreparing",
334 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
337 g_param_spec_uint ("buffer-size", "Buffer Size",
338 "The kernel UDP buffer size to use", 0, G_MAXUINT,
339 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
341 g_object_class_install_property (gobject_class, PROP_ELEMENT,
342 g_param_spec_object ("element", "The Element",
343 "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
344 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
346 g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
347 g_param_spec_boolean ("time-provider", "Time Provider",
348 "Use a NetTimeProvider for clients",
349 DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
351 g_object_class_install_property (gobject_class, PROP_LATENCY,
352 g_param_spec_uint ("latency", "Latency",
353 "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
354 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
356 g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
357 g_param_spec_flags ("transport-mode", "Transport Mode",
358 "If this media pipeline can be used for PLAY or RECORD",
359 GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
360 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
362 g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
363 g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
364 "If this media pipeline should be stopped "
365 "when a client disconnects without TEARDOWN",
366 DEFAULT_STOP_ON_DISCONNECT,
367 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
369 g_object_class_install_property (gobject_class, PROP_CLOCK,
370 g_param_spec_object ("clock", "Clock",
371 "Clock to be used by the media pipeline",
372 GST_TYPE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
374 gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
375 g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
376 G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
377 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
379 gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
380 g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
381 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
382 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
383 GST_TYPE_RTSP_STREAM);
385 gst_rtsp_media_signals[SIGNAL_PREPARED] =
386 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
387 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
388 g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
390 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
391 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
392 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
393 g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
395 gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
396 g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
397 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
398 NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
400 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
401 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
402 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
403 g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
405 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
407 klass->handle_message = default_handle_message;
408 klass->prepare = default_prepare;
409 klass->unprepare = default_unprepare;
410 klass->suspend = default_suspend;
411 klass->unsuspend = default_unsuspend;
412 klass->convert_range = default_convert_range;
413 klass->query_position = default_query_position;
414 klass->query_stop = default_query_stop;
415 klass->create_rtpbin = default_create_rtpbin;
416 klass->setup_sdp = default_setup_sdp;
417 klass->handle_sdp = default_handle_sdp;
421 gst_rtsp_media_init (GstRTSPMedia * media)
423 GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
427 priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
428 g_mutex_init (&priv->lock);
429 g_cond_init (&priv->cond);
430 g_rec_mutex_init (&priv->state_lock);
432 priv->shared = DEFAULT_SHARED;
433 priv->suspend_mode = DEFAULT_SUSPEND_MODE;
434 priv->reusable = DEFAULT_REUSABLE;
435 priv->profiles = DEFAULT_PROFILES;
436 priv->protocols = DEFAULT_PROTOCOLS;
437 priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
438 priv->buffer_size = DEFAULT_BUFFER_SIZE;
439 priv->time_provider = DEFAULT_TIME_PROVIDER;
440 priv->transport_mode = DEFAULT_TRANSPORT_MODE;
441 priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
442 priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
446 gst_rtsp_media_finalize (GObject * obj)
448 GstRTSPMediaPrivate *priv;
451 media = GST_RTSP_MEDIA (obj);
454 GST_INFO ("finalize media %p", media);
456 if (priv->permissions)
457 gst_rtsp_permissions_unref (priv->permissions);
459 g_ptr_array_unref (priv->streams);
461 g_list_free_full (priv->dynamic, gst_object_unref);
464 gst_object_unref (priv->pipeline);
466 gst_object_unref (priv->nettime);
467 gst_object_unref (priv->element);
469 g_object_unref (priv->pool);
471 g_list_free (priv->payloads);
472 g_free (priv->multicast_iface);
473 g_mutex_clear (&priv->lock);
474 g_cond_clear (&priv->cond);
475 g_rec_mutex_clear (&priv->state_lock);
477 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
481 gst_rtsp_media_get_property (GObject * object, guint propid,
482 GValue * value, GParamSpec * pspec)
484 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
488 g_value_set_object (value, media->priv->element);
491 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
493 case PROP_SUSPEND_MODE:
494 g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
497 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
500 g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
503 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
505 case PROP_EOS_SHUTDOWN:
506 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
508 case PROP_BUFFER_SIZE:
509 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
511 case PROP_TIME_PROVIDER:
512 g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
515 g_value_set_uint (value, gst_rtsp_media_get_latency (media));
517 case PROP_TRANSPORT_MODE:
518 g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
520 case PROP_STOP_ON_DISCONNECT:
521 g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
524 g_value_take_object (value, gst_rtsp_media_get_clock (media));
527 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
532 gst_rtsp_media_set_property (GObject * object, guint propid,
533 const GValue * value, GParamSpec * pspec)
535 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
539 media->priv->element = g_value_get_object (value);
540 gst_object_ref_sink (media->priv->element);
543 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
545 case PROP_SUSPEND_MODE:
546 gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
549 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
552 gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
555 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
557 case PROP_EOS_SHUTDOWN:
558 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
560 case PROP_BUFFER_SIZE:
561 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
563 case PROP_TIME_PROVIDER:
564 gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
567 gst_rtsp_media_set_latency (media, g_value_get_uint (value));
569 case PROP_TRANSPORT_MODE:
570 gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
572 case PROP_STOP_ON_DISCONNECT:
573 gst_rtsp_media_set_stop_on_disconnect (media,
574 g_value_get_boolean (value));
577 gst_rtsp_media_set_clock (media, g_value_get_object (value));
580 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
588 } DoQueryPositionData;
591 do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
595 if (gst_rtsp_stream_query_position (stream, &tmp)) {
596 data->position = MAX (data->position, tmp);
602 default_query_position (GstRTSPMedia * media, gint64 * position)
604 GstRTSPMediaPrivate *priv;
605 DoQueryPositionData data;
612 g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
614 *position = data.position;
626 do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
630 if (gst_rtsp_stream_query_stop (stream, &tmp)) {
631 data->stop = MAX (data->stop, tmp);
637 default_query_stop (GstRTSPMedia * media, gint64 * stop)
639 GstRTSPMediaPrivate *priv;
640 DoQueryStopData data;
647 g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
655 default_create_rtpbin (GstRTSPMedia * media)
659 rtpbin = gst_element_factory_make ("rtpbin", NULL);
664 /* must be called with state lock */
666 collect_media_stats (GstRTSPMedia * media)
668 GstRTSPMediaPrivate *priv = media->priv;
669 gint64 position = 0, stop = -1;
671 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
672 priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
675 priv->range.unit = GST_RTSP_RANGE_NPT;
677 GST_INFO ("collect media stats");
680 priv->range.min.type = GST_RTSP_TIME_NOW;
681 priv->range.min.seconds = -1;
682 priv->range_start = -1;
683 priv->range.max.type = GST_RTSP_TIME_END;
684 priv->range.max.seconds = -1;
685 priv->range_stop = -1;
687 GstRTSPMediaClass *klass;
690 klass = GST_RTSP_MEDIA_GET_CLASS (media);
692 /* get the position */
694 if (klass->query_position)
695 ret = klass->query_position (media, &position);
698 GST_INFO ("position query failed");
702 /* get the current segment stop */
704 if (klass->query_stop)
705 ret = klass->query_stop (media, &stop);
708 GST_INFO ("stop query failed");
712 GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
713 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
715 if (position == -1) {
716 priv->range.min.type = GST_RTSP_TIME_NOW;
717 priv->range.min.seconds = -1;
718 priv->range_start = -1;
720 priv->range.min.type = GST_RTSP_TIME_SECONDS;
721 priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
722 priv->range_start = position;
725 priv->range.max.type = GST_RTSP_TIME_END;
726 priv->range.max.seconds = -1;
727 priv->range_stop = -1;
729 priv->range.max.type = GST_RTSP_TIME_SECONDS;
730 priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
731 priv->range_stop = stop;
737 * gst_rtsp_media_new:
738 * @element: (transfer full): a #GstElement
740 * Create a new #GstRTSPMedia instance. @element is the bin element that
741 * provides the different streams. The #GstRTSPMedia object contains the
742 * element to produce RTP data for one or more related (audio/video/..)
745 * Ownership is taken of @element.
747 * Returns: (transfer full): a new #GstRTSPMedia object.
750 gst_rtsp_media_new (GstElement * element)
752 GstRTSPMedia *result;
754 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
756 result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
762 * gst_rtsp_media_get_element:
763 * @media: a #GstRTSPMedia
765 * Get the element that was used when constructing @media.
767 * Returns: (transfer full): a #GstElement. Unref after usage.
770 gst_rtsp_media_get_element (GstRTSPMedia * media)
772 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
774 return gst_object_ref (media->priv->element);
778 * gst_rtsp_media_take_pipeline:
779 * @media: a #GstRTSPMedia
780 * @pipeline: (transfer full): a #GstPipeline
782 * Set @pipeline as the #GstPipeline for @media. Ownership is
783 * taken of @pipeline.
786 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
788 GstRTSPMediaPrivate *priv;
790 GstNetTimeProvider *nettime;
792 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
793 g_return_if_fail (GST_IS_PIPELINE (pipeline));
797 g_mutex_lock (&priv->lock);
798 old = priv->pipeline;
799 priv->pipeline = GST_ELEMENT_CAST (pipeline);
800 nettime = priv->nettime;
801 priv->nettime = NULL;
802 g_mutex_unlock (&priv->lock);
805 gst_object_unref (old);
808 gst_object_unref (nettime);
810 gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
814 * gst_rtsp_media_set_permissions:
815 * @media: a #GstRTSPMedia
816 * @permissions: (transfer none): a #GstRTSPPermissions
818 * Set @permissions on @media.
821 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
822 GstRTSPPermissions * permissions)
824 GstRTSPMediaPrivate *priv;
826 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
830 g_mutex_lock (&priv->lock);
831 if (priv->permissions)
832 gst_rtsp_permissions_unref (priv->permissions);
833 if ((priv->permissions = permissions))
834 gst_rtsp_permissions_ref (permissions);
835 g_mutex_unlock (&priv->lock);
839 * gst_rtsp_media_get_permissions:
840 * @media: a #GstRTSPMedia
842 * Get the permissions object from @media.
844 * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage.
847 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
849 GstRTSPMediaPrivate *priv;
850 GstRTSPPermissions *result;
852 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
856 g_mutex_lock (&priv->lock);
857 if ((result = priv->permissions))
858 gst_rtsp_permissions_ref (result);
859 g_mutex_unlock (&priv->lock);
865 * gst_rtsp_media_set_suspend_mode:
866 * @media: a #GstRTSPMedia
867 * @mode: the new #GstRTSPSuspendMode
869 * Control how @ media will be suspended after the SDP has been generated and
870 * after a PAUSE request has been performed.
872 * Media must be unprepared when setting the suspend mode.
875 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
877 GstRTSPMediaPrivate *priv;
879 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
883 g_rec_mutex_lock (&priv->state_lock);
884 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
886 priv->suspend_mode = mode;
887 g_rec_mutex_unlock (&priv->state_lock);
894 GST_WARNING ("media %p was prepared", media);
895 g_rec_mutex_unlock (&priv->state_lock);
900 * gst_rtsp_media_get_suspend_mode:
901 * @media: a #GstRTSPMedia
903 * Get how @media will be suspended.
905 * Returns: #GstRTSPSuspendMode.
908 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
910 GstRTSPMediaPrivate *priv;
911 GstRTSPSuspendMode res;
913 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
917 g_rec_mutex_lock (&priv->state_lock);
918 res = priv->suspend_mode;
919 g_rec_mutex_unlock (&priv->state_lock);
925 * gst_rtsp_media_set_shared:
926 * @media: a #GstRTSPMedia
927 * @shared: the new value
929 * Set or unset if the pipeline for @media can be shared will multiple clients.
930 * When @shared is %TRUE, client requests for this media will share the media
934 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
936 GstRTSPMediaPrivate *priv;
938 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
942 g_mutex_lock (&priv->lock);
943 priv->shared = shared;
944 g_mutex_unlock (&priv->lock);
948 * gst_rtsp_media_is_shared:
949 * @media: a #GstRTSPMedia
951 * Check if the pipeline for @media can be shared between multiple clients.
953 * Returns: %TRUE if the media can be shared between clients.
956 gst_rtsp_media_is_shared (GstRTSPMedia * media)
958 GstRTSPMediaPrivate *priv;
961 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
965 g_mutex_lock (&priv->lock);
967 g_mutex_unlock (&priv->lock);
973 * gst_rtsp_media_set_reusable:
974 * @media: a #GstRTSPMedia
975 * @reusable: the new value
977 * Set or unset if the pipeline for @media can be reused after the pipeline has
981 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
983 GstRTSPMediaPrivate *priv;
985 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
989 g_mutex_lock (&priv->lock);
990 priv->reusable = reusable;
991 g_mutex_unlock (&priv->lock);
995 * gst_rtsp_media_is_reusable:
996 * @media: a #GstRTSPMedia
998 * Check if the pipeline for @media can be reused after an unprepare.
1000 * Returns: %TRUE if the media can be reused
1003 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
1005 GstRTSPMediaPrivate *priv;
1008 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1012 g_mutex_lock (&priv->lock);
1013 res = priv->reusable;
1014 g_mutex_unlock (&priv->lock);
1020 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
1022 gst_rtsp_stream_set_profiles (stream, *profiles);
1026 * gst_rtsp_media_set_profiles:
1027 * @media: a #GstRTSPMedia
1028 * @profiles: the new flags
1030 * Configure the allowed lower transport for @media.
1033 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
1035 GstRTSPMediaPrivate *priv;
1037 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1041 g_mutex_lock (&priv->lock);
1042 priv->profiles = profiles;
1043 g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
1044 g_mutex_unlock (&priv->lock);
1048 * gst_rtsp_media_get_profiles:
1049 * @media: a #GstRTSPMedia
1051 * Get the allowed profiles of @media.
1053 * Returns: a #GstRTSPProfile
1056 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
1058 GstRTSPMediaPrivate *priv;
1061 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
1065 g_mutex_lock (&priv->lock);
1066 res = priv->profiles;
1067 g_mutex_unlock (&priv->lock);
1073 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
1075 gst_rtsp_stream_set_protocols (stream, *protocols);
1079 * gst_rtsp_media_set_protocols:
1080 * @media: a #GstRTSPMedia
1081 * @protocols: the new flags
1083 * Configure the allowed lower transport for @media.
1086 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
1088 GstRTSPMediaPrivate *priv;
1090 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1094 g_mutex_lock (&priv->lock);
1095 priv->protocols = protocols;
1096 g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
1097 g_mutex_unlock (&priv->lock);
1101 * gst_rtsp_media_get_protocols:
1102 * @media: a #GstRTSPMedia
1104 * Get the allowed protocols of @media.
1106 * Returns: a #GstRTSPLowerTrans
1109 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
1111 GstRTSPMediaPrivate *priv;
1112 GstRTSPLowerTrans res;
1114 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
1115 GST_RTSP_LOWER_TRANS_UNKNOWN);
1119 g_mutex_lock (&priv->lock);
1120 res = priv->protocols;
1121 g_mutex_unlock (&priv->lock);
1127 * gst_rtsp_media_set_eos_shutdown:
1128 * @media: a #GstRTSPMedia
1129 * @eos_shutdown: the new value
1131 * Set or unset if an EOS event will be sent to the pipeline for @media before
1135 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
1137 GstRTSPMediaPrivate *priv;
1139 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1143 g_mutex_lock (&priv->lock);
1144 priv->eos_shutdown = eos_shutdown;
1145 g_mutex_unlock (&priv->lock);
1149 * gst_rtsp_media_is_eos_shutdown:
1150 * @media: a #GstRTSPMedia
1152 * Check if the pipeline for @media will send an EOS down the pipeline before
1155 * Returns: %TRUE if the media will send EOS before unpreparing.
1158 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
1160 GstRTSPMediaPrivate *priv;
1163 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1167 g_mutex_lock (&priv->lock);
1168 res = priv->eos_shutdown;
1169 g_mutex_unlock (&priv->lock);
1175 * gst_rtsp_media_set_buffer_size:
1176 * @media: a #GstRTSPMedia
1177 * @size: the new value
1179 * Set the kernel UDP buffer size.
1182 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1184 GstRTSPMediaPrivate *priv;
1187 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1189 GST_LOG_OBJECT (media, "set buffer size %u", size);
1193 g_mutex_lock (&priv->lock);
1194 priv->buffer_size = size;
1196 for (i = 0; i < priv->streams->len; i++) {
1197 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1198 gst_rtsp_stream_set_buffer_size (stream, size);
1200 g_mutex_unlock (&priv->lock);
1204 * gst_rtsp_media_get_buffer_size:
1205 * @media: a #GstRTSPMedia
1207 * Get the kernel UDP buffer size.
1209 * Returns: the kernel UDP buffer size.
1212 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1214 GstRTSPMediaPrivate *priv;
1217 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1221 g_mutex_lock (&priv->lock);
1222 res = priv->buffer_size;
1223 g_mutex_unlock (&priv->lock);
1229 * gst_rtsp_media_set_stop_on_disconnect:
1230 * @media: a #GstRTSPMedia
1231 * @stop_on_disconnect: the new value
1233 * Set or unset if the pipeline for @media should be stopped when a
1234 * client disconnects without sending TEARDOWN.
1237 gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
1238 gboolean stop_on_disconnect)
1240 GstRTSPMediaPrivate *priv;
1242 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1246 g_mutex_lock (&priv->lock);
1247 priv->stop_on_disconnect = stop_on_disconnect;
1248 g_mutex_unlock (&priv->lock);
1252 * gst_rtsp_media_is_stop_on_disconnect:
1253 * @media: a #GstRTSPMedia
1255 * Check if the pipeline for @media will be stopped when a client disconnects
1256 * without sending TEARDOWN.
1258 * Returns: %TRUE if the media will be stopped when a client disconnects
1259 * without sending TEARDOWN.
1262 gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
1264 GstRTSPMediaPrivate *priv;
1267 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
1271 g_mutex_lock (&priv->lock);
1272 res = priv->stop_on_disconnect;
1273 g_mutex_unlock (&priv->lock);
1279 * gst_rtsp_media_set_retransmission_time:
1280 * @media: a #GstRTSPMedia
1281 * @time: the new value
1283 * Set the amount of time to store retransmission packets.
1286 gst_rtsp_media_set_retransmission_time (GstRTSPMedia * media, GstClockTime time)
1288 GstRTSPMediaPrivate *priv;
1291 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1293 GST_LOG_OBJECT (media, "set retransmission time %" G_GUINT64_FORMAT, time);
1297 g_mutex_lock (&priv->lock);
1298 priv->rtx_time = time;
1299 for (i = 0; i < priv->streams->len; i++) {
1300 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1302 gst_rtsp_stream_set_retransmission_time (stream, time);
1306 g_object_set (priv->rtpbin, "do-retransmission", time > 0, NULL);
1307 g_mutex_unlock (&priv->lock);
1311 * gst_rtsp_media_get_retransmission_time:
1312 * @media: a #GstRTSPMedia
1314 * Get the amount of time to store retransmission data.
1316 * Returns: the amount of time to store retransmission data.
1319 gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
1321 GstRTSPMediaPrivate *priv;
1324 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1328 g_mutex_lock (&priv->lock);
1329 res = priv->rtx_time;
1330 g_mutex_unlock (&priv->lock);
1336 * gst_rtsp_media_set_latency:
1337 * @media: a #GstRTSPMedia
1338 * @latency: latency in milliseconds
1340 * Configure the latency used for receiving media.
1343 gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
1345 GstRTSPMediaPrivate *priv;
1347 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1349 GST_LOG_OBJECT (media, "set latency %ums", latency);
1353 g_mutex_lock (&priv->lock);
1354 priv->latency = latency;
1356 g_object_set (priv->rtpbin, "latency", latency, NULL);
1357 g_mutex_unlock (&priv->lock);
1361 * gst_rtsp_media_get_latency:
1362 * @media: a #GstRTSPMedia
1364 * Get the latency that is used for receiving media.
1366 * Returns: latency in milliseconds
1369 gst_rtsp_media_get_latency (GstRTSPMedia * media)
1371 GstRTSPMediaPrivate *priv;
1374 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1378 g_mutex_lock (&priv->lock);
1379 res = priv->latency;
1380 g_mutex_unlock (&priv->lock);
1386 * gst_rtsp_media_use_time_provider:
1387 * @media: a #GstRTSPMedia
1388 * @time_provider: if a #GstNetTimeProvider should be used
1390 * Set @media to provide a #GstNetTimeProvider.
1393 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1395 GstRTSPMediaPrivate *priv;
1397 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1401 g_mutex_lock (&priv->lock);
1402 priv->time_provider = time_provider;
1403 g_mutex_unlock (&priv->lock);
1407 * gst_rtsp_media_is_time_provider:
1408 * @media: a #GstRTSPMedia
1410 * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1412 * Use gst_rtsp_media_get_time_provider() to get the network clock.
1414 * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1417 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1419 GstRTSPMediaPrivate *priv;
1422 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1426 g_mutex_lock (&priv->lock);
1427 res = priv->time_provider;
1428 g_mutex_unlock (&priv->lock);
1434 * gst_rtsp_media_set_clock:
1435 * @media: a #GstRTSPMedia
1436 * @clock: #GstClock to be used
1438 * Configure the clock used for the media.
1441 gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
1443 GstRTSPMediaPrivate *priv;
1445 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1446 g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1448 GST_LOG_OBJECT (media, "setting clock %" GST_PTR_FORMAT, clock);
1452 g_mutex_lock (&priv->lock);
1454 gst_object_unref (priv->clock);
1455 priv->clock = clock ? gst_object_ref (clock) : NULL;
1456 if (priv->pipeline) {
1458 gst_pipeline_use_clock (GST_PIPELINE_CAST (priv->pipeline), clock);
1460 gst_pipeline_auto_clock (GST_PIPELINE_CAST (priv->pipeline));
1463 g_mutex_unlock (&priv->lock);
1467 * gst_rtsp_media_set_publish_clock_mode:
1468 * @media: a #GstRTSPMedia
1469 * @mode: the clock publish mode
1471 * Sets if and how the media clock should be published according to RFC7273.
1476 gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
1477 GstRTSPPublishClockMode mode)
1479 GstRTSPMediaPrivate *priv;
1483 g_mutex_lock (&priv->lock);
1484 priv->publish_clock_mode = mode;
1486 n = priv->streams->len;
1487 for (i = 0; i < n; i++) {
1488 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1490 gst_rtsp_stream_set_publish_clock_mode (stream, mode);
1492 g_mutex_unlock (&priv->lock);
1496 * gst_rtsp_media_get_publish_clock_mode:
1497 * @factory: a #GstRTSPMedia
1499 * Gets if and how the media clock should be published according to RFC7273.
1501 * Returns: The GstRTSPPublishClockMode
1505 GstRTSPPublishClockMode
1506 gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
1508 GstRTSPMediaPrivate *priv;
1509 GstRTSPPublishClockMode ret;
1512 g_mutex_lock (&priv->lock);
1513 ret = priv->publish_clock_mode;
1514 g_mutex_unlock (&priv->lock);
1520 * gst_rtsp_media_set_address_pool:
1521 * @media: a #GstRTSPMedia
1522 * @pool: (transfer none): a #GstRTSPAddressPool
1524 * configure @pool to be used as the address pool of @media.
1527 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1528 GstRTSPAddressPool * pool)
1530 GstRTSPMediaPrivate *priv;
1531 GstRTSPAddressPool *old;
1533 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1537 GST_LOG_OBJECT (media, "set address pool %p", pool);
1539 g_mutex_lock (&priv->lock);
1540 if ((old = priv->pool) != pool)
1541 priv->pool = pool ? g_object_ref (pool) : NULL;
1544 g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1546 g_mutex_unlock (&priv->lock);
1549 g_object_unref (old);
1553 * gst_rtsp_media_get_address_pool:
1554 * @media: a #GstRTSPMedia
1556 * Get the #GstRTSPAddressPool used as the address pool of @media.
1558 * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after
1561 GstRTSPAddressPool *
1562 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1564 GstRTSPMediaPrivate *priv;
1565 GstRTSPAddressPool *result;
1567 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1571 g_mutex_lock (&priv->lock);
1572 if ((result = priv->pool))
1573 g_object_ref (result);
1574 g_mutex_unlock (&priv->lock);
1580 * gst_rtsp_media_set_multicast_iface:
1581 * @media: a #GstRTSPMedia
1582 * @multicast_iface: (transfer none): a multicast interface name
1584 * configure @multicast_iface to be used for @media.
1587 gst_rtsp_media_set_multicast_iface (GstRTSPMedia * media,
1588 const gchar * multicast_iface)
1590 GstRTSPMediaPrivate *priv;
1593 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1597 GST_LOG_OBJECT (media, "set multicast interface %s", multicast_iface);
1599 g_mutex_lock (&priv->lock);
1600 if ((old = priv->multicast_iface) != multicast_iface)
1601 priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
1604 g_ptr_array_foreach (priv->streams,
1605 (GFunc) gst_rtsp_stream_set_multicast_iface, (gchar *) multicast_iface);
1606 g_mutex_unlock (&priv->lock);
1613 * gst_rtsp_media_get_multicast_iface:
1614 * @media: a #GstRTSPMedia
1616 * Get the multicast interface used for @media.
1618 * Returns: (transfer full): the multicast interface for @media. g_free() after
1622 gst_rtsp_media_get_multicast_iface (GstRTSPMedia * media)
1624 GstRTSPMediaPrivate *priv;
1627 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1631 g_mutex_lock (&priv->lock);
1632 if ((result = priv->multicast_iface))
1633 result = g_strdup (result);
1634 g_mutex_unlock (&priv->lock);
1640 _find_payload_types (GstRTSPMedia * media)
1643 GQueue queue = G_QUEUE_INIT;
1645 n = media->priv->streams->len;
1646 for (i = 0; i < n; i++) {
1647 GstRTSPStream *stream = g_ptr_array_index (media->priv->streams, i);
1648 guint pt = gst_rtsp_stream_get_pt (stream);
1650 g_queue_push_tail (&queue, GUINT_TO_POINTER (pt));
1657 _next_available_pt (GList * payloads)
1661 for (i = 96; i <= 127; i++) {
1662 GList *iter = g_list_find (payloads, GINT_TO_POINTER (i));
1664 return GPOINTER_TO_UINT (i);
1671 * gst_rtsp_media_collect_streams:
1672 * @media: a #GstRTSPMedia
1674 * Find all payloader elements, they should be named pay\%d in the
1675 * element of @media, and create #GstRTSPStreams for them.
1677 * Collect all dynamic elements, named dynpay\%d, and add them to
1678 * the list of dynamic elements.
1680 * Find all depayloader elements, they should be named depay\%d in the
1681 * element of @media, and create #GstRTSPStreams for them.
1684 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
1686 GstRTSPMediaPrivate *priv;
1687 GstElement *element, *elem;
1691 gboolean more_elem_remaining = TRUE;
1692 GstRTSPTransportMode mode = 0;
1694 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1697 element = priv->element;
1700 for (i = 0; more_elem_remaining; i++) {
1703 more_elem_remaining = FALSE;
1705 name = g_strdup_printf ("pay%d", i);
1706 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1708 GST_INFO ("found stream %d with payloader %p", i, elem);
1710 /* take the pad of the payloader */
1711 pad = gst_element_get_static_pad (elem, "src");
1713 /* find the real payload element in case elem is a GstBin */
1714 pay = find_payload_element (elem);
1716 /* create the stream */
1718 GST_WARNING ("could not find real payloader, using bin");
1719 gst_rtsp_media_create_stream (media, elem, pad);
1721 gst_rtsp_media_create_stream (media, pay, pad);
1722 gst_object_unref (pay);
1725 gst_object_unref (pad);
1726 gst_object_unref (elem);
1729 more_elem_remaining = TRUE;
1730 mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
1734 name = g_strdup_printf ("dynpay%d", i);
1735 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1736 /* a stream that will dynamically create pads to provide RTP packets */
1737 GST_INFO ("found dynamic element %d, %p", i, elem);
1739 g_mutex_lock (&priv->lock);
1740 priv->dynamic = g_list_prepend (priv->dynamic, elem);
1741 g_mutex_unlock (&priv->lock);
1744 more_elem_remaining = TRUE;
1745 mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
1749 name = g_strdup_printf ("depay%d", i);
1750 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
1751 GST_INFO ("found stream %d with depayloader %p", i, elem);
1753 /* take the pad of the payloader */
1754 pad = gst_element_get_static_pad (elem, "sink");
1755 /* create the stream */
1756 gst_rtsp_media_create_stream (media, elem, pad);
1757 gst_object_unref (pad);
1758 gst_object_unref (elem);
1761 more_elem_remaining = TRUE;
1762 mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
1768 if (priv->transport_mode != mode)
1769 GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
1770 priv->transport_mode, mode);
1775 * gst_rtsp_media_create_stream:
1776 * @media: a #GstRTSPMedia
1777 * @payloader: a #GstElement
1780 * Create a new stream in @media that provides RTP data on @pad.
1781 * @pad should be a pad of an element inside @media->element.
1783 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
1787 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
1790 GstRTSPMediaPrivate *priv;
1791 GstRTSPStream *stream;
1796 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1797 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
1798 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1802 g_mutex_lock (&priv->lock);
1803 idx = priv->streams->len;
1805 GST_DEBUG ("media %p: creating stream with index %d", media, idx);
1807 if (GST_PAD_IS_SRC (pad))
1808 name = g_strdup_printf ("src_%u", idx);
1810 name = g_strdup_printf ("sink_%u", idx);
1812 ghostpad = gst_ghost_pad_new (name, pad);
1813 gst_pad_set_active (ghostpad, TRUE);
1814 gst_element_add_pad (priv->element, ghostpad);
1817 stream = gst_rtsp_stream_new (idx, payloader, ghostpad);
1819 gst_rtsp_stream_set_address_pool (stream, priv->pool);
1820 gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface);
1821 gst_rtsp_stream_set_profiles (stream, priv->profiles);
1822 gst_rtsp_stream_set_protocols (stream, priv->protocols);
1823 gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
1824 gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
1825 gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
1827 g_ptr_array_add (priv->streams, stream);
1829 if (GST_PAD_IS_SRC (pad)) {
1833 g_list_free (priv->payloads);
1834 priv->payloads = _find_payload_types (media);
1836 n = priv->streams->len;
1837 for (i = 0; i < n; i++) {
1838 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1839 guint rtx_pt = _next_available_pt (priv->payloads);
1842 GST_WARNING ("Ran out of space of dynamic payload types");
1846 gst_rtsp_stream_set_retransmission_pt (stream, rtx_pt);
1849 g_list_append (priv->payloads, GUINT_TO_POINTER (rtx_pt));
1852 g_mutex_unlock (&priv->lock);
1854 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
1861 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
1863 GstRTSPMediaPrivate *priv;
1868 g_mutex_lock (&priv->lock);
1869 /* remove the ghostpad */
1870 srcpad = gst_rtsp_stream_get_srcpad (stream);
1871 gst_element_remove_pad (priv->element, srcpad);
1872 gst_object_unref (srcpad);
1873 /* now remove the stream */
1874 g_object_ref (stream);
1875 g_ptr_array_remove (priv->streams, stream);
1876 g_mutex_unlock (&priv->lock);
1878 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
1881 g_object_unref (stream);
1885 * gst_rtsp_media_n_streams:
1886 * @media: a #GstRTSPMedia
1888 * Get the number of streams in this media.
1890 * Returns: The number of streams.
1893 gst_rtsp_media_n_streams (GstRTSPMedia * media)
1895 GstRTSPMediaPrivate *priv;
1898 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1902 g_mutex_lock (&priv->lock);
1903 res = priv->streams->len;
1904 g_mutex_unlock (&priv->lock);
1910 * gst_rtsp_media_get_stream:
1911 * @media: a #GstRTSPMedia
1912 * @idx: the stream index
1914 * Retrieve the stream with index @idx from @media.
1916 * Returns: (nullable) (transfer none): the #GstRTSPStream at index
1917 * @idx or %NULL when a stream with that index did not exist.
1920 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
1922 GstRTSPMediaPrivate *priv;
1925 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1929 g_mutex_lock (&priv->lock);
1930 if (idx < priv->streams->len)
1931 res = g_ptr_array_index (priv->streams, idx);
1934 g_mutex_unlock (&priv->lock);
1940 * gst_rtsp_media_find_stream:
1941 * @media: a #GstRTSPMedia
1942 * @control: the control of the stream
1944 * Find a stream in @media with @control as the control uri.
1946 * Returns: (nullable) (transfer none): the #GstRTSPStream with
1947 * control uri @control or %NULL when a stream with that control did
1951 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
1953 GstRTSPMediaPrivate *priv;
1957 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1958 g_return_val_if_fail (control != NULL, NULL);
1964 g_mutex_lock (&priv->lock);
1965 for (i = 0; i < priv->streams->len; i++) {
1966 GstRTSPStream *test;
1968 test = g_ptr_array_index (priv->streams, i);
1969 if (gst_rtsp_stream_has_control (test, control)) {
1974 g_mutex_unlock (&priv->lock);
1979 /* called with state-lock */
1981 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
1982 GstRTSPRangeUnit unit)
1984 return gst_rtsp_range_convert_units (range, unit);
1988 * gst_rtsp_media_get_range_string:
1989 * @media: a #GstRTSPMedia
1990 * @play: for the PLAY request
1991 * @unit: the unit to use for the string
1993 * Get the current range as a string. @media must be prepared with
1994 * gst_rtsp_media_prepare ().
1996 * Returns: (transfer full): The range as a string, g_free() after usage.
1999 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
2000 GstRTSPRangeUnit unit)
2002 GstRTSPMediaClass *klass;
2003 GstRTSPMediaPrivate *priv;
2005 GstRTSPTimeRange range;
2007 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2008 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2009 g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2013 g_rec_mutex_lock (&priv->state_lock);
2014 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2015 priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2018 g_mutex_lock (&priv->lock);
2020 /* Update the range value with current position/duration */
2021 collect_media_stats (media);
2024 range = priv->range;
2026 if (!play && priv->n_active > 0) {
2027 range.min.type = GST_RTSP_TIME_NOW;
2028 range.min.seconds = -1;
2030 g_mutex_unlock (&priv->lock);
2031 g_rec_mutex_unlock (&priv->state_lock);
2033 if (!klass->convert_range (media, &range, unit))
2034 goto conversion_failed;
2036 result = gst_rtsp_range_to_string (&range);
2043 GST_WARNING ("media %p was not prepared", media);
2044 g_rec_mutex_unlock (&priv->state_lock);
2049 GST_WARNING ("range conversion to unit %d failed", unit);
2055 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
2057 gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
2061 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
2063 GstRTSPMediaPrivate *priv = media->priv;
2065 GST_DEBUG ("media %p set blocked %d", media, blocked);
2066 priv->blocked = blocked;
2067 g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
2071 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
2073 GstRTSPMediaPrivate *priv = media->priv;
2075 g_mutex_lock (&priv->lock);
2076 priv->status = status;
2077 GST_DEBUG ("setting new status to %d", status);
2078 g_cond_broadcast (&priv->cond);
2079 g_mutex_unlock (&priv->lock);
2083 * gst_rtsp_media_get_status:
2084 * @media: a #GstRTSPMedia
2086 * Get the status of @media. When @media is busy preparing, this function waits
2087 * until @media is prepared or in error.
2089 * Returns: the status of @media.
2092 gst_rtsp_media_get_status (GstRTSPMedia * media)
2094 GstRTSPMediaPrivate *priv = media->priv;
2095 GstRTSPMediaStatus result;
2098 g_mutex_lock (&priv->lock);
2099 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
2100 /* while we are preparing, wait */
2101 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
2102 GST_DEBUG ("waiting for status change");
2103 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
2104 GST_DEBUG ("timeout, assuming error status");
2105 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
2108 /* could be success or error */
2109 result = priv->status;
2110 GST_DEBUG ("got status %d", result);
2111 g_mutex_unlock (&priv->lock);
2117 * gst_rtsp_media_seek:
2118 * @media: a #GstRTSPMedia
2119 * @range: (transfer none): a #GstRTSPTimeRange
2121 * Seek the pipeline of @media to @range. @media must be prepared with
2122 * gst_rtsp_media_prepare().
2124 * Returns: %TRUE on success.
2127 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
2129 GstRTSPMediaClass *klass;
2130 GstRTSPMediaPrivate *priv;
2132 GstClockTime start, stop;
2133 GstSeekType start_type, stop_type;
2135 gint64 current_position;
2137 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2139 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2140 g_return_val_if_fail (range != NULL, FALSE);
2141 g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2145 g_rec_mutex_lock (&priv->state_lock);
2146 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2149 /* Update the seekable state of the pipeline in case it changed */
2150 if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
2151 /* TODO: Seeking for RECORD? */
2152 priv->seekable = FALSE;
2154 guint i, n = priv->streams->len;
2156 for (i = 0; i < n; i++) {
2157 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2159 if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
2160 GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
2161 priv->seekable = FALSE;
2166 query = gst_query_new_seeking (GST_FORMAT_TIME);
2167 if (gst_element_query (priv->pipeline, query)) {
2172 gst_query_parse_seeking (query, &format, &seekable, &start, &end);
2173 priv->seekable = seekable;
2176 gst_query_unref (query);
2179 if (!priv->seekable)
2182 start_type = stop_type = GST_SEEK_TYPE_NONE;
2184 if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
2186 gst_rtsp_range_get_times (range, &start, &stop);
2188 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2189 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2190 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2191 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
2193 current_position = -1;
2194 if (klass->query_position)
2195 klass->query_position (media, ¤t_position);
2196 GST_INFO ("current media position %" GST_TIME_FORMAT,
2197 GST_TIME_ARGS (current_position));
2199 if (start != GST_CLOCK_TIME_NONE)
2200 start_type = GST_SEEK_TYPE_SET;
2202 if (priv->range_stop == stop)
2203 stop = GST_CLOCK_TIME_NONE;
2204 else if (stop != GST_CLOCK_TIME_NONE)
2205 stop_type = GST_SEEK_TYPE_SET;
2207 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
2210 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2211 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2213 /* depends on the current playing state of the pipeline. We might need to
2214 * queue this until we get EOS. */
2215 flags = GST_SEEK_FLAG_FLUSH;
2217 /* if range start was not supplied we must continue from current position.
2218 * but since we're doing a flushing seek, let us query the current position
2219 * so we end up at exactly the same position after the seek. */
2220 if (range->min.type == GST_RTSP_TIME_END) { /* Yepp, that's right! */
2221 if (current_position == -1) {
2222 GST_WARNING ("current position unknown");
2224 GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
2225 GST_TIME_ARGS (current_position));
2226 start = current_position;
2227 start_type = GST_SEEK_TYPE_SET;
2228 flags |= GST_SEEK_FLAG_ACCURATE;
2231 /* only set keyframe flag when modifying start */
2232 if (start_type != GST_SEEK_TYPE_NONE)
2233 flags |= GST_SEEK_FLAG_KEY_UNIT;
2236 if (start == current_position && stop_type == GST_SEEK_TYPE_NONE) {
2237 GST_DEBUG ("not seeking because no position change");
2240 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2242 media_streams_set_blocked (media, TRUE);
2244 /* FIXME, we only do forwards playback, no trick modes yet */
2245 res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
2246 flags, start_type, start, stop_type, stop);
2248 /* and block for the seek to complete */
2249 GST_INFO ("done seeking %d", res);
2253 g_rec_mutex_unlock (&priv->state_lock);
2255 /* wait until pipeline is prerolled again, this will also collect stats */
2256 if (!wait_preroll (media))
2257 goto preroll_failed;
2259 g_rec_mutex_lock (&priv->state_lock);
2260 GST_INFO ("prerolled again");
2263 GST_INFO ("no seek needed");
2266 g_rec_mutex_unlock (&priv->state_lock);
2273 g_rec_mutex_unlock (&priv->state_lock);
2274 GST_INFO ("media %p is not prepared", media);
2279 g_rec_mutex_unlock (&priv->state_lock);
2280 GST_INFO ("pipeline is not seekable");
2285 g_rec_mutex_unlock (&priv->state_lock);
2286 GST_WARNING ("conversion to npt not supported");
2291 g_rec_mutex_unlock (&priv->state_lock);
2292 GST_INFO ("seeking failed");
2293 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2298 GST_WARNING ("failed to preroll after seek");
2304 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
2306 *blocked &= gst_rtsp_stream_is_blocking (stream);
2310 media_streams_blocking (GstRTSPMedia * media)
2312 gboolean blocking = TRUE;
2314 g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
2320 static GstStateChangeReturn
2321 set_state (GstRTSPMedia * media, GstState state)
2323 GstRTSPMediaPrivate *priv = media->priv;
2324 GstStateChangeReturn ret;
2326 GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
2328 ret = gst_element_set_state (priv->pipeline, state);
2333 static GstStateChangeReturn
2334 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
2336 GstRTSPMediaPrivate *priv = media->priv;
2337 GstStateChangeReturn ret;
2339 GST_INFO ("set target state to %s for media %p",
2340 gst_element_state_get_name (state), media);
2341 priv->target_state = state;
2343 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
2344 priv->target_state, NULL);
2347 ret = set_state (media, state);
2349 ret = GST_STATE_CHANGE_SUCCESS;
2354 /* called with state-lock */
2356 default_handle_message (GstRTSPMedia * media, GstMessage * message)
2358 GstRTSPMediaPrivate *priv = media->priv;
2359 GstMessageType type;
2361 type = GST_MESSAGE_TYPE (message);
2364 case GST_MESSAGE_STATE_CHANGED:
2366 GstState old, new, pending;
2368 if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
2371 gst_message_parse_state_changed (message, &old, &new, &pending);
2373 GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
2374 gst_element_state_get_name (old), gst_element_state_get_name (new),
2375 gst_element_state_get_name (pending));
2376 if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)
2377 && old == GST_STATE_READY && new == GST_STATE_PAUSED) {
2378 GST_INFO ("%p: went to PAUSED, prepared now", media);
2379 collect_media_stats (media);
2381 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2382 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2387 case GST_MESSAGE_BUFFERING:
2391 gst_message_parse_buffering (message, &percent);
2393 /* no state management needed for live pipelines */
2397 if (percent == 100) {
2398 /* a 100% message means buffering is done */
2399 priv->buffering = FALSE;
2400 /* if the desired state is playing, go back */
2401 if (priv->target_state == GST_STATE_PLAYING) {
2402 GST_INFO ("Buffering done, setting pipeline to PLAYING");
2403 set_state (media, GST_STATE_PLAYING);
2405 GST_INFO ("Buffering done");
2408 /* buffering busy */
2409 if (priv->buffering == FALSE) {
2410 if (priv->target_state == GST_STATE_PLAYING) {
2411 /* we were not buffering but PLAYING, PAUSE the pipeline. */
2412 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
2413 set_state (media, GST_STATE_PAUSED);
2415 GST_INFO ("Buffering ...");
2418 priv->buffering = TRUE;
2422 case GST_MESSAGE_LATENCY:
2424 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
2427 case GST_MESSAGE_ERROR:
2432 gst_message_parse_error (message, &gerror, &debug);
2433 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
2434 g_error_free (gerror);
2437 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2440 case GST_MESSAGE_WARNING:
2445 gst_message_parse_warning (message, &gerror, &debug);
2446 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
2447 g_error_free (gerror);
2451 case GST_MESSAGE_ELEMENT:
2453 const GstStructure *s;
2455 s = gst_message_get_structure (message);
2456 if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
2457 GST_DEBUG ("media received blocking message");
2458 if (priv->blocked && media_streams_blocking (media)) {
2459 GST_DEBUG ("media is blocking");
2460 collect_media_stats (media);
2462 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2463 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2468 case GST_MESSAGE_STREAM_STATUS:
2470 case GST_MESSAGE_ASYNC_DONE:
2472 /* when we are dynamically adding pads, the addition of the udpsrc will
2473 * temporarily produce ASYNC_DONE messages. We have to ignore them and
2474 * wait for the final ASYNC_DONE after everything prerolled */
2475 GST_INFO ("%p: ignoring ASYNC_DONE", media);
2477 GST_INFO ("%p: got ASYNC_DONE", media);
2478 collect_media_stats (media);
2480 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2481 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2484 case GST_MESSAGE_EOS:
2485 GST_INFO ("%p: got EOS", media);
2487 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
2488 GST_DEBUG ("shutting down after EOS");
2489 finish_unprepare (media);
2493 GST_INFO ("%p: got message type %d (%s)", media, type,
2494 gst_message_type_get_name (type));
2501 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
2503 GstRTSPMediaPrivate *priv = media->priv;
2504 GstRTSPMediaClass *klass;
2507 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2509 g_rec_mutex_lock (&priv->state_lock);
2510 if (klass->handle_message)
2511 ret = klass->handle_message (media, message);
2514 g_rec_mutex_unlock (&priv->state_lock);
2520 watch_destroyed (GstRTSPMedia * media)
2522 GST_DEBUG_OBJECT (media, "source destroyed");
2523 g_object_unref (media);
2527 find_payload_element (GstElement * payloader)
2529 GstElement *pay = NULL;
2531 if (GST_IS_BIN (payloader)) {
2533 GValue item = { 0 };
2535 iter = gst_bin_iterate_recurse (GST_BIN (payloader));
2536 while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
2537 GstElement *element = (GstElement *) g_value_get_object (&item);
2538 GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
2542 gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
2546 if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
2547 pay = gst_object_ref (element);
2548 g_value_unset (&item);
2551 g_value_unset (&item);
2553 gst_iterator_free (iter);
2555 pay = g_object_ref (payloader);
2561 /* called from streaming threads */
2563 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
2565 GstRTSPMediaPrivate *priv = media->priv;
2566 GstRTSPStream *stream;
2569 /* find the real payload element */
2570 pay = find_payload_element (element);
2571 stream = gst_rtsp_media_create_stream (media, pay, pad);
2572 gst_object_unref (pay);
2574 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
2576 g_rec_mutex_lock (&priv->state_lock);
2577 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
2580 g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
2582 /* we will be adding elements below that will cause ASYNC_DONE to be
2583 * posted in the bus. We want to ignore those messages until the
2584 * pipeline really prerolled. */
2585 priv->adding = TRUE;
2587 /* join the element in the PAUSED state because this callback is
2588 * called from the streaming thread and it is PAUSED */
2589 if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2590 priv->rtpbin, GST_STATE_PAUSED)) {
2591 GST_WARNING ("failed to join bin element");
2594 priv->adding = FALSE;
2595 g_rec_mutex_unlock (&priv->state_lock);
2602 gst_rtsp_media_remove_stream (media, stream);
2603 g_rec_mutex_unlock (&priv->state_lock);
2604 GST_INFO ("ignore pad because we are not preparing");
2610 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
2612 GstRTSPMediaPrivate *priv = media->priv;
2613 GstRTSPStream *stream;
2615 stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
2619 GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
2621 g_rec_mutex_lock (&priv->state_lock);
2622 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
2623 g_rec_mutex_unlock (&priv->state_lock);
2625 gst_rtsp_media_remove_stream (media, stream);
2629 remove_fakesink (GstRTSPMediaPrivate * priv)
2631 GstElement *fakesink;
2633 g_mutex_lock (&priv->lock);
2634 if ((fakesink = priv->fakesink))
2635 gst_object_ref (fakesink);
2636 priv->fakesink = NULL;
2637 g_mutex_unlock (&priv->lock);
2640 gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
2641 gst_element_set_state (fakesink, GST_STATE_NULL);
2642 gst_object_unref (fakesink);
2643 GST_INFO ("removed fakesink");
2648 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
2650 GstRTSPMediaPrivate *priv = media->priv;
2652 GST_INFO ("no more pads");
2653 remove_fakesink (priv);
2656 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
2658 struct _DynPaySignalHandlers
2660 gulong pad_added_handler;
2661 gulong pad_removed_handler;
2662 gulong no_more_pads_handler;
2666 start_preroll (GstRTSPMedia * media)
2668 GstRTSPMediaPrivate *priv = media->priv;
2669 GstStateChangeReturn ret;
2671 GST_INFO ("setting pipeline to PAUSED for media %p", media);
2672 /* first go to PAUSED */
2673 ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
2676 case GST_STATE_CHANGE_SUCCESS:
2677 GST_INFO ("SUCCESS state change for media %p", media);
2678 priv->seekable = TRUE;
2680 case GST_STATE_CHANGE_ASYNC:
2681 GST_INFO ("ASYNC state change for media %p", media);
2682 priv->seekable = TRUE;
2684 case GST_STATE_CHANGE_NO_PREROLL:
2685 /* we need to go to PLAYING */
2686 GST_INFO ("NO_PREROLL state change: live media %p", media);
2687 /* FIXME we disable seeking for live streams for now. We should perform a
2688 * seeking query in preroll instead */
2689 priv->seekable = FALSE;
2690 priv->is_live = TRUE;
2691 if (!(priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
2692 /* start blocked to make sure nothing goes to the sink */
2693 media_streams_set_blocked (media, TRUE);
2695 ret = set_state (media, GST_STATE_PLAYING);
2696 if (ret == GST_STATE_CHANGE_FAILURE)
2699 case GST_STATE_CHANGE_FAILURE:
2707 GST_WARNING ("failed to preroll pipeline");
2713 wait_preroll (GstRTSPMedia * media)
2715 GstRTSPMediaStatus status;
2717 GST_DEBUG ("wait to preroll pipeline");
2719 /* wait until pipeline is prerolled */
2720 status = gst_rtsp_media_get_status (media);
2721 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
2722 goto preroll_failed;
2728 GST_WARNING ("failed to preroll pipeline");
2734 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
2736 GstRTSPMediaPrivate *priv = media->priv;
2737 GstRTSPStream *stream = NULL;
2740 g_mutex_lock (&priv->lock);
2741 for (i = 0; i < priv->streams->len; i++) {
2742 stream = g_ptr_array_index (priv->streams, i);
2744 if (sessid == gst_rtsp_stream_get_index (stream))
2747 g_mutex_unlock (&priv->lock);
2749 return gst_rtsp_stream_request_aux_sender (stream, sessid);
2753 start_prepare (GstRTSPMedia * media)
2755 GstRTSPMediaPrivate *priv = media->priv;
2759 g_rec_mutex_lock (&priv->state_lock);
2760 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
2761 goto no_longer_preparing;
2763 /* link streams we already have, other streams might appear when we have
2764 * dynamic elements */
2765 for (i = 0; i < priv->streams->len; i++) {
2766 GstRTSPStream *stream;
2768 stream = g_ptr_array_index (priv->streams, i);
2770 if (priv->rtx_time > 0) {
2771 /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
2772 g_signal_connect (priv->rtpbin, "request-aux-sender",
2773 (GCallback) request_aux_sender, media);
2776 if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
2777 priv->rtpbin, GST_STATE_NULL)) {
2778 goto join_bin_failed;
2783 g_object_set (priv->rtpbin, "do-retransmission", priv->rtx_time > 0, NULL);
2785 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
2786 GstElement *elem = walk->data;
2787 DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
2789 GST_INFO ("adding callbacks for dynamic element %p", elem);
2791 handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
2792 (GCallback) pad_added_cb, media);
2793 handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
2794 (GCallback) pad_removed_cb, media);
2795 handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
2796 (GCallback) no_more_pads_cb, media);
2798 g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
2800 if (!priv->fakesink) {
2801 /* we add a fakesink here in order to make the state change async. We remove
2802 * the fakesink again in the no-more-pads callback. */
2803 priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
2804 gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
2808 if (!start_preroll (media))
2809 goto preroll_failed;
2811 g_rec_mutex_unlock (&priv->state_lock);
2815 no_longer_preparing:
2817 GST_INFO ("media is no longer preparing");
2818 g_rec_mutex_unlock (&priv->state_lock);
2823 GST_WARNING ("failed to join bin element");
2824 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2825 g_rec_mutex_unlock (&priv->state_lock);
2830 GST_WARNING ("failed to preroll pipeline");
2831 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2832 g_rec_mutex_unlock (&priv->state_lock);
2838 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2840 GstRTSPMediaPrivate *priv;
2841 GstRTSPMediaClass *klass;
2843 GMainContext *context;
2848 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2850 if (!klass->create_rtpbin)
2851 goto no_create_rtpbin;
2853 priv->rtpbin = klass->create_rtpbin (media);
2854 if (priv->rtpbin != NULL) {
2855 gboolean success = TRUE;
2857 g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
2859 if (klass->setup_rtpbin)
2860 success = klass->setup_rtpbin (media, priv->rtpbin);
2862 if (success == FALSE) {
2863 gst_object_unref (priv->rtpbin);
2864 priv->rtpbin = NULL;
2867 if (priv->rtpbin == NULL)
2870 priv->thread = thread;
2871 context = (thread != NULL) ? (thread->context) : NULL;
2873 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
2875 /* add the pipeline bus to our custom mainloop */
2876 priv->source = gst_bus_create_watch (bus);
2877 gst_object_unref (bus);
2879 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
2880 g_object_ref (media), (GDestroyNotify) watch_destroyed);
2882 priv->id = g_source_attach (priv->source, context);
2884 /* add stuff to the bin */
2885 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
2887 /* do remainder in context */
2888 source = g_idle_source_new ();
2889 g_source_set_callback (source, (GSourceFunc) start_prepare,
2890 g_object_ref (media), (GDestroyNotify) g_object_unref);
2891 g_source_attach (source, context);
2892 g_source_unref (source);
2899 GST_ERROR ("no create_rtpbin function");
2900 g_critical ("no create_rtpbin vmethod function set");
2905 GST_WARNING ("no rtpbin element");
2906 g_warning ("failed to create element 'rtpbin', check your installation");
2912 * gst_rtsp_media_prepare:
2913 * @media: a #GstRTSPMedia
2914 * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
2915 * bus handler or %NULL
2917 * Prepare @media for streaming. This function will create the objects
2918 * to manage the streaming. A pipeline must have been set on @media with
2919 * gst_rtsp_media_take_pipeline().
2921 * It will preroll the pipeline and collect vital information about the streams
2922 * such as the duration.
2924 * Returns: %TRUE on success.
2927 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
2929 GstRTSPMediaPrivate *priv;
2930 GstRTSPMediaClass *klass;
2932 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2936 g_rec_mutex_lock (&priv->state_lock);
2937 priv->prepare_count++;
2939 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
2940 priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
2943 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2946 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
2947 goto not_unprepared;
2949 if (!priv->reusable && priv->reused)
2952 GST_INFO ("preparing media %p", media);
2954 /* reset some variables */
2955 priv->is_live = FALSE;
2956 priv->seekable = FALSE;
2957 priv->buffering = FALSE;
2959 /* we're preparing now */
2960 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2962 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2963 if (klass->prepare) {
2964 if (!klass->prepare (media, thread))
2965 goto prepare_failed;
2969 g_rec_mutex_unlock (&priv->state_lock);
2971 /* now wait for all pads to be prerolled, FIXME, we should somehow be
2972 * able to do this async so that we don't block the server thread. */
2973 if (!wait_preroll (media))
2974 goto preroll_failed;
2976 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
2978 GST_INFO ("object %p is prerolled", media);
2985 /* we are not going to use the giving thread, so stop it. */
2987 gst_rtsp_thread_stop (thread);
2992 GST_LOG ("media %p was prepared", media);
2993 /* we are not going to use the giving thread, so stop it. */
2995 gst_rtsp_thread_stop (thread);
2996 g_rec_mutex_unlock (&priv->state_lock);
3002 /* we are not going to use the giving thread, so stop it. */
3004 gst_rtsp_thread_stop (thread);
3005 GST_WARNING ("media %p was not unprepared", media);
3006 priv->prepare_count--;
3007 g_rec_mutex_unlock (&priv->state_lock);
3012 /* we are not going to use the giving thread, so stop it. */
3014 gst_rtsp_thread_stop (thread);
3015 priv->prepare_count--;
3016 g_rec_mutex_unlock (&priv->state_lock);
3017 GST_WARNING ("can not reuse media %p", media);
3022 /* we are not going to use the giving thread, so stop it. */
3024 gst_rtsp_thread_stop (thread);
3025 priv->prepare_count--;
3026 g_rec_mutex_unlock (&priv->state_lock);
3027 GST_ERROR ("failed to prepare media");
3032 GST_WARNING ("failed to preroll pipeline");
3033 gst_rtsp_media_unprepare (media);
3038 /* must be called with state-lock */
3040 finish_unprepare (GstRTSPMedia * media)
3042 GstRTSPMediaPrivate *priv = media->priv;
3046 GST_DEBUG ("shutting down");
3048 /* release the lock on shutdown, otherwise pad_added_cb might try to
3049 * acquire the lock and then we deadlock */
3050 g_rec_mutex_unlock (&priv->state_lock);
3051 set_state (media, GST_STATE_NULL);
3052 g_rec_mutex_lock (&priv->state_lock);
3053 remove_fakesink (priv);
3055 for (i = 0; i < priv->streams->len; i++) {
3056 GstRTSPStream *stream;
3058 GST_INFO ("Removing elements of stream %d from pipeline", i);
3060 stream = g_ptr_array_index (priv->streams, i);
3062 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3065 /* remove the pad signal handlers */
3066 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3067 GstElement *elem = walk->data;
3068 DynPaySignalHandlers *handlers;
3071 g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3072 g_assert (handlers != NULL);
3074 g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3075 g_signal_handler_disconnect (G_OBJECT (elem),
3076 handlers->pad_removed_handler);
3077 g_signal_handler_disconnect (G_OBJECT (elem),
3078 handlers->no_more_pads_handler);
3080 g_slice_free (DynPaySignalHandlers, handlers);
3083 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3084 priv->rtpbin = NULL;
3087 gst_object_unref (priv->nettime);
3088 priv->nettime = NULL;
3090 priv->reused = TRUE;
3091 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3093 /* when the media is not reusable, this will effectively unref the media and
3095 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3097 /* the source has the last ref to the media */
3099 GST_DEBUG ("destroy source");
3100 g_source_destroy (priv->source);
3101 g_source_unref (priv->source);
3104 GST_DEBUG ("stop thread");
3105 gst_rtsp_thread_stop (priv->thread);
3109 /* called with state-lock */
3111 default_unprepare (GstRTSPMedia * media)
3113 GstRTSPMediaPrivate *priv = media->priv;
3115 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3117 if (priv->eos_shutdown) {
3118 GST_DEBUG ("sending EOS for shutdown");
3119 /* ref so that we don't disappear */
3120 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
3121 /* we need to go to playing again for the EOS to propagate, normally in this
3122 * state, nothing is receiving data from us anymore so this is ok. */
3123 set_state (media, GST_STATE_PLAYING);
3125 finish_unprepare (media);
3131 * gst_rtsp_media_unprepare:
3132 * @media: a #GstRTSPMedia
3134 * Unprepare @media. After this call, the media should be prepared again before
3135 * it can be used again. If the media is set to be non-reusable, a new instance
3138 * Returns: %TRUE on success.
3141 gst_rtsp_media_unprepare (GstRTSPMedia * media)
3143 GstRTSPMediaPrivate *priv;
3146 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3150 g_rec_mutex_lock (&priv->state_lock);
3151 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
3152 goto was_unprepared;
3154 priv->prepare_count--;
3155 if (priv->prepare_count > 0)
3158 GST_INFO ("unprepare media %p", media);
3160 media_streams_set_blocked (media, FALSE);
3161 set_target_state (media, GST_STATE_NULL, FALSE);
3164 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
3165 GstRTSPMediaClass *klass;
3167 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3168 if (klass->unprepare)
3169 success = klass->unprepare (media);
3171 finish_unprepare (media);
3173 g_rec_mutex_unlock (&priv->state_lock);
3179 g_rec_mutex_unlock (&priv->state_lock);
3180 GST_INFO ("media %p was already unprepared", media);
3185 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
3186 g_rec_mutex_unlock (&priv->state_lock);
3191 /* should be called with state-lock */
3193 get_clock_unlocked (GstRTSPMedia * media)
3195 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
3196 GST_DEBUG_OBJECT (media, "media was not prepared");
3199 return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
3203 * gst_rtsp_media_get_clock:
3204 * @media: a #GstRTSPMedia
3206 * Get the clock that is used by the pipeline in @media.
3208 * @media must be prepared before this method returns a valid clock object.
3210 * Returns: (transfer full): the #GstClock used by @media. unref after usage.
3213 gst_rtsp_media_get_clock (GstRTSPMedia * media)
3216 GstRTSPMediaPrivate *priv;
3218 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3222 g_rec_mutex_lock (&priv->state_lock);
3223 clock = get_clock_unlocked (media);
3224 g_rec_mutex_unlock (&priv->state_lock);
3230 * gst_rtsp_media_get_base_time:
3231 * @media: a #GstRTSPMedia
3233 * Get the base_time that is used by the pipeline in @media.
3235 * @media must be prepared before this method returns a valid base_time.
3237 * Returns: the base_time used by @media.
3240 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
3242 GstClockTime result;
3243 GstRTSPMediaPrivate *priv;
3245 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
3249 g_rec_mutex_lock (&priv->state_lock);
3250 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3253 result = gst_element_get_base_time (media->priv->pipeline);
3254 g_rec_mutex_unlock (&priv->state_lock);
3261 g_rec_mutex_unlock (&priv->state_lock);
3262 GST_DEBUG_OBJECT (media, "media was not prepared");
3263 return GST_CLOCK_TIME_NONE;
3268 * gst_rtsp_media_get_time_provider:
3269 * @media: a #GstRTSPMedia
3270 * @address: (allow-none): an address or %NULL
3271 * @port: a port or 0
3273 * Get the #GstNetTimeProvider for the clock used by @media. The time provider
3274 * will listen on @address and @port for client time requests.
3276 * Returns: (transfer full): the #GstNetTimeProvider of @media.
3278 GstNetTimeProvider *
3279 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
3282 GstRTSPMediaPrivate *priv;
3283 GstNetTimeProvider *provider = NULL;
3285 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3289 g_rec_mutex_lock (&priv->state_lock);
3290 if (priv->time_provider) {
3291 if ((provider = priv->nettime) == NULL) {
3294 if (priv->time_provider && (clock = get_clock_unlocked (media))) {
3295 provider = gst_net_time_provider_new (clock, address, port);
3296 gst_object_unref (clock);
3298 priv->nettime = provider;
3302 g_rec_mutex_unlock (&priv->state_lock);
3305 gst_object_ref (provider);
3311 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
3313 return gst_rtsp_sdp_from_media (sdp, info, media);
3317 * gst_rtsp_media_setup_sdp:
3318 * @media: a #GstRTSPMedia
3319 * @sdp: (transfer none): a #GstSDPMessage
3320 * @info: (transfer none): a #GstSDPInfo
3322 * Add @media specific info to @sdp. @info is used to configure the connection
3323 * information in the SDP.
3325 * Returns: TRUE on success.
3328 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
3331 GstRTSPMediaPrivate *priv;
3332 GstRTSPMediaClass *klass;
3335 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3336 g_return_val_if_fail (sdp != NULL, FALSE);
3337 g_return_val_if_fail (info != NULL, FALSE);
3341 g_rec_mutex_lock (&priv->state_lock);
3343 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3345 if (!klass->setup_sdp)
3348 res = klass->setup_sdp (media, sdp, info);
3350 g_rec_mutex_unlock (&priv->state_lock);
3357 g_rec_mutex_unlock (&priv->state_lock);
3358 GST_ERROR ("no setup_sdp function");
3359 g_critical ("no setup_sdp vmethod function set");
3365 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
3367 GstRTSPMediaPrivate *priv = media->priv;
3370 medias_len = gst_sdp_message_medias_len (sdp);
3371 if (medias_len != priv->streams->len) {
3372 GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
3373 priv->streams->len, medias_len);
3377 for (i = 0; i < medias_len; i++) {
3378 const gchar *proto, *media_type;
3379 const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
3380 GstRTSPStream *stream;
3381 gint j, formats_len;
3382 const gchar *control;
3383 GstRTSPProfile profile, profiles;
3385 stream = g_ptr_array_index (priv->streams, i);
3387 /* TODO: Should we do something with the other SDP information? */
3390 proto = gst_sdp_media_get_proto (sdp_media);
3391 if (proto == NULL) {
3392 GST_ERROR ("%p: SDP media %d has no proto", media, i);
3396 if (g_str_equal (proto, "RTP/AVP")) {
3397 media_type = "application/x-rtp";
3398 profile = GST_RTSP_PROFILE_AVP;
3399 } else if (g_str_equal (proto, "RTP/SAVP")) {
3400 media_type = "application/x-srtp";
3401 profile = GST_RTSP_PROFILE_SAVP;
3402 } else if (g_str_equal (proto, "RTP/AVPF")) {
3403 media_type = "application/x-rtp";
3404 profile = GST_RTSP_PROFILE_AVPF;
3405 } else if (g_str_equal (proto, "RTP/SAVPF")) {
3406 media_type = "application/x-srtp";
3407 profile = GST_RTSP_PROFILE_SAVPF;
3409 GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
3413 profiles = gst_rtsp_stream_get_profiles (stream);
3414 if ((profiles & profile) == 0) {
3415 GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
3419 formats_len = gst_sdp_media_formats_len (sdp_media);
3420 for (j = 0; j < formats_len; j++) {
3425 pt = atoi (gst_sdp_media_get_format (sdp_media, j));
3427 GST_DEBUG (" looking at %d pt: %d", j, pt);
3430 caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
3432 GST_WARNING (" skipping pt %d without caps", pt);
3436 /* do some tweaks */
3437 GST_DEBUG ("mapping sdp session level attributes to caps");
3438 gst_sdp_message_attributes_to_caps (sdp, caps);
3439 GST_DEBUG ("mapping sdp media level attributes to caps");
3440 gst_sdp_media_attributes_to_caps (sdp_media, caps);
3442 s = gst_caps_get_structure (caps, 0);
3443 gst_structure_set_name (s, media_type);
3445 gst_rtsp_stream_set_pt_map (stream, pt, caps);
3446 gst_caps_unref (caps);
3449 control = gst_sdp_media_get_attribute_val (sdp_media, "control");
3451 gst_rtsp_stream_set_control (stream, control);
3459 * gst_rtsp_media_handle_sdp:
3460 * @media: a #GstRTSPMedia
3461 * @sdp: (transfer none): a #GstSDPMessage
3463 * Configure an SDP on @media for receiving streams
3465 * Returns: TRUE on success.
3468 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
3470 GstRTSPMediaPrivate *priv;
3471 GstRTSPMediaClass *klass;
3474 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3475 g_return_val_if_fail (sdp != NULL, FALSE);
3479 g_rec_mutex_lock (&priv->state_lock);
3481 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3483 if (!klass->handle_sdp)
3486 res = klass->handle_sdp (media, sdp);
3488 g_rec_mutex_unlock (&priv->state_lock);
3495 g_rec_mutex_unlock (&priv->state_lock);
3496 GST_ERROR ("no handle_sdp function");
3497 g_critical ("no handle_sdp vmethod function set");
3503 do_set_seqnum (GstRTSPStream * stream)
3506 seq_num = gst_rtsp_stream_get_current_seqnum (stream);
3507 gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
3510 /* call with state_lock */
3512 default_suspend (GstRTSPMedia * media)
3514 GstRTSPMediaPrivate *priv = media->priv;
3515 GstStateChangeReturn ret;
3516 gboolean unblock = FALSE;
3518 switch (priv->suspend_mode) {
3519 case GST_RTSP_SUSPEND_MODE_NONE:
3520 GST_DEBUG ("media %p no suspend", media);
3522 case GST_RTSP_SUSPEND_MODE_PAUSE:
3523 GST_DEBUG ("media %p suspend to PAUSED", media);
3524 ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3525 if (ret == GST_STATE_CHANGE_FAILURE)
3529 case GST_RTSP_SUSPEND_MODE_RESET:
3530 GST_DEBUG ("media %p suspend to NULL", media);
3531 ret = set_target_state (media, GST_STATE_NULL, TRUE);
3532 if (ret == GST_STATE_CHANGE_FAILURE)
3534 /* Because payloader needs to set the sequence number as
3535 * monotonic, we need to preserve the sequence number
3536 * after pause. (otherwise going from pause to play, which
3537 * is actually from NULL to PLAY will create a new sequence
3539 g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
3546 /* let the streams do the state changes freely, if any */
3548 media_streams_set_blocked (media, FALSE);
3555 GST_WARNING ("failed changing pipeline's state for media %p", media);
3561 * gst_rtsp_media_suspend:
3562 * @media: a #GstRTSPMedia
3564 * Suspend @media. The state of the pipeline managed by @media is set to
3565 * GST_STATE_NULL but all streams are kept. @media can be prepared again
3566 * with gst_rtsp_media_unsuspend()
3568 * @media must be prepared with gst_rtsp_media_prepare();
3570 * Returns: %TRUE on success.
3573 gst_rtsp_media_suspend (GstRTSPMedia * media)
3575 GstRTSPMediaPrivate *priv = media->priv;
3576 GstRTSPMediaClass *klass;
3578 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3580 GST_FIXME ("suspend for dynamic pipelines needs fixing");
3582 g_rec_mutex_lock (&priv->state_lock);
3583 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3586 /* don't attempt to suspend when something is busy */
3587 if (priv->n_active > 0)
3590 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3591 if (klass->suspend) {
3592 if (!klass->suspend (media))
3593 goto suspend_failed;
3596 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
3598 g_rec_mutex_unlock (&priv->state_lock);
3605 g_rec_mutex_unlock (&priv->state_lock);
3606 GST_WARNING ("media %p was not prepared", media);
3611 g_rec_mutex_unlock (&priv->state_lock);
3612 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3613 GST_WARNING ("failed to suspend media %p", media);
3618 /* call with state_lock */
3620 default_unsuspend (GstRTSPMedia * media)
3622 GstRTSPMediaPrivate *priv = media->priv;
3623 gboolean preroll_ok;
3625 switch (priv->suspend_mode) {
3626 case GST_RTSP_SUSPEND_MODE_NONE:
3627 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3629 case GST_RTSP_SUSPEND_MODE_PAUSE:
3630 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3632 case GST_RTSP_SUSPEND_MODE_RESET:
3634 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3635 if (!start_preroll (media))
3638 g_rec_mutex_unlock (&priv->state_lock);
3639 preroll_ok = wait_preroll (media);
3640 g_rec_mutex_lock (&priv->state_lock);
3643 goto preroll_failed;
3654 GST_WARNING ("failed to preroll pipeline");
3659 GST_WARNING ("failed to preroll pipeline");
3665 * gst_rtsp_media_unsuspend:
3666 * @media: a #GstRTSPMedia
3668 * Unsuspend @media if it was in a suspended state. This method does nothing
3669 * when the media was not in the suspended state.
3671 * Returns: %TRUE on success.
3674 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
3676 GstRTSPMediaPrivate *priv = media->priv;
3677 GstRTSPMediaClass *klass;
3679 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3681 g_rec_mutex_lock (&priv->state_lock);
3682 if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
3685 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3686 if (klass->unsuspend) {
3687 if (!klass->unsuspend (media))
3688 goto unsuspend_failed;
3692 g_rec_mutex_unlock (&priv->state_lock);
3699 g_rec_mutex_unlock (&priv->state_lock);
3700 GST_WARNING ("failed to unsuspend media %p", media);
3701 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3706 /* must be called with state-lock */
3708 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
3710 GstRTSPMediaPrivate *priv = media->priv;
3712 if (state == GST_STATE_NULL) {
3713 gst_rtsp_media_unprepare (media);
3715 GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
3716 set_target_state (media, state, FALSE);
3717 /* when we are buffering, don't update the state yet, this will be done
3718 * when buffering finishes */
3719 if (priv->buffering) {
3720 GST_INFO ("Buffering busy, delay state change");
3722 if (state == GST_STATE_PLAYING)
3723 /* make sure pads are not blocking anymore when going to PLAYING */
3724 media_streams_set_blocked (media, FALSE);
3726 set_state (media, state);
3728 /* and suspend after pause */
3729 if (state == GST_STATE_PAUSED)
3730 gst_rtsp_media_suspend (media);
3736 * gst_rtsp_media_set_pipeline_state:
3737 * @media: a #GstRTSPMedia
3738 * @state: the target state of the pipeline
3740 * Set the state of the pipeline managed by @media to @state
3743 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
3745 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
3747 g_rec_mutex_lock (&media->priv->state_lock);
3748 media_set_pipeline_state_locked (media, state);
3749 g_rec_mutex_unlock (&media->priv->state_lock);
3753 * gst_rtsp_media_set_state:
3754 * @media: a #GstRTSPMedia
3755 * @state: the target state of the media
3756 * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
3757 * a #GPtrArray of #GstRTSPStreamTransport pointers
3759 * Set the state of @media to @state and for the transports in @transports.
3761 * @media must be prepared with gst_rtsp_media_prepare();
3763 * Returns: %TRUE on success.
3766 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
3767 GPtrArray * transports)
3769 GstRTSPMediaPrivate *priv;
3771 gboolean activate, deactivate, do_state;
3774 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3775 g_return_val_if_fail (transports != NULL, FALSE);
3779 g_rec_mutex_lock (&priv->state_lock);
3780 if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
3782 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
3783 priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
3786 /* NULL and READY are the same */
3787 if (state == GST_STATE_READY)
3788 state = GST_STATE_NULL;
3790 activate = deactivate = FALSE;
3792 GST_INFO ("going to state %s media %p, target state %s",
3793 gst_element_state_get_name (state), media,
3794 gst_element_state_get_name (priv->target_state));
3797 case GST_STATE_NULL:
3798 /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
3799 if (priv->target_state >= GST_STATE_PAUSED)
3802 case GST_STATE_PAUSED:
3803 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
3804 if (priv->target_state == GST_STATE_PLAYING)
3807 case GST_STATE_PLAYING:
3808 /* we're going to PLAYING, activate */
3814 old_active = priv->n_active;
3816 GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
3817 activate, deactivate);
3818 for (i = 0; i < transports->len; i++) {
3819 GstRTSPStreamTransport *trans;
3821 /* we need a non-NULL entry in the array */
3822 trans = g_ptr_array_index (transports, i);
3827 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
3829 } else if (deactivate) {
3830 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
3835 /* we just activated the first media, do the playing state change */
3836 if (old_active == 0 && activate)
3838 /* if we have no more active media, do the downward state changes */
3839 else if (priv->n_active == 0)
3844 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
3847 if (priv->target_state != state) {
3849 media_set_pipeline_state_locked (media, state);
3851 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
3855 /* remember where we are */
3856 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
3857 old_active != priv->n_active))
3858 collect_media_stats (media);
3860 g_rec_mutex_unlock (&priv->state_lock);
3867 GST_WARNING ("media %p was not prepared", media);
3868 g_rec_mutex_unlock (&priv->state_lock);
3873 GST_WARNING ("media %p in error status while changing to state %d",
3875 if (state == GST_STATE_NULL) {
3876 for (i = 0; i < transports->len; i++) {
3877 GstRTSPStreamTransport *trans;
3879 /* we need a non-NULL entry in the array */
3880 trans = g_ptr_array_index (transports, i);
3884 gst_rtsp_stream_transport_set_active (trans, FALSE);
3888 g_rec_mutex_unlock (&priv->state_lock);
3894 * gst_rtsp_media_set_transport_mode:
3895 * @media: a #GstRTSPMedia
3896 * @mode: the new value
3898 * Sets if the media pipeline can work in PLAY or RECORD mode
3901 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
3902 GstRTSPTransportMode mode)
3904 GstRTSPMediaPrivate *priv;
3906 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
3910 g_mutex_lock (&priv->lock);
3911 priv->transport_mode = mode;
3912 g_mutex_unlock (&priv->lock);
3916 * gst_rtsp_media_get_transport_mode:
3917 * @media: a #GstRTSPMedia
3919 * Check if the pipeline for @media can be used for PLAY or RECORD methods.
3921 * Returns: The transport mode.
3923 GstRTSPTransportMode
3924 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
3926 GstRTSPMediaPrivate *priv;
3927 GstRTSPTransportMode res;
3929 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3933 g_mutex_lock (&priv->lock);
3934 res = priv->transport_mode;
3935 g_mutex_unlock (&priv->lock);