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 LOGV("%s(): enter", __FUNCTION__); 126 127 pthread_mutex_lock(&g_module_lock); 128 if (!g_initialized) { 129 g_module_list = construct_components("wrs_omxil_components.list"); 130 if (!g_module_list) { 131 pthread_mutex_unlock(&g_module_lock); 132 LOGE("%s(): exit failure, construct_components failed", 133 __FUNCTION__); 134 return OMX_ErrorInsufficientResources; 135 } 136 137 g_initialized = 1; 138 } 139 pthread_mutex_unlock(&g_module_lock); 140 141 LOGV("%s(): exit done", __FUNCTION__); 142 return OMX_ErrorNone; 143 } 144 145 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) 146 { 147 OMX_ERRORTYPE ret = OMX_ErrorNone; 148 149 LOGV("%s(): enter", __FUNCTION__); 150 151 pthread_mutex_lock(&g_module_lock); 152 if (!g_nr_instances) 153 g_module_list = destruct_components(g_module_list); 154 else 155 ret = OMX_ErrorUndefined; 156 pthread_mutex_unlock(&g_module_lock); 157 158 g_initialized = 0; 159 160 LOGV("%s(): exit done (ret : 0x%08x)", __FUNCTION__, ret); 161 return ret; 162 } 163 164 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( 165 OMX_OUT OMX_STRING cComponentName, 166 OMX_IN OMX_U32 nNameLength, 167 OMX_IN OMX_U32 nIndex) 168 { 169 CModule *cmodule; 170 struct list *entry; 171 OMX_STRING cname; 172 173 pthread_mutex_lock(&g_module_lock); 174 entry = __list_entry(g_module_list, nIndex); 175 if (!entry) { 176 pthread_mutex_unlock(&g_module_lock); 177 return OMX_ErrorNoMore; 178 } 179 pthread_mutex_unlock(&g_module_lock); 180 181 cmodule = static_cast<CModule *>(entry->data); 182 cname = cmodule->GetComponentName(); 183 184 strncpy(cComponentName, cname, nNameLength); 185 186 LOGV("%s(): found %u th component %s", __FUNCTION__, nIndex, cname); 187 return OMX_ErrorNone; 188 } 189 190 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( 191 OMX_OUT OMX_HANDLETYPE* pHandle, 192 OMX_IN OMX_STRING cComponentName, 193 OMX_IN OMX_PTR pAppData, 194 OMX_IN OMX_CALLBACKTYPE *pCallBacks) 195 { 196 struct list *entry; 197 OMX_ERRORTYPE ret; 198 199 LOGV("%s(): enter, try to get %s", __FUNCTION__, cComponentName); 200 201 pthread_mutex_lock(&g_module_lock); 202 list_foreach(g_module_list, entry) { 203 CModule *cmodule; 204 OMX_STRING cname; 205 206 cmodule = static_cast<CModule *>(entry->data); 207 208 cname = cmodule->GetComponentName(); 209 if (!strcmp(cComponentName, cname)) { 210 ComponentBase *cbase = NULL; 211 212 ret = cmodule->Load(MODULE_NOW); 213 if (ret != OMX_ErrorNone) { 214 LOGE("%s(): exit failure, cmodule->Load failed\n", 215 __FUNCTION__); 216 goto unlock_list; 217 } 218 219 ret = cmodule->InstantiateComponent(&cbase); 220 if (ret != OMX_ErrorNone){ 221 LOGE("%s(): exit failure, cmodule->Instantiate failed\n", 222 __FUNCTION__); 223 goto unload_cmodule; 224 } 225 226 ret = cbase->GetHandle(pHandle, pAppData, pCallBacks); 227 if (ret != OMX_ErrorNone) { 228 LOGE("%s(): exit failure, cbase->GetHandle failed\n", 229 __FUNCTION__); 230 goto delete_cbase; 231 } 232 233 cbase->SetCModule(cmodule); 234 235 g_nr_instances++; 236 pthread_mutex_unlock(&g_module_lock); 237 238 LOGI("get handle of component %s successfully", cComponentName); 239 LOGV("%s(): exit done\n", __FUNCTION__); 240 return OMX_ErrorNone; 241 242 delete_cbase: 243 delete cbase; 244 unload_cmodule: 245 cmodule->Unload(); 246 unlock_list: 247 pthread_mutex_unlock(&g_module_lock); 248 249 LOGE("%s(): exit failure, (ret : 0x%08x)\n", __FUNCTION__, ret); 250 return ret; 251 } 252 } 253 pthread_mutex_unlock(&g_module_lock); 254 255 LOGE("%s(): exit failure, %s not found", __FUNCTION__, cComponentName); 256 return OMX_ErrorInvalidComponent; 257 } 258 259 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 260 OMX_IN OMX_HANDLETYPE hComponent) 261 { 262 ComponentBase *cbase; 263 CModule *cmodule; 264 OMX_ERRORTYPE ret; 265 char cname[OMX_MAX_STRINGNAME_SIZE]; 266 267 if (!hComponent) 268 return OMX_ErrorBadParameter; 269 270 cbase = static_cast<ComponentBase *> 271 (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate); 272 if (!cbase) { 273 LOGE("%s(): exit failure, cannot find cbase pointer\n", 274 __FUNCTION__); 275 return OMX_ErrorBadParameter; 276 } 277 strcpy(&cname[0], cbase->GetName()); 278 279 LOGV("%s(): enter, try to free %s", __FUNCTION__, cbase->GetName()); 280 281 282 ret = cbase->FreeHandle(hComponent); 283 if (ret != OMX_ErrorNone) { 284 LOGE("%s(): exit failure, cbase->FreeHandle() failed (ret = 0x%08x)\n", 285 __FUNCTION__, ret); 286 return ret; 287 } 288 289 pthread_mutex_lock(&g_module_lock); 290 g_nr_instances--; 291 pthread_mutex_unlock(&g_module_lock); 292 293 cmodule = cbase->GetCModule(); 294 if (!cmodule) 295 LOGE("fatal error, %s does not have cmodule\n", cbase->GetName()); 296 297 delete cbase; 298 299 if (cmodule) 300 cmodule->Unload(); 301 302 LOGI("free handle of component %s successfully", cname); 303 LOGV("%s(): exit done", __FUNCTION__); 304 return OMX_ErrorNone; 305 } 306 307 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( 308 OMX_IN OMX_STRING role, 309 OMX_INOUT OMX_U32 *pNumComps, 310 OMX_INOUT OMX_U8 **compNames) 311 { 312 struct list *entry; 313 OMX_U32 nr_comps = 0, copied_nr_comps = 0; 314 315 pthread_mutex_lock(&g_module_lock); 316 list_foreach(g_module_list, entry) { 317 CModule *cmodule; 318 OMX_STRING cname; 319 bool having_role; 320 321 cmodule = static_cast<CModule *>(entry->data); 322 323 having_role = cmodule->QueryHavingThisRole(role); 324 if (having_role) { 325 if (compNames && compNames[nr_comps]) { 326 cname = cmodule->GetComponentName(); 327 strncpy((OMX_STRING)&compNames[nr_comps][0], cname, 328 OMX_MAX_STRINGNAME_SIZE); 329 copied_nr_comps++; 330 LOGV("%s(): component %s has %s role", __FUNCTION__, 331 cname, role); 332 } 333 nr_comps++; 334 } 335 } 336 pthread_mutex_unlock(&g_module_lock); 337 338 if (!copied_nr_comps) 339 *pNumComps = nr_comps; 340 else { 341 if (copied_nr_comps != *pNumComps) 342 return OMX_ErrorBadParameter; 343 } 344 345 return OMX_ErrorNone; 346 } 347 348 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( 349 OMX_IN OMX_STRING compName, 350 OMX_INOUT OMX_U32 *pNumRoles, 351 OMX_OUT OMX_U8 **roles) 352 { 353 struct list *entry; 354 355 pthread_mutex_lock(&g_module_lock); 356 list_foreach(g_module_list, entry) { 357 CModule *cmodule; 358 OMX_STRING cname; 359 360 cmodule = static_cast<CModule *>(entry->data); 361 362 cname = cmodule->GetComponentName(); 363 if (!strcmp(compName, cname)) { 364 pthread_mutex_unlock(&g_module_lock); 365 #if LOG_NDEBUG 366 return cmodule->GetComponentRoles(pNumRoles, roles); 367 #else 368 OMX_ERRORTYPE ret; 369 ret = cmodule->GetComponentRoles(pNumRoles, roles); 370 if (ret != OMX_ErrorNone) { 371 OMX_U32 i; 372 373 for (i = 0; i < *pNumRoles; i++) { 374 LOGV("%s(): component %s has %s role", __FUNCTION__, 375 compName, &roles[i][0]); 376 } 377 } 378 return ret; 379 #endif 380 } 381 } 382 pthread_mutex_unlock(&g_module_lock); 383 384 return OMX_ErrorInvalidComponent; 385 } 386