71720773d28572f2b9d3725e8ed058ac6beecb6a
[profile/ivi/gst-openmax0.10.git] / omx / gstomx.c
1 /*
2  * Copyright (C) 2007-2009 Nokia Corporation.
3  *
4  * Author: Felipe Contreras <felipe.contreras@nokia.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation
9  * version 2.1 of the License.
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  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include <gst/gststructure.h>
27
28 #include "gstomx.h"
29 #include "gstomx_dummy.h"
30 #include "gstomx_mpeg4dec.h"
31 #include "gstomx_h263dec.h"
32 #include "gstomx_h264dec.h"
33 #include "gstomx_wmvdec.h"
34 #include "gstomx_mpeg4enc.h"
35 #include "gstomx_h264enc.h"
36 #include "gstomx_h263enc.h"
37 #include "gstomx_vorbisdec.h"
38 #include "gstomx_mp3dec.h"
39 #ifdef EXPERIMENTAL
40 #include "gstomx_mp2dec.h"
41 #include "gstomx_aacdec.h"
42 #include "gstomx_aacenc.h"
43 #include "gstomx_amrnbdec.h"
44 #include "gstomx_amrnbenc.h"
45 #include "gstomx_amrwbdec.h"
46 #include "gstomx_amrwbenc.h"
47 #include "gstomx_adpcmdec.h"
48 #include "gstomx_adpcmenc.h"
49 #include "gstomx_g711dec.h"
50 #include "gstomx_g711enc.h"
51 #include "gstomx_g729dec.h"
52 #include "gstomx_g729enc.h"
53 #include "gstomx_ilbcdec.h"
54 #include "gstomx_ilbcenc.h"
55 #include "gstomx_jpegenc.h"
56 #endif /* EXPERIMENTAL */
57 #include "gstomx_audiosink.h"
58 #ifdef EXPERIMENTAL
59 #include "gstomx_videosink.h"
60 #include "gstomx_filereadersrc.h"
61 #endif /* EXPERIMENTAL */
62 #include "gstomx_volume.h"
63
64 GST_DEBUG_CATEGORY (gstomx_debug);
65
66 static const GstStructure *element_table;
67 static GQuark element_name_quark;
68
69 extern const gchar *default_config;
70
71 static GType (*get_type[]) (void) = {
72   gst_omx_dummy_get_type,
73       gst_omx_mpeg4dec_get_type,
74       gst_omx_h264dec_get_type,
75       gst_omx_h263dec_get_type,
76       gst_omx_wmvdec_get_type,
77       gst_omx_mpeg4enc_get_type,
78       gst_omx_h264enc_get_type,
79       gst_omx_h263enc_get_type,
80       gst_omx_vorbisdec_get_type, gst_omx_mp3dec_get_type,
81 #ifdef EXPERIMENTAL
82       gst_omx_mp2dec_get_type,
83       gst_omx_amrnbdec_get_type,
84       gst_omx_amrnbenc_get_type,
85       gst_omx_amrwbdec_get_type,
86       gst_omx_amrwbenc_get_type,
87       gst_omx_aacdec_get_type,
88       gst_omx_aacenc_get_type,
89       gst_omx_adpcmdec_get_type,
90       gst_omx_adpcmenc_get_type,
91       gst_omx_g711dec_get_type,
92       gst_omx_g711enc_get_type,
93       gst_omx_g729dec_get_type,
94       gst_omx_g729enc_get_type,
95       gst_omx_ilbcdec_get_type,
96       gst_omx_ilbcenc_get_type, gst_omx_jpegenc_get_type,
97 #endif /* EXPERIMENTAL */
98       gst_omx_audiosink_get_type,
99 #ifdef EXPERIMENTAL
100       gst_omx_videosink_get_type, gst_omx_filereadersrc_get_type,
101 #endif /* EXPERIMENTAL */
102 gst_omx_volume_get_type,};
103
104 static gchar *
105 get_config_path (void)
106 {
107 #if 1     /* Fix_config_path */
108   return g_build_filename (OMX_CONFIG_DIRPATH, OMX_CONFIG_FILENAME, NULL);
109 #else
110   gchar *path;
111   const gchar *const *dirs;
112   int i;
113
114   path = g_strdup (g_getenv ("OMX_CONFIG"));
115
116   if (path)
117     return path;
118
119   dirs = g_get_system_config_dirs ();
120   for (i = 0; dirs[i]; i++) {
121     path =
122         g_build_filename (dirs[i], "gstreamer-0.10", "gst-openmax.conf", NULL);
123     if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
124       return path;
125     g_free (path);
126   }
127
128   return g_build_filename (g_get_user_config_dir (), "gst-openmax.conf", NULL);
129 #endif
130 }
131
132 static void
133 fetch_element_table (GstPlugin * plugin)
134 {
135   gchar *path;
136   gchar *config, *s;
137   GstStructure *tmp, *element;
138
139   element_table = gst_plugin_get_cache_data (plugin);
140
141   if (element_table)
142     return;
143
144   path = get_config_path ();
145
146   if (!g_file_get_contents (path, &config, NULL, NULL)) {
147     g_warning ("could not find config file '%s'.. using defaults!", path);
148     config = (gchar *) default_config;
149   }
150
151   gst_plugin_add_dependency_simple (plugin, "ONX_CONFIG", path, NULL,
152       GST_PLUGIN_DEPENDENCY_FLAG_NONE);
153
154   g_free (path);
155
156   GST_DEBUG ("parsing config:\n%s", config);
157
158   tmp = gst_structure_empty_new ("element_table");
159
160   s = config;
161
162   while ((element = gst_structure_from_string (s, &s))) {
163     const gchar *element_name = gst_structure_get_name (element);
164     gst_structure_set (tmp, element_name, GST_TYPE_STRUCTURE, element, NULL);
165   }
166
167   if (config != default_config)
168     g_free (config);
169
170   GST_DEBUG ("element_table=%" GST_PTR_FORMAT, tmp);
171
172   gst_plugin_set_cache_data (plugin, tmp);
173
174   element_table = tmp;
175 }
176
177 static GstStructure *
178 get_element_entry (const gchar * element_name)
179 {
180   GstStructure *element;
181
182   if (!gst_structure_get ((GstStructure *) element_table, element_name,
183           GST_TYPE_STRUCTURE, &element, NULL)) {
184     element = NULL;
185   }
186
187   /* This assert should never fail, because plugin elements are registered
188    * based on the entries in this table.  Someone would have to manually
189    * override the type qdata for this to fail.
190    */
191   g_assert (element);
192
193   return element;
194 }
195
196 /* register a new dynamic sub-class with the name 'type_name'.. this gives us
197  * a way to use the same (for example) GstOmxMp3Dec element mapping to
198  * multiple different element names with different OMX library implementations
199  * and/or component names
200  */
201 static GType
202 create_subtype (GType parent_type, const gchar * type_name)
203 {
204   GTypeQuery q;
205   GTypeInfo i = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
206
207   if (!type_name)
208     return 0;
209
210   g_type_query (parent_type, &q);
211
212   i.class_size = q.class_size;
213   i.instance_size = q.instance_size;
214
215   return g_type_register_static (parent_type, type_name, &i, 0);
216 }
217
218 static gboolean
219 plugin_init (GstPlugin * plugin)
220 {
221   guint i, cnt;
222
223   GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-openmax");
224   GST_DEBUG_CATEGORY_INIT (gstomx_util_debug, "omx_util", 0,
225       "gst-openmax utility");
226
227   element_name_quark = g_quark_from_static_string ("element-name");
228
229   /*
230    * First, call all the _get_type() functions to ensure the types are
231    * registered.
232    */
233   for (i = 0; i < G_N_ELEMENTS (get_type); i++)
234     get_type[i] ();
235
236   fetch_element_table (plugin);
237
238   g_omx_init ();
239
240   cnt = gst_structure_n_fields (element_table);
241   for (i = 0; i < cnt; i++) {
242     const gchar *element_name = gst_structure_nth_field_name (element_table, i);
243     GstStructure *element = get_element_entry (element_name);
244     const gchar *type_name, *parent_type_name;
245     const gchar *component_name, *component_role, *library_name;
246     GType type;
247     gint rank;
248
249     GST_DEBUG ("element_name=%s, element=%" GST_PTR_FORMAT, element_name,
250         element);
251
252     parent_type_name = gst_structure_get_string (element, "parent-type");
253     type_name = gst_structure_get_string (element, "type");
254     component_name = gst_structure_get_string (element, "component-name");
255     component_role = gst_structure_get_string (element, "component-role");
256     library_name = gst_structure_get_string (element, "library-name");
257
258     if (!type_name || !component_name || !library_name) {
259       g_warning ("malformed config file: missing required fields for %s",
260           element_name);
261       return FALSE;
262     }
263
264     if (parent_type_name) {
265       type = g_type_from_name (parent_type_name);
266       if (type) {
267         type = create_subtype (type, type_name);
268       } else {
269         g_warning ("malformed config file: invalid parent-type '%s' for %s",
270             parent_type_name, element_name);
271         return FALSE;
272       }
273     } else {
274       type = g_type_from_name (type_name);
275     }
276
277     if (!type) {
278       g_warning ("malformed config file: invalid type '%s' for %s",
279           type_name, element_name);
280       return FALSE;
281     }
282
283     g_type_set_qdata (type, element_name_quark, (gpointer) element_name);
284
285     if (!gst_structure_get_int (element, "rank", &rank)) {
286       /* use default rank: */
287       rank = GST_RANK_NONE;
288     }
289
290     if (!gst_element_register (plugin, element_name, rank, type)) {
291       g_warning ("failed registering '%s'", element_name);
292       return FALSE;
293     }
294   }
295
296   return TRUE;
297 }
298
299 gboolean
300 gstomx_get_component_info (void *core, GType type)
301 {
302   GOmxCore *rcore = core;
303   const gchar *element_name;
304   GstStructure *element;
305   const gchar *str;
306
307   element_name = g_type_get_qdata (type, element_name_quark);
308   element = get_element_entry (element_name);
309
310   if (!element)
311     return FALSE;
312
313   str = gst_structure_get_string (element, "library-name");
314   rcore->library_name = g_strdup (str);
315
316   str = gst_structure_get_string (element, "component-name");
317   rcore->component_name = g_strdup (str);
318
319   str = gst_structure_get_string (element, "component-role");
320   rcore->component_role = g_strdup (str);
321
322   return TRUE;
323 }
324
325 void *
326 gstomx_core_new (void *object, GType type)
327 {
328   GOmxCore *core = g_omx_core_new (object);
329   gstomx_get_component_info (core, type);
330   g_omx_core_init (core);
331   return core;
332 }
333
334 GstCaps *
335 gstomx_template_caps (GType type, const gchar * pad_name)
336 {
337   const gchar *element_name;
338   GstStructure *element;
339   const gchar *caps_str;
340
341   element_name = g_type_get_qdata (type, element_name_quark);
342   element = get_element_entry (element_name);
343
344
345   /* this shouldn't really happen.. */
346   if (!element)
347     return GST_CAPS_ANY;
348
349   caps_str = gst_structure_get_string (element, pad_name);
350
351   GST_DEBUG ("%s: %s", element_name, caps_str);
352
353   /* default to ANY.. at least for now.. maybe when everything is converted
354    * over, we should treat missing caps as a more serious condition?
355    */
356   if (!caps_str) {
357     g_warning ("%s is missing required field: %s", element_name, pad_name);
358     return GST_CAPS_ANY;
359   }
360
361   return gst_caps_from_string (caps_str);
362 }
363
364 void
365 gstomx_install_property_helper (GObjectClass * gobject_class)
366 {
367
368   g_object_class_install_property (gobject_class, ARG_COMPONENT_NAME,
369       g_param_spec_string ("component-name", "Component name",
370           "Name of the OpenMAX IL component to use",
371           NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
372
373   g_object_class_install_property (gobject_class, ARG_COMPONENT_ROLE,
374       g_param_spec_string ("component-role", "Component role",
375           "Role of the OpenMAX IL component",
376           NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
377
378   g_object_class_install_property (gobject_class, ARG_LIBRARY_NAME,
379       g_param_spec_string ("library-name", "Library name",
380           "Name of the OpenMAX IL implementation library to use",
381           NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
382 }
383
384 gboolean
385 gstomx_get_property_helper (void *core, guint prop_id, GValue * value)
386 {
387   GOmxCore *gomx = core;
388   switch (prop_id) {
389     case ARG_COMPONENT_NAME:
390       g_value_set_string (value, gomx->component_name);
391       return TRUE;
392     case ARG_COMPONENT_ROLE:
393       g_value_set_string (value, gomx->component_role);
394       return TRUE;
395     case ARG_LIBRARY_NAME:
396       g_value_set_string (value, gomx->library_name);
397       return TRUE;
398     default:
399       return FALSE;
400   }
401 }
402
403 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
404     GST_VERSION_MINOR,
405     "omx",
406     "OpenMAX IL",
407     plugin_init,
408     PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)