/* * wrs_core.cpp, Wind River OpenMax-IL Core * * Copyright (c) 2009-2010 Wind River Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include //#define LOG_NDEBUG 0 #define LOG_TAG "wrs-omxil-core" #include static unsigned int g_initialized = 0; static unsigned int g_nr_instances = 0; static struct list *g_module_list = NULL; static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER; static struct list *construct_components(const char *config_file_name) { FILE *config_file; char library_name[OMX_MAX_STRINGNAME_SIZE]; char config_file_path[256]; struct list *head = NULL; strncpy(config_file_path, "/etc/", 256); strncat(config_file_path, config_file_name, 256); config_file = fopen(config_file_path, "r"); if (!config_file) { strncpy(config_file_path, "./", 256); strncat(config_file_path, config_file_name, 256); config_file = fopen(config_file_path, "r"); if (!config_file) { LOGE("not found file %s\n", config_file_name); return NULL; } } while (fscanf(config_file, "%s", library_name) > 0) { CModule *cmodule; struct list *entry; OMX_ERRORTYPE ret; library_name[OMX_MAX_STRINGNAME_SIZE-1] = '\0'; /* skip libraries starting with # */ if (library_name[0] == '#') continue; cmodule = new CModule(&library_name[0]); if (!cmodule) continue; LOGI("found component library %s\n", library_name); ret = cmodule->Load(MODULE_LAZY); if (ret != OMX_ErrorNone) goto delete_cmodule; ret = cmodule->QueryComponentNameAndRoles(); if (ret != OMX_ErrorNone) goto unload_cmodule; entry = list_alloc(cmodule); if (!entry) goto unload_cmodule; head = __list_add_tail(head, entry); cmodule->Unload(); LOGI("module %s:%s added to component list\n", cmodule->GetLibraryName(), cmodule->GetComponentName()); continue; unload_cmodule: cmodule->Unload(); delete_cmodule: delete cmodule; } fclose(config_file); return head; } static struct list *destruct_components(struct list *head) { struct list *entry, *next; list_foreach_safe(head, entry, next) { CModule *cmodule = static_cast(entry->data); head = __list_delete(head, entry); delete cmodule; } return head; } OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) { LOGV("%s(): enter", __FUNCTION__); pthread_mutex_lock(&g_module_lock); if (!g_initialized) { g_module_list = construct_components("wrs_omxil_components.list"); if (!g_module_list) { pthread_mutex_unlock(&g_module_lock); LOGE("%s(): exit failure, construct_components failed", __FUNCTION__); return OMX_ErrorInsufficientResources; } g_initialized = 1; } pthread_mutex_unlock(&g_module_lock); LOGV("%s(): exit done", __FUNCTION__); return OMX_ErrorNone; } OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) { OMX_ERRORTYPE ret = OMX_ErrorNone; LOGV("%s(): enter", __FUNCTION__); pthread_mutex_lock(&g_module_lock); if (!g_nr_instances) g_module_list = destruct_components(g_module_list); else ret = OMX_ErrorUndefined; pthread_mutex_unlock(&g_module_lock); g_initialized = 0; LOGV("%s(): exit done (ret : 0x%08x)", __FUNCTION__, ret); return ret; } OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( OMX_OUT OMX_STRING cComponentName, OMX_IN OMX_U32 nNameLength, OMX_IN OMX_U32 nIndex) { CModule *cmodule; struct list *entry; OMX_STRING cname; pthread_mutex_lock(&g_module_lock); entry = __list_entry(g_module_list, nIndex); if (!entry) { pthread_mutex_unlock(&g_module_lock); return OMX_ErrorNoMore; } pthread_mutex_unlock(&g_module_lock); cmodule = static_cast(entry->data); cname = cmodule->GetComponentName(); strncpy(cComponentName, cname, nNameLength); LOGV("%s(): found %u th component %s", __FUNCTION__, nIndex, cname); return OMX_ErrorNone; } OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_PTR pAppData, OMX_IN OMX_CALLBACKTYPE *pCallBacks) { struct list *entry; OMX_ERRORTYPE ret; LOGV("%s(): enter, try to get %s", __FUNCTION__, cComponentName); pthread_mutex_lock(&g_module_lock); list_foreach(g_module_list, entry) { CModule *cmodule; OMX_STRING cname; cmodule = static_cast(entry->data); cname = cmodule->GetComponentName(); if (!strcmp(cComponentName, cname)) { ComponentBase *cbase = NULL; ret = cmodule->Load(MODULE_NOW); if (ret != OMX_ErrorNone) { LOGE("%s(): exit failure, cmodule->Load failed\n", __FUNCTION__); goto unlock_list; } ret = cmodule->InstantiateComponent(&cbase); if (ret != OMX_ErrorNone){ LOGE("%s(): exit failure, cmodule->Instantiate failed\n", __FUNCTION__); goto unload_cmodule; } ret = cbase->GetHandle(pHandle, pAppData, pCallBacks); if (ret != OMX_ErrorNone) { LOGE("%s(): exit failure, cbase->GetHandle failed\n", __FUNCTION__); goto delete_cbase; } cbase->SetCModule(cmodule); g_nr_instances++; pthread_mutex_unlock(&g_module_lock); LOGI("get handle of component %s successfully", cComponentName); LOGV("%s(): exit done\n", __FUNCTION__); return OMX_ErrorNone; delete_cbase: delete cbase; unload_cmodule: cmodule->Unload(); unlock_list: pthread_mutex_unlock(&g_module_lock); LOGE("%s(): exit failure, (ret : 0x%08x)\n", __FUNCTION__, ret); return ret; } } pthread_mutex_unlock(&g_module_lock); LOGE("%s(): exit failure, %s not found", __FUNCTION__, cComponentName); return OMX_ErrorInvalidComponent; } OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( OMX_IN OMX_HANDLETYPE hComponent) { ComponentBase *cbase; CModule *cmodule; OMX_ERRORTYPE ret; char cname[OMX_MAX_STRINGNAME_SIZE]; if (!hComponent) return OMX_ErrorBadParameter; cbase = static_cast (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate); if (!cbase) { LOGE("%s(): exit failure, cannot find cbase pointer\n", __FUNCTION__); return OMX_ErrorBadParameter; } strcpy(&cname[0], cbase->GetName()); LOGV("%s(): enter, try to free %s", __FUNCTION__, cbase->GetName()); ret = cbase->FreeHandle(hComponent); if (ret != OMX_ErrorNone) { LOGE("%s(): exit failure, cbase->FreeHandle() failed (ret = 0x%08x)\n", __FUNCTION__, ret); return ret; } pthread_mutex_lock(&g_module_lock); g_nr_instances--; pthread_mutex_unlock(&g_module_lock); cmodule = cbase->GetCModule(); if (!cmodule) LOGE("fatal error, %s does not have cmodule\n", cbase->GetName()); delete cbase; if (cmodule) cmodule->Unload(); LOGI("free handle of component %s successfully", cname); LOGV("%s(): exit done", __FUNCTION__); return OMX_ErrorNone; } OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( OMX_IN OMX_STRING role, OMX_INOUT OMX_U32 *pNumComps, OMX_INOUT OMX_U8 **compNames) { struct list *entry; OMX_U32 nr_comps = 0, copied_nr_comps = 0; pthread_mutex_lock(&g_module_lock); list_foreach(g_module_list, entry) { CModule *cmodule; OMX_STRING cname; bool having_role; cmodule = static_cast(entry->data); having_role = cmodule->QueryHavingThisRole(role); if (having_role) { if (compNames && compNames[nr_comps]) { cname = cmodule->GetComponentName(); strncpy((OMX_STRING)&compNames[nr_comps][0], cname, OMX_MAX_STRINGNAME_SIZE); copied_nr_comps++; LOGV("%s(): component %s has %s role", __FUNCTION__, cname, role); } nr_comps++; } } pthread_mutex_unlock(&g_module_lock); if (!copied_nr_comps) *pNumComps = nr_comps; else { if (copied_nr_comps != *pNumComps) return OMX_ErrorBadParameter; } return OMX_ErrorNone; } OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( OMX_IN OMX_STRING compName, OMX_INOUT OMX_U32 *pNumRoles, OMX_OUT OMX_U8 **roles) { struct list *entry; pthread_mutex_lock(&g_module_lock); list_foreach(g_module_list, entry) { CModule *cmodule; OMX_STRING cname; cmodule = static_cast(entry->data); cname = cmodule->GetComponentName(); if (!strcmp(compName, cname)) { pthread_mutex_unlock(&g_module_lock); #if LOG_NDEBUG return cmodule->GetComponentRoles(pNumRoles, roles); #else OMX_ERRORTYPE ret; ret = cmodule->GetComponentRoles(pNumRoles, roles); if (ret != OMX_ErrorNone) { OMX_U32 i; for (i = 0; i < *pNumRoles; i++) { LOGV("%s(): component %s has %s role", __FUNCTION__, compName, &roles[i][0]); } } return ret; #endif } } pthread_mutex_unlock(&g_module_lock); return OMX_ErrorInvalidComponent; }