omxil: Split omx core management to a separate file
authorMartin Storsjö <martin@martin.st>
Mon, 11 Mar 2013 14:51:41 +0000 (16:51 +0200)
committerMartin Storsjö <martin@martin.st>
Mon, 18 Mar 2013 16:14:51 +0000 (18:14 +0200)
The point of the omx core management is to try to load and init the
OMX core once, even if there's multiple e.g. decoder instances. The
reason for this is that there are OMX cores where the deinit function
will deinitialize the whole core on the first deinit call, even if
init has been called twice.

If this file is to be built as part of multiple separate shared
plugins, each of the plugins will initialize the OMX core separately,
which could cause issues with such OMX cores.

Since the second plugin that uses the OMX core, an OMX vout plugin,
isn't used automatically, and the only OMX implementation it currently
is tested to actually work with (the Broadcom OMX core on Raspberry
Pi) doesn't have issues with being uninitialized multiple times,
there's no need to jump through hoops to fix this theoretical issue
right now though.

For reference, if we really want to make sure the omx core is loaded
and initialized only once, the plugins need to be loaded with
RTLD_GLOBAL and all the variables in omxil_core.c need to be marked
with __attribute__ ((visibility ("default"))). But that's generally
not an option, and shouldn't be necessary right now at least.

Signed-off-by: Martin Storsjö <martin@martin.st>
modules/codec/Modules.am
modules/codec/omxil/omxil.c
modules/codec/omxil/omxil.h
modules/codec/omxil/omxil_core.c [new file with mode: 0644]
modules/codec/omxil/omxil_core.h [new file with mode: 0644]

index ebd25bc..bfd8023 100644 (file)
@@ -186,7 +186,7 @@ libomxil_plugin_la_SOURCES = \
        omxil/utils.c omxil/omxil_utils.h \
        h264_nal.h \
        omxil/qcom.c omxil/qcom.h \
-       omxil/omxil.c omxil/omxil.h
+       omxil/omxil.c omxil/omxil.h omxil/omxil_core.c omxil/omxil_core.h
 libomxil_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/omxil
 libomxil_plugin_la_LIBADD = $(AM_LIBADD) $(LIBDL)
 
index 8c2595d..b6f4e6f 100644 (file)
 # include "config.h"
 #endif
 
-#include <dlfcn.h>
-#if defined(USE_IOMX)
-/* On dll_open, just check that the OMX_Init symbol already is loaded */
-# define dll_open(name) dlsym(RTLD_DEFAULT, "OMX_Init")
-# define dll_close(handle) do { } while (0)
-# define dlsym(handle, name) dlsym(RTLD_DEFAULT, "I" name)
-#else
-# define dll_open(name) dlopen( name, RTLD_NOW )
-# define dll_close(handle) dlclose(handle)
-#endif
-
 #include <limits.h>
 
 #include <vlc_common.h>
@@ -49,6 +38,7 @@
 #include "../h264_nal.h"
 
 #include "omxil.h"
+#include "omxil_core.h"
 
 #ifndef NDEBUG
 # define OMXIL_EXTRA_DEBUG
 
 #define SENTINEL_FLAG 0x10000
 
-/*****************************************************************************
- * List of OpenMAX IL core we will try in order
- *****************************************************************************/
-static const char *ppsz_dll_list[] =
-{
-#if defined(USE_IOMX)
-    "libiomx.so", /* Not used when using IOMX, the lib should already be loaded */
-#else
-    "libOMX_Core.so", /* TI OMAP IL core */
-    "libOmxCore.so", /* Qualcomm IL core */
-    "libomxil-bellagio.so",  /* Bellagio IL core */
-#endif
-    0
-};
-
-/*****************************************************************************
- * Global OMX Core instance, shared between module instances
- *****************************************************************************/
-static vlc_mutex_t omx_core_mutex = VLC_STATIC_MUTEX;
-static unsigned int omx_refcount = 0;
-static void *dll_handle;
-static OMX_ERRORTYPE (*pf_init) (void);
-static OMX_ERRORTYPE (*pf_deinit) (void);
-static OMX_ERRORTYPE (*pf_get_handle) (OMX_HANDLETYPE *, OMX_STRING,
-                                       OMX_PTR, OMX_CALLBACKTYPE *);
-static OMX_ERRORTYPE (*pf_free_handle) (OMX_HANDLETYPE);
-static OMX_ERRORTYPE (*pf_component_enum)(OMX_STRING, OMX_U32, OMX_U32);
-static OMX_ERRORTYPE (*pf_get_roles_of_component)(OMX_STRING, OMX_U32 *, OMX_U8 **);
-
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -129,72 +90,6 @@ vlc_module_begin ()
     set_callbacks( OpenEncoder, CloseGeneric )
 vlc_module_end ()
 
