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 void *p_obj = NULL; 181 OMX_COMPONENTTYPE *p_comp = NULL; 182 omx_core_component_t *p_core_comp = NULL; 183 OMX_BOOL close_handle = OMX_FALSE; 184 185 if (NULL == handle) { 186 ALOGE("%s:%d] Error invalid input ", __func__, __LINE__); 187 return OMX_ErrorBadParameter; 188 } 189 190 pthread_mutex_lock(&g_omxcore_lock); 191 192 comp_idx = get_comp_from_list(componentName); 193 if (comp_idx < 0) { 194 ALOGE("%s:%d] Cannot find the component", __func__, __LINE__); 195 pthread_mutex_unlock(&g_omxcore_lock); 196 return OMX_ErrorInvalidComponent; 197 } 198 p_core_comp = &g_omxcore->component[comp_idx]; 199 200 *handle = NULL; 201 202 //If component already present get the instance index 203 inst_idx = get_free_inst_idx(p_core_comp); 204 if (inst_idx < 0) { 205 ALOGE("%s:%d] Cannot alloc new instance", __func__, __LINE__); 206 rc = OMX_ErrorInvalidComponent; 207 goto error; 208 } 209 210 if (FALSE == p_core_comp->open) { 211 /* load the library */ 212 p_core_comp->lib_handle = dlopen(p_core_comp->lib_name, RTLD_NOW); 213 if (NULL == p_core_comp->lib_handle) { 214 ALOGE("%s:%d] Cannot load the library", __func__, __LINE__); 215 rc = OMX_ErrorInvalidComponent; 216 goto error; 217 } 218 219 p_core_comp->open = TRUE; 220 /* Init the component and get component functions */ 221 p_core_comp->create_comp_func = dlsym(p_core_comp->lib_handle, 222 "create_component_fns"); 223 p_core_comp->get_instance = dlsym(p_core_comp->lib_handle, "getInstance"); 224 225 close_handle = OMX_TRUE; 226 if (!p_core_comp->create_comp_func || !p_core_comp->get_instance) { 227 ALOGE("%s:%d] Cannot maps the symbols", __func__, __LINE__); 228 rc = OMX_ErrorInvalidComponent; 229 goto error; 230 } 231 } 232 233 /* Call the function from the address to create the obj */ 234 p_obj = (*p_core_comp->get_instance)(); 235 ALOGI("%s:%d] get instance pts is %p", __func__, __LINE__, p_obj); 236 if (NULL == p_obj) { 237 ALOGE("%s:%d] Error cannot create object", __func__, __LINE__); 238 rc = OMX_ErrorInvalidComponent; 239 goto error; 240 } 241 242 /* Call the function from the address to get the func ptrs */ 243 p_comp = (*p_core_comp->create_comp_func)(p_obj); 244 if (NULL == p_comp) { 245 ALOGE("%s:%d] Error cannot create component", __func__, __LINE__); 246 rc = OMX_ErrorInvalidComponent; 247 goto error; 248 } 249 250 *handle = p_core_comp->handle[inst_idx] = (OMX_HANDLETYPE)p_comp; 251 252 ALOGD("%s:%d] handle = %p Instanceindex = %d," 253 "comp_idx %d g_ptr %p", __func__, __LINE__, 254 p_core_comp->handle[inst_idx], inst_idx, 255 comp_idx, g_omxcore); 256 257 p_comp->SetCallbacks(p_comp, callBacks, appData); 258 pthread_mutex_unlock(&g_omxcore_lock); 259 ALOGI("%s:%d] Success", __func__, __LINE__); 260 return OMX_ErrorNone; 261 262 error: 263 264 if (OMX_TRUE == close_handle) { 265 dlclose(p_core_comp->lib_handle); 266 p_core_comp->lib_handle = NULL; 267 } 268 pthread_mutex_unlock(&g_omxcore_lock); 269 ALOGE("%s:%d] Error %d", __func__, __LINE__, rc); 270 return rc; 271 } 272 273 /*============================================================================== 274 * Function : getIndexFromComponent 275 * Parameters: handle, 276 * Return Value : Component present - true or false, Instance Index, Component 277 * Index 278 * Description: Check if the handle is present in the list and get the component 279 * index and instance index for the component handle. 280 ==============================================================================*/ 281 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *aCompIdx, 282 int *aInstIdx) 283 { 284 int i = 0, j = 0; 285 for (i = 0; i < g_omxcore->comp_cnt; i++) { 286 for (j = 0; j < OMX_COMP_MAX_INSTANCES; j++) { 287 if ((OMX_COMPONENTTYPE *)g_omxcore->component[i].handle[j] == 288 (OMX_COMPONENTTYPE *)ahComp) { 289 ALOGD("%s:%d] comp_idx %d inst_idx %d", __func__, __LINE__, i, j); 290 *aCompIdx = i; 291 *aInstIdx = j; 292 return TRUE; 293 } 294 } 295 } 296 return FALSE; 297 } 298 299 /*============================================================================== 300 * Function : is_comp_active 301 * Parameters: p_core_comp 302 * Return Value : int 303 * Description: Check if the component has any active instances 304 ==============================================================================*/ 305 static uint8_t is_comp_active(omx_core_component_t *p_core_comp) 306 { 307 uint8_t i = 0; 308 for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) { 309 if (NULL != p_core_comp->handle[i]) { 310 return TRUE; 311 } 312 } 313 return FALSE; 314 } 315 316 /*============================================================================== 317 * Function : OMX_FreeHandle 318 * Parameters: hComp 319 * Return Value : OMX_ERRORTYPE 320 * Description: Deinit the omx component and remove it from the global list 321 ==============================================================================*/ 322 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 323 OMX_IN OMX_HANDLETYPE hComp) 324 { 325 OMX_ERRORTYPE rc = OMX_ErrorNone; 326 int comp_idx, inst_idx; 327 OMX_COMPONENTTYPE *p_comp = NULL; 328 omx_core_component_t *p_core_comp = NULL; 329 330 ALOGV("%s:%d] ", __func__, __LINE__); 331 if (hComp == NULL) { 332 return OMX_ErrorBadParameter; 333 } 334 335 pthread_mutex_lock(&g_omxcore_lock); 336 337 p_comp = (OMX_COMPONENTTYPE *)hComp; 338 if (FALSE == get_idx_from_handle(hComp, &comp_idx, &inst_idx)) { 339 ALOGE("%s:%d] Error invalid component", __func__, __LINE__); 340 pthread_mutex_unlock(&g_omxcore_lock); 341 return OMX_ErrorInvalidComponent; 342 } 343 344 345 //Deinit the component; 346 rc = p_comp->ComponentDeInit(hComp); 347 if (rc != OMX_ErrorNone) { 348 /* Remove the handle from the comp structure */ 349 ALOGE("%s:%d] Error comp deinit failed", __func__, __LINE__); 350 pthread_mutex_unlock(&g_omxcore_lock); 351 return OMX_ErrorInvalidComponent; 352 } 353 p_core_comp = &g_omxcore->component[comp_idx]; 354 p_core_comp->handle[inst_idx] = NULL; 355 if (!is_comp_active(p_core_comp)) { 356 rc = dlclose(p_core_comp->lib_handle); 357 p_core_comp->lib_handle = NULL; 358 p_core_comp->get_instance = NULL; 359 p_core_comp->create_comp_func = NULL; 360 p_core_comp->open = FALSE; 361 } else { 362 ALOGI("%s:%d] Error Component is still Active", __func__, __LINE__); 363 } 364 pthread_mutex_unlock(&g_omxcore_lock); 365 ALOGV("%s:%d] Success", __func__, __LINE__); 366 return rc; 367 } 368