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