-/*****************************************************************************
- * CreateComponentsList: creates a list of components matching the given role
- *****************************************************************************/
-static int CreateComponentsList(decoder_t *p_dec, const char *psz_role)
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    char psz_name[OMX_MAX_STRINGNAME_SIZE];
-    OMX_ERRORTYPE omx_error;
-    OMX_U32 roles = 0;
-    OMX_U8 **ppsz_roles = 0;
-    unsigned int i, j;
-
-    if(!psz_role) goto end;
-
-    for( i = 0; ; i++ )
-    {
-        bool b_found = false;
-
-        omx_error = pf_component_enum(psz_name, OMX_MAX_STRINGNAME_SIZE, i);
-        if(omx_error != OMX_ErrorNone) break;
-
-        msg_Dbg(p_dec, "component %s", psz_name);
-
-        omx_error = pf_get_roles_of_component(psz_name, &roles, 0);
-        if(omx_error != OMX_ErrorNone || !roles) continue;
-
-        ppsz_roles = malloc(roles * (sizeof(OMX_U8*) + OMX_MAX_STRINGNAME_SIZE));
-        if(!ppsz_roles) continue;
-
-        for( j = 0; j < roles; j++ )
-            ppsz_roles[j] = ((OMX_U8 *)(&ppsz_roles[roles])) +
-                j * OMX_MAX_STRINGNAME_SIZE;
-
-        omx_error = pf_get_roles_of_component(psz_name, &roles, ppsz_roles);
-        if(omx_error != OMX_ErrorNone) roles = 0;
-
-        for(j = 0; j < roles; j++)
-        {
-            msg_Dbg(p_dec, "  - role: %s", ppsz_roles[j]);
-            if(!strcmp((char *)ppsz_roles[j], psz_role)) b_found = true;
-        }
-
-        free(ppsz_roles);
-
-        if(!b_found) continue;
-
-        if(p_sys->components >= MAX_COMPONENTS_LIST_SIZE)
-        {
-            msg_Dbg(p_dec, "too many matching components");
-            continue;
-        }
-
-        strncpy(p_sys->ppsz_components[p_sys->components], psz_name,
-                OMX_MAX_STRINGNAME_SIZE-1);
-        p_sys->components++;
-    }
-
- end:
-    msg_Dbg(p_dec, "found %i matching components for role %s",
-            p_sys->components, psz_role);
-    for( i = 0; i < p_sys->components; i++ )
-        msg_Dbg(p_dec, "- %s", p_sys->ppsz_components[i]);
-
-    return p_sys->components;
-}
-
 /*****************************************************************************
  * ImplementationSpecificWorkarounds: place-holder for implementation
  * specific workarounds
@@ -874,45 +769,14 @@ static int OpenGeneric( vlc_object_t *p_this, bool b_encode )
     OMX_BUFFERHEADERTYPE *p_header;
     unsigned int i, j;
 
-    vlc_mutex_lock( &omx_core_mutex );
-    if( omx_refcount > 0 )
-        goto loaded;
-
-    /* Load the OMX core */
-    for( i = 0; ppsz_dll_list[i]; i++ )
-    {
-        dll_handle = dll_open( ppsz_dll_list[i] );
-        if( dll_handle ) break;
-    }
-    if( !dll_handle )
-    {
-        vlc_mutex_unlock( &omx_core_mutex );
-        return VLC_EGENERIC;
-    }
-
-    pf_init = dlsym( dll_handle, "OMX_Init" );
-    pf_deinit = dlsym( dll_handle, "OMX_Deinit" );
-    pf_get_handle = dlsym( dll_handle, "OMX_GetHandle" );
-    pf_free_handle = dlsym( dll_handle, "OMX_FreeHandle" );
-    pf_component_enum = dlsym( dll_handle, "OMX_ComponentNameEnum" );
-    pf_get_roles_of_component = dlsym( dll_handle, "OMX_GetRolesOfComponent" );
-    if( !pf_init || !pf_deinit || !pf_get_handle || !pf_free_handle ||
-        !pf_component_enum || !pf_get_roles_of_component )
-    {
-        msg_Warn( p_this, "cannot find OMX_* symbols in `%s' (%s)",
-                  ppsz_dll_list[i], dlerror() );
-        dll_close(dll_handle);
-        vlc_mutex_unlock( &omx_core_mutex );
+    if (InitOmxCore(p_this) != VLC_SUCCESS) {
         return VLC_EGENERIC;
     }
 
-loaded:
     /* Allocate the memory needed to store the decoder's structure */
     if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
     {
-        if( omx_refcount == 0 )
-            dll_close(dll_handle);
-        vlc_mutex_unlock( &omx_core_mutex );
+        DeinitOmxCore();
         return VLC_ENOMEM;
     }
 
@@ -949,25 +813,13 @@ loaded:
     msg_Dbg(p_dec, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec->fmt_in.i_codec,
             (char *)&p_dec->fmt_out.i_codec);
 
-    /* Initialise the OMX core */
-    omx_error = omx_refcount > 0 ? OMX_ErrorNone : pf_init();
-    omx_refcount++;
-    if(omx_error != OMX_ErrorNone)
-    {
-        msg_Warn( p_this, "OMX_Init failed (%x: %s)", omx_error,
-                  ErrorToString(omx_error) );
-        vlc_mutex_unlock( &omx_core_mutex );
-        CloseGeneric(p_this);
-        return VLC_EGENERIC;
-    }
-    p_sys->b_init = true;
-    vlc_mutex_unlock( &omx_core_mutex );
-
     /* Enumerate components and build a list of the one we want to try */
-    if( !CreateComponentsList(p_dec,
+    p_sys->components =
+        CreateComponentsList(p_this,
              GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec :
                         p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat,
-                        p_sys->b_enc)) )
+                        p_sys->b_enc), p_sys->ppsz_components);
+    if( !p_sys->components )
     {
         msg_Warn( p_this, "couldn't find an omx component for codec %4.4s",
                   (char *)&p_dec->fmt_in.i_codec );
@@ -1688,14 +1540,8 @@ static void CloseGeneric( vlc_object_t *p_this )
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     if(p_sys->omx_handle) DeinitialiseComponent(p_dec, p_sys->omx_handle);
-    vlc_mutex_lock( &omx_core_mutex );
-    omx_refcount--;
-    if( omx_refcount == 0 )
-    {
-        if( p_sys->b_init ) pf_deinit();
-        dll_close( dll_handle );
-    }
-    vlc_mutex_unlock( &omx_core_mutex );
+
+    DeinitOmxCore();
 
     vlc_mutex_destroy (&p_sys->mutex);
     vlc_cond_destroy (&p_sys->cond);
index ceb420a..aaa1551 100644 (file)
 #include "OMX_Video.h"
 
 #include "omxil_utils.h"
-
-/*****************************************************************************
- * defines
- *****************************************************************************/
-#define MAX_COMPONENTS_LIST_SIZE 32
+#include "omxil_core.h"
 
 /*****************************************************************************
  * decoder_sys_t : omxil decoder descriptor
@@ -80,7 +76,6 @@ struct decoder_sys_t
     OMX_HANDLETYPE omx_handle;
 
     bool b_enc;
-    bool b_init;
 
     char psz_component[OMX_MAX_STRINGNAME_SIZE];
     char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE];
diff --git a/modules/codec/omxil/omxil_core.c b/modules/codec/omxil/omxil_core.c
new file mode 100644 (file)
index 0000000..907c83e
--- /dev/null
@@ -0,0 +1,210 @@
+/*****************************************************************************
+ * omxil.c: Video decoder module making use of OpenMAX IL components.
+ *****************************************************************************
+ * Copyright (C) 2010 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <dlfcn.h>
+#if defined(USE_IOMX)
+/* On dll_open, just check that the OMX_Init symbol already is loaded */
+# define dll_open(name) dlsym(RTLD_DEFAULT, "OMX_Init")
+# define dll_close(handle) do { } while (0)
+# define dlsym(handle, name) dlsym(RTLD_DEFAULT, "I" name)
+#else
+# define dll_open(name) dlopen( name, RTLD_NOW )
+# define dll_close(handle) dlclose(handle)
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_block_helper.h>
+#include <vlc_cpu.h>
+
+#include "omxil.h"
+#include "omxil_core.h"
+
+/*****************************************************************************
+ * List of OpenMAX IL core we will try in order
+ *****************************************************************************/
+static const char *ppsz_dll_list[] =
+{
+#if defined(USE_IOMX)
+    "libiomx.so", /* Not used when using IOMX, the lib should already be loaded */
+#else
+    "libOMX_Core.so", /* TI OMAP IL core */
+    "libOmxCore.so", /* Qualcomm IL core */
+    "libomxil-bellagio.so",  /* Bellagio IL core */
+#endif
+    0
+};
+
+/*****************************************************************************
+ * Global OMX Core instance, shared between module instances
+ *****************************************************************************/
+static vlc_mutex_t omx_core_mutex = VLC_STATIC_MUTEX;
+static unsigned int omx_refcount = 0;
+static void *dll_handle;
+OMX_ERRORTYPE (*pf_init) (void);
+OMX_ERRORTYPE (*pf_deinit) (void);
+OMX_ERRORTYPE (*pf_get_handle) (OMX_HANDLETYPE *, OMX_STRING,
+                                OMX_PTR, OMX_CALLBACKTYPE *);
+OMX_ERRORTYPE (*pf_free_handle) (OMX_HANDLETYPE);
+OMX_ERRORTYPE (*pf_component_enum)(OMX_STRING, OMX_U32, OMX_U32);
+OMX_ERRORTYPE (*pf_get_roles_of_component)(OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+int InitOmxCore(vlc_object_t *p_this)
+{
+    int i;
+    vlc_mutex_lock( &omx_core_mutex );
+    if( omx_refcount > 0 ) {
+        omx_refcount++;
+        vlc_mutex_unlock( &omx_core_mutex );
+        return VLC_SUCCESS;
+    }
+
+    /* Load the OMX core */
+    for( i = 0; ppsz_dll_list[i]; i++ )
+    {
+        dll_handle = dll_open( ppsz_dll_list[i] );
+        if( dll_handle ) break;
+    }
+    if( !dll_handle )
+    {
+        vlc_mutex_unlock( &omx_core_mutex );
+        return VLC_EGENERIC;
+    }
+
+    pf_init = dlsym( dll_handle, "OMX_Init" );
+    pf_deinit = dlsym( dll_handle, "OMX_Deinit" );
+    pf_get_handle = dlsym( dll_handle, "OMX_GetHandle" );
+    pf_free_handle = dlsym( dll_handle, "OMX_FreeHandle" );
+    pf_component_enum = dlsym( dll_handle, "OMX_ComponentNameEnum" );
+    pf_get_roles_of_component = dlsym( dll_handle, "OMX_GetRolesOfComponent" );
+    if( !pf_init || !pf_deinit || !pf_get_handle || !pf_free_handle ||
+        !pf_component_enum || !pf_get_roles_of_component )
+    {
+        msg_Warn( p_this, "cannot find OMX_* symbols in `%s' (%s)",
+                  ppsz_dll_list[i], dlerror() );
+        dll_close(dll_handle);
+        vlc_mutex_unlock( &omx_core_mutex );
+        return VLC_EGENERIC;
+    }
+
+    /* Initialise the OMX core */
+    OMX_ERRORTYPE omx_error = pf_init();
+    if(omx_error != OMX_ErrorNone)
+    {
+        msg_Warn( p_this, "OMX_Init failed (%x: %s)", omx_error,
+                  ErrorToString(omx_error) );
+        dll_close(dll_handle);
+        vlc_mutex_unlock( &omx_core_mutex );
+        return VLC_EGENERIC;
+    }
+    omx_refcount++;
+    vlc_mutex_unlock( &omx_core_mutex );
+    return VLC_SUCCESS;
+}
+
+void DeinitOmxCore(void)
+{
+    vlc_mutex_lock( &omx_core_mutex );
+    omx_refcount--;
+    if( omx_refcount == 0 )
+    {
+        pf_deinit();
+        dll_close( dll_handle );
+    }
+    vlc_mutex_unlock( &omx_core_mutex );
+}
+
+/*****************************************************************************
+ * CreateComponentsList: creates a list of components matching the given role
+ *****************************************************************************/
+int CreateComponentsList(vlc_object_t *p_this, const char *psz_role,
+                         char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE])
+{
+    char psz_name[OMX_MAX_STRINGNAME_SIZE];
+    OMX_ERRORTYPE omx_error;
+    OMX_U32 roles = 0;
+    OMX_U8 **ppsz_roles = 0;
+    unsigned int i, j, components = 0;
+
+    if(!psz_role) goto end;
+
+    for( i = 0; ; i++ )
+    {
+        bool b_found = false;
+
+        omx_error = pf_component_enum(psz_name, OMX_MAX_STRINGNAME_SIZE, i);
+        if(omx_error != OMX_ErrorNone) break;
+
+        msg_Dbg(p_this, "component %s", psz_name);
+
+        omx_error = pf_get_roles_of_component(psz_name, &roles, 0);
+        if(omx_error != OMX_ErrorNone || !roles) continue;
+
+        ppsz_roles = malloc(roles * (sizeof(OMX_U8*) + OMX_MAX_STRINGNAME_SIZE));
+        if(!ppsz_roles) continue;
+
+        for( j = 0; j < roles; j++ )
+            ppsz_roles[j] = ((OMX_U8 *)(&ppsz_roles[roles])) +
+                j * OMX_MAX_STRINGNAME_SIZE;
+
+        omx_error = pf_get_roles_of_component(psz_name, &roles, ppsz_roles);
+        if(omx_error != OMX_ErrorNone) roles = 0;
+
+        for(j = 0; j < roles; j++)
+        {
+            msg_Dbg(p_this, "  - role: %s", ppsz_roles[j]);
+            if(!strcmp((char *)ppsz_roles[j], psz_role)) b_found = true;
+        }
+
+        free(ppsz_roles);
+
+        if(!b_found) continue;
+
+        if(components >= MAX_COMPONENTS_LIST_SIZE)
+        {
+            msg_Dbg(p_this, "too many matching components");
+            continue;
+        }
+
+        strncpy(ppsz_components[components], psz_name,
+                OMX_MAX_STRINGNAME_SIZE-1);
+        components++;
+    }
+
+ end:
+    msg_Dbg(p_this, "found %i matching components for role %s",
+            components, psz_role);
+    for( i = 0; i < components; i++ )
+        msg_Dbg(p_this, "- %s", ppsz_components[i]);
+
+    return components;
+}
+
diff --git a/modules/codec/omxil/omxil_core.h b/modules/codec/omxil/omxil_core.h
new file mode 100644 (file)
index 0000000..b223f6b
--- /dev/null
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * omxil.c: Video decoder module making use of OpenMAX IL components.
+ *****************************************************************************
+ * Copyright (C) 2010 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "OMX_Core.h"
+
+#include <vlc_common.h>
+
+OMX_ERRORTYPE (*pf_init) (void);
+OMX_ERRORTYPE (*pf_deinit) (void);
+OMX_ERRORTYPE (*pf_get_handle) (OMX_HANDLETYPE *, OMX_STRING,
+                                OMX_PTR, OMX_CALLBACKTYPE *);
+OMX_ERRORTYPE (*pf_free_handle) (OMX_HANDLETYPE);
+OMX_ERRORTYPE (*pf_component_enum)(OMX_STRING, OMX_U32, OMX_U32);
+OMX_ERRORTYPE (*pf_get_roles_of_component)(OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+int InitOmxCore(vlc_object_t *p_this);
+void DeinitOmxCore(void);
+
+#define MAX_COMPONENTS_LIST_SIZE 32
+int CreateComponentsList(vlc_object_t *p_this, const char *psz_role,
+                         char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE]);
+