1 /* 2 * wrs_core.cpp, Wind River OpenMax-IL Core 3 * 4 * Copyright (c) 2009-2010 Wind River Systems, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include <pthread.h> 24 25 #include <OMX_Core.h> 26 #include <OMX_Component.h> 27 28 #include <list.h> 29 #include <cmodule.h> 30 #include <componentbase.h> 31 32 //#define LOG_NDEBUG 0 33 34 #define LOG_TAG "wrs-omxil-core" 35 #include <log.h> 36 37 static unsigned int g_initialized = 0; 38 static unsigned int g_nr_instances = 0; 39 40 static struct list *g_module_list = NULL; 41 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER; 42 43 static struct list *construct_components(const char *config_file_name) 44 { 45 FILE *config_file; 46 char library_name[OMX_MAX_STRINGNAME_SIZE]; 47 char config_file_path[256]; 48 struct list *head = NULL; 49 50 strncpy(config_file_path, "/etc/", 256); 51 strncat(config_file_path, config_file_name, 256); 52 config_file = fopen(config_file_path, "r"); 53 if (!config_file) { 54 strncpy(config_file_path, "./", 256); 55 strncat(config_file_path, config_file_name, 256); 56 config_file = fopen(config_file_path, "r"); 57 if (!config_file) { 58 LOGE("not found file %s\n", config_file_name); 59 return NULL; 60 } 61 } 62 63 while (fscanf(config_file, "%s", library_name) > 0) { 64 CModule *cmodule; 65 struct list *entry; 66 OMX_ERRORTYPE ret; 67 68 library_name[OMX_MAX_STRINGNAME_SIZE-1] = '\0'; 69 70 /* skip libraries starting with # */ 71 if (library_name[0] == '#') 72 continue; 73 74 cmodule = new CModule(&library_name[0]); 75 if (!cmodule) 76 continue; 77 78 LOGI("found component library %s\n", library_name); 79 80 ret = cmodule->Load(MODULE_LAZY); 81 if (ret != OMX_ErrorNone) 82 goto delete_cmodule; 83 84 ret = cmodule->QueryComponentNameAndRoles(); 85 if (ret != OMX_ErrorNone) 86 goto unload_cmodule; 87 88 entry = list_alloc(cmodule); 89 if (!entry) 90 goto unload_cmodule; 91 head = __list_add_tail(head, entry); 92 93 cmodule->Unload(); 94 LOGI("module %s:%s added to component list\n", 95 cmodule->GetLibraryName(), cmodule->GetComponentName()); 96 97 continue; 98 99 unload_cmodule: 100 cmodule->Unload(); 101 delete_cmodule: 102 delete cmodule; 103 } 104 105 fclose(config_file); 106 return head; 107 } 108 109 static struct list *destruct_components(struct list *head) 110 { 111 struct list *entry, *next; 112 113 list_foreach_safe(head, entry, next) { 114 CModule *cmodule = static_cast<CModule *>(entry->data); 115 116 head = __list_delete(head, entry); 117 delete cmodule; 118 } 119 120 return head; 121 } 122 123 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) 124 { 125 int ret; 126 127 LOGV("%s(): enter", __FUNCTION__); 128 129 pthread_mutex_lock(&g_module_lock); 130 if (!g_initialized) { 131 g_module_list = construct_components("wrs_omxil_components.list"); 132 if (!g_module_list) { 133 pthread_mutex_unlock(&g_module_lock); 134 LOGE("%s(): exit failure, construct_components failed", 135 __FUNCTION__); 136 return OMX_ErrorInsufficientResources; 137 } 138 139 g_initialized = 1; 140 } 141 pthread_mutex_unlock(&g_module_lock); 142 143 LOGV("%s(): exit done", __FUNCTION__); 144 return OMX_ErrorNone; 145 } 146 147 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) 148 { 149 OMX_ERRORTYPE ret = OMX_ErrorNone; 150 151 LOGV("%s(): enter", __FUNCTION__); 152 153 pthread_mutex_lock(&g_module_lock); 154 if (!g_nr_instances) 155 g_module_list = destruct_components(g_module_list); 156 else 157 ret = OMX_ErrorUndefined; 158 pthread_mutex_unlock(&g_module_lock); 159 160 g_initialized = 0; 161 162 LOGV("%s(): exit done (ret : 0x%08x)", __FUNCTION__, ret); 163 return ret; 164 } 165 166 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( 167 OMX_OUT OMX_STRING cComponentName, 168 OMX_IN OMX_U32 nNameLength, 169 OMX_IN OMX_U32 nIndex) 170 { 171 CModule *cmodule; 172 ComponentBase *cbase; 173 struct list *entry; 174 OMX_STRING cname; 175 176 pthread_mutex_lock(&g_module_lock); 177 entry = __list_entry(g_module_list, nIndex); 178 if (!entry) { 179 pthread_mutex_unlock(&g_module_lock); 180 return OMX_ErrorNoMore; 181 } 182 pthread_mutex_unlock(&g_module_lock); 183 184 cmodule = static_cast<CModule *>(entry->data); 185 cname = cmodule->GetComponentName(); 186 187 strncpy(cComponentName, cname, nNameLength); 188 189 LOGV("%s(): found %u th component %s", __FUNCTION__, nIndex, cname); 190 return OMX_ErrorNone; 191 } 192 193 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( 194 OMX_OUT OMX_HANDLETYPE* pHandle, 195 OMX_IN OMX_STRING cComponentName, 196 OMX_IN OMX_PTR pAppData, 197 OMX_IN OMX_CALLBACKTYPE *pCallBacks) 198 { 199 struct list *entry; 200 OMX_ERRORTYPE ret; 201 202 LOGV("%s(): enter, try to get %s", __FUNCTION__, cComponentName); 203 204 pthread_mutex_lock(&g_module_lock); 205 list_foreach(g_module_list, entry) { 206 CModule *cmodule; 207 OMX_STRING cname; 208 209 cmodule = static_cast<CModule *>(entry->data); 210 211 cname = cmodule->GetComponentName(); 212 if (!strcmp(cComponentName, cname)) { 213 ComponentBase *cbase = NULL; 214 215 ret = cmodule->Load(MODULE_NOW); 216 if (ret != OMX_ErrorNone) { 217 LOGE("%s(): exit failure, cmodule->Load failed\n", 218 __FUNCTION__); 219 goto unlock_list; 220 } 221 222 ret = cmodule->InstantiateComponent(&cbase); 223 if (ret != OMX_ErrorNone){ 224 LOGE("%s(): exit failure, cmodule->Instantiate failed\n", 225 __FUNCTION__); 226 goto unload_cmodule; 227 } 228 229 ret = cbase->GetHandle(pHandle, pAppData, pCallBacks); 230 if (ret != OMX_ErrorNone) { 231 LOGE("%s(): exit failure, cbase->GetHandle failed\n", 232 __FUNCTION__); 233 goto delete_cbase; 234 } 235 236 cbase->SetCModule(cmodule); 237 238 g_nr_instances++; 239 pthread_mutex_unlock(&g_module_lock); 240 241 LOGI("get handle of component %s successfully", cComponentName); 242 LOGV("%s(): exit done\n", __FUNCTION__); 243 return OMX_ErrorNone; 244 245 delete_cbase: 246 delete cbase; 247 unload_cmodule: 248 cmodule->Unload(); 249 unlock_list: 250 pthread_mutex_unlock(&g_module_lock); 251 252 LOGE("%s(): exit failure, (ret : 0x%08x)\n", __FUNCTION__, ret); 253 return ret; 254 } 255 } 256 pthread_mutex_unlock(&g_module_lock); 257 258 LOGE("%s(): exit failure, %s not found", __FUNCTION__, cComponentName); 259 return OMX_ErrorInvalidComponent; 260 } 261 262 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 263 OMX_IN OMX_HANDLETYPE hComponent) 264 { 265 ComponentBase *cbase; 266 CModule *cmodule; 267 OMX_ERRORTYPE ret; 268 char cname[OMX_MAX_STRINGNAME_SIZE]; 269 270 if (!hComponent) 271 return OMX_ErrorBadParameter; 272 273 cbase = static_cast<ComponentBase *> 274 (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate); 275 if (!cbase) { 276 LOGE("%s(): exit failure, cannot find cbase pointer\n", 277 __FUNCTION__); 278 return OMX_ErrorBadParameter; 279 } 280 strcpy(&cname[0], cbase->GetName()); 281 282 LOGV("%s(): enter, try to free %s", __FUNCTION__, cbase->GetName()); 283 284 285 ret = cbase->FreeHandle(hComponent); 286 if (ret != OMX_ErrorNone) { 287 LOGE("%s(): exit failure, cbase->FreeHandle() failed (ret = 0x%08x)\n", 288 __FUNCTION__, ret); 289 return ret; 290 } 291 292 pthread_mutex_lock(&g_module_lock); 293 g_nr_instances--; 294 pthread_mutex_unlock(&g_module_lock); 295 296 cmodule = cbase->GetCModule(); 297 if (!cmodule) 298 LOGE("fatal error, %s does not have cmodule\n", cbase->GetName()); 299 300 delete cbase; 301 302 if (cmodule) 303 cmodule->Unload(); 304 305 LOGI("free handle of component %s successfully", cname); 306 LOGV("%s(): exit done", __FUNCTION__); 307 return OMX_ErrorNone; 308 } 309 310 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( 311 OMX_IN OMX_STRING role, 312 OMX_INOUT OMX_U32 *pNumComps, 313 OMX_INOUT OMX_U8 **compNames) 314 { 315 struct list *entry; 316 OMX_U32 nr_comps = 0, copied_nr_comps = 0; 317 318 pthread_mutex_lock(&g_module_lock); 319 list_foreach(g_module_list, entry) { 320 CModule *cmodule; 321 OMX_STRING cname; 322 bool having_role; 323 324 cmodule = static_cast<CModule *>(entry->data); 325 326 having_role = cmodule->QueryHavingThisRole(role); 327 if (having_role) { 328 if (compNames && compNames[nr_comps]) { 329 cname = cmodule->GetComponentName(); 330 strncpy((OMX_STRING)&compNames[nr_comps][0], cname, 331 OMX_MAX_STRINGNAME_SIZE); 332 copied_nr_comps++; 333 LOGV("%s(): component %s has %s role", __FUNCTION__, 334 cname, role); 335 } 336 nr_comps++; 337 } 338 } 339 pthread_mutex_unlock(&g_module_lock); 340 341 if (!copied_nr_comps) 342 *pNumComps = nr_comps; 343 else { 344 if (copied_nr_comps != *pNumComps) 345 return OMX_ErrorBadParameter; 346 } 347 348 return OMX_ErrorNone; 349 } 350 351 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( 352 OMX_IN OMX_STRING compName, 353 OMX_INOUT OMX_U32 *pNumRoles, 354 OMX_OUT OMX_U8 **roles) 355 { 356 struct list *entry; 357 358 pthread_mutex_lock(&g_module_lock); 359 list_foreach(g_module_list, entry) { 360 CModule *cmodule; 361 ComponentBase *cbase; 362 OMX_STRING cname; 363 OMX_ERRORTYPE ret; 364 365 cmodule = static_cast<CModule *>(entry->data); 366 367 cname = cmodule->GetComponentName(); 368 if (!strcmp(compName, cname)) { 369 pthread_mutex_unlock(&g_module_lock); 370 #if LOG_NDEBUG 371 return cmodule->GetComponentRoles(pNumRoles, roles); 372 #else 373 ret = cmodule->GetComponentRoles(pNumRoles, roles); 374 if (ret != OMX_ErrorNone) { 375 OMX_U32 i; 376 377 for (i = 0; i < *pNumRoles; i++) { 378 LOGV("%s(): component %s has %s role", __FUNCTION__, 379 compName, &roles[i][0]); 380 } 381 } 382 return ret; 383 #endif 384 } 385 } 386 pthread_mutex_unlock(&g_module_lock); 387 388 return OMX_ErrorInvalidComponent; 389 } 390