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