1/*Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved. 2 3Redistribution and use in source and binary forms, with or without 4modification, are permitted provided that the following conditions are 5met: 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 16THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26IF 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 43static omx_core_t *g_omxcore; 44static pthread_mutex_t g_omxcore_lock = PTHREAD_MUTEX_INITIALIZER; 45static int g_omxcore_cnt = 0; 46 47//Map the library name with the component name 48static 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 55static 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==============================================================================*/ 64OMX_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==============================================================================*/ 111OMX_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==============================================================================*/ 137static 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*============================================================================*/ 160static 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==============================================================================*/ 179OMX_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 270error: 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==============================================================================*/ 289static 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==============================================================================*/ 313static 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==============================================================================*/ 330OMX_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