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             // remove it in media resource manager before call  pComp->freeComponent
    262             g_mrm_omx_adaptor->MRM_OMX_RemoveComponent(pComp->getComponent());
    263             OMX_ERRORTYPE omx_res = pComp->freeComponent();
    264             if (omx_res != OMX_ErrorNone) {
    265                 ALOGE("%s: free OMX handle %p failed", __func__, hComponent);
    266                 pthread_mutex_unlock(&g_module_lock);
    267                 return omx_res;
    268             }
    269             delete pComp;
    270             g_isv_components.removeAt(i);
    271             ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent);
    272             pthread_mutex_unlock(&g_module_lock);
    273             return OMX_ErrorNone;
    274         }
    275     }
    276     pthread_mutex_unlock(&g_module_lock);
    277     ALOGE("%s(): exit failure, component %p not found", __func__, hComponent);
    278     return OMX_ErrorInvalidComponent;
    279 }
    280 
    281 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
    282     OMX_IN OMX_HANDLETYPE __maybe_unused hOutput,
    283     OMX_IN OMX_U32 __maybe_unused nPortOutput,
    284     OMX_IN OMX_HANDLETYPE __maybe_unused hInput,
    285     OMX_IN OMX_U32 __maybe_unused nPortInput)
    286 {
    287     return OMX_ErrorNotImplemented;
    288 }
    289 
    290 OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
    291     OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe,
    292     OMX_IN OMX_STRING __maybe_unused szURI)
    293 {
    294     return OMX_ErrorNotImplemented;
    295 }
    296 
    297 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
    298     OMX_IN OMX_STRING __maybe_unused role,
    299     OMX_INOUT OMX_U32 __maybe_unused *pNumComps,
    300     OMX_INOUT OMX_U8  __maybe_unused **compNames)
    301 {
    302     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    303     return OMX_ErrorNotImplemented;
    304 }
    305 
    306 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
    307     OMX_IN OMX_STRING compName,
    308     OMX_INOUT OMX_U32 *pNumRoles,
    309     OMX_OUT OMX_U8 **roles)
    310 {
    311     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    312     pthread_mutex_lock(&g_module_lock);
    313     for (OMX_U32 j = 0; j < CORE_NUMBER; j++) {
    314         if (g_cores[j].mLibHandle == NULL) {
    315            continue;
    316         }
    317 
    318         OMX_U32 numRoles;
    319         OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    320                 const_cast<OMX_STRING>(compName), &numRoles, NULL);
    321 
    322         if (err != OMX_ErrorNone) {
    323             continue;
    324         }
    325 
    326         if (numRoles > 0) {
    327             OMX_U8 **array = new OMX_U8 *[numRoles];
    328             for (OMX_U32 i = 0; i < numRoles; ++i) {
    329                 array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
    330             }
    331 
    332             OMX_U32 numRoles2 = numRoles;
    333             err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    334                     const_cast<OMX_STRING>(compName), &numRoles2, array);
    335 
    336             *pNumRoles = numRoles;
    337             for (OMX_U32 i = 0; i < numRoles; i++) {
    338                 if (i < numRoles-1)
    339                     roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE;
    340 
    341                 strncpy((OMX_STRING)&roles[i][0],
    342                         (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE);
    343                 delete[] array[i];
    344                 array[i] = NULL;
    345             }
    346 
    347             delete[] array;
    348             array = NULL;
    349         }
    350 
    351         pthread_mutex_unlock(&g_module_lock);
    352         ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    353         return OMX_ErrorNone;
    354     }
    355     pthread_mutex_unlock(&g_module_lock);
    356 
    357     ALOGE("%s: invalid component", __func__);
    358     return OMX_ErrorInvalidComponent;
    359 }
    360 
    361