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