[Gstreamer-openmax] [PATCH v3 1/3] Initial support for configuration file

Felipe Contreras felipe.contreras at nokia.com
Wed Mar 3 14:43:14 PST 2010


From: Rob Clark <rob at ti.com>

Configurable mapping between gst-openmax elements and OMX library-name
and component-name via config file. The config file may even create
multiple different elements with unique names using the same gst-openmax
class but different OMX library-name and/or component-name.

In the simple case, of one OMX component per gst-openmax class, specify
the gst-openmax class as the 'type', and the 'library-name' and
'compnent-name' of the OMX component, and optionally the 'rank'
(defaults to 0 or GST_RANK_NONE):

----
omx_h264dec,
  type=GstOmxH264Dec,
  library-name=libomxil-bellagio.so.0,
  component-name=OMX.st.video_decoder.avc,
  rank=256;
----

Or in the advanced case of multiple OMX components per gst-openmax
class, specify the gst-openmax class as the 'parent-type' and a
dynamically created sub-class for the 'type':

----
omx_mp3dec_ti,
  parent-type=GstOmxMp3Dec,
  type=GstOmxMp3DecTi
  library-name=libOMX_Core.so.0,
  component-name=OMX.TI.AUDIO.DECODE,
  component-role=audio_decode.dsp.mp3,
  rank=256;

omx_mp3dec_nokia,
  parent-type=GstOmxMp3Dec,
  type=GstOmxMp3DecNokia
  library-name=libomxil_bellagio.so.0,
  component-name=OMX.nokia.audio_decode.mp3,
  rank=128;
----

By default, the config file is stored in $HOME/.config/gst-openmax.conf,
although if none is found a default config will be created.

Modified by Felipe Contreras to keep using the library and component
names through qdata. Plus a bunch of cleanups and reorganization.

Signed-off-by: Felipe Contreras <felipe.contreras at nokia.com>
---
 omx/gstomx.c |  264 ++++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 211 insertions(+), 53 deletions(-)

diff --git a/omx/gstomx.c b/omx/gstomx.c
index 6756f54..8b082a2 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -21,6 +21,10 @@
 
 #include "config.h"
 
+#include <string.h>
+
+#include <gst/gststructure.h>
+
 #include "gstomx.h"
 #include "gstomx_dummy.h"
 #include "gstomx_mpeg4dec.h"
@@ -59,85 +63,239 @@
 
 GST_DEBUG_CATEGORY (gstomx_debug);
 
