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