1 /*Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above
9 copyright notice, this list of conditions and the following
10 disclaimer in the documentation and/or other materials provided
11 with the distribution.
12 * Neither the name of The Linux Foundation nor the names of its
13 contributors may be used to endorse or promote products derived
14 from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
27
28 #define LOG_NDEBUG 0
29 #define LOG_NIDEBUG 0
30 #define LOG_TAG "qomx_image_core"
31
32 // System dependencies
33 #include <dlfcn.h>
34 #include <malloc.h>
35 #include <string.h>
36 #include <utils/Log.h>
37
38 // OpenMAX dependencies
39 #include "qomx_core.h"
40
41 #define BUFF_SIZE 255
42
43 static omx_core_t *g_omxcore;
44 static pthread_mutex_t g_omxcore_lock = PTHREAD_MUTEX_INITIALIZER;
45 static int g_omxcore_cnt = 0;
46
47 //Map the library name with the component name
48 static const comp_info_t g_comp_info[] =
49 {
50 { "OMX.qcom.image.jpeg.encoder", "libqomx_jpegenc.so" },
51 { "OMX.qcom.image.jpeg.decoder", "libqomx_jpegdec.so" },
52 { "OMX.qcom.image.jpeg.encoder_pipeline", "libqomx_jpegenc_pipe.so" }
53 };
54
55 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *acompIndex,
56 int *ainstanceIndex);
57
58 /*==============================================================================
59 * Function : OMX_Init
60 * Parameters: None
61 * Description: This is the first call that is made to the OMX Core
62 * and initializes the OMX IL core
63 ==============================================================================*/
OMX_Init()64 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init()
65 {
66 OMX_ERRORTYPE rc = OMX_ErrorNone;
67 int i = 0;
68 int comp_cnt = sizeof(g_comp_info)/sizeof(g_comp_info[0]);
69
70 pthread_mutex_lock(&g_omxcore_lock);
71
72 /* check if core is created */
73 if (g_omxcore) {
74 g_omxcore_cnt++;
75 pthread_mutex_unlock(&g_omxcore_lock);
76 return rc;
77 }
78
79 if (comp_cnt > OMX_COMP_MAX_NUM) {
80 ALOGE("%s:%d] cannot exceed max number of components",
81 __func__, __LINE__);
82 pthread_mutex_unlock(&g_omxcore_lock);
83 return OMX_ErrorUndefined;
84 }
85 /* create new global object */
86 g_omxcore = malloc(sizeof(omx_core_t));
87 if (g_omxcore) {
88 memset(g_omxcore, 0x0, sizeof(omx_core_t));
89
90 /* populate the library name and component name */
91 for (i = 0; i < comp_cnt; i++) {
92 g_omxcore->component[i].comp_name = g_comp_info[i].comp_name;
93 g_omxcore->component[i].lib_name = g_comp_info[i].lib_name;
94 }
95 g_omxcore->comp_cnt = comp_cnt;
96 g_omxcore_cnt++;
97 } else {
98 rc = OMX_ErrorInsufficientResources;
99 }
100 pthread_mutex_unlock(&g_omxcore_lock);
101 ALOGI("%s:%d] Complete %d", __func__, __LINE__, comp_cnt);
102 return rc;
103 }
104
105 /*==============================================================================
106 * Function : OMX_Deinit
107 * Parameters: None
108 * Return Value : OMX_ERRORTYPE
109 * Description: Deinit all the OMX components
110 ==============================================================================*/
OMX_Deinit()111 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit()
112 {
113 pthread_mutex_lock(&g_omxcore_lock);
114
115 if (g_omxcore_cnt == 1) {
116 if (g_omxcore) {
117 free(g_omxcore);
118 g_omxcore = NULL;
119 }
120 }
121 if (g_omxcore_cnt) {
122 g_omxcore_cnt--;
123 }
124
125 ALOGI("%s:%d] Complete", __func__, __LINE__);
126 pthread_mutex_unlock(&g_omxcore_lock);
127 return OMX_ErrorNone;
128 }
129
130 /*==============================================================================
131 * Function : get_comp_from_list
132 * Parameters: componentName
133 * Return Value : component_index
134 * Description: If the componnt is already present in the list, return the
135 * component index. If not return the next index to create the component.
136 ==============================================================================*/
get_comp_from_list(char * comp_name)137 static int get_comp_from_list(char *comp_name)
138 {
139 int index = -1, i = 0;
140
141 if (NULL == comp_name)
142 return -1;
143
144 for (i = 0; i < g_omxcore->comp_cnt; i++) {
145 if (!strcmp(g_omxcore->component[i].comp_name, comp_name)) {
146 index = i;
147 break;
148 }
149 }
150 return index;
151 }
152
153 /*==============================================================================
154 * Function : get_free_inst_idx
155 * Parameters: p_comp
156 * Return Value : The next instance index if available
157 * Description: Get the next available index for to store the new instance of the
158 * component being created.
159 *============================================================================*/
get_free_inst_idx(omx_core_component_t * p_comp)160 static int get_free_inst_idx(omx_core_component_t *p_comp)
161 {
162 int idx = -1, i = 0;
163
164 for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
165 if (NULL == p_comp->handle[i]) {
166 idx = i;
167 break;
168 }
169 }
170 return idx;
171 }
172
173 /*==============================================================================
174 * Function : OMX_GetHandle
175 * Parameters: handle, componentName, appData, callbacks
176 * Return Value : OMX_ERRORTYPE
177 * Description: Construct and load the requested omx library
178 ==============================================================================*/
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE * handle,OMX_IN OMX_STRING componentName,OMX_IN OMX_PTR appData,OMX_IN OMX_CALLBACKTYPE * callBacks)179 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
180 OMX_OUT OMX_HANDLETYPE* handle,
181 OMX_IN OMX_STRING componentName,
182 OMX_IN OMX_PTR appData,
183 OMX_IN OMX_CALLBACKTYPE* callBacks)
184 {
185 OMX_ERRORTYPE rc = OMX_ErrorNone;
186 int comp_idx = 0, inst_idx = 0;
187 char libName[BUFF_SIZE] = {0};
188 void *p_obj = NULL;
189 OMX_COMPONENTTYPE *p_comp = NULL;
190 omx_core_component_t *p_core_comp = NULL;
191 OMX_BOOL close_handle = OMX_FALSE;
192
193 if (NULL == handle) {
194 ALOGE("%s:%d] Error invalid input ", __func__, __LINE__);
195 return OMX_ErrorBadParameter;
196 }
197
198 pthread_mutex_lock(&g_omxcore_lock);
199
200 comp_idx = get_comp_from_list(componentName);
201 if (comp_idx < 0) {
202 ALOGE("%s:%d] Cannot find the component", __func__, __LINE__);
203 pthread_mutex_unlock(&g_omxcore_lock);
204 return OMX_ErrorInvalidComponent;
205 }
206 p_core_comp = &g_omxcore->component[comp_idx];
207
208 *handle = NULL;
209
210 //If component already present get the instance index
211 inst_idx = get_free_inst_idx(p_core_comp);
212 if (inst_idx < 0) {
213 ALOGE("%s:%d] Cannot alloc new instance", __func__, __LINE__);
214 rc = OMX_ErrorInvalidComponent;
215 goto error;
216 }
217
218 if (FALSE == p_core_comp->open) {
219 /* load the library */
220 p_core_comp->lib_handle = dlopen(p_core_comp->lib_name, RTLD_NOW);
221 if (NULL == p_core_comp->lib_handle) {
222 ALOGE("%s:%d] Cannot load the library", __func__, __LINE__);
223 rc = OMX_ErrorInvalidComponent;
224 goto error;
225 }
226
227 p_core_comp->open = TRUE;
228 /* Init the component and get component functions */
229 p_core_comp->create_comp_func = dlsym(p_core_comp->lib_handle,
230 "create_component_fns");
231 p_core_comp->get_instance = dlsym(p_core_comp->lib_handle, "getInstance");
232
233 close_handle = OMX_TRUE;
234 if (!p_core_comp->create_comp_func || !p_core_comp->get_instance) {
235 ALOGE("%s:%d] Cannot maps the symbols", __func__, __LINE__);
236 rc = OMX_ErrorInvalidComponent;
237 goto error;
238 }
239 }
240
241 /* Call the function from the address to create the obj */
242 p_obj = (*p_core_comp->get_instance)();
243 ALOGI("%s:%d] get instance pts is %p", __func__, __LINE__, p_obj);
244 if (NULL == p_obj) {
245 ALOGE("%s:%d] Error cannot create object", __func__, __LINE__);
246 rc = OMX_ErrorInvalidComponent;
247 goto error;
248 }
249
250 /* Call the function from the address to get the func ptrs */
251 p_comp = (*p_core_comp->create_comp_func)(p_obj);
252 if (NULL == p_comp) {
253 ALOGE("%s:%d] Error cannot create component", __func__, __LINE__);
254 rc = OMX_ErrorInvalidComponent;
255 goto error;
256 }
257
258 *handle = p_core_comp->handle[inst_idx] = (OMX_HANDLETYPE)p_comp;
259
260 ALOGD("%s:%d] handle = %p Instanceindex = %d,"
261 "comp_idx %d g_ptr %p", __func__, __LINE__,
262 p_core_comp->handle[inst_idx], inst_idx,
263 comp_idx, g_omxcore);
264
265 p_comp->SetCallbacks(p_comp, callBacks, appData);
266 pthread_mutex_unlock(&g_omxcore_lock);
267 ALOGI("%s:%d] Success", __func__, __LINE__);
268 return OMX_ErrorNone;
269
270 error:
271
272 if (OMX_TRUE == close_handle) {
273 dlclose(p_core_comp->lib_handle);
274 p_core_comp->lib_handle = NULL;
275 }
276 pthread_mutex_unlock(&g_omxcore_lock);
277 ALOGE("%s:%d] Error %d", __func__, __LINE__, rc);
278 return rc;
279 }
280
281 /*==============================================================================
282 * Function : getIndexFromComponent
283 * Parameters: handle,
284 * Return Value : Component present - true or false, Instance Index, Component
285 * Index
286 * Description: Check if the handle is present in the list and get the component
287 * index and instance index for the component handle.
288 ==============================================================================*/
get_idx_from_handle(OMX_IN OMX_HANDLETYPE * ahComp,int * aCompIdx,int * aInstIdx)289 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *aCompIdx,
290 int *aInstIdx)
291 {
292 int i = 0, j = 0;
293 for (i = 0; i < g_omxcore->comp_cnt; i++) {
294 for (j = 0; j < OMX_COMP_MAX_INSTANCES; j++) {
295 if ((OMX_COMPONENTTYPE *)g_omxcore->component[i].handle[j] ==
296 (OMX_COMPONENTTYPE *)ahComp) {
297 ALOGD("%s:%d] comp_idx %d inst_idx %d", __func__, __LINE__, i, j);
298 *aCompIdx = i;
299 *aInstIdx = j;
300 return TRUE;
301 }
302 }
303 }
304 return FALSE;
305 }
306
307 /*==============================================================================
308 * Function : is_comp_active
309 * Parameters: p_core_comp
310 * Return Value : int
311 * Description: Check if the component has any active instances
312 ==============================================================================*/
is_comp_active(omx_core_component_t * p_core_comp)313 static uint8_t is_comp_active(omx_core_component_t *p_core_comp)
314 {
315 uint8_t i = 0;
316 for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
317 if (NULL != p_core_comp->handle[i]) {
318 return TRUE;
319 }
320 }
321 return FALSE;
322 }
323
324 /*==============================================================================
325 * Function : OMX_FreeHandle
326 * Parameters: hComp
327 * Return Value : OMX_ERRORTYPE
328 * Description: Deinit the omx component and remove it from the global list
329 ==============================================================================*/
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp)330 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
331 OMX_IN OMX_HANDLETYPE hComp)
332 {
333 OMX_ERRORTYPE rc = OMX_ErrorNone;
334 int comp_idx, inst_idx;
335 OMX_COMPONENTTYPE *p_comp = NULL;
336 omx_core_component_t *p_core_comp = NULL;
337
338 ALOGV("%s:%d] ", __func__, __LINE__);
339 if (hComp == NULL) {
340 return OMX_ErrorBadParameter;
341 }
342
343 pthread_mutex_lock(&g_omxcore_lock);
344
345 p_comp = (OMX_COMPONENTTYPE *)hComp;
346 if (FALSE == get_idx_from_handle(hComp, &comp_idx, &inst_idx)) {
347 ALOGE("%s:%d] Error invalid component", __func__, __LINE__);
348 pthread_mutex_unlock(&g_omxcore_lock);
349 return OMX_ErrorInvalidComponent;
350 }
351
352
353 //Deinit the component;
354 rc = p_comp->ComponentDeInit(hComp);
355 if (rc != OMX_ErrorNone) {
356 /* Remove the handle from the comp structure */
357 ALOGE("%s:%d] Error comp deinit failed", __func__, __LINE__);
358 pthread_mutex_unlock(&g_omxcore_lock);
359 return OMX_ErrorInvalidComponent;
360 }
361 p_core_comp = &g_omxcore->component[comp_idx];
362 p_core_comp->handle[inst_idx] = NULL;
363 if (!is_comp_active(p_core_comp)) {
364 rc = dlclose(p_core_comp->lib_handle);
365 p_core_comp->lib_handle = NULL;
366 p_core_comp->get_instance = NULL;
367 p_core_comp->create_comp_func = NULL;
368 p_core_comp->open = FALSE;
369 } else {
370 ALOGI("%s:%d] Error Component is still Active", __func__, __LINE__);
371 }
372 pthread_mutex_unlock(&g_omxcore_lock);
373 ALOGV("%s:%d] Success", __func__, __LINE__);
374 return rc;
375 }
376