1 /*****************************************************************************
2 * omxil.c: Video decoder module making use of OpenMAX IL components.
3 *****************************************************************************
4 * Copyright (C) 2010 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 /* On dll_open, just check that the OMX_Init symbol already is loaded */
34 # define dll_open(name) dlsym(RTLD_DEFAULT, "OMX_Init")
35 # define dll_close(handle) do { } while (0)
36 # define dlsym(handle, name) dlsym(RTLD_DEFAULT, "I" name)
38 # define dll_open(name) dlopen( name, RTLD_NOW )
39 # define dll_close(handle) dlclose(handle)
42 #include <vlc_common.h>
43 #include <vlc_plugin.h>
44 #include <vlc_codec.h>
45 #include <vlc_block_helper.h>
49 #include "omxil_core.h"
51 /*****************************************************************************
52 * List of OpenMAX IL core we will try in order
53 *****************************************************************************/
54 static const char *ppsz_dll_list[] =
57 "libiomx.so", /* Not used when using IOMX, the lib should already be loaded */
58 #elif defined(RPI_OMX)
59 "/opt/vc/lib/libopenmaxil.so", /* Broadcom IL core */
61 "libOMX_Core.so", /* TI OMAP IL core */
62 "libOmxCore.so", /* Qualcomm IL core */
63 "libomxil-bellagio.so", /* Bellagio IL core */
64 "libnvomx.so", /* Tegra3 IL core */
70 static const char *ppsz_extra_dll_list[] =
72 "/opt/vc/lib/libbcm_host.so", /* Broadcom host library */
77 /*****************************************************************************
78 * Global OMX Core instance, shared between module instances
79 *****************************************************************************/
80 static vlc_mutex_t omx_core_mutex = VLC_STATIC_MUTEX;
81 static unsigned int omx_refcount = 0;
82 static void *dll_handle;
83 OMX_ERRORTYPE (*pf_init) (void);
84 OMX_ERRORTYPE (*pf_deinit) (void);
85 OMX_ERRORTYPE (*pf_get_handle) (OMX_HANDLETYPE *, OMX_STRING,
86 OMX_PTR, OMX_CALLBACKTYPE *);
87 OMX_ERRORTYPE (*pf_free_handle) (OMX_HANDLETYPE);
88 OMX_ERRORTYPE (*pf_component_enum)(OMX_STRING, OMX_U32, OMX_U32);
89 OMX_ERRORTYPE (*pf_get_roles_of_component)(OMX_STRING, OMX_U32 *, OMX_U8 **);
90 OMX_ERRORTYPE (*pf_enable_graphic_buffers)(OMX_HANDLETYPE, OMX_U32, OMX_BOOL);
91 OMX_ERRORTYPE (*pf_get_graphic_buffer_usage)(OMX_HANDLETYPE, OMX_U32, OMX_U32*);
93 int (*pf_omx_hwbuffer_connect) (void *);
94 int (*pf_omx_hwbuffer_disconnect) (void *);
95 int (*pf_omx_hwbuffer_get_hal_format) (const char *, int *);
96 int (*pf_omx_hwbuffer_setup) (void *, int, int, int, int );
97 int (*pf_omx_hwbuffer_get_min_undequeued) (void *, unsigned int *);
98 int (*pf_omx_hwbuffer_set_buffer_count) (void *, unsigned int );
99 int (*pf_omx_hwbuffer_setcrop) (void *, int, int, int, int);
100 int (*pf_omx_hwbuffer_dequeue) (void *, void **);
101 int (*pf_omx_hwbuffer_lock) (void *, void *);
102 int (*pf_omx_hwbuffer_queue) (void *, void *);
103 int (*pf_omx_hwbuffer_cancel) (void *, void *);
106 static void *extra_dll_handle;
107 static void (*pf_host_init)(void);
108 static void (*pf_host_deinit)(void);
110 static void CloseExtraDll()
114 // Intentionally not unloading the host library, since it cannot be
115 // unloaded cleanly after it has been initialized.
118 #define CloseExtraDll()
121 int InitOmxCore(vlc_object_t *p_this)
124 vlc_mutex_lock( &omx_core_mutex );
125 if( omx_refcount > 0 ) {
127 vlc_mutex_unlock( &omx_core_mutex );
132 /* Load an extra library first, if available */
133 extra_dll_handle = NULL;
134 for( i = 0; ppsz_extra_dll_list[i]; i++ )
136 extra_dll_handle = dll_open( ppsz_extra_dll_list[i] );
137 if( extra_dll_handle ) break;
139 if( extra_dll_handle )
141 pf_host_init = dlsym( extra_dll_handle, "bcm_host_init" );
142 pf_host_deinit = dlsym( extra_dll_handle, "bcm_host_deinit" );
148 /* Load the OMX core */
149 for( i = 0; ppsz_dll_list[i]; i++ )
151 dll_handle = dll_open( ppsz_dll_list[i] );
152 if( dll_handle ) break;
157 vlc_mutex_unlock( &omx_core_mutex );
161 pf_init = dlsym( dll_handle, "OMX_Init" );
162 pf_deinit = dlsym( dll_handle, "OMX_Deinit" );
163 pf_get_handle = dlsym( dll_handle, "OMX_GetHandle" );
164 pf_free_handle = dlsym( dll_handle, "OMX_FreeHandle" );
165 pf_component_enum = dlsym( dll_handle, "OMX_ComponentNameEnum" );
166 pf_get_roles_of_component = dlsym( dll_handle, "OMX_GetRolesOfComponent" );
167 if( !pf_init || !pf_deinit || !pf_get_handle || !pf_free_handle ||
168 !pf_component_enum || !pf_get_roles_of_component )
170 msg_Warn( p_this, "cannot find OMX_* symbols in `%s' (%s)",
171 ppsz_dll_list[i], dlerror() );
172 dll_close(dll_handle);
174 vlc_mutex_unlock( &omx_core_mutex );
177 #if defined(USE_IOMX)
178 pf_enable_graphic_buffers = dlsym( dll_handle, "OMXAndroid_EnableGraphicBuffers" );
179 pf_get_graphic_buffer_usage = dlsym( dll_handle, "OMXAndroid_GetGraphicBufferUsage" );
181 pf_omx_hwbuffer_connect = dlsym( dll_handle, "OMXHWBuffer_Connect" );
182 pf_omx_hwbuffer_disconnect = dlsym( dll_handle, "OMXHWBuffer_Disconnect" );
183 pf_omx_hwbuffer_get_hal_format = dlsym( dll_handle, "OMXHWBuffer_GetHalFormat" );
184 pf_omx_hwbuffer_setup = dlsym( dll_handle, "OMXHWBuffer_Setup" );
185 pf_omx_hwbuffer_get_min_undequeued = dlsym( dll_handle, "OMXHWBuffer_GetMinUndequeued" );
186 pf_omx_hwbuffer_set_buffer_count = dlsym( dll_handle, "OMXHWBuffer_SetBufferCount" );
187 pf_omx_hwbuffer_setcrop = dlsym( dll_handle, "OMXHWBuffer_Setcrop" );
188 pf_omx_hwbuffer_dequeue = dlsym( dll_handle, "OMXHWBuffer_Dequeue" );
189 pf_omx_hwbuffer_lock = dlsym( dll_handle, "OMXHWBuffer_Lock" );
190 pf_omx_hwbuffer_queue = dlsym( dll_handle, "OMXHWBuffer_Queue" );
191 pf_omx_hwbuffer_cancel = dlsym( dll_handle, "OMXHWBuffer_Cancel" );
194 /* Initialise the OMX core */
195 OMX_ERRORTYPE omx_error = pf_init();
196 if(omx_error != OMX_ErrorNone)
198 msg_Warn( p_this, "OMX_Init failed (%x: %s)", omx_error,
199 ErrorToString(omx_error) );
200 dll_close(dll_handle);
202 vlc_mutex_unlock( &omx_core_mutex );
206 vlc_mutex_unlock( &omx_core_mutex );
210 void DeinitOmxCore(void)
212 vlc_mutex_lock( &omx_core_mutex );
214 if( omx_refcount == 0 )
217 dll_close( dll_handle );
220 vlc_mutex_unlock( &omx_core_mutex );
223 /*****************************************************************************
224 * CreateComponentsList: creates a list of components matching the given role
225 *****************************************************************************/
229 const char *psz_role;
230 const char *psz_name;
234 { "video_decoder.avc", "OMX.broadcom.video_decode" },
235 { "video_decoder.mpeg2", "OMX.broadcom.video_decode" },
236 { "iv_renderer", "OMX.broadcom.video_render" },
241 int CreateComponentsList(vlc_object_t *p_this, const char *psz_role,
242 char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE])
244 char psz_name[OMX_MAX_STRINGNAME_SIZE];
245 OMX_ERRORTYPE omx_error;
247 OMX_U8 **ppsz_roles = 0;
248 unsigned int i, j, components = 0;
250 if(!psz_role) goto end;
254 bool b_found = false;
256 omx_error = pf_component_enum(psz_name, OMX_MAX_STRINGNAME_SIZE, i);
257 if(omx_error != OMX_ErrorNone) break;
259 msg_Dbg(p_this, "component %s", psz_name);
261 for( unsigned int j = 0; role_mappings[j].psz_role; j++ ) {
262 if( !strcmp( psz_role, role_mappings[j].psz_role ) &&
263 !strcmp( psz_name, role_mappings[j].psz_name ) ) {
268 omx_error = pf_get_roles_of_component(psz_name, &roles, 0);
269 if(omx_error != OMX_ErrorNone || !roles) continue;
271 ppsz_roles = malloc(roles * (sizeof(OMX_U8*) + OMX_MAX_STRINGNAME_SIZE));
272 if(!ppsz_roles) continue;
274 for( j = 0; j < roles; j++ )
275 ppsz_roles[j] = ((OMX_U8 *)(&ppsz_roles[roles])) +
276 j * OMX_MAX_STRINGNAME_SIZE;
278 omx_error = pf_get_roles_of_component(psz_name, &roles, ppsz_roles);
279 if(omx_error != OMX_ErrorNone) roles = 0;
281 for(j = 0; j < roles; j++)
283 msg_Dbg(p_this, " - role: %s", ppsz_roles[j]);
284 if(!strcmp((char *)ppsz_roles[j], psz_role)) b_found = true;
289 if(!b_found) continue;
292 if(components >= MAX_COMPONENTS_LIST_SIZE)
294 msg_Dbg(p_this, "too many matching components");
298 strncpy(ppsz_components[components], psz_name,
299 OMX_MAX_STRINGNAME_SIZE-1);
304 msg_Dbg(p_this, "found %i matching components for role %s",
305 components, psz_role);
306 for( i = 0; i < components; i++ )
307 msg_Dbg(p_this, "- %s", ppsz_components[i]);