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