b12633954626b331a4a5d3cec42cf5477d2dd725
[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_PRIVATE(obj)  \
44        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryPrivate))
45
46 #define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock))
47 #define GST_RTSP_MEDIA_FACTORY_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
48 #define GST_RTSP_MEDIA_FACTORY_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
49
50 struct _GstRTSPMediaFactoryPrivate
51 {
52   GMutex lock;                  /* protects everything but medias */
53   GstRTSPPermissions *permissions;
54   gchar *launch;
55   gboolean shared;
56   GstRTSPSuspendMode suspend_mode;
57   gboolean eos_shutdown;
58   GstRTSPProfile profiles;
59   GstRTSPLowerTrans protocols;
60   guint buffer_size;
61   GstRTSPAddressPool *pool;
62   GstRTSPTransportMode transport_mode;
63
64   GstClockTime rtx_time;
65   guint latency;
66
67   GMutex medias_lock;
68   GHashTable *medias;           /* protected by medias_lock */
69
70   GType media_gtype;
71 };
72
73 #define DEFAULT_LAUNCH          NULL
74 #define DEFAULT_SHARED          FALSE
75 #define DEFAULT_SUSPEND_MODE    GST_RTSP_SUSPEND_MODE_NONE
76 #define DEFAULT_EOS_SHUTDOWN    FALSE
77 #define DEFAULT_PROFILES        GST_RTSP_PROFILE_AVP
78 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
79                                         GST_RTSP_LOWER_TRANS_TCP
80 #define DEFAULT_BUFFER_SIZE     0x80000
81 #define DEFAULT_LATENCY         200
82 #define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
83
84 enum
85 {
86   PROP_0,
87   PROP_LAUNCH,
88   PROP_SHARED,
89   PROP_SUSPEND_MODE,
90   PROP_EOS_SHUTDOWN,
91   PROP_PROFILES,
92   PROP_PROTOCOLS,
93   PROP_BUFFER_SIZE,
94   PROP_LATENCY,
95   PROP_TRANSPORT_MODE,
96   PROP_LAST
97 };
98
99 enum
100 {
101   SIGNAL_MEDIA_CONSTRUCTED,
102   SIGNAL_MEDIA_CONFIGURE,
103   SIGNAL_LAST
104 };
105
106 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
107 #define GST_CAT_DEFAULT rtsp_media_debug
108
109 static guint gst_rtsp_media_factory_signals[SIGNAL_LAST] = { 0 };
110
111 static void gst_rtsp_media_factory_get_property (GObject * object, guint propid,
112     GValue * value, GParamSpec * pspec);
113 static void gst_rtsp_media_factory_set_property (GObject * object, guint propid,
114     const GValue * value, GParamSpec * pspec);
115 static void gst_rtsp_media_factory_finalize (GObject * obj);
116
117 static gchar *default_gen_key (GstRTSPMediaFactory * factory,
118     const GstRTSPUrl * url);
119 static GstElement *default_create_element (GstRTSPMediaFactory * factory,
120     const GstRTSPUrl * url);
121 static GstRTSPMedia *default_construct (GstRTSPMediaFactory * factory,
122     const GstRTSPUrl * url);
123 static void default_configure (GstRTSPMediaFactory * factory,
124     GstRTSPMedia * media);
125 static GstElement *default_create_pipeline (GstRTSPMediaFactory * factory,
126     GstRTSPMedia * media);
127
128 G_DEFINE_TYPE (GstRTSPMediaFactory, gst_rtsp_media_factory, G_TYPE_OBJECT);
129
130 static void
131 gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
132 {
133   GObjectClass *gobject_class;
134
135   g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryPrivate));
136
137   gobject_class = G_OBJECT_CLASS (klass);
138
139   gobject_class->get_property = gst_rtsp_media_factory_get_property;
140   gobject_class->set_property = gst_rtsp_media_factory_set_property;
141   gobject_class->finalize = gst_rtsp_media_factory_finalize;
142
143   /**
144    * GstRTSPMediaFactory::launch:
145    *
146    * The gst_parse_launch() line to use for constructing the pipeline in the
147    * default prepare vmethod.
148    *
149    * The pipeline description should return a GstBin as the toplevel element
150    * which can be accomplished by enclosing the dscription with brackets '('
151    * ')'.
152    *
153    * The description should return a pipeline with payloaders named pay0, pay1,
154    * etc.. Each of the payloaders will result in a stream.
155    *
156    * Support for dynamic payloaders can be accomplished by adding payloaders
157    * named dynpay0, dynpay1, etc..
158    */
159   g_object_class_install_property (gobject_class, PROP_LAUNCH,
160       g_param_spec_string ("launch", "Launch",
161           "A launch description of the pipeline", DEFAULT_LAUNCH,
162           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
163
164   g_object_class_install_property (gobject_class, PROP_SHARED,
165       g_param_spec_boolean ("shared", "Shared",
166           "If media from this factory is shared", DEFAULT_SHARED,
167           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
168
169   g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE,
170       g_param_spec_enum ("suspend-mode", "Suspend Mode",
171           "Control how media will be suspended", GST_TYPE_RTSP_SUSPEND_MODE,
172           DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173
174   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
175       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
176           "Send EOS down the pipeline before shutting down",
177           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
178
179   g_object_class_install_property (gobject_class, PROP_PROFILES,
180       g_param_spec_flags ("profiles", "Profiles",
181           "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE,
182           DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
183
184   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
185       g_param_spec_flags ("protocols", "Protocols",
186           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
187           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188
189   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
190       g_param_spec_uint ("buffer-size", "Buffer Size",
191           "The kernel UDP buffer size to use", 0, G_MAXUINT,
192           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193
194   g_object_class_install_property (gobject_class, PROP_LATENCY,
195       g_param_spec_uint ("latency", "Latency",
196           "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
197           DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198
199   g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
200       g_param_spec_flags ("transport-mode", "Transport Mode",
201           "If media from this factory is for PLAY or RECORD",
202           GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
203           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
204
205   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] =
206       g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass),
207       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
208           media_constructed), NULL, NULL, g_cclosure_marshal_generic,
209       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
210
211   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE] =
212       g_signal_new ("media-configure", G_TYPE_FROM_CLASS (klass),
213       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
214           media_configure), NULL, NULL, g_cclosure_marshal_generic,
215       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
216
217   klass->gen_key = default_gen_key;
218   klass->create_element = default_create_element;
219   klass->construct = default_construct;
220   klass->configure = default_configure;
221   klass->create_pipeline = default_create_pipeline;
222
223   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmediafactory", 0,
224       "GstRTSPMediaFactory");
225 }
226
227 static void
228 gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
229 {
230   GstRTSPMediaFactoryPrivate *priv =
231       GST_RTSP_MEDIA_FACTORY_GET_PRIVATE (factory);
232   factory->priv = priv;
233
234   priv->launch = g_strdup (DEFAULT_LAUNCH);
235   priv->shared = DEFAULT_SHARED;
236   priv->suspend_mode = DEFAULT_SUSPEND_MODE;
237   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
238   priv->profiles = DEFAULT_PROFILES;
239   priv->protocols = DEFAULT_PROTOCOLS;
240   priv->buffer_size = DEFAULT_BUFFER_SIZE;
241   priv->latency = DEFAULT_LATENCY;
242   priv->transport_mode = DEFAULT_TRANSPORT_MODE;
243
244   g_mutex_init (&priv->lock);
245   g_mutex_init (&priv->medias_lock);
246   priv->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
247       g_free, g_object_unref);
248   priv->media_gtype = GST_TYPE_RTSP_MEDIA;
249 }
250
251 static void
252 gst_rtsp_media_factory_finalize (GObject * obj)
253 {
254   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
255   GstRTSPMediaFactoryPrivate *priv = factory->priv;
256
257   if (priv->permissions)
258     gst_rtsp_permissions_unref (priv->permissions);
259   g_hash_table_unref (priv->medias);
260   g_mutex_clear (&priv->medias_lock);
261   g_free (priv->launch);
262   g_mutex_clear (&priv->lock);
263   if (priv->pool)
264     g_object_unref (priv->pool);
265
266   G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
267 }
268
269 static void
270 gst_rtsp_media_factory_get_property (GObject * object, guint propid,
271     GValue * value, GParamSpec * pspec)
272 {
273   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
274
275   switch (propid) {
276     case PROP_LAUNCH:
277       g_value_take_string (value, gst_rtsp_media_factory_get_launch (factory));
278       break;
279     case PROP_SHARED:
280       g_value_set_boolean (value, gst_rtsp_media_factory_is_shared (factory));
281       break;
282     case PROP_SUSPEND_MODE:
283       g_value_set_enum (value,
284           gst_rtsp_media_factory_get_suspend_mode (factory));
285       break;
286     case PROP_EOS_SHUTDOWN:
287       g_value_set_boolean (value,
288           gst_rtsp_media_factory_is_eos_shutdown (factory));
289       break;
290     case PROP_PROFILES:
291       g_value_set_flags (value, gst_rtsp_media_factory_get_profiles (factory));
292       break;
293     case PROP_PROTOCOLS:
294       g_value_set_flags (value, gst_rtsp_media_factory_get_protocols (factory));
295       break;
296     case PROP_BUFFER_SIZE:
297       g_value_set_uint (value,
298           gst_rtsp_media_factory_get_buffer_size (factory));
299       break;
300     case PROP_LATENCY:
301       g_value_set_uint (value, gst_rtsp_media_factory_get_latency (factory));
302       break;
303     case PROP_TRANSPORT_MODE:
304       g_value_set_flags (value,
305           gst_rtsp_media_factory_get_transport_mode (factory));
306       break;
307     default:
308       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
309   }
310 }
311
312 static void
313 gst_rtsp_media_factory_set_property (GObject * object, guint propid,
314     const GValue * value, GParamSpec * pspec)
315 {
316   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
317
318   switch (propid) {
319     case PROP_LAUNCH:
320       gst_rtsp_media_factory_set_launch (factory, g_value_get_string (value));
321       break;
322     case PROP_SHARED:
323       gst_rtsp_media_factory_set_shared (factory, g_value_get_boolean (value));
324       break;
325     case PROP_SUSPEND_MODE:
326       gst_rtsp_media_factory_set_suspend_mode (factory,
327           g_value_get_enum (value));
328       break;
329     case PROP_EOS_SHUTDOWN:
330       gst_rtsp_media_factory_set_eos_shutdown (factory,
331           g_value_get_boolean (value));
332       break;
333     case PROP_PROFILES:
334       gst_rtsp_media_factory_set_profiles (factory, g_value_get_flags (value));
335       break;
336     case PROP_PROTOCOLS:
337       gst_rtsp_media_factory_set_protocols (factory, g_value_get_flags (value));
338       break;
339     case PROP_BUFFER_SIZE:
340       gst_rtsp_media_factory_set_buffer_size (factory,
341           g_value_get_uint (value));
342       break;
343     case PROP_LATENCY:
344       gst_rtsp_media_factory_set_latency (factory, g_value_get_uint (value));
345       break;
346     case PROP_TRANSPORT_MODE:
347       gst_rtsp_media_factory_set_transport_mode (factory,
348           g_value_get_flags (value));
349       break;
350     default:
351       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
352   }
353 }
354
355 /**
356  * gst_rtsp_media_factory_new:
357  *
358  * Create a new #GstRTSPMediaFactory instance.
359  *
360  * Returns: (transfer full): a new #GstRTSPMediaFactory object.
361  */
362 GstRTSPMediaFactory *
363 gst_rtsp_media_factory_new (void)
364 {
365   GstRTSPMediaFactory *result;
366
367   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY, NULL);
368
369   return result;
370 }
371
372 /**
373  * gst_rtsp_media_factory_set_permissions:
374  * @factory: a #GstRTSPMediaFactory
375  * @permissions: (transfer none): a #GstRTSPPermissions
376  *
377  * Set @permissions on @factory.
378  */
379 void
380 gst_rtsp_media_factory_set_permissions (GstRTSPMediaFactory * factory,
381     GstRTSPPermissions * permissions)
382 {
383   GstRTSPMediaFactoryPrivate *priv;
384
385   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
386
387   priv = factory->priv;
388
389   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
390   if (priv->permissions)
391     gst_rtsp_permissions_unref (priv->permissions);
392   if ((priv->permissions = permissions))
393     gst_rtsp_permissions_ref (permissions);
394   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
395 }
396
397 /**
398  * gst_rtsp_media_factory_get_permissions:
399  * @factory: a #GstRTSPMediaFactory
400  *
401  * Get the permissions object from @factory.
402  *
403  * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage.
404  */
405 GstRTSPPermissions *
406 gst_rtsp_media_factory_get_permissions (GstRTSPMediaFactory * factory)
407 {
408   GstRTSPMediaFactoryPrivate *priv;
409   GstRTSPPermissions *result;
410
411   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
412
413   priv = factory->priv;
414
415   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
416   if ((result = priv->permissions))
417     gst_rtsp_permissions_ref (result);
418   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
419
420   return result;
421 }
422
423 /**
424  * gst_rtsp_media_factory_add_role:
425  * @factory: a #GstRTSPMediaFactory
426  * @role: a role
427  * @fieldname: the first field name
428  * @...: additional arguments
429  *
430  * A convenience method to add @role with @fieldname and additional arguments to
431  * the permissions of @factory. If @factory had no permissions, new permissions
432  * will be created and the role will be added to it.
433  */
434 void
435 gst_rtsp_media_factory_add_role (GstRTSPMediaFactory * factory,
436     const gchar * role, const gchar * fieldname, ...)
437 {
438   GstRTSPMediaFactoryPrivate *priv;
439   va_list var_args;
440
441   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
442   g_return_if_fail (role != NULL);
443   g_return_if_fail (fieldname != NULL);
444
445   priv = factory->priv;
446
447   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
448   if (priv->permissions == NULL)
449     priv->permissions = gst_rtsp_permissions_new ();
450
451   va_start (var_args, fieldname);
452   gst_rtsp_permissions_add_role_valist (priv->permissions, role, fieldname,
453       var_args);
454   va_end (var_args);
455   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
456 }
457
458 /**
459  * gst_rtsp_media_factory_set_launch:
460  * @factory: a #GstRTSPMediaFactory
461  * @launch: the launch description
462  *
463  *
464  * The gst_parse_launch() line to use for constructing the pipeline in the
465  * default prepare vmethod.
466  *
467  * The pipeline description should return a GstBin as the toplevel element
468  * which can be accomplished by enclosing the dscription with brackets '('
469  * ')'.
470  *
471  * The description should return a pipeline with payloaders named pay0, pay1,
472  * etc.. Each of the payloaders will result in a stream.
473  */
474 void
475 gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
476     const gchar * launch)
477 {
478   GstRTSPMediaFactoryPrivate *priv;
479
480   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
481   g_return_if_fail (launch != NULL);
482
483   priv = factory->priv;
484
485   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
486   g_free (priv->launch);
487   priv->launch = g_strdup (launch);
488   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
489 }
490
491 /**
492  * gst_rtsp_media_factory_get_launch:
493  * @factory: a #GstRTSPMediaFactory
494  *
495  * Get the gst_parse_launch() pipeline description that will be used in the
496  * default prepare vmethod.
497  *
498  * Returns: (transfer full): the configured launch description. g_free() after
499  * usage.
500  */
501 gchar *
502 gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory)
503 {
504   GstRTSPMediaFactoryPrivate *priv;
505   gchar *result;
506
507   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
508
509   priv = factory->priv;
510
511   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
512   result = g_strdup (priv->launch);
513   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
514
515   return result;
516 }
517
518 /**
519  * gst_rtsp_media_factory_set_suspend_mode:
520  * @factory: a #GstRTSPMediaFactory
521  * @mode: the new #GstRTSPSuspendMode
522  *
523  * Configure how media created from this factory will be suspended.
524  */
525 void
526 gst_rtsp_media_factory_set_suspend_mode (GstRTSPMediaFactory * factory,
527     GstRTSPSuspendMode mode)
528 {
529   GstRTSPMediaFactoryPrivate *priv;
530
531   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
532
533   priv = factory->priv;
534
535   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
536   priv->suspend_mode = mode;
537   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
538 }
539
540 /**
541  * gst_rtsp_media_factory_get_suspend_mode:
542  * @factory: a #GstRTSPMediaFactory
543  *
544  * Get how media created from this factory will be suspended.
545  *
546  * Returns: a #GstRTSPSuspendMode.
547  */
548 GstRTSPSuspendMode
549 gst_rtsp_media_factory_get_suspend_mode (GstRTSPMediaFactory * factory)
550 {
551   GstRTSPMediaFactoryPrivate *priv;
552   GstRTSPSuspendMode result;
553
554   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
555       GST_RTSP_SUSPEND_MODE_NONE);
556
557   priv = factory->priv;
558
559   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
560   result = priv->suspend_mode;
561   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
562
563   return result;
564 }
565
566 /**
567  * gst_rtsp_media_factory_set_shared:
568  * @factory: a #GstRTSPMediaFactory
569  * @shared: the new value
570  *
571  * Configure if media created from this factory can be shared between clients.
572  */
573 void
574 gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
575     gboolean shared)
576 {
577   GstRTSPMediaFactoryPrivate *priv;
578
579   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
580
581   priv = factory->priv;
582
583   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
584   priv->shared = shared;
585   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
586 }
587
588 /**
589  * gst_rtsp_media_factory_is_shared:
590  * @factory: a #GstRTSPMediaFactory
591  *
592  * Get if media created from this factory can be shared between clients.
593  *
594  * Returns: %TRUE if the media will be shared between clients.
595  */
596 gboolean
597 gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory)
598 {
599   GstRTSPMediaFactoryPrivate *priv;
600   gboolean result;
601
602   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
603
604   priv = factory->priv;
605
606   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
607   result = priv->shared;
608   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
609
610   return result;
611 }
612
613 /**
614  * gst_rtsp_media_factory_set_eos_shutdown:
615  * @factory: a #GstRTSPMediaFactory
616  * @eos_shutdown: the new value
617  *
618  * Configure if media created from this factory will have an EOS sent to the
619  * pipeline before shutdown.
620  */
621 void
622 gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
623     gboolean eos_shutdown)
624 {
625   GstRTSPMediaFactoryPrivate *priv;
626
627   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
628
629   priv = factory->priv;
630
631   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
632   priv->eos_shutdown = eos_shutdown;
633   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
634 }
635
636 /**
637  * gst_rtsp_media_factory_is_eos_shutdown:
638  * @factory: a #GstRTSPMediaFactory
639  *
640  * Get if media created from this factory will have an EOS event sent to the
641  * pipeline before shutdown.
642  *
643  * Returns: %TRUE if the media will receive EOS before shutdown.
644  */
645 gboolean
646 gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory)
647 {
648   GstRTSPMediaFactoryPrivate *priv;
649   gboolean result;
650
651   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
652
653   priv = factory->priv;
654
655   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
656   result = priv->eos_shutdown;
657   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
658
659   return result;
660 }
661
662 /**
663  * gst_rtsp_media_factory_set_buffer_size:
664  * @factory: a #GstRTSPMedia
665  * @size: the new value
666  *
667  * Set the kernel UDP buffer size.
668  */
669 void
670 gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
671     guint size)
672 {
673   GstRTSPMediaFactoryPrivate *priv;
674
675   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
676
677   priv = factory->priv;
678
679   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
680   priv->buffer_size = size;
681   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
682 }
683
684 /**
685  * gst_rtsp_media_factory_get_buffer_size:
686  * @factory: a #GstRTSPMedia
687  *
688  * Get the kernel UDP buffer size.
689  *
690  * Returns: the kernel UDP buffer size.
691  */
692 guint
693 gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
694 {
695   GstRTSPMediaFactoryPrivate *priv;
696   guint result;
697
698   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
699
700   priv = factory->priv;
701
702   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
703   result = priv->buffer_size;
704   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
705
706   return result;
707 }
708
709 /**
710  * gst_rtsp_media_factory_set_address_pool:
711  * @factory: a #GstRTSPMediaFactory
712  * @pool: (transfer none): a #GstRTSPAddressPool
713  *
714  * configure @pool to be used as the address pool of @factory.
715  */
716 void
717 gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
718     GstRTSPAddressPool * pool)
719 {
720   GstRTSPMediaFactoryPrivate *priv;
721   GstRTSPAddressPool *old;
722
723   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
724
725   priv = factory->priv;
726
727   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
728   if ((old = priv->pool) != pool)
729     priv->pool = pool ? g_object_ref (pool) : NULL;
730   else
731     old = NULL;
732   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
733
734   if (old)
735     g_object_unref (old);
736 }
737
738 /**
739  * gst_rtsp_media_factory_get_address_pool:
740  * @factory: a #GstRTSPMediaFactory
741  *
742  * Get the #GstRTSPAddressPool used as the address pool of @factory.
743  *
744  * Returns: (transfer full): the #GstRTSPAddressPool of @factory. g_object_unref() after
745  * usage.
746  */
747 GstRTSPAddressPool *
748 gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory)
749 {
750   GstRTSPMediaFactoryPrivate *priv;
751   GstRTSPAddressPool *result;
752
753   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
754
755   priv = factory->priv;
756
757   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
758   if ((result = priv->pool))
759     g_object_ref (result);
760   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
761
762   return result;
763 }
764
765 /**
766  * gst_rtsp_media_factory_set_profiles:
767  * @factory: a #GstRTSPMediaFactory
768  * @profiles: the new flags
769  *
770  * Configure the allowed profiles for @factory.
771  */
772 void
773 gst_rtsp_media_factory_set_profiles (GstRTSPMediaFactory * factory,
774     GstRTSPProfile profiles)
775 {
776   GstRTSPMediaFactoryPrivate *priv;
777
778   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
779
780   priv = factory->priv;
781
782   GST_DEBUG_OBJECT (factory, "profiles %d", profiles);
783
784   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
785   priv->profiles = profiles;
786   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
787 }
788
789 /**
790  * gst_rtsp_media_factory_get_profiles:
791  * @factory: a #GstRTSPMediaFactory
792  *
793  * Get the allowed profiles of @factory.
794  *
795  * Returns: a #GstRTSPProfile
796  */
797 GstRTSPProfile
798 gst_rtsp_media_factory_get_profiles (GstRTSPMediaFactory * factory)
799 {
800   GstRTSPMediaFactoryPrivate *priv;
801   GstRTSPProfile res;
802
803   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
804       GST_RTSP_PROFILE_UNKNOWN);
805
806   priv = factory->priv;
807
808   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
809   res = priv->profiles;
810   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
811
812   return res;
813 }
814
815 /**
816  * gst_rtsp_media_factory_set_protocols:
817  * @factory: a #GstRTSPMediaFactory
818  * @protocols: the new flags
819  *
820  * Configure the allowed lower transport for @factory.
821  */
822 void
823 gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
824     GstRTSPLowerTrans protocols)
825 {
826   GstRTSPMediaFactoryPrivate *priv;
827
828   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
829
830   priv = factory->priv;
831
832   GST_DEBUG_OBJECT (factory, "protocols %d", protocols);
833
834   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
835   priv->protocols = protocols;
836   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
837 }
838
839 /**
840  * gst_rtsp_media_factory_get_protocols:
841  * @factory: a #GstRTSPMediaFactory
842  *
843  * Get the allowed protocols of @factory.
844  *
845  * Returns: a #GstRTSPLowerTrans
846  */
847 GstRTSPLowerTrans
848 gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
849 {
850   GstRTSPMediaFactoryPrivate *priv;
851   GstRTSPLowerTrans res;
852
853   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
854       GST_RTSP_LOWER_TRANS_UNKNOWN);
855
856   priv = factory->priv;
857
858   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
859   res = priv->protocols;
860   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
861
862   return res;
863 }
864
865 /**
866  * gst_rtsp_media_factory_set_retransmission_time:
867  * @factory: a #GstRTSPMediaFactory
868  * @time: a #GstClockTime
869  *
870  * Configure the time to store for possible retransmission
871  */
872 void
873 gst_rtsp_media_factory_set_retransmission_time (GstRTSPMediaFactory * factory,
874     GstClockTime time)
875 {
876   GstRTSPMediaFactoryPrivate *priv;
877
878   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
879
880   priv = factory->priv;
881
882   GST_DEBUG_OBJECT (factory, "retransmission time %" G_GUINT64_FORMAT, time);
883
884   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
885   priv->rtx_time = time;
886   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
887 }
888
889 /**
890  * gst_rtsp_media_factory_get_retransmission_time:
891  * @factory: a #GstRTSPMediaFactory
892  *
893  * Get the time that is stored for retransmission purposes
894  *
895  * Returns: a #GstClockTime
896  */
897 GstClockTime
898 gst_rtsp_media_factory_get_retransmission_time (GstRTSPMediaFactory * factory)
899 {
900   GstRTSPMediaFactoryPrivate *priv;
901   GstClockTime res;
902
903   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
904
905   priv = factory->priv;
906
907   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
908   res = priv->rtx_time;
909   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
910
911   return res;
912 }
913
914 /**
915  * gst_rtsp_media_factory_set_latency:
916  * @factory: a #GstRTSPMediaFactory
917  * @latency: latency in milliseconds
918  *
919  * Configure the latency used for receiving media
920  */
921 void
922 gst_rtsp_media_factory_set_latency (GstRTSPMediaFactory * factory,
923     guint latency)
924 {
925   GstRTSPMediaFactoryPrivate *priv;
926
927   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
928
929   priv = factory->priv;
930
931   GST_DEBUG_OBJECT (factory, "latency %ums", latency);
932
933   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
934   priv->latency = latency;
935   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
936 }
937
938 /**
939  * gst_rtsp_media_factory_get_latency:
940  * @factory: a #GstRTSPMediaFactory
941  *
942  * Get the latency that is used for receiving media
943  *
944  * Returns: latency in milliseconds
945  */
946 guint
947 gst_rtsp_media_factory_get_latency (GstRTSPMediaFactory * factory)
948 {
949   GstRTSPMediaFactoryPrivate *priv;
950   guint res;
951
952   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
953
954   priv = factory->priv;
955
956   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
957   res = priv->latency;
958   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
959
960   return res;
961 }
962
963 static gboolean
964 compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2)
965 {
966   return (media1 == media2);
967 }
968
969 static void
970 media_unprepared (GstRTSPMedia * media, GWeakRef * ref)
971 {
972   GstRTSPMediaFactory *factory = g_weak_ref_get (ref);
973   GstRTSPMediaFactoryPrivate *priv;
974
975   if (!factory)
976     return;
977
978   priv = factory->priv;;
979
980   g_mutex_lock (&priv->medias_lock);
981   g_hash_table_foreach_remove (priv->medias, (GHRFunc) compare_media, media);
982   g_mutex_unlock (&priv->medias_lock);
983
984   g_object_unref (factory);
985 }
986
987 static GWeakRef *
988 weak_ref_new (gpointer obj)
989 {
990   GWeakRef *ref = g_slice_new (GWeakRef);
991
992   g_weak_ref_init (ref, obj);
993   return ref;
994 }
995
996 static void
997 weak_ref_free (GWeakRef * ref)
998 {
999   g_weak_ref_clear (ref);
1000   g_slice_free (GWeakRef, ref);
1001 }
1002
1003 /**
1004  * gst_rtsp_media_factory_construct:
1005  * @factory: a #GstRTSPMediaFactory
1006  * @url: the url used
1007  *
1008  * Construct the media object and create its streams. Implementations
1009  * should create the needed gstreamer elements and add them to the result
1010  * object. No state changes should be performed on them yet.
1011  *
1012  * One or more GstRTSPStream objects should be created from the result
1013  * with gst_rtsp_media_create_stream ().
1014  *
1015  * After the media is constructed, it can be configured and then prepared
1016  * with gst_rtsp_media_prepare ().
1017  *
1018  * Returns: (transfer full): a new #GstRTSPMedia if the media could be prepared.
1019  */
1020 GstRTSPMedia *
1021 gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
1022     const GstRTSPUrl * url)
1023 {
1024   GstRTSPMediaFactoryPrivate *priv;
1025   gchar *key;
1026   GstRTSPMedia *media;
1027   GstRTSPMediaFactoryClass *klass;
1028
1029   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
1030   g_return_val_if_fail (url != NULL, NULL);
1031
1032   priv = factory->priv;;
1033   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1034
1035   /* convert the url to a key for the hashtable. NULL return or a NULL function
1036    * will not cache anything for this factory. */
1037   if (klass->gen_key)
1038     key = klass->gen_key (factory, url);
1039   else
1040     key = NULL;
1041
1042   g_mutex_lock (&priv->medias_lock);
1043   if (key) {
1044     /* we have a key, see if we find a cached media */
1045     media = g_hash_table_lookup (priv->medias, key);
1046     if (media)
1047       g_object_ref (media);
1048   } else
1049     media = NULL;
1050
1051   if (media == NULL) {
1052     /* nothing cached found, try to create one */
1053     if (klass->construct) {
1054       media = klass->construct (factory, url);
1055       if (media)
1056         g_signal_emit (factory,
1057             gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED], 0, media,
1058             NULL);
1059     } else
1060       media = NULL;
1061
1062     if (media) {
1063       /* configure the media */
1064       if (klass->configure)
1065         klass->configure (factory, media);
1066
1067       g_signal_emit (factory,
1068           gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE], 0, media,
1069           NULL);
1070
1071       /* check if we can cache this media */
1072       if (gst_rtsp_media_is_shared (media)) {
1073         /* insert in the hashtable, takes ownership of the key */
1074         g_object_ref (media);
1075         g_hash_table_insert (priv->medias, key, media);
1076         key = NULL;
1077       }
1078       if (!gst_rtsp_media_is_reusable (media)) {
1079         /* when not reusable, connect to the unprepare signal to remove the item
1080          * from our cache when it gets unprepared */
1081         g_signal_connect_data (media, "unprepared",
1082             (GCallback) media_unprepared, weak_ref_new (factory),
1083             (GClosureNotify) weak_ref_free, 0);
1084       }
1085     }
1086   }
1087   g_mutex_unlock (&priv->medias_lock);
1088
1089   if (key)
1090     g_free (key);
1091
1092   GST_INFO ("constructed media %p for url %s", media, url->abspath);
1093
1094   return media;
1095 }
1096
1097 /**
1098  * gst_rtsp_media_factory_set_media_gtype:
1099  * @factory: a #GstRTSPMediaFactory
1100  * @media_gtype: the GType of the class to create
1101  *
1102  * Configure the GType of the GstRTSPMedia subclass to
1103  * create (by default, overridden construct vmethods
1104  * may of course do something different)
1105  *
1106  * Since: 1.6
1107  */
1108 void
1109 gst_rtsp_media_factory_set_media_gtype (GstRTSPMediaFactory * factory,
1110     GType media_gtype)
1111 {
1112   GstRTSPMediaFactoryPrivate *priv;
1113
1114   g_return_if_fail (g_type_is_a (media_gtype, GST_TYPE_RTSP_MEDIA));
1115
1116   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1117   priv = factory->priv;
1118   priv->media_gtype = media_gtype;
1119   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1120 }
1121
1122 /**
1123  * gst_rtsp_media_factory_get_media_gtype:
1124  * @factory: a #GstRTSPMediaFactory
1125  *
1126  * Return the GType of the GstRTSPMedia subclass this
1127  * factory will create.
1128  *
1129  * Since: 1.6
1130  */
1131 GType
1132 gst_rtsp_media_factory_get_media_gtype (GstRTSPMediaFactory * factory)
1133 {
1134   GstRTSPMediaFactoryPrivate *priv;
1135   GType ret;
1136
1137   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1138   priv = factory->priv;
1139   ret = priv->media_gtype;
1140   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1141
1142   return ret;
1143 }
1144
1145 static gchar *
1146 default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1147 {
1148   gchar *result;
1149   const gchar *pre_query;
1150   const gchar *query;
1151
1152   pre_query = url->query ? "?" : "";
1153   query = url->query ? url->query : "";
1154
1155   result =
1156       g_strdup_printf ("%u%s%s%s", url->port, url->abspath, pre_query, query);
1157
1158   return result;
1159 }
1160
1161 static GstElement *
1162 default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1163 {
1164   GstRTSPMediaFactoryPrivate *priv = factory->priv;
1165   GstElement *element;
1166   GError *error = NULL;
1167
1168   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1169   /* we need a parse syntax */
1170   if (priv->launch == NULL)
1171     goto no_launch;
1172
1173   /* parse the user provided launch line */
1174   element = gst_parse_launch (priv->launch, &error);
1175   if (element == NULL)
1176     goto parse_error;
1177
1178   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1179
1180   if (error != NULL) {
1181     /* a recoverable error was encountered */
1182     GST_WARNING ("recoverable parsing error: %s", error->message);
1183     g_error_free (error);
1184   }
1185   return element;
1186
1187   /* ERRORS */
1188 no_launch:
1189   {
1190     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1191     g_critical ("no launch line specified");
1192     return NULL;
1193   }
1194 parse_error:
1195   {
1196     g_critical ("could not parse launch syntax (%s): %s", priv->launch,
1197         (error ? error->message : "unknown reason"));
1198     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1199     if (error)
1200       g_error_free (error);
1201     return NULL;
1202   }
1203 }
1204
1205 static GstRTSPMedia *
1206 default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
1207 {
1208   GstRTSPMedia *media;
1209   GstElement *element, *pipeline;
1210   GstRTSPMediaFactoryClass *klass;
1211   GType media_gtype;
1212
1213   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1214
1215   if (!klass->create_pipeline)
1216     goto no_create;
1217
1218   element = gst_rtsp_media_factory_create_element (factory, url);
1219   if (element == NULL)
1220     goto no_element;
1221
1222   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1223   media_gtype = factory->priv->media_gtype;
1224   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1225
1226   /* create a new empty media */
1227   media = g_object_new (media_gtype, "element", element, NULL);
1228
1229   gst_rtsp_media_collect_streams (media);
1230
1231   pipeline = klass->create_pipeline (factory, media);
1232   if (pipeline == NULL)
1233     goto no_pipeline;
1234
1235   return media;
1236
1237   /* ERRORS */
1238 no_create:
1239   {
1240     g_critical ("no create_pipeline function");
1241     return NULL;
1242   }
1243 no_element:
1244   {
1245     g_critical ("could not create element");
1246     return NULL;
1247   }
1248 no_pipeline:
1249   {
1250     g_critical ("can't create pipeline");
1251     g_object_unref (media);
1252     return NULL;
1253   }
1254 }
1255
1256 static GstElement *
1257 default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
1258 {
1259   GstElement *pipeline;
1260
1261   pipeline = gst_pipeline_new ("media-pipeline");
1262   gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
1263
1264   return pipeline;
1265 }
1266
1267 static void
1268 default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
1269 {
1270   GstRTSPMediaFactoryPrivate *priv = factory->priv;
1271   gboolean shared, eos_shutdown;
1272   guint size;
1273   GstRTSPSuspendMode suspend_mode;
1274   GstRTSPProfile profiles;
1275   GstRTSPLowerTrans protocols;
1276   GstRTSPAddressPool *pool;
1277   GstRTSPPermissions *perms;
1278   GstClockTime rtx_time;
1279   guint latency;
1280   GstRTSPTransportMode transport_mode;
1281
1282   /* configure the sharedness */
1283   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1284   suspend_mode = priv->suspend_mode;
1285   shared = priv->shared;
1286   eos_shutdown = priv->eos_shutdown;
1287   size = priv->buffer_size;
1288   profiles = priv->profiles;
1289   protocols = priv->protocols;
1290   rtx_time = priv->rtx_time;
1291   latency = priv->latency;
1292   transport_mode = priv->transport_mode;
1293   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1294
1295   gst_rtsp_media_set_suspend_mode (media, suspend_mode);
1296   gst_rtsp_media_set_shared (media, shared);
1297   gst_rtsp_media_set_eos_shutdown (media, eos_shutdown);
1298   gst_rtsp_media_set_buffer_size (media, size);
1299   gst_rtsp_media_set_profiles (media, profiles);
1300   gst_rtsp_media_set_protocols (media, protocols);
1301   gst_rtsp_media_set_retransmission_time (media, rtx_time);
1302   gst_rtsp_media_set_latency (media, latency);
1303   gst_rtsp_media_set_transport_mode (media, transport_mode);
1304
1305   if ((pool = gst_rtsp_media_factory_get_address_pool (factory))) {
1306     gst_rtsp_media_set_address_pool (media, pool);
1307     g_object_unref (pool);
1308   }
1309   if ((perms = gst_rtsp_media_factory_get_permissions (factory))) {
1310     gst_rtsp_media_set_permissions (media, perms);
1311     gst_rtsp_permissions_unref (perms);
1312   }
1313 }
1314
1315 /**
1316  * gst_rtsp_media_factory_create_element:
1317  * @factory: a #GstRTSPMediaFactory
1318  * @url: the url used
1319  *
1320  * Construct and return a #GstElement that is a #GstBin containing
1321  * the elements to use for streaming the media.
1322  *
1323  * The bin should contain payloaders pay\%d for each stream. The default
1324  * implementation of this function returns the bin created from the
1325  * launch parameter.
1326  *
1327  * Returns: (transfer floating): a new #GstElement.
1328  */
1329 GstElement *
1330 gst_rtsp_media_factory_create_element (GstRTSPMediaFactory * factory,
1331     const GstRTSPUrl * url)
1332 {
1333   GstRTSPMediaFactoryClass *klass;
1334   GstElement *result;
1335
1336   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
1337   g_return_val_if_fail (url != NULL, NULL);
1338
1339   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1340
1341   if (klass->create_element)
1342     result = klass->create_element (factory, url);
1343   else
1344     result = NULL;
1345
1346   return result;
1347 }
1348
1349 /**
1350  * gst_rtsp_media_factory_set_transport_mode:
1351  * @factory: a #GstRTSPMediaFactory
1352  * @mode: the new value
1353  *
1354  * Configure if this factory creates media for PLAY or RECORD modes.
1355  */
1356 void
1357 gst_rtsp_media_factory_set_transport_mode (GstRTSPMediaFactory * factory,
1358     GstRTSPTransportMode mode)
1359 {
1360   GstRTSPMediaFactoryPrivate *priv;
1361
1362   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
1363
1364   priv = factory->priv;
1365
1366   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1367   priv->transport_mode = mode;
1368   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1369 }
1370
1371 /**
1372  * gst_rtsp_media_factory_get_transport_mode:
1373  * @factory: a #GstRTSPMediaFactory
1374  *
1375  * Get if media created from this factory can be used for PLAY or RECORD
1376  * methods.
1377  *
1378  * Returns: The supported transport modes.
1379  */
1380 GstRTSPTransportMode
1381 gst_rtsp_media_factory_get_transport_mode (GstRTSPMediaFactory * factory)
1382 {
1383   GstRTSPMediaFactoryPrivate *priv;
1384   GstRTSPTransportMode result;
1385
1386   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
1387
1388   priv = factory->priv;
1389
1390   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
1391   result = priv->transport_mode;
1392   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
1393
1394   return result;
1395 }