Commit 369a7322 authored by Martin Storsjö's avatar Martin Storsjö

omxil: Split omx core management to a separate file

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: default avatarMartin Storsjö <martin@martin.st>
parent d5dd3255
...@@ -186,7 +186,7 @@ libomxil_plugin_la_SOURCES = \ ...@@ -186,7 +186,7 @@ libomxil_plugin_la_SOURCES = \
omxil/utils.c omxil/omxil_utils.h \ omxil/utils.c omxil/omxil_utils.h \
h264_nal.h \ h264_nal.h \
omxil/qcom.c omxil/qcom.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_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/omxil
libomxil_plugin_la_LIBADD = $(AM_LIBADD) $(LIBDL) libomxil_plugin_la_LIBADD = $(AM_LIBADD) $(LIBDL)
......
...@@ -28,17 +28,6 @@ ...@@ -28,17 +28,6 @@
# include "config.h" # include "config.h"
#endif #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 <limits.h>
#include <vlc_common.h> #include <vlc_common.h>
...@@ -49,6 +38,7 @@ ...@@ -49,6 +38,7 @@
#include "../h264_nal.h" #include "../h264_nal.h"
#include "omxil.h" #include "omxil.h"
#include "omxil_core.h"
#ifndef NDEBUG #ifndef NDEBUG
# define OMXIL_EXTRA_DEBUG # define OMXIL_EXTRA_DEBUG
...@@ -56,35 +46,6 @@ ...@@ -56,35 +46,6 @@
#define SENTINEL_FLAG 0x10000 #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 * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -129,72 +90,6 @@ vlc_module_begin () ...@@ -129,72 +90,6 @@ vlc_module_begin ()
set_callbacks( OpenEncoder, CloseGeneric ) set_callbacks( OpenEncoder, CloseGeneric )
vlc_module_end () 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 * ImplementationSpecificWorkarounds: place-holder for implementation
* specific workarounds * specific workarounds
...@@ -874,45 +769,14 @@ static int OpenGeneric( vlc_object_t *p_this, bool b_encode ) ...@@ -874,45 +769,14 @@ static int OpenGeneric( vlc_object_t *p_this, bool b_encode )
OMX_BUFFERHEADERTYPE *p_header; OMX_BUFFERHEADERTYPE *p_header;
unsigned int i, j; unsigned int i, j;
vlc_mutex_lock( &omx_core_mutex ); if (InitOmxCore(p_this) != VLC_SUCCESS) {
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 );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
loaded:
/* Allocate the memory needed to store the decoder's structure */ /* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL ) if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
{ {
if( omx_refcount == 0 ) DeinitOmxCore();
dll_close(dll_handle);
vlc_mutex_unlock( &omx_core_mutex );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
...@@ -949,25 +813,13 @@ loaded: ...@@ -949,25 +813,13 @@ loaded:
msg_Dbg(p_dec, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec->fmt_in.i_codec, 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); (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 */ /* 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 : GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec :
p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat, 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", msg_Warn( p_this, "couldn't find an omx component for codec %4.4s",
(char *)&p_dec->fmt_in.i_codec ); (char *)&p_dec->fmt_in.i_codec );
...@@ -1688,14 +1540,8 @@ static void CloseGeneric( vlc_object_t *p_this ) ...@@ -1688,14 +1540,8 @@ static void CloseGeneric( vlc_object_t *p_this )
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
if(p_sys->omx_handle) DeinitialiseComponent(p_dec, p_sys->omx_handle); if(p_sys->omx_handle) DeinitialiseComponent(p_dec, p_sys->omx_handle);
vlc_mutex_lock( &omx_core_mutex );
omx_refcount--; DeinitOmxCore();
if( omx_refcount == 0 )
{
if( p_sys->b_init ) pf_deinit();
dll_close( dll_handle );
}
vlc_mutex_unlock( &omx_core_mutex );
vlc_mutex_destroy (&p_sys->mutex); vlc_mutex_destroy (&p_sys->mutex);
vlc_cond_destroy (&p_sys->cond); vlc_cond_destroy (&p_sys->cond);
......
...@@ -30,11 +30,7 @@ ...@@ -30,11 +30,7 @@
#include "OMX_Video.h" #include "OMX_Video.h"
#include "omxil_utils.h" #include "omxil_utils.h"
#include "omxil_core.h"
/*****************************************************************************
* defines
*****************************************************************************/
#define MAX_COMPONENTS_LIST_SIZE 32
/***************************************************************************** /*****************************************************************************
* decoder_sys_t : omxil decoder descriptor * decoder_sys_t : omxil decoder descriptor
...@@ -80,7 +76,6 @@ struct decoder_sys_t ...@@ -80,7 +76,6 @@ struct decoder_sys_t
OMX_HANDLETYPE omx_handle; OMX_HANDLETYPE omx_handle;
bool b_enc; bool b_enc;
bool b_init;
char psz_component[OMX_MAX_STRINGNAME_SIZE]; char psz_component[OMX_MAX_STRINGNAME_SIZE];
char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE]; char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE];
......
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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]);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment