1 /*Copyright (c) 2012-2014, 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 #include <utils/Log.h> 32 33 #include "qomx_core.h" 34 35 #define BUFF_SIZE 255 36 37 static omx_core_t *g_omxcore; 38 static pthread_mutex_t g_omxcore_lock = PTHREAD_MUTEX_INITIALIZER; 39 static int g_omxcore_cnt = 0; 40 41 //Map the library name with the component name 42 static const comp_info_t g_comp_info[] = 43 { 44 { "OMX.qcom.image.jpeg.encoder", "libqomx_jpegenc.so" }, 45 { "OMX.qcom.image.jpeg.decoder", "libqomx_jpegdec.so" }, 46 { "OMX.qcom.image.jpeg.encoder_pipeline", "libqomx_jpegenc_pipe.so" } 47 }; 48 49 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *acompIndex, 50 int *ainstanceIndex); 51 52 /*============================================================================== 53 * Function : OMX_Init 54 * Parameters: None 55 * Description: This is the first call that is made to the OMX Core 56 * and initializes the OMX IL core 57 ==============================================================================*/ 58 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init() 59 { 60 OMX_ERRORTYPE rc = OMX_ErrorNone; 61 int i = 0; 62 int comp_cnt = sizeof(g_comp_info)/sizeof(g_comp_info[0]); 63 64 pthread_mutex_lock(&g_omxcore_lock); 65 66 /* check if core is created */ 67 if (g_omxcore) { 68 g_omxcore_cnt++; 69 pthread_mutex_unlock(&g_omxcore_lock); 70 return rc; 71 } 72 73 if (comp_cnt > OMX_COMP_MAX_NUM) { 74 ALOGE("%s:%d] cannot exceed max number of components", 75 __func__, __LINE__); 76 pthread_mutex_unlock(&g_omxcore_lock); 77 return OMX_ErrorUndefined; 78 } 79 /* create new global object */ 80 g_omxcore = malloc(sizeof(omx_core_t)); 81 if (g_omxcore) { 82 memset(g_omxcore, 0x0, sizeof(omx_core_t)); 83 84 /* populate the library name and component name */ 85 for (i = 0; i < comp_cnt; i++) { 86 g_omxcore->component[i].comp_name = g_comp_info[i].comp_name; 87 g_omxcore->component[i].lib_name = g_comp_info[i].lib_name; 88 } 89 g_omxcore->comp_cnt = comp_cnt; 90 g_omxcore_cnt++; 91 } else { 92 rc = OMX_ErrorInsufficientResources; 93 } 94 pthread_mutex_unlock(&g_omxcore_lock); 95 ALOGI("%s:%d] Complete %d", __func__, __LINE__, comp_cnt); 96 return rc; 97 } 98 99 /*============================================================================== 100 * Function : OMX_Deinit 101 * Parameters: None 102 * Return Value : OMX_ERRORTYPE 103 * Description: Deinit all the OMX components 104 ==============================================================================*/ 105 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit() 106 { 107 pthread_mutex_lock(&g_omxcore_lock); 108 109 if (g_omxcore_cnt == 1) { 110 if (g_omxcore) { 111 free(g_omxcore); 112 g_omxcore = NULL; 113 } 114 } 115 if (g_omxcore_cnt) { 116 g_omxcore_cnt--; 117 } 118 119 ALOGI("%s:%d] Complete", __func__, __LINE__); 120 pthread_mutex_unlock(&g_omxcore_lock); 121 return OMX_ErrorNone; 122 } 123 124 /*============================================================================== 125 * Function : get_comp_from_list 126 * Parameters: componentName 127 * Return Value : component_index 128 * Description: If the componnt is already present in the list, return the 129 * component index. If not return the next index to create the component. 130 ==============================================================================*/ 131 static int get_comp_from_list(char *comp_name) 132 { 133 int index = -1, i = 0; 134 135 if (NULL == comp_name) 136 return -1; 137 138 for (i = 0; i < g_omxcore->comp_cnt; i++) { 139 if (!strcmp(g_omxcore->component[i].comp_name, comp_name)) { 140 index = i; 141 break; 142 } 143 } 144 return index; 145 } 146 147 /*============================================================================== 148 * Function : get_free_inst_idx 149 * Parameters: p_comp 150 * Return Value : The next instance index if available 151 * Description: Get the next available index for to store the new instance of the 152 * component being created. 153 *============================================================================*/ 154 static int get_free_inst_idx(omx_core_component_t *p_comp) 155 { 156 int idx = -1, i = 0; 157 158 for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) { 159 if (NULL == p_comp->handle[i]) { 160 idx = i; 161 break; 162 } 163 } 164 return idx; 165 } 166 167 /*============================================================================== 168 * Function : OMX_GetHandle 169 * Parameters: handle, componentName, appData, callbacks 170 * Return Value : OMX_ERRORTYPE 171 * Description: Construct and load the requested omx library 172 ==============================================================================*/ 173 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( 174 OMX_OUT OMX_HANDLETYPE* handle, 175 OMX_IN OMX_STRING componentName, 176 OMX_IN OMX_PTR appData, 177 OMX_IN OMX_CALLBACKTYPE* callBacks) 178 { 179 OMX_ERRORTYPE rc = OMX_ErrorNone; 180 int comp_idx = 0, inst_idx = 0; 181 char libName[BUFF_SIZE] = {0}; 182 void *p_obj = NULL; 183 OMX_COMPONENTTYPE *p_comp = NULL; 184 omx_core_component_t *p_core_comp = NULL; 185 OMX_BOOL close_handle = OMX_FALSE; 186 187 if (NULL == handle) { 188 ALOGE("%s:%d] Error invalid input ", __func__, __LINE__); 189 return OMX_ErrorBadParameter; 190 } 191 192 pthread_mutex_lock(&g_omxcore_lock); 193 194 comp_idx = get_comp_from_list(componentName); 195 if (comp_idx < 0) { 196 ALOGE("%s:%d] Cannot find the component", __func__, __LINE__); 197 pthread_mutex_unlock(&g_omxcore_lock); 198 return OMX_ErrorInvalidComponent; 199 } 200 p_core_comp = &g_omxcore->component[comp_idx]; 201 202 *handle = NULL; 203 204 //If component already present get the instance index 205 inst_idx = get_free_inst_idx(p_core_comp); 206 if (inst_idx < 0) { 207 ALOGE("%s:%d] Cannot alloc new instance", __func__, __LINE__); 208 rc = OMX_ErrorInvalidComponent; 209 goto error; 210 } 211 212 if (FALSE == p_core_comp->open) { 213 /* load the library */ 214 p_core_comp->lib_handle = dlopen(p_core_comp->lib_name, RTLD_NOW); 215 if (NULL == p_core_comp->lib_handle) { 216 ALOGE("%s:%d] Cannot load the library", __func__, __LINE__); 217 rc = OMX_ErrorInvalidComponent; 218 goto error; 219 } 220 221 p_core_comp->open = TRUE; 222 /* Init the component and get component functions */ 223 p_core_comp->create_comp_func = dlsym(p_core_comp->lib_handle, 224 "create_component_fns"); 225 p_core_comp->get_instance = dlsym(p_core_comp->lib_handle, "getInstance"); 226 227 close_handle = OMX_TRUE; 228 if (!p_core_comp->create_comp_func || !p_core_comp->get_instance) { 229 ALOGE("%s:%d] Cannot maps the symbols", __func__, __LINE__); 230 rc = OMX_ErrorInvalidComponent; 231 goto error; 232 } 233 } 234 235 /* Call the function from the address to create the obj */ 236 p_obj = (*p_core_comp->get_instance)(); 237 ALOGI("%s:%d] get instance pts is %p", __func__, __LINE__, p_obj); 238 if (NULL == p_obj) { 239 ALOGE("%s:%d] Error cannot create object", __func__, __LINE__); 240 rc = OMX_ErrorInvalidComponent; 241 goto error; 242 } 243 244 /* Call the function from the address to get the func ptrs */ 245 p_comp = (*p_core_comp->create_comp_func)(p_obj); 246 if (NULL == p_comp) { 247 ALOGE("%s:%d] Error cannot create component", __func__, __LINE__); 248 rc = OMX_ErrorInvalidComponent; 249 goto error; 250 } 251 252 *handle = p_core_comp->handle[inst_idx] = (OMX_HANDLETYPE)p_comp; 253 254 ALOGD("%s:%d] handle = %p Instanceindex = %d," 255 "comp_idx %d g_ptr %p", __func__, __LINE__, 256 p_core_comp->handle[inst_idx], inst_idx, 257 comp_idx, g_omxcore); 258 259 p_comp->SetCallbacks(p_comp, callBacks, appData); 260 pthread_mutex_unlock(&g_omxcore_lock); 261 ALOGI("%s:%d] Success", __func__, __LINE__); 262 return OMX_ErrorNone; 263 264 error: 265 266 if (OMX_TRUE == close_handle) { 267 dlclose(p_core_comp->lib_handle); 268 p_core_comp->lib_handle = NULL; 269 } 270 pthread_mutex_unlock(&g_omxcore_lock); 271 ALOGE("%s:%d] Error %d", __func__, __LINE__, rc); 272 return rc; 273 } 274 275 /*============================================================================== 276 * Function : getIndexFromComponent 277 * Parameters: handle, 278 * Return Value : Component present - true or false, Instance Index, Component 279 * Index 280 * Description: Check if the handle is present in the list and get the component 281 * index and instance index for the component handle. 282 ==============================================================================*/ 283 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *aCompIdx, 284 int *aInstIdx) 285 { 286 int i = 0, j = 0; 287 for (i = 0; i < g_omxcore->comp_cnt; i++) { 288 for (j = 0; j < OMX_COMP_MAX_INSTANCES; j++) { 289 if ((OMX_COMPONENTTYPE *)g_omxcore->component[i].handle[j] == 290 (OMX_COMPONENTTYPE *)ahComp) { 291 ALOGD("%s:%d] comp_idx %d inst_idx %d", __func__, __LINE__, i, j); 292 *aCompIdx = i; 293 *aInstIdx = j; 294 return TRUE; 295 } 296 } 297 } 298 return FALSE; 299 } 300 301 /*============================================================================== 302 * Function : is_comp_active 303 * Parameters: p_core_comp 304 * Return Value : int 305 * Description: Check if the component has any active instances 306 ==============================================================================*/ 307 static uint8_t is_comp_active(omx_core_component_t *p_core_comp) 308 { 309 uint8_t i = 0; 310 for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) { 311 if (NULL != p_core_comp->handle[i]) { 312 return TRUE; 313 } 314 } 315 return FALSE; 316 } 317 318 /*============================================================================== 319 * Function : OMX_FreeHandle 320 * Parameters: hComp 321 * Return Value : OMX_ERRORTYPE 322 * Description: Deinit the omx component and remove it from the global list 323 ==============================================================================*/ 324 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 325 OMX_IN OMX_HANDLETYPE hComp) 326 { 327 OMX_ERRORTYPE rc = OMX_ErrorNone; 328 int comp_idx, inst_idx; 329 OMX_COMPONENTTYPE *p_comp = NULL; 330 omx_core_component_t *p_core_comp = NULL; 331 332 ALOGV("%s:%d] ", __func__, __LINE__); 333 if (hComp == NULL) { 334 return OMX_ErrorBadParameter; 335 } 336 337 pthread_mutex_lock(&g_omxcore_lock); 338 339 p_comp = (OMX_COMPONENTTYPE *)hComp; 340 if (FALSE == get_idx_from_handle(hComp, &comp_idx, &inst_idx)) { 341 ALOGE("%s:%d] Error invalid component", __func__, __LINE__); 342 pthread_mutex_unlock(&g_omxcore_lock); 343 return OMX_ErrorInvalidComponent; 344 } 345 346 347 //Deinit the component; 348 rc = p_comp->ComponentDeInit(hComp); 349 if (rc != OMX_ErrorNone) { 350 /* Remove the handle from the comp structure */ 351 ALOGE("%s:%d] Error comp deinit failed", __func__, __LINE__); 352 pthread_mutex_unlock(&g_omxcore_lock); 353 return OMX_ErrorInvalidComponent; 354 } 355 p_core_comp = &g_omxcore->component[comp_idx]; 356 p_core_comp->handle[inst_idx] = NULL; 357 if (!is_comp_active(p_core_comp)) { 358 rc = dlclose(p_core_comp->lib_handle); 359 p_core_comp->lib_handle = NULL; 360 p_core_comp->get_instance = NULL; 361 p_core_comp->create_comp_func = NULL; 362 p_core_comp->open = FALSE; 363 } else { 364 ALOGI("%s:%d] Error Component is still Active", __func__, __LINE__); 365 } 366 pthread_mutex_unlock(&g_omxcore_lock); 367 ALOGV("%s:%d] Success", __func__, __LINE__); 368 return rc; 369 } 370