Initial release including wifi display based on gst-rtsp-server-1.4.1
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media-factory-uri.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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:rtsp-media-factory-uri
21  * @short_description: A factory for URI sources
22  * @see_also: #GstRTSPMediaFactory, #GstRTSPMedia
23  *
24  * This specialized #GstRTSPMediaFactory constructs media pipelines from a URI,
25  * given with gst_rtsp_media_factory_uri_set_uri().
26  *
27  * It will automatically demux and payload the different streams found in the
28  * media at URL.
29  *
30  * Last reviewed on 2013-07-11 (1.0.0)
31  */
32
33 #include <string.h>
34
35 #include "rtsp-media-factory-uri.h"
36
37 #define GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE(obj)  \
38     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIPrivate))
39
40 struct _GstRTSPMediaFactoryURIPrivate
41 {
42   GMutex lock;
43   gchar *uri;                   /* protected by lock */
44   gboolean use_gstpay;
45
46   GstCaps *raw_vcaps;
47   GstCaps *raw_acaps;
48   GList *demuxers;
49   GList *payloaders;
50   GList *decoders;
51 };
52
53 #define DEFAULT_URI         NULL
54 #define DEFAULT_USE_GSTPAY  FALSE
55
56 enum
57 {
58   PROP_0,
59   PROP_URI,
60   PROP_USE_GSTPAY,
61   PROP_LAST
62 };
63
64
65 #define RAW_VIDEO_CAPS \
66     "video/x-raw"
67
68 #define RAW_AUDIO_CAPS \
69     "audio/x-raw"
70
71 static GstStaticCaps raw_video_caps = GST_STATIC_CAPS (RAW_VIDEO_CAPS);
72 static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS (RAW_AUDIO_CAPS);
73
74 typedef struct
75 {
76   GstRTSPMediaFactoryURI *factory;
77   guint pt;
78 } FactoryData;
79
80 static void
81 free_data (FactoryData * data)
82 {
83   g_object_unref (data->factory);
84   g_free (data);
85 }
86
87 static const gchar *factory_key = "GstRTSPMediaFactoryURI";
88
89 GST_DEBUG_CATEGORY_STATIC (rtsp_media_factory_uri_debug);
90 #define GST_CAT_DEFAULT rtsp_media_factory_uri_debug
91
92 static void gst_rtsp_media_factory_uri_get_property (GObject * object,
93     guint propid, GValue * value, GParamSpec * pspec);
94 static void gst_rtsp_media_factory_uri_set_property (GObject * object,
95     guint propid, const GValue * value, GParamSpec * pspec);
96 static void gst_rtsp_media_factory_uri_finalize (GObject * obj);
97
98 static GstElement *rtsp_media_factory_uri_create_element (GstRTSPMediaFactory *
99     factory, const GstRTSPUrl * url);
100
101 G_DEFINE_TYPE (GstRTSPMediaFactoryURI, gst_rtsp_media_factory_uri,
102     GST_TYPE_RTSP_MEDIA_FACTORY);
103
104 static void
105 gst_rtsp_media_factory_uri_class_init (GstRTSPMediaFactoryURIClass * klass)
106 {
107   GObjectClass *gobject_class;
108   GstRTSPMediaFactoryClass *mediafactory_class;
109
110   g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryURIPrivate));
111
112   gobject_class = G_OBJECT_CLASS (klass);
113   mediafactory_class = GST_RTSP_MEDIA_FACTORY_CLASS (klass);
114
115   gobject_class->get_property = gst_rtsp_media_factory_uri_get_property;
116   gobject_class->set_property = gst_rtsp_media_factory_uri_set_property;
117   gobject_class->finalize = gst_rtsp_media_factory_uri_finalize;
118
119   /**
120    * GstRTSPMediaFactoryURI::uri:
121    *
122    * The uri of the resource that will be served by this factory.
123    */
124   g_object_class_install_property (gobject_class, PROP_URI,
125       g_param_spec_string ("uri", "URI",
126           "The URI of the resource to stream", DEFAULT_URI,
127           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
128   /**
129    * GstRTSPMediaFactoryURI::use-gstpay:
130    *
131    * Allow the usage of gstpay in order to avoid decoding of compressed formats
132    * without a payloader.
133    */
134   g_object_class_install_property (gobject_class, PROP_USE_GSTPAY,
135       g_param_spec_boolean ("use-gstpay", "Use gstpay",
136           "Use the gstpay payloader to avoid decoding", DEFAULT_USE_GSTPAY,
137           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
138
139   mediafactory_class->create_element = rtsp_media_factory_uri_create_element;
140
141   GST_DEBUG_CATEGORY_INIT (rtsp_media_factory_uri_debug, "rtspmediafactoryuri",
142       0, "GstRTSPMediaFactoryUri");
143 }
144
145 typedef struct
146 {
147   GList *demux;
148   GList *payload;
149   GList *decode;
150 } FilterData;
151
152 static gboolean
153 payloader_filter (GstPluginFeature * feature, FilterData * data)
154 {
155   const gchar *klass;
156   GstElementFactory *fact;
157   GList **list = NULL;
158
159   /* we only care about element factories */
160   if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
161     return FALSE;
162
163   if (gst_plugin_feature_get_rank (feature) < GST_RANK_MARGINAL)
164     return FALSE;
165
166   fact = GST_ELEMENT_FACTORY_CAST (feature);
167
168   klass = gst_element_factory_get_metadata (fact, GST_ELEMENT_METADATA_KLASS);
169
170   if (strstr (klass, "Decoder"))
171     list = &data->decode;
172   else if (strstr (klass, "Demux"))
173     list = &data->demux;
174   else if (strstr (klass, "Parser") && strstr (klass, "Codec"))
175     list = &data->demux;
176   else if (strstr (klass, "Payloader") && strstr (klass, "RTP"))
177     list = &data->payload;
178
179   if (list) {
180     GST_DEBUG ("adding %s", GST_OBJECT_NAME (fact));
181     *list = g_list_prepend (*list, gst_object_ref (fact));
182   }
183
184   return FALSE;
185 }
186
187 static void
188 gst_rtsp_media_factory_uri_init (GstRTSPMediaFactoryURI * factory)
189 {
190   GstRTSPMediaFactoryURIPrivate *priv =
191       GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE (factory);
192   FilterData data = { NULL, NULL, NULL };
193
194   GST_DEBUG_OBJECT (factory, "new");
195
196   factory->priv = priv;
197
198   priv->uri = g_strdup (DEFAULT_URI);
199   priv->use_gstpay = DEFAULT_USE_GSTPAY;
200   g_mutex_init (&priv->lock);
201
202   /* get the feature list using the filter */
203   gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter)
204       payloader_filter, FALSE, &data);
205   /* sort */
206   priv->demuxers =
207       g_list_sort (data.demux, gst_plugin_feature_rank_compare_func);
208   priv->payloaders =
209       g_list_sort (data.payload, gst_plugin_feature_rank_compare_func);
210   priv->decoders =
211       g_list_sort (data.decode, gst_plugin_feature_rank_compare_func);
212
213   priv->raw_vcaps = gst_static_caps_get (&raw_video_caps);
214   priv->raw_acaps = gst_static_caps_get (&raw_audio_caps);
215 }
216
217 static void
218 gst_rtsp_media_factory_uri_finalize (GObject * obj)
219 {
220   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (obj);
221   GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
222
223   GST_DEBUG_OBJECT (factory, "finalize");
224
225   g_free (priv->uri);
226   gst_plugin_feature_list_free (priv->demuxers);
227   gst_plugin_feature_list_free (priv->payloaders);
228   gst_plugin_feature_list_free (priv->decoders);
229   gst_caps_unref (priv->raw_vcaps);
230   gst_caps_unref (priv->raw_acaps);
231   g_mutex_clear (&priv->lock);
232
233   G_OBJECT_CLASS (gst_rtsp_media_factory_uri_parent_class)->finalize (obj);
234 }
235
236 static void
237 gst_rtsp_media_factory_uri_get_property (GObject * object, guint propid,
238     GValue * value, GParamSpec * pspec)
239 {
240   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
241   GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
242
243   switch (propid) {
244     case PROP_URI:
245       g_value_take_string (value, gst_rtsp_media_factory_uri_get_uri (factory));
246       break;
247     case PROP_USE_GSTPAY:
248       g_value_set_boolean (value, priv->use_gstpay);
249       break;
250     default:
251       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
252   }
253 }
254
255 static void
256 gst_rtsp_media_factory_uri_set_property (GObject * object, guint propid,
257     const GValue * value, GParamSpec * pspec)
258 {
259   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
260   GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
261
262   switch (propid) {
263     case PROP_URI:
264       gst_rtsp_media_factory_uri_set_uri (factory, g_value_get_string (value));
265       break;
266     case PROP_USE_GSTPAY:
267       priv->use_gstpay = g_value_get_boolean (value);
268       break;
269     default:
270       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
271   }
272 }
273
274 /**
275  * gst_rtsp_media_factory_uri_new:
276  *
277  * Create a new #GstRTSPMediaFactoryURI instance.
278  *
279  * Returns: (transfer full): a new #GstRTSPMediaFactoryURI object.
280  */
281 GstRTSPMediaFactoryURI *
282 gst_rtsp_media_factory_uri_new (void)
283 {
284   GstRTSPMediaFactoryURI *result;
285
286   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY_URI, NULL);
287
288   return result;
289 }
290
291 /**
292  * gst_rtsp_media_factory_uri_set_uri:
293  * @factory: a #GstRTSPMediaFactory
294  * @uri: the uri the stream
295  *
296  * Set the URI of the resource that will be streamed by this factory.
297  */
298 void
299 gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory,
300     const gchar * uri)
301 {
302   GstRTSPMediaFactoryURIPrivate *priv;
303
304   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory));
305   g_return_if_fail (uri != NULL);
306
307   priv = factory->priv;
308
309   g_mutex_lock (&priv->lock);
310   g_free (priv->uri);
311   priv->uri = g_strdup (uri);
312   g_mutex_unlock (&priv->lock);
313 }
314
315 /**
316  * gst_rtsp_media_factory_uri_get_uri:
317  * @factory: a #GstRTSPMediaFactory
318  *
319  * Get the URI that will provide media for this factory.
320  *
321  * Returns: (transfer full): the configured URI. g_free() after usage.
322  */
323 gchar *
324 gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory)
325 {
326   GstRTSPMediaFactoryURIPrivate *priv;
327   gchar *result;
328
329   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory), NULL);
330
331   priv = factory->priv;
332
333   g_mutex_lock (&priv->lock);
334   result = g_strdup (priv->uri);
335   g_mutex_unlock (&priv->lock);
336
337   return result;
338 }
339
340 static GstElementFactory *
341 find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps)
342 {
343   GstRTSPMediaFactoryURIPrivate *priv = urifact->priv;
344   GList *list;
345   GstElementFactory *factory = NULL;
346   gboolean autoplug_more = FALSE;
347
348   /* first find a demuxer that can link */
349   list = gst_element_factory_list_filter (priv->demuxers, caps,
350       GST_PAD_SINK, FALSE);
351
352   if (list) {
353     GstStructure *structure = gst_caps_get_structure (caps, 0);
354     gboolean parsed = FALSE;
355     gint mpegversion = 0;
356
357     if (!gst_structure_get_boolean (structure, "parsed", &parsed) &&
358         gst_structure_has_name (structure, "audio/mpeg") &&
359         gst_structure_get_int (structure, "mpegversion", &mpegversion) &&
360         (mpegversion == 2 || mpegversion == 4)) {
361       /* for AAC it's framed=true instead of parsed=true */
362       gst_structure_get_boolean (structure, "framed", &parsed);
363     }
364
365     /* Avoid plugging parsers in a loop. This is not 100% correct, as some
366      * parsers don't set parsed=true in caps. We should do something like
367      * decodebin does and track decode chains and elements plugged in those
368      * chains...
369      */
370     if (parsed) {
371       GList *walk;
372       const gchar *klass;
373
374       for (walk = list; walk; walk = walk->next) {
375         factory = GST_ELEMENT_FACTORY (walk->data);
376         klass = gst_element_factory_get_metadata (factory,
377             GST_ELEMENT_METADATA_KLASS);
378         if (strstr (klass, "Parser"))
379           /* caps have parsed=true, so skip this parser to avoid loops */
380           continue;
381
382         autoplug_more = TRUE;
383         break;
384       }
385     } else {
386       /* caps don't have parsed=true set and we have a demuxer/parser */
387       autoplug_more = TRUE;
388     }
389
390     gst_plugin_feature_list_free (list);
391   }
392
393   if (autoplug_more)
394     /* we have a demuxer, try that one first */
395     return NULL;
396
397   /* no demuxer try a depayloader */
398   list = gst_element_factory_list_filter (priv->payloaders, caps,
399       GST_PAD_SINK, FALSE);
400
401   if (list == NULL) {
402     if (priv->use_gstpay) {
403       /* no depayloader or parser/demuxer, use gstpay when allowed */
404       factory = gst_element_factory_find ("rtpgstpay");
405     } else {
406       /* no depayloader, try a decoder, we'll get to a payloader for a decoded
407        * video or audio format, worst case. */
408       list = gst_element_factory_list_filter (priv->decoders, caps,
409           GST_PAD_SINK, FALSE);
410
411       if (list != NULL) {
412         /* we have a decoder, try that one first */
413         gst_plugin_feature_list_free (list);
414         return NULL;
415       }
416     }
417   }
418
419   if (list != NULL) {
420     factory = GST_ELEMENT_FACTORY_CAST (list->data);
421     g_object_ref (factory);
422     gst_plugin_feature_list_free (list);
423   }
424   return factory;
425 }
426
427 static gboolean
428 autoplug_continue_cb (GstElement * uribin, GstPad * pad, GstCaps * caps,
429     GstElement * element)
430 {
431   FactoryData *data;
432   GstElementFactory *factory;
433
434   GST_DEBUG ("found pad %s:%s of caps %" GST_PTR_FORMAT,
435       GST_DEBUG_PAD_NAME (pad), caps);
436
437   data = g_object_get_data (G_OBJECT (element), factory_key);
438
439   if (!(factory = find_payloader (data->factory, caps)))
440     goto no_factory;
441
442   /* we found a payloader, stop autoplugging so we can plug the
443    * payloader. */
444   GST_DEBUG ("found factory %s",
445       gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
446   gst_object_unref (factory);
447
448   return FALSE;
449
450   /* ERRORS */
451 no_factory:
452   {
453     /* no payloader, continue autoplugging */
454     GST_DEBUG ("no payloader found");
455     return TRUE;
456   }
457 }
458
459 static void
460 pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
461 {
462   GstRTSPMediaFactoryURI *urifact;
463   GstRTSPMediaFactoryURIPrivate *priv;
464   FactoryData *data;
465   GstElementFactory *factory;
466   GstElement *payloader;
467   GstCaps *caps;
468   GstPad *sinkpad, *srcpad, *ghostpad;
469   GstElement *convert;
470   gchar *padname;
471
472   GST_DEBUG ("added pad %s:%s", GST_DEBUG_PAD_NAME (pad));
473
474   /* link the element now and expose the pad */
475   data = g_object_get_data (G_OBJECT (element), factory_key);
476   urifact = data->factory;
477   priv = urifact->priv;
478
479   /* ref to make refcounting easier later */
480   gst_object_ref (pad);
481   padname = gst_pad_get_name (pad);
482
483   /* get pad caps first, then call get_caps, then fail */
484   if ((caps = gst_pad_get_current_caps (pad)) == NULL)
485     if ((caps = gst_pad_query_caps (pad, NULL)) == NULL)
486       goto no_caps;
487
488   /* check for raw caps */
489   if (gst_caps_can_intersect (caps, priv->raw_vcaps)) {
490     /* we have raw video caps, insert converter */
491     convert = gst_element_factory_make ("videoconvert", NULL);
492   } else if (gst_caps_can_intersect (caps, priv->raw_acaps)) {
493     /* we have raw audio caps, insert converter */
494     convert = gst_element_factory_make ("audioconvert", NULL);
495   } else {
496     convert = NULL;
497   }
498
499   if (convert) {
500     gst_bin_add (GST_BIN_CAST (element), convert);
501     gst_element_set_state (convert, GST_STATE_PLAYING);
502
503     sinkpad = gst_element_get_static_pad (convert, "sink");
504     gst_pad_link (pad, sinkpad);
505     gst_object_unref (sinkpad);
506
507     /* unref old pad, we reffed before */
508     gst_object_unref (pad);
509
510     /* continue with new pad and caps */
511     pad = gst_element_get_static_pad (convert, "src");
512     if ((caps = gst_pad_get_current_caps (pad)) == NULL)
513       if ((caps = gst_pad_query_caps (pad, NULL)) == NULL)
514         goto no_caps;
515   }
516
517   if (!(factory = find_payloader (urifact, caps)))
518     goto no_factory;
519
520   gst_caps_unref (caps);
521
522   /* we have a payloader now */
523   GST_DEBUG ("found payloader factory %s",
524       gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
525
526   payloader = gst_element_factory_create (factory, NULL);
527   if (payloader == NULL)
528     goto no_payloader;
529
530   g_object_set (payloader, "pt", data->pt, NULL);
531   data->pt++;
532
533   if (g_object_class_find_property (G_OBJECT_GET_CLASS (payloader),
534           "buffer-list"))
535     g_object_set (payloader, "buffer-list", TRUE, NULL);
536
537   /* add the payloader to the pipeline */
538   gst_bin_add (GST_BIN_CAST (element), payloader);
539   gst_element_set_state (payloader, GST_STATE_PLAYING);
540
541   /* link the pad to the sinkpad of the payloader */
542   sinkpad = gst_element_get_static_pad (payloader, "sink");
543   gst_pad_link (pad, sinkpad);
544   gst_object_unref (sinkpad);
545   gst_object_unref (pad);
546
547   /* now expose the srcpad of the payloader as a ghostpad with the same name
548    * as the uridecodebin pad name. */
549   srcpad = gst_element_get_static_pad (payloader, "src");
550   ghostpad = gst_ghost_pad_new (padname, srcpad);
551   gst_object_unref (srcpad);
552   g_free (padname);
553
554   gst_pad_set_active (ghostpad, TRUE);
555   gst_element_add_pad (element, ghostpad);
556
557   return;
558
559   /* ERRORS */
560 no_caps:
561   {
562     GST_WARNING ("could not get caps from pad");
563     g_free (padname);
564     gst_object_unref (pad);
565     return;
566   }
567 no_factory:
568   {
569     GST_DEBUG ("no payloader found");
570     g_free (padname);
571     gst_caps_unref (caps);
572     gst_object_unref (pad);
573     return;
574   }
575 no_payloader:
576   {
577     GST_ERROR ("could not create payloader from factory");
578     g_free (padname);
579     gst_caps_unref (caps);
580     gst_object_unref (pad);
581     return;
582   }
583 }
584
585 static void
586 no_more_pads_cb (GstElement * uribin, GstElement * element)
587 {
588   GST_DEBUG ("no-more-pads");
589   gst_element_no_more_pads (element);
590 }
591
592 static GstElement *
593 rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
594     const GstRTSPUrl * url)
595 {
596   GstRTSPMediaFactoryURIPrivate *priv;
597   GstElement *topbin, *element, *uribin;
598   GstRTSPMediaFactoryURI *urifact;
599   FactoryData *data;
600
601   urifact = GST_RTSP_MEDIA_FACTORY_URI_CAST (factory);
602   priv = urifact->priv;
603
604   GST_LOG ("creating element");
605
606   topbin = gst_bin_new ("GstRTSPMediaFactoryURI");
607   g_assert (topbin != NULL);
608
609   /* our bin will dynamically expose payloaded pads */
610   element = gst_bin_new ("dynpay0");
611   g_assert (element != NULL);
612
613   uribin = gst_element_factory_make ("uridecodebin", "uribin");
614   if (uribin == NULL)
615     goto no_uridecodebin;
616
617   g_object_set (uribin, "uri", priv->uri, NULL);
618
619   /* keep factory data around */
620   data = g_new0 (FactoryData, 1);
621   data->factory = g_object_ref (factory);
622   data->pt = 96;
623
624   g_object_set_data_full (G_OBJECT (element), factory_key,
625       data, (GDestroyNotify) free_data);
626
627   /* connect to the signals */
628   g_signal_connect (uribin, "autoplug-continue",
629       (GCallback) autoplug_continue_cb, element);
630   g_signal_connect (uribin, "pad-added", (GCallback) pad_added_cb, element);
631   g_signal_connect (uribin, "no-more-pads", (GCallback) no_more_pads_cb,
632       element);
633
634   gst_bin_add (GST_BIN_CAST (element), uribin);
635   gst_bin_add (GST_BIN_CAST (topbin), element);
636
637   return topbin;
638
639 no_uridecodebin:
640   {
641     g_critical ("can't create uridecodebin element");
642     gst_object_unref (element);
643     return NULL;
644   }
645 }