From: Felipe C. <fel...@no...> - 2010-03-03 22:43:46
|
From: Rob Clark <ro...@ti...> 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 <fel...@no...> --- 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 |