0c17fe1b089d3bc11bc4932a1d967afd19bba22b
[platform/upstream/gst-rtsp-server.git] / gst / rtsp-server / rtsp-media.c
1 /* GStreamer
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>
5  *
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.
10  *
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.
15  *
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.
20  */
21 /**
22  * SECTION:rtsp-media
23  * @short_description: The media pipeline
24  * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession,
25  *     #GstRTSPSessionMedia
26  *
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.
30  *
31  * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the
32  * client does a DESCRIBE or SETUP of a resource.
33  *
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.
38  *
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.
43  *
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
46  * the prepare phase.
47  *
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.
51  *
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().
54  *
55  * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When
56  * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to
57  * cleanly shut down.
58  *
59  * With gst_rtsp_media_set_shared(), the media can be shared between multiple
60  * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline
61  * can be prepared again after an unprepare.
62  *
63  * Last reviewed on 2013-07-11 (1.0.0)
64  */
65 #ifdef HAVE_CONFIG_H
66 #include "config.h"
67 #endif
68
69 #include <stdio.h>
70 #include <string.h>
71 #include <stdlib.h>
72
73 #include <gst/app/gstappsrc.h>
74 #include <gst/app/gstappsink.h>
75
76 #include <gst/sdp/gstmikey.h>
77 #include <gst/rtp/gstrtppayloads.h>
78
79 #define AES_128_KEY_LEN 16
80 #define AES_256_KEY_LEN 32
81
82 #define HMAC_32_KEY_LEN 4
83 #define HMAC_80_KEY_LEN 10
84
85 #include "rtsp-media.h"
86
87 struct _GstRTSPMediaPrivate
88 {
89   GMutex lock;
90   GCond cond;
91
92   /* protected by lock */
93   GstRTSPPermissions *permissions;
94   gboolean shared;
95   gboolean suspend_mode;
96   gboolean reusable;
97   GstRTSPProfile profiles;
98   GstRTSPLowerTrans protocols;
99   gboolean reused;
100   gboolean eos_shutdown;
101   guint buffer_size;
102   GstRTSPAddressPool *pool;
103   gchar *multicast_iface;
104   guint max_mcast_ttl;
105   gboolean bind_mcast_address;
106   gboolean blocked;
107   GstRTSPTransportMode transport_mode;
108   gboolean stop_on_disconnect;
109
110   GstElement *element;
111   GRecMutex state_lock;         /* locking order: state lock, lock */
112   GPtrArray *streams;           /* protected by lock */
113   GList *dynamic;               /* protected by lock */
114   GstRTSPMediaStatus status;    /* protected by lock */
115   gint prepare_count;
116   gint n_active;
117   gboolean complete;
118   gboolean finishing_unprepare;
119
120   /* the pipeline for the media */
121   GstElement *pipeline;
122   GSource *source;
123   guint id;
124   GstRTSPThread *thread;
125   GList *pending_pipeline_elements;
126
127   gboolean time_provider;
128   GstNetTimeProvider *nettime;
129
130   gboolean is_live;
131   GstClockTimeDiff seekable;
132   gboolean buffering;
133   GstState target_state;
134
135   /* RTP session manager */
136   GstElement *rtpbin;
137
138   /* the range of media */
139   GstRTSPTimeRange range;       /* protected by lock */
140   GstClockTime range_start;
141   GstClockTime range_stop;
142
143   GList *payloads;              /* protected by lock */
144   GstClockTime rtx_time;        /* protected by lock */
145   gboolean do_retransmission;   /* protected by lock */
146   guint latency;                /* protected by lock */
147   GstClock *clock;              /* protected by lock */
148   GstRTSPPublishClockMode publish_clock_mode;
149
150   /* Dynamic element handling */
151   guint nb_dynamic_elements;
152   guint no_more_pads_pending;
153 };
154
155 #define DEFAULT_SHARED          FALSE
156 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
157 #define DEFAULT_REUSABLE        FALSE
158 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
159 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
160                                         GST_RTSP_LOWER_TRANS_TCP
161 #define DEFAULT_EOS_SHUTDOWN    FALSE
162 #define DEFAULT_BUFFER_SIZE     0x80000
163 #define DEFAULT_TIME_PROVIDER   FALSE
164 #define DEFAULT_LATENCY         200
165 #define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
166 #define DEFAULT_STOP_ON_DISCONNECT TRUE
167 #define DEFAULT_MAX_MCAST_TTL   255
168 #define DEFAULT_BIND_MCAST_ADDRESS FALSE
169
170 #define DEFAULT_DO_RETRANSMISSION FALSE
171
172 /* define to dump received RTCP packets */
173 #undef DUMP_STATS
174
175 enum
176 {
177   PROP_0,
178   PROP_SHARED,
179   PROP_SUSPEND_MODE,
180   PROP_REUSABLE,
181   PROP_PROFILES,
182   PROP_PROTOCOLS,
183   PROP_EOS_SHUTDOWN,
184   PROP_BUFFER_SIZE,
185   PROP_ELEMENT,
186   PROP_TIME_PROVIDER,
187   PROP_LATENCY,
188   PROP_TRANSPORT_MODE,
189   PROP_STOP_ON_DISCONNECT,
190   PROP_CLOCK,
191   PROP_MAX_MCAST_TTL,
192   PROP_BIND_MCAST_ADDRESS,
193   PROP_LAST
194 };
195
196 enum
197 {
198   SIGNAL_NEW_STREAM,
199   SIGNAL_REMOVED_STREAM,
200   SIGNAL_PREPARED,
201   SIGNAL_UNPREPARED,
202   SIGNAL_TARGET_STATE,
203   SIGNAL_NEW_STATE,
204   SIGNAL_PREPARING,
205   SIGNAL_UNPREPARING,
206   SIGNAL_LAST
207 };
208
209 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
210 #define GST_CAT_DEFAULT rtsp_media_debug
211
212 static void gst_rtsp_media_get_property (GObject * object, guint propid,
213     GValue * value, GParamSpec * pspec);
214 static void gst_rtsp_media_set_property (GObject * object, guint propid,
215     const GValue * value, GParamSpec * pspec);
216 static void gst_rtsp_media_finalize (GObject * obj);
217
218 static gboolean default_handle_message (GstRTSPMedia * media,
219     GstMessage * message);
220 static void finish_unprepare (GstRTSPMedia * media);
221 static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread);
222 static gboolean default_unprepare (GstRTSPMedia * media);
223 static gboolean default_suspend (GstRTSPMedia * media);
224 static gboolean default_unsuspend (GstRTSPMedia * media);
225 static gboolean default_convert_range (GstRTSPMedia * media,
226     GstRTSPTimeRange * range, GstRTSPRangeUnit unit);
227 static gboolean default_query_position (GstRTSPMedia * media,
228     gint64 * position);
229 static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop);
230 static GstElement *default_create_rtpbin (GstRTSPMedia * media);
231 static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
232     GstSDPInfo * info);
233 static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
234
235 static gboolean wait_preroll (GstRTSPMedia * media);
236
237 static GstElement *find_payload_element (GstElement * payloader);
238
239 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
240
241 static gboolean check_complete (GstRTSPMedia * media);
242 gboolean gst_rtsp_media_has_completed_sender (GstRTSPMedia * media);
243
244 static gboolean gst_rtsp_media_is_receive_only (GstRTSPMedia * media);
245
246 #define C_ENUM(v) ((gint) v)
247
248 GType
249 gst_rtsp_suspend_mode_get_type (void)
250 {
251   static gsize id = 0;
252   static const GEnumValue values[] = {
253     {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"},
254     {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE",
255         "pause"},
256     {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET",
257         "reset"},
258     {0, NULL, NULL}
259   };
260
261   if (g_once_init_enter (&id)) {
262     GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values);
263     g_once_init_leave (&id, tmp);
264   }
265   return (GType) id;
266 }
267
268 #define C_FLAGS(v) ((guint) v)
269
270 GType
271 gst_rtsp_transport_mode_get_type (void)
272 {
273   static gsize id = 0;
274   static const GFlagsValue values[] = {
275     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
276         "play"},
277     {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
278         "record"},
279     {0, NULL, NULL}
280   };
281
282   if (g_once_init_enter (&id)) {
283     GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
284     g_once_init_leave (&id, tmp);
285   }
286   return (GType) id;
287 }
288
289 GType
290 gst_rtsp_publish_clock_mode_get_type (void)
291 {
292   static gsize id = 0;
293   static const GEnumValue values[] = {
294     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
295         "GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
296     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
297           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
298         "clock"},
299     {C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
300           "GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
301         "clock-and-offset"},
302     {0, NULL, NULL}
303   };
304
305   if (g_once_init_enter (&id)) {
306     GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
307     g_once_init_leave (&id, tmp);
308   }
309   return (GType) id;
310 }
311
312 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
313
314 static void
315 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
316 {
317   GObjectClass *gobject_class;
318
319   gobject_class = G_OBJECT_CLASS (klass);
320
321   gobject_class->get_property = gst_rtsp_media_get_property;
322   gobject_class->set_property = gst_rtsp_media_set_property;
323   gobject_class->finalize = gst_rtsp_media_finalize;
324
325   g_object_class_install_property (gobject_class, PROP_SHARED,
326       g_param_spec_boolean ("shared", "Shared",
327           "If this media pipeline can be shared", DEFAULT_SHARED,
328           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
329
330   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
331       g_param_spec_enum ("suspend-mode", "Suspend Mode",
332           "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE,
333           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
334
335   g_object_class_install_property (gobject_class, PROP_REUSABLE,
336       g_param_spec_boolean ("reusable", "Reusable",
337           "If this media pipeline can be reused after an unprepare",
338           DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
339
340   g_object_class_install_property (gobject_class, PROP_PROFILES,
341       g_param_spec_flags ("profiles", "Profiles",
342           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
343           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
344
345   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
346       g_param_spec_flags ("protocols", "Protocols",
347           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
348           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
349
350   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
351       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
352           "Send an EOS event to the pipeline before unpreparing",
353           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
354
355   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
356       g_param_spec_uint ("buffer-size", "Buffer Size",
357           "The kernel UDP buffer size to use", 0, G_MAXUINT,
358           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
359
360   g_object_class_install_property (gobject_class, PROP_ELEMENT,
361       g_param_spec_object ("element", "The Element",
362           "The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
363           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
364
365   g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER,
366       g_param_spec_boolean ("time-provider", "Time Provider",
367           "Use a NetTimeProvider for clients",
368           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
369
370   g_object_class_install_property (gobject_class, PROP_LATENCY,
371       g_param_spec_uint ("latency", "Latency",
372           "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
373           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
374
375   g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
376       g_param_spec_flags ("transport-mode", "Transport Mode",
377           "If this media pipeline can be used for PLAY or RECORD",
378           GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
379           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
380
381   g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
382       g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
383           "If this media pipeline should be stopped "
384           "when a client disconnects without TEARDOWN",
385           DEFAULT_STOP_ON_DISCONNECT,
386           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
387
388   g_object_class_install_property (gobject_class, PROP_CLOCK,
389       g_param_spec_object ("clock", "Clock",
390           "Clock to be used by the media pipeline",
391           GST_TYPE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
392
393   g_object_class_install_property (gobject_class, PROP_MAX_MCAST_TTL,
394       g_param_spec_uint ("max-mcast-ttl", "Maximum multicast ttl",
395           "The maximum time-to-live value of outgoing multicast packets", 1,
396           255, DEFAULT_MAX_MCAST_TTL,
397           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
398
399   g_object_class_install_property (gobject_class, PROP_BIND_MCAST_ADDRESS,
400       g_param_spec_boolean ("bind-mcast-address", "Bind mcast address",
401           "Whether the multicast sockets should be bound to multicast addresses "
402           "or INADDR_ANY",
403           DEFAULT_BIND_MCAST_ADDRESS,
404           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
405
406   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
407       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
408       G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
409       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM);
410
411   gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] =
412       g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass),
413       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream),
414       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
415       GST_TYPE_RTSP_STREAM);
416
417   gst_rtsp_media_signals[SIGNAL_PREPARED] =
418       g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
419       G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
420       g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
421
422   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
423       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
424       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
425       g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
426
427   gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
428       g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
429       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
430       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
431
432   gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
433       g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
434       G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
435       g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
436
437   gst_rtsp_media_signals[SIGNAL_PREPARING] =
438       g_signal_new ("preparing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
439       G_STRUCT_OFFSET (GstRTSPMediaClass, preparing), NULL, NULL,
440       g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_RTSP_STREAM,
441       G_TYPE_UINT);
442
443   gst_rtsp_media_signals[SIGNAL_UNPREPARING] =
444       g_signal_new ("unpreparing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
445       G_STRUCT_OFFSET (GstRTSPMediaClass, unpreparing), NULL, NULL,
446       g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_RTSP_STREAM,
447       G_TYPE_UINT);
448
449   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
450
451   klass->handle_message = default_handle_message;
452   klass->prepare = default_prepare;
453   klass->unprepare = default_unprepare;
454   klass->suspend = default_suspend;
455   klass->unsuspend = default_unsuspend;
456   klass->convert_range = default_convert_range;
457   klass->query_position = default_query_position;
458   klass->query_stop = default_query_stop;
459   klass->create_rtpbin = default_create_rtpbin;
460   klass->setup_sdp = default_setup_sdp;
461   klass->handle_sdp = default_handle_sdp;
462 }
463
464 static void
465 gst_rtsp_media_init (GstRTSPMedia * media)
466 {
467   GstRTSPMediaPrivate *priv = gst_rtsp_media_get_instance_private (media);
468
469   media->priv = priv;
470
471   priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
472   g_mutex_init (&priv->lock);
473   g_cond_init (&priv->cond);
474   g_rec_mutex_init (&priv->state_lock);
475
476   priv->shared = DEFAULT_SHARED;
477   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
478   priv->reusable = DEFAULT_REUSABLE;
479   priv->profiles = DEFAULT_PROFILES;
480   priv->protocols = DEFAULT_PROTOCOLS;
481   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
482   priv->buffer_size = DEFAULT_BUFFER_SIZE;
483   priv->time_provider = DEFAULT_TIME_PROVIDER;
484   priv->transport_mode = DEFAULT_TRANSPORT_MODE;
485   priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
486   priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
487   priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
488   priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
489   priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
490 }
491
492 static void
493 gst_rtsp_media_finalize (GObject * obj)
494 {
495   GstRTSPMediaPrivate *priv;
496   GstRTSPMedia *media;
497
498   media = GST_RTSP_MEDIA (obj);
499   priv = media->priv;
500
501   GST_INFO ("finalize media %p", media);
502
503   if (priv->permissions)
504     gst_rtsp_permissions_unref (priv->permissions);
505
506   g_ptr_array_unref (priv->streams);
507
508   g_list_free_full (priv->dynamic, gst_object_unref);
509   g_list_free_full (priv->pending_pipeline_elements, gst_object_unref);
510
511   if (priv->pipeline)
512     gst_object_unref (priv->pipeline);
513   if (priv->nettime)
514     gst_object_unref (priv->nettime);
515   gst_object_unref (priv->element);
516   if (priv->pool)
517     g_object_unref (priv->pool);
518   if (priv->payloads)
519     g_list_free (priv->payloads);
520   if (priv->clock)
521     gst_object_unref (priv->clock);
522   g_free (priv->multicast_iface);
523   g_mutex_clear (&priv->lock);
524   g_cond_clear (&priv->cond);
525   g_rec_mutex_clear (&priv->state_lock);
526
527   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
528 }
529
530 static void
531 gst_rtsp_media_get_property (GObject * object, guint propid,
532     GValue * value, GParamSpec * pspec)
533 {
534   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
535
536   switch (propid) {
537     case PROP_ELEMENT:
538       g_value_set_object (value, media->priv->element);
539       break;
540     case PROP_SHARED:
541       g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
542       break;
543     case PROP_SUSPEND_MODE:
544       g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media));
545       break;
546     case PROP_REUSABLE:
547       g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
548       break;
549     case PROP_PROFILES:
550       g_value_set_flags (value, gst_rtsp_media_get_profiles (media));
551       break;
552     case PROP_PROTOCOLS:
553       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
554       break;
555     case PROP_EOS_SHUTDOWN:
556       g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
557       break;
558     case PROP_BUFFER_SIZE:
559       g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
560       break;
561     case PROP_TIME_PROVIDER:
562       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
563       break;
564     case PROP_LATENCY:
565       g_value_set_uint (value, gst_rtsp_media_get_latency (media));
566       break;
567     case PROP_TRANSPORT_MODE:
568       g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
569       break;
570     case PROP_STOP_ON_DISCONNECT:
571       g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
572       break;
573     case PROP_CLOCK:
574       g_value_take_object (value, gst_rtsp_media_get_clock (media));
575       break;
576     case PROP_MAX_MCAST_TTL:
577       g_value_set_uint (value, gst_rtsp_media_get_max_mcast_ttl (media));
578       break;
579     case PROP_BIND_MCAST_ADDRESS:
580       g_value_set_boolean (value, gst_rtsp_media_is_bind_mcast_address (media));
581       break;
582     default:
583       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
584   }
585 }
586
587 static void
588 gst_rtsp_media_set_property (GObject * object, guint propid,
589     const GValue * value, GParamSpec * pspec)
590 {
591   GstRTSPMedia *media = GST_RTSP_MEDIA (object);
592
593   switch (propid) {
594     case PROP_ELEMENT:
595       media->priv->element = g_value_get_object (value);
596       gst_object_ref_sink (media->priv->element);
597       break;
598     case PROP_SHARED:
599       gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
600       break;
601     case PROP_SUSPEND_MODE:
602       gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value));
603       break;
604     case PROP_REUSABLE:
605       gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
606       break;
607     case PROP_PROFILES:
608       gst_rtsp_media_set_profiles (media, g_value_get_flags (value));
609       break;
610     case PROP_PROTOCOLS:
611       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
612       break;
613     case PROP_EOS_SHUTDOWN:
614       gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
615       break;
616     case PROP_BUFFER_SIZE:
617       gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
618       break;
619     case PROP_TIME_PROVIDER:
620       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
621       break;
622     case PROP_LATENCY:
623       gst_rtsp_media_set_latency (media, g_value_get_uint (value));
624       break;
625     case PROP_TRANSPORT_MODE:
626       gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
627       break;
628     case PROP_STOP_ON_DISCONNECT:
629       gst_rtsp_media_set_stop_on_disconnect (media,
630           g_value_get_boolean (value));
631       break;
632     case PROP_CLOCK:
633       gst_rtsp_media_set_clock (media, g_value_get_object (value));
634       break;
635     case PROP_MAX_MCAST_TTL:
636       gst_rtsp_media_set_max_mcast_ttl (media, g_value_get_uint (value));
637       break;
638     case PROP_BIND_MCAST_ADDRESS:
639       gst_rtsp_media_set_bind_mcast_address (media,
640           g_value_get_boolean (value));
641       break;
642     default:
643       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
644   }
645 }
646
647 typedef struct
648 {
649   gint64 position;
650   gboolean complete_streams_only;
651   gboolean ret;
652 } DoQueryPositionData;
653
654 static void
655 do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
656 {
657   gint64 tmp;
658
659   if (!gst_rtsp_stream_is_sender (stream))
660     return;
661
662   if (data->complete_streams_only && !gst_rtsp_stream_is_complete (stream)) {
663     GST_DEBUG_OBJECT (stream, "stream not complete, do not query position");
664     return;
665   }
666
667   if (gst_rtsp_stream_query_position (stream, &tmp)) {
668     data->position = MIN (data->position, tmp);
669     data->ret = TRUE;
670   }
671
672   GST_INFO_OBJECT (stream, "media position: %" GST_TIME_FORMAT,
673       GST_TIME_ARGS (data->position));
674 }
675
676 static gboolean
677 default_query_position (GstRTSPMedia * media, gint64 * position)
678 {
679   GstRTSPMediaPrivate *priv;
680   DoQueryPositionData data;
681
682   priv = media->priv;
683
684   data.position = G_MAXINT64;
685   data.ret = FALSE;
686
687   /* if the media is complete, i.e. one or more streams have been configured
688    * with sinks, then we want to query the position on those streams only.
689    * a query on an incmplete stream may return a position that originates from
690    * an earlier preroll */
691   if (check_complete (media))
692     data.complete_streams_only = TRUE;
693   else
694     data.complete_streams_only = FALSE;
695
696   g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
697
698   if (!data.ret)
699     *position = GST_CLOCK_TIME_NONE;
700   else
701     *position = data.position;
702
703   return data.ret;
704 }
705
706 typedef struct
707 {
708   gint64 stop;
709   gboolean ret;
710 } DoQueryStopData;
711
712 static void
713 do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
714 {
715   gint64 tmp = 0;
716
717   if (gst_rtsp_stream_query_stop (stream, &tmp)) {
718     data->stop = MAX (data->stop, tmp);
719     data->ret = TRUE;
720   }
721 }
722
723 static gboolean
724 default_query_stop (GstRTSPMedia * media, gint64 * stop)
725 {
726   GstRTSPMediaPrivate *priv;
727   DoQueryStopData data;
728
729   priv = media->priv;
730
731   data.stop = -1;
732   data.ret = FALSE;
733
734   g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
735
736   *stop = data.stop;
737
738   return data.ret;
739 }
740
741 static GstElement *
742 default_create_rtpbin (GstRTSPMedia * media)
743 {
744   GstElement *rtpbin;
745
746   rtpbin = gst_element_factory_make ("rtpbin", NULL);
747
748   return rtpbin;
749 }
750
751 /* Must be called with priv->lock */
752 static gboolean
753 is_receive_only (GstRTSPMedia * media)
754 {
755   GstRTSPMediaPrivate *priv = media->priv;
756   gboolean receive_only = TRUE;
757   guint i;
758
759   for (i = 0; i < priv->streams->len; i++) {
760     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
761     if (gst_rtsp_stream_is_sender (stream) ||
762         !gst_rtsp_stream_is_receiver (stream)) {
763       receive_only = FALSE;
764       break;
765     }
766   }
767
768   return receive_only;
769 }
770
771 /* must be called with state lock */
772 static void
773 check_seekable (GstRTSPMedia * media)
774 {
775   GstQuery *query;
776   GstRTSPMediaPrivate *priv = media->priv;
777
778   g_mutex_lock (&priv->lock);
779   /* Update the seekable state of the pipeline in case it changed */
780   if (is_receive_only (media)) {
781     /* TODO: Seeking for "receive-only"? */
782     priv->seekable = -1;
783   } else {
784     guint i, n = priv->streams->len;
785
786     for (i = 0; i < n; i++) {
787       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
788
789       if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
790           GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
791         priv->seekable = -1;
792         g_mutex_unlock (&priv->lock);
793         return;
794       }
795     }
796   }
797
798   query = gst_query_new_seeking (GST_FORMAT_TIME);
799   if (gst_element_query (priv->pipeline, query)) {
800     GstFormat format;
801     gboolean seekable;
802     gint64 start, end;
803
804     gst_query_parse_seeking (query, &format, &seekable, &start, &end);
805     priv->seekable = seekable ? G_MAXINT64 : 0;
806   } else if (priv->streams->len) {
807     gboolean seekable = TRUE;
808     guint i, n = priv->streams->len;
809
810     GST_DEBUG_OBJECT (media, "Checking %d streams", n);
811     for (i = 0; i < n; i++) {
812       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
813       seekable &= gst_rtsp_stream_seekable (stream);
814     }
815     priv->seekable = seekable ? G_MAXINT64 : -1;
816   }
817
818   GST_DEBUG_OBJECT (media, "seekable:%" G_GINT64_FORMAT, priv->seekable);
819   g_mutex_unlock (&priv->lock);
820   gst_query_unref (query);
821 }
822
823 /* must be called with state lock */
824 static gboolean
825 check_complete (GstRTSPMedia * media)
826 {
827   GstRTSPMediaPrivate *priv = media->priv;
828
829   guint i, n = priv->streams->len;
830
831   for (i = 0; i < n; i++) {
832     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
833
834     if (gst_rtsp_stream_is_complete (stream))
835       return TRUE;
836   }
837
838   return FALSE;
839 }
840
841 /* must be called with state lock and private lock */
842 static void
843 collect_media_stats (GstRTSPMedia * media)
844 {
845   GstRTSPMediaPrivate *priv = media->priv;
846   gint64 position = 0, stop = -1;
847
848   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
849       priv->status != GST_RTSP_MEDIA_STATUS_PREPARING) {
850     return;
851   }
852
853   priv->range.unit = GST_RTSP_RANGE_NPT;
854
855   GST_INFO ("collect media stats");
856
857   if (priv->is_live) {
858     priv->range.min.type = GST_RTSP_TIME_NOW;
859     priv->range.min.seconds = -1;
860     priv->range_start = -1;
861     priv->range.max.type = GST_RTSP_TIME_END;
862     priv->range.max.seconds = -1;
863     priv->range_stop = -1;
864   } else {
865     GstRTSPMediaClass *klass;
866     gboolean ret;
867
868     klass = GST_RTSP_MEDIA_GET_CLASS (media);
869
870     /* get the position */
871     ret = FALSE;
872     if (klass->query_position)
873       ret = klass->query_position (media, &position);
874
875     if (!ret) {
876       GST_INFO ("position query failed");
877       position = 0;
878     }
879
880     /* get the current segment stop */
881     ret = FALSE;
882     if (klass->query_stop)
883       ret = klass->query_stop (media, &stop);
884
885     if (!ret) {
886       GST_INFO ("stop query failed");
887       stop = -1;
888     }
889
890     GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %"
891         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop));
892
893     if (position == -1) {
894       priv->range.min.type = GST_RTSP_TIME_NOW;
895       priv->range.min.seconds = -1;
896       priv->range_start = -1;
897     } else {
898       priv->range.min.type = GST_RTSP_TIME_SECONDS;
899       priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
900       priv->range_start = position;
901     }
902     if (stop == -1) {
903       priv->range.max.type = GST_RTSP_TIME_END;
904       priv->range.max.seconds = -1;
905       priv->range_stop = -1;
906     } else {
907       priv->range.max.type = GST_RTSP_TIME_SECONDS;
908       priv->range.max.seconds = ((gdouble) stop) / GST_SECOND;
909       priv->range_stop = stop;
910     }
911     g_mutex_unlock (&priv->lock);
912     check_seekable (media);
913     g_mutex_lock (&priv->lock);
914   }
915 }
916
917 /**
918  * gst_rtsp_media_new:
919  * @element: (transfer full): a #GstElement
920  *
921  * Create a new #GstRTSPMedia instance. @element is the bin element that
922  * provides the different streams. The #GstRTSPMedia object contains the
923  * element to produce RTP data for one or more related (audio/video/..)
924  * streams.
925  *
926  * Ownership is taken of @element.
927  *
928  * Returns: (transfer full): a new #GstRTSPMedia object.
929  */
930 GstRTSPMedia *
931 gst_rtsp_media_new (GstElement * element)
932 {
933   GstRTSPMedia *result;
934
935   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
936
937   result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL);
938
939   return result;
940 }
941
942 /**
943  * gst_rtsp_media_get_element:
944  * @media: a #GstRTSPMedia
945  *
946  * Get the element that was used when constructing @media.
947  *
948  * Returns: (transfer full): a #GstElement. Unref after usage.
949  */
950 GstElement *
951 gst_rtsp_media_get_element (GstRTSPMedia * media)
952 {
953   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
954
955   return gst_object_ref (media->priv->element);
956 }
957
958 /**
959  * gst_rtsp_media_take_pipeline:
960  * @media: a #GstRTSPMedia
961  * @pipeline: (transfer full): a #GstPipeline
962  *
963  * Set @pipeline as the #GstPipeline for @media. Ownership is
964  * taken of @pipeline.
965  */
966 void
967 gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
968 {
969   GstRTSPMediaPrivate *priv;
970   GstElement *old;
971   GstNetTimeProvider *nettime;
972   GList *l;
973
974   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
975   g_return_if_fail (GST_IS_PIPELINE (pipeline));
976
977   priv = media->priv;
978
979   g_mutex_lock (&priv->lock);
980   old = priv->pipeline;
981   priv->pipeline = GST_ELEMENT_CAST (pipeline);
982   nettime = priv->nettime;
983   priv->nettime = NULL;
984   g_mutex_unlock (&priv->lock);
985
986   if (old)
987     gst_object_unref (old);
988
989   if (nettime)
990     gst_object_unref (nettime);
991
992   gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
993
994   for (l = priv->pending_pipeline_elements; l; l = l->next) {
995     gst_bin_add (GST_BIN_CAST (pipeline), l->data);
996   }
997   g_list_free (priv->pending_pipeline_elements);
998   priv->pending_pipeline_elements = NULL;
999 }
1000
1001 /**
1002  * gst_rtsp_media_set_permissions:
1003  * @media: a #GstRTSPMedia
1004  * @permissions: (transfer none) (nullable): a #GstRTSPPermissions
1005  *
1006  * Set @permissions on @media.
1007  */
1008 void
1009 gst_rtsp_media_set_permissions (GstRTSPMedia * media,
1010     GstRTSPPermissions * permissions)
1011 {
1012   GstRTSPMediaPrivate *priv;
1013
1014   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1015
1016   priv = media->priv;
1017
1018   g_mutex_lock (&priv->lock);
1019   if (priv->permissions)
1020     gst_rtsp_permissions_unref (priv->permissions);
1021   if ((priv->permissions = permissions))
1022     gst_rtsp_permissions_ref (permissions);
1023   g_mutex_unlock (&priv->lock);
1024 }
1025
1026 /**
1027  * gst_rtsp_media_get_permissions:
1028  * @media: a #GstRTSPMedia
1029  *
1030  * Get the permissions object from @media.
1031  *
1032  * Returns: (transfer full) (nullable): a #GstRTSPPermissions object, unref after usage.
1033  */
1034 GstRTSPPermissions *
1035 gst_rtsp_media_get_permissions (GstRTSPMedia * media)
1036 {
1037   GstRTSPMediaPrivate *priv;
1038   GstRTSPPermissions *result;
1039
1040   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1041
1042   priv = media->priv;
1043
1044   g_mutex_lock (&priv->lock);
1045   if ((result = priv->permissions))
1046     gst_rtsp_permissions_ref (result);
1047   g_mutex_unlock (&priv->lock);
1048
1049   return result;
1050 }
1051
1052 /**
1053  * gst_rtsp_media_set_suspend_mode:
1054  * @media: a #GstRTSPMedia
1055  * @mode: the new #GstRTSPSuspendMode
1056  *
1057  * Control how @ media will be suspended after the SDP has been generated and
1058  * after a PAUSE request has been performed.
1059  *
1060  * Media must be unprepared when setting the suspend mode.
1061  */
1062 void
1063 gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode)
1064 {
1065   GstRTSPMediaPrivate *priv;
1066
1067   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1068
1069   priv = media->priv;
1070
1071   g_rec_mutex_lock (&priv->state_lock);
1072   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1073     goto was_prepared;
1074   priv->suspend_mode = mode;
1075   g_rec_mutex_unlock (&priv->state_lock);
1076
1077   return;
1078
1079   /* ERRORS */
1080 was_prepared:
1081   {
1082     GST_WARNING ("media %p was prepared", media);
1083     g_rec_mutex_unlock (&priv->state_lock);
1084   }
1085 }
1086
1087 /**
1088  * gst_rtsp_media_get_suspend_mode:
1089  * @media: a #GstRTSPMedia
1090  *
1091  * Get how @media will be suspended.
1092  *
1093  * Returns: #GstRTSPSuspendMode.
1094  */
1095 GstRTSPSuspendMode
1096 gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media)
1097 {
1098   GstRTSPMediaPrivate *priv;
1099   GstRTSPSuspendMode res;
1100
1101   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE);
1102
1103   priv = media->priv;
1104
1105   g_rec_mutex_lock (&priv->state_lock);
1106   res = priv->suspend_mode;
1107   g_rec_mutex_unlock (&priv->state_lock);
1108
1109   return res;
1110 }
1111
1112 /**
1113  * gst_rtsp_media_set_shared:
1114  * @media: a #GstRTSPMedia
1115  * @shared: the new value
1116  *
1117  * Set or unset if the pipeline for @media can be shared will multiple clients.
1118  * When @shared is %TRUE, client requests for this media will share the media
1119  * pipeline.
1120  */
1121 void
1122 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
1123 {
1124   GstRTSPMediaPrivate *priv;
1125
1126   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1127
1128   priv = media->priv;
1129
1130   g_mutex_lock (&priv->lock);
1131   priv->shared = shared;
1132   g_mutex_unlock (&priv->lock);
1133 }
1134
1135 /**
1136  * gst_rtsp_media_is_shared:
1137  * @media: a #GstRTSPMedia
1138  *
1139  * Check if the pipeline for @media can be shared between multiple clients.
1140  *
1141  * Returns: %TRUE if the media can be shared between clients.
1142  */
1143 gboolean
1144 gst_rtsp_media_is_shared (GstRTSPMedia * media)
1145 {
1146   GstRTSPMediaPrivate *priv;
1147   gboolean res;
1148
1149   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1150
1151   priv = media->priv;
1152
1153   g_mutex_lock (&priv->lock);
1154   res = priv->shared;
1155   g_mutex_unlock (&priv->lock);
1156
1157   return res;
1158 }
1159
1160 /**
1161  * gst_rtsp_media_set_reusable:
1162  * @media: a #GstRTSPMedia
1163  * @reusable: the new value
1164  *
1165  * Set or unset if the pipeline for @media can be reused after the pipeline has
1166  * been unprepared.
1167  */
1168 void
1169 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
1170 {
1171   GstRTSPMediaPrivate *priv;
1172
1173   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1174
1175   priv = media->priv;
1176
1177   g_mutex_lock (&priv->lock);
1178   priv->reusable = reusable;
1179   g_mutex_unlock (&priv->lock);
1180 }
1181
1182 /**
1183  * gst_rtsp_media_is_reusable:
1184  * @media: a #GstRTSPMedia
1185  *
1186  * Check if the pipeline for @media can be reused after an unprepare.
1187  *
1188  * Returns: %TRUE if the media can be reused
1189  */
1190 gboolean
1191 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
1192 {
1193   GstRTSPMediaPrivate *priv;
1194   gboolean res;
1195
1196   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1197
1198   priv = media->priv;
1199
1200   g_mutex_lock (&priv->lock);
1201   res = priv->reusable;
1202   g_mutex_unlock (&priv->lock);
1203
1204   return res;
1205 }
1206
1207 static void
1208 do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles)
1209 {
1210   gst_rtsp_stream_set_profiles (stream, *profiles);
1211 }
1212
1213 /**
1214  * gst_rtsp_media_set_profiles:
1215  * @media: a #GstRTSPMedia
1216  * @profiles: the new flags
1217  *
1218  * Configure the allowed lower transport for @media.
1219  */
1220 void
1221 gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles)
1222 {
1223   GstRTSPMediaPrivate *priv;
1224
1225   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1226
1227   priv = media->priv;
1228
1229   g_mutex_lock (&priv->lock);
1230   priv->profiles = profiles;
1231   g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles);
1232   g_mutex_unlock (&priv->lock);
1233 }
1234
1235 /**
1236  * gst_rtsp_media_get_profiles:
1237  * @media: a #GstRTSPMedia
1238  *
1239  * Get the allowed profiles of @media.
1240  *
1241  * Returns: a #GstRTSPProfile
1242  */
1243 GstRTSPProfile
1244 gst_rtsp_media_get_profiles (GstRTSPMedia * media)
1245 {
1246   GstRTSPMediaPrivate *priv;
1247   GstRTSPProfile res;
1248
1249   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN);
1250
1251   priv = media->priv;
1252
1253   g_mutex_lock (&priv->lock);
1254   res = priv->profiles;
1255   g_mutex_unlock (&priv->lock);
1256
1257   return res;
1258 }
1259
1260 static void
1261 do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols)
1262 {
1263   gst_rtsp_stream_set_protocols (stream, *protocols);
1264 }
1265
1266 /**
1267  * gst_rtsp_media_set_protocols:
1268  * @media: a #GstRTSPMedia
1269  * @protocols: the new flags
1270  *
1271  * Configure the allowed lower transport for @media.
1272  */
1273 void
1274 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
1275 {
1276   GstRTSPMediaPrivate *priv;
1277
1278   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1279
1280   priv = media->priv;
1281
1282   g_mutex_lock (&priv->lock);
1283   priv->protocols = protocols;
1284   g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols);
1285   g_mutex_unlock (&priv->lock);
1286 }
1287
1288 /**
1289  * gst_rtsp_media_get_protocols:
1290  * @media: a #GstRTSPMedia
1291  *
1292  * Get the allowed protocols of @media.
1293  *
1294  * Returns: a #GstRTSPLowerTrans
1295  */
1296 GstRTSPLowerTrans
1297 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
1298 {
1299   GstRTSPMediaPrivate *priv;
1300   GstRTSPLowerTrans res;
1301
1302   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
1303       GST_RTSP_LOWER_TRANS_UNKNOWN);
1304
1305   priv = media->priv;
1306
1307   g_mutex_lock (&priv->lock);
1308   res = priv->protocols;
1309   g_mutex_unlock (&priv->lock);
1310
1311   return res;
1312 }
1313
1314 /**
1315  * gst_rtsp_media_set_eos_shutdown:
1316  * @media: a #GstRTSPMedia
1317  * @eos_shutdown: the new value
1318  *
1319  * Set or unset if an EOS event will be sent to the pipeline for @media before
1320  * it is unprepared.
1321  */
1322 void
1323 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
1324 {
1325   GstRTSPMediaPrivate *priv;
1326
1327   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1328
1329   priv = media->priv;
1330
1331   g_mutex_lock (&priv->lock);
1332   priv->eos_shutdown = eos_shutdown;
1333   g_mutex_unlock (&priv->lock);
1334 }
1335
1336 /**
1337  * gst_rtsp_media_is_eos_shutdown:
1338  * @media: a #GstRTSPMedia
1339  *
1340  * Check if the pipeline for @media will send an EOS down the pipeline before
1341  * unpreparing.
1342  *
1343  * Returns: %TRUE if the media will send EOS before unpreparing.
1344  */
1345 gboolean
1346 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
1347 {
1348   GstRTSPMediaPrivate *priv;
1349   gboolean res;
1350
1351   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1352
1353   priv = media->priv;
1354
1355   g_mutex_lock (&priv->lock);
1356   res = priv->eos_shutdown;
1357   g_mutex_unlock (&priv->lock);
1358
1359   return res;
1360 }
1361
1362 /**
1363  * gst_rtsp_media_set_buffer_size:
1364  * @media: a #GstRTSPMedia
1365  * @size: the new value
1366  *
1367  * Set the kernel UDP buffer size.
1368  */
1369 void
1370 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
1371 {
1372   GstRTSPMediaPrivate *priv;
1373   guint i;
1374
1375   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1376
1377   GST_LOG_OBJECT (media, "set buffer size %u", size);
1378
1379   priv = media->priv;
1380
1381   g_mutex_lock (&priv->lock);
1382   priv->buffer_size = size;
1383
1384   for (i = 0; i < priv->streams->len; i++) {
1385     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1386     gst_rtsp_stream_set_buffer_size (stream, size);
1387   }
1388   g_mutex_unlock (&priv->lock);
1389 }
1390
1391 /**
1392  * gst_rtsp_media_get_buffer_size:
1393  * @media: a #GstRTSPMedia
1394  *
1395  * Get the kernel UDP buffer size.
1396  *
1397  * Returns: the kernel UDP buffer size.
1398  */
1399 guint
1400 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
1401 {
1402   GstRTSPMediaPrivate *priv;
1403   guint res;
1404
1405   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1406
1407   priv = media->priv;
1408
1409   g_mutex_lock (&priv->lock);
1410   res = priv->buffer_size;
1411   g_mutex_unlock (&priv->lock);
1412
1413   return res;
1414 }
1415
1416 /**
1417  * gst_rtsp_media_set_stop_on_disconnect:
1418  * @media: a #GstRTSPMedia
1419  * @stop_on_disconnect: the new value
1420  *
1421  * Set or unset if the pipeline for @media should be stopped when a
1422  * client disconnects without sending TEARDOWN.
1423  */
1424 void
1425 gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
1426     gboolean stop_on_disconnect)
1427 {
1428   GstRTSPMediaPrivate *priv;
1429
1430   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1431
1432   priv = media->priv;
1433
1434   g_mutex_lock (&priv->lock);
1435   priv->stop_on_disconnect = stop_on_disconnect;
1436   g_mutex_unlock (&priv->lock);
1437 }
1438
1439 /**
1440  * gst_rtsp_media_is_stop_on_disconnect:
1441  * @media: a #GstRTSPMedia
1442  *
1443  * Check if the pipeline for @media will be stopped when a client disconnects
1444  * without sending TEARDOWN.
1445  *
1446  * Returns: %TRUE if the media will be stopped when a client disconnects
1447  *     without sending TEARDOWN.
1448  */
1449 gboolean
1450 gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
1451 {
1452   GstRTSPMediaPrivate *priv;
1453   gboolean res;
1454
1455   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
1456
1457   priv = media->priv;
1458
1459   g_mutex_lock (&priv->lock);
1460   res = priv->stop_on_disconnect;
1461   g_mutex_unlock (&priv->lock);
1462
1463   return res;
1464 }
1465
1466 /**
1467  * gst_rtsp_media_set_retransmission_time:
1468  * @media: a #GstRTSPMedia
1469  * @time: the new value
1470  *
1471  * Set the amount of time to store retransmission packets.
1472  */
1473 void
1474 gst_rtsp_media_set_retransmission_time (GstRTSPMedia * media, GstClockTime time)
1475 {
1476   GstRTSPMediaPrivate *priv;
1477   guint i;
1478
1479   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1480
1481   GST_LOG_OBJECT (media, "set retransmission time %" G_GUINT64_FORMAT, time);
1482
1483   priv = media->priv;
1484
1485   g_mutex_lock (&priv->lock);
1486   priv->rtx_time = time;
1487   for (i = 0; i < priv->streams->len; i++) {
1488     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1489
1490     gst_rtsp_stream_set_retransmission_time (stream, time);
1491   }
1492   g_mutex_unlock (&priv->lock);
1493 }
1494
1495 /**
1496  * gst_rtsp_media_get_retransmission_time:
1497  * @media: a #GstRTSPMedia
1498  *
1499  * Get the amount of time to store retransmission data.
1500  *
1501  * Returns: the amount of time to store retransmission data.
1502  */
1503 GstClockTime
1504 gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
1505 {
1506   GstRTSPMediaPrivate *priv;
1507   GstClockTime res;
1508
1509   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1510
1511   priv = media->priv;
1512
1513   g_mutex_lock (&priv->lock);
1514   res = priv->rtx_time;
1515   g_mutex_unlock (&priv->lock);
1516
1517   return res;
1518 }
1519
1520 /**
1521  * gst_rtsp_media_set_do_retransmission:
1522  *
1523  * Set whether retransmission requests will be sent
1524  *
1525  * Since: 1.16
1526  */
1527 void
1528 gst_rtsp_media_set_do_retransmission (GstRTSPMedia * media,
1529     gboolean do_retransmission)
1530 {
1531   GstRTSPMediaPrivate *priv;
1532
1533   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1534
1535   priv = media->priv;
1536
1537   g_mutex_lock (&priv->lock);
1538   priv->do_retransmission = do_retransmission;
1539
1540   if (priv->rtpbin)
1541     g_object_set (priv->rtpbin, "do-retransmission", do_retransmission, NULL);
1542   g_mutex_unlock (&priv->lock);
1543 }
1544
1545 /**
1546  * gst_rtsp_media_get_do_retransmission:
1547  *
1548  * Returns: Whether retransmission requests will be sent
1549  *
1550  * Since: 1.16
1551  */
1552 gboolean
1553 gst_rtsp_media_get_do_retransmission (GstRTSPMedia * media)
1554 {
1555   GstRTSPMediaPrivate *priv;
1556   gboolean res;
1557
1558   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
1559
1560   priv = media->priv;
1561
1562   g_mutex_lock (&priv->lock);
1563   res = priv->do_retransmission;
1564   g_mutex_unlock (&priv->lock);
1565
1566   return res;
1567 }
1568
1569 /**
1570  * gst_rtsp_media_set_latency:
1571  * @media: a #GstRTSPMedia
1572  * @latency: latency in milliseconds
1573  *
1574  * Configure the latency used for receiving media.
1575  */
1576 void
1577 gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
1578 {
1579   GstRTSPMediaPrivate *priv;
1580   guint i;
1581
1582   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1583
1584   GST_LOG_OBJECT (media, "set latency %ums", latency);
1585
1586   priv = media->priv;
1587
1588   g_mutex_lock (&priv->lock);
1589   priv->latency = latency;
1590   if (priv->rtpbin) {
1591     g_object_set (priv->rtpbin, "latency", latency, NULL);
1592
1593     for (i = 0; i < media->priv->streams->len; i++) {
1594       GObject *storage = NULL;
1595
1596       g_signal_emit_by_name (G_OBJECT (media->priv->rtpbin), "get-storage",
1597           i, &storage);
1598       if (storage)
1599         g_object_set (storage, "size-time",
1600             (media->priv->latency + 50) * GST_MSECOND, NULL);
1601     }
1602   }
1603
1604   g_mutex_unlock (&priv->lock);
1605 }
1606
1607 /**
1608  * gst_rtsp_media_get_latency:
1609  * @media: a #GstRTSPMedia
1610  *
1611  * Get the latency that is used for receiving media.
1612  *
1613  * Returns: latency in milliseconds
1614  */
1615 guint
1616 gst_rtsp_media_get_latency (GstRTSPMedia * media)
1617 {
1618   GstRTSPMediaPrivate *priv;
1619   guint res;
1620
1621   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1622
1623   priv = media->priv;
1624
1625   g_mutex_lock (&priv->lock);
1626   res = priv->latency;
1627   g_mutex_unlock (&priv->lock);
1628
1629   return res;
1630 }
1631
1632 /**
1633  * gst_rtsp_media_use_time_provider:
1634  * @media: a #GstRTSPMedia
1635  * @time_provider: if a #GstNetTimeProvider should be used
1636  *
1637  * Set @media to provide a #GstNetTimeProvider.
1638  */
1639 void
1640 gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider)
1641 {
1642   GstRTSPMediaPrivate *priv;
1643
1644   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1645
1646   priv = media->priv;
1647
1648   g_mutex_lock (&priv->lock);
1649   priv->time_provider = time_provider;
1650   g_mutex_unlock (&priv->lock);
1651 }
1652
1653 /**
1654  * gst_rtsp_media_is_time_provider:
1655  * @media: a #GstRTSPMedia
1656  *
1657  * Check if @media can provide a #GstNetTimeProvider for its pipeline clock.
1658  *
1659  * Use gst_rtsp_media_get_time_provider() to get the network clock.
1660  *
1661  * Returns: %TRUE if @media can provide a #GstNetTimeProvider.
1662  */
1663 gboolean
1664 gst_rtsp_media_is_time_provider (GstRTSPMedia * media)
1665 {
1666   GstRTSPMediaPrivate *priv;
1667   gboolean res;
1668
1669   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1670
1671   priv = media->priv;
1672
1673   g_mutex_lock (&priv->lock);
1674   res = priv->time_provider;
1675   g_mutex_unlock (&priv->lock);
1676
1677   return res;
1678 }
1679
1680 /**
1681  * gst_rtsp_media_set_clock:
1682  * @media: a #GstRTSPMedia
1683  * @clock: (nullable): #GstClock to be used
1684  *
1685  * Configure the clock used for the media.
1686  */
1687 void
1688 gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
1689 {
1690   GstRTSPMediaPrivate *priv;
1691
1692   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1693   g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1694
1695   GST_LOG_OBJECT (media, "setting clock %" GST_PTR_FORMAT, clock);
1696
1697   priv = media->priv;
1698
1699   g_mutex_lock (&priv->lock);
1700   if (priv->clock)
1701     gst_object_unref (priv->clock);
1702   priv->clock = clock ? gst_object_ref (clock) : NULL;
1703   if (priv->pipeline) {
1704     if (clock)
1705       gst_pipeline_use_clock (GST_PIPELINE_CAST (priv->pipeline), clock);
1706     else
1707       gst_pipeline_auto_clock (GST_PIPELINE_CAST (priv->pipeline));
1708   }
1709
1710   g_mutex_unlock (&priv->lock);
1711 }
1712
1713 /**
1714  * gst_rtsp_media_set_publish_clock_mode:
1715  * @media: a #GstRTSPMedia
1716  * @mode: the clock publish mode
1717  *
1718  * Sets if and how the media clock should be published according to RFC7273.
1719  *
1720  * Since: 1.8
1721  */
1722 void
1723 gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
1724     GstRTSPPublishClockMode mode)
1725 {
1726   GstRTSPMediaPrivate *priv;
1727   guint i, n;
1728
1729   priv = media->priv;
1730   g_mutex_lock (&priv->lock);
1731   priv->publish_clock_mode = mode;
1732
1733   n = priv->streams->len;
1734   for (i = 0; i < n; i++) {
1735     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1736
1737     gst_rtsp_stream_set_publish_clock_mode (stream, mode);
1738   }
1739   g_mutex_unlock (&priv->lock);
1740 }
1741
1742 /**
1743  * gst_rtsp_media_get_publish_clock_mode:
1744  * @media: a #GstRTSPMedia
1745  *
1746  * Gets if and how the media clock should be published according to RFC7273.
1747  *
1748  * Returns: The GstRTSPPublishClockMode
1749  *
1750  * Since: 1.8
1751  */
1752 GstRTSPPublishClockMode
1753 gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
1754 {
1755   GstRTSPMediaPrivate *priv;
1756   GstRTSPPublishClockMode ret;
1757
1758   priv = media->priv;
1759   g_mutex_lock (&priv->lock);
1760   ret = priv->publish_clock_mode;
1761   g_mutex_unlock (&priv->lock);
1762
1763   return ret;
1764 }
1765
1766 /**
1767  * gst_rtsp_media_set_address_pool:
1768  * @media: a #GstRTSPMedia
1769  * @pool: (transfer none) (nullable): a #GstRTSPAddressPool
1770  *
1771  * configure @pool to be used as the address pool of @media.
1772  */
1773 void
1774 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
1775     GstRTSPAddressPool * pool)
1776 {
1777   GstRTSPMediaPrivate *priv;
1778   GstRTSPAddressPool *old;
1779
1780   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1781
1782   priv = media->priv;
1783
1784   GST_LOG_OBJECT (media, "set address pool %p", pool);
1785
1786   g_mutex_lock (&priv->lock);
1787   if ((old = priv->pool) != pool)
1788     priv->pool = pool ? g_object_ref (pool) : NULL;
1789   else
1790     old = NULL;
1791   g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
1792       pool);
1793   g_mutex_unlock (&priv->lock);
1794
1795   if (old)
1796     g_object_unref (old);
1797 }
1798
1799 /**
1800  * gst_rtsp_media_get_address_pool:
1801  * @media: a #GstRTSPMedia
1802  *
1803  * Get the #GstRTSPAddressPool used as the address pool of @media.
1804  *
1805  * Returns: (transfer full) (nullable): the #GstRTSPAddressPool of @media.
1806  * g_object_unref() after usage.
1807  */
1808 GstRTSPAddressPool *
1809 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
1810 {
1811   GstRTSPMediaPrivate *priv;
1812   GstRTSPAddressPool *result;
1813
1814   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1815
1816   priv = media->priv;
1817
1818   g_mutex_lock (&priv->lock);
1819   if ((result = priv->pool))
1820     g_object_ref (result);
1821   g_mutex_unlock (&priv->lock);
1822
1823   return result;
1824 }
1825
1826 /**
1827  * gst_rtsp_media_set_multicast_iface:
1828  * @media: a #GstRTSPMedia
1829  * @multicast_iface: (transfer none) (nullable): a multicast interface name
1830  *
1831  * configure @multicast_iface to be used for @media.
1832  */
1833 void
1834 gst_rtsp_media_set_multicast_iface (GstRTSPMedia * media,
1835     const gchar * multicast_iface)
1836 {
1837   GstRTSPMediaPrivate *priv;
1838   gchar *old;
1839
1840   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1841
1842   priv = media->priv;
1843
1844   GST_LOG_OBJECT (media, "set multicast interface %s", multicast_iface);
1845
1846   g_mutex_lock (&priv->lock);
1847   if ((old = priv->multicast_iface) != multicast_iface)
1848     priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
1849   else
1850     old = NULL;
1851   g_ptr_array_foreach (priv->streams,
1852       (GFunc) gst_rtsp_stream_set_multicast_iface, (gchar *) multicast_iface);
1853   g_mutex_unlock (&priv->lock);
1854
1855   if (old)
1856     g_free (old);
1857 }
1858
1859 /**
1860  * gst_rtsp_media_get_multicast_iface:
1861  * @media: a #GstRTSPMedia
1862  *
1863  * Get the multicast interface used for @media.
1864  *
1865  * Returns: (transfer full) (nullable): the multicast interface for @media.
1866  * g_free() after usage.
1867  */
1868 gchar *
1869 gst_rtsp_media_get_multicast_iface (GstRTSPMedia * media)
1870 {
1871   GstRTSPMediaPrivate *priv;
1872   gchar *result;
1873
1874   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
1875
1876   priv = media->priv;
1877
1878   g_mutex_lock (&priv->lock);
1879   if ((result = priv->multicast_iface))
1880     result = g_strdup (result);
1881   g_mutex_unlock (&priv->lock);
1882
1883   return result;
1884 }
1885
1886 /**
1887  * gst_rtsp_media_set_max_mcast_ttl:
1888  * @media: a #GstRTSPMedia
1889  * @ttl: the new multicast ttl value
1890  *
1891  * Set the maximum time-to-live value of outgoing multicast packets.
1892  *
1893  * Returns: %TRUE if the requested ttl has been set successfully.
1894  *
1895  * Since: 1.16
1896  */
1897 gboolean
1898 gst_rtsp_media_set_max_mcast_ttl (GstRTSPMedia * media, guint ttl)
1899 {
1900   GstRTSPMediaPrivate *priv;
1901   guint i;
1902
1903   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1904
1905   GST_LOG_OBJECT (media, "set max mcast ttl %u", ttl);
1906
1907   priv = media->priv;
1908
1909   g_mutex_lock (&priv->lock);
1910
1911   if (ttl == 0 || ttl > DEFAULT_MAX_MCAST_TTL) {
1912     GST_WARNING_OBJECT (media, "The reqested mcast TTL value is not valid.");
1913     g_mutex_unlock (&priv->lock);
1914     return FALSE;
1915   }
1916   priv->max_mcast_ttl = ttl;
1917
1918   for (i = 0; i < priv->streams->len; i++) {
1919     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1920     gst_rtsp_stream_set_max_mcast_ttl (stream, ttl);
1921   }
1922   g_mutex_unlock (&priv->lock);
1923
1924   return TRUE;
1925 }
1926
1927 /**
1928  * gst_rtsp_media_get_max_mcast_ttl:
1929  * @media: a #GstRTSPMedia
1930  *
1931  * Get the the maximum time-to-live value of outgoing multicast packets.
1932  *
1933  * Returns: the maximum time-to-live value of outgoing multicast packets.
1934  *
1935  * Since: 1.16
1936  */
1937 guint
1938 gst_rtsp_media_get_max_mcast_ttl (GstRTSPMedia * media)
1939 {
1940   GstRTSPMediaPrivate *priv;
1941   guint res;
1942
1943   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1944
1945   priv = media->priv;
1946
1947   g_mutex_lock (&priv->lock);
1948   res = priv->max_mcast_ttl;
1949   g_mutex_unlock (&priv->lock);
1950
1951   return res;
1952 }
1953
1954 /**
1955  * gst_rtsp_media_set_bind_mcast_address:
1956  * @media: a #GstRTSPMedia
1957  * @bind_mcast_addr: the new value
1958  *
1959  * Decide whether the multicast socket should be bound to a multicast address or
1960  * INADDR_ANY.
1961  *
1962  * Since: 1.16
1963  */
1964 void
1965 gst_rtsp_media_set_bind_mcast_address (GstRTSPMedia * media,
1966     gboolean bind_mcast_addr)
1967 {
1968   GstRTSPMediaPrivate *priv;
1969   guint i;
1970
1971   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
1972
1973   priv = media->priv;
1974
1975   g_mutex_lock (&priv->lock);
1976   priv->bind_mcast_address = bind_mcast_addr;
1977   for (i = 0; i < priv->streams->len; i++) {
1978     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
1979     gst_rtsp_stream_set_bind_mcast_address (stream, bind_mcast_addr);
1980   }
1981   g_mutex_unlock (&priv->lock);
1982 }
1983
1984 /**
1985  * gst_rtsp_media_is_bind_mcast_address:
1986  * @media: a #GstRTSPMedia
1987  *
1988  * Check if multicast sockets are configured to be bound to multicast addresses.
1989  *
1990  * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
1991  *
1992  * Since: 1.16
1993  */
1994 gboolean
1995 gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia * media)
1996 {
1997   GstRTSPMediaPrivate *priv;
1998   gboolean result;
1999
2000   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2001
2002   priv = media->priv;
2003
2004   g_mutex_lock (&priv->lock);
2005   result = priv->bind_mcast_address;
2006   g_mutex_unlock (&priv->lock);
2007
2008   return result;
2009 }
2010
2011 static GList *
2012 _find_payload_types (GstRTSPMedia * media)
2013 {
2014   gint i, n;
2015   GQueue queue = G_QUEUE_INIT;
2016
2017   n = media->priv->streams->len;
2018   for (i = 0; i < n; i++) {
2019     GstRTSPStream *stream = g_ptr_array_index (media->priv->streams, i);
2020     guint pt = gst_rtsp_stream_get_pt (stream);
2021
2022     g_queue_push_tail (&queue, GUINT_TO_POINTER (pt));
2023   }
2024
2025   return queue.head;
2026 }
2027
2028 static guint
2029 _next_available_pt (GList * payloads)
2030 {
2031   guint i;
2032
2033   for (i = 96; i <= 127; i++) {
2034     GList *iter = g_list_find (payloads, GINT_TO_POINTER (i));
2035     if (!iter)
2036       return GPOINTER_TO_UINT (i);
2037   }
2038
2039   return 0;
2040 }
2041
2042 /**
2043  * gst_rtsp_media_collect_streams:
2044  * @media: a #GstRTSPMedia
2045  *
2046  * Find all payloader elements, they should be named pay\%d in the
2047  * element of @media, and create #GstRTSPStreams for them.
2048  *
2049  * Collect all dynamic elements, named dynpay\%d, and add them to
2050  * the list of dynamic elements.
2051  *
2052  * Find all depayloader elements, they should be named depay\%d in the
2053  * element of @media, and create #GstRTSPStreams for them.
2054  */
2055 void
2056 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
2057 {
2058   GstRTSPMediaPrivate *priv;
2059   GstElement *element, *elem;
2060   GstPad *pad;
2061   gint i;
2062   gboolean have_elem;
2063   gboolean more_elem_remaining = TRUE;
2064   GstRTSPTransportMode mode = 0;
2065
2066   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
2067
2068   priv = media->priv;
2069   element = priv->element;
2070
2071   have_elem = FALSE;
2072   for (i = 0; more_elem_remaining; i++) {
2073     gchar *name;
2074
2075     more_elem_remaining = FALSE;
2076
2077     name = g_strdup_printf ("pay%d", i);
2078     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2079       GstElement *pay;
2080       GST_INFO ("found stream %d with payloader %p", i, elem);
2081
2082       /* take the pad of the payloader */
2083       pad = gst_element_get_static_pad (elem, "src");
2084
2085       /* find the real payload element in case elem is a GstBin */
2086       pay = find_payload_element (elem);
2087
2088       /* create the stream */
2089       if (pay == NULL) {
2090         GST_WARNING ("could not find real payloader, using bin");
2091         gst_rtsp_media_create_stream (media, elem, pad);
2092       } else {
2093         gst_rtsp_media_create_stream (media, pay, pad);
2094         gst_object_unref (pay);
2095       }
2096
2097       gst_object_unref (pad);
2098       gst_object_unref (elem);
2099
2100       have_elem = TRUE;
2101       more_elem_remaining = TRUE;
2102       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2103     }
2104     g_free (name);
2105
2106     name = g_strdup_printf ("dynpay%d", i);
2107     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2108       /* a stream that will dynamically create pads to provide RTP packets */
2109       GST_INFO ("found dynamic element %d, %p", i, elem);
2110
2111       g_mutex_lock (&priv->lock);
2112       priv->dynamic = g_list_prepend (priv->dynamic, elem);
2113       g_mutex_unlock (&priv->lock);
2114
2115       priv->nb_dynamic_elements++;
2116
2117       have_elem = TRUE;
2118       more_elem_remaining = TRUE;
2119       mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
2120     }
2121     g_free (name);
2122
2123     name = g_strdup_printf ("depay%d", i);
2124     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
2125       GST_INFO ("found stream %d with depayloader %p", i, elem);
2126
2127       /* take the pad of the payloader */
2128       pad = gst_element_get_static_pad (elem, "sink");
2129       /* create the stream */
2130       gst_rtsp_media_create_stream (media, elem, pad);
2131       gst_object_unref (pad);
2132       gst_object_unref (elem);
2133
2134       have_elem = TRUE;
2135       more_elem_remaining = TRUE;
2136       mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
2137     }
2138     g_free (name);
2139   }
2140
2141   if (have_elem) {
2142     if (priv->transport_mode != mode)
2143       GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
2144           priv->transport_mode, mode);
2145   }
2146 }
2147
2148 typedef struct
2149 {
2150   GstElement *appsink, *appsrc;
2151   GstRTSPStream *stream;
2152 } AppSinkSrcData;
2153
2154 static GstFlowReturn
2155 appsink_new_sample (GstAppSink * appsink, gpointer user_data)
2156 {
2157   AppSinkSrcData *data = user_data;
2158   GstSample *sample;
2159   GstFlowReturn ret;
2160
2161   sample = gst_app_sink_pull_sample (appsink);
2162   if (!sample)
2163     return GST_FLOW_FLUSHING;
2164
2165
2166   ret = gst_app_src_push_sample (GST_APP_SRC (data->appsrc), sample);
2167   gst_sample_unref (sample);
2168   return ret;
2169 }
2170
2171 static GstAppSinkCallbacks appsink_callbacks = {
2172   NULL,
2173   NULL,
2174   appsink_new_sample,
2175 };
2176
2177 static GstPadProbeReturn
2178 appsink_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2179 {
2180   AppSinkSrcData *data = user_data;
2181
2182   if (GST_IS_EVENT (info->data)
2183       && GST_EVENT_TYPE (info->data) == GST_EVENT_LATENCY) {
2184     GstClockTime min, max;
2185
2186     if (gst_base_sink_query_latency (GST_BASE_SINK (data->appsink), NULL, NULL,
2187             &min, &max)) {
2188       g_object_set (data->appsrc, "min-latency", min, "max-latency", max, NULL);
2189       GST_DEBUG ("setting latency to min %" GST_TIME_FORMAT " max %"
2190           GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
2191     }
2192   } else if (GST_IS_QUERY (info->data)) {
2193     GstPad *srcpad = gst_element_get_static_pad (data->appsrc, "src");
2194     if (gst_pad_peer_query (srcpad, GST_QUERY_CAST (info->data))) {
2195       gst_object_unref (srcpad);
2196       return GST_PAD_PROBE_HANDLED;
2197     }
2198     gst_object_unref (srcpad);
2199   }
2200
2201   return GST_PAD_PROBE_OK;
2202 }
2203
2204 static GstPadProbeReturn
2205 appsrc_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2206 {
2207   AppSinkSrcData *data = user_data;
2208
2209   if (GST_IS_QUERY (info->data)) {
2210     GstPad *sinkpad = gst_element_get_static_pad (data->appsink, "sink");
2211     if (gst_pad_peer_query (sinkpad, GST_QUERY_CAST (info->data))) {
2212       gst_object_unref (sinkpad);
2213       return GST_PAD_PROBE_HANDLED;
2214     }
2215     gst_object_unref (sinkpad);
2216   }
2217
2218   return GST_PAD_PROBE_OK;
2219 }
2220
2221 /**
2222  * gst_rtsp_media_create_stream:
2223  * @media: a #GstRTSPMedia
2224  * @payloader: a #GstElement
2225  * @pad: a #GstPad
2226  *
2227  * Create a new stream in @media that provides RTP data on @pad.
2228  * @pad should be a pad of an element inside @media->element.
2229  *
2230  * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long
2231  * as @media exists.
2232  */
2233 GstRTSPStream *
2234 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
2235     GstPad * pad)
2236 {
2237   GstRTSPMediaPrivate *priv;
2238   GstRTSPStream *stream;
2239   GstPad *streampad;
2240   gchar *name;
2241   gint idx;
2242   AppSinkSrcData *data = NULL;
2243
2244   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2245   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
2246   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2247
2248   priv = media->priv;
2249
2250   g_mutex_lock (&priv->lock);
2251   idx = priv->streams->len;
2252
2253   GST_DEBUG ("media %p: creating stream with index %d", media, idx);
2254
2255   if (GST_PAD_IS_SRC (pad))
2256     name = g_strdup_printf ("src_%u", idx);
2257   else
2258     name = g_strdup_printf ("sink_%u", idx);
2259
2260   if ((GST_PAD_IS_SRC (pad) && priv->element->numsinkpads > 0) ||
2261       (GST_PAD_IS_SINK (pad) && priv->element->numsrcpads > 0)) {
2262     GstElement *appsink, *appsrc;
2263     GstPad *sinkpad, *srcpad;
2264
2265     appsink = gst_element_factory_make ("appsink", NULL);
2266     appsrc = gst_element_factory_make ("appsrc", NULL);
2267
2268     if (GST_PAD_IS_SINK (pad)) {
2269       srcpad = gst_element_get_static_pad (appsrc, "src");
2270
2271       gst_bin_add (GST_BIN (priv->element), appsrc);
2272
2273       gst_pad_link (srcpad, pad);
2274       gst_object_unref (srcpad);
2275
2276       streampad = gst_element_get_static_pad (appsink, "sink");
2277
2278       priv->pending_pipeline_elements =
2279           g_list_prepend (priv->pending_pipeline_elements, appsink);
2280     } else {
2281       sinkpad = gst_element_get_static_pad (appsink, "sink");
2282
2283       gst_pad_link (pad, sinkpad);
2284       gst_object_unref (sinkpad);
2285
2286       streampad = gst_element_get_static_pad (appsrc, "src");
2287
2288       priv->pending_pipeline_elements =
2289           g_list_prepend (priv->pending_pipeline_elements, appsrc);
2290     }
2291
2292     g_object_set (appsrc, "block", TRUE, "format", GST_FORMAT_TIME, "is-live",
2293         TRUE, "emit-signals", FALSE, NULL);
2294     g_object_set (appsink, "sync", FALSE, "async", FALSE, "emit-signals",
2295         FALSE, "buffer-list", TRUE, NULL);
2296
2297     data = g_new0 (AppSinkSrcData, 1);
2298     data->appsink = appsink;
2299     data->appsrc = appsrc;
2300
2301     sinkpad = gst_element_get_static_pad (appsink, "sink");
2302     gst_pad_add_probe (sinkpad,
2303         GST_PAD_PROBE_TYPE_EVENT_UPSTREAM | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM,
2304         appsink_pad_probe, data, NULL);
2305     gst_object_unref (sinkpad);
2306
2307     srcpad = gst_element_get_static_pad (appsrc, "src");
2308     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_QUERY_UPSTREAM,
2309         appsrc_pad_probe, data, NULL);
2310     gst_object_unref (srcpad);
2311
2312     gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &appsink_callbacks,
2313         data, NULL);
2314     g_object_set_data_full (G_OBJECT (streampad), "media-appsink-appsrc", data,
2315         g_free);
2316   } else {
2317     streampad = gst_ghost_pad_new (name, pad);
2318     gst_pad_set_active (streampad, TRUE);
2319     gst_element_add_pad (priv->element, streampad);
2320   }
2321   g_free (name);
2322
2323   stream = gst_rtsp_stream_new (idx, payloader, streampad);
2324   if (data)
2325     data->stream = stream;
2326   if (priv->pool)
2327     gst_rtsp_stream_set_address_pool (stream, priv->pool);
2328   gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface);
2329   gst_rtsp_stream_set_max_mcast_ttl (stream, priv->max_mcast_ttl);
2330   gst_rtsp_stream_set_bind_mcast_address (stream, priv->bind_mcast_address);
2331   gst_rtsp_stream_set_profiles (stream, priv->profiles);
2332   gst_rtsp_stream_set_protocols (stream, priv->protocols);
2333   gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
2334   gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
2335   gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
2336
2337   g_ptr_array_add (priv->streams, stream);
2338
2339   if (GST_PAD_IS_SRC (pad)) {
2340     gint i, n;
2341
2342     if (priv->payloads)
2343       g_list_free (priv->payloads);
2344     priv->payloads = _find_payload_types (media);
2345
2346     n = priv->streams->len;
2347     for (i = 0; i < n; i++) {
2348       GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2349       guint rtx_pt = _next_available_pt (priv->payloads);
2350
2351       if (rtx_pt == 0) {
2352         GST_WARNING ("Ran out of space of dynamic payload types");
2353         break;
2354       }
2355
2356       gst_rtsp_stream_set_retransmission_pt (stream, rtx_pt);
2357
2358       priv->payloads =
2359           g_list_append (priv->payloads, GUINT_TO_POINTER (rtx_pt));
2360     }
2361   }
2362   g_mutex_unlock (&priv->lock);
2363
2364   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
2365       NULL);
2366
2367   return stream;
2368 }
2369
2370 static void
2371 gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream)
2372 {
2373   GstRTSPMediaPrivate *priv;
2374   GstPad *srcpad;
2375   AppSinkSrcData *data;
2376
2377   priv = media->priv;
2378
2379   g_mutex_lock (&priv->lock);
2380   /* remove the ghostpad */
2381   srcpad = gst_rtsp_stream_get_srcpad (stream);
2382   data = g_object_get_data (G_OBJECT (srcpad), "media-appsink-appsrc");
2383   if (data) {
2384     if (GST_OBJECT_PARENT (data->appsrc) == GST_OBJECT_CAST (priv->pipeline))
2385       gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsrc);
2386     else if (GST_OBJECT_PARENT (data->appsrc) ==
2387         GST_OBJECT_CAST (priv->element))
2388       gst_bin_remove (GST_BIN_CAST (priv->element), data->appsrc);
2389     if (GST_OBJECT_PARENT (data->appsink) == GST_OBJECT_CAST (priv->pipeline))
2390       gst_bin_remove (GST_BIN_CAST (priv->pipeline), data->appsink);
2391     else if (GST_OBJECT_PARENT (data->appsink) ==
2392         GST_OBJECT_CAST (priv->element))
2393       gst_bin_remove (GST_BIN_CAST (priv->element), data->appsink);
2394   } else {
2395     gst_element_remove_pad (priv->element, srcpad);
2396   }
2397   gst_object_unref (srcpad);
2398   /* now remove the stream */
2399   g_object_ref (stream);
2400   g_ptr_array_remove (priv->streams, stream);
2401   g_mutex_unlock (&priv->lock);
2402
2403   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0,
2404       stream, NULL);
2405
2406   g_object_unref (stream);
2407 }
2408
2409 /**
2410  * gst_rtsp_media_n_streams:
2411  * @media: a #GstRTSPMedia
2412  *
2413  * Get the number of streams in this media.
2414  *
2415  * Returns: The number of streams.
2416  */
2417 guint
2418 gst_rtsp_media_n_streams (GstRTSPMedia * media)
2419 {
2420   GstRTSPMediaPrivate *priv;
2421   guint res;
2422
2423   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
2424
2425   priv = media->priv;
2426
2427   g_mutex_lock (&priv->lock);
2428   res = priv->streams->len;
2429   g_mutex_unlock (&priv->lock);
2430
2431   return res;
2432 }
2433
2434 /**
2435  * gst_rtsp_media_get_stream:
2436  * @media: a #GstRTSPMedia
2437  * @idx: the stream index
2438  *
2439  * Retrieve the stream with index @idx from @media.
2440  *
2441  * Returns: (nullable) (transfer none): the #GstRTSPStream at index
2442  * @idx or %NULL when a stream with that index did not exist.
2443  */
2444 GstRTSPStream *
2445 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
2446 {
2447   GstRTSPMediaPrivate *priv;
2448   GstRTSPStream *res;
2449
2450   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2451
2452   priv = media->priv;
2453
2454   g_mutex_lock (&priv->lock);
2455   if (idx < priv->streams->len)
2456     res = g_ptr_array_index (priv->streams, idx);
2457   else
2458     res = NULL;
2459   g_mutex_unlock (&priv->lock);
2460
2461   return res;
2462 }
2463
2464 /**
2465  * gst_rtsp_media_find_stream:
2466  * @media: a #GstRTSPMedia
2467  * @control: the control of the stream
2468  *
2469  * Find a stream in @media with @control as the control uri.
2470  *
2471  * Returns: (nullable) (transfer none): the #GstRTSPStream with
2472  * control uri @control or %NULL when a stream with that control did
2473  * not exist.
2474  */
2475 GstRTSPStream *
2476 gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
2477 {
2478   GstRTSPMediaPrivate *priv;
2479   GstRTSPStream *res;
2480   gint i;
2481
2482   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2483   g_return_val_if_fail (control != NULL, NULL);
2484
2485   priv = media->priv;
2486
2487   res = NULL;
2488
2489   g_mutex_lock (&priv->lock);
2490   for (i = 0; i < priv->streams->len; i++) {
2491     GstRTSPStream *test;
2492
2493     test = g_ptr_array_index (priv->streams, i);
2494     if (gst_rtsp_stream_has_control (test, control)) {
2495       res = test;
2496       break;
2497     }
2498   }
2499   g_mutex_unlock (&priv->lock);
2500
2501   return res;
2502 }
2503
2504 /* called with state-lock */
2505 static gboolean
2506 default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range,
2507     GstRTSPRangeUnit unit)
2508 {
2509   return gst_rtsp_range_convert_units (range, unit);
2510 }
2511
2512 /**
2513  * gst_rtsp_media_get_range_string:
2514  * @media: a #GstRTSPMedia
2515  * @play: for the PLAY request
2516  * @unit: the unit to use for the string
2517  *
2518  * Get the current range as a string. @media must be prepared with
2519  * gst_rtsp_media_prepare ().
2520  *
2521  * Returns: (transfer full) (nullable): The range as a string, g_free() after usage.
2522  */
2523 gchar *
2524 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play,
2525     GstRTSPRangeUnit unit)
2526 {
2527   GstRTSPMediaClass *klass;
2528   GstRTSPMediaPrivate *priv;
2529   gchar *result;
2530   GstRTSPTimeRange range;
2531
2532   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2533   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
2534   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2535
2536   priv = media->priv;
2537
2538   g_rec_mutex_lock (&priv->state_lock);
2539   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
2540       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
2541     goto not_prepared;
2542
2543   /* Update the range value with current position/duration */
2544   g_mutex_lock (&priv->lock);
2545   collect_media_stats (media);
2546
2547   /* make copy */
2548   range = priv->range;
2549
2550   if (!play && priv->n_active > 0) {
2551     range.min.type = GST_RTSP_TIME_NOW;
2552     range.min.seconds = -1;
2553   }
2554   g_mutex_unlock (&priv->lock);
2555   g_rec_mutex_unlock (&priv->state_lock);
2556
2557   if (!klass->convert_range (media, &range, unit))
2558     goto conversion_failed;
2559
2560   result = gst_rtsp_range_to_string (&range);
2561
2562   return result;
2563
2564   /* ERRORS */
2565 not_prepared:
2566   {
2567     GST_WARNING ("media %p was not prepared", media);
2568     g_rec_mutex_unlock (&priv->state_lock);
2569     return NULL;
2570   }
2571 conversion_failed:
2572   {
2573     GST_WARNING ("range conversion to unit %d failed", unit);
2574     return NULL;
2575   }
2576 }
2577
2578 gboolean
2579 gst_rtsp_media_has_completed_sender (GstRTSPMedia * media)
2580 {
2581   GstRTSPMediaPrivate *priv = media->priv;
2582   gboolean sender = FALSE;
2583   guint i;
2584
2585   g_mutex_lock (&priv->lock);
2586   for (i = 0; i < priv->streams->len; i++) {
2587     GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
2588     if (gst_rtsp_stream_is_complete (stream) &&
2589         gst_rtsp_stream_is_sender (stream)) {
2590       sender = TRUE;
2591       break;
2592     }
2593   }
2594   g_mutex_unlock (&priv->lock);
2595
2596   return sender;
2597 }
2598
2599 static void
2600 stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
2601 {
2602   gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
2603 }
2604
2605 static void
2606 media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
2607 {
2608   GstRTSPMediaPrivate *priv = media->priv;
2609
2610   GST_DEBUG ("media %p set blocked %d", media, blocked);
2611   priv->blocked = blocked;
2612   g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
2613 }
2614
2615 static void
2616 stream_unblock (GstRTSPStream * stream, GstRTSPMedia * media)
2617 {
2618   gst_rtsp_stream_unblock_linked (stream);
2619 }
2620
2621 static void
2622 media_unblock_linked (GstRTSPMedia * media)
2623 {
2624   GstRTSPMediaPrivate *priv = media->priv;
2625
2626   GST_DEBUG ("media %p unblocking linked streams", media);
2627   /* media is not blocked any longer, as it contains active streams,
2628    * streams that are complete */
2629   priv->blocked = FALSE;
2630   g_ptr_array_foreach (priv->streams, (GFunc) stream_unblock, media);
2631 }
2632
2633 void
2634 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
2635 {
2636   GstRTSPMediaPrivate *priv = media->priv;
2637
2638   g_mutex_lock (&priv->lock);
2639   priv->status = status;
2640   GST_DEBUG ("setting new status to %d", status);
2641   g_cond_broadcast (&priv->cond);
2642   g_mutex_unlock (&priv->lock);
2643 }
2644
2645 /**
2646  * gst_rtsp_media_get_status:
2647  * @media: a #GstRTSPMedia
2648  *
2649  * Get the status of @media. When @media is busy preparing, this function waits
2650  * until @media is prepared or in error.
2651  *
2652  * Returns: the status of @media.
2653  */
2654 GstRTSPMediaStatus
2655 gst_rtsp_media_get_status (GstRTSPMedia * media)
2656 {
2657   GstRTSPMediaPrivate *priv = media->priv;
2658   GstRTSPMediaStatus result;
2659   gint64 end_time;
2660
2661   g_mutex_lock (&priv->lock);
2662   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
2663   /* while we are preparing, wait */
2664   while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
2665     GST_DEBUG ("waiting for status change");
2666     if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
2667       GST_DEBUG ("timeout, assuming error status");
2668       priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
2669     }
2670   }
2671   /* could be success or error */
2672   result = priv->status;
2673   GST_DEBUG ("got status %d", result);
2674   g_mutex_unlock (&priv->lock);
2675
2676   return result;
2677 }
2678
2679 /**
2680  * gst_rtsp_media_seek_full:
2681  * @media: a #GstRTSPMedia
2682  * @range: (transfer none): a #GstRTSPTimeRange
2683  * @flags: The minimal set of #GstSeekFlags to use
2684  *
2685  * Seek the pipeline of @media to @range. @media must be prepared with
2686  * gst_rtsp_media_prepare(). In order to perform the seek operation,
2687  * the pipeline must contain all needed transport parts (transport sinks).
2688  *
2689  * Returns: %TRUE on success.
2690  *
2691  * Since: 1.14
2692  */
2693 gboolean
2694 gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
2695     GstSeekFlags flags)
2696 {
2697   GstRTSPMediaClass *klass;
2698   GstRTSPMediaPrivate *priv;
2699   gboolean res;
2700   GstClockTime start, stop;
2701   GstSeekType start_type, stop_type;
2702   gint64 current_position;
2703
2704   klass = GST_RTSP_MEDIA_GET_CLASS (media);
2705
2706   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
2707   g_return_val_if_fail (range != NULL, FALSE);
2708   g_return_val_if_fail (klass->convert_range != NULL, FALSE);
2709
2710   priv = media->priv;
2711
2712   g_rec_mutex_lock (&priv->state_lock);
2713   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
2714     goto not_prepared;
2715
2716   /* check if the media pipeline is complete in order to perform a
2717    * seek operation on it */
2718   if (!check_complete (media))
2719     goto not_complete;
2720
2721   /* Update the seekable state of the pipeline in case it changed */
2722   check_seekable (media);
2723
2724   if (priv->seekable == 0) {
2725     GST_FIXME_OBJECT (media, "Handle going back to 0 for none live"
2726         " not seekable streams.");
2727
2728     goto not_seekable;
2729   } else if (priv->seekable < 0) {
2730     goto not_seekable;
2731   }
2732
2733   start_type = stop_type = GST_SEEK_TYPE_NONE;
2734
2735   if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT))
2736     goto not_supported;
2737   gst_rtsp_range_get_times (range, &start, &stop);
2738
2739   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2740       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2741   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2742       GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
2743
2744   current_position = -1;
2745   if (klass->query_position)
2746     klass->query_position (media, &current_position);
2747   GST_INFO ("current media position %" GST_TIME_FORMAT,
2748       GST_TIME_ARGS (current_position));
2749
2750   if (start != GST_CLOCK_TIME_NONE)
2751     start_type = GST_SEEK_TYPE_SET;
2752
2753   if (priv->range_stop == stop)
2754     stop = GST_CLOCK_TIME_NONE;
2755   else if (stop != GST_CLOCK_TIME_NONE)
2756     stop_type = GST_SEEK_TYPE_SET;
2757
2758   if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) {
2759     gboolean had_flags = flags != 0;
2760
2761     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2762         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2763
2764     /* depends on the current playing state of the pipeline. We might need to
2765      * queue this until we get EOS. */
2766     if (had_flags)
2767       flags |= GST_SEEK_FLAG_FLUSH;
2768     else
2769       flags = GST_SEEK_FLAG_FLUSH;
2770
2771
2772     /* if range start was not supplied we must continue from current position.
2773      * but since we're doing a flushing seek, let us query the current position
2774      * so we end up at exactly the same position after the seek. */
2775     if (range->min.type == GST_RTSP_TIME_END) { /* Yepp, that's right! */
2776       if (current_position == -1) {
2777         GST_WARNING ("current position unknown");
2778       } else {
2779         GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT,
2780             GST_TIME_ARGS (current_position));
2781         start = current_position;
2782         start_type = GST_SEEK_TYPE_SET;
2783         if (!had_flags)
2784           flags |= GST_SEEK_FLAG_ACCURATE;
2785       }
2786     } else {
2787       /* only set keyframe flag when modifying start */
2788       if (start_type != GST_SEEK_TYPE_NONE)
2789         if (!had_flags)
2790           flags |= GST_SEEK_FLAG_KEY_UNIT;
2791     }
2792
2793     if (start == current_position && stop_type == GST_SEEK_TYPE_NONE) {
2794       GST_DEBUG ("not seeking because no position change");
2795       res = TRUE;
2796     } else {
2797       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
2798
2799       /* FIXME, we only do forwards playback, no trick modes yet */
2800       res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
2801           flags, start_type, start, stop_type, stop);
2802
2803       /* and block for the seek to complete */
2804       GST_INFO ("done seeking %d", res);
2805       if (!res)
2806         goto seek_failed;
2807
2808       g_rec_mutex_unlock (&priv->state_lock);
2809
2810       /* wait until pipeline is prerolled again, this will also collect stats */
2811       if (!wait_preroll (media))
2812         goto preroll_failed;
2813
2814       g_rec_mutex_lock (&priv->state_lock);
2815       GST_INFO ("prerolled again");
2816     }
2817   } else {
2818     GST_INFO ("no seek needed");
2819     res = TRUE;
2820   }
2821   g_rec_mutex_unlock (&priv->state_lock);
2822
2823   return res;
2824
2825   /* ERRORS */
2826 not_prepared:
2827   {
2828     g_rec_mutex_unlock (&priv->state_lock);
2829     GST_INFO ("media %p is not prepared", media);
2830     return FALSE;
2831   }
2832 not_complete:
2833   {
2834     g_rec_mutex_unlock (&priv->state_lock);
2835     GST_INFO ("pipeline is not complete");
2836     return FALSE;
2837   }
2838 not_seekable:
2839   {
2840     g_rec_mutex_unlock (&priv->state_lock);
2841     GST_INFO ("pipeline is not seekable");
2842     return FALSE;
2843   }
2844 not_supported:
2845   {
2846     g_rec_mutex_unlock (&priv->state_lock);
2847     GST_WARNING ("conversion to npt not supported");
2848     return FALSE;
2849   }
2850 seek_failed:
2851   {
2852     g_rec_mutex_unlock (&priv->state_lock);
2853     GST_INFO ("seeking failed");
2854     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
2855     return FALSE;
2856   }
2857 preroll_failed:
2858   {
2859     GST_WARNING ("failed to preroll after seek");
2860     return FALSE;
2861   }
2862 }
2863
2864
2865 /**
2866  * gst_rtsp_media_seek:
2867  * @media: a #GstRTSPMedia
2868  * @range: (transfer none): a #GstRTSPTimeRange
2869  *
2870  * Seek the pipeline of @media to @range. @media must be prepared with
2871  * gst_rtsp_media_prepare().
2872  *
2873  * Returns: %TRUE on success.
2874  */
2875 gboolean
2876 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
2877 {
2878   return gst_rtsp_media_seek_full (media, range, 0);
2879 }
2880
2881
2882 static void
2883 stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
2884 {
2885   *blocked &= gst_rtsp_stream_is_blocking (stream);
2886 }
2887
2888 static gboolean
2889 media_streams_blocking (GstRTSPMedia * media)
2890 {
2891   gboolean blocking = TRUE;
2892
2893   g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
2894       &blocking);
2895
2896   return blocking;
2897 }
2898
2899 static GstStateChangeReturn
2900 set_state (GstRTSPMedia * media, GstState state)
2901 {
2902   GstRTSPMediaPrivate *priv = media->priv;
2903   GstStateChangeReturn ret;
2904
2905   GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state),
2906       media);
2907   ret = gst_element_set_state (priv->pipeline, state);
2908
2909   {
2910     gchar *filename = NULL;
2911     filename = g_strdup_printf ("media_%s", gst_element_state_get_name (state));
2912     GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (priv->pipeline),
2913         GST_DEBUG_GRAPH_SHOW_ALL, filename);
2914
2915     g_free (filename);
2916   }
2917
2918   return ret;
2919 }
2920
2921 static GstStateChangeReturn
2922 set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state)
2923 {
2924   GstRTSPMediaPrivate *priv = media->priv;
2925   GstStateChangeReturn ret;
2926
2927   GST_INFO ("set target state to %s for media %p",
2928       gst_element_state_get_name (state), media);
2929   priv->target_state = state;
2930
2931   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0,
2932       priv->target_state, NULL);
2933
2934   if (do_state)
2935     ret = set_state (media, state);
2936   else
2937     ret = GST_STATE_CHANGE_SUCCESS;
2938
2939   return ret;
2940 }
2941
2942 /* called with state-lock */
2943 static gboolean
2944 default_handle_message (GstRTSPMedia * media, GstMessage * message)
2945 {
2946   GstRTSPMediaPrivate *priv = media->priv;
2947   GstMessageType type;
2948
2949   type = GST_MESSAGE_TYPE (message);
2950
2951   switch (type) {
2952     case GST_MESSAGE_STATE_CHANGED:
2953     {
2954       GstState old, new, pending;
2955
2956       if (GST_MESSAGE_SRC (message) != GST_OBJECT (priv->pipeline))
2957         break;
2958
2959       gst_message_parse_state_changed (message, &old, &new, &pending);
2960
2961       GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
2962           gst_element_state_get_name (old), gst_element_state_get_name (new),
2963           gst_element_state_get_name (pending));
2964       if (priv->no_more_pads_pending == 0
2965           && gst_rtsp_media_is_receive_only (media) && old == GST_STATE_READY
2966           && new == GST_STATE_PAUSED) {
2967         GST_INFO ("%p: went to PAUSED, prepared now", media);
2968         g_mutex_lock (&priv->lock);
2969         collect_media_stats (media);
2970         g_mutex_unlock (&priv->lock);
2971
2972         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
2973           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
2974       }
2975
2976       break;
2977     }
2978     case GST_MESSAGE_BUFFERING:
2979     {
2980       gint percent;
2981
2982       gst_message_parse_buffering (message, &percent);
2983
2984       /* no state management needed for live pipelines */
2985       if (priv->is_live)
2986         break;
2987
2988       if (percent == 100) {
2989         /* a 100% message means buffering is done */
2990         priv->buffering = FALSE;
2991         /* if the desired state is playing, go back */
2992         if (priv->target_state == GST_STATE_PLAYING) {
2993           GST_INFO ("Buffering done, setting pipeline to PLAYING");
2994           set_state (media, GST_STATE_PLAYING);
2995         } else {
2996           GST_INFO ("Buffering done");
2997         }
2998       } else {
2999         /* buffering busy */
3000         if (priv->buffering == FALSE) {
3001           if (priv->target_state == GST_STATE_PLAYING) {
3002             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
3003             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
3004             set_state (media, GST_STATE_PAUSED);
3005           } else {
3006             GST_INFO ("Buffering ...");
3007           }
3008         }
3009         priv->buffering = TRUE;
3010       }
3011       break;
3012     }
3013     case GST_MESSAGE_LATENCY:
3014     {
3015       gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
3016       break;
3017     }
3018     case GST_MESSAGE_ERROR:
3019     {
3020       GError *gerror;
3021       gchar *debug;
3022
3023       gst_message_parse_error (message, &gerror, &debug);
3024       GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
3025       g_error_free (gerror);
3026       g_free (debug);
3027
3028       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3029       break;
3030     }
3031     case GST_MESSAGE_WARNING:
3032     {
3033       GError *gerror;
3034       gchar *debug;
3035
3036       gst_message_parse_warning (message, &gerror, &debug);
3037       GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
3038       g_error_free (gerror);
3039       g_free (debug);
3040       break;
3041     }
3042     case GST_MESSAGE_ELEMENT:
3043     {
3044       const GstStructure *s;
3045
3046       s = gst_message_get_structure (message);
3047       if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
3048         GST_DEBUG ("media received blocking message");
3049         if (priv->blocked && media_streams_blocking (media) &&
3050             priv->no_more_pads_pending == 0) {
3051           GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "media is blocking");
3052           g_mutex_lock (&priv->lock);
3053           collect_media_stats (media);
3054           g_mutex_unlock (&priv->lock);
3055
3056           if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3057             gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3058         }
3059       }
3060       break;
3061     }
3062     case GST_MESSAGE_STREAM_STATUS:
3063       break;
3064     case GST_MESSAGE_ASYNC_DONE:
3065       if (priv->complete) {
3066         /* receive the final ASYNC_DONE, that is posted by the media pipeline
3067          * after all the transport parts have been successfully added to
3068          * the media streams. */
3069         GST_DEBUG_OBJECT (media, "got async-done");
3070         if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3071           gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3072       }
3073       break;
3074     case GST_MESSAGE_EOS:
3075       GST_INFO ("%p: got EOS", media);
3076
3077       if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
3078         GST_DEBUG ("shutting down after EOS");
3079         finish_unprepare (media);
3080       }
3081       break;
3082     default:
3083       GST_INFO ("%p: got message type %d (%s)", media, type,
3084           gst_message_type_get_name (type));
3085       break;
3086   }
3087   return TRUE;
3088 }
3089
3090 static gboolean
3091 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
3092 {
3093   GstRTSPMediaPrivate *priv = media->priv;
3094   GstRTSPMediaClass *klass;
3095   gboolean ret;
3096
3097   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3098
3099   g_rec_mutex_lock (&priv->state_lock);
3100   if (klass->handle_message)
3101     ret = klass->handle_message (media, message);
3102   else
3103     ret = FALSE;
3104   g_rec_mutex_unlock (&priv->state_lock);
3105
3106   return ret;
3107 }
3108
3109 static void
3110 watch_destroyed (GstRTSPMedia * media)
3111 {
3112   GST_DEBUG_OBJECT (media, "source destroyed");
3113   g_object_unref (media);
3114 }
3115
3116 static GstElement *
3117 find_payload_element (GstElement * payloader)
3118 {
3119   GstElement *pay = NULL;
3120
3121   if (GST_IS_BIN (payloader)) {
3122     GstIterator *iter;
3123     GValue item = { 0 };
3124
3125     iter = gst_bin_iterate_recurse (GST_BIN (payloader));
3126     while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) {
3127       GstElement *element = (GstElement *) g_value_get_object (&item);
3128       GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element);
3129       const gchar *klass;
3130
3131       klass =
3132           gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS);
3133       if (klass == NULL)
3134         continue;
3135
3136       if (strstr (klass, "Payloader") && strstr (klass, "RTP")) {
3137         pay = gst_object_ref (element);
3138         g_value_unset (&item);
3139         break;
3140       }
3141       g_value_unset (&item);
3142     }
3143     gst_iterator_free (iter);
3144   } else {
3145     pay = g_object_ref (payloader);
3146   }
3147
3148   return pay;
3149 }
3150
3151 /* called from streaming threads */
3152 static void
3153 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3154 {
3155   GstRTSPMediaPrivate *priv = media->priv;
3156   GstRTSPStream *stream;
3157   GstElement *pay;
3158
3159   /* find the real payload element */
3160   pay = find_payload_element (element);
3161   stream = gst_rtsp_media_create_stream (media, pay, pad);
3162   gst_object_unref (pay);
3163
3164   GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3165
3166   g_rec_mutex_lock (&priv->state_lock);
3167   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3168     goto not_preparing;
3169
3170   g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream);
3171
3172   /* join the element in the PAUSED state because this callback is
3173    * called from the streaming thread and it is PAUSED */
3174   if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3175           priv->rtpbin, GST_STATE_PAUSED)) {
3176     GST_WARNING ("failed to join bin element");
3177   }
3178
3179   if (priv->blocked)
3180     gst_rtsp_stream_set_blocked (stream, TRUE);
3181
3182   g_rec_mutex_unlock (&priv->state_lock);
3183
3184   return;
3185
3186   /* ERRORS */
3187 not_preparing:
3188   {
3189     gst_rtsp_media_remove_stream (media, stream);
3190     g_rec_mutex_unlock (&priv->state_lock);
3191     GST_INFO ("ignore pad because we are not preparing");
3192     return;
3193   }
3194 }
3195
3196 static void
3197 pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
3198 {
3199   GstRTSPMediaPrivate *priv = media->priv;
3200   GstRTSPStream *stream;
3201
3202   stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream");
3203   if (stream == NULL)
3204     return;
3205
3206   GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream);
3207
3208   g_rec_mutex_lock (&priv->state_lock);
3209   gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3210   g_rec_mutex_unlock (&priv->state_lock);
3211
3212   gst_rtsp_media_remove_stream (media, stream);
3213 }
3214
3215 static void
3216 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
3217 {
3218   GstRTSPMediaPrivate *priv = media->priv;
3219
3220   GST_INFO_OBJECT (element, "no more pads");
3221   g_mutex_lock (&priv->lock);
3222   priv->no_more_pads_pending--;
3223   g_mutex_unlock (&priv->lock);
3224 }
3225
3226 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
3227
3228 struct _DynPaySignalHandlers
3229 {
3230   gulong pad_added_handler;
3231   gulong pad_removed_handler;
3232   gulong no_more_pads_handler;
3233 };
3234
3235 static gboolean
3236 start_preroll (GstRTSPMedia * media)
3237 {
3238   GstRTSPMediaPrivate *priv = media->priv;
3239   GstStateChangeReturn ret;
3240
3241   GST_INFO ("setting pipeline to PAUSED for media %p", media);
3242
3243   /* start blocked since it is possible that there are no sink elements yet */
3244   media_streams_set_blocked (media, TRUE);
3245   ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
3246
3247   switch (ret) {
3248     case GST_STATE_CHANGE_SUCCESS:
3249       GST_INFO ("SUCCESS state change for media %p", media);
3250       break;
3251     case GST_STATE_CHANGE_ASYNC:
3252       GST_INFO ("ASYNC state change for media %p", media);
3253       break;
3254     case GST_STATE_CHANGE_NO_PREROLL:
3255       /* we need to go to PLAYING */
3256       GST_INFO ("NO_PREROLL state change: live media %p", media);
3257       /* FIXME we disable seeking for live streams for now. We should perform a
3258        * seeking query in preroll instead */
3259       priv->seekable = -1;
3260       priv->is_live = TRUE;
3261
3262       ret = set_state (media, GST_STATE_PLAYING);
3263       if (ret == GST_STATE_CHANGE_FAILURE)
3264         goto state_failed;
3265       break;
3266     case GST_STATE_CHANGE_FAILURE:
3267       goto state_failed;
3268   }
3269
3270   return TRUE;
3271
3272 state_failed:
3273   {
3274     GST_WARNING ("failed to preroll pipeline");
3275     return FALSE;
3276   }
3277 }
3278
3279 static gboolean
3280 wait_preroll (GstRTSPMedia * media)
3281 {
3282   GstRTSPMediaStatus status;
3283
3284   GST_DEBUG ("wait to preroll pipeline");
3285
3286   /* wait until pipeline is prerolled */
3287   status = gst_rtsp_media_get_status (media);
3288   if (status == GST_RTSP_MEDIA_STATUS_ERROR)
3289     goto preroll_failed;
3290
3291   return TRUE;
3292
3293 preroll_failed:
3294   {
3295     GST_WARNING ("failed to preroll pipeline");
3296     return FALSE;
3297   }
3298 }
3299
3300 static GstElement *
3301 request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3302 {
3303   GstRTSPMediaPrivate *priv = media->priv;
3304   GstRTSPStream *stream = NULL;
3305   guint i;
3306   GstElement *res = NULL;
3307
3308   g_mutex_lock (&priv->lock);
3309   for (i = 0; i < priv->streams->len; i++) {
3310     stream = g_ptr_array_index (priv->streams, i);
3311
3312     if (sessid == gst_rtsp_stream_get_index (stream))
3313       break;
3314
3315     stream = NULL;
3316   }
3317   g_mutex_unlock (&priv->lock);
3318
3319   if (stream)
3320     res = gst_rtsp_stream_request_aux_sender (stream, sessid);
3321
3322   return res;
3323 }
3324
3325 static GstElement *
3326 request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3327 {
3328   GstRTSPMediaPrivate *priv = media->priv;
3329   GstRTSPStream *stream = NULL;
3330   guint i;
3331   GstElement *res = NULL;
3332
3333   g_mutex_lock (&priv->lock);
3334   for (i = 0; i < priv->streams->len; i++) {
3335     stream = g_ptr_array_index (priv->streams, i);
3336
3337     if (sessid == gst_rtsp_stream_get_index (stream))
3338       break;
3339
3340     stream = NULL;
3341   }
3342   g_mutex_unlock (&priv->lock);
3343
3344   if (stream)
3345     res = gst_rtsp_stream_request_aux_receiver (stream, sessid);
3346
3347   return res;
3348 }
3349
3350 static GstElement *
3351 request_fec_decoder (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
3352 {
3353   GstRTSPMediaPrivate *priv = media->priv;
3354   GstRTSPStream *stream = NULL;
3355   guint i;
3356   GstElement *res = NULL;
3357
3358   g_mutex_lock (&priv->lock);
3359   for (i = 0; i < priv->streams->len; i++) {
3360     stream = g_ptr_array_index (priv->streams, i);
3361
3362     if (sessid == gst_rtsp_stream_get_index (stream))
3363       break;
3364
3365     stream = NULL;
3366   }
3367   g_mutex_unlock (&priv->lock);
3368
3369   if (stream) {
3370     res = gst_rtsp_stream_request_ulpfec_decoder (stream, rtpbin, sessid);
3371   }
3372
3373   return res;
3374 }
3375
3376 static void
3377 new_storage_cb (GstElement * rtpbin, GObject * storage, guint sessid,
3378     GstRTSPMedia * media)
3379 {
3380   g_object_set (storage, "size-time", (media->priv->latency + 50) * GST_MSECOND,
3381       NULL);
3382 }
3383
3384 static gboolean
3385 start_prepare (GstRTSPMedia * media)
3386 {
3387   GstRTSPMediaPrivate *priv = media->priv;
3388   guint i;
3389   GList *walk;
3390
3391   g_rec_mutex_lock (&priv->state_lock);
3392   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
3393     goto no_longer_preparing;
3394
3395   g_signal_connect (priv->rtpbin, "new-storage", G_CALLBACK (new_storage_cb),
3396       media);
3397   g_signal_connect (priv->rtpbin, "request-fec-decoder",
3398       G_CALLBACK (request_fec_decoder), media);
3399
3400   /* link streams we already have, other streams might appear when we have
3401    * dynamic elements */
3402   for (i = 0; i < priv->streams->len; i++) {
3403     GstRTSPStream *stream;
3404
3405     stream = g_ptr_array_index (priv->streams, i);
3406
3407     if (priv->rtx_time > 0) {
3408       /* enable retransmission by setting rtprtxsend as the "aux" element of rtpbin */
3409       g_signal_connect (priv->rtpbin, "request-aux-sender",
3410           (GCallback) request_aux_sender, media);
3411     }
3412
3413     if (priv->do_retransmission) {
3414       g_signal_connect (priv->rtpbin, "request-aux-receiver",
3415           (GCallback) request_aux_receiver, media);
3416     }
3417
3418     if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
3419             priv->rtpbin, GST_STATE_NULL)) {
3420       goto join_bin_failed;
3421     }
3422
3423     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARING], 0, stream,
3424         i, NULL);
3425   }
3426
3427   if (priv->rtpbin)
3428     g_object_set (priv->rtpbin, "do-retransmission", priv->do_retransmission,
3429         "do-lost", TRUE, NULL);
3430
3431   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3432     GstElement *elem = walk->data;
3433     DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
3434
3435     GST_INFO ("adding callbacks for dynamic element %p", elem);
3436
3437     handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
3438         (GCallback) pad_added_cb, media);
3439     handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
3440         (GCallback) pad_removed_cb, media);
3441     handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
3442         (GCallback) no_more_pads_cb, media);
3443
3444     g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
3445   }
3446
3447   if (priv->nb_dynamic_elements == 0 && gst_rtsp_media_is_receive_only (media)) {
3448     /* If we are receive_only (RECORD), do not try to preroll, to avoid
3449      * a second ASYNC state change failing */
3450     priv->is_live = TRUE;
3451     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
3452   } else if (!start_preroll (media)) {
3453     goto preroll_failed;
3454   }
3455
3456   g_rec_mutex_unlock (&priv->state_lock);
3457
3458   return FALSE;
3459
3460 no_longer_preparing:
3461   {
3462     GST_INFO ("media is no longer preparing");
3463     g_rec_mutex_unlock (&priv->state_lock);
3464     return FALSE;
3465   }
3466 join_bin_failed:
3467   {
3468     GST_WARNING ("failed to join bin element");
3469     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3470     g_rec_mutex_unlock (&priv->state_lock);
3471     return FALSE;
3472   }
3473 preroll_failed:
3474   {
3475     GST_WARNING ("failed to preroll pipeline");
3476     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
3477     g_rec_mutex_unlock (&priv->state_lock);
3478     return FALSE;
3479   }
3480 }
3481
3482 static gboolean
3483 default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3484 {
3485   GstRTSPMediaPrivate *priv;
3486   GstRTSPMediaClass *klass;
3487   GstBus *bus;
3488   GMainContext *context;
3489   GSource *source;
3490
3491   priv = media->priv;
3492
3493   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3494
3495   if (!klass->create_rtpbin)
3496     goto no_create_rtpbin;
3497
3498   priv->rtpbin = klass->create_rtpbin (media);
3499   if (priv->rtpbin != NULL) {
3500     gboolean success = TRUE;
3501
3502     g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
3503
3504     if (klass->setup_rtpbin)
3505       success = klass->setup_rtpbin (media, priv->rtpbin);
3506
3507     if (success == FALSE) {
3508       gst_object_unref (priv->rtpbin);
3509       priv->rtpbin = NULL;
3510     }
3511   }
3512   if (priv->rtpbin == NULL)
3513     goto no_rtpbin;
3514
3515   priv->thread = thread;
3516   context = (thread != NULL) ? (thread->context) : NULL;
3517
3518   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
3519
3520   /* add the pipeline bus to our custom mainloop */
3521   priv->source = gst_bus_create_watch (bus);
3522   gst_object_unref (bus);
3523
3524   g_source_set_callback (priv->source, (GSourceFunc) bus_message,
3525       g_object_ref (media), (GDestroyNotify) watch_destroyed);
3526
3527   priv->id = g_source_attach (priv->source, context);
3528
3529   /* add stuff to the bin */
3530   gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
3531
3532   /* do remainder in context */
3533   source = g_idle_source_new ();
3534   g_source_set_callback (source, (GSourceFunc) start_prepare,
3535       g_object_ref (media), (GDestroyNotify) g_object_unref);
3536   g_source_attach (source, context);
3537   g_source_unref (source);
3538
3539   return TRUE;
3540
3541   /* ERRORS */
3542 no_create_rtpbin:
3543   {
3544     GST_ERROR ("no create_rtpbin function");
3545     g_critical ("no create_rtpbin vmethod function set");
3546     return FALSE;
3547   }
3548 no_rtpbin:
3549   {
3550     GST_WARNING ("no rtpbin element");
3551     g_warning ("failed to create element 'rtpbin', check your installation");
3552     return FALSE;
3553   }
3554 }
3555
3556 /**
3557  * gst_rtsp_media_prepare:
3558  * @media: a #GstRTSPMedia
3559  * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
3560  *   bus handler or %NULL
3561  *
3562  * Prepare @media for streaming. This function will create the objects
3563  * to manage the streaming. A pipeline must have been set on @media with
3564  * gst_rtsp_media_take_pipeline().
3565  *
3566  * It will preroll the pipeline and collect vital information about the streams
3567  * such as the duration.
3568  *
3569  * Returns: %TRUE on success.
3570  */
3571 gboolean
3572 gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
3573 {
3574   GstRTSPMediaPrivate *priv;
3575   GstRTSPMediaClass *klass;
3576
3577   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3578
3579   priv = media->priv;
3580
3581   g_rec_mutex_lock (&priv->state_lock);
3582   priv->prepare_count++;
3583
3584   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED ||
3585       priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED)
3586     goto was_prepared;
3587
3588   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
3589     goto is_preparing;
3590
3591   if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
3592     goto not_unprepared;
3593
3594   if (!priv->reusable && priv->reused)
3595     goto is_reused;
3596
3597   GST_INFO ("preparing media %p", media);
3598
3599   /* reset some variables */
3600   priv->is_live = FALSE;
3601   priv->seekable = -1;
3602   priv->buffering = FALSE;
3603   priv->no_more_pads_pending = priv->nb_dynamic_elements;
3604
3605   /* we're preparing now */
3606   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
3607
3608   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3609   if (klass->prepare) {
3610     if (!klass->prepare (media, thread))
3611       goto prepare_failed;
3612   }
3613
3614 wait_status:
3615   g_rec_mutex_unlock (&priv->state_lock);
3616
3617   /* now wait for all pads to be prerolled, FIXME, we should somehow be
3618    * able to do this async so that we don't block the server thread. */
3619   if (!wait_preroll (media))
3620     goto preroll_failed;
3621
3622   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL);
3623
3624   GST_INFO ("object %p is prerolled", media);
3625
3626   return TRUE;
3627
3628   /* OK */
3629 is_preparing:
3630   {
3631     /* we are not going to use the giving thread, so stop it. */
3632     if (thread)
3633       gst_rtsp_thread_stop (thread);
3634     goto wait_status;
3635   }
3636 was_prepared:
3637   {
3638     GST_LOG ("media %p was prepared", media);
3639     /* we are not going to use the giving thread, so stop it. */
3640     if (thread)
3641       gst_rtsp_thread_stop (thread);
3642     g_rec_mutex_unlock (&priv->state_lock);
3643     return TRUE;
3644   }
3645   /* ERRORS */
3646 not_unprepared:
3647   {
3648     /* we are not going to use the giving thread, so stop it. */
3649     if (thread)
3650       gst_rtsp_thread_stop (thread);
3651     GST_WARNING ("media %p was not unprepared", media);
3652     priv->prepare_count--;
3653     g_rec_mutex_unlock (&priv->state_lock);
3654     return FALSE;
3655   }
3656 is_reused:
3657   {
3658     /* we are not going to use the giving thread, so stop it. */
3659     if (thread)
3660       gst_rtsp_thread_stop (thread);
3661     priv->prepare_count--;
3662     g_rec_mutex_unlock (&priv->state_lock);
3663     GST_WARNING ("can not reuse media %p", media);
3664     return FALSE;
3665   }
3666 prepare_failed:
3667   {
3668     /* we are not going to use the giving thread, so stop it. */
3669     if (thread)
3670       gst_rtsp_thread_stop (thread);
3671     priv->prepare_count--;
3672     g_rec_mutex_unlock (&priv->state_lock);
3673     GST_ERROR ("failed to prepare media");
3674     return FALSE;
3675   }
3676 preroll_failed:
3677   {
3678     GST_WARNING ("failed to preroll pipeline");
3679     gst_rtsp_media_unprepare (media);
3680     return FALSE;
3681   }
3682 }
3683
3684 /* must be called with state-lock */
3685 static void
3686 finish_unprepare (GstRTSPMedia * media)
3687 {
3688   GstRTSPMediaPrivate *priv = media->priv;
3689   gint i;
3690   GList *walk;
3691
3692   if (priv->finishing_unprepare)
3693     return;
3694   priv->finishing_unprepare = TRUE;
3695
3696   GST_DEBUG ("shutting down");
3697
3698   /* release the lock on shutdown, otherwise pad_added_cb might try to
3699    * acquire the lock and then we deadlock */
3700   g_rec_mutex_unlock (&priv->state_lock);
3701   set_state (media, GST_STATE_NULL);
3702   g_rec_mutex_lock (&priv->state_lock);
3703
3704   media_streams_set_blocked (media, FALSE);
3705
3706   for (i = 0; i < priv->streams->len; i++) {
3707     GstRTSPStream *stream;
3708
3709     GST_INFO ("Removing elements of stream %d from pipeline", i);
3710
3711     stream = g_ptr_array_index (priv->streams, i);
3712
3713     gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
3714
3715     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARING], 0, stream,
3716         i, NULL);
3717   }
3718
3719   /* remove the pad signal handlers */
3720   for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
3721     GstElement *elem = walk->data;
3722     DynPaySignalHandlers *handlers;
3723
3724     handlers =
3725         g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers");
3726     g_assert (handlers != NULL);
3727
3728     g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler);
3729     g_signal_handler_disconnect (G_OBJECT (elem),
3730         handlers->pad_removed_handler);
3731     g_signal_handler_disconnect (G_OBJECT (elem),
3732         handlers->no_more_pads_handler);
3733
3734     g_slice_free (DynPaySignalHandlers, handlers);
3735   }
3736
3737   gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
3738   priv->rtpbin = NULL;
3739
3740   if (priv->nettime)
3741     gst_object_unref (priv->nettime);
3742   priv->nettime = NULL;
3743
3744   priv->reused = TRUE;
3745   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED);
3746
3747   /* when the media is not reusable, this will effectively unref the media and
3748    * recreate it */
3749   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
3750
3751   /* the source has the last ref to the media */
3752   if (priv->source) {
3753     GST_DEBUG ("destroy source");
3754     g_source_destroy (priv->source);
3755     g_source_unref (priv->source);
3756   }
3757   if (priv->thread) {
3758     GST_DEBUG ("stop thread");
3759     gst_rtsp_thread_stop (priv->thread);
3760   }
3761
3762   priv->finishing_unprepare = FALSE;
3763 }
3764
3765 /* called with state-lock */
3766 static gboolean
3767 default_unprepare (GstRTSPMedia * media)
3768 {
3769   GstRTSPMediaPrivate *priv = media->priv;
3770
3771   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3772
3773   if (priv->eos_shutdown) {
3774     GST_DEBUG ("sending EOS for shutdown");
3775     /* ref so that we don't disappear */
3776     gst_element_send_event (priv->pipeline, gst_event_new_eos ());
3777     /* we need to go to playing again for the EOS to propagate, normally in this
3778      * state, nothing is receiving data from us anymore so this is ok. */
3779     set_state (media, GST_STATE_PLAYING);
3780   } else {
3781     finish_unprepare (media);
3782   }
3783   return TRUE;
3784 }
3785
3786 /**
3787  * gst_rtsp_media_unprepare:
3788  * @media: a #GstRTSPMedia
3789  *
3790  * Unprepare @media. After this call, the media should be prepared again before
3791  * it can be used again. If the media is set to be non-reusable, a new instance
3792  * must be created.
3793  *
3794  * Returns: %TRUE on success.
3795  */
3796 gboolean
3797 gst_rtsp_media_unprepare (GstRTSPMedia * media)
3798 {
3799   GstRTSPMediaPrivate *priv;
3800   gboolean success;
3801
3802   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3803
3804   priv = media->priv;
3805
3806   g_rec_mutex_lock (&priv->state_lock);
3807   if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
3808     goto was_unprepared;
3809
3810   priv->prepare_count--;
3811   if (priv->prepare_count > 0)
3812     goto is_busy;
3813
3814   GST_INFO ("unprepare media %p", media);
3815   set_target_state (media, GST_STATE_NULL, FALSE);
3816   success = TRUE;
3817
3818   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
3819     GstRTSPMediaClass *klass;
3820
3821     klass = GST_RTSP_MEDIA_GET_CLASS (media);
3822     if (klass->unprepare)
3823       success = klass->unprepare (media);
3824   } else {
3825     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING);
3826     finish_unprepare (media);
3827   }
3828   g_rec_mutex_unlock (&priv->state_lock);
3829
3830   return success;
3831
3832 was_unprepared:
3833   {
3834     g_rec_mutex_unlock (&priv->state_lock);
3835     GST_INFO ("media %p was already unprepared", media);
3836     return TRUE;
3837   }
3838 is_busy:
3839   {
3840     GST_INFO ("media %p still prepared %d times", media, priv->prepare_count);
3841     g_rec_mutex_unlock (&priv->state_lock);
3842     return TRUE;
3843   }
3844 }
3845
3846 /* should be called with state-lock */
3847 static GstClock *
3848 get_clock_unlocked (GstRTSPMedia * media)
3849 {
3850   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) {
3851     GST_DEBUG_OBJECT (media, "media was not prepared");
3852     return NULL;
3853   }
3854   return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline));
3855 }
3856
3857 /**
3858  * gst_rtsp_media_get_clock:
3859  * @media: a #GstRTSPMedia
3860  *
3861  * Get the clock that is used by the pipeline in @media.
3862  *
3863  * @media must be prepared before this method returns a valid clock object.
3864  *
3865  * Returns: (transfer full) (nullable): the #GstClock used by @media. unref after usage.
3866  */
3867 GstClock *
3868 gst_rtsp_media_get_clock (GstRTSPMedia * media)
3869 {
3870   GstClock *clock;
3871   GstRTSPMediaPrivate *priv;
3872
3873   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3874
3875   priv = media->priv;
3876
3877   g_rec_mutex_lock (&priv->state_lock);
3878   clock = get_clock_unlocked (media);
3879   g_rec_mutex_unlock (&priv->state_lock);
3880
3881   return clock;
3882 }
3883
3884 /**
3885  * gst_rtsp_media_get_base_time:
3886  * @media: a #GstRTSPMedia
3887  *
3888  * Get the base_time that is used by the pipeline in @media.
3889  *
3890  * @media must be prepared before this method returns a valid base_time.
3891  *
3892  * Returns: the base_time used by @media.
3893  */
3894 GstClockTime
3895 gst_rtsp_media_get_base_time (GstRTSPMedia * media)
3896 {
3897   GstClockTime result;
3898   GstRTSPMediaPrivate *priv;
3899
3900   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE);
3901
3902   priv = media->priv;
3903
3904   g_rec_mutex_lock (&priv->state_lock);
3905   if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
3906     goto not_prepared;
3907
3908   result = gst_element_get_base_time (media->priv->pipeline);
3909   g_rec_mutex_unlock (&priv->state_lock);
3910
3911   return result;
3912
3913   /* ERRORS */
3914 not_prepared:
3915   {
3916     g_rec_mutex_unlock (&priv->state_lock);
3917     GST_DEBUG_OBJECT (media, "media was not prepared");
3918     return GST_CLOCK_TIME_NONE;
3919   }
3920 }
3921
3922 /**
3923  * gst_rtsp_media_get_time_provider:
3924  * @media: a #GstRTSPMedia
3925  * @address: (allow-none): an address or %NULL
3926  * @port: a port or 0
3927  *
3928  * Get the #GstNetTimeProvider for the clock used by @media. The time provider
3929  * will listen on @address and @port for client time requests.
3930  *
3931  * Returns: (transfer full): the #GstNetTimeProvider of @media.
3932  */
3933 GstNetTimeProvider *
3934 gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
3935     guint16 port)
3936 {
3937   GstRTSPMediaPrivate *priv;
3938   GstNetTimeProvider *provider = NULL;
3939
3940   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
3941
3942   priv = media->priv;
3943
3944   g_rec_mutex_lock (&priv->state_lock);
3945   if (priv->time_provider) {
3946     if ((provider = priv->nettime) == NULL) {
3947       GstClock *clock;
3948
3949       if (priv->time_provider && (clock = get_clock_unlocked (media))) {
3950         provider = gst_net_time_provider_new (clock, address, port);
3951         gst_object_unref (clock);
3952
3953         priv->nettime = provider;
3954       }
3955     }
3956   }
3957   g_rec_mutex_unlock (&priv->state_lock);
3958
3959   if (provider)
3960     gst_object_ref (provider);
3961
3962   return provider;
3963 }
3964
3965 static gboolean
3966 default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
3967 {
3968   return gst_rtsp_sdp_from_media (sdp, info, media);
3969 }
3970
3971 /**
3972  * gst_rtsp_media_setup_sdp:
3973  * @media: a #GstRTSPMedia
3974  * @sdp: (transfer none): a #GstSDPMessage
3975  * @info: (transfer none): a #GstSDPInfo
3976  *
3977  * Add @media specific info to @sdp. @info is used to configure the connection
3978  * information in the SDP.
3979  *
3980  * Returns: TRUE on success.
3981  */
3982 gboolean
3983 gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
3984     GstSDPInfo * info)
3985 {
3986   GstRTSPMediaPrivate *priv;
3987   GstRTSPMediaClass *klass;
3988   gboolean res;
3989
3990   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
3991   g_return_val_if_fail (sdp != NULL, FALSE);
3992   g_return_val_if_fail (info != NULL, FALSE);
3993
3994   priv = media->priv;
3995
3996   g_rec_mutex_lock (&priv->state_lock);
3997
3998   klass = GST_RTSP_MEDIA_GET_CLASS (media);
3999
4000   if (!klass->setup_sdp)
4001     goto no_setup_sdp;
4002
4003   res = klass->setup_sdp (media, sdp, info);
4004
4005   g_rec_mutex_unlock (&priv->state_lock);
4006
4007   return res;
4008
4009   /* ERRORS */
4010 no_setup_sdp:
4011   {
4012     g_rec_mutex_unlock (&priv->state_lock);
4013     GST_ERROR ("no setup_sdp function");
4014     g_critical ("no setup_sdp vmethod function set");
4015     return FALSE;
4016   }
4017 }
4018
4019 static gboolean
4020 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4021 {
4022   GstRTSPMediaPrivate *priv = media->priv;
4023   gint i, medias_len;
4024
4025   medias_len = gst_sdp_message_medias_len (sdp);
4026   if (medias_len != priv->streams->len) {
4027     GST_ERROR ("%p: Media has more or less streams than SDP (%d /= %d)", media,
4028         priv->streams->len, medias_len);
4029     return FALSE;
4030   }
4031
4032   for (i = 0; i < medias_len; i++) {
4033     const gchar *proto;
4034     const GstSDPMedia *sdp_media = gst_sdp_message_get_media (sdp, i);
4035     GstRTSPStream *stream;
4036     gint j, formats_len;
4037     const gchar *control;
4038     GstRTSPProfile profile, profiles;
4039
4040     stream = g_ptr_array_index (priv->streams, i);
4041
4042     /* TODO: Should we do something with the other SDP information? */
4043
4044     /* get proto */
4045     proto = gst_sdp_media_get_proto (sdp_media);
4046     if (proto == NULL) {
4047       GST_ERROR ("%p: SDP media %d has no proto", media, i);
4048       return FALSE;
4049     }
4050
4051     if (g_str_equal (proto, "RTP/AVP")) {
4052       profile = GST_RTSP_PROFILE_AVP;
4053     } else if (g_str_equal (proto, "RTP/SAVP")) {
4054       profile = GST_RTSP_PROFILE_SAVP;
4055     } else if (g_str_equal (proto, "RTP/AVPF")) {
4056       profile = GST_RTSP_PROFILE_AVPF;
4057     } else if (g_str_equal (proto, "RTP/SAVPF")) {
4058       profile = GST_RTSP_PROFILE_SAVPF;
4059     } else {
4060       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4061       return FALSE;
4062     }
4063
4064     profiles = gst_rtsp_stream_get_profiles (stream);
4065     if ((profiles & profile) == 0) {
4066       GST_ERROR ("%p: unsupported profile '%s' for stream %d", media, proto, i);
4067       return FALSE;
4068     }
4069
4070     formats_len = gst_sdp_media_formats_len (sdp_media);
4071     for (j = 0; j < formats_len; j++) {
4072       gint pt;
4073       GstCaps *caps;
4074       GstStructure *s;
4075
4076       pt = atoi (gst_sdp_media_get_format (sdp_media, j));
4077
4078       GST_DEBUG (" looking at %d pt: %d", j, pt);
4079
4080       /* convert caps */
4081       caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
4082       if (caps == NULL) {
4083         GST_WARNING (" skipping pt %d without caps", pt);
4084         continue;
4085       }
4086
4087       /* do some tweaks */
4088       GST_DEBUG ("mapping sdp session level attributes to caps");
4089       gst_sdp_message_attributes_to_caps (sdp, caps);
4090       GST_DEBUG ("mapping sdp media level attributes to caps");
4091       gst_sdp_media_attributes_to_caps (sdp_media, caps);
4092
4093       s = gst_caps_get_structure (caps, 0);
4094       gst_structure_set_name (s, "application/x-rtp");
4095
4096       if (!g_strcmp0 (gst_structure_get_string (s, "encoding-name"), "ULPFEC"))
4097         gst_structure_set (s, "is-fec", G_TYPE_BOOLEAN, TRUE, NULL);
4098
4099       gst_rtsp_stream_set_pt_map (stream, pt, caps);
4100       gst_caps_unref (caps);
4101     }
4102
4103     control = gst_sdp_media_get_attribute_val (sdp_media, "control");
4104     if (control)
4105       gst_rtsp_stream_set_control (stream, control);
4106
4107   }
4108
4109   return TRUE;
4110 }
4111
4112 /**
4113  * gst_rtsp_media_handle_sdp:
4114  * @media: a #GstRTSPMedia
4115  * @sdp: (transfer none): a #GstSDPMessage
4116  *
4117  * Configure an SDP on @media for receiving streams
4118  *
4119  * Returns: TRUE on success.
4120  */
4121 gboolean
4122 gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
4123 {
4124   GstRTSPMediaPrivate *priv;
4125   GstRTSPMediaClass *klass;
4126   gboolean res;
4127
4128   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4129   g_return_val_if_fail (sdp != NULL, FALSE);
4130
4131   priv = media->priv;
4132
4133   g_rec_mutex_lock (&priv->state_lock);
4134
4135   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4136
4137   if (!klass->handle_sdp)
4138     goto no_handle_sdp;
4139
4140   res = klass->handle_sdp (media, sdp);
4141
4142   g_rec_mutex_unlock (&priv->state_lock);
4143
4144   return res;
4145
4146   /* ERRORS */
4147 no_handle_sdp:
4148   {
4149     g_rec_mutex_unlock (&priv->state_lock);
4150     GST_ERROR ("no handle_sdp function");
4151     g_critical ("no handle_sdp vmethod function set");
4152     return FALSE;
4153   }
4154 }
4155
4156 static void
4157 do_set_seqnum (GstRTSPStream * stream)
4158 {
4159   guint16 seq_num;
4160
4161   if (gst_rtsp_stream_is_sender (stream)) {
4162     seq_num = gst_rtsp_stream_get_current_seqnum (stream);
4163     gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
4164   }
4165 }
4166
4167 /* call with state_lock */
4168 static gboolean
4169 default_suspend (GstRTSPMedia * media)
4170 {
4171   GstRTSPMediaPrivate *priv = media->priv;
4172   GstStateChangeReturn ret;
4173
4174   switch (priv->suspend_mode) {
4175     case GST_RTSP_SUSPEND_MODE_NONE:
4176       GST_DEBUG ("media %p no suspend", media);
4177       break;
4178     case GST_RTSP_SUSPEND_MODE_PAUSE:
4179       GST_DEBUG ("media %p suspend to PAUSED", media);
4180       ret = set_target_state (media, GST_STATE_PAUSED, TRUE);
4181       if (ret == GST_STATE_CHANGE_FAILURE)
4182         goto state_failed;
4183       break;
4184     case GST_RTSP_SUSPEND_MODE_RESET:
4185       GST_DEBUG ("media %p suspend to NULL", media);
4186       ret = set_target_state (media, GST_STATE_NULL, TRUE);
4187       if (ret == GST_STATE_CHANGE_FAILURE)
4188         goto state_failed;
4189       /* Because payloader needs to set the sequence number as
4190        * monotonic, we need to preserve the sequence number
4191        * after pause. (otherwise going from pause to play,  which
4192        * is actually from NULL to PLAY will create a new sequence
4193        * number. */
4194       g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
4195       break;
4196     default:
4197       break;
4198   }
4199
4200   return TRUE;
4201
4202   /* ERRORS */
4203 state_failed:
4204   {
4205     GST_WARNING ("failed changing pipeline's state for media %p", media);
4206     return FALSE;
4207   }
4208 }
4209
4210 /**
4211  * gst_rtsp_media_suspend:
4212  * @media: a #GstRTSPMedia
4213  *
4214  * Suspend @media. The state of the pipeline managed by @media is set to
4215  * GST_STATE_NULL but all streams are kept. @media can be prepared again
4216  * with gst_rtsp_media_unsuspend()
4217  *
4218  * @media must be prepared with gst_rtsp_media_prepare();
4219  *
4220  * Returns: %TRUE on success.
4221  */
4222 gboolean
4223 gst_rtsp_media_suspend (GstRTSPMedia * media)
4224 {
4225   GstRTSPMediaPrivate *priv = media->priv;
4226   GstRTSPMediaClass *klass;
4227
4228   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4229
4230   GST_FIXME ("suspend for dynamic pipelines needs fixing");
4231
4232   g_rec_mutex_lock (&priv->state_lock);
4233   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
4234     goto not_prepared;
4235
4236   /* don't attempt to suspend when something is busy */
4237   if (priv->n_active > 0)
4238     goto done;
4239
4240   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4241   if (klass->suspend) {
4242     if (!klass->suspend (media))
4243       goto suspend_failed;
4244   }
4245
4246   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
4247 done:
4248   g_rec_mutex_unlock (&priv->state_lock);
4249
4250   return TRUE;
4251
4252   /* ERRORS */
4253 not_prepared:
4254   {
4255     g_rec_mutex_unlock (&priv->state_lock);
4256     GST_WARNING ("media %p was not prepared", media);
4257     return FALSE;
4258   }
4259 suspend_failed:
4260   {
4261     g_rec_mutex_unlock (&priv->state_lock);
4262     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4263     GST_WARNING ("failed to suspend media %p", media);
4264     return FALSE;
4265   }
4266 }
4267
4268 /* call with state_lock */
4269 static gboolean
4270 default_unsuspend (GstRTSPMedia * media)
4271 {
4272   GstRTSPMediaPrivate *priv = media->priv;
4273   gboolean preroll_ok;
4274
4275   switch (priv->suspend_mode) {
4276     case GST_RTSP_SUSPEND_MODE_NONE:
4277       if (gst_rtsp_media_is_receive_only (media))
4278         break;
4279       if (media_streams_blocking (media)) {
4280         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4281         /* at this point the media pipeline has been updated and contain all
4282          * specific transport parts: all active streams contain at least one sink
4283          * element and it's safe to unblock any blocked streams that are active */
4284         media_unblock_linked (media);
4285       } else {
4286         /* streams are not blocked and media is suspended from PAUSED */
4287         gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4288       }
4289       g_rec_mutex_unlock (&priv->state_lock);
4290       if (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_ERROR) {
4291         g_rec_mutex_lock (&priv->state_lock);
4292         goto preroll_failed;
4293       }
4294       g_rec_mutex_lock (&priv->state_lock);
4295       break;
4296     case GST_RTSP_SUSPEND_MODE_PAUSE:
4297       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
4298       break;
4299     case GST_RTSP_SUSPEND_MODE_RESET:
4300     {
4301       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
4302       /* at this point the media pipeline has been updated and contain all
4303        * specific transport parts: all active streams contain at least one sink
4304        * element and it's safe to unblock any blocked streams that are active */
4305       media_unblock_linked (media);
4306       if (!start_preroll (media))
4307         goto start_failed;
4308
4309       g_rec_mutex_unlock (&priv->state_lock);
4310       preroll_ok = wait_preroll (media);
4311       g_rec_mutex_lock (&priv->state_lock);
4312
4313       if (!preroll_ok)
4314         goto preroll_failed;
4315     }
4316     default:
4317       break;
4318   }
4319
4320   return TRUE;
4321
4322   /* ERRORS */
4323 start_failed:
4324   {
4325     GST_WARNING ("failed to preroll pipeline");
4326     return FALSE;
4327   }
4328 preroll_failed:
4329   {
4330     GST_WARNING ("failed to preroll pipeline");
4331     return FALSE;
4332   }
4333 }
4334
4335 /**
4336  * gst_rtsp_media_unsuspend:
4337  * @media: a #GstRTSPMedia
4338  *
4339  * Unsuspend @media if it was in a suspended state. This method does nothing
4340  * when the media was not in the suspended state.
4341  *
4342  * Returns: %TRUE on success.
4343  */
4344 gboolean
4345 gst_rtsp_media_unsuspend (GstRTSPMedia * media)
4346 {
4347   GstRTSPMediaPrivate *priv = media->priv;
4348   GstRTSPMediaClass *klass;
4349
4350   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4351
4352   g_rec_mutex_lock (&priv->state_lock);
4353   if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4354     goto done;
4355
4356   klass = GST_RTSP_MEDIA_GET_CLASS (media);
4357   if (klass->unsuspend) {
4358     if (!klass->unsuspend (media))
4359       goto unsuspend_failed;
4360   }
4361
4362 done:
4363   g_rec_mutex_unlock (&priv->state_lock);
4364
4365   return TRUE;
4366
4367   /* ERRORS */
4368 unsuspend_failed:
4369   {
4370     g_rec_mutex_unlock (&priv->state_lock);
4371     GST_WARNING ("failed to unsuspend media %p", media);
4372     gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
4373     return FALSE;
4374   }
4375 }
4376
4377 /* must be called with state-lock */
4378 static void
4379 media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
4380 {
4381   GstRTSPMediaPrivate *priv = media->priv;
4382
4383   if (state == GST_STATE_NULL) {
4384     gst_rtsp_media_unprepare (media);
4385   } else {
4386     GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
4387     set_target_state (media, state, FALSE);
4388     /* when we are buffering, don't update the state yet, this will be done
4389      * when buffering finishes */
4390     if (priv->buffering) {
4391       GST_INFO ("Buffering busy, delay state change");
4392     } else {
4393       if (state == GST_STATE_PLAYING)
4394         /* make sure pads are not blocking anymore when going to PLAYING */
4395         media_unblock_linked (media);
4396
4397       set_state (media, state);
4398
4399       /* and suspend after pause */
4400       if (state == GST_STATE_PAUSED)
4401         gst_rtsp_media_suspend (media);
4402     }
4403   }
4404 }
4405
4406 /**
4407  * gst_rtsp_media_set_pipeline_state:
4408  * @media: a #GstRTSPMedia
4409  * @state: the target state of the pipeline
4410  *
4411  * Set the state of the pipeline managed by @media to @state
4412  */
4413 void
4414 gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state)
4415 {
4416   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4417
4418   g_rec_mutex_lock (&media->priv->state_lock);
4419   media_set_pipeline_state_locked (media, state);
4420   g_rec_mutex_unlock (&media->priv->state_lock);
4421 }
4422
4423 /**
4424  * gst_rtsp_media_set_state:
4425  * @media: a #GstRTSPMedia
4426  * @state: the target state of the media
4427  * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport):
4428  * a #GPtrArray of #GstRTSPStreamTransport pointers
4429  *
4430  * Set the state of @media to @state and for the transports in @transports.
4431  *
4432  * @media must be prepared with gst_rtsp_media_prepare();
4433  *
4434  * Returns: %TRUE on success.
4435  */
4436 gboolean
4437 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
4438     GPtrArray * transports)
4439 {
4440   GstRTSPMediaPrivate *priv;
4441   gint i;
4442   gboolean activate, deactivate, do_state;
4443   gint old_active;
4444
4445   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4446   g_return_val_if_fail (transports != NULL, FALSE);
4447
4448   priv = media->priv;
4449
4450   g_rec_mutex_lock (&priv->state_lock);
4451
4452   if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING
4453       && gst_rtsp_media_is_shared (media)) {
4454     g_rec_mutex_unlock (&priv->state_lock);
4455     gst_rtsp_media_get_status (media);
4456     g_rec_mutex_lock (&priv->state_lock);
4457   }
4458   if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR)
4459     goto error_status;
4460   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
4461       priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
4462     goto not_prepared;
4463
4464   /* NULL and READY are the same */
4465   if (state == GST_STATE_READY)
4466     state = GST_STATE_NULL;
4467
4468   activate = deactivate = FALSE;
4469
4470   GST_INFO ("going to state %s media %p, target state %s",
4471       gst_element_state_get_name (state), media,
4472       gst_element_state_get_name (priv->target_state));
4473
4474   switch (state) {
4475     case GST_STATE_NULL:
4476       /* we're going from PLAYING or PAUSED to READY or NULL, deactivate */
4477       if (priv->target_state >= GST_STATE_PAUSED)
4478         deactivate = TRUE;
4479       break;
4480     case GST_STATE_PAUSED:
4481       /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
4482       if (priv->target_state == GST_STATE_PLAYING)
4483         deactivate = TRUE;
4484       break;
4485     case GST_STATE_PLAYING:
4486       /* we're going to PLAYING, activate */
4487       activate = TRUE;
4488       break;
4489     default:
4490       break;
4491   }
4492   old_active = priv->n_active;
4493
4494   GST_DEBUG ("%d transports, activate %d, deactivate %d", transports->len,
4495       activate, deactivate);
4496   for (i = 0; i < transports->len; i++) {
4497     GstRTSPStreamTransport *trans;
4498
4499     /* we need a non-NULL entry in the array */
4500     trans = g_ptr_array_index (transports, i);
4501     if (trans == NULL)
4502       continue;
4503
4504     if (activate) {
4505       if (gst_rtsp_stream_transport_set_active (trans, TRUE))
4506         priv->n_active++;
4507     } else if (deactivate) {
4508       if (gst_rtsp_stream_transport_set_active (trans, FALSE))
4509         priv->n_active--;
4510     }
4511   }
4512
4513   /* we just activated the first media, do the playing state change */
4514   if (old_active == 0 && activate)
4515     do_state = TRUE;
4516   /* if we have no more active media and prepare count is not indicate
4517    * that there are new session/sessions ongoing,
4518    * do the downward state changes */
4519   else if (priv->n_active == 0 && priv->prepare_count <= 1)
4520     do_state = TRUE;
4521   else
4522     do_state = FALSE;
4523
4524   GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
4525       media, do_state);
4526
4527   if (priv->target_state != state) {
4528     if (do_state) {
4529       media_set_pipeline_state_locked (media, state);
4530       g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
4531           NULL);
4532     }
4533   }
4534
4535   /* remember where we are */
4536   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
4537           old_active != priv->n_active)) {
4538     g_mutex_lock (&priv->lock);
4539     collect_media_stats (media);
4540     g_mutex_unlock (&priv->lock);
4541   }
4542   g_rec_mutex_unlock (&priv->state_lock);
4543
4544   return TRUE;
4545
4546   /* ERRORS */
4547 not_prepared:
4548   {
4549     GST_WARNING ("media %p was not prepared", media);
4550     g_rec_mutex_unlock (&priv->state_lock);
4551     return FALSE;
4552   }
4553 error_status:
4554   {
4555     GST_WARNING ("media %p in error status while changing to state %d",
4556         media, state);
4557     if (state == GST_STATE_NULL) {
4558       for (i = 0; i < transports->len; i++) {
4559         GstRTSPStreamTransport *trans;
4560
4561         /* we need a non-NULL entry in the array */
4562         trans = g_ptr_array_index (transports, i);
4563         if (trans == NULL)
4564           continue;
4565
4566         gst_rtsp_stream_transport_set_active (trans, FALSE);
4567       }
4568       priv->n_active = 0;
4569     }
4570     g_rec_mutex_unlock (&priv->state_lock);
4571     return FALSE;
4572   }
4573 }
4574
4575 /**
4576  * gst_rtsp_media_set_transport_mode:
4577  * @media: a #GstRTSPMedia
4578  * @mode: the new value
4579  *
4580  * Sets if the media pipeline can work in PLAY or RECORD mode
4581  */
4582 void
4583 gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
4584     GstRTSPTransportMode mode)
4585 {
4586   GstRTSPMediaPrivate *priv;
4587
4588   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
4589
4590   priv = media->priv;
4591
4592   g_mutex_lock (&priv->lock);
4593   priv->transport_mode = mode;
4594   g_mutex_unlock (&priv->lock);
4595 }
4596
4597 /**
4598  * gst_rtsp_media_get_transport_mode:
4599  * @media: a #GstRTSPMedia
4600  *
4601  * Check if the pipeline for @media can be used for PLAY or RECORD methods.
4602  *
4603  * Returns: The transport mode.
4604  */
4605 GstRTSPTransportMode
4606 gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
4607 {
4608   GstRTSPMediaPrivate *priv;
4609   GstRTSPTransportMode res;
4610
4611   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4612
4613   priv = media->priv;
4614
4615   g_mutex_lock (&priv->lock);
4616   res = priv->transport_mode;
4617   g_mutex_unlock (&priv->lock);
4618
4619   return res;
4620 }
4621
4622 /**
4623  * gst_rtsp_media_seekable:
4624  * @media: a #GstRTSPMedia
4625  *
4626  * Check if the pipeline for @media seek and up to what point in time,
4627  * it can seek.
4628  *
4629  * Returns: -1 if the stream is not seekable, 0 if seekable only to the beginning
4630  * and > 0 to indicate the longest duration between any two random access points.
4631  * %G_MAXINT64 means any value is possible.
4632  *
4633  * Since: 1.14
4634  */
4635 GstClockTimeDiff
4636 gst_rtsp_media_seekable (GstRTSPMedia * media)
4637 {
4638   GstRTSPMediaPrivate *priv;
4639   GstClockTimeDiff res;
4640
4641   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4642
4643   priv = media->priv;
4644
4645   /* Currently we are not able to seek on live streams,
4646    * and no stream is seekable only to the beginning */
4647   g_mutex_lock (&priv->lock);
4648   res = priv->seekable;
4649   g_mutex_unlock (&priv->lock);
4650
4651   return res;
4652 }
4653
4654 /**
4655  * gst_rtsp_media_complete_pipeline:
4656  * @media: a #GstRTSPMedia
4657  * @transports: (element-type GstRTSPTransport): a list of #GstRTSPTransport
4658  *
4659  * Add a receiver and sender parts to the pipeline based on the transport from
4660  * SETUP.
4661  *
4662  * Returns: %TRUE if the media pipeline has been sucessfully updated.
4663  *
4664  * Since: 1.14
4665  */
4666 gboolean
4667 gst_rtsp_media_complete_pipeline (GstRTSPMedia * media, GPtrArray * transports)
4668 {
4669   GstRTSPMediaPrivate *priv;
4670   guint i;
4671
4672   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
4673   g_return_val_if_fail (transports, FALSE);
4674
4675   GST_DEBUG_OBJECT (media, "complete pipeline");
4676
4677   priv = media->priv;
4678
4679   g_mutex_lock (&priv->lock);
4680   for (i = 0; i < priv->streams->len; i++) {
4681     GstRTSPStreamTransport *transport;
4682     GstRTSPStream *stream;
4683     const GstRTSPTransport *rtsp_transport;
4684
4685     transport = g_ptr_array_index (transports, i);
4686     if (!transport)
4687       continue;
4688
4689     stream = gst_rtsp_stream_transport_get_stream (transport);
4690     if (!stream)
4691       continue;
4692
4693     rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
4694
4695     if (!gst_rtsp_stream_complete_stream (stream, rtsp_transport)) {
4696       g_mutex_unlock (&priv->lock);
4697       return FALSE;
4698     }
4699   }
4700
4701   priv->complete = TRUE;
4702   g_mutex_unlock (&priv->lock);
4703
4704   return TRUE;
4705 }
4706
4707 gboolean
4708 gst_rtsp_media_is_receive_only (GstRTSPMedia * media)
4709 {
4710   GstRTSPMediaPrivate *priv = media->priv;
4711   gboolean receive_only;
4712
4713   g_mutex_lock (&priv->lock);
4714   receive_only = is_receive_only (media);
4715   g_mutex_unlock (&priv->lock);
4716
4717   return receive_only;
4718 }
4719
4720 GstElement *
4721 gst_rtsp_media_get_pipeline (GstRTSPMedia * media)
4722 {
4723   GstRTSPMediaPrivate *priv;
4724
4725   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4726
4727   priv = media->priv;
4728
4729   g_mutex_lock (&priv->lock);
4730   g_object_ref (priv->pipeline);
4731   g_mutex_unlock (&priv->lock);
4732
4733   return priv->pipeline;
4734 }
4735
4736
4737 GstElement *
4738 gst_rtsp_media_get_rtpbin (GstRTSPMedia * media)
4739 {
4740   GstRTSPMediaPrivate *priv;
4741
4742   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
4743
4744   priv = media->priv;
4745
4746   g_mutex_lock (&priv->lock);
4747   g_object_ref (priv->rtpbin);
4748   g_mutex_unlock (&priv->lock);
4749
4750   return priv->rtpbin;
4751 }