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

Clark, Rob rob at ti.com
Wed Mar 3 15:04:50 PST 2010


not a comment on current patch (which looks fine to me, btw), but a note about what I'm thinking for future evolution of config file..

since we are using a GstStructure as the the config file syntax, it would be really simple to start adding element specific fields.  For example, anything that subclasses GstOmxBaseVideoDec could have an optional output-formats list.  Like:


----
omx_h264dec,
 type=GstOmxH264Dec,
 library-name=libomxil-bellagio.so.0,
 component-name=OMX.st.video_decoder.avc,
 srcpad-formats=(fourcc){I420, YUY2, NV12},
 rank=256;
----

or audio decoder could have fields for supported # of channels or rates, etc, etc.

It should be really easy to add an API to take an element and field name as parameter, and return a GValue which could be dropped into the caps.


At that point, it might make sense to move the library and component name strings out of the element..  I'm not sure.  But that can come as a later patch.

(Oh, and I want to make those library-name and component-name properties as read-only too.. but also another patch)


Thoughts?


BR,
-R


On Mar 3, 2010, at 4:43 PM, Felipe Contreras wrote:

> 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