Home | History | Annotate | Download | only in omx
      1 /*
      2  * Copyright (C) 2012 Intel Corporation.  All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 
     18 #include <inttypes.h>
     19 
     20 #include <OMX_Core.h>
     21 #include <OMX_Component.h>
     22 #include <dlfcn.h>
     23 
     24 #include "isv_omxcore.h"
     25 #include "isv_omxcomponent.h"
     26 #include "isv_profile.h"
     27 
     28 #include "OMX_adaptor.h"
     29 
     30 //#define LOG_NDEBUG 0
     31 #undef LOG_TAG
     32 #define LOG_TAG "isv-omxil"
     33 
     34 #define WRS_CORE_NAME "libwrs_omxil_core_pvwrapped.so"
     35 #define CORE_NUMBER 1
     36 #ifdef USE_MEDIASDK
     37 #define MSDK_CORE_NAME "libmfx_omx_core.so"
     38 #undef CORE_NUMBER
     39 #define CORE_NUMBER 2
     40 #endif
     41 
     42 
     43 using namespace android;
     44 
     45 static unsigned int g_initialized = 0;
     46 static unsigned int g_nr_instances = 0;
     47 static unsigned int g_nr_comp = 0;
     48 
     49 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
     50 static ISVOMXCore g_cores[CORE_NUMBER];
     51 static Vector<ISVComponent*> g_isv_components;
     52 
     53 MRM_OMX_Adaptor* g_mrm_omx_adaptor = NULL;
     54 
     55 /**********************************************************************************
     56  * core entry
     57  */
     58 
     59 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
     60 {
     61     int ret;
     62     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
     63 
     64     pthread_mutex_lock(&g_module_lock);
     65     if (!g_initialized) {
     66         for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
     67 
     68             void* libHandle = NULL;
     69             if (i == 0)
     70                 libHandle = dlopen(WRS_CORE_NAME, RTLD_LAZY);
     71 #ifdef USE_MEDIASDK
     72             else
     73                 libHandle = dlopen(MSDK_CORE_NAME, RTLD_LAZY);
     74 #endif
     75             if (libHandle != NULL) {
     76                 g_cores[i].mLibHandle = libHandle;
     77                 g_cores[i].mInit = (ISVOMXCore::InitFunc)dlsym(libHandle, "OMX_Init");
     78                 g_cores[i].mDeinit = (ISVOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit");
     79 
     80                 g_cores[i].mComponentNameEnum =
     81                     (ISVOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum");
     82 
     83                 g_cores[i].mGetHandle = (ISVOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle");
     84                 g_cores[i].mFreeHandle = (ISVOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle");
     85 
     86                 g_cores[i].mGetRolesOfComponentHandle =
     87                     (ISVOMXCore::GetRolesOfComponentFunc)dlsym(
     88                             libHandle, "OMX_GetRolesOfComponent");
     89                 if (g_cores[i].mInit != NULL) {
     90                     (*(g_cores[i].mInit))();
     91                 }
     92                 if (g_cores[i].mComponentNameEnum != NULL) {
     93                     // calculating number of components registered inside given OMX core
     94                     char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 };
     95                     OMX_U32 tmpIndex = 0;
     96                     while (OMX_ErrorNone == ((*(g_cores[i].mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) {
     97                         tmpIndex++;
     98                         ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: declares component %s", tmpComponentName);
     99                     }
    100                     g_cores[i].mNumComponents = tmpIndex;
    101                     g_nr_comp += g_cores[i].mNumComponents;
    102                     ALOGD_IF(ISV_CORE_DEBUG,
    103                              "OMX IL core: contains %" PRIu32 " components",
    104                              g_cores[i].mNumComponents);
    105                 }
    106             } else {
    107                 pthread_mutex_unlock(&g_module_lock);
    108                 ALOGW("OMX IL core not found");
    109             }
    110         }
    111         g_mrm_omx_adaptor = MRM_OMX_Adaptor::getInstance();
    112         g_mrm_omx_adaptor->MRM_OMX_Init();
    113         g_initialized = 1;
    114     }
    115     pthread_mutex_unlock(&g_module_lock);
    116 
    117     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    118     return OMX_ErrorNone;
    119 }
    120 
    121 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
    122 {
    123     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    124     OMX_ERRORTYPE ret = OMX_ErrorNone;
    125 
    126     ALOGV("%s: enter", __func__);
    127     if (g_initialized == 0)
    128         return OMX_ErrorNone;
    129 
    130     pthread_mutex_lock(&g_module_lock);
    131     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    132         if (g_cores[i].mDeinit != NULL) {
    133             (*(g_cores[i].mDeinit))();
    134         }
    135     }
    136     pthread_mutex_unlock(&g_module_lock);
    137 
    138     if (g_mrm_omx_adaptor != NULL) {
    139         g_mrm_omx_adaptor = NULL;
    140     }
    141 
    142     g_initialized = 0;
    143 
    144     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret);
    145     return ret;
    146 }
    147 
    148 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
    149     OMX_OUT OMX_STRING cComponentName,
    150     OMX_IN OMX_U32 nNameLength,
    151     OMX_IN OMX_U32 nIndex)
    152 {
    153     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    154     pthread_mutex_lock(&g_module_lock);
    155     OMX_U32 relativeIndex = nIndex;
    156     if (nIndex >= g_nr_comp) {
    157         pthread_mutex_unlock(&g_module_lock);
    158         ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    159         return OMX_ErrorNoMore;
    160     }
    161 
    162     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    163         if (g_cores[i].mLibHandle == NULL) {
    164            continue;
    165         }
    166         if (relativeIndex < g_cores[i].mNumComponents) {
    167             pthread_mutex_unlock(&g_module_lock);
    168             ALOGD_IF(ISV_CORE_DEBUG, "%s: found %" PRIu32 "th component %s",
    169                      __func__, nIndex, cComponentName);
    170             return ((*(g_cores[i].mComponentNameEnum))(cComponentName, nNameLength, relativeIndex));
    171         } else relativeIndex -= g_cores[i].mNumComponents;
    172     }
    173     pthread_mutex_unlock(&g_module_lock);
    174     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit error!!!", __func__);
    175     return OMX_ErrorUndefined;
    176 }
    177 
    178 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
    179     OMX_OUT OMX_HANDLETYPE* pHandle,
    180     OMX_IN OMX_STRING cComponentName,
    181     OMX_IN OMX_PTR pAppData,
    182     OMX_IN OMX_CALLBACKTYPE *pCallBacks)
    183 {
    184     struct list *entry;
    185     OMX_ERRORTYPE ret;
    186     OMX_HANDLETYPE tempHandle;
    187     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to get %s", __func__, cComponentName);
    188     pthread_mutex_lock(&g_module_lock);
    189 
    190     // create a isv component instant
    191     ISVComponent *pISVComponent = new ISVComponent(pAppData);
    192     if (!pISVComponent) {
    193         ALOGE("%s: failed to alloc isv omx component", __func__);
    194         pthread_mutex_unlock(&g_module_lock);
    195         return OMX_ErrorInsufficientResources;
    196     }
    197 
    198     OMX_CALLBACKTYPE *pISVCallBacks = pISVComponent->getCallBacks(pCallBacks);
    199     if (!pISVCallBacks) {
    200         ALOGE("%s: failed to get isv callback functions", __func__);
    201         pthread_mutex_unlock(&g_module_lock);
    202         return OMX_ErrorInsufficientResources;
    203     }
    204 
    205     ret = g_mrm_omx_adaptor->MRM_OMX_CheckIfFullLoad(cComponentName);
    206     if (ret == OMX_ErrorInsufficientResources) {
    207         ALOGE("OMX_GetHandle failed. codec under full load status from media resource manager.\
    208                return OMX_ErrorInsufficientResources");
    209         pthread_mutex_unlock(&g_module_lock);
    210         return OMX_ErrorInsufficientResources;
    211     }
    212 
    213     /* find the real component*/
    214     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    215         if (g_cores[i].mLibHandle == NULL) {
    216             continue;
    217         }
    218 
    219         OMX_ERRORTYPE omx_res = (*(g_cores[i].mGetHandle))(
    220                 &tempHandle,
    221                 const_cast<char *>(cComponentName),
    222                 pAppData, pISVCallBacks);
    223         if(omx_res == OMX_ErrorNone) {
    224             pISVComponent->setComponent(static_cast<OMX_COMPONENTTYPE*>(tempHandle), &g_cores[i]);
    225             g_isv_components.push_back(pISVComponent);
    226             *pHandle = pISVComponent->getBaseComponent();
    227 
    228             ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle);
    229 
    230             // set component into media resource manager adaptor
    231             g_mrm_omx_adaptor->MRM_OMX_SetComponent(tempHandle, cComponentName);
    232 
    233             pthread_mutex_unlock(&g_module_lock);
    234             return OMX_ErrorNone;
    235         } else if(omx_res == OMX_ErrorInsufficientResources) {
    236             pthread_mutex_unlock(&g_module_lock);
    237             delete pISVComponent;
    238             pISVComponent = NULL;
    239             return OMX_ErrorInsufficientResources;
    240         }
    241     }
    242     pthread_mutex_unlock(&g_module_lock);
    243 
    244     delete pISVComponent;
    245     pISVComponent = NULL;
    246     ALOGD_IF(ISV_CORE_DEBUG, "%s(): exit failure, %s not found", __func__, cComponentName);
    247     return OMX_ErrorInvalidComponent;
    248 }
    249 
    250 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
    251     OMX_IN OMX_HANDLETYPE hComponent)
    252 {
    253     OMX_ERRORTYPE ret;
    254 
    255     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to free component hanle %p", __func__, hComponent);
    256     pthread_mutex_lock(&g_module_lock);
    257 
    258     for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
    259         ISVComponent *pComp = g_isv_components.itemAt(i);
    260         if (static_cast<OMX_HANDLETYPE>(pComp->getBaseComponent()) == hComponent) {
    261             OMX_ERRORTYPE omx_res = pComp->freeComponent();
    262             if (omx_res != OMX_ErrorNone) {
    263                 ALOGE("%s: free OMX handle %p failed", __func__, hComponent);
    264                 pthread_mutex_unlock(&g_module_lock);
    265                 return omx_res;
    266             }
    267             delete pComp;
    268             g_isv_components.removeAt(i);
    269             ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent);
    270 
    271             // remove it in media resource manager
    272             g_mrm_omx_adaptor->MRM_OMX_RemoveComponent(pComp->getComponent());
    273             pthread_mutex_unlock(&g_module_lock);
    274             return OMX_ErrorNone;
    275         }
    276     }
    277     pthread_mutex_unlock(&g_module_lock);
    278     ALOGE("%s(): exit failure, component %p not found", __func__, hComponent);
    279     return OMX_ErrorInvalidComponent;
    280 }
    281 
    282 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
    283     OMX_IN OMX_HANDLETYPE __maybe_unused hOutput,
    284     OMX_IN OMX_U32 __maybe_unused nPortOutput,
    285     OMX_IN OMX_HANDLETYPE __maybe_unused hInput,
    286     OMX_IN OMX_U32 __maybe_unused nPortInput)
    287 {
    288     return OMX_ErrorNotImplemented;
    289 }
    290 
    291 OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
    292     OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe,
    293     OMX_IN OMX_STRING __maybe_unused szURI)
    294 {
    295     return OMX_ErrorNotImplemented;
    296 }
    297 
    298 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
    299     OMX_IN OMX_STRING __maybe_unused role,
    300     OMX_INOUT OMX_U32 __maybe_unused *pNumComps,
    301     OMX_INOUT OMX_U8  __maybe_unused **compNames)
    302 {
    303     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    304     return OMX_ErrorNotImplemented;
    305 }
    306 
    307 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
    308     OMX_IN OMX_STRING compName,
    309     OMX_INOUT OMX_U32 *pNumRoles,
    310     OMX_OUT OMX_U8 **roles)
    311 {
    312     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    313     pthread_mutex_lock(&g_module_lock);
    314     for (OMX_U32 j = 0; j < CORE_NUMBER; j++) {
    315         if (g_cores[j].mLibHandle == NULL) {
    316            continue;
    317         }
    318 
    319         OMX_U32 numRoles;
    320         OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    321                 const_cast<OMX_STRING>(compName), &numRoles, NULL);
    322 
    323         if (err != OMX_ErrorNone) {
    324             continue;
    325         }
    326 
    327         if (numRoles > 0) {
    328             OMX_U8 **array = new OMX_U8 *[numRoles];
    329             for (OMX_U32 i = 0; i < numRoles; ++i) {
    330                 array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
    331             }
    332 
    333             OMX_U32 numRoles2 = numRoles;
    334             err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    335                     const_cast<OMX_STRING>(compName), &numRoles2, array);
    336 
    337             *pNumRoles = numRoles;
    338             for (OMX_U32 i = 0; i < numRoles; i++) {
    339                 if (i < numRoles-1)
    340                     roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE;
    341 
    342                 strncpy((OMX_STRING)&roles[i][0],
    343                         (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE);
    344                 delete[] array[i];
    345                 array[i] = NULL;
    346             }
    347 
    348             delete[] array;
    349             array = NULL;
    350         }
    351 
    352         pthread_mutex_unlock(&g_module_lock);
    353         ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    354         return OMX_ErrorNone;
    355     }
    356     pthread_mutex_unlock(&g_module_lock);
    357 
    358     ALOGE("%s: invalid component", __func__);
    359     return OMX_ErrorInvalidComponent;
    360 }
    361 
    362