Add new API for setting/getting maximum multicast ttl value
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media-factory.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-factory
23  * @short_description: A factory for media pipelines
24  * @see_also: #GstRTSPMountPoints, #GstRTSPMedia
25  *
26  * The #GstRTSPMediaFactory is responsible for creating or recycling
27  * #GstRTSPMedia objects based on the passed URL.
28  *
29  * The default implementation of the object can create #GstRTSPMedia objects
30  * containing a pipeline created from a launch description set with
31  * gst_rtsp_media_factory_set_launch().
32  *
33  * Media from a factory can be shared by setting the shared flag with
34  * gst_rtsp_media_factory_set_shared(). When a factory is shared,
35  * gst_rtsp_media_factory_construct() will return the same #GstRTSPMedia when
36  * the url matches.
37  *
38  * Last reviewed on 2013-07-11 (1.0.0)
39  */
40
41 #include "rtsp-media-factory.h"
42
43 #define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock))
44 #define GST_RTSP_MEDIA_FACTORY_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
45 #define GST_RTSP_MEDIA_FACTORY_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
46
47 struct _GstRTSPMediaFactoryPrivate
48 {
49   GMutex lock;                  /* protects everything but medias */
50   GstRTSPPermissions *permissions;
51   gchar *launch;
52   gboolean shared;
53   GstRTSPSuspendMode suspend_mode;
54   gboolean eos_shutdown;
55   GstRTSPProfile profiles;
56   GstRTSPLowerTrans protocols;
57   guint buffer_size;
58   GstRTSPAddressPool *pool;
59   GstRTSPTransportMode transport_mode;
60   gboolean stop_on_disconnect;
61   gchar *multicast_iface;
62   guint max_mcast_ttl;
63
64   GstClockTime rtx_time;
65   guint latency;
66   gboolean do_retransmission;
67
68   GMutex medias_lock;
69   GHashTable *medias;           /* protected by medias_lock */
70
71   GType media_gtype;
72
73   GstClock *clock;
74
75   GstRTSPPublishClockMode publish_clock_mode;
76 };
77
78 #define DEFAULT_LAUNCH          NULL
79 #define DEFAULT_SHARED          FALSE
80 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
81 #define DEFAULT_EOS_SHUTDOWN    FALSE
82 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
83 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
84                                         GST_RTSP_LOWER_TRANS_TCP
85 #define DEFAULT_BUFFER_SIZE     0x80000
86 #define DEFAULT_LATENCY         200
87 #define DEFAULT_MAX_MCAST_TTL   255
88 #define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
89 #define DEFAULT_STOP_ON_DISCONNECT TRUE
90 #define DEFAULT_DO_RETRANSMISSION FALSE
91
92 enum
93 {
94   PROP_0,
95   PROP_LAUNCH,
96   PROP_SHARED,
97   PROP_SUSPEND_MODE,
98   PROP_EOS_SHUTDOWN,
99   PROP_PROFILES,
100   PROP_PROTOCOLS,
101   PROP_BUFFER_SIZE,
102   PROP_LATENCY,
103   PROP_TRANSPORT_MODE,
104   PROP_STOP_ON_DISCONNECT,
105   PROP_CLOCK,
106   PROP_MAX_MCAST_TTL,
107   PROP_LAST
108 };
109
110 enum
111 {
112   SIGNAL_MEDIA_CONSTRUCTED,
113   SIGNAL_MEDIA_CONFIGURE,
114   SIGNAL_LAST
115 };
116
117 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
118 #define GST_CAT_DEFAULT rtsp_media_debug
119
120 static guint gst_rtsp_media_factory_signals[SIGNAL_LAST] = { 0 };
121
122 static void gst_rtsp_media_factory_get_property (GObject * object, guint propid,
123     GValue * value, GParamSpec * pspec);
124 static void gst_rtsp_media_factory_set_property (GObject * object, guint propid,
125     const GValue * value, GParamSpec * pspec);
126 static void gst_rtsp_media_factory_finalize (GObject * obj);
127
128 static gchar *default_gen_key (GstRTSPMediaFactory * factory,
129     const GstRTSPUrl * url);
130 static GstElement *default_create_element (GstRTSPMediaFactory * factory,
131     const GstRTSPUrl * url);
132 static GstRTSPMedia *default_construct (GstRTSPMediaFactory * factory,
133     const GstRTSPUrl * url);
134 static void default_configure (GstRTSPMediaFactory * factory,
135     GstRTSPMedia * media);
136 static GstElement *default_create_pipeline (GstRTSPMediaFactory * factory,
137     GstRTSPMedia * media);
138
139 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPMediaFactory, gst_rtsp_media_factory,
140     G_TYPE_OBJECT);
141
142 static void
143 gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
144 {
145   GObjectClass *gobject_class;
146
147   gobject_class = G_OBJECT_CLASS (klass);
148
149   gobject_class->get_property = gst_rtsp_media_factory_get_property;
150   gobject_class->set_property = gst_rtsp_media_factory_set_property;
151   gobject_class->finalize = gst_rtsp_media_factory_finalize;
152
153   /**
154    * GstRTSPMediaFactory::launch:
155    *
156    * The gst_parse_launch() line to use for constructing the pipeline in the
157    * default prepare vmethod.
158    *
159    * The pipeline description should return a GstBin as the toplevel element
160    * which can be accomplished by enclosing the description with brackets '('
161    * ')'.
162    *
163    * The description should return a pipeline with payloaders named pay0, pay1,
164    * etc.. Each of the payloaders will result in a stream.
165    *
166    * Support for dynamic payloaders can be accomplished by adding payloaders
167    * named dynpay0, dynpay1, etc..
168    */
169   g_object_class_install_property (gobject_class, PROP_LAUNCH,
170       g_param_spec_string ("launch", "Launch",
171           "A launch description of the pipeline", DEFAULT_LAUNCH,
172           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173
174   g_object_class_install_property (gobject_class, PROP_SHARED,
175       g_param_spec_boolean ("shared", "Shared",
176           "If media from this factory is shared", DEFAULT_SHARED,
177           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
178
179   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
180       g_param_spec_enum ("suspend-mode", "Suspend Mode",
181           "Control how media will be suspended", GST_TYPE_RTSP_SUSPEND_MODE,
182           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
183
184   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
185       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
186           "Send EOS down the pipeline before shutting down",
187           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188
189   g_object_class_install_property (gobject_class, PROP_PROFILES,
190       g_param_spec_flags ("profiles", "Profiles",
191           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
192           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193
194   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
195       g_param_spec_flags ("protocols", "Protocols",
196           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
197           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198
199   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
200       g_param_spec_uint ("buffer-size", "Buffer Size",
201           "The kernel UDP buffer size to use", 0, G_MAXUINT,
202           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
203
204   g_object_class_install_property (gobject_class, PROP_LATENCY,
205       g_param_spec_uint ("latency", "Latency",
206           "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
207           DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
208
209   g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
210       g_param_spec_flags ("transport-mode", "Transport Mode",
211           "If media from this factory is for PLAY or RECORD",
212           GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
213           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
214
215   g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
216       g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
217           "If media from this factory should be stopped "
218           "when a client disconnects without TEARDOWN",
219           DEFAULT_STOP_ON_DISCONNECT,
220           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
221
222   g_object_class_install_property (gobject_class, PROP_CLOCK,
223       g_param_spec_object ("clock", "Clock",
224           "Clock to be used by the pipelines created for all "
225           "medias of this factory", GST_TYPE_CLOCK,
226           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
227
228   g_object_class_install_property (gobject_class, PROP_MAX_MCAST_TTL,
229       g_param_spec_uint ("max-mcast-ttl", "Maximum multicast ttl",
230           "The maximum time-to-live value of outgoing multicast packets", 1,
231           255, DEFAULT_MAX_MCAST_TTL,
232           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233
234   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] =
235       g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass),
236       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
237           media_constructed), NULL, NULL, g_cclosure_marshal_generic,
238       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
239
240   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE] =
241       g_signal_new ("media-configure", G_TYPE_FROM_CLASS (klass),
242       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
243           media_configure), NULL, NULL, g_cclosure_marshal_generic,
244       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
245
246   klass->gen_key = default_gen_key;
247   klass->create_element = default_create_element;
248   klass->construct = default_construct;
249   klass->configure = default_configure;
250   klass->create_pipeline = default_create_pipeline;
251
252   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmediafactory", 0,
253       "GstRTSPMediaFactory");
254 }
255
256 static void
257 gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
258 {
259   GstRTSPMediaFactoryPrivate *priv =
260       gst_rtsp_media_factory_get_instance_private (factory);
261   factory->priv = priv;
262
263   priv->launch = g_strdup (DEFAULT_LAUNCH);
264   priv->shared = DEFAULT_SHARED;
265   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
266   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
267   priv->profiles = DEFAULT_PROFILES;
268   priv->protocols = DEFAULT_PROTOCOLS;
269   priv->buffer_size = DEFAULT_BUFFER_SIZE;
270   priv->latency = DEFAULT_LATENCY;
271   priv->transport_mode = DEFAULT_TRANSPORT_MODE;
272   priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
273   priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
274   priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
275   priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
276
277   g_mutex_init (&priv->lock);
278   g_mutex_init (&priv->medias_lock);
279   priv->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
280       g_free, g_object_unref);
281   priv->media_gtype = GST_TYPE_RTSP_MEDIA;
282 }
283
284 static void
285 gst_rtsp_media_factory_finalize (GObject * obj)
286 {
287   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
288   GstRTSPMediaFactoryPrivate *priv = factory->priv;
289
290   if (priv->clock)
291     gst_object_unref (priv->clock);
292   if (priv->permissions)
293     gst_rtsp_permissions_unref (priv->permissions);
294   g_hash_table_unref (priv->medias);
295   g_mutex_clear (&priv->medias_lock);
296   g_free (priv->launch);
297   g_mutex_clear (&priv->lock);
298   if (priv->pool)
299     g_object_unref (priv->pool);
300   g_free (priv->multicast_iface);
301
302   G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
303 }
304
305 static void
306 gst_rtsp_media_factory_get_property (GObject * object, guint propid,
307     GValue * value, GParamSpec * pspec)
308 {
309   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
310
311   switch (propid) {
312     case PROP_LAUNCH:
313       g_value_take_string (value, gst_rtsp_media_factory_get_launch (factory));
314       break;
315     case PROP_SHARED:
316       g_value_set_boolean (value, gst_rtsp_media_factory_is_shared (factory));
317       break;
318     case PROP_SUSPEND_MODE:
319       g_value_set_enum (value,
320           gst_rtsp_media_factory_get_suspend_mode (factory));
321       break;
322     case PROP_EOS_SHUTDOWN:
323       g_value_set_boolean (value,
324           gst_rtsp_media_factory_is_eos_shutdown (factory));
325       break;
326     case PROP_PROFILES:
327       g_value_set_flags (value, gst_rtsp_media_factory_get_profiles (factory));
328       break;
329     case PROP_PROTOCOLS:
330       g_value_set_flags (value, gst_rtsp_media_factory_get_protocols (factory));
331       break;
332     case PROP_BUFFER_SIZE:
333       g_value_set_uint (value,
334           gst_rtsp_media_factory_get_buffer_size (factory));
335       break;
336     case PROP_LATENCY:
337       g_value_set_uint (value, gst_rtsp_media_factory_get_latency (factory));
338       break;
339     case PROP_TRANSPORT_MODE:
340       g_value_set_flags (value,
341           gst_rtsp_media_factory_get_transport_mode (factory));
342       break;
343     case PROP_STOP_ON_DISCONNECT:
344       g_value_set_boolean (value,
345           gst_rtsp_media_factory_is_stop_on_disonnect (factory));
346       break;
347     case PROP_CLOCK:
348       g_value_take_object (value, gst_rtsp_media_factory_get_clock (factory));
349       break;
350     case PROP_MAX_MCAST_TTL:
351       g_value_set_uint (value,
352           gst_rtsp_media_factory_get_max_mcast_ttl (factory));
353     default:
354       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
355   }
356 }
357
358 static void
359 gst_rtsp_media_factory_set_property (GObject * object, guint propid,
360     const GValue * value, GParamSpec * pspec)
361 {
362   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
363
364   switch (propid) {
365     case PROP_LAUNCH:
366       gst_rtsp_media_factory_set_launch (factory, g_value_get_string (value));
367       break;
368     case PROP_SHARED:
369       gst_rtsp_media_factory_set_shared (factory, g_value_get_boolean (value));
370       break;
371     case PROP_SUSPEND_MODE:
372       gst_rtsp_media_factory_set_suspend_mode (factory,
373           g_value_get_enum (value));
374       break;
375     case PROP_EOS_SHUTDOWN:
376       gst_rtsp_media_factory_set_eos_shutdown (factory,
377           g_value_get_boolean (value));
378       break;
379     case PROP_PROFILES:
380       gst_rtsp_media_factory_set_profiles (factory, g_value_get_flags (value));
381       break;
382     case PROP_PROTOCOLS:
383       gst_rtsp_media_factory_set_protocols (factory, g_value_get_flags (value));
384       break;
385     case PROP_BUFFER_SIZE:
386       gst_rtsp_media_factory_set_buffer_size (factory,
387           g_value_get_uint (value));
388       break;
389     case PROP_LATENCY:
390       gst_rtsp_media_factory_set_latency (factory, g_value_get_uint (value));
391       break;
392     case PROP_TRANSPORT_MODE:
393       gst_rtsp_media_factory_set_transport_mode (factory,
394           g_value_get_flags (value));
395       break;
396     case PROP_STOP_ON_DISCONNECT:
397       gst_rtsp_media_factory_set_stop_on_disconnect (factory,
398           g_value_get_boolean (value));
399       break;
400     case PROP_CLOCK:
401       gst_rtsp_media_factory_set_clock (factory, g_value_get_object (value));
402       break;
403     case PROP_MAX_MCAST_TTL:
404       gst_rtsp_media_factory_set_max_mcast_ttl (factory,
405           g_value_get_uint (value));
406     default:
407       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
408   }
409 }
410
411 /**
412  * gst_rtsp_media_factory_new:
413  *
414  * Create a new #GstRTSPMediaFactory instance.
415  *
416  * Returns: (transfer full): a new #GstRTSPMediaFactory object.
417  */
418 GstRTSPMediaFactory *
419 gst_rtsp_media_factory_new (void)
420 {
421   GstRTSPMediaFactory *result;
422
423   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY, NULL);
424
425   return result;
426 }
427
428 /**
429  * gst_rtsp_media_factory_set_permissions:
430  * @factory: a #GstRTSPMediaFactory
431  * @permissions: (transfer none) (nullable): a #GstRTSPPermissions
432  *
433  * Set @permissions on @factory.
434  */
435 void
436 gst_rtsp_media_factory_set_permissions (GstRTSPMediaFactory * factory,
437     GstRTSPPermissions * permissions)
438 {
439   GstRTSPMediaFactoryPrivate *priv;
440
441   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
442
443   priv = factory->priv;
444
445   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
446   if (priv->permissions)
447     gst_rtsp_permissions_unref (priv->permissions);
448   if ((priv->permissions = permissions))
449     gst_rtsp_permissions_ref (permissions);
450   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
451 }
452
453 /**
454  * gst_rtsp_media_factory_get_permissions:
455  * @factory: a #GstRTSPMediaFactory
456  *
457  * Get the permissions object from @factory.
458  *
459  * Returns: (transfer full) (nullable): a #GstRTSPPermissions object, unref after usage.
460  */
461 GstRTSPPermissions *
462 gst_rtsp_media_factory_get_permissions (GstRTSPMediaFactory * factory)
463 {
464   GstRTSPMediaFactoryPrivate *priv;
465   GstRTSPPermissions *result;
466
467   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
468
469   priv = factory->priv;
470
471   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
472   if ((result = priv->permissions))
473     gst_rtsp_permissions_ref (result);
474   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
475
476   return result;
477 }
478
479 /**
480  * gst_rtsp_media_factory_add_role:
481  * @factory: a #GstRTSPMediaFactory
482  * @role: a role
483  * @fieldname: the first field name
484  * @...: additional arguments
485  *
486  * A convenience method to add @role with @fieldname and additional arguments to
487  * the permissions of @factory. If @factory had no permissions, new permissions
488  * will be created and the role will be added to it.
489  */
490 void
491 gst_rtsp_media_factory_add_role (GstRTSPMediaFactory * factory,
492     const gchar * role, const gchar * fieldname, ...)
493 {
494   GstRTSPMediaFactoryPrivate *priv;
495   va_list var_args;
496
497   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
498   g_return_if_fail (role != NULL);
499   g_return_if_fail (fieldname != NULL);
500
501   priv = factory->priv;
502
503   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
504   if (priv->permissions == NULL)
505     priv->permissions = gst_rtsp_permissions_new ();
506
507   va_start (var_args, fieldname);
508   gst_rtsp_permissions_add_role_valist (priv->permissions, role, fieldname,
509       var_args);
510   va_end (var_args);
511   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
512 }
513
514 /**
515  * gst_rtsp_media_factory_add_role_from_structure:
516  *
517  * A convenience wrapper around gst_rtsp_permissions_add_role_from_structure().
518  * If @factory had no permissions, new permissions will be created and the
519  * role will be added to it.
520  *
521  * Since: 1.14
522  */
523 void
524 gst_rtsp_media_factory_add_role_from_structure (GstRTSPMediaFactory * factory,
525     GstStructure * structure)
526 {
527   GstRTSPMediaFactoryPrivate *priv;
528   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
529   g_return_if_fail (GST_IS_STRUCTURE (structure));
530
531   priv = factory->priv;
532
533   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
534   if (priv->permissions == NULL)
535     priv->permissions = gst_rtsp_permissions_new ();
536
537   gst_rtsp_permissions_add_role_from_structure (priv->permissions, structure);
538   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
539 }
540
541 /**
542  * gst_rtsp_media_factory_set_launch:
543  * @factory: a #GstRTSPMediaFactory
544  * @launch: the launch description
545  *
546  *
547  * The gst_parse_launch() line to use for constructing the pipeline in the
548  * default prepare vmethod.
549  *
550  * The pipeline description should return a GstBin as the toplevel element
551  * which can be accomplished by enclosing the description with brackets '('
552  * ')'.
553  *
554  * The description should return a pipeline with payloaders named pay0, pay1,
555  * etc.. Each of the payloaders will result in a stream.
556  */
557 void
558 gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
559     const gchar * launch)
560 {
561   GstRTSPMediaFactoryPrivate *priv;
562
563   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
564   g_return_if_fail (launch != NULL);
565
566   priv = factory->priv;
567
568   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
569   g_free (priv->launch);
570   priv->launch = g_strdup (launch);
571   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
572 }
573
574 /**
575  * gst_rtsp_media_factory_get_launch:
576  * @factory: a #GstRTSPMediaFactory
577  *
578  * Get the gst_parse_launch() pipeline description that will be used in the
579  * default prepare vmethod.
580  *
581  * Returns: (transfer full) (nullable): the configured launch description. g_free() after
582  * usage.
583  */
584 gchar *
585 gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory)
586 {
587   GstRTSPMediaFactoryPrivate *priv;
588   gchar *result;
589
590   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
591
592   priv = factory->priv;
593
594   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
595   result = g_strdup (priv->launch);
596   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
597
598   return result;
599 }
600
601 /**
602  * gst_rtsp_media_factory_set_suspend_mode:
603  * @factory: a #GstRTSPMediaFactory
604  * @mode: the new #GstRTSPSuspendMode
605  *
606  * Configure how media created from this factory will be suspended.
607  */
608 void
609 gst_rtsp_media_factory_set_suspend_mode (GstRTSPMediaFactory * factory,
610     GstRTSPSuspendMode mode)
611 {
612   GstRTSPMediaFactoryPrivate *priv;
613
614   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
615
616   priv = factory->priv;
617
618   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
619   priv->suspend_mode = mode;
620   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
621 }
622
623 /**
624  * gst_rtsp_media_factory_get_suspend_mode:
625  * @factory: a #GstRTSPMediaFactory
626  *
627  * Get how media created from this factory will be suspended.
628  *
629  * Returns: a #GstRTSPSuspendMode.
630  */
631 GstRTSPSuspendMode
632 gst_rtsp_media_factory_get_suspend_mode (GstRTSPMediaFactory * factory)
633 {
634   GstRTSPMediaFactoryPrivate *priv;
635   GstRTSPSuspendMode result;
636
637   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
638       GST_RTSP_SUSPEND_MODE_NONE);
639
640   priv = factory->priv;
641
642   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
643   result = priv->suspend_mode;
644   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
645
646   return result;
647 }
648
649 /**
650  * gst_rtsp_media_factory_set_shared:
651  * @factory: a #GstRTSPMediaFactory
652  * @shared: the new value
653  *
654  * Configure if media created from this factory can be shared between clients.
655  */
656 void
657 gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
658     gboolean shared)
659 {
660   GstRTSPMediaFactoryPrivate *priv;
661
662   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
663
664   priv = factory->priv;
665
666   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
667   priv->shared = shared;
668   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
669 }
670
671 /**
672  * gst_rtsp_media_factory_is_shared:
673  * @factory: a #GstRTSPMediaFactory
674  *
675  * Get if media created from this factory can be shared between clients.
676  *
677  * Returns: %TRUE if the media will be shared between clients.
678  */
679 gboolean
680 gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory)
681 {
682   GstRTSPMediaFactoryPrivate *priv;
683   gboolean result;
684
685   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
686
687   priv = factory->priv;
688
689   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
690   result = priv->shared;
691   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
692
693   return result;
694 }
695
696 /**
697  * gst_rtsp_media_factory_set_eos_shutdown:
698  * @factory: a #GstRTSPMediaFactory
699  * @eos_shutdown: the new value
700  *
701  * Configure if media created from this factory will have an EOS sent to the
702  * pipeline before shutdown.
703  */
704 void
705 gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
706     gboolean eos_shutdown)
707 {
708   GstRTSPMediaFactoryPrivate *priv;
709
710   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
711
712   priv = factory->priv;
713
714   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
715   priv->eos_shutdown = eos_shutdown;
716   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
717 }
718
719 /**
720  * gst_rtsp_media_factory_is_eos_shutdown:
721  * @factory: a #GstRTSPMediaFactory
722  *
723  * Get if media created from this factory will have an EOS event sent to the
724  * pipeline before shutdown.
725  *
726  * Returns: %TRUE if the media will receive EOS before shutdown.
727  */
728 gboolean
729 gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory)
730 {
731   GstRTSPMediaFactoryPrivate *priv;
732   gboolean result;
733
734   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
735
736   priv = factory->priv;
737
738   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
739   result = priv->eos_shutdown;
740   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
741
742   return result;
743 }
744
745 /**
746  * gst_rtsp_media_factory_set_buffer_size:
747  * @factory: a #GstRTSPMedia
748  * @size: the new value
749  *
750  * Set the kernel UDP buffer size.
751  */
752 void
753 gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
754     guint size)
755 {
756   GstRTSPMediaFactoryPrivate *priv;
757
758   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
759
760   priv = factory->priv;
761
762   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
763   priv->buffer_size = size;
764   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
765 }
766
767 /**
768  * gst_rtsp_media_factory_get_buffer_size:
769  * @factory: a #GstRTSPMedia
770  *
771  * Get the kernel UDP buffer size.
772  *
773  * Returns: the kernel UDP buffer size.
774  */
775 guint
776 gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
777 {
778   GstRTSPMediaFactoryPrivate *priv;
779   guint result;
780
781   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
782
783   priv = factory->priv;
784
785   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
786   result = priv->buffer_size;
787   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
788
789   return result;
790 }
791
792 /**
793  * gst_rtsp_media_factory_set_address_pool:
794  * @factory: a #GstRTSPMediaFactory
795  * @pool: (transfer none) (nullable): a #GstRTSPAddressPool
796  *
797  * configure @pool to be used as the address pool of @factory.
798  */
799 void
800 gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
801     GstRTSPAddressPool * pool)
802 {
803   GstRTSPMediaFactoryPrivate *priv;
804   GstRTSPAddressPool *old;
805
806   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
807
808   priv = factory->priv;
809
810   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
811   if ((old = priv->pool) != pool)
812     priv->pool = pool ? g_object_ref (pool) : NULL;
813   else
814     old = NULL;
815   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
816
817   if (old)
818     g_object_unref (old);
819 }
820
821 /**
822  * gst_rtsp_media_factory_get_address_pool:
823  * @factory: a #GstRTSPMediaFactory
824  *
825  * Get the #GstRTSPAddressPool used as the address pool of @factory.
826  *
827  * Returns: (transfer full) (nullable): the #GstRTSPAddressPool of @factory. g_object_unref() after
828  * usage.
829  */
830 GstRTSPAddressPool *
831 gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory)
832 {
833   GstRTSPMediaFactoryPrivate *priv;
834   GstRTSPAddressPool *result;
835
836   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
837
838   priv = factory->priv;
839
840   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
841   if ((result = priv->pool))
842     g_object_ref (result);
843   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
844
845   return result;
846 }
847
848 /**
849  * gst_rtsp_media_factory_set_multicast_iface:
850  * @factory: a #GstRTSPMediaFactory
851  * @multicast_iface: (transfer none) (nullable): a multicast interface name
852  *
853  * configure @multicast_iface to be used for @factory.
854  */
855 void
856 gst_rtsp_media_factory_set_multicast_iface (GstRTSPMediaFactory * media_factory,
857     const gchar * multicast_iface)
858 {
859   GstRTSPMediaFactoryPrivate *priv;
860   gchar *old;
861
862   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (media_factory));
863
864   priv = media_factory->priv;
865
866   GST_LOG_OBJECT (media_factory, "set multicast interface %s", multicast_iface);
867
868   g_mutex_lock (&priv->lock);
869   if ((old = priv->multicast_iface) != multicast_iface)
870     priv->multicast_iface = multicast_iface ? g_strdup (multicast_iface) : NULL;
871   else
872     old = NULL;
873   g_mutex_unlock (&priv->lock);
874
875   if (old)
876     g_free (old);
877 }
878
879 /**
880  * gst_rtsp_media_factory_get_multicast_iface:
881  * @factory: a #GstRTSPMediaFactory
882  *
883  * Get the multicast interface used for @factory.
884  *
885  * Returns: (transfer full) (nullable): the multicast interface for @factory. g_free() after
886  * usage.
887  */
888 gchar *
889 gst_rtsp_media_factory_get_multicast_iface (GstRTSPMediaFactory * media_factory)
890 {
891   GstRTSPMediaFactoryPrivate *priv;
892   gchar *result;
893
894   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (media_factory), NULL);
895
896   priv = media_factory->priv;
897
898   g_mutex_lock (&priv->lock);
899   if ((result = priv->multicast_iface))
900     result = g_strdup (result);
901   g_mutex_unlock (&priv->lock);
902
903   return result;
904 }
905
906 /**
907  * gst_rtsp_media_factory_set_profiles:
908  * @factory: a #GstRTSPMediaFactory
909  * @profiles: the new flags
910  *
911  * Configure the allowed profiles for @factory.
912  */
913 void
914 gst_rtsp_media_factory_set_profiles (GstRTSPMediaFactory * factory,
915     GstRTSPProfile profiles)
916 {
917   GstRTSPMediaFactoryPrivate *priv;
918
919   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
920
921   priv = factory->priv;
922
923   GST_DEBUG_OBJECT (factory, "profiles %d", profiles);
924
925   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
926   priv->profiles = profiles;
927   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
928 }
929
930 /**
931  * gst_rtsp_media_factory_get_profiles:
932  * @factory: a #GstRTSPMediaFactory
933  *
934  * Get the allowed profiles of @factory.
935  *
936  * Returns: a #GstRTSPProfile
937  */
938 GstRTSPProfile
939 gst_rtsp_media_factory_get_profiles (GstRTSPMediaFactory * factory)
940 {
941   GstRTSPMediaFactoryPrivate *priv;
942   GstRTSPProfile res;
943
944   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
945       GST_RTSP_PROFILE_UNKNOWN);
946
947   priv = factory->priv;
948
949   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
950   res = priv->profiles;
951   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
952
953   return res;
954 }
955
956 /**
957  * gst_rtsp_media_factory_set_protocols:
958  * @factory: a #GstRTSPMediaFactory
959  * @protocols: the new flags
960  *
961  * Configure the allowed lower transport for @factory.
962  */
963 void
964 gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
965     GstRTSPLowerTrans protocols)
966 {
967   GstRTSPMediaFactoryPrivate *priv;
968
969   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
970
971   priv = factory->priv;
972
973   GST_DEBUG_OBJECT (factory, "protocols %d", protocols);
974
975   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
976   priv->protocols = protocols;
977   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
978 }
979
980 /**
981  * gst_rtsp_media_factory_get_protocols:
982  * @factory: a #GstRTSPMediaFactory
983  *
984  * Get the allowed protocols of @factory.
985  *
986  * Returns: a #GstRTSPLowerTrans
987  */
988 GstRTSPLowerTrans
989 gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
990 {
991   GstRTSPMediaFactoryPrivate *priv;
992   GstRTSPLowerTrans res;
993
994   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
995       GST_RTSP_LOWER_TRANS_UNKNOWN);
996
997   priv = factory->priv;
998
999   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1000   res = priv->protocols;
1001   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1002
1003   return res;
1004 }
1005
1006 /**
1007  * gst_rtsp_media_factory_set_stop_on_disconnect:
1008  * @factory: a #GstRTSPMediaFactory
1009  * @stop_on_disconnect: the new value
1010  *
1011  * Configure if media created from this factory should be stopped
1012  * when a client disconnects without sending TEARDOWN.
1013  */
1014 void
1015 gst_rtsp_media_factory_set_stop_on_disconnect (GstRTSPMediaFactory * factory,
1016     gboolean stop_on_disconnect)
1017 {
1018   GstRTSPMediaFactoryPrivate *priv;
1019
1020   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1021
1022   priv = factory->priv;
1023
1024   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1025   priv->stop_on_disconnect = stop_on_disconnect;
1026   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1027 }
1028
1029 /**
1030  * gst_rtsp_media_factory_is_stop_on_disconnect:
1031  * @factory: a #GstRTSPMediaFactory
1032  *
1033  * Get if media created from this factory should be stopped when a client
1034  * disconnects without sending TEARDOWN.
1035  *
1036  * Returns: %TRUE if the media will be stopped when a client disconnects
1037  *     without sending TEARDOWN.
1038  */
1039 gboolean
1040 gst_rtsp_media_factory_is_stop_on_disonnect (GstRTSPMediaFactory * factory)
1041 {
1042   GstRTSPMediaFactoryPrivate *priv;
1043   gboolean result;
1044
1045   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), TRUE);
1046
1047   priv = factory->priv;
1048
1049   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1050   result = priv->stop_on_disconnect;
1051   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1052
1053   return result;
1054 }
1055
1056 /**
1057  * gst_rtsp_media_factory_set_retransmission_time:
1058  * @factory: a #GstRTSPMediaFactory
1059  * @time: a #GstClockTime
1060  *
1061  * Configure the time to store for possible retransmission
1062  */
1063 void
1064 gst_rtsp_media_factory_set_retransmission_time (GstRTSPMediaFactory * factory,
1065     GstClockTime time)
1066 {
1067   GstRTSPMediaFactoryPrivate *priv;
1068
1069   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1070
1071   priv = factory->priv;
1072
1073   GST_DEBUG_OBJECT (factory, "retransmission time %" G_GUINT64_FORMAT, time);
1074
1075   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1076   priv->rtx_time = time;
1077   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1078 }
1079
1080 /**
1081  * gst_rtsp_media_factory_get_retransmission_time:
1082  * @factory: a #GstRTSPMediaFactory
1083  *
1084  * Get the time that is stored for retransmission purposes
1085  *
1086  * Returns: a #GstClockTime
1087  */
1088 GstClockTime
1089 gst_rtsp_media_factory_get_retransmission_time (GstRTSPMediaFactory * factory)
1090 {
1091   GstRTSPMediaFactoryPrivate *priv;
1092   GstClockTime res;
1093
1094   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
1095
1096   priv = factory->priv;
1097
1098   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1099   res = priv->rtx_time;
1100   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1101
1102   return res;
1103 }
1104
1105 /**
1106  * gst_rtsp_media_factory_set_do_retransmission:
1107  *
1108  * Set whether retransmission requests will be sent for
1109  * receiving media
1110  *
1111  * Since: 1.16
1112  */
1113 void
1114 gst_rtsp_media_factory_set_do_retransmission (GstRTSPMediaFactory * factory,
1115     gboolean do_retransmission)
1116 {
1117   GstRTSPMediaFactoryPrivate *priv;
1118
1119   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1120
1121   priv = factory->priv;
1122
1123   GST_DEBUG_OBJECT (factory, "Do retransmission %d", do_retransmission);
1124
1125   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1126   priv->do_retransmission = do_retransmission;
1127   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1128 }
1129
1130 /**
1131  * gst_rtsp_media_factory_get_do_retransmission:
1132  *
1133  * Returns: Whether retransmission requests will be sent for receiving media
1134  *
1135  * Since: 1.16
1136  */
1137 gboolean
1138 gst_rtsp_media_factory_get_do_retransmission (GstRTSPMediaFactory * factory)
1139 {
1140   GstRTSPMediaFactoryPrivate *priv;
1141   gboolean res;
1142
1143   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
1144
1145   priv = factory->priv;
1146
1147   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1148   res = priv->do_retransmission;
1149   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1150
1151   return res;
1152 }
1153
1154 /**
1155  * gst_rtsp_media_factory_set_latency:
1156  * @factory: a #GstRTSPMediaFactory
1157  * @latency: latency in milliseconds
1158  *
1159  * Configure the latency used for receiving media
1160  */
1161 void
1162 gst_rtsp_media_factory_set_latency (GstRTSPMediaFactory * factory,
1163     guint latency)
1164 {
1165   GstRTSPMediaFactoryPrivate *priv;
1166
1167   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1168
1169   priv = factory->priv;
1170
1171   GST_DEBUG_OBJECT (factory, "latency %ums", latency);
1172
1173   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1174   priv->latency = latency;
1175   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1176 }
1177
1178 /**
1179  * gst_rtsp_media_factory_get_latency:
1180  * @factory: a #GstRTSPMediaFactory
1181  *
1182  * Get the latency that is used for receiving media
1183  *
1184  * Returns: latency in milliseconds
1185  */
1186 guint
1187 gst_rtsp_media_factory_get_latency (GstRTSPMediaFactory * factory)
1188 {
1189   GstRTSPMediaFactoryPrivate *priv;
1190   guint res;
1191
1192   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
1193
1194   priv = factory->priv;
1195
1196   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1197   res = priv->latency;
1198   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1199
1200   return res;
1201 }
1202
1203 static gboolean
1204 compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2)
1205 {
1206   return (media1 == media2);
1207 }
1208
1209 static void
1210 media_unprepared (GstRTSPMedia * media, GWeakRef * ref)
1211 {
1212   GstRTSPMediaFactory *factory = g_weak_ref_get (ref);
1213   GstRTSPMediaFactoryPrivate *priv;
1214
1215   if (!factory)
1216     return;
1217
1218   priv = factory->priv;
1219
1220   g_mutex_lock (&priv->medias_lock);
1221   g_hash_table_foreach_remove (priv->medias, (GHRFunc) compare_media, media);
1222   g_mutex_unlock (&priv->medias_lock);
1223
1224   g_object_unref (factory);
1225 }
1226
1227 static GWeakRef *
1228 weak_ref_new (gpointer obj)
1229 {
1230   GWeakRef *ref = g_slice_new (GWeakRef);
1231
1232   g_weak_ref_init (ref, obj);
1233   return ref;
1234 }
1235
1236 static void
1237 weak_ref_free (GWeakRef * ref)
1238 {
1239   g_weak_ref_clear (ref);
1240   g_slice_free (GWeakRef, ref);
1241 }
1242
1243 /**
1244  * gst_rtsp_media_factory_construct:
1245  * @factory: a #GstRTSPMediaFactory
1246  * @url: the url used
1247  *
1248  * Construct the media object and create its streams. Implementations
1249  * should create the needed gstreamer elements and add them to the result
1250  * object. No state changes should be performed on them yet.
1251  *
1252  * One or more GstRTSPStream objects should be created from the result
1253  * with gst_rtsp_media_create_stream ().
1254  *
1255  * After the media is constructed, it can be configured and then prepared
1256  * with gst_rtsp_media_prepare ().
1257  *
1258  * Returns: (transfer full): a new #GstRTSPMedia if the media could be prepared.
1259  */
1260 GstRTSPMedia *
1261 gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
1262     const GstRTSPUrl * url)
1263 {
1264   GstRTSPMediaFactoryPrivate *priv;
1265   gchar *key;
1266   GstRTSPMedia *media;
1267   GstRTSPMediaFactoryClass *klass;
1268
1269   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
1270   g_return_val_if_fail (url != NULL, NULL);
1271
1272   priv = factory->priv;
1273   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1274
1275   /* convert the url to a key for the hashtable. NULL return or a NULL function
1276    * will not cache anything for this factory. */
1277   if (klass->gen_key)
1278     key = klass->gen_key (factory, url);
1279   else
1280     key = NULL;
1281
1282   g_mutex_lock (&priv->medias_lock);
1283   if (key) {
1284     /* we have a key, see if we find a cached media */
1285     media = g_hash_table_lookup (priv->medias, key);
1286     if (media)
1287       g_object_ref (media);
1288   } else
1289     media = NULL;
1290
1291   if (media == NULL) {
1292     /* nothing cached found, try to create one */
1293     if (klass->construct) {
1294       media = klass->construct (factory, url);
1295       if (media)
1296         g_signal_emit (factory,
1297             gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED], 0, media,
1298             NULL);
1299     } else
1300       media = NULL;
1301
1302     if (media) {
1303       /* configure the media */
1304       if (klass->configure)
1305         klass->configure (factory, media);
1306
1307       g_signal_emit (factory,
1308           gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE], 0, media,
1309           NULL);
1310
1311       /* check if we can cache this media */
1312       if (gst_rtsp_media_is_shared (media) && key) {
1313         /* insert in the hashtable, takes ownership of the key */
1314         g_object_ref (media);
1315         g_hash_table_insert (priv->medias, key, media);
1316         key = NULL;
1317       }
1318       if (!gst_rtsp_media_is_reusable (media)) {
1319         /* when not reusable, connect to the unprepare signal to remove the item
1320          * from our cache when it gets unprepared */
1321         g_signal_connect_data (media, "unprepared",
1322             (GCallback) media_unprepared, weak_ref_new (factory),
1323             (GClosureNotify) weak_ref_free, 0);
1324       }
1325     }
1326   }
1327   g_mutex_unlock (&priv->medias_lock);
1328
1329   if (key)
1330     g_free (key);
1331
1332   GST_INFO ("constructed media %p for url %s", media, url->abspath);
1333
1334   return media;
1335 }
1336
1337 /**
1338  * gst_rtsp_media_factory_set_media_gtype:
1339  * @factory: a #GstRTSPMediaFactory
1340  * @media_gtype: the GType of the class to create
1341  *
1342  * Configure the GType of the GstRTSPMedia subclass to
1343  * create (by default, overridden construct vmethods
1344  * may of course do something different)
1345  *
1346  * Since: 1.6
1347  */
1348 void
1349 gst_rtsp_media_factory_set_media_gtype (GstRTSPMediaFactory * factory,
1350     GType media_gtype)
1351 {
1352   GstRTSPMediaFactoryPrivate *priv;
1353
1354   g_return_if_fail (g_type_is_a (media_gtype, GST_TYPE_RTSP_MEDIA));
1355
1356   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1357   priv = factory->priv;
1358   priv->media_gtype = media_gtype;
1359   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1360 }
1361
1362 /**
1363  * gst_rtsp_media_factory_get_media_gtype:
1364  * @factory: a #GstRTSPMediaFactory
1365  *
1366  * Return the GType of the GstRTSPMedia subclass this
1367  * factory will create.
1368  *
1369  * Since: 1.6
1370  */
1371 GType
1372 gst_rtsp_media_factory_get_media_gtype (GstRTSPMediaFactory * factory)
1373 {
1374   GstRTSPMediaFactoryPrivate *priv;
1375   GType ret;
1376
1377   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1378   priv = factory->priv;
1379   ret = priv->media_gtype;
1380   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1381
1382   return ret;
1383 }
1384
1385 /**
1386  * gst_rtsp_media_factory_set_clock:
1387  * @factory: a #GstRTSPMediaFactory
1388  * @clock: (nullable): the clock to be used by the media factory
1389  *
1390  * Configures a specific clock to be used by the pipelines
1391  * of all medias created from this factory.
1392  *
1393  * Since: 1.8
1394  */
1395 void
1396 gst_rtsp_media_factory_set_clock (GstRTSPMediaFactory * factory,
1397     GstClock * clock)
1398 {
1399   GstClock **clock_p;
1400
1401   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1402   g_return_if_fail (GST_IS_CLOCK (clock) || clock == NULL);
1403
1404   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1405   clock_p = &factory->priv->clock;
1406   gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
1407   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1408 }
1409
1410 /**
1411  * gst_rtsp_media_factory_get_clock:
1412  * @factory: a #GstRTSPMediaFactory
1413  *
1414  * Returns the clock that is going to be used by the pipelines
1415  * of all medias created from this factory.
1416  *
1417  * Returns: (transfer full): The GstClock
1418  *
1419  * Since: 1.8
1420  */
1421 GstClock *
1422 gst_rtsp_media_factory_get_clock (GstRTSPMediaFactory * factory)
1423 {
1424   GstRTSPMediaFactoryPrivate *priv;
1425   GstClock *ret;
1426
1427   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
1428
1429   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1430   priv = factory->priv;
1431   ret = priv->clock ? gst_object_ref (priv->clock) : NULL;
1432   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1433
1434   return ret;
1435 }
1436
1437 /**
1438  * gst_rtsp_media_factory_set_publish_clock_mode:
1439  * @factory: a #GstRTSPMediaFactory
1440  * @mode: the clock publish mode
1441  *
1442  * Sets if and how the media clock should be published according to RFC7273.
1443  *
1444  * Since: 1.8
1445  */
1446 void
1447 gst_rtsp_media_factory_set_publish_clock_mode (GstRTSPMediaFactory * factory,
1448     GstRTSPPublishClockMode mode)
1449 {
1450   GstRTSPMediaFactoryPrivate *priv;
1451
1452   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1453   priv = factory->priv;
1454   priv->publish_clock_mode = mode;
1455   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1456 }
1457
1458 /**
1459  * gst_rtsp_media_factory_get_publish_clock_mode:
1460  * @factory: a #GstRTSPMediaFactory
1461  *
1462  * Gets if and how the media clock should be published according to RFC7273.
1463  *
1464  * Returns: The GstRTSPPublishClockMode
1465  *
1466  * Since: 1.8
1467  */
1468 GstRTSPPublishClockMode
1469 gst_rtsp_media_factory_get_publish_clock_mode (GstRTSPMediaFactory * factory)
1470 {
1471   GstRTSPMediaFactoryPrivate *priv;
1472   GstRTSPPublishClockMode ret;
1473
1474   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1475   priv = factory->priv;
1476   ret = priv->publish_clock_mode;
1477   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1478
1479   return ret;
1480 }
1481
1482 /**
1483  * gst_rtsp_media_factory_set_max_mcast_ttl:
1484  * @factory: a #GstRTSPMedia
1485  * @ttl: the new multicast ttl value
1486  *
1487  * Set the maximum time-to-live value of outgoing multicast packets.
1488  *
1489  * Returns: %TRUE if the requested ttl has been set successfully.
1490  */
1491 gboolean
1492 gst_rtsp_media_factory_set_max_mcast_ttl (GstRTSPMediaFactory * factory,
1493     guint ttl)
1494 {
1495   GstRTSPMediaFactoryPrivate *priv;
1496
1497   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
1498
1499   priv = factory->priv;
1500
1501   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1502   if (ttl == 0 || ttl > DEFAULT_MAX_MCAST_TTL) {
1503     GST_WARNING_OBJECT (factory, "The requested mcast TTL value is not valid.");
1504     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1505     return FALSE;
1506   }
1507   priv->max_mcast_ttl = ttl;
1508   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1509
1510   return TRUE;
1511 }
1512
1513 /**
1514  * gst_rtsp_media_factory_get_max_mcast_ttl:
1515  * @factory: a #GstRTSPMedia
1516  *
1517  * Get the the maximum time-to-live value of outgoing multicast packets.
1518  *
1519  * Returns: the maximum time-to-live value of outgoing multicast packets.
1520  */
1521 guint
1522 gst_rtsp_media_factory_get_max_mcast_ttl (GstRTSPMediaFactory * factory)
1523 {
1524   GstRTSPMediaFactoryPrivate *priv;
1525   guint result;
1526
1527   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
1528
1529   priv = factory->priv;
1530
1531   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1532   result = priv->max_mcast_ttl;
1533   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1534
1535   return result;
1536 }
1537
1538 static gchar *
1539 default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1540 {
1541   gchar *result;
1542   const gchar *pre_query;
1543   const gchar *query;
1544   guint16 port;
1545
1546   pre_query = url->query ? "?" : "";
1547   query = url->query ? url->query : "";
1548
1549   gst_rtsp_url_get_port (url, &port);
1550
1551   result = g_strdup_printf ("%u%s%s%s", port, url->abspath, pre_query, query);
1552
1553   return result;
1554 }
1555
1556 static GstElement *
1557 default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1558 {
1559   GstRTSPMediaFactoryPrivate *priv = factory->priv;
1560   GstElement *element;
1561   GError *error = NULL;
1562
1563   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1564   /* we need a parse syntax */
1565   if (priv->launch == NULL)
1566     goto no_launch;
1567
1568   /* parse the user provided launch line */
1569   element =
1570       gst_parse_launch_full (priv->launch, NULL, GST_PARSE_FLAG_PLACE_IN_BIN,
1571       &error);
1572   if (element == NULL)
1573     goto parse_error;
1574
1575   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1576
1577   if (error != NULL) {
1578     /* a recoverable error was encountered */
1579     GST_WARNING ("recoverable parsing error: %s", error->message);
1580     g_error_free (error);
1581   }
1582   return element;
1583
1584   /* ERRORS */
1585 no_launch:
1586   {
1587     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1588     g_critical ("no launch line specified");
1589     return NULL;
1590   }
1591 parse_error:
1592   {
1593     g_critical ("could not parse launch syntax (%s): %s", priv->launch,
1594         (error ? error->message : "unknown reason"));
1595     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1596     if (error)
1597       g_error_free (error);
1598     return NULL;
1599   }
1600 }
1601
1602 static GstRTSPMedia *
1603 default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1604 {
1605   GstRTSPMedia *media;
1606   GstElement *element, *pipeline;
1607   GstRTSPMediaFactoryClass *klass;
1608   GType media_gtype;
1609
1610   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1611
1612   if (!klass->create_pipeline)
1613     goto no_create;
1614
1615   element = gst_rtsp_media_factory_create_element (factory, url);
1616   if (element == NULL)
1617     goto no_element;
1618
1619   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1620   media_gtype = factory->priv->media_gtype;
1621   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1622
1623   /* create a new empty media */
1624   media =
1625       g_object_new (media_gtype, "element", element, "transport-mode",
1626       factory->priv->transport_mode, NULL);
1627
1628   gst_rtsp_media_collect_streams (media);
1629
1630   pipeline = klass->create_pipeline (factory, media);
1631   if (pipeline == NULL)
1632     goto no_pipeline;
1633
1634   return media;
1635
1636   /* ERRORS */
1637 no_create:
1638   {
1639     g_critical ("no create_pipeline function");
1640     return NULL;
1641   }
1642 no_element:
1643   {
1644     g_critical ("could not create element");
1645     return NULL;
1646   }
1647 no_pipeline:
1648   {
1649     g_critical ("can't create pipeline");
1650     g_object_unref (media);
1651     return NULL;
1652   }
1653 }
1654
1655 static GstElement *
1656 default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
1657 {
1658   GstElement *pipeline;
1659
1660   pipeline = gst_pipeline_new ("media-pipeline");
1661
1662   /* FIXME 2.0: This should be done by the caller, not the vfunc. Every
1663    * implementation of the vfunc has to call it otherwise at the end.
1664    * Also it does not allow use to add further behaviour here that could
1665    * be reused by subclasses that chain up */
1666   gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
1667
1668   return pipeline;
1669 }
1670
1671 static void
1672 default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
1673 {
1674   GstRTSPMediaFactoryPrivate *priv = factory->priv;
1675   gboolean shared, eos_shutdown, stop_on_disconnect;
1676   guint size;
1677   GstRTSPSuspendMode suspend_mode;
1678   GstRTSPProfile profiles;
1679   GstRTSPLowerTrans protocols;
1680   GstRTSPAddressPool *pool;
1681   GstRTSPPermissions *perms;
1682   GstClockTime rtx_time;
1683   guint latency;
1684   GstRTSPTransportMode transport_mode;
1685   GstClock *clock;
1686   gchar *multicast_iface;
1687   GstRTSPPublishClockMode publish_clock_mode;
1688   guint ttl;
1689
1690   /* configure the sharedness */
1691   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1692   suspend_mode = priv->suspend_mode;
1693   shared = priv->shared;
1694   eos_shutdown = priv->eos_shutdown;
1695   size = priv->buffer_size;
1696   profiles = priv->profiles;
1697   protocols = priv->protocols;
1698   rtx_time = priv->rtx_time;
1699   latency = priv->latency;
1700   transport_mode = priv->transport_mode;
1701   stop_on_disconnect = priv->stop_on_disconnect;
1702   clock = priv->clock ? gst_object_ref (priv->clock) : NULL;
1703   publish_clock_mode = priv->publish_clock_mode;
1704   ttl = priv->max_mcast_ttl;
1705   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1706
1707   gst_rtsp_media_set_suspend_mode (media, suspend_mode);
1708   gst_rtsp_media_set_shared (media, shared);
1709   gst_rtsp_media_set_eos_shutdown (media, eos_shutdown);
1710   gst_rtsp_media_set_buffer_size (media, size);
1711   gst_rtsp_media_set_profiles (media, profiles);
1712   gst_rtsp_media_set_protocols (media, protocols);
1713   gst_rtsp_media_set_retransmission_time (media, rtx_time);
1714   gst_rtsp_media_set_do_retransmission (media, priv->do_retransmission);
1715   gst_rtsp_media_set_latency (media, latency);
1716   gst_rtsp_media_set_transport_mode (media, transport_mode);
1717   gst_rtsp_media_set_stop_on_disconnect (media, stop_on_disconnect);
1718   gst_rtsp_media_set_publish_clock_mode (media, publish_clock_mode);
1719   gst_rtsp_media_set_max_mcast_ttl (media, ttl);
1720
1721   if (clock) {
1722     gst_rtsp_media_set_clock (media, clock);
1723     gst_object_unref (clock);
1724   }
1725
1726   if ((pool = gst_rtsp_media_factory_get_address_pool (factory))) {
1727     gst_rtsp_media_set_address_pool (media, pool);
1728     g_object_unref (pool);
1729   }
1730   if ((multicast_iface = gst_rtsp_media_factory_get_multicast_iface (factory))) {
1731     gst_rtsp_media_set_multicast_iface (media, multicast_iface);
1732     g_free (multicast_iface);
1733   }
1734   if ((perms = gst_rtsp_media_factory_get_permissions (factory))) {
1735     gst_rtsp_media_set_permissions (media, perms);
1736     gst_rtsp_permissions_unref (perms);
1737   }
1738 }
1739
1740 /**
1741  * gst_rtsp_media_factory_create_element:
1742  * @factory: a #GstRTSPMediaFactory
1743  * @url: the url used
1744  *
1745  * Construct and return a #GstElement that is a #GstBin containing
1746  * the elements to use for streaming the media.
1747  *
1748  * The bin should contain payloaders pay\%d for each stream. The default
1749  * implementation of this function returns the bin created from the
1750  * launch parameter.
1751  *
1752  * Returns: (transfer floating): a new #GstElement.
1753  */
1754 GstElement *
1755 gst_rtsp_media_factory_create_element (GstRTSPMediaFactory * factory,
1756     const GstRTSPUrl * url)
1757 {
1758   GstRTSPMediaFactoryClass *klass;
1759   GstElement *result;
1760
1761   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
1762   g_return_val_if_fail (url != NULL, NULL);
1763
1764   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1765
1766   if (klass->create_element)
1767     result = klass->create_element (factory, url);
1768   else
1769     result = NULL;
1770
1771   return result;
1772 }
1773
1774 /**
1775  * gst_rtsp_media_factory_set_transport_mode:
1776  * @factory: a #GstRTSPMediaFactory
1777  * @mode: the new value
1778  *
1779  * Configure if this factory creates media for PLAY or RECORD modes.
1780  */
1781 void
1782 gst_rtsp_media_factory_set_transport_mode (GstRTSPMediaFactory * factory,
1783     GstRTSPTransportMode mode)
1784 {
1785   GstRTSPMediaFactoryPrivate *priv;
1786
1787   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1788
1789   priv = factory->priv;
1790
1791   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1792   priv->transport_mode = mode;
1793   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1794 }
1795
1796 /**
1797  * gst_rtsp_media_factory_get_transport_mode:
1798  * @factory: a #GstRTSPMediaFactory
1799  *
1800  * Get if media created from this factory can be used for PLAY or RECORD
1801  * methods.
1802  *
1803  * Returns: The transport mode.
1804  */
1805 GstRTSPTransportMode
1806 gst_rtsp_media_factory_get_transport_mode (GstRTSPMediaFactory * factory)
1807 {
1808   GstRTSPMediaFactoryPrivate *priv;
1809   GstRTSPTransportMode result;
1810
1811   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
1812
1813   priv = factory->priv;
1814
1815   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1816   result = priv->transport_mode;
1817   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1818
1819   return result;
1820 }