rtsp-client: don't use g_object_unref on GstRTSPSessionMedia
[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  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "rtsp-media-factory.h"
21
22 #define DEFAULT_LAUNCH          NULL
23 #define DEFAULT_SHARED          FALSE
24 #define DEFAULT_EOS_SHUTDOWN    FALSE
25 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
26 #define DEFAULT_BUFFER_SIZE     0x80000
27 #define DEFAULT_MULTICAST_GROUP "224.2.0.1"
28
29 enum
30 {
31   PROP_0,
32   PROP_LAUNCH,
33   PROP_SHARED,
34   PROP_EOS_SHUTDOWN,
35   PROP_PROTOCOLS,
36   PROP_BUFFER_SIZE,
37   PROP_MULTICAST_GROUP,
38   PROP_LAST
39 };
40
41 enum
42 {
43   SIGNAL_MEDIA_CONSTRUCTED,
44   SIGNAL_MEDIA_CONFIGURE,
45   SIGNAL_LAST
46 };
47
48 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
49 #define GST_CAT_DEFAULT rtsp_media_debug
50
51 static guint gst_rtsp_media_factory_signals[SIGNAL_LAST] = { 0 };
52
53 static void gst_rtsp_media_factory_get_property (GObject * object, guint propid,
54     GValue * value, GParamSpec * pspec);
55 static void gst_rtsp_media_factory_set_property (GObject * object, guint propid,
56     const GValue * value, GParamSpec * pspec);
57 static void gst_rtsp_media_factory_finalize (GObject * obj);
58
59 static gchar *default_gen_key (GstRTSPMediaFactory * factory,
60     const GstRTSPUrl * url);
61 static GstElement *default_get_element (GstRTSPMediaFactory * factory,
62     const GstRTSPUrl * url);
63 static GstRTSPMedia *default_construct (GstRTSPMediaFactory * factory,
64     const GstRTSPUrl * url);
65 static void default_configure (GstRTSPMediaFactory * factory,
66     GstRTSPMedia * media);
67 static GstElement *default_create_pipeline (GstRTSPMediaFactory * factory,
68     GstRTSPMedia * media);
69
70 G_DEFINE_TYPE (GstRTSPMediaFactory, gst_rtsp_media_factory, G_TYPE_OBJECT);
71
72 static void
73 gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
74 {
75   GObjectClass *gobject_class;
76
77   gobject_class = G_OBJECT_CLASS (klass);
78
79   gobject_class->get_property = gst_rtsp_media_factory_get_property;
80   gobject_class->set_property = gst_rtsp_media_factory_set_property;
81   gobject_class->finalize = gst_rtsp_media_factory_finalize;
82
83   /**
84    * GstRTSPMediaFactory::launch
85    *
86    * The gst_parse_launch() line to use for constructing the pipeline in the
87    * default prepare vmethod.
88    *
89    * The pipeline description should return a GstBin as the toplevel element
90    * which can be accomplished by enclosing the dscription with brackets '('
91    * ')'.
92    *
93    * The description should return a pipeline with payloaders named pay0, pay1,
94    * etc.. Each of the payloaders will result in a stream.
95    *
96    * Support for dynamic payloaders can be accomplished by adding payloaders
97    * named dynpay0, dynpay1, etc..
98    */
99   g_object_class_install_property (gobject_class, PROP_LAUNCH,
100       g_param_spec_string ("launch", "Launch",
101           "A launch description of the pipeline", DEFAULT_LAUNCH,
102           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
103
104   g_object_class_install_property (gobject_class, PROP_SHARED,
105       g_param_spec_boolean ("shared", "Shared",
106           "If media from this factory is shared", DEFAULT_SHARED,
107           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
108
109   g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
110       g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
111           "Send EOS down the pipeline before shutting down",
112           DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
113
114   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
115       g_param_spec_flags ("protocols", "Protocols",
116           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
117           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
118
119   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
120       g_param_spec_uint ("buffer-size", "Buffer Size",
121           "The kernel UDP buffer size to use", 0, G_MAXUINT,
122           DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
123
124   g_object_class_install_property (gobject_class, PROP_MULTICAST_GROUP,
125       g_param_spec_string ("multicast-group", "Multicast Group",
126           "The Multicast group to send media to",
127           DEFAULT_MULTICAST_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
128
129   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] =
130       g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass),
131       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
132           media_constructed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
133       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
134
135   gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE] =
136       g_signal_new ("media-configure", G_TYPE_FROM_CLASS (klass),
137       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
138           media_configure), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
139       G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
140
141   klass->gen_key = default_gen_key;
142   klass->get_element = default_get_element;
143   klass->construct = default_construct;
144   klass->configure = default_configure;
145   klass->create_pipeline = default_create_pipeline;
146
147   GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmediafactory", 0,
148       "GstRTSPMediaFactory");
149 }
150
151 static void
152 gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
153 {
154   factory->launch = g_strdup (DEFAULT_LAUNCH);
155   factory->shared = DEFAULT_SHARED;
156   factory->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
157   factory->protocols = DEFAULT_PROTOCOLS;
158   factory->buffer_size = DEFAULT_BUFFER_SIZE;
159   factory->multicast_group = g_strdup (DEFAULT_MULTICAST_GROUP);
160
161   g_mutex_init (&factory->lock);
162   g_mutex_init (&factory->medias_lock);
163   factory->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
164       g_free, g_object_unref);
165 }
166
167 static void
168 gst_rtsp_media_factory_finalize (GObject * obj)
169 {
170   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
171
172   g_hash_table_unref (factory->medias);
173   g_mutex_clear (&factory->medias_lock);
174   g_free (factory->launch);
175   g_free (factory->multicast_group);
176   g_mutex_clear (&factory->lock);
177   if (factory->auth)
178     g_object_unref (factory->auth);
179
180   G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
181 }
182
183 static void
184 gst_rtsp_media_factory_get_property (GObject * object, guint propid,
185     GValue * value, GParamSpec * pspec)
186 {
187   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
188
189   switch (propid) {
190     case PROP_LAUNCH:
191       g_value_take_string (value, gst_rtsp_media_factory_get_launch (factory));
192       break;
193     case PROP_SHARED:
194       g_value_set_boolean (value, gst_rtsp_media_factory_is_shared (factory));
195       break;
196     case PROP_EOS_SHUTDOWN:
197       g_value_set_boolean (value,
198           gst_rtsp_media_factory_is_eos_shutdown (factory));
199       break;
200     case PROP_PROTOCOLS:
201       g_value_set_flags (value, gst_rtsp_media_factory_get_protocols (factory));
202       break;
203     case PROP_BUFFER_SIZE:
204       g_value_set_uint (value,
205           gst_rtsp_media_factory_get_buffer_size (factory));
206       break;
207     case PROP_MULTICAST_GROUP:
208       g_value_take_string (value,
209           gst_rtsp_media_factory_get_multicast_group (factory));
210       break;
211     default:
212       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
213   }
214 }
215
216 static void
217 gst_rtsp_media_factory_set_property (GObject * object, guint propid,
218     const GValue * value, GParamSpec * pspec)
219 {
220   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
221
222   switch (propid) {
223     case PROP_LAUNCH:
224       gst_rtsp_media_factory_set_launch (factory, g_value_get_string (value));
225       break;
226     case PROP_SHARED:
227       gst_rtsp_media_factory_set_shared (factory, g_value_get_boolean (value));
228       break;
229     case PROP_EOS_SHUTDOWN:
230       gst_rtsp_media_factory_set_eos_shutdown (factory,
231           g_value_get_boolean (value));
232       break;
233     case PROP_PROTOCOLS:
234       gst_rtsp_media_factory_set_protocols (factory, g_value_get_flags (value));
235       break;
236     case PROP_BUFFER_SIZE:
237       gst_rtsp_media_factory_set_buffer_size (factory,
238           g_value_get_uint (value));
239       break;
240     case PROP_MULTICAST_GROUP:
241       gst_rtsp_media_factory_set_multicast_group (factory,
242           g_value_get_string (value));
243       break;
244     default:
245       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
246   }
247 }
248
249 /**
250  * gst_rtsp_media_factory_new:
251  *
252  * Create a new #GstRTSPMediaFactory instance.
253  *
254  * Returns: a new #GstRTSPMediaFactory object.
255  */
256 GstRTSPMediaFactory *
257 gst_rtsp_media_factory_new (void)
258 {
259   GstRTSPMediaFactory *result;
260
261   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY, NULL);
262
263   return result;
264 }
265
266 /**
267  * gst_rtsp_media_factory_set_launch:
268  * @factory: a #GstRTSPMediaFactory
269  * @launch: the launch description
270  *
271  *
272  * The gst_parse_launch() line to use for constructing the pipeline in the
273  * default prepare vmethod.
274  *
275  * The pipeline description should return a GstBin as the toplevel element
276  * which can be accomplished by enclosing the dscription with brackets '('
277  * ')'.
278  *
279  * The description should return a pipeline with payloaders named pay0, pay1,
280  * etc.. Each of the payloaders will result in a stream.
281  */
282 void
283 gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
284     const gchar * launch)
285 {
286   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
287   g_return_if_fail (launch != NULL);
288
289   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
290   g_free (factory->launch);
291   factory->launch = g_strdup (launch);
292   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
293 }
294
295 /**
296  * gst_rtsp_media_factory_get_launch:
297  * @factory: a #GstRTSPMediaFactory
298  *
299  * Get the gst_parse_launch() pipeline description that will be used in the
300  * default prepare vmethod.
301  *
302  * Returns: the configured launch description. g_free() after usage.
303  */
304 gchar *
305 gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory)
306 {
307   gchar *result;
308
309   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
310
311   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
312   result = g_strdup (factory->launch);
313   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
314
315   return result;
316 }
317
318 /**
319  * gst_rtsp_media_factory_set_shared:
320  * @factory: a #GstRTSPMediaFactory
321  * @shared: the new value
322  *
323  * Configure if media created from this factory can be shared between clients.
324  */
325 void
326 gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
327     gboolean shared)
328 {
329   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
330
331   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
332   factory->shared = shared;
333   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
334 }
335
336 /**
337  * gst_rtsp_media_factory_is_shared:
338  * @factory: a #GstRTSPMediaFactory
339  *
340  * Get if media created from this factory can be shared between clients.
341  *
342  * Returns: %TRUE if the media will be shared between clients.
343  */
344 gboolean
345 gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory)
346 {
347   gboolean result;
348
349   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
350
351   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
352   result = factory->shared;
353   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
354
355   return result;
356 }
357
358 /**
359  * gst_rtsp_media_factory_set_eos_shutdown:
360  * @factory: a #GstRTSPMediaFactory
361  * @eos_shutdown: the new value
362  *
363  * Configure if media created from this factory will have an EOS sent to the
364  * pipeline before shutdown.
365  */
366 void
367 gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
368     gboolean eos_shutdown)
369 {
370   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
371
372   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
373   factory->eos_shutdown = eos_shutdown;
374   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
375 }
376
377 /**
378  * gst_rtsp_media_factory_is_eos_shutdown:
379  * @factory: a #GstRTSPMediaFactory
380  *
381  * Get if media created from this factory will have an EOS event sent to the
382  * pipeline before shutdown.
383  *
384  * Returns: %TRUE if the media will receive EOS before shutdown.
385  */
386 gboolean
387 gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory)
388 {
389   gboolean result;
390
391   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
392
393   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
394   result = factory->eos_shutdown;
395   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
396
397   return result;
398 }
399
400 /**
401  * gst_rtsp_media_factory_set_buffer_size:
402  * @factory: a #GstRTSPMedia
403  * @size: the new value
404  *
405  * Set the kernel UDP buffer size.
406  */
407 void
408 gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
409     guint size)
410 {
411   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
412
413   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
414   factory->buffer_size = size;
415   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
416 }
417
418 /**
419  * gst_rtsp_media_factory_get_buffer_size:
420  * @factory: a #GstRTSPMedia
421  *
422  * Get the kernel UDP buffer size.
423  *
424  * Returns: the kernel UDP buffer size.
425  */
426 guint
427 gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
428 {
429   guint result;
430
431   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
432
433   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
434   result = factory->buffer_size;
435   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
436
437   return result;
438 }
439
440 /**
441  * gst_rtsp_media_factory_set_multicast_group:
442  * @factory: a #GstRTSPMedia
443  * @mc: the new multicast group
444  *
445  * Set the multicast group that media from @factory will be streamed to.
446  */
447 void
448 gst_rtsp_media_factory_set_multicast_group (GstRTSPMediaFactory * factory,
449     const gchar * mc)
450 {
451   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
452
453   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
454   g_free (factory->multicast_group);
455   factory->multicast_group = g_strdup (mc);
456   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
457 }
458
459 /**
460  * gst_rtsp_media_factory_get_multicast_group:
461  * @factory: a #GstRTSPMedia
462  *
463  * Get the multicast group that media from @factory will be streamed to.
464  *
465  * Returns: the multicast group
466  */
467 gchar *
468 gst_rtsp_media_factory_get_multicast_group (GstRTSPMediaFactory * factory)
469 {
470   gchar *result;
471
472   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
473
474   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
475   result = g_strdup (factory->multicast_group);
476   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
477
478   return result;
479 }
480
481 /**
482  * gst_rtsp_media_factory_set_auth:
483  * @factory: a #GstRTSPMediaFactory
484  * @auth: a #GstRTSPAuth
485  *
486  * configure @auth to be used as the authentication manager of @factory.
487  */
488 void
489 gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory,
490     GstRTSPAuth * auth)
491 {
492   GstRTSPAuth *old;
493
494   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
495
496   old = factory->auth;
497
498   if (old != auth) {
499     if (auth)
500       g_object_ref (auth);
501     factory->auth = auth;
502     if (old)
503       g_object_unref (old);
504   }
505 }
506
507 /**
508  * gst_rtsp_media_factory_get_auth:
509  * @factory: a #GstRTSPMediaFactory
510  *
511  * Get the #GstRTSPAuth used as the authentication manager of @factory.
512  *
513  * Returns: the #GstRTSPAuth of @factory. g_object_unref() after
514  * usage.
515  */
516 GstRTSPAuth *
517 gst_rtsp_media_factory_get_auth (GstRTSPMediaFactory * factory)
518 {
519   GstRTSPAuth *result;
520
521   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
522
523   if ((result = factory->auth))
524     g_object_ref (result);
525
526   return result;
527 }
528
529 /**
530  * gst_rtsp_media_factory_set_protocols:
531  * @factory: a #GstRTSPMediaFactory
532  * @protocols: the new flags
533  *
534  * Configure the allowed lower transport for @factory.
535  */
536 void
537 gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
538     GstRTSPLowerTrans protocols)
539 {
540   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
541
542   factory->protocols = protocols;
543 }
544
545 /**
546  * gst_rtsp_media_factory_get_protocols:
547  * @factory: a #GstRTSPMediaFactory
548  *
549  * Get the allowed protocols of @factory.
550  *
551  * Returns: a #GstRTSPLowerTrans
552  */
553 GstRTSPLowerTrans
554 gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
555 {
556   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
557       GST_RTSP_LOWER_TRANS_UNKNOWN);
558
559   return factory->protocols;
560 }
561
562 static gboolean
563 compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2)
564 {
565   return (media1 == media2);
566 }
567
568 static void
569 media_unprepared (GstRTSPMedia * media, GstRTSPMediaFactory * factory)
570 {
571   g_mutex_lock (&factory->medias_lock);
572   g_hash_table_foreach_remove (factory->medias, (GHRFunc) compare_media, media);
573   g_mutex_unlock (&factory->medias_lock);
574 }
575
576 /**
577  * gst_rtsp_media_factory_construct:
578  * @factory: a #GstRTSPMediaFactory
579  * @url: the url used
580  *
581  * Prepare the media object and create its streams. Implementations
582  * should create the needed gstreamer elements and add them to the result
583  * object. No state changes should be performed on them yet.
584  *
585  * One or more GstRTSPMediaStream objects should be added to the result with
586  * the srcpad member set to a source pad that produces buffer of type 
587  * application/x-rtp.
588  *
589  * Returns: a new #GstRTSPMedia if the media could be prepared.
590  */
591 GstRTSPMedia *
592 gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
593     const GstRTSPUrl * url)
594 {
595   gchar *key;
596   GstRTSPMedia *media;
597   GstRTSPMediaFactoryClass *klass;
598
599   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
600
601   /* convert the url to a key for the hashtable. NULL return or a NULL function
602    * will not cache anything for this factory. */
603   if (klass->gen_key)
604     key = klass->gen_key (factory, url);
605   else
606     key = NULL;
607
608   g_mutex_lock (&factory->medias_lock);
609   if (key) {
610     /* we have a key, see if we find a cached media */
611     media = g_hash_table_lookup (factory->medias, key);
612     if (media)
613       g_object_ref (media);
614   } else
615     media = NULL;
616
617   if (media == NULL) {
618     /* nothing cached found, try to create one */
619     if (klass->construct) {
620       media = klass->construct (factory, url);
621       if (media)
622         g_signal_emit (factory,
623             gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED], 0, media,
624             NULL);
625     } else
626       media = NULL;
627
628     if (media) {
629       /* configure the media */
630       if (klass->configure)
631         klass->configure (factory, media);
632
633       g_signal_emit (factory,
634           gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE], 0, media,
635           NULL);
636
637       /* check if we can cache this media */
638       if (gst_rtsp_media_is_shared (media)) {
639         /* insert in the hashtable, takes ownership of the key */
640         g_object_ref (media);
641         g_hash_table_insert (factory->medias, key, media);
642         key = NULL;
643       }
644       if (!gst_rtsp_media_is_reusable (media)) {
645         /* when not reusable, connect to the unprepare signal to remove the item
646          * from our cache when it gets unprepared */
647         g_signal_connect (media, "unprepared", (GCallback) media_unprepared,
648             factory);
649       }
650     }
651   }
652   g_mutex_unlock (&factory->medias_lock);
653
654   if (key)
655     g_free (key);
656
657   GST_INFO ("constructed media %p for url %s", media, url->abspath);
658
659   return media;
660 }
661
662 static gchar *
663 default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
664 {
665   gchar *result;
666   const gchar *pre_query;
667   const gchar *query;
668
669   pre_query = url->query ? "?" : "";
670   query = url->query ? url->query : "";
671
672   result =
673       g_strdup_printf ("%u%s%s%s", url->port, url->abspath, pre_query, query);
674
675   return result;
676 }
677
678 static GstElement *
679 default_get_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
680 {
681   GstElement *element;
682   GError *error = NULL;
683
684   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
685   /* we need a parse syntax */
686   if (factory->launch == NULL)
687     goto no_launch;
688
689   /* parse the user provided launch line */
690   element = gst_parse_launch (factory->launch, &error);
691   if (element == NULL)
692     goto parse_error;
693
694   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
695
696   if (error != NULL) {
697     /* a recoverable error was encountered */
698     GST_WARNING ("recoverable parsing error: %s", error->message);
699     g_error_free (error);
700   }
701   return element;
702
703   /* ERRORS */
704 no_launch:
705   {
706     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
707     g_critical ("no launch line specified");
708     return NULL;
709   }
710 parse_error:
711   {
712     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
713     g_critical ("could not parse launch syntax (%s): %s", factory->launch,
714         (error ? error->message : "unknown reason"));
715     if (error)
716       g_error_free (error);
717     return NULL;
718   }
719 }
720
721 /* try to find all the payloader elements, they should be named 'pay%d'. for
722  * each of the payloaders we will create a stream and collect the source pad. */
723 void
724 gst_rtsp_media_factory_collect_streams (GstRTSPMediaFactory * factory,
725     const GstRTSPUrl * url, GstRTSPMedia * media)
726 {
727   GstElement *element, *elem;
728   GstPad *pad;
729   gint i;
730   GstRTSPMediaStream *stream;
731   gboolean have_elem;
732
733   element = media->element;
734
735   have_elem = TRUE;
736   for (i = 0; have_elem; i++) {
737     gchar *name;
738
739     have_elem = FALSE;
740
741     name = g_strdup_printf ("pay%d", i);
742     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
743       /* create the stream */
744       stream = g_new0 (GstRTSPMediaStream, 1);
745       stream->payloader = elem;
746
747       GST_INFO ("found stream %d with payloader %p", i, elem);
748
749       pad = gst_element_get_static_pad (elem, "src");
750
751       /* ghost the pad of the payloader to the element */
752       stream->srcpad = gst_ghost_pad_new (name, pad);
753       g_object_unref (pad);
754       gst_pad_set_active (stream->srcpad, TRUE);
755       gst_element_add_pad (media->element, stream->srcpad);
756       gst_object_unref (elem);
757
758       /* add stream now */
759       g_array_append_val (media->streams, stream);
760       have_elem = TRUE;
761     }
762     g_free (name);
763
764     name = g_strdup_printf ("dynpay%d", i);
765     if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
766       /* a stream that will dynamically create pads to provide RTP packets */
767
768       GST_INFO ("found dynamic element %d, %p", i, elem);
769
770       media->dynamic = g_list_prepend (media->dynamic, elem);
771
772       have_elem = TRUE;
773     }
774     g_free (name);
775   }
776 }
777
778 static GstRTSPMedia *
779 default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
780 {
781   GstRTSPMedia *media;
782   GstElement *element;
783   GstRTSPMediaFactoryClass *klass;
784
785   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
786
787   if (!klass->create_pipeline)
788     goto no_create;
789
790   if (klass->get_element)
791     element = klass->get_element (factory, url);
792   else
793     element = NULL;
794   if (element == NULL)
795     goto no_element;
796
797   /* create a new empty media */
798   media = gst_rtsp_media_new ();
799   media->element = element;
800
801   media->pipeline = klass->create_pipeline (factory, media);
802   if (media->pipeline == NULL)
803     goto no_pipeline;
804
805   gst_rtsp_media_factory_collect_streams (factory, url, media);
806
807   return media;
808
809   /* ERRORS */
810 no_create:
811   {
812     g_critical ("no create_pipeline function");
813     return NULL;
814   }
815 no_element:
816   {
817     g_critical ("could not create element");
818     return NULL;
819   }
820 no_pipeline:
821   {
822     g_critical ("can't create pipeline");
823     g_object_unref (media);
824     return NULL;
825   }
826 }
827
828 static GstElement *
829 default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
830 {
831   GstElement *pipeline;
832
833   if (media->element == NULL)
834     goto no_element;
835
836   pipeline = gst_pipeline_new ("media-pipeline");
837   gst_bin_add (GST_BIN_CAST (pipeline), media->element);
838
839   return pipeline;
840
841   /* ERRORS */
842 no_element:
843   {
844     g_critical ("no element");
845     return NULL;
846   }
847 }
848
849 static void
850 default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
851 {
852   gboolean shared, eos_shutdown;
853   guint size;
854   GstRTSPAuth *auth;
855   GstRTSPLowerTrans protocols;
856   gchar *mc;
857
858   /* configure the sharedness */
859   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
860   shared = factory->shared;
861   eos_shutdown = factory->eos_shutdown;
862   size = factory->buffer_size;
863   protocols = factory->protocols;
864   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
865
866   gst_rtsp_media_set_shared (media, shared);
867   gst_rtsp_media_set_eos_shutdown (media, eos_shutdown);
868   gst_rtsp_media_set_buffer_size (media, size);
869   gst_rtsp_media_set_protocols (media, protocols);
870
871   if ((auth = gst_rtsp_media_factory_get_auth (factory))) {
872     gst_rtsp_media_set_auth (media, auth);
873     g_object_unref (auth);
874   }
875   if ((mc = gst_rtsp_media_factory_get_multicast_group (factory))) {
876     gst_rtsp_media_set_multicast_group (media, mc);
877     g_free (mc);
878   }
879 }