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(), or gst_rtsp_media_seek_full()
54 * or gst_rtsp_media_seek_trickmode() for finer control of the seek.
56 * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
57 * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
60 * With gst_rtsp_media_set_shared(), the media can be shared between multiple
61 * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
62 * can be prepared again after an unprepare.
64 * Last reviewed on 2013-07-11 (1.0.0)
74 #include <gst/app/gstappsrc.h>
75 #include <gst/app/gstappsink.h>
77 #include <gst/sdp/gstmikey.h>
78 #include <gst/rtp/gstrtppayloads.h>
80 #define AES_128_KEY_LEN 16
81 #define AES_256_KEY_LEN 32
83 #define HMAC_32_KEY_LEN 4
84 #define HMAC_80_KEY_LEN 10
86 #include "rtsp-media.h"
88 struct _GstRTSPMediaPrivate
93 /* the global lock is used to lock the entire media. This is needed by callers
94 such as rtsp_client to protect the media when it is shared by many clients.
95 The lock prevents that concurrenting clients messes up media.
96 Typically the lock is taken in external API calls such as SETUP */
99 /* protected by lock */
100 GstRTSPPermissions *permissions;
102 gboolean suspend_mode;
104 GstRTSPProfile profiles;
105 GstRTSPLowerTrans protocols;
107 gboolean eos_shutdown;
110 GstRTSPAddressPool *pool;
111 gchar *multicast_iface;
113 gboolean bind_mcast_address;
115 GstRTSPTransportMode transport_mode;
116 gboolean stop_on_disconnect;
117 guint blocking_msg_received;
120 GRecMutex state_lock; /* locking order: state lock, lock */
121 GPtrArray *streams; /* protected by lock */
122 GList *dynamic; /* protected by lock */
123 GstRTSPMediaStatus status; /* protected by lock */
127 gboolean finishing_unprepare;
129 /* the pipeline for the media */
130 GstElement *pipeline;
133 GstRTSPThread *thread;
134 GList *pending_pipeline_elements;
136 gboolean time_provider;
137 GstNetTimeProvider *nettime;
140 GstClockTimeDiff seekable;
142 GstState target_state;
144 /* RTP session manager */
147 /* the range of media */
148 GstRTSPTimeRange range; /* protected by lock */
149 GstClockTime range_start;
150 GstClockTime range_stop;
152 GList *payloads; /* protected by lock */
153 GstClockTime rtx_time; /* protected by lock */
154 gboolean do_retransmission; /* protected by lock */
155 guint latency; /* protected by lock */
156 GstClock *clock; /* protected by lock */
157 gboolean do_rate_control; /* protected by lock */
158 GstRTSPPublishClockMode publish_clock_mode;
160 /* Dynamic element handling */
161 guint nb_dynamic_elements;
162 guint no_more_pads_pending;
163 gboolean expected_async_done;
166 #define DEFAULT_SHARED FALSE
167 #define DEFAULT_SUSPEND_MODE GST_RTSP_SUSPEND_MODE_NONE
168 #define DEFAULT_REUSABLE FALSE
169 #define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP
170 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
171 GST_RTSP_LOWER_TRANS_TCP
172 #define DEFAULT_EOS_SHUTDOWN FALSE
173 #define DEFAULT_BUFFER_SIZE 0x80000
174 #define DEFAULT_DSCP_QOS (-1)
175 #define DEFAULT_TIME_PROVIDER FALSE
176 #define DEFAULT_LATENCY 200
177 #define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
178 #define DEFAULT_STOP_ON_DISCONNECT TRUE
179 #define DEFAULT_MAX_MCAST_TTL 255
180 #define DEFAULT_BIND_MCAST_ADDRESS FALSE
181 #define DEFAULT_DO_RATE_CONTROL TRUE
183 #define DEFAULT_DO_RETRANSMISSION FALSE
185 /* define to dump received RTCP packets */
202 PROP_STOP_ON_DISCONNECT,
205 PROP_BIND_MCAST_ADDRESS,
213 SIGNAL_REMOVED_STREAM,
221 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
222 #define GST_CAT_DEFAULT rtsp_media_debug
224 static void gst_rtsp_media_get_property (GObject * object, guint propid,
225 GValue * value, GParamSpec * pspec);
226 static void gst_rtsp_media_set_property (GObject * object, guint propid,
227 const GValue * value, GParamSpec * pspec);
228 static void gst_rtsp_media_finalize (GObject * obj);
230 static gboolean default_handle_message (GstRTSPMedia * media,
231 GstMessage * message);
232 static void finish_unprepare (GstRTSPMedia * media);
233 static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread);
234 static gboolean default_unprepare (GstRTSPMedia * media);
235 static gboolean default_suspend (GstRTSPMedia * media);
236 static gboolean default_unsuspend (GstRTSPMedia * media);
237 static gboolean default_convert_range (GstRTSPMedia * media,
238 GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
239 static gboolean default_query_position (GstRTSPMedia * media,
241 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
242 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
243 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
245 static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
247 static gboolean wait_preroll (GstRTSPMedia * media);
249 static GstElement *find_payload_element (GstElement * payloader, GstPad * pad);
251 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
253 static gboolean check_complete (GstRTSPMedia * media);
255 #define C_ENUM(v) ((gint) v)
257 #define TRICKMODE_FLAGS (GST_SEEK_FLAG_TRICKMODE | GST_SEEK_FLAG_TRICKMODE_KEY_UNITS | GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED)
260 gst_rtsp_suspend_mode_get_type (void)
263 static const GEnumValue values[] = {
264 {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
265 {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
267 {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
272 if (g_once_init_enter (&id)) {
273 GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
274 g_once_init_leave (&id, tmp);
279 #define C_FLAGS(v) ((guint) v)
282 gst_rtsp_transport_mode_get_type (void)
285 static const GFlagsValue values[] = {
286 {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
288 {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
293 if (g_once_init_enter (&id)) {
294 GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
295 g_once_init_leave (&id, tmp);
301 gst_rtsp_publish_clock_mode_get_type (void)
304 static const GEnumValue values[] = {
305 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
306 "GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
307 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
308 "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
310 {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
311 "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
316 if (g_once_init_enter (&id)) {
317 GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
318 g_once_init_leave (&id, tmp);
323 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
326 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
328 GObjectClass *gobject_class;
330 gobject_class = G_OBJECT_CLASS (klass);
332 gobject_class->get_property = gst_rtsp_media_get_property;
333 gobject_class->set_property = gst_rtsp_media_set_property;
334 gobject_class->finalize = gst_rtsp_media_finalize;
336 g_object_class_install_property (gobject_class, PROP_SHARED,
337 g_param_spec_boolean ("shared", "Shared",
338 "If this media pipeline can be shared", DEFAULT_SHARED,
339 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
341 g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
342 g_param_spec_enum ("suspend-mode", "Suspend Mode",
343 "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
344 DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
346 g_object_class_install_property (gobject_class, PROP_REUSABLE,
347 g_param_spec_boolean ("reusable", "Reusable",
348 "If this media pipeline can be reused after an unprepare",
349 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
351 g_object_class_install_property (gobject_class, PROP_PROFILES,
352 g_param_spec_flags ("profiles", "Profiles",
353 "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
354 DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
356 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
357 g_param_spec_flags ("protocols", "Protocols",
358 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
359 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
362 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
363 "Send an EOS event to the pipeline before unpreparing",
364 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
366 g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
367 g_param_spec_uint ("buffer-size", "Buffer Size",
368 "The kernel UDP buffer size to use", 0, G_MAXUINT,
369 DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371 g_object_class_install_property (gobject_class, PROP_ELEMENT,
372 g_param_spec_object ("element", "The Element",
373 "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
374 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
376 g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
377 g_param_spec_boolean ("time-provider", "Time Provider",
378 "Use a NetTimeProvider for clients",
379 DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
381 g_object_class_install_property (gobject_class, PROP_LATENCY,
382 g_param_spec_uint ("latency", "Latency",
383 "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
384 DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
386 g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
387 g_param_spec_flags ("transport-mode", "Transport Mode",
388 "If this media pipeline can be used for PLAY or RECORD",
389 GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
390 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
392 g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
393 g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
394 "If this media pipeline should be stopped "
395 "when a client disconnects without TEARDOWN",
396 DEFAULT_STOP_ON_DISCONNECT,
397 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
399 g_object_class_install_property (gobject_class, PROP_CLOCK,
400 g_param_spec_object ("clock", "Clock",
401 "Clock to be used by the media pipeline",
402 GST_TYPE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
404 g_object_class_install_property (gobject_class, PROP_MAX_MCAST_TTL,
405 g_param_spec_uint ("max-mcast-ttl", "Maximum multicast ttl",
406 "The maximum time-to-live value of outgoing multicast packets", 1,
407 255, DEFAULT_MAX_MCAST_TTL,
408 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
410 g_object_class_install_property (gobject_class, PROP_BIND_MCAST_ADDRESS,
411 g_param_spec_boolean ("bind-mcast-address", "Bind mcast address",
412 "Whether the multicast sockets should be bound to multicast addresses "
414 DEFAULT_BIND_MCAST_ADDRESS,
415 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
417 g_object_class_install_property (gobject_class, PROP_DSCP_QOS,
418 g_param_spec_int ("dscp-qos", "DSCP QoS",
419 "The IP DSCP field to use for each related stream", -1, 63,
420 DEFAULT_DSCP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
422 gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
423 g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
424 G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL, NULL,
425 G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
427 gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
428 g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
429 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
430 NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
432 gst_rtsp_media_signals[SIGNAL_PREPARED] =
433 g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
434 G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL, NULL,
435 G_TYPE_NONE, 0, G_TYPE_NONE);
437 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
438 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
439 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL, NULL,
440 G_TYPE_NONE, 0, G_TYPE_NONE);
442 gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
443 g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
444 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
445 NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
447 gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
448 g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
449 G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL, NULL,
450 G_TYPE_NONE, 1, G_TYPE_INT);
452 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
454 klass->handle_message = default_handle_message;
455 klass->prepare = default_prepare;
456 klass->unprepare = default_unprepare;
457 klass->suspend = default_suspend;
458 klass->unsuspend = default_unsuspend;
459 klass->convert_range = default_convert_range;
460 klass->query_position = default_query_position;
461 klass->query_stop = default_query_stop;
462 klass->create_rtpbin = default_create_rtpbin;
463 klass->setup_sdp = default_setup_sdp;
464 klass->handle_sdp = default_handle_sdp;
468 gst_rtsp_media_init (GstRTSPMedia * media)
470 GstRTSPMediaPrivate *priv = gst_rtsp_media_get_instance_private (media);
474 priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
475 g_mutex_init (&priv->lock);
476 g_mutex_init (&priv->global_lock);
477 g_cond_init (&priv->cond);
478 g_rec_mutex_init (&priv->state_lock);
480 priv->shared = DEFAULT_SHARED;
481 priv->suspend_mode = DEFAULT_SUSPEND_MODE;
482 priv->reusable = DEFAULT_REUSABLE;
483 priv->profiles = DEFAULT_PROFILES;
484 priv->protocols = DEFAULT_PROTOCOLS;
485 priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
486 priv->buffer_size = DEFAULT_BUFFER_SIZE;
487 priv->time_provider = DEFAULT_TIME_PROVIDER;
488 priv->transport_mode = DEFAULT_TRANSPORT_MODE;
489 priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
490 priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
491 priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
492 priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
493 priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
494 priv->do_rate_control = DEFAULT_DO_RATE_CONTROL;
495 priv->dscp_qos = DEFAULT_DSCP_QOS;
496 priv->expected_async_done = FALSE;
497 priv->blocking_msg_received = 0;
501 gst_rtsp_media_finalize (GObject * obj)
503 GstRTSPMediaPrivate *priv;
506 media = GST_RTSP_MEDIA (obj);
509 GST_INFO ("finalize media %p", media);
511 if (priv->permissions)
512 gst_rtsp_permissions_unref (priv->permissions);
514 g_ptr_array_unref (priv->streams);
516 g_list_free_full (priv->dynamic, gst_object_unref);
517 g_list_free_full (priv->pending_pipeline_elements, gst_object_unref);
520 gst_object_unref (priv->pipeline);
522 gst_object_unref (priv->nettime);
523 gst_object_unref (priv->element);
525 g_object_unref (priv->pool);
527 g_list_free (priv->payloads);
529 gst_object_unref (priv->clock);
530 g_free (priv->multicast_iface);
531 g_mutex_clear (&priv->lock);
532 g_mutex_clear (&priv->global_lock);
533 g_cond_clear (&priv->cond);
534 g_rec_mutex_clear (&priv->state_lock);
536 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
540 gst_rtsp_media_get_property (GObject * object, guint propid,
541 GValue * value, GParamSpec * pspec)
543 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
547 g_value_set_object (value, media->priv->element);
550 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
552 case PROP_SUSPEND_MODE:
553 g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
556 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
559 g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
562 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
564 case PROP_EOS_SHUTDOWN:
565 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
567 case PROP_BUFFER_SIZE:
568 g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
570 case PROP_TIME_PROVIDER:
571 g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
574 g_value_set_uint (value, gst_rtsp_media_get_latency (media));
576 case PROP_TRANSPORT_MODE:
577 g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
579 case PROP_STOP_ON_DISCONNECT:
580 g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
583 g_value_take_object (value, gst_rtsp_media_get_clock (media));
585 case PROP_MAX_MCAST_TTL:
586 g_value_set_uint (value, gst_rtsp_media_get_max_mcast_ttl (media));
588 case PROP_BIND_MCAST_ADDRESS:
589 g_value_set_boolean (value, gst_rtsp_media_is_bind_mcast_address (media));
592 g_value_set_int (value, gst_rtsp_media_get_dscp_qos (media));
595 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
600 gst_rtsp_media_set_property (GObject * object, guint propid,
601 const GValue * value, GParamSpec * pspec)
603 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
607 media->priv->element = g_value_get_object (value);
608 gst_object_ref_sink (media->priv->element);
611 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
613 case PROP_SUSPEND_MODE:
614 gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
617 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
620 gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
623 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
625 case PROP_EOS_SHUTDOWN:
626 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
628 case PROP_BUFFER_SIZE:
629 gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
631 case PROP_TIME_PROVIDER:
632 gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
635 gst_rtsp_media_set_latency (media, g_value_get_uint (value));
637 case PROP_TRANSPORT_MODE:
638 gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
640 case PROP_STOP_ON_DISCONNECT:
641 gst_rtsp_media_set_stop_on_disconnect (media,
642 g_value_get_boolean (value));
645 gst_rtsp_media_set_clock (media, g_value_get_object (value));
647 case PROP_MAX_MCAST_TTL:
648 gst_rtsp_media_set_max_mcast_ttl (media, g_value_get_uint (value));
650 case PROP_BIND_MCAST_ADDRESS:
651 gst_rtsp_media_set_bind_mcast_address (media,
652 g_value_get_boolean (value));
655 gst_rtsp_media_set_dscp_qos (media, g_value_get_int (value));
658 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
665 gboolean complete_streams_only;
667 } DoQueryPositionData;
670 do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
674 if (!gst_rtsp_stream_is_sender (stream))
677 if (data->complete_streams_only && !gst_rtsp_stream_is_complete (stream)) {
678 GST_DEBUG_OBJECT (stream, "stream not complete, do not query position");
682 if (gst_rtsp_stream_query_position (stream, &tmp)) {
683 data->position = MIN (data->position, tmp);
687 GST_INFO_OBJECT (stream, "media position: %" GST_TIME_FORMAT,
688 GST_TIME_ARGS (data->position));
692 default_query_position (GstRTSPMedia * media, gint64 * position)
694 GstRTSPMediaPrivate *priv;
695 DoQueryPositionData data;
699 data.position = G_MAXINT64;
702 /* if the media is complete, i.e. one or more streams have been configured
703 * with sinks, then we want to query the position on those streams only.
704 * a query on an incmplete stream may return a position that originates from
705 * an earlier preroll */
706 if (check_complete (media))
707 data.complete_streams_only = TRUE;
709 data.complete_streams_only = FALSE;
711 g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
714 *position = GST_CLOCK_TIME_NONE;
716 *position = data.position;
728 do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
732 if (gst_rtsp_stream_query_stop (stream, &tmp)) {
733 data->stop = MAX (data->stop, tmp);
739 default_query_stop (GstRTSPMedia * media, gint64 * stop)
741 GstRTSPMediaPrivate *priv;
742 DoQueryStopData data;
749 g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
757 default_create_rtpbin (GstRTSPMedia * media)
761 rtpbin = gst_element_factory_make ("rtpbin", NULL);
766 /* Must be called with priv->lock */
768 is_receive_only (GstRTSPMedia * media)
770 GstRTSPMediaPrivate *priv = media->priv;
771 gboolean receive_only = TRUE;
774 for (i = 0; i < priv->streams->len; i++) {
775 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
776 if (gst_rtsp_stream_is_sender (stream) ||
777 !gst_rtsp_stream_is_receiver (stream)) {
778 receive_only = FALSE;
786 /* must be called with state lock */
788 check_seekable (GstRTSPMedia * media)
791 GstRTSPMediaPrivate *priv = media->priv;
793 g_mutex_lock (&priv->lock);
794 /* Update the seekable state of the pipeline in case it changed */
795 if (is_receive_only (media)) {
796 /* TODO: Seeking for "receive-only"? */
799 guint i, n = priv->streams->len;
801 for (i = 0; i < n; i++) {
802 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
804 if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
805 GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
807 g_mutex_unlock (&priv->lock);
813 query = gst_query_new_seeking (GST_FORMAT_TIME);
814 if (gst_element_query (priv->pipeline, query)) {
819 gst_query_parse_seeking (query, &format, &seekable, &start, &end);
820 priv->seekable = seekable ? G_MAXINT64 : 0;
821 } else if (priv->streams->len) {
822 gboolean seekable = TRUE;
823 guint i, n = priv->streams->len;
825 GST_DEBUG_OBJECT (media, "Checking %d streams", n);
826 for (i = 0; i < n; i++) {
827 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
828 seekable &= gst_rtsp_stream_seekable (stream);
830 priv->seekable = seekable ? G_MAXINT64 : -1;
833 GST_DEBUG_OBJECT (media, "seekable:%" G_GINT64_FORMAT, priv->seekable);
834 g_mutex_unlock (&priv->lock);
835 gst_query_unref (query);
838 /* must be called with state lock */
840 check_complete (GstRTSPMedia * media)
842 GstRTSPMediaPrivate *priv = media->priv;
844 guint i, n = priv->streams->len;
846 for (i = 0; i < n; i++) {
847 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
849 if (gst_rtsp_stream_is_complete (stream))
856 /* must be called with state lock and private lock */
858 collect_media_stats (GstRTSPMedia * media)
860 GstRTSPMediaPrivate *priv = media->priv;
861 gint64 position = 0, stop = -1;
863 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
864 priv->status != GST_RTSP_MEDIA_STATUS_PREPARING) {
868 priv->range.unit = GST_RTSP_RANGE_NPT;
870 GST_INFO ("collect media stats");
873 priv->range.min.type = GST_RTSP_TIME_NOW;
874 priv->range.min.seconds = -1;
875 priv->range_start = -1;
876 priv->range.max.type = GST_RTSP_TIME_END;
877 priv->range.max.seconds = -1;
878 priv->range_stop = -1;
880 GstRTSPMediaClass *klass;
883 klass = GST_RTSP_MEDIA_GET_CLASS (media);
885 /* get the position */
887 if (klass->query_position)
888 ret = klass->query_position (media, &position);
891 GST_INFO ("position query failed");
895 /* get the current segment stop */
897 if (klass->query_stop)
898 ret = klass->query_stop (media, &stop);
901 GST_INFO ("stop query failed");
905 GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
906 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
908 if (position == -1) {
909 priv->range.min.type = GST_RTSP_TIME_NOW;
910 priv->range.min.seconds = -1;
911 priv->range_start = -1;
913 priv->range.min.type = GST_RTSP_TIME_SECONDS;
914 priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
915 priv->range_start = position;
918 priv->range.max.type = GST_RTSP_TIME_END;
919 priv->range.max.seconds = -1;
920 priv->range_stop = -1;
922 priv->range.max.type = GST_RTSP_TIME_SECONDS;
923 priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
924 priv->range_stop = stop;
926 g_mutex_unlock (&priv->lock);
927 check_seekable (media);
928 g_mutex_lock (&priv->lock);
933 * gst_rtsp_media_new:
934 * @element: (transfer full): a #GstElement
936 * Create a new #GstRTSPMedia instance. @element is the bin element that
937 * provides the different streams. The #GstRTSPMedia object contains the
938 * element to produce RTP data for one or more related (audio/video/..)
941 * Ownership is taken of @element.
943 * Returns: (transfer full): a new #GstRTSPMedia object.
946 gst_rtsp_media_new (GstElement * element)
948 GstRTSPMedia *result;
950 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
952 result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
958 * gst_rtsp_media_get_element:
959 * @media: a #GstRTSPMedia
961 * Get the element that was used when constructing @media.
963 * Returns: (transfer full): a #GstElement. Unref after usage.
966 gst_rtsp_media_get_element (GstRTSPMedia * media)
968 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
970 return gst_object_ref (media->priv->element);
974 * gst_rtsp_media_take_pipeline:
975 * @media: a #GstRTSPMedia
976 * @pipeline: (transfer floating): a #GstPipeline
978 * Set @pipeline as the #GstPipeline for @media. Ownership is
979 * taken of @pipeline.
982 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
984 GstRTSPMediaPrivate *priv;
986 GstNetTimeProvider *nettime;
989 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
990 g_return_if_fail (GST_IS_PIPELINE (pipeline));
994 g_mutex_lock (&priv->lock);
995 old = priv->pipeline;
996 priv->pipeline = gst_object_ref_sink (GST_ELEMENT_CAST (pipeline));
997 nettime = priv->nettime;
998 priv->nettime = NULL;
999 g_mutex_unlock (&priv->lock);
1002 gst_object_unref (old);
1005 gst_object_unref (nettime);
1007 gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
1009 for (l = priv->pending_pipeline_elements; l; l = l->next) {
1010 gst_bin_add (GST_BIN_CAST (pipeline), l->data);
1012 g_list_free (priv->pending_pipeline_elements);
1013 priv->pending_pipeline_elements = NULL;
1017 * gst_rtsp_media_set_permissions:
1018 * @media: a #GstRTSPMedia
1019 * @permissions: (transfer none) (nullable): a #GstRTSPPermissions
1021 * Set @permissions on @media.
1024 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
1025 GstRTSPPermissions * permissions)
1027 GstRTSPMediaPrivate *priv;
1029 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1033 g_mutex_lock (&priv->lock);
1034 if (priv->permissions)
1035 gst_rtsp_permissions_unref (priv->permissions);
1036 if ((priv->permissions = permissions))
1037 gst_rtsp_permissions_ref (permissions);
1038 g_mutex_unlock (&priv->lock);
1042 * gst_rtsp_media_get_permissions:
1043 * @media: a #GstRTSPMedia
1045 * Get the permissions object from @media.
1047 * Returns: (transfer full) (nullable): a #GstRTSPPermissions object, unref after usage.
1049 GstRTSPPermissions *
1050 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
1052 GstRTSPMediaPrivate *priv;
1053 GstRTSPPermissions *result;
1055 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1059 g_mutex_lock (&priv->lock);
1060 if ((result = priv->permissions))
1061 gst_rtsp_permissions_ref (result);
1062 g_mutex_unlock (&priv->lock);
1068 * gst_rtsp_media_set_suspend_mode:
1069 * @media: a #GstRTSPMedia
1070 * @mode: the new #GstRTSPSuspendMode
1072 * Control how @ media will be suspended after the SDP has been generated and
1073 * after a PAUSE request has been performed.
1075 * Media must be unprepared when setting the suspend mode.
1078 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
1080 GstRTSPMediaPrivate *priv;
1082 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1086 g_rec_mutex_lock (&priv->state_lock);
1087 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1089 priv->suspend_mode = mode;
1090 g_rec_mutex_unlock (&priv->state_lock);
1097 GST_WARNING ("media %p was prepared", media);
1098 g_rec_mutex_unlock (&priv->state_lock);
1103 * gst_rtsp_media_get_suspend_mode:
1104 * @media: a #GstRTSPMedia
1106 * Get how @media will be suspended.
1108 * Returns: #GstRTSPSuspendMode.
1111 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
1113 GstRTSPMediaPrivate *priv;
1114 GstRTSPSuspendMode res;
1116 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
1120 g_rec_mutex_lock (&priv->state_lock);
1121 res = priv->suspend_mode;
1122 g_rec_mutex_unlock (&priv->state_lock);
1128 * gst_rtsp_media_set_shared:
1129 * @media: a #GstRTSPMedia
1130 * @shared: the new value
1132 * Set or unset if the pipeline for @media can be shared will multiple clients.
1133 * When @shared is %TRUE, client requests for this media will share the media
1137 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
1139 GstRTSPMediaPrivate *priv;
1141 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1145 g_mutex_lock (&priv->lock);
1146 priv->shared = shared;
1147 g_mutex_unlock (&priv->lock);
1151 * gst_rtsp_media_is_shared:
1152 * @media: a #GstRTSPMedia
1154 * Check if the pipeline for @media can be shared between multiple clients.
1156 * Returns: %TRUE if the media can be shared between clients.
1159 gst_rtsp_media_is_shared (GstRTSPMedia * media)
1161 GstRTSPMediaPrivate *priv;
1164 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1168 g_mutex_lock (&priv->lock);
1170 g_mutex_unlock (&priv->lock);
1176 * gst_rtsp_media_set_reusable:
1177 * @media: a #GstRTSPMedia
1178 * @reusable: the new value
1180 * Set or unset if the pipeline for @media can be reused after the pipeline has
1184 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
1186 GstRTSPMediaPrivate *priv;
1188 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1192 g_mutex_lock (&priv->lock);
1193 priv->reusable = reusable;
1194 g_mutex_unlock (&priv->lock);
1198 * gst_rtsp_media_is_reusable:
1199 * @media: a #GstRTSPMedia
1201 * Check if the pipeline for @media can be reused after an unprepare.
1203 * Returns: %TRUE if the media can be reused
1206 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
1208 GstRTSPMediaPrivate *priv;
1211 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1215 g_mutex_lock (&priv->lock);
1216 res = priv->reusable;
1217 g_mutex_unlock (&priv->lock);
1223 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
1225 gst_rtsp_stream_set_profiles (stream, *profiles);
1229 * gst_rtsp_media_set_profiles:
1230 * @media: a #GstRTSPMedia
1231 * @profiles: the new flags
1233 * Configure the allowed lower transport for @media.
1236 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
1238 GstRTSPMediaPrivate *priv;
1240 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1244 g_mutex_lock (&priv->lock);
1245 priv->profiles = profiles;
1246 g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
1247 g_mutex_unlock (&priv->lock);
1251 * gst_rtsp_media_get_profiles:
1252 * @media: a #GstRTSPMedia
1254 * Get the allowed profiles of @media.
1256 * Returns: a #GstRTSPProfile
1259 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
1261 GstRTSPMediaPrivate *priv;
1264 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
1268 g_mutex_lock (&priv->lock);
1269 res = priv->profiles;
1270 g_mutex_unlock (&priv->lock);
1276 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
1278 gst_rtsp_stream_set_protocols (stream, *protocols);
1282 * gst_rtsp_media_set_protocols:
1283 * @media: a #GstRTSPMedia
1284 * @protocols: the new flags
1286 * Configure the allowed lower transport for @media.
1289 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
1291 GstRTSPMediaPrivate *priv;
1293 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1297 g_mutex_lock (&priv->lock);
1298 priv->protocols = protocols;
1299 g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
1300 g_mutex_unlock (&priv->lock);
1304 * gst_rtsp_media_get_protocols:
1305 * @media: a #GstRTSPMedia
1307 * Get the allowed protocols of @media.
1309 * Returns: a #GstRTSPLowerTrans
1312 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
1314 GstRTSPMediaPrivate *priv;
1315 GstRTSPLowerTrans res;
1317 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
1318 GST_RTSP_LOWER_TRANS_UNKNOWN);
1322 g_mutex_lock (&priv->lock);
1323 res = priv->protocols;
1324 g_mutex_unlock (&priv->lock);
1330 * gst_rtsp_media_set_eos_shutdown:
1331 * @media: a #GstRTSPMedia
1332 * @eos_shutdown: the new value
1334 * Set or unset if an EOS event will be sent to the pipeline for @media before
1338 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
1340 GstRTSPMediaPrivate *priv;
1342 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1346 g_mutex_lock (&priv->lock);
1347 priv->eos_shutdown = eos_shutdown;
1348 g_mutex_unlock (&priv->lock);
1352 * gst_rtsp_media_is_eos_shutdown:
1353 * @media: a #GstRTSPMedia
1355 * Check if the pipeline for @media will send an EOS down the pipeline before
1358 * Returns: %TRUE if the media will send EOS before unpreparing.
1361 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
1363 GstRTSPMediaPrivate *priv;
1366 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1370 g_mutex_lock (&priv->lock);
1371 res = priv->eos_shutdown;
1372 g_mutex_unlock (&priv->lock);
1378 * gst_rtsp_media_set_buffer_size:
1379 * @media: a #GstRTSPMedia
1380 * @size: the new value
1382 * Set the kernel UDP buffer size.
1385 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1387 GstRTSPMediaPrivate *priv;
1390 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1392 GST_LOG_OBJECT (media, "set buffer size %u", size);
1396 g_mutex_lock (&priv->lock);
1397 priv->buffer_size = size;
1399 for (i = 0; i < priv->streams->len; i++) {
1400 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1401 gst_rtsp_stream_set_buffer_size (stream, size);
1403 g_mutex_unlock (&priv->lock);
1407 * gst_rtsp_media_get_buffer_size:
1408 * @media: a #GstRTSPMedia
1410 * Get the kernel UDP buffer size.
1412 * Returns: the kernel UDP buffer size.
1415 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1417 GstRTSPMediaPrivate *priv;
1420 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1424 g_mutex_lock (&priv->lock);
1425 res = priv->buffer_size;
1426 g_mutex_unlock (&priv->lock);
1432 do_set_dscp_qos (GstRTSPStream * stream, gint * dscp_qos)
1434 gst_rtsp_stream_set_dscp_qos (stream, *dscp_qos);
1438 * gst_rtsp_media_set_dscp_qos:
1439 * @media: a #GstRTSPMedia
1440 * @dscp_qos: a new dscp qos value (0-63, or -1 to disable)
1442 * Configure the dscp qos of attached streams to @dscp_qos.
1447 gst_rtsp_media_set_dscp_qos (GstRTSPMedia * media, gint dscp_qos)
1449 GstRTSPMediaPrivate *priv;
1451 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1453 GST_LOG_OBJECT (media, "set DSCP QoS %d", dscp_qos);
1455 if (dscp_qos < -1 || dscp_qos > 63) {
1456 GST_WARNING_OBJECT (media, "trying to set illegal dscp qos %d", dscp_qos);
1462 g_mutex_lock (&priv->lock);
1463 priv->dscp_qos = dscp_qos;
1464 g_ptr_array_foreach (priv->streams, (GFunc) do_set_dscp_qos, &dscp_qos);
1465 g_mutex_unlock (&priv->lock);
1469 * gst_rtsp_media_get_dscp_qos:
1470 * @media: a #GstRTSPMedia
1472 * Get the configured DSCP QoS of attached media.
1474 * Returns: the DSCP QoS value of attached streams or -1 if disabled.
1479 gst_rtsp_media_get_dscp_qos (GstRTSPMedia * media)
1481 GstRTSPMediaPrivate *priv;
1484 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1488 g_mutex_unlock (&priv->lock);
1489 res = priv->dscp_qos;
1490 g_mutex_unlock (&priv->lock);
1496 * gst_rtsp_media_set_stop_on_disconnect:
1497 * @media: a #GstRTSPMedia
1498 * @stop_on_disconnect: the new value
1500 * Set or unset if the pipeline for @media should be stopped when a
1501 * client disconnects without sending TEARDOWN.
1504 gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
1505 gboolean stop_on_disconnect)
1507 GstRTSPMediaPrivate *priv;
1509 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1513 g_mutex_lock (&priv->lock);
1514 priv->stop_on_disconnect = stop_on_disconnect;
1515 g_mutex_unlock (&priv->lock);
1519 * gst_rtsp_media_is_stop_on_disconnect:
1520 * @media: a #GstRTSPMedia
1522 * Check if the pipeline for @media will be stopped when a client disconnects
1523 * without sending TEARDOWN.
1525 * Returns: %TRUE if the media will be stopped when a client disconnects
1526 * without sending TEARDOWN.
1529 gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
1531 GstRTSPMediaPrivate *priv;
1534 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
1538 g_mutex_lock (&priv->lock);
1539 res = priv->stop_on_disconnect;
1540 g_mutex_unlock (&priv->lock);
1546 * gst_rtsp_media_set_retransmission_time:
1547 * @media: a #GstRTSPMedia
1548 * @time: the new value
1550 * Set the amount of time to store retransmission packets.
1553 gst_rtsp_media_set_retransmission_time (GstRTSPMedia * media, GstClockTime time)
1555 GstRTSPMediaPrivate *priv;
1558 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1560 GST_LOG_OBJECT (media, "set retransmission time %" G_GUINT64_FORMAT, time);
1564 g_mutex_lock (&priv->lock);
1565 priv->rtx_time = time;
1566 for (i = 0; i < priv->streams->len; i++) {
1567 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1569 gst_rtsp_stream_set_retransmission_time (stream, time);
1571 g_mutex_unlock (&priv->lock);
1575 * gst_rtsp_media_get_retransmission_time:
1576 * @media: a #GstRTSPMedia
1578 * Get the amount of time to store retransmission data.
1580 * Returns: the amount of time to store retransmission data.
1583 gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
1585 GstRTSPMediaPrivate *priv;
1588 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1592 g_mutex_lock (&priv->lock);
1593 res = priv->rtx_time;
1594 g_mutex_unlock (&priv->lock);
1600 * gst_rtsp_media_set_do_retransmission:
1602 * Set whether retransmission requests will be sent
1607 gst_rtsp_media_set_do_retransmission (GstRTSPMedia * media,
1608 gboolean do_retransmission)
1610 GstRTSPMediaPrivate *priv;
1612 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1616 g_mutex_lock (&priv->lock);
1617 priv->do_retransmission = do_retransmission;
1620 g_object_set (priv->rtpbin, "do-retransmission", do_retransmission, NULL);
1621 g_mutex_unlock (&priv->lock);
1625 * gst_rtsp_media_get_do_retransmission:
1627 * Returns: Whether retransmission requests will be sent
1632 gst_rtsp_media_get_do_retransmission (GstRTSPMedia * media)
1634 GstRTSPMediaPrivate *priv;
1637 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1641 g_mutex_lock (&priv->lock);
1642 res = priv->do_retransmission;
1643 g_mutex_unlock (&priv->lock);
1649 * gst_rtsp_media_set_latency:
1650 * @media: a #GstRTSPMedia
1651 * @latency: latency in milliseconds
1653 * Configure the latency used for receiving media.
1656 gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
1658 GstRTSPMediaPrivate *priv;
1661 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1663 GST_LOG_OBJECT (media, "set latency %ums", latency);
1667 g_mutex_lock (&priv->lock);
1668 priv->latency = latency;
1670 g_object_set (priv->rtpbin, "latency", latency, NULL);
1672 for (i = 0; i < media->priv->streams->len; i++) {
1673 GObject *storage = NULL;
1675 g_signal_emit_by_name (G_OBJECT (media->priv->rtpbin), "get-storage",
1678 g_object_set (storage, "size-time",
1679 (media->priv->latency + 50) * GST_MSECOND, NULL);
1683 g_mutex_unlock (&priv->lock);
1687 * gst_rtsp_media_get_latency:
1688 * @media: a #GstRTSPMedia
1690 * Get the latency that is used for receiving media.
1692 * Returns: latency in milliseconds
1695 gst_rtsp_media_get_latency (GstRTSPMedia * media)
1697 GstRTSPMediaPrivate *priv;
1700 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1704 g_mutex_lock (&priv->lock);
1705 res = priv->latency;
1706 g_mutex_unlock (&priv->lock);
1712 * gst_rtsp_media_use_time_provider:
1713 * @media: a #GstRTSPMedia
1714 * @time_provider: if a #GstNetTimeProvider should be used
1716 * Set @media to provide a #GstNetTimeProvider.
1719 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1721 GstRTSPMediaPrivate *priv;
1723 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1727 g_mutex_lock (&priv->lock);
1728 priv->time_provider = time_provider;
1729 g_mutex_unlock (&priv->lock);
1733 * gst_rtsp_media_is_time_provider:
1734 * @media: a #GstRTSPMedia
1736 * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1738 * Use gst_rtsp_media_get_time_provider() to get the network clock.
1740 * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1743 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1745 GstRTSPMediaPrivate *priv;
1748 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1752 g_mutex_lock (&priv->lock);
1753 res = priv->time_provider;
1754 g_mutex_unlock (&priv->lock);
1760 * gst_rtsp_media_set_clock:
1761 * @media: a #GstRTSPMedia
1762 * @clock: (nullable): #GstClock to be used
1764 * Configure the clock used for the media.
1767 gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
1769 GstRTSPMediaPrivate *priv;
1771 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1772 g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1774 GST_LOG_OBJECT (media, "setting clock %" GST_PTR_FORMAT, clock);
1778 g_mutex_lock (&priv->lock);
1780 gst_object_unref (priv->clock);
1781 priv->clock = clock ? gst_object_ref (clock) : NULL;
1782 if (priv->pipeline) {
1784 gst_pipeline_use_clock (GST_PIPELINE_CAST (priv->pipeline), clock);
1786 gst_pipeline_auto_clock (GST_PIPELINE_CAST (priv->pipeline));
1789 g_mutex_unlock (&priv->lock);
1793 * gst_rtsp_media_set_publish_clock_mode:
1794 * @media: a #GstRTSPMedia
1795 * @mode: the clock publish mode
1797 * Sets if and how the media clock should be published according to RFC7273.
1802 gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
1803 GstRTSPPublishClockMode mode)
1805 GstRTSPMediaPrivate *priv;
1809 g_mutex_lock (&priv->lock);
1810 priv->publish_clock_mode = mode;
1812 n = priv->streams->len;
1813 for (i = 0; i < n; i++) {
1814 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1816 gst_rtsp_stream_set_publish_clock_mode (stream, mode);
1818 g_mutex_unlock (&priv->lock);
1822 * gst_rtsp_media_get_publish_clock_mode:
1823 * @media: a #GstRTSPMedia
1825 * Gets if and how the media clock should be published according to RFC7273.
1827 * Returns: The GstRTSPPublishClockMode
1831 GstRTSPPublishClockMode
1832 gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
1834 GstRTSPMediaPrivate *priv;
1835 GstRTSPPublishClockMode ret;
1838 g_mutex_lock (&priv->lock);
1839 ret = priv->publish_clock_mode;
1840 g_mutex_unlock (&priv->lock);
1846 * gst_rtsp_media_set_address_pool:
1847 * @media: a #GstRTSPMedia
1848 * @pool: (transfer none) (nullable): a #GstRTSPAddressPool
1850 * configure @pool to be used as the address pool of @media.
1853 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1854 GstRTSPAddressPool * pool)
1856 GstRTSPMediaPrivate *priv;
1857 GstRTSPAddressPool *old;
1859 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1863 GST_LOG_OBJECT (media, "set address pool %p", pool);
1865 g_mutex_lock (&priv->lock);
1866 if ((old = priv->pool) != pool)
1867 priv->pool = pool ? g_object_ref (pool) : NULL;
1870 g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1872 g_mutex_unlock (&priv->lock);
1875 g_object_unref (old);
1879 * gst_rtsp_media_get_address_pool:
1880 * @media: a #GstRTSPMedia
1882 * Get the #GstRTSPAddressPool used as the address pool of @media.
1884 * Returns: (transfer full) (nullable): the #GstRTSPAddressPool of @media.
1885 * g_object_unref() after usage.
1887 GstRTSPAddressPool *
1888 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1890 GstRTSPMediaPrivate *priv;
1891 GstRTSPAddressPool *result;
1893 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1897 g_mutex_lock (&priv->lock);
1898 if ((result = priv->pool))
1899 g_object_ref (result);
1900 g_mutex_unlock (&priv->lock);
1906 * gst_rtsp_media_set_multicast_iface:
1907 * @media: a #GstRTSPMedia
1908 * @multicast_iface: (transfer none) (nullable): a multicast interface name
1910 * configure @multicast_iface to be used for @media.
1913 gst_rtsp_media_set_multicast_iface (GstRTSPMedia * media,
1914 const gchar * multicast_iface)
1916 GstRTSPMediaPrivate *priv;
1919 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1923 GST_LOG_OBJECT (media, "set multicast interface %s", multicast_iface);
1925 g_mutex_lock (&priv->lock);
1926 if ((old = priv->multicast_iface) != multicast_iface)
1927 priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
1930 g_ptr_array_foreach (priv->streams,
1931 (GFunc) gst_rtsp_stream_set_multicast_iface, (gchar *) multicast_iface);
1932 g_mutex_unlock (&priv->lock);
1939 * gst_rtsp_media_get_multicast_iface:
1940 * @media: a #GstRTSPMedia
1942 * Get the multicast interface used for @media.
1944 * Returns: (transfer full) (nullable): the multicast interface for @media.
1945 * g_free() after usage.
1948 gst_rtsp_media_get_multicast_iface (GstRTSPMedia * media)
1950 GstRTSPMediaPrivate *priv;
1953 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1957 g_mutex_lock (&priv->lock);
1958 if ((result = priv->multicast_iface))
1959 result = g_strdup (result);
1960 g_mutex_unlock (&priv->lock);
1966 * gst_rtsp_media_set_max_mcast_ttl:
1967 * @media: a #GstRTSPMedia
1968 * @ttl: the new multicast ttl value
1970 * Set the maximum time-to-live value of outgoing multicast packets.
1972 * Returns: %TRUE if the requested ttl has been set successfully.
1977 gst_rtsp_media_set_max_mcast_ttl (GstRTSPMedia * media, guint ttl)
1979 GstRTSPMediaPrivate *priv;
1982 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1984 GST_LOG_OBJECT (media, "set max mcast ttl %u", ttl);
1988 g_mutex_lock (&priv->lock);
1990 if (ttl == 0 || ttl > DEFAULT_MAX_MCAST_TTL) {
1991 GST_WARNING_OBJECT (media, "The reqested mcast TTL value is not valid.");
1992 g_mutex_unlock (&priv->lock);
1995 priv->max_mcast_ttl = ttl;
1997 for (i = 0; i < priv->streams->len; i++) {
1998 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1999 gst_rtsp_stream_set_max_mcast_ttl (stream, ttl);
2001 g_mutex_unlock (&priv->lock);
2007 * gst_rtsp_media_get_max_mcast_ttl:
2008 * @media: a #GstRTSPMedia
2010 * Get the the maximum time-to-live value of outgoing multicast packets.
2012 * Returns: the maximum time-to-live value of outgoing multicast packets.
2017 gst_rtsp_media_get_max_mcast_ttl (GstRTSPMedia * media)
2019 GstRTSPMediaPrivate *priv;
2022 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2026 g_mutex_lock (&priv->lock);
2027 res = priv->max_mcast_ttl;
2028 g_mutex_unlock (&priv->lock);
2034 * gst_rtsp_media_set_bind_mcast_address:
2035 * @media: a #GstRTSPMedia
2036 * @bind_mcast_addr: the new value
2038 * Decide whether the multicast socket should be bound to a multicast address or
2044 gst_rtsp_media_set_bind_mcast_address (GstRTSPMedia * media,
2045 gboolean bind_mcast_addr)
2047 GstRTSPMediaPrivate *priv;
2050 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2054 g_mutex_lock (&priv->lock);
2055 priv->bind_mcast_address = bind_mcast_addr;
2056 for (i = 0; i < priv->streams->len; i++) {
2057 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2058 gst_rtsp_stream_set_bind_mcast_address (stream, bind_mcast_addr);
2060 g_mutex_unlock (&priv->lock);
2064 * gst_rtsp_media_is_bind_mcast_address:
2065 * @media: a #GstRTSPMedia
2067 * Check if multicast sockets are configured to be bound to multicast addresses.
2069 * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
2074 gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia * media)
2076 GstRTSPMediaPrivate *priv;
2079 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2083 g_mutex_lock (&priv->lock);
2084 result = priv->bind_mcast_address;
2085 g_mutex_unlock (&priv->lock);
2091 _find_payload_types (GstRTSPMedia * media)
2094 GQueue queue = G_QUEUE_INIT;
2096 n = media->priv->streams->len;
2097 for (i = 0; i < n; i++) {
2098 GstRTSPStream *stream = g_ptr_array_index (media->priv->streams, i);
2099 guint pt = gst_rtsp_stream_get_pt (stream);
2101 g_queue_push_tail (&queue, GUINT_TO_POINTER (pt));
2108 _next_available_pt (GList * payloads)
2112 for (i = 96; i <= 127; i++) {
2113 GList *iter = g_list_find (payloads, GINT_TO_POINTER (i));
2115 return GPOINTER_TO_UINT (i);
2122 * gst_rtsp_media_collect_streams:
2123 * @media: a #GstRTSPMedia
2125 * Find all payloader elements, they should be named pay\%d in the
2126 * element of @media, and create #GstRTSPStreams for them.
2128 * Collect all dynamic elements, named dynpay\%d, and add them to
2129 * the list of dynamic elements.
2131 * Find all depayloader elements, they should be named depay\%d in the
2132 * element of @media, and create #GstRTSPStreams for them.
2135 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
2137 GstRTSPMediaPrivate *priv;
2138 GstElement *element, *elem;
2142 gboolean more_elem_remaining = TRUE;
2143 GstRTSPTransportMode mode = 0;
2145 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2148 element = priv->element;
2151 for (i = 0; more_elem_remaining; i++) {
2154 more_elem_remaining = FALSE;
2156 name = g_strdup_printf ("pay%d", i);
2157 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2159 GST_INFO ("found stream %d with payloader %p", i, elem);
2161 /* take the pad of the payloader */
2162 pad = gst_element_get_static_pad (elem, "src");
2164 /* find the real payload element in case elem is a GstBin */
2165 pay = find_payload_element (elem, pad);
2167 /* create the stream */
2169 GST_WARNING ("could not find real payloader, using bin");
2170 gst_rtsp_media_create_stream (media, elem, pad);
2172 gst_rtsp_media_create_stream (media, pay, pad);
2173 gst_object_unref (pay);
2176 gst_object_unref (pad);
2177 gst_object_unref (elem);
2180 more_elem_remaining = TRUE;
2181 mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2185 name = g_strdup_printf ("dynpay%d", i);
2186 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2187 /* a stream that will dynamically create pads to provide RTP packets */
2188 GST_INFO ("found dynamic element %d, %p", i, elem);
2190 g_mutex_lock (&priv->lock);
2191 priv->dynamic = g_list_prepend (priv->dynamic, elem);
2192 g_mutex_unlock (&priv->lock);
2194 priv->nb_dynamic_elements++;
2197 more_elem_remaining = TRUE;
2198 mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2202 name = g_strdup_printf ("depay%d", i);
2203 if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2204 GST_INFO ("found stream %d with depayloader %p", i, elem);
2206 /* take the pad of the payloader */
2207 pad = gst_element_get_static_pad (elem, "sink");
2208 /* create the stream */
2209 gst_rtsp_media_create_stream (media, elem, pad);
2210 gst_object_unref (pad);
2211 gst_object_unref (elem);
2214 more_elem_remaining = TRUE;
2215 mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
2221 if (priv->transport_mode != mode)
2222 GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
2223 priv->transport_mode, mode);
2229 GstElement *appsink, *appsrc;
2230 GstRTSPStream *stream;
2233 static GstFlowReturn
2234 appsink_new_sample (GstAppSink * appsink, gpointer user_data)
2236 AppSinkSrcData *data = user_data;
2240 sample = gst_app_sink_pull_sample (appsink);
2242 return GST_FLOW_FLUSHING;
2245 ret = gst_app_src_push_sample (GST_APP_SRC (data->appsrc), sample);
2246 gst_sample_unref (sample);
2250 static GstAppSinkCallbacks appsink_callbacks = {
2256 static GstPadProbeReturn
2257 appsink_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2259 AppSinkSrcData *data = user_data;
2261 if (GST_IS_EVENT (info->data)
2262 && GST_EVENT_TYPE (info->data) == GST_EVENT_LATENCY) {
2263 GstClockTime min, max;
2265 if (gst_base_sink_query_latency (GST_BASE_SINK (data->appsink), NULL, NULL,
2267 g_object_set (data->appsrc, "min-latency", min, "max-latency", max, NULL);
2268 GST_DEBUG ("setting latency to min %" GST_TIME_FORMAT " max %"
2269 GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
2271 } else if (GST_IS_QUERY (info->data)) {
2272 GstPad *srcpad = gst_element_get_static_pad (data->appsrc, "src");
2273 if (gst_pad_peer_query (srcpad, GST_QUERY_CAST (info->data))) {
2274 gst_object_unref (srcpad);
2275 return GST_PAD_PROBE_HANDLED;
2277 gst_object_unref (srcpad);
2280 return GST_PAD_PROBE_OK;
2283 static GstPadProbeReturn
2284 appsrc_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2286 AppSinkSrcData *data = user_data;
2288 if (GST_IS_QUERY (info->data)) {
2289 GstPad *sinkpad = gst_element_get_static_pad (data->appsink, "sink");
2290 if (gst_pad_peer_query (sinkpad, GST_QUERY_CAST (info->data))) {
2291 gst_object_unref (sinkpad);
2292 return GST_PAD_PROBE_HANDLED;
2294 gst_object_unref (sinkpad);
2297 return GST_PAD_PROBE_OK;
2301 * gst_rtsp_media_create_stream:
2302 * @media: a #GstRTSPMedia
2303 * @payloader: a #GstElement
2306 * Create a new stream in @media that provides RTP data on @pad.
2307 * @pad should be a pad of an element inside @media->element.
2309 * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
2313 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
2316 GstRTSPMediaPrivate *priv;
2317 GstRTSPStream *stream;
2321 AppSinkSrcData *data = NULL;
2323 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2324 g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
2325 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2329 g_mutex_lock (&priv->lock);
2330 idx = priv->streams->len;
2332 GST_DEBUG ("media %p: creating stream with index %d and payloader %"
2333 GST_PTR_FORMAT, media, idx, payloader);
2335 if (GST_PAD_IS_SRC (pad))
2336 name = g_strdup_printf ("src_%u", idx);
2338 name = g_strdup_printf ("sink_%u", idx);
2340 if ((GST_PAD_IS_SRC (pad) && priv->element->numsinkpads > 0) ||
2341 (GST_PAD_IS_SINK (pad) && priv->element->numsrcpads > 0)) {
2342 GstElement *appsink, *appsrc;
2343 GstPad *sinkpad, *srcpad;
2345 appsink = gst_element_factory_make ("appsink", NULL);
2346 appsrc = gst_element_factory_make ("appsrc", NULL);
2348 if (GST_PAD_IS_SINK (pad)) {
2349 srcpad = gst_element_get_static_pad (appsrc, "src");
2351 gst_bin_add (GST_BIN (priv->element), appsrc);
2353 gst_pad_link (srcpad, pad);
2354 gst_object_unref (srcpad);
2356 streampad = gst_element_get_static_pad (appsink, "sink");
2358 priv->pending_pipeline_elements =
2359 g_list_prepend (priv->pending_pipeline_elements, appsink);
2361 sinkpad = gst_element_get_static_pad (appsink, "sink");
2363 gst_pad_link (pad, sinkpad);
2364 gst_object_unref (sinkpad);
2366 streampad = gst_element_get_static_pad (appsrc, "src");
2368 priv->pending_pipeline_elements =
2369 g_list_prepend (priv->pending_pipeline_elements, appsrc);
2372 g_object_set (appsrc, "block", TRUE, "format", GST_FORMAT_TIME, "is-live",
2373 TRUE, "emit-signals", FALSE, NULL);
2374 g_object_set (appsink, "sync", FALSE, "async", FALSE, "emit-signals",
2375 FALSE, "buffer-list", TRUE, NULL);
2377 data = g_new0 (AppSinkSrcData, 1);
2378 data->appsink = appsink;
2379 data->appsrc = appsrc;
2381 sinkpad = gst_element_get_static_pad (appsink, "sink");
2382 gst_pad_add_probe (sinkpad,
2383 GST_PAD_PROBE_TYPE_EVENT_UPSTREAM | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM,
2384 appsink_pad_probe, data, NULL);
2385 gst_object_unref (sinkpad);
2387 srcpad = gst_element_get_static_pad (appsrc, "src");
2388 gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_QUERY_UPSTREAM,
2389 appsrc_pad_probe, data, NULL);
2390 gst_object_unref (srcpad);
2392 gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &appsink_callbacks,
2394 g_object_set_data_full (G_OBJECT (streampad), "media-appsink-appsrc", data,
2397 streampad = gst_ghost_pad_new (name, pad);
2398 gst_pad_set_active (streampad, TRUE);
2399 gst_element_add_pad (priv->element, streampad);
2403 stream = gst_rtsp_stream_new (idx, payloader, streampad);
2405 data->stream = stream;
2407 gst_rtsp_stream_set_address_pool (stream, priv->pool);
2408 gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface);
2409 gst_rtsp_stream_set_max_mcast_ttl (stream, priv->max_mcast_ttl);
2410 gst_rtsp_stream_set_bind_mcast_address (stream, priv->bind_mcast_address);
2411 gst_rtsp_stream_set_profiles (stream, priv->profiles);
2412 gst_rtsp_stream_set_protocols (stream, priv->protocols);
2413 gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
2414 gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
2415 gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
2416 gst_rtsp_stream_set_rate_control (stream, priv->do_rate_control);
2418 g_ptr_array_add (priv->streams, stream);
2420 if (GST_PAD_IS_SRC (pad)) {
2424 g_list_free (priv->payloads);
2425 priv->payloads = _find_payload_types (media);
2427 n = priv->streams->len;
2428 for (i = 0; i < n; i++) {
2429 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2430 guint rtx_pt = _next_available_pt (priv->payloads);
2433 GST_WARNING ("Ran out of space of dynamic payload types");
2437 gst_rtsp_stream_set_retransmission_pt (stream, rtx_pt);
2440 g_list_append (priv->payloads, GUINT_TO_POINTER (rtx_pt));
2443 g_mutex_unlock (&priv->lock);
2445 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
2452 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
2454 GstRTSPMediaPrivate *priv;
2456 AppSinkSrcData *data;
2460 g_mutex_lock (&priv->lock);
2461 /* remove the ghostpad */
2462 srcpad = gst_rtsp_stream_get_srcpad (stream);
2463 data = g_object_get_data (G_OBJECT (srcpad), "media-appsink-appsrc");
2465 if (GST_OBJECT_PARENT (data->appsrc) == GST_OBJECT_CAST (priv->pipeline))
2466 gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsrc);
2467 else if (GST_OBJECT_PARENT (data->appsrc) ==
2468 GST_OBJECT_CAST (priv->element))
2469 gst_bin_remove (GST_BIN_CAST (priv->element), data->appsrc);
2470 if (GST_OBJECT_PARENT (data->appsink) == GST_OBJECT_CAST (priv->pipeline))
2471 gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsink);
2472 else if (GST_OBJECT_PARENT (data->appsink) ==
2473 GST_OBJECT_CAST (priv->element))
2474 gst_bin_remove (GST_BIN_CAST (priv->element), data->appsink);
2476 gst_element_remove_pad (priv->element, srcpad);
2478 gst_object_unref (srcpad);
2479 /* now remove the stream */
2480 g_object_ref (stream);
2481 g_ptr_array_remove (priv->streams, stream);
2482 g_mutex_unlock (&priv->lock);
2484 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
2487 g_object_unref (stream);
2491 * gst_rtsp_media_n_streams:
2492 * @media: a #GstRTSPMedia
2494 * Get the number of streams in this media.
2496 * Returns: The number of streams.
2499 gst_rtsp_media_n_streams (GstRTSPMedia * media)
2501 GstRTSPMediaPrivate *priv;
2504 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
2508 g_mutex_lock (&priv->lock);
2509 res = priv->streams->len;
2510 g_mutex_unlock (&priv->lock);
2516 * gst_rtsp_media_get_stream:
2517 * @media: a #GstRTSPMedia
2518 * @idx: the stream index
2520 * Retrieve the stream with index @idx from @media.
2522 * Returns: (nullable) (transfer none): the #GstRTSPStream at index
2523 * @idx or %NULL when a stream with that index did not exist.
2526 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
2528 GstRTSPMediaPrivate *priv;
2531 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2535 g_mutex_lock (&priv->lock);
2536 if (idx < priv->streams->len)
2537 res = g_ptr_array_index (priv->streams, idx);
2540 g_mutex_unlock (&priv->lock);
2546 * gst_rtsp_media_find_stream:
2547 * @media: a #GstRTSPMedia
2548 * @control: the control of the stream
2550 * Find a stream in @media with @control as the control uri.
2552 * Returns: (nullable) (transfer none): the #GstRTSPStream with
2553 * control uri @control or %NULL when a stream with that control did
2557 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
2559 GstRTSPMediaPrivate *priv;
2563 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2564 g_return_val_if_fail (control != NULL, NULL);
2570 g_mutex_lock (&priv->lock);
2571 for (i = 0; i < priv->streams->len; i++) {
2572 GstRTSPStream *test;
2574 test = g_ptr_array_index (priv->streams, i);
2575 if (gst_rtsp_stream_has_control (test, control)) {
2580 g_mutex_unlock (&priv->lock);
2585 /* called with state-lock */
2587 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
2588 GstRTSPRangeUnit unit)
2590 return gst_rtsp_range_convert_units (range, unit);
2594 * gst_rtsp_media_get_range_string:
2595 * @media: a #GstRTSPMedia
2596 * @play: for the PLAY request
2597 * @unit: the unit to use for the string
2599 * Get the current range as a string. @media must be prepared with
2600 * gst_rtsp_media_prepare ().
2602 * Returns: (transfer full) (nullable): The range as a string, g_free() after usage.
2605 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
2606 GstRTSPRangeUnit unit)
2608 GstRTSPMediaClass *klass;
2609 GstRTSPMediaPrivate *priv;
2611 GstRTSPTimeRange range;
2613 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2614 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2615 g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2619 g_rec_mutex_lock (&priv->state_lock);
2620 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2621 priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2624 /* Update the range value with current position/duration */
2625 g_mutex_lock (&priv->lock);
2626 collect_media_stats (media);
2629 range = priv->range;
2631 if (!play && priv->n_active > 0) {
2632 range.min.type = GST_RTSP_TIME_NOW;
2633 range.min.seconds = -1;
2635 g_mutex_unlock (&priv->lock);
2636 g_rec_mutex_unlock (&priv->state_lock);
2638 if (!klass->convert_range (media, &range, unit))
2639 goto conversion_failed;
2641 result = gst_rtsp_range_to_string (&range);
2648 GST_WARNING ("media %p was not prepared", media);
2649 g_rec_mutex_unlock (&priv->state_lock);
2654 GST_WARNING ("range conversion to unit %d failed", unit);
2660 * gst_rtsp_media_get_rates:
2661 * @media: a #GstRTSPMedia
2662 * @rate: (optional) (out caller-allocates): the rate of the current segment
2663 * @applied_rate: (optional) (out caller-allocates): the applied_rate of the current segment
2665 * Get the rate and applied_rate of the current segment.
2667 * Returns: %FALSE if looking up the rate and applied rate failed. Otherwise
2668 * %TRUE is returned and @rate and @applied_rate are set to the rate and
2669 * applied_rate of the current segment.
2673 gst_rtsp_media_get_rates (GstRTSPMedia * media, gdouble * rate,
2674 gdouble * applied_rate)
2676 GstRTSPMediaPrivate *priv;
2677 GstRTSPStream *stream;
2678 gdouble save_rate, save_applied_rate;
2679 gboolean result = TRUE;
2680 gboolean first_stream = TRUE;
2683 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2685 if (!rate && !applied_rate) {
2686 GST_WARNING_OBJECT (media, "rate and applied_rate are both NULL");
2692 g_mutex_lock (&priv->lock);
2694 g_assert (priv->streams->len > 0);
2695 for (i = 0; i < priv->streams->len; i++) {
2696 stream = g_ptr_array_index (priv->streams, i);
2697 if (gst_rtsp_stream_is_complete (stream)) {
2698 if (gst_rtsp_stream_get_rates (stream, rate, applied_rate)) {
2701 save_applied_rate = *applied_rate;
2702 first_stream = FALSE;
2704 if (save_rate != *rate || save_applied_rate != *applied_rate) {
2705 /* diffrent rate or applied_rate, weird */
2712 /* complete stream withot rate and applied_rate, weird */
2721 GST_WARNING_OBJECT (media,
2722 "failed to obtain consistent rate and applied_rate");
2725 g_mutex_unlock (&priv->lock);
2731 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
2733 gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
2737 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
2739 GstRTSPMediaPrivate *priv = media->priv;
2741 GST_DEBUG ("media %p set blocked %d", media, blocked);
2742 priv->blocked = blocked;
2743 g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
2746 priv->blocking_msg_received = 0;
2750 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
2752 GstRTSPMediaPrivate *priv = media->priv;
2754 g_mutex_lock (&priv->lock);
2755 priv->status = status;
2756 GST_DEBUG ("setting new status to %d", status);
2757 g_cond_broadcast (&priv->cond);
2758 g_mutex_unlock (&priv->lock);
2762 * gst_rtsp_media_get_status:
2763 * @media: a #GstRTSPMedia
2765 * Get the status of @media. When @media is busy preparing, this function waits
2766 * until @media is prepared or in error.
2768 * Returns: the status of @media.
2771 gst_rtsp_media_get_status (GstRTSPMedia * media)
2773 GstRTSPMediaPrivate *priv = media->priv;
2774 GstRTSPMediaStatus result;
2777 g_mutex_lock (&priv->lock);
2778 end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
2779 /* while we are preparing, wait */
2780 while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
2781 GST_DEBUG ("waiting for status change");
2782 if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
2783 GST_DEBUG ("timeout, assuming error status");
2784 priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
2787 /* could be success or error */
2788 result = priv->status;
2789 GST_DEBUG ("got status %d", result);
2790 g_mutex_unlock (&priv->lock);
2796 * gst_rtsp_media_seek_trickmode:
2797 * @media: a #GstRTSPMedia
2798 * @range: (transfer none): a #GstRTSPTimeRange
2799 * @flags: The minimal set of #GstSeekFlags to use
2800 * @rate: the rate to use in the seek
2801 * @trickmode_interval: The trickmode interval to use for KEY_UNITS trick mode
2803 * Seek the pipeline of @media to @range with the given @flags and @rate,
2804 * and @trickmode_interval.
2805 * @media must be prepared with gst_rtsp_media_prepare().
2806 * In order to perform the seek operation, the pipeline must contain all
2807 * needed transport parts (transport sinks).
2809 * Returns: %TRUE on success.
2814 gst_rtsp_media_seek_trickmode (GstRTSPMedia * media,
2815 GstRTSPTimeRange * range, GstSeekFlags flags, gdouble rate,
2816 GstClockTime trickmode_interval)
2818 GstRTSPMediaClass *klass;
2819 GstRTSPMediaPrivate *priv;
2821 GstClockTime start, stop;
2822 GstSeekType start_type, stop_type;
2823 gint64 current_position;
2824 gboolean force_seek;
2826 klass = GST_RTSP_MEDIA_GET_CLASS (media);
2828 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2829 /* if there's a range then klass->convert_range must be set */
2830 g_return_val_if_fail (range == NULL || klass->convert_range != NULL, FALSE);
2832 GST_DEBUG ("flags=%x rate=%f", flags, rate);
2836 g_rec_mutex_lock (&priv->state_lock);
2837 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2840 /* check if the media pipeline is complete in order to perform a
2841 * seek operation on it */
2842 if (!check_complete (media))
2845 /* Update the seekable state of the pipeline in case it changed */
2846 check_seekable (media);
2848 if (priv->seekable == 0) {
2849 GST_FIXME_OBJECT (media, "Handle going back to 0 for none live"
2850 " not seekable streams.");
2853 } else if (priv->seekable < 0) {
2857 start_type = stop_type = GST_SEEK_TYPE_NONE;
2858 start = stop = GST_CLOCK_TIME_NONE;
2860 /* if caller provided a range convert it to NPT format
2861 * if no range provided the seek is assumed to be the same position but with
2862 * e.g. the rate changed */
2863 if (range != NULL) {
2864 if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
2866 gst_rtsp_range_get_times (range, &start, &stop);
2868 GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2869 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2870 GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2871 GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
2874 current_position = -1;
2875 if (klass->query_position)
2876 klass->query_position (media, ¤t_position);
2877 GST_INFO ("current media position %" GST_TIME_FORMAT,
2878 GST_TIME_ARGS (current_position));
2880 if (start != GST_CLOCK_TIME_NONE)
2881 start_type = GST_SEEK_TYPE_SET;
2883 if (stop != GST_CLOCK_TIME_NONE)
2884 stop_type = GST_SEEK_TYPE_SET;
2886 /* we force a seek if any trickmode flag is set, or if the flush flag is set or
2887 * the rate is non-standard, i.e. not 1.0 */
2888 force_seek = (flags & TRICKMODE_FLAGS) || (flags & GST_SEEK_FLAG_FLUSH) ||
2891 if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE || force_seek) {
2892 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2893 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2895 /* depends on the current playing state of the pipeline. We might need to
2896 * queue this until we get EOS. */
2897 flags |= GST_SEEK_FLAG_FLUSH;
2899 /* if range start was not supplied we must continue from current position.
2900 * but since we're doing a flushing seek, let us query the current position
2901 * so we end up at exactly the same position after the seek. */
2902 if (range == NULL || range->min.type == GST_RTSP_TIME_END) {
2903 if (current_position == -1) {
2904 GST_WARNING ("current position unknown");
2906 GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
2907 GST_TIME_ARGS (current_position));
2908 start = current_position;
2909 start_type = GST_SEEK_TYPE_SET;
2913 if (start == current_position && stop_type == GST_SEEK_TYPE_NONE &&
2915 GST_DEBUG ("no position change, no flags set by caller, so not seeking");
2918 GstEvent *seek_event;
2919 gboolean unblock = FALSE;
2921 /* Handle expected async-done before waiting on next async-done.
2923 * Since the seek further down in code will cause a preroll and
2924 * a async-done will be generated it's important to wait on async-done
2925 * if that is expected. Otherwise there is the risk that the waiting
2926 * for async-done after the seek is detecting the expected async-done
2927 * instead of the one that corresponds to the seek. Then execution
2928 * continue and act as if the pipeline is prerolled, but it's not.
2930 * During wait_preroll message GST_MESSAGE_ASYNC_DONE will come
2931 * and then the state will change from preparing to prepared */
2932 if (priv->expected_async_done) {
2933 GST_DEBUG (" expected to get async-done, waiting ");
2934 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2935 g_rec_mutex_unlock (&priv->state_lock);
2937 /* wait until pipeline is prerolled */
2938 if (!wait_preroll (media))
2939 goto preroll_failed_expected_async_done;
2941 g_rec_mutex_lock (&priv->state_lock);
2942 GST_DEBUG (" got expected async-done");
2945 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2948 GstClockTime temp_time = start;
2949 GstSeekType temp_type = start_type;
2952 start_type = stop_type;
2954 stop_type = temp_type;
2957 seek_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type,
2958 start, stop_type, stop);
2960 gst_event_set_seek_trickmode_interval (seek_event, trickmode_interval);
2962 if (!media->priv->blocked) {
2963 /* Prevent a race condition with multiple streams,
2964 * where one stream may have time to preroll before others
2965 * have even started flushing, causing async-done to be
2968 media_streams_set_blocked (media, TRUE);
2972 res = gst_element_send_event (priv->pipeline, seek_event);
2975 media_streams_set_blocked (media, FALSE);
2977 /* and block for the seek to complete */
2978 GST_INFO ("done seeking %d", res);
2982 g_rec_mutex_unlock (&priv->state_lock);
2984 /* wait until pipeline is prerolled again, this will also collect stats */
2985 if (!wait_preroll (media))
2986 goto preroll_failed;
2988 g_rec_mutex_lock (&priv->state_lock);
2989 GST_INFO ("prerolled again");
2992 GST_INFO ("no seek needed");
2995 g_rec_mutex_unlock (&priv->state_lock);
3002 g_rec_mutex_unlock (&priv->state_lock);
3003 GST_INFO ("media %p is not prepared", media);
3008 g_rec_mutex_unlock (&priv->state_lock);
3009 GST_INFO ("pipeline is not complete");
3014 g_rec_mutex_unlock (&priv->state_lock);
3015 GST_INFO ("pipeline is not seekable");
3020 g_rec_mutex_unlock (&priv->state_lock);
3021 GST_WARNING ("conversion to npt not supported");
3026 g_rec_mutex_unlock (&priv->state_lock);
3027 GST_INFO ("seeking failed");
3028 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3033 GST_WARNING ("failed to preroll after seek");
3036 preroll_failed_expected_async_done:
3038 GST_WARNING ("failed to preroll");
3044 * gst_rtsp_media_seek_full:
3045 * @media: a #GstRTSPMedia
3046 * @range: (transfer none): a #GstRTSPTimeRange
3047 * @flags: The minimal set of #GstSeekFlags to use
3049 * Seek the pipeline of @media to @range with the given @flags.
3050 * @media must be prepared with gst_rtsp_media_prepare().
3052 * Returns: %TRUE on success.
3056 gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
3059 return gst_rtsp_media_seek_trickmode (media, range, flags, 1.0, 0);
3063 * gst_rtsp_media_seek:
3064 * @media: a #GstRTSPMedia
3065 * @range: (transfer none): a #GstRTSPTimeRange
3067 * Seek the pipeline of @media to @range. @media must be prepared with
3068 * gst_rtsp_media_prepare().
3070 * Returns: %TRUE on success.
3073 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
3075 return gst_rtsp_media_seek_trickmode (media, range, GST_SEEK_FLAG_NONE,
3080 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
3082 *blocked &= gst_rtsp_stream_is_blocking (stream);
3086 media_streams_blocking (GstRTSPMedia * media)
3088 gboolean blocking = TRUE;
3090 g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
3096 static GstStateChangeReturn
3097 set_state (GstRTSPMedia * media, GstState state)
3099 GstRTSPMediaPrivate *priv = media->priv;
3100 GstStateChangeReturn ret;
3102 GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
3104 ret = gst_element_set_state (priv->pipeline, state);
3109 static GstStateChangeReturn
3110 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
3112 GstRTSPMediaPrivate *priv = media->priv;
3113 GstStateChangeReturn ret;
3115 GST_INFO ("set target state to %s for media %p",
3116 gst_element_state_get_name (state), media);
3117 priv->target_state = state;
3119 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
3120 priv->target_state, NULL);
3123 ret = set_state (media, state);
3125 ret = GST_STATE_CHANGE_SUCCESS;
3131 stream_collect_active (GstRTSPStream * stream, guint * active_streams)
3133 if (gst_rtsp_stream_is_complete (stream))
3134 (*active_streams)++;
3138 nbr_active_streams (GstRTSPMedia * media)
3142 g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_active,
3148 /* called with state-lock */
3149 /* called with state-lock */
3151 default_handle_message (GstRTSPMedia * media, GstMessage * message)
3153 GstRTSPMediaPrivate *priv = media->priv;
3154 GstMessageType type;
3156 type = GST_MESSAGE_TYPE (message);
3159 case GST_MESSAGE_STATE_CHANGED:
3161 GstState old, new, pending;
3163 if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
3166 gst_message_parse_state_changed (message, &old, &new, &pending);
3168 GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
3169 gst_element_state_get_name (old), gst_element_state_get_name (new),
3170 gst_element_state_get_name (pending));
3171 if (priv->no_more_pads_pending == 0
3172 && gst_rtsp_media_is_receive_only (media) && old == GST_STATE_READY
3173 && new == GST_STATE_PAUSED) {
3174 GST_INFO ("%p: went to PAUSED, prepared now", media);
3175 g_mutex_lock (&priv->lock);
3176 collect_media_stats (media);
3177 g_mutex_unlock (&priv->lock);
3179 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3180 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3185 case GST_MESSAGE_BUFFERING:
3189 gst_message_parse_buffering (message, &percent);
3191 /* no state management needed for live pipelines */
3195 if (percent == 100) {
3196 /* a 100% message means buffering is done */
3197 priv->buffering = FALSE;
3198 /* if the desired state is playing, go back */
3199 if (priv->target_state == GST_STATE_PLAYING) {
3200 GST_INFO ("Buffering done, setting pipeline to PLAYING");
3201 set_state (media, GST_STATE_PLAYING);
3203 GST_INFO ("Buffering done");
3206 /* buffering busy */
3207 if (priv->buffering == FALSE) {
3208 if (priv->target_state == GST_STATE_PLAYING) {
3209 /* we were not buffering but PLAYING, PAUSE the pipeline. */
3210 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
3211 set_state (media, GST_STATE_PAUSED);
3213 GST_INFO ("Buffering ...");
3216 priv->buffering = TRUE;
3220 case GST_MESSAGE_LATENCY:
3222 gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
3225 case GST_MESSAGE_ERROR:
3230 gst_message_parse_error (message, &gerror, &debug);
3231 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
3232 g_error_free (gerror);
3235 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3238 case GST_MESSAGE_WARNING:
3243 gst_message_parse_warning (message, &gerror, &debug);
3244 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
3245 g_error_free (gerror);
3249 case GST_MESSAGE_ELEMENT:
3251 const GstStructure *s;
3253 s = gst_message_get_structure (message);
3254 if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
3255 GST_DEBUG ("media received blocking message");
3256 priv->blocking_msg_received++;
3257 if (priv->blocked && media_streams_blocking (media) &&
3258 priv->no_more_pads_pending == 0 &&
3259 (priv->blocking_msg_received == nbr_active_streams (media) ||
3260 priv->blocking_msg_received == priv->streams->len)) {
3261 GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "media is blocking");
3262 g_mutex_lock (&priv->lock);
3263 collect_media_stats (media);
3264 g_mutex_unlock (&priv->lock);
3266 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3267 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3269 priv->blocking_msg_received = 0;
3274 case GST_MESSAGE_STREAM_STATUS:
3276 case GST_MESSAGE_ASYNC_DONE:
3277 if (priv->expected_async_done)
3278 priv->expected_async_done = FALSE;
3279 if (priv->complete) {
3280 /* receive the final ASYNC_DONE, that is posted by the media pipeline
3281 * after all the transport parts have been successfully added to
3282 * the media streams. */
3283 GST_DEBUG_OBJECT (media, "got async-done");
3284 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3285 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3288 case GST_MESSAGE_EOS:
3289 GST_INFO ("%p: got EOS", media);
3291 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
3292 GST_DEBUG ("shutting down after EOS");
3293 finish_unprepare (media);
3297 GST_INFO ("%p: got message type %d (%s)", media, type,
3298 gst_message_type_get_name (type));
3305 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
3307 GstRTSPMediaPrivate *priv = media->priv;
3308 GstRTSPMediaClass *klass;
3311 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3313 g_rec_mutex_lock (&priv->state_lock);
3314 if (klass->handle_message)
3315 ret = klass->handle_message (media, message);
3318 g_rec_mutex_unlock (&priv->state_lock);
3324 watch_destroyed (GstRTSPMedia * media)
3326 GST_DEBUG_OBJECT (media, "source destroyed");
3327 g_object_unref (media);
3331 is_payloader (GstElement * element)
3333 GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
3336 klass = gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
3340 if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
3348 find_payload_element (GstElement * payloader, GstPad * pad)
3350 GstElement *pay = NULL;
3352 if (GST_IS_BIN (payloader)) {
3354 GValue item = { 0 };
3355 gchar *pad_name, *payloader_name;
3356 GstElement *element;
3358 if ((element = gst_bin_get_by_name (GST_BIN (payloader), "pay"))) {
3359 if (is_payloader (element))
3361 gst_object_unref (element);
3364 pad_name = gst_object_get_name (GST_OBJECT (pad));
3365 payloader_name = g_strdup_printf ("pay_%s", pad_name);
3367 if ((element = gst_bin_get_by_name (GST_BIN (payloader), payloader_name))) {
3368 g_free (payloader_name);
3369 if (is_payloader (element))
3371 gst_object_unref (element);
3373 g_free (payloader_name);
3376 iter = gst_bin_iterate_recurse (GST_BIN (payloader));
3377 while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
3378 element = (GstElement *) g_value_get_object (&item);
3380 if (is_payloader (element)) {
3381 pay = gst_object_ref (element);
3382 g_value_unset (&item);
3385 g_value_unset (&item);
3387 gst_iterator_free (iter);
3389 pay = g_object_ref (payloader);
3395 /* called from streaming threads */
3397 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3399 GstRTSPMediaPrivate *priv = media->priv;
3400 GstRTSPStream *stream;
3403 /* find the real payload element */
3404 pay = find_payload_element (element, pad);
3405 stream = gst_rtsp_media_create_stream (media, pay, pad);
3406 gst_object_unref (pay);
3408 GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3410 g_rec_mutex_lock (&priv->state_lock);
3411 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3414 g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
3416 /* join the element in the PAUSED state because this callback is
3417 * called from the streaming thread and it is PAUSED */
3418 if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3419 priv->rtpbin, GST_STATE_PAUSED)) {
3420 GST_WARNING ("failed to join bin element");
3424 gst_rtsp_stream_set_blocked (stream, TRUE);
3426 g_rec_mutex_unlock (&priv->state_lock);
3433 gst_rtsp_media_remove_stream (media, stream);
3434 g_rec_mutex_unlock (&priv->state_lock);
3435 GST_INFO ("ignore pad because we are not preparing");
3441 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3443 GstRTSPMediaPrivate *priv = media->priv;
3444 GstRTSPStream *stream;
3446 stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
3450 GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3452 g_rec_mutex_lock (&priv->state_lock);
3453 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3454 g_rec_mutex_unlock (&priv->state_lock);
3456 gst_rtsp_media_remove_stream (media, stream);
3460 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
3462 GstRTSPMediaPrivate *priv = media->priv;
3464 GST_INFO_OBJECT (element, "no more pads");
3465 g_mutex_lock (&priv->lock);
3466 priv->no_more_pads_pending--;
3467 g_mutex_unlock (&priv->lock);
3470 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
3472 struct _DynPaySignalHandlers
3474 gulong pad_added_handler;
3475 gulong pad_removed_handler;
3476 gulong no_more_pads_handler;
3480 start_preroll (GstRTSPMedia * media)
3482 GstRTSPMediaPrivate *priv = media->priv;
3483 GstStateChangeReturn ret;
3485 GST_INFO ("setting pipeline to PAUSED for media %p", media);
3487 /* start blocked since it is possible that there are no sink elements yet */
3488 media_streams_set_blocked (media, TRUE);
3489 ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3492 case GST_STATE_CHANGE_SUCCESS:
3493 GST_INFO ("SUCCESS state change for media %p", media);
3495 case GST_STATE_CHANGE_ASYNC:
3496 GST_INFO ("ASYNC state change for media %p", media);
3498 case GST_STATE_CHANGE_NO_PREROLL:
3499 /* we need to go to PLAYING */
3500 GST_INFO ("NO_PREROLL state change: live media %p", media);
3501 /* FIXME we disable seeking for live streams for now. We should perform a
3502 * seeking query in preroll instead */
3503 priv->seekable = -1;
3504 priv->is_live = TRUE;
3506 ret = set_state (media, GST_STATE_PLAYING);
3507 if (ret == GST_STATE_CHANGE_FAILURE)
3510 case GST_STATE_CHANGE_FAILURE:
3518 GST_WARNING ("failed to preroll pipeline");
3524 wait_preroll (GstRTSPMedia * media)
3526 GstRTSPMediaStatus status;
3528 GST_DEBUG ("wait to preroll pipeline");
3530 /* wait until pipeline is prerolled */
3531 status = gst_rtsp_media_get_status (media);
3532 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
3533 goto preroll_failed;
3539 GST_WARNING ("failed to preroll pipeline");
3545 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3547 GstRTSPMediaPrivate *priv = media->priv;
3548 GstRTSPStream *stream = NULL;
3550 GstElement *res = NULL;
3552 g_mutex_lock (&priv->lock);
3553 for (i = 0; i < priv->streams->len; i++) {
3554 stream = g_ptr_array_index (priv->streams, i);
3556 if (sessid == gst_rtsp_stream_get_index (stream))
3561 g_mutex_unlock (&priv->lock);
3564 res = gst_rtsp_stream_request_aux_sender (stream, sessid);
3570 request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3572 GstRTSPMediaPrivate *priv = media->priv;
3573 GstRTSPStream *stream = NULL;
3575 GstElement *res = NULL;
3577 g_mutex_lock (&priv->lock);
3578 for (i = 0; i < priv->streams->len; i++) {
3579 stream = g_ptr_array_index (priv->streams, i);
3581 if (sessid == gst_rtsp_stream_get_index (stream))
3586 g_mutex_unlock (&priv->lock);
3589 res = gst_rtsp_stream_request_aux_receiver (stream, sessid);
3595 request_fec_decoder (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3597 GstRTSPMediaPrivate *priv = media->priv;
3598 GstRTSPStream *stream = NULL;
3600 GstElement *res = NULL;
3602 g_mutex_lock (&priv->lock);
3603 for (i = 0; i < priv->streams->len; i++) {
3604 stream = g_ptr_array_index (priv->streams, i);
3606 if (sessid == gst_rtsp_stream_get_index (stream))
3611 g_mutex_unlock (&priv->lock);
3614 res = gst_rtsp_stream_request_ulpfec_decoder (stream, rtpbin, sessid);
3621 new_storage_cb (GstElement * rtpbin, GObject * storage, guint sessid,
3622 GstRTSPMedia * media)
3624 g_object_set (storage, "size-time", (media->priv->latency + 50) * GST_MSECOND,
3629 start_prepare (GstRTSPMedia * media)
3631 GstRTSPMediaPrivate *priv = media->priv;
3635 g_rec_mutex_lock (&priv->state_lock);
3636 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3637 goto no_longer_preparing;
3639 g_signal_connect (priv->rtpbin, "new-storage", G_CALLBACK (new_storage_cb),
3641 g_signal_connect (priv->rtpbin, "request-fec-decoder",
3642 G_CALLBACK (request_fec_decoder), media);
3644 /* link streams we already have, other streams might appear when we have
3645 * dynamic elements */
3646 for (i = 0; i < priv->streams->len; i++) {
3647 GstRTSPStream *stream;
3649 stream = g_ptr_array_index (priv->streams, i);
3651 if (priv->rtx_time > 0) {
3652 /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
3653 g_signal_connect (priv->rtpbin, "request-aux-sender",
3654 (GCallback) request_aux_sender, media);
3657 if (priv->do_retransmission) {
3658 g_signal_connect (priv->rtpbin, "request-aux-receiver",
3659 (GCallback) request_aux_receiver, media);
3662 if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3663 priv->rtpbin, GST_STATE_NULL)) {
3664 goto join_bin_failed;
3669 g_object_set (priv->rtpbin, "do-retransmission", priv->do_retransmission,
3670 "do-lost", TRUE, NULL);
3672 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3673 GstElement *elem = walk->data;
3674 DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
3676 GST_INFO ("adding callbacks for dynamic element %p", elem);
3678 handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
3679 (GCallback) pad_added_cb, media);
3680 handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
3681 (GCallback) pad_removed_cb, media);
3682 handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
3683 (GCallback) no_more_pads_cb, media);
3685 g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
3688 if (priv->nb_dynamic_elements == 0 && gst_rtsp_media_is_receive_only (media)) {
3689 /* If we are receive_only (RECORD), do not try to preroll, to avoid
3690 * a second ASYNC state change failing */
3691 priv->is_live = TRUE;
3692 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3693 } else if (!start_preroll (media)) {
3694 goto preroll_failed;
3697 g_rec_mutex_unlock (&priv->state_lock);
3701 no_longer_preparing:
3703 GST_INFO ("media is no longer preparing");
3704 g_rec_mutex_unlock (&priv->state_lock);
3709 GST_WARNING ("failed to join bin element");
3710 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3711 g_rec_mutex_unlock (&priv->state_lock);
3716 GST_WARNING ("failed to preroll pipeline");
3717 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3718 g_rec_mutex_unlock (&priv->state_lock);
3724 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3726 GstRTSPMediaPrivate *priv;
3727 GstRTSPMediaClass *klass;
3729 GMainContext *context;
3734 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3736 if (!klass->create_rtpbin)
3737 goto no_create_rtpbin;
3739 priv->rtpbin = klass->create_rtpbin (media);
3740 if (priv->rtpbin != NULL) {
3741 gboolean success = TRUE;
3743 g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
3745 if (klass->setup_rtpbin)
3746 success = klass->setup_rtpbin (media, priv->rtpbin);
3748 if (success == FALSE) {
3749 gst_object_unref (priv->rtpbin);
3750 priv->rtpbin = NULL;
3753 if (priv->rtpbin == NULL)
3756 priv->thread = thread;
3757 context = (thread != NULL) ? (thread->context) : NULL;
3759 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
3761 /* add the pipeline bus to our custom mainloop */
3762 priv->source = gst_bus_create_watch (bus);
3763 gst_object_unref (bus);
3765 g_source_set_callback (priv->source, (GSourceFunc) bus_message,
3766 g_object_ref (media), (GDestroyNotify) watch_destroyed);
3768 priv->id = g_source_attach (priv->source, context);
3770 /* add stuff to the bin */
3771 gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
3773 /* do remainder in context */
3774 source = g_idle_source_new ();
3775 g_source_set_callback (source, (GSourceFunc) start_prepare,
3776 g_object_ref (media), (GDestroyNotify) g_object_unref);
3777 g_source_attach (source, context);
3778 g_source_unref (source);
3785 GST_ERROR ("no create_rtpbin function");
3786 g_critical ("no create_rtpbin vmethod function set");
3791 GST_WARNING ("no rtpbin element");
3792 g_warning ("failed to create element 'rtpbin', check your installation");
3798 * gst_rtsp_media_prepare:
3799 * @media: a #GstRTSPMedia
3800 * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
3801 * bus handler or %NULL
3803 * Prepare @media for streaming. This function will create the objects
3804 * to manage the streaming. A pipeline must have been set on @media with
3805 * gst_rtsp_media_take_pipeline().
3807 * It will preroll the pipeline and collect vital information about the streams
3808 * such as the duration.
3810 * Returns: %TRUE on success.
3813 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3815 GstRTSPMediaPrivate *priv;
3816 GstRTSPMediaClass *klass;
3818 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3822 g_rec_mutex_lock (&priv->state_lock);
3823 priv->prepare_count++;
3825 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
3826 priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
3829 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3832 if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
3833 goto not_unprepared;
3835 if (!priv->reusable && priv->reused)
3838 GST_INFO ("preparing media %p", media);
3840 /* reset some variables */
3841 priv->is_live = FALSE;
3842 priv->seekable = -1;
3843 priv->buffering = FALSE;
3844 priv->no_more_pads_pending = priv->nb_dynamic_elements;
3846 /* we're preparing now */
3847 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3849 klass = GST_RTSP_MEDIA_GET_CLASS (media);
3850 if (klass->prepare) {
3851 if (!klass->prepare (media, thread))
3852 goto prepare_failed;
3856 g_rec_mutex_unlock (&priv->state_lock);
3858 /* now wait for all pads to be prerolled, FIXME, we should somehow be
3859 * able to do this async so that we don't block the server thread. */
3860 if (!wait_preroll (media))
3861 goto preroll_failed;
3863 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
3865 GST_INFO ("object %p is prerolled", media);
3872 /* we are not going to use the giving thread, so stop it. */
3874 gst_rtsp_thread_stop (thread);
3879 GST_LOG ("media %p was prepared", media);
3880 /* we are not going to use the giving thread, so stop it. */
3882 gst_rtsp_thread_stop (thread);
3883 g_rec_mutex_unlock (&priv->state_lock);
3889 /* we are not going to use the giving thread, so stop it. */
3891 gst_rtsp_thread_stop (thread);
3892 GST_WARNING ("media %p was not unprepared", media);
3893 priv->prepare_count--;
3894 g_rec_mutex_unlock (&priv->state_lock);
3899 /* we are not going to use the giving thread, so stop it. */
3901 gst_rtsp_thread_stop (thread);
3902 priv->prepare_count--;
3903 g_rec_mutex_unlock (&priv->state_lock);
3904 GST_WARNING ("can not reuse media %p", media);
3909 /* we are not going to use the giving thread, so stop it. */
3911 gst_rtsp_thread_stop (thread);
3912 priv->prepare_count--;
3913 g_rec_mutex_unlock (&priv->state_lock);
3914 GST_ERROR ("failed to prepare media");
3919 GST_WARNING ("failed to preroll pipeline");
3920 gst_rtsp_media_unprepare (media);
3925 /* must be called with state-lock */
3927 finish_unprepare (GstRTSPMedia * media)
3929 GstRTSPMediaPrivate *priv = media->priv;
3933 if (priv->finishing_unprepare)
3935 priv->finishing_unprepare = TRUE;
3937 GST_DEBUG ("shutting down");
3939 /* release the lock on shutdown, otherwise pad_added_cb might try to
3940 * acquire the lock and then we deadlock */
3941 g_rec_mutex_unlock (&priv->state_lock);
3942 set_state (media, GST_STATE_NULL);
3943 g_rec_mutex_lock (&priv->state_lock);
3945 media_streams_set_blocked (media, FALSE);
3947 for (i = 0; i < priv->streams->len; i++) {
3948 GstRTSPStream *stream;
3950 GST_INFO ("Removing elements of stream %d from pipeline", i);
3952 stream = g_ptr_array_index (priv->streams, i);
3954 gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3957 /* remove the pad signal handlers */
3958 for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3959 GstElement *elem = walk->data;
3960 DynPaySignalHandlers *handlers;
3963 g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3964 g_assert (handlers != NULL);
3966 g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3967 g_signal_handler_disconnect (G_OBJECT (elem),
3968 handlers->pad_removed_handler);
3969 g_signal_handler_disconnect (G_OBJECT (elem),
3970 handlers->no_more_pads_handler);
3972 g_slice_free (DynPaySignalHandlers, handlers);
3975 gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3976 priv->rtpbin = NULL;
3979 gst_object_unref (priv->nettime);
3980 priv->nettime = NULL;
3982 priv->reused = TRUE;
3983 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3985 /* when the media is not reusable, this will effectively unref the media and
3987 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3989 /* the source has the last ref to the media */
3991 GST_DEBUG ("destroy source");
3992 g_source_destroy (priv->source);
3993 g_source_unref (priv->source);
3996 GST_DEBUG ("stop thread");
3997 gst_rtsp_thread_stop (priv->thread);
4000 priv->finishing_unprepare = FALSE;
4003 /* called with state-lock */
4005 default_unprepare (GstRTSPMedia * media)
4007 GstRTSPMediaPrivate *priv = media->priv;
4009 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
4011 if (priv->eos_shutdown) {
4012 GST_DEBUG ("sending EOS for shutdown");
4013 /* ref so that we don't disappear */
4014 gst_element_send_event (priv->pipeline, gst_event_new_eos ());
4015 /* we need to go to playing again for the EOS to propagate, normally in this
4016 * state, nothing is receiving data from us anymore so this is ok. */
4017 set_state (media, GST_STATE_PLAYING);
4019 finish_unprepare (media);
4025 * gst_rtsp_media_unprepare:
4026 * @media: a #GstRTSPMedia
4028 * Unprepare @media. After this call, the media should be prepared again before
4029 * it can be used again. If the media is set to be non-reusable, a new instance
4032 * Returns: %TRUE on success.
4035 gst_rtsp_media_unprepare (GstRTSPMedia * media)
4037 GstRTSPMediaPrivate *priv;
4040 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4044 g_rec_mutex_lock (&priv->state_lock);
4045 if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
4046 goto was_unprepared;
4048 priv->prepare_count--;
4049 if (priv->prepare_count > 0)
4052 GST_INFO ("unprepare media %p", media);
4053 set_target_state (media, GST_STATE_NULL, FALSE);
4056 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
4057 GstRTSPMediaClass *klass;
4059 klass = GST_RTSP_MEDIA_GET_CLASS (media);
4060 if (klass->unprepare)
4061 success = klass->unprepare (media);
4063 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
4064 finish_unprepare (media);
4066 g_rec_mutex_unlock (&priv->state_lock);
4072 g_rec_mutex_unlock (&priv->state_lock);
4073 GST_INFO ("media %p was already unprepared", media);
4078 GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
4079 g_rec_mutex_unlock (&priv->state_lock);
4084 /* should be called with state-lock */
4086 get_clock_unlocked (GstRTSPMedia * media)
4088 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
4089 GST_DEBUG_OBJECT (media, "media was not prepared");
4092 return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
4096 * gst_rtsp_media_lock:
4097 * @media: a #GstRTSPMedia
4099 * Lock the entire media. This is needed by callers such as rtsp_client to
4100 * protect the media when it is shared by many clients.
4101 * The lock prevents that concurrent clients alters the shared media,
4102 * while one client already is working with it.
4103 * Typically the lock is taken in external RTSP API calls that uses shared media
4104 * such as DESCRIBE, SETUP, ANNOUNCE, TEARDOWN, PLAY, PAUSE.
4106 * As best practice take the lock as soon as the function get hold of a shared
4107 * media object. Release the lock right before the function returns.
4112 gst_rtsp_media_lock (GstRTSPMedia * media)
4114 GstRTSPMediaPrivate *priv;
4116 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4120 g_mutex_lock (&priv->global_lock);
4124 * gst_rtsp_media_unlock:
4125 * @media: a #GstRTSPMedia
4132 gst_rtsp_media_unlock (GstRTSPMedia * media)
4134 GstRTSPMediaPrivate *priv;
4136 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4140 g_mutex_unlock (&priv->global_lock);
4144 * gst_rtsp_media_get_clock:
4145 * @media: a #GstRTSPMedia
4147 * Get the clock that is used by the pipeline in @media.
4149 * @media must be prepared before this method returns a valid clock object.
4151 * Returns: (transfer full) (nullable): the #GstClock used by @media. unref after usage.
4154 gst_rtsp_media_get_clock (GstRTSPMedia * media)
4157 GstRTSPMediaPrivate *priv;
4159 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4163 g_rec_mutex_lock (&priv->state_lock);
4164 clock = get_clock_unlocked (media);
4165 g_rec_mutex_unlock (&priv->state_lock);
4171 * gst_rtsp_media_get_base_time:
4172 * @media: a #GstRTSPMedia
4174 * Get the base_time that is used by the pipeline in @media.
4176 * @media must be prepared before this method returns a valid base_time.
4178 * Returns: the base_time used by @media.
4181 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
4183 GstClockTime result;
4184 GstRTSPMediaPrivate *priv;
4186 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
4190 g_rec_mutex_lock (&priv->state_lock);
4191 if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4194 result = gst_element_get_base_time (media->priv->pipeline);
4195 g_rec_mutex_unlock (&priv->state_lock);
4202 g_rec_mutex_unlock (&priv->state_lock);
4203 GST_DEBUG_OBJECT (media, "media was not prepared");
4204 return GST_CLOCK_TIME_NONE;
4209 * gst_rtsp_media_get_time_provider:
4210 * @media: a #GstRTSPMedia
4211 * @address: (allow-none): an address or %NULL
4212 * @port: a port or 0
4214 * Get the #GstNetTimeProvider for the clock used by @media. The time provider
4215 * will listen on @address and @port for client time requests.
4217 * Returns: (transfer full): the #GstNetTimeProvider of @media.
4219 GstNetTimeProvider *
4220 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
4223 GstRTSPMediaPrivate *priv;
4224 GstNetTimeProvider *provider = NULL;
4226 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4230 g_rec_mutex_lock (&priv->state_lock);
4231 if (priv->time_provider) {
4232 if ((provider = priv->nettime) == NULL) {
4235 if (priv->time_provider && (clock = get_clock_unlocked (media))) {
4236 provider = gst_net_time_provider_new (clock, address, port);
4237 gst_object_unref (clock);
4239 priv->nettime = provider;
4243 g_rec_mutex_unlock (&priv->state_lock);
4246 gst_object_ref (provider);
4252 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
4254 return gst_rtsp_sdp_from_media (sdp, info, media);
4258 * gst_rtsp_media_setup_sdp:
4259 * @media: a #GstRTSPMedia
4260 * @sdp: (transfer none): a #GstSDPMessage
4261 * @info: (transfer none): a #GstSDPInfo
4263 * Add @media specific info to @sdp. @info is used to configure the connection
4264 * information in the SDP.
4266 * Returns: TRUE on success.
4269 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
4272 GstRTSPMediaPrivate *priv;
4273 GstRTSPMediaClass *klass;
4276 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4277 g_return_val_if_fail (sdp != NULL, FALSE);
4278 g_return_val_if_fail (info != NULL, FALSE);
4282 g_rec_mutex_lock (&priv->state_lock);
4284 klass = GST_RTSP_MEDIA_GET_CLASS (media);
4286 if (!klass->setup_sdp)
4289 res = klass->setup_sdp (media, sdp, info);
4291 g_rec_mutex_unlock (&priv->state_lock);
4298 g_rec_mutex_unlock (&priv->state_lock);
4299 GST_ERROR ("no setup_sdp function");
4300 g_critical ("no setup_sdp vmethod function set");
4306 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4308 GstRTSPMediaPrivate *priv = media->priv;
4311 medias_len = gst_sdp_message_medias_len (sdp);
4312 if (medias_len != priv->streams->len) {
4313 GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
4314 priv->streams->len, medias_len);
4318 for (i = 0; i < medias_len; i++) {
4320 const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
4321 GstRTSPStream *stream;
4322 gint j, formats_len;
4323 const gchar *control;
4324 GstRTSPProfile profile, profiles;
4326 stream = g_ptr_array_index (priv->streams, i);
4328 /* TODO: Should we do something with the other SDP information? */
4331 proto = gst_sdp_media_get_proto (sdp_media);
4332 if (proto == NULL) {
4333 GST_ERROR ("%p: SDP media %d has no proto", media, i);
4337 if (g_str_equal (proto, "RTP/AVP")) {
4338 profile = GST_RTSP_PROFILE_AVP;
4339 } else if (g_str_equal (proto, "RTP/SAVP")) {
4340 profile = GST_RTSP_PROFILE_SAVP;
4341 } else if (g_str_equal (proto, "RTP/AVPF")) {
4342 profile = GST_RTSP_PROFILE_AVPF;
4343 } else if (g_str_equal (proto, "RTP/SAVPF")) {
4344 profile = GST_RTSP_PROFILE_SAVPF;
4346 GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4350 profiles = gst_rtsp_stream_get_profiles (stream);
4351 if ((profiles & profile) == 0) {
4352 GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4356 formats_len = gst_sdp_media_formats_len (sdp_media);
4357 for (j = 0; j < formats_len; j++) {
4362 pt = atoi (gst_sdp_media_get_format (sdp_media, j));
4364 GST_DEBUG (" looking at %d pt: %d", j, pt);
4367 caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
4369 GST_WARNING (" skipping pt %d without caps", pt);
4373 /* do some tweaks */
4374 GST_DEBUG ("mapping sdp session level attributes to caps");
4375 gst_sdp_message_attributes_to_caps (sdp, caps);
4376 GST_DEBUG ("mapping sdp media level attributes to caps");
4377 gst_sdp_media_attributes_to_caps (sdp_media, caps);
4379 s = gst_caps_get_structure (caps, 0);
4380 gst_structure_set_name (s, "application/x-rtp");
4382 if (!g_strcmp0 (gst_structure_get_string (s, "encoding-name"), "ULPFEC"))
4383 gst_structure_set (s, "is-fec", G_TYPE_BOOLEAN, TRUE, NULL);
4385 gst_rtsp_stream_set_pt_map (stream, pt, caps);
4386 gst_caps_unref (caps);
4389 control = gst_sdp_media_get_attribute_val (sdp_media, "control");
4391 gst_rtsp_stream_set_control (stream, control);
4399 * gst_rtsp_media_handle_sdp:
4400 * @media: a #GstRTSPMedia
4401 * @sdp: (transfer none): a #GstSDPMessage
4403 * Configure an SDP on @media for receiving streams
4405 * Returns: TRUE on success.
4408 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4410 GstRTSPMediaPrivate *priv;
4411 GstRTSPMediaClass *klass;
4414 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4415 g_return_val_if_fail (sdp != NULL, FALSE);
4419 g_rec_mutex_lock (&priv->state_lock);
4421 klass = GST_RTSP_MEDIA_GET_CLASS (media);
4423 if (!klass->handle_sdp)
4426 res = klass->handle_sdp (media, sdp);
4428 g_rec_mutex_unlock (&priv->state_lock);
4435 g_rec_mutex_unlock (&priv->state_lock);
4436 GST_ERROR ("no handle_sdp function");
4437 g_critical ("no handle_sdp vmethod function set");
4443 do_set_seqnum (GstRTSPStream * stream)
4447 if (gst_rtsp_stream_is_sender (stream)) {
4448 seq_num = gst_rtsp_stream_get_current_seqnum (stream);
4449 gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
4453 /* call with state_lock */
4455 default_suspend (GstRTSPMedia * media)
4457 GstRTSPMediaPrivate *priv = media->priv;
4458 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
4460 switch (priv->suspend_mode) {
4461 case GST_RTSP_SUSPEND_MODE_NONE:
4462 GST_DEBUG ("media %p no suspend", media);
4464 case GST_RTSP_SUSPEND_MODE_PAUSE:
4465 GST_DEBUG ("media %p suspend to PAUSED", media);
4466 ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
4467 if (ret == GST_STATE_CHANGE_FAILURE)
4470 case GST_RTSP_SUSPEND_MODE_RESET:
4471 GST_DEBUG ("media %p suspend to NULL", media);
4472 ret = set_target_state (media, GST_STATE_NULL, TRUE);
4473 if (ret == GST_STATE_CHANGE_FAILURE)
4475 /* Because payloader needs to set the sequence number as
4476 * monotonic, we need to preserve the sequence number
4477 * after pause. (otherwise going from pause to play, which
4478 * is actually from NULL to PLAY will create a new sequence
4480 g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
4486 /* If we use any suspend mode that changes the state then we must update
4487 * expected_async_done, since we might not be doing an asyncronous state
4488 * change anymore. */
4489 if (ret != GST_STATE_CHANGE_FAILURE && ret != GST_STATE_CHANGE_ASYNC)
4490 priv->expected_async_done = FALSE;
4497 GST_WARNING ("failed changing pipeline's state for media %p", media);
4503 * gst_rtsp_media_suspend:
4504 * @media: a #GstRTSPMedia
4506 * Suspend @media. The state of the pipeline managed by @media is set to
4507 * GST_STATE_NULL but all streams are kept. @media can be prepared again
4508 * with gst_rtsp_media_unsuspend()
4510 * @media must be prepared with gst_rtsp_media_prepare();
4512 * Returns: %TRUE on success.
4515 gst_rtsp_media_suspend (GstRTSPMedia * media)
4517 GstRTSPMediaPrivate *priv = media->priv;
4518 GstRTSPMediaClass *klass;
4520 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4522 GST_FIXME ("suspend for dynamic pipelines needs fixing");
4524 /* this typically can happen for shared media. */
4525 if (priv->prepare_count > 1 &&
4526 priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED) {
4528 } else if (priv->prepare_count > 1) {
4529 goto prepared_by_other_client;
4532 g_rec_mutex_lock (&priv->state_lock);
4533 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4536 /* don't attempt to suspend when something is busy */
4537 if (priv->n_active > 0)
4540 klass = GST_RTSP_MEDIA_GET_CLASS (media);
4541 if (klass->suspend) {
4542 if (!klass->suspend (media))
4543 goto suspend_failed;
4546 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
4548 g_rec_mutex_unlock (&priv->state_lock);
4553 prepared_by_other_client:
4555 GST_WARNING ("media %p was prepared by other client", media);
4560 g_rec_mutex_unlock (&priv->state_lock);
4561 GST_WARNING ("media %p was not prepared", media);
4566 g_rec_mutex_unlock (&priv->state_lock);
4567 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4568 GST_WARNING ("failed to suspend media %p", media);
4573 /* call with state_lock */
4575 default_unsuspend (GstRTSPMedia * media)
4577 GstRTSPMediaPrivate *priv = media->priv;
4578 gboolean preroll_ok;
4580 switch (priv->suspend_mode) {
4581 case GST_RTSP_SUSPEND_MODE_NONE:
4582 if (gst_rtsp_media_is_receive_only (media))
4584 if (media_streams_blocking (media)) {
4585 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4586 /* at this point the media pipeline has been updated and contain all
4587 * specific transport parts: all active streams contain at least one sink
4588 * element and it's safe to unblock all blocked streams */
4589 media_streams_set_blocked (media, FALSE);
4591 /* streams are not blocked and media is suspended from PAUSED */
4592 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4594 g_rec_mutex_unlock (&priv->state_lock);
4595 if (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_ERROR) {
4596 g_rec_mutex_lock (&priv->state_lock);
4597 goto preroll_failed;
4599 g_rec_mutex_lock (&priv->state_lock);
4601 case GST_RTSP_SUSPEND_MODE_PAUSE:
4602 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4604 case GST_RTSP_SUSPEND_MODE_RESET:
4606 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4607 /* at this point the media pipeline has been updated and contain all
4608 * specific transport parts: all active streams contain at least one sink
4609 * element and it's safe to unblock all blocked streams */
4610 media_streams_set_blocked (media, FALSE);
4611 if (!start_preroll (media))
4614 g_rec_mutex_unlock (&priv->state_lock);
4615 preroll_ok = wait_preroll (media);
4616 g_rec_mutex_lock (&priv->state_lock);
4619 goto preroll_failed;
4630 GST_WARNING ("failed to preroll pipeline");
4635 GST_WARNING ("failed to preroll pipeline");
4641 * gst_rtsp_media_unsuspend:
4642 * @media: a #GstRTSPMedia
4644 * Unsuspend @media if it was in a suspended state. This method does nothing
4645 * when the media was not in the suspended state.
4647 * Returns: %TRUE on success.
4650 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
4652 GstRTSPMediaPrivate *priv = media->priv;
4653 GstRTSPMediaClass *klass;
4655 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4657 g_rec_mutex_lock (&priv->state_lock);
4658 if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4661 klass = GST_RTSP_MEDIA_GET_CLASS (media);
4662 if (klass->unsuspend) {
4663 if (!klass->unsuspend (media))
4664 goto unsuspend_failed;
4668 g_rec_mutex_unlock (&priv->state_lock);
4675 g_rec_mutex_unlock (&priv->state_lock);
4676 GST_WARNING ("failed to unsuspend media %p", media);
4677 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4682 /* must be called with state-lock */
4684 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
4686 GstRTSPMediaPrivate *priv = media->priv;
4687 GstStateChangeReturn set_state_ret;
4688 priv->expected_async_done = FALSE;
4690 if (state == GST_STATE_NULL) {
4691 gst_rtsp_media_unprepare (media);
4693 GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
4694 set_target_state (media, state, FALSE);
4696 if (state == GST_STATE_PLAYING) {
4697 /* make sure pads are not blocking anymore when going to PLAYING */
4698 media_streams_set_blocked (media, FALSE);
4701 /* when we are buffering, don't update the state yet, this will be done
4702 * when buffering finishes */
4703 if (priv->buffering) {
4704 GST_INFO ("Buffering busy, delay state change");
4706 if (state == GST_STATE_PAUSED) {
4707 set_state_ret = set_state (media, state);
4708 if (set_state_ret == GST_STATE_CHANGE_ASYNC)
4709 priv->expected_async_done = TRUE;
4710 /* and suspend after pause */
4711 gst_rtsp_media_suspend (media);
4713 set_state (media, state);
4720 * gst_rtsp_media_set_pipeline_state:
4721 * @media: a #GstRTSPMedia
4722 * @state: the target state of the pipeline
4724 * Set the state of the pipeline managed by @media to @state
4727 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
4729 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4731 g_rec_mutex_lock (&media->priv->state_lock);
4732 media_set_pipeline_state_locked (media, state);
4733 g_rec_mutex_unlock (&media->priv->state_lock);
4737 * gst_rtsp_media_set_state:
4738 * @media: a #GstRTSPMedia
4739 * @state: the target state of the media
4740 * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
4741 * a #GPtrArray of #GstRTSPStreamTransport pointers
4743 * Set the state of @media to @state and for the transports in @transports.
4745 * @media must be prepared with gst_rtsp_media_prepare();
4747 * Returns: %TRUE on success.
4750 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
4751 GPtrArray * transports)
4753 GstRTSPMediaPrivate *priv;
4755 gboolean activate, deactivate, do_state;
4758 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4759 g_return_val_if_fail (transports != NULL, FALSE);
4763 g_rec_mutex_lock (&priv->state_lock);
4765 if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING
4766 && gst_rtsp_media_is_shared (media)) {
4767 g_rec_mutex_unlock (&priv->state_lock);
4768 gst_rtsp_media_get_status (media);
4769 g_rec_mutex_lock (&priv->state_lock);
4771 if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
4773 if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
4774 priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4777 /* NULL and READY are the same */
4778 if (state == GST_STATE_READY)
4779 state = GST_STATE_NULL;
4781 activate = deactivate = FALSE;
4783 GST_INFO ("going to state %s media %p, target state %s",
4784 gst_element_state_get_name (state), media,
4785 gst_element_state_get_name (priv->target_state));
4788 case GST_STATE_NULL:
4789 /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
4790 if (priv->target_state >= GST_STATE_PAUSED)
4793 case GST_STATE_PAUSED:
4794 /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
4795 if (priv->target_state == GST_STATE_PLAYING)
4798 case GST_STATE_PLAYING:
4799 /* we're going to PLAYING, activate */
4805 old_active = priv->n_active;
4807 GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
4808 activate, deactivate);
4809 for (i = 0; i < transports->len; i++) {
4810 GstRTSPStreamTransport *trans;
4812 /* we need a non-NULL entry in the array */
4813 trans = g_ptr_array_index (transports, i);
4818 if (gst_rtsp_stream_transport_set_active (trans, TRUE))
4820 } else if (deactivate) {
4821 if (gst_rtsp_stream_transport_set_active (trans, FALSE))
4827 media_streams_set_blocked (media, FALSE);
4829 /* we just activated the first media, do the playing state change */
4830 if (old_active == 0 && activate)
4832 /* if we have no more active media and prepare count is not indicate
4833 * that there are new session/sessions ongoing,
4834 * do the downward state changes */
4835 else if (priv->n_active == 0 && priv->prepare_count <= 1)
4840 GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
4843 if (priv->target_state != state) {
4845 media_set_pipeline_state_locked (media, state);
4846 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
4851 /* remember where we are */
4852 if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
4853 old_active != priv->n_active)) {
4854 g_mutex_lock (&priv->lock);
4855 collect_media_stats (media);
4856 g_mutex_unlock (&priv->lock);
4858 g_rec_mutex_unlock (&priv->state_lock);
4865 GST_WARNING ("media %p was not prepared", media);
4866 g_rec_mutex_unlock (&priv->state_lock);
4871 GST_WARNING ("media %p in error status while changing to state %d",
4873 if (state == GST_STATE_NULL) {
4874 for (i = 0; i < transports->len; i++) {
4875 GstRTSPStreamTransport *trans;
4877 /* we need a non-NULL entry in the array */
4878 trans = g_ptr_array_index (transports, i);
4882 gst_rtsp_stream_transport_set_active (trans, FALSE);
4886 g_rec_mutex_unlock (&priv->state_lock);
4892 * gst_rtsp_media_set_transport_mode:
4893 * @media: a #GstRTSPMedia
4894 * @mode: the new value
4896 * Sets if the media pipeline can work in PLAY or RECORD mode
4899 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
4900 GstRTSPTransportMode mode)
4902 GstRTSPMediaPrivate *priv;
4904 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4908 g_mutex_lock (&priv->lock);
4909 priv->transport_mode = mode;
4910 g_mutex_unlock (&priv->lock);
4914 * gst_rtsp_media_get_transport_mode:
4915 * @media: a #GstRTSPMedia
4917 * Check if the pipeline for @media can be used for PLAY or RECORD methods.
4919 * Returns: The transport mode.
4921 GstRTSPTransportMode
4922 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
4924 GstRTSPMediaPrivate *priv;
4925 GstRTSPTransportMode res;
4927 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4931 g_mutex_lock (&priv->lock);
4932 res = priv->transport_mode;
4933 g_mutex_unlock (&priv->lock);
4939 * gst_rtsp_media_seekable:
4940 * @media: a #GstRTSPMedia
4942 * Check if the pipeline for @media seek and up to what point in time,
4945 * Returns: -1 if the stream is not seekable, 0 if seekable only to the beginning
4946 * and > 0 to indicate the longest duration between any two random access points.
4947 * %G_MAXINT64 means any value is possible.
4952 gst_rtsp_media_seekable (GstRTSPMedia * media)
4954 GstRTSPMediaPrivate *priv;
4955 GstClockTimeDiff res;
4957 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4961 /* Currently we are not able to seek on live streams,
4962 * and no stream is seekable only to the beginning */
4963 g_mutex_lock (&priv->lock);
4964 res = priv->seekable;
4965 g_mutex_unlock (&priv->lock);
4971 * gst_rtsp_media_complete_pipeline:
4972 * @media: a #GstRTSPMedia
4973 * @transports: (element-type GstRTSPTransport): a list of #GstRTSPTransport
4975 * Add a receiver and sender parts to the pipeline based on the transport from
4978 * Returns: %TRUE if the media pipeline has been sucessfully updated.
4983 gst_rtsp_media_complete_pipeline (GstRTSPMedia * media, GPtrArray * transports)
4985 GstRTSPMediaPrivate *priv;
4988 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4989 g_return_val_if_fail (transports, FALSE);
4991 GST_DEBUG_OBJECT (media, "complete pipeline");
4995 g_mutex_lock (&priv->lock);
4996 for (i = 0; i < priv->streams->len; i++) {
4997 GstRTSPStreamTransport *transport;
4998 GstRTSPStream *stream;
4999 const GstRTSPTransport *rtsp_transport;
5001 transport = g_ptr_array_index (transports, i);
5005 stream = gst_rtsp_stream_transport_get_stream (transport);
5009 rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
5011 if (!gst_rtsp_stream_complete_stream (stream, rtsp_transport)) {
5012 g_mutex_unlock (&priv->lock);
5017 priv->complete = TRUE;
5018 g_mutex_unlock (&priv->lock);
5024 * gst_rtsp_media_is_receive_only:
5026 * Returns: %TRUE if @media is receive-only, %FALSE otherwise.
5030 gst_rtsp_media_is_receive_only (GstRTSPMedia * media)
5032 GstRTSPMediaPrivate *priv = media->priv;
5033 gboolean receive_only;
5035 g_mutex_lock (&priv->lock);
5036 receive_only = is_receive_only (media);
5037 g_mutex_unlock (&priv->lock);
5039 return receive_only;
5043 * gst_rtsp_media_has_completed_sender:
5045 * See gst_rtsp_stream_is_complete(), gst_rtsp_stream_is_sender().
5047 * Returns: whether @media has at least one complete sender stream.
5051 gst_rtsp_media_has_completed_sender (GstRTSPMedia * media)
5053 GstRTSPMediaPrivate *priv = media->priv;
5054 gboolean sender = FALSE;
5057 g_mutex_lock (&priv->lock);
5058 for (i = 0; i < priv->streams->len; i++) {
5059 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
5060 if (gst_rtsp_stream_is_complete (stream))
5061 if (gst_rtsp_stream_is_sender (stream) ||
5062 !gst_rtsp_stream_is_receiver (stream)) {
5067 g_mutex_unlock (&priv->lock);
5073 * gst_rtsp_media_set_rate_control:
5075 * Define whether @media will follow the Rate-Control=no behaviour as specified
5076 * in the ONVIF replay spec.
5081 gst_rtsp_media_set_rate_control (GstRTSPMedia * media, gboolean enabled)
5083 GstRTSPMediaPrivate *priv;
5086 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
5088 GST_LOG_OBJECT (media, "%s rate control", enabled ? "Enabling" : "Disabling");
5092 g_mutex_lock (&priv->lock);
5093 priv->do_rate_control = enabled;
5094 for (i = 0; i < priv->streams->len; i++) {
5095 GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
5097 gst_rtsp_stream_set_rate_control (stream, enabled);
5100 g_mutex_unlock (&priv->lock);
5104 * gst_rtsp_media_get_rate_control:
5106 * Returns: whether @media will follow the Rate-Control=no behaviour as specified
5107 * in the ONVIF replay spec.
5112 gst_rtsp_media_get_rate_control (GstRTSPMedia * media)
5114 GstRTSPMediaPrivate *priv;
5117 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
5121 g_mutex_lock (&priv->lock);
5122 res = priv->do_rate_control;
5123 g_mutex_unlock (&priv->lock);