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     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