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