-typedef struct TableItem
-{
-    const gchar *name;
-    const gchar *library_name;
-    const gchar *component_name;
-    guint rank;
-    GType (*get_type) (void);
-} TableItem;
-
-static TableItem element_table[] =
-{
-    { "omx_dummy", "libomxil-bellagio.so.0", "OMX.st.dummy", GST_RANK_NONE, gst_omx_dummy_get_type },
-    { "omx_mpeg4dec", "libomxil-bellagio.so.0", "OMX.st.video_decoder.mpeg4", GST_RANK_PRIMARY, gst_omx_mpeg4dec_get_type },
-    { "omx_h264dec", "libomxil-bellagio.so.0", "OMX.st.video_decoder.avc", GST_RANK_PRIMARY, gst_omx_h264dec_get_type },
-    { "omx_h263dec", "libomxil-bellagio.so.0", "OMX.st.video_decoder.h263", GST_RANK_PRIMARY, gst_omx_h263dec_get_type },
-    { "omx_wmvdec", "libomxil-bellagio.so.0", "OMX.st.video_decoder.wmv", GST_RANK_PRIMARY, gst_omx_wmvdec_get_type },
-    { "omx_mpeg4enc", "libomxil-bellagio.so.0", "OMX.st.video_encoder.mpeg4", GST_RANK_PRIMARY, gst_omx_mpeg4enc_get_type },
-    { "omx_h264enc", "libomxil-bellagio.so.0", "OMX.st.video_encoder.avc", GST_RANK_PRIMARY, gst_omx_h264enc_get_type },
-    { "omx_h263enc", "libomxil-bellagio.so.0", "OMX.st.video_encoder.h263", GST_RANK_PRIMARY, gst_omx_h263enc_get_type },
-    { "omx_vorbisdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.ogg.single", GST_RANK_SECONDARY, gst_omx_vorbisdec_get_type },
-    { "omx_mp3dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.mp3.mad", GST_RANK_PRIMARY, gst_omx_mp3dec_get_type },
+static GstStructure *element_table = NULL;
+static GQuark element_name_quark;
+
+const gchar *default_config = NULL;
+
+static GType (*get_type[]) (void) = {
+    gst_omx_dummy_get_type,
+    gst_omx_mpeg4dec_get_type,
+    gst_omx_h264dec_get_type,
+    gst_omx_h263dec_get_type,
+    gst_omx_wmvdec_get_type,
+    gst_omx_mpeg4enc_get_type,
+    gst_omx_h264enc_get_type,
+    gst_omx_h263enc_get_type,
+    gst_omx_vorbisdec_get_type,
+    gst_omx_mp3dec_get_type,
 #ifdef EXPERIMENTAL
-    { "omx_mp2dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.mp3.mad", GST_RANK_PRIMARY, gst_omx_mp2dec_get_type },
-    { "omx_amrnbdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.amrnb", GST_RANK_PRIMARY, gst_omx_amrnbdec_get_type },
-    { "omx_amrnbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrnb", GST_RANK_PRIMARY, gst_omx_amrnbenc_get_type },
-    { "omx_amrwbdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.amrwb", GST_RANK_PRIMARY, gst_omx_amrwbdec_get_type },
-    { "omx_amrwbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrwb", GST_RANK_PRIMARY, gst_omx_amrwbenc_get_type },
-    { "omx_aacdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.aac", GST_RANK_PRIMARY, gst_omx_aacdec_get_type },
-    { "omx_aacenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.aac", GST_RANK_PRIMARY, gst_omx_aacenc_get_type },
-    { "omx_adpcmdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.adpcm", GST_RANK_PRIMARY, gst_omx_adpcmdec_get_type },
-    { "omx_adpcmenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.adpcm", GST_RANK_PRIMARY, gst_omx_adpcmenc_get_type },
-    { "omx_g711dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.g711", GST_RANK_PRIMARY, gst_omx_g711dec_get_type },
-    { "omx_g711enc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.g711", GST_RANK_PRIMARY, gst_omx_g711enc_get_type },
-    { "omx_g729dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.g729", GST_RANK_PRIMARY, gst_omx_g729dec_get_type },
-    { "omx_g729enc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.g729", GST_RANK_PRIMARY, gst_omx_g729enc_get_type },
-    { "omx_ilbcdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.ilbc", GST_RANK_PRIMARY, gst_omx_ilbcdec_get_type },
-    { "omx_ilbcenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.ilbc", GST_RANK_PRIMARY, gst_omx_ilbcenc_get_type },
-    { "omx_jpegenc", "libomxil-bellagio.so.0", "OMX.st.image_encoder.jpeg", GST_RANK_PRIMARY, gst_omx_jpegenc_get_type },
+    gst_omx_mp2dec_get_type,
+    gst_omx_amrnbdec_get_type,
+    gst_omx_amrnbenc_get_type,
+    gst_omx_amrwbdec_get_type,
+    gst_omx_amrwbenc_get_type,
+    gst_omx_aacdec_get_type,
+    gst_omx_aacenc_get_type,
+    gst_omx_adpcmdec_get_type,
+    gst_omx_adpcmenc_get_type,
+    gst_omx_g711dec_get_type,
+    gst_omx_g711enc_get_type,
+    gst_omx_g729dec_get_type,
+    gst_omx_g729enc_get_type,
+    gst_omx_ilbcdec_get_type,
+    gst_omx_ilbcenc_get_type,
+    gst_omx_jpegenc_get_type,
 #endif /* EXPERIMENTAL */
-    { "omx_audiosink", "libomxil-bellagio.so.0", "OMX.st.alsa.alsasink", GST_RANK_NONE, gst_omx_audiosink_get_type },
+    gst_omx_audiosink_get_type,
 #ifdef EXPERIMENTAL
-    { "omx_videosink", "libomxil-bellagio.so.0", "OMX.st.videosink", GST_RANK_NONE, gst_omx_videosink_get_type },
-    { "omx_filereadersrc", "libomxil-bellagio.so.0", "OMX.st.audio_filereader", GST_RANK_NONE, gst_omx_filereadersrc_get_type },
+    gst_omx_videosink_get_type,
+    gst_omx_filereadersrc_get_type,
 #endif /* EXPERIMENTAL */
-    { "omx_volume", "libomxil-bellagio.so.0", "OMX.st.volume.component", GST_RANK_NONE, gst_omx_volume_get_type },
-    { NULL, NULL, NULL, 0, NULL },
+    gst_omx_volume_get_type,
 };
 
+/**
+ * @todo find a way to call plugin_init() when the config file changes
+ * @todo support a system-wide config file
+ * @todo provide a recommended system-wide config file
+ */
+
+/* TODO: we can cache table w/ gst_plugin_{get,set}_cache_data..
+ */
+static GstStructure *
+get_element_table (void)
+{
+    static volatile gsize gonce_data = 0;
+    if (g_once_init_enter (&gonce_data))
+    {
+        gchar *path;
+        gchar *config, *s;
+        GstStructure *element;
+
+        path = g_strdup (g_getenv ("OMX_REGISTRY"));
+        if (!path)
+        {
+            path = g_build_filename (g_get_user_config_dir (),
+                    "gst-openmax.conf", NULL);
+        }
+
+        if (!g_file_get_contents (path, &config, NULL, NULL))
+        {
+            g_warning ("could not find config file '%s'.. using defaults!", path);
+            config = (gchar *) default_config;
+        }
+
+        g_free (path);
+
+        GST_DEBUG ("parsing config:\n%s", config);
+
+        element_table = gst_structure_empty_new ("element_table");
+
+        s = config;
+
+        while ((element = gst_structure_from_string (s, &s)))
+        {
+            const gchar *element_name = gst_structure_get_name (element);
+            gst_structure_set (element_table,
+                    element_name, GST_TYPE_STRUCTURE, element, NULL);
+        }
+
+        if (config != default_config)
+            g_free (config);
+
+        GST_DEBUG ("element_table=%" GST_PTR_FORMAT, element_table);
+
+        g_once_init_leave (&gonce_data, 1);
+    }
+
+    return element_table;
+}
+
+static GstStructure *
+get_element_entry (const gchar *element_name)
+{
+    GstStructure *element_table = get_element_table ();
+    GstStructure *element;
+
+    if (!gst_structure_get (element_table, element_name,
+                            GST_TYPE_STRUCTURE, &element, NULL))
+    {
+        element = NULL;
+    }
+
+    /* This assert should never fail, because plugin elements are registered
+     * based on the entries in this table.  Someone would have to manually
+     * override the type qdata for this to fail.
+     */
+    g_assert (element);
+
+    return element;
+}
+
+/* register a new dynamic sub-class with the name 'type_name'.. this gives us
+ * a way to use the same (for example) GstOmxMp3Dec element mapping to
+ * multiple different element names with different OMX library implementations
+ * and/or component names
+ */
+static GType
+create_subtype (GType parent_type, const gchar *type_name)
+{
+    GTypeQuery q;
+    GTypeInfo i = {0};
+
+    if (!type_name)
+        return 0;
+
+    g_type_query (parent_type, &q);
+
+    i.class_size = q.class_size;
+    i.instance_size = q.instance_size;
+
+    return g_type_register_static (parent_type, type_name, &i, 0);
+}
+
 static gboolean
 plugin_init (GstPlugin *plugin)
 {
     GQuark library_name_quark;
     GQuark component_name_quark;
+    gint i, cnt;
+    GstStructure *element_table;
+
     GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-openmax");
     GST_DEBUG_CATEGORY_INIT (gstomx_util_debug, "omx_util", 0, "gst-openmax utility");
 
     library_name_quark = g_quark_from_static_string ("library-name");
     component_name_quark = g_quark_from_static_string ("component-name");
+    element_name_quark = g_quark_from_static_string ("element-name");
+
+    /*
+     * First, call all the _get_type() functions to ensure the types are
+     * registered.
+     */
+    for (i = 0; i < G_N_ELEMENTS (get_type); i++)
+        get_type[i] ();
+
+    element_table = get_element_table ();
 
     g_omx_init ();
 
+    cnt = gst_structure_n_fields (element_table);
+    for (i = 0; i < cnt; i++)
     {
-        guint i;
-        for (i = 0; element_table[i].name; i++)
-        {
-            TableItem *element;
-            GType type;
+        const gchar *element_name = gst_structure_nth_field_name (element_table, i);
+        GstStructure *element = get_element_entry (element_name);
+        const gchar *type_name, *parent_type_name;
+        const gchar *component_name, *library_name;
+        GType type;
+        gint rank;
 
-            element = &element_table[i];
-            type = element->get_type ();
-            g_type_set_qdata (type, library_name_quark, (gpointer) element->library_name);
-            g_type_set_qdata (type, component_name_quark, (gpointer) element->component_name);
+        GST_DEBUG ("element_name=%s, element=%" GST_PTR_FORMAT, element_name, element);
 
-            if (!gst_element_register (plugin, element->name, element->rank, type))
+        parent_type_name = gst_structure_get_string (element, "parent-type");
+        type_name = gst_structure_get_string (element, "type");
+        component_name = gst_structure_get_string (element, "component-name");
+        library_name = gst_structure_get_string (element, "library-name");
+
+        if (!type_name || !component_name || !library_name)
+        {
+            g_warning ("malformed config file: missing required fields for %s",
+                       element_name);
+            return FALSE;
+        }
+
+        if (parent_type_name)
+        {
+            type = g_type_from_name (parent_type_name);
+            if (type)
+            {
+                type = create_subtype (type, type_name);
+            }
+            else
             {
-                g_warning ("failed registering '%s'", element->name);
+                g_warning ("malformed config file: invalid parent-type '%s' for %s",
+                           parent_type_name, element_name);
                 return FALSE;
             }
         }
+        else
+        {
+            type = g_type_from_name (type_name);
+        }
+
+        if (!type)
+        {
+            g_warning ("malformed config file: invalid type '%s' for %s",
+                       type_name, element_name);
+            return FALSE;
+        }
+
+        g_type_set_qdata (type, library_name_quark, (gpointer) library_name);
+        g_type_set_qdata (type, component_name_quark, (gpointer) component_name);
+        g_type_set_qdata (type, element_name_quark, (gpointer) element_name);
+
+        if (!gst_structure_get_int (element, "rank", &rank))
+        {
+            /* use default rank: */
+            rank = GST_RANK_NONE;
+        }
+
+        if (!gst_element_register (plugin, element_name, rank, type))
+        {
+            g_warning ("failed registering '%s'", element_name);
+            return FALSE;
+        }
     }
 
     return TRUE;
-- 
1.7.0.1





More information about the Gstreamer-openmax mailing list