]> git.sesse.net Git - vlc/blob - modules/codec/omxil/omxil_core.c
iomx: Move hal_format overriding into iomx_hwbuffer
[vlc] / modules / codec / omxil / omxil_core.c
1 /*****************************************************************************
2  * omxil.c: Video decoder module making use of OpenMAX IL components.
3  *****************************************************************************
4  * Copyright (C) 2010 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <dlfcn.h>
32 #if defined(USE_IOMX)
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)
37 #else
38 # define dll_open(name) dlopen( name, RTLD_NOW )
39 # define dll_close(handle) dlclose(handle)
40 #endif
41
42 #include <vlc_common.h>
43 #include <vlc_plugin.h>
44 #include <vlc_codec.h>
45 #include <vlc_block_helper.h>
46 #include <vlc_cpu.h>
47
48 #include "omxil.h"
49 #include "omxil_core.h"
50
51 /*****************************************************************************
52  * List of OpenMAX IL core we will try in order
53  *****************************************************************************/
54 static const char *ppsz_dll_list[] =
55 {
56 #if defined(USE_IOMX)
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 */
60 #else
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 */
65 #endif
66     0
67 };
68
69 #ifdef RPI_OMX
70 static const char *ppsz_extra_dll_list[] =
71 {
72     "/opt/vc/lib/libbcm_host.so",  /* Broadcom host library */
73     0
74 };
75 #endif
76
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*);
92
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 *);
104
105 #ifdef RPI_OMX
106 static void *extra_dll_handle;
107 static void (*pf_host_init)(void);
108 static void (*pf_host_deinit)(void);
109
110 static void CloseExtraDll()
111 {
112     if (pf_host_deinit)
113         pf_host_deinit();
114     // Intentionally not unloading the host library, since it cannot be
115     // unloaded cleanly after it has been initialized.
116 }
117 #else
118 #define CloseExtraDll()
119 #endif
120
121 int InitOmxCore(vlc_object_t *p_this)
122 {
123     int i;
124     vlc_mutex_lock( &omx_core_mutex );
125     if( omx_refcount > 0 ) {
126         omx_refcount++;
127         vlc_mutex_unlock( &omx_core_mutex );
128         return VLC_SUCCESS;
129     }
130
131 #ifdef RPI_OMX
132     /* Load an extra library first, if available */
133     extra_dll_handle = NULL;
134     for( i = 0; ppsz_extra_dll_list[i]; i++ )
135     {
136         extra_dll_handle = dll_open( ppsz_extra_dll_list[i] );
137         if( extra_dll_handle ) break;
138     }
139     if( extra_dll_handle )
140     {
141         pf_host_init = dlsym( extra_dll_handle, "bcm_host_init" );
142         pf_host_deinit = dlsym( extra_dll_handle, "bcm_host_deinit" );
143         if (pf_host_init)
144             pf_host_init();
145     }
146 #endif
147
148     /* Load the OMX core */
149     for( i = 0; ppsz_dll_list[i]; i++ )
150     {
151         dll_handle = dll_open( ppsz_dll_list[i] );
152         if( dll_handle ) break;
153     }
154     if( !dll_handle )
155     {
156         CloseExtraDll();
157         vlc_mutex_unlock( &omx_core_mutex );
158         return VLC_EGENERIC;
159     }
160
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 )
169     {
170         msg_Warn( p_this, "cannot find OMX_* symbols in `%s' (%s)",
171                   ppsz_dll_list[i], dlerror() );
172         dll_close(dll_handle);
173         CloseExtraDll();
174         vlc_mutex_unlock( &omx_core_mutex );
175         return VLC_EGENERIC;
176     }
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" );
180
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" );
192 #endif
193
194     /* Initialise the OMX core */
195     OMX_ERRORTYPE omx_error = pf_init();
196     if(omx_error != OMX_ErrorNone)
197     {
198         msg_Warn( p_this, "OMX_Init failed (%x: %s)", omx_error,
199                   ErrorToString(omx_error) );
200         dll_close(dll_handle);
201         CloseExtraDll();
202         vlc_mutex_unlock( &omx_core_mutex );
203         return VLC_EGENERIC;
204     }
205     omx_refcount++;
206     vlc_mutex_unlock( &omx_core_mutex );
207     return VLC_SUCCESS;
208 }
209
210 void DeinitOmxCore(void)
211 {
212     vlc_mutex_lock( &omx_core_mutex );
213     omx_refcount--;
214     if( omx_refcount == 0 )
215     {
216         pf_deinit();
217         dll_close( dll_handle );
218         CloseExtraDll();
219     }
220     vlc_mutex_unlock( &omx_core_mutex );
221 }
222
223 /*****************************************************************************
224  * CreateComponentsList: creates a list of components matching the given role
225  *****************************************************************************/
226
227 static const struct
228 {
229     const char *psz_role;
230     const char *psz_name;
231 } role_mappings[] =
232 {
233 #ifdef RPI_OMX
234     { "video_decoder.avc", "OMX.broadcom.video_decode" },
235     { "video_decoder.mpeg2", "OMX.broadcom.video_decode" },
236     { "iv_renderer", "OMX.broadcom.video_render" },
237 #endif
238     { 0, 0 }
239 };
240
241 int CreateComponentsList(vlc_object_t *p_this, const char *psz_role,
242                          char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE])
243 {
244     char psz_name[OMX_MAX_STRINGNAME_SIZE];
245     OMX_ERRORTYPE omx_error;
246     OMX_U32 roles = 0;
247     OMX_U8 **ppsz_roles = 0;
248     unsigned int i, j, components = 0;
249
250     if(!psz_role) goto end;
251
252     for( i = 0; ; i++ )
253     {
254         bool b_found = false;
255
256         omx_error = pf_component_enum(psz_name, OMX_MAX_STRINGNAME_SIZE, i);
257         if(omx_error != OMX_ErrorNone) break;
258
259         msg_Dbg(p_this, "component %s", psz_name);
260
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 ) ) {
264                 goto found;
265             }
266         }
267
268         omx_error = pf_get_roles_of_component(psz_name, &roles, 0);
269         if(omx_error != OMX_ErrorNone || !roles) continue;
270
271         ppsz_roles = malloc(roles * (sizeof(OMX_U8*) + OMX_MAX_STRINGNAME_SIZE));
272         if(!ppsz_roles) continue;
273
274         for( j = 0; j < roles; j++ )
275             ppsz_roles[j] = ((OMX_U8 *)(&ppsz_roles[roles])) +
276                 j * OMX_MAX_STRINGNAME_SIZE;
277
278         omx_error = pf_get_roles_of_component(psz_name, &roles, ppsz_roles);
279         if(omx_error != OMX_ErrorNone) roles = 0;
280
281         for(j = 0; j < roles; j++)
282         {
283             msg_Dbg(p_this, "  - role: %s", ppsz_roles[j]);
284             if(!strcmp((char *)ppsz_roles[j], psz_role)) b_found = true;
285         }
286
287         free(ppsz_roles);
288
289         if(!b_found) continue;
290
291 found:
292         if(components >= MAX_COMPONENTS_LIST_SIZE)
293         {
294             msg_Dbg(p_this, "too many matching components");
295             continue;
296         }
297
298         strncpy(ppsz_components[components], psz_name,
299                 OMX_MAX_STRINGNAME_SIZE-1);
300         components++;
301     }
302
303  end:
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]);
308
309     return components;
310 }
311