You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

272 lines
8.4 KiB

/*****************************************************************************
* omxil.c: Video decoder module making use of OpenMAX IL components.
*****************************************************************************
* Copyright (C) 2010 VLC authors and VideoLAN
*
* 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>
#define dll_open(name) dlopen( name, RTLD_NOW )
#define dll_close(handle) dlclose(handle)
#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(RPI_OMX)
"/opt/vc/lib/libopenmaxil.so", /* Broadcom IL core */
#elif 1
"libOMX_Core.so", /* TI OMAP IL core */
"libOmxCore.so", /* Qualcomm IL core */
"libnvomx.so", /* Tegra3 IL core */
#else
"libomxil-bellagio.so", /* Bellagio IL core reference implementation */
#endif
0
};
#ifdef RPI_OMX
static const char *ppsz_extra_dll_list[] =
{
"/opt/vc/lib/libbcm_host.so", /* Broadcom host library */
0
};
#endif
/*****************************************************************************
* 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 **);
#ifdef RPI_OMX
static void *extra_dll_handle;
static void (*pf_host_init)(void);
static void (*pf_host_deinit)(void);
static void CloseExtraDll()
{
if (pf_host_deinit)
pf_host_deinit();
// Intentionally not unloading the host library, since it cannot be
// unloaded cleanly after it has been initialized.
}
#else
#define CloseExtraDll()
#endif
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;
}
#ifdef RPI_OMX
/* Load an extra library first, if available */
extra_dll_handle = NULL;
for( i = 0; ppsz_extra_dll_list[i]; i++ )
{
extra_dll_handle = dll_open( ppsz_extra_dll_list[i] );
if( extra_dll_handle ) break;
}
if( extra_dll_handle )
{
pf_host_init = dlsym( extra_dll_handle, "bcm_host_init" );
pf_host_deinit = dlsym( extra_dll_handle, "bcm_host_deinit" );
if (pf_host_init)
pf_host_init();
}
#endif
/* 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 )
{
CloseExtraDll();
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);
CloseExtraDll();
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);
CloseExtraDll();
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 );
CloseExtraDll();
}
vlc_mutex_unlock( &omx_core_mutex );
}
/*****************************************************************************
* CreateComponentsList: creates a list of components matching the given role
*****************************************************************************/
static const struct
{
const char *psz_role;
const char *psz_name;
} role_mappings[] =
{
#ifdef RPI_OMX
{ "video_decoder.avc", "OMX.broadcom.video_decode" },
{ "video_decoder.mpeg2", "OMX.broadcom.video_decode" },
{ "iv_renderer", "OMX.broadcom.video_render" },
#endif
{ 0, 0 }
};
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);
for( unsigned int j = 0; role_mappings[j].psz_role; j++ ) {
if( !strcmp( psz_role, role_mappings[j].psz_role ) &&
!strcmp( psz_name, role_mappings[j].psz_name ) ) {
goto found;
}
}
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;
found:
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;
}