Home | History | Annotate | Download | only in src
      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