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 <OMX_Core.h>
     19 #include <OMX_Component.h>
     20 #include <dlfcn.h>
     21 
     22 #include "isv_omxcore.h"
     23 #include "isv_omxcomponent.h"
     24 #include "isv_profile.h"
     25 
     26 //#define LOG_NDEBUG 0
     27 #undef LOG_TAG
     28 #define LOG_TAG "isv-omxil"
     29 
     30 #define WRS_CORE_NAME "libwrs_omxil_core_pvwrapped.so"
     31 #define CORE_NUMBER 1
     32 #ifdef USE_MEDIASDK
     33 #define MSDK_CORE_NAME "libmfx_omx_core.so"
     34 #undef CORE_NUMBER
     35 #define CORE_NUMBER 2
     36 #endif
     37 
     38 
     39 using namespace android;
     40 
     41 static unsigned int g_initialized = 0;
     42 static unsigned int g_nr_instances = 0;
     43 static unsigned int g_nr_comp = 0;
     44 
     45 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
     46 static ISVOMXCore g_cores[CORE_NUMBER];
     47 static Vector<ISVComponent*> g_isv_components;
     48 
     49 /**********************************************************************************
     50  * core entry
     51  */
     52 
     53 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
     54 {
     55     int ret;
     56     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
     57 
     58     pthread_mutex_lock(&g_module_lock);
     59     if (!g_initialized) {
     60         for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
     61 
     62             void* libHandle = NULL;
     63             if (i == 0)
     64                 libHandle = dlopen(WRS_CORE_NAME, RTLD_LAZY);
     65 #ifdef USE_MEDIASDK
     66             else
     67                 libHandle = dlopen(MSDK_CORE_NAME, RTLD_LAZY);
     68 #endif
     69             if (libHandle != NULL) {
     70                 g_cores[i].mLibHandle = libHandle;
     71                 g_cores[i].mInit = (ISVOMXCore::InitFunc)dlsym(libHandle, "OMX_Init");
     72                 g_cores[i].mDeinit = (ISVOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit");
     73 
     74                 g_cores[i].mComponentNameEnum =
     75                     (ISVOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum");
     76 
     77                 g_cores[i].mGetHandle = (ISVOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle");
     78                 g_cores[i].mFreeHandle = (ISVOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle");
     79 
     80                 g_cores[i].mGetRolesOfComponentHandle =
     81                     (ISVOMXCore::GetRolesOfComponentFunc)dlsym(
     82                             libHandle, "OMX_GetRolesOfComponent");
     83                 if (g_cores[i].mInit != NULL) {
     84                     (*(g_cores[i].mInit))();
     85                 }
     86                 if (g_cores[i].mComponentNameEnum != NULL) {
     87                     // calculating number of components registered inside given OMX core
     88                     char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 };
     89                     OMX_U32 tmpIndex = 0;
     90                     while (OMX_ErrorNone == ((*(g_cores[i].mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) {
     91                         tmpIndex++;
     92                         ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: declares component %s", tmpComponentName);
     93                     }
     94                     g_cores[i].mNumComponents = tmpIndex;
     95                     g_nr_comp += g_cores[i].mNumComponents;
     96                     ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: contains %ld components", g_cores[i].mNumComponents);
     97                 }
     98             } else {
     99                 pthread_mutex_unlock(&g_module_lock);
    100                 ALOGW("OMX IL core not found");
    101             }
    102         }
    103         g_initialized = 1;
    104     }
    105     pthread_mutex_unlock(&g_module_lock);
    106 
    107     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    108     return OMX_ErrorNone;
    109 }
    110 
    111 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
    112 {
    113     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    114     OMX_ERRORTYPE ret = OMX_ErrorNone;
    115 
    116     ALOGV("%s: enter", __func__);
    117     if (g_initialized == 0)
    118         return OMX_ErrorNone;
    119 
    120     pthread_mutex_lock(&g_module_lock);
    121     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    122         if (g_cores[i].mDeinit != NULL) {
    123             (*(g_cores[i].mDeinit))();
    124         }
    125     }
    126     pthread_mutex_unlock(&g_module_lock);
    127 
    128     g_initialized = 0;
    129 
    130     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret);
    131     return ret;
    132 }
    133 
    134 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
    135     OMX_OUT OMX_STRING cComponentName,
    136     OMX_IN OMX_U32 nNameLength,
    137     OMX_IN OMX_U32 nIndex)
    138 {
    139     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    140     pthread_mutex_lock(&g_module_lock);
    141     OMX_U32 relativeIndex = nIndex;
    142     if (nIndex >= g_nr_comp) {
    143         pthread_mutex_unlock(&g_module_lock);
    144         ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    145         return OMX_ErrorNoMore;
    146     }
    147 
    148     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    149         if (g_cores[i].mLibHandle == NULL) {
    150            continue;
    151         }
    152         if (relativeIndex < g_cores[i].mNumComponents) {
    153             pthread_mutex_unlock(&g_module_lock);
    154             ALOGD_IF(ISV_CORE_DEBUG, "%s: found %luth component %s", __func__, nIndex, cComponentName);
    155             return ((*(g_cores[i].mComponentNameEnum))(cComponentName, nNameLength, relativeIndex));
    156         } else relativeIndex -= g_cores[i].mNumComponents;
    157     }
    158     pthread_mutex_unlock(&g_module_lock);
    159     ALOGD_IF(ISV_CORE_DEBUG, "%s: exit error!!!", __func__);
    160     return OMX_ErrorUndefined;
    161 }
    162 
    163 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
    164     OMX_OUT OMX_HANDLETYPE* pHandle,
    165     OMX_IN OMX_STRING cComponentName,
    166     OMX_IN OMX_PTR pAppData,
    167     OMX_IN OMX_CALLBACKTYPE *pCallBacks)
    168 {
    169     struct list *entry;
    170     OMX_ERRORTYPE ret;
    171     OMX_HANDLETYPE tempHandle;
    172     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to get %s", __func__, cComponentName);
    173     pthread_mutex_lock(&g_module_lock);
    174 
    175     // create a isv component instant
    176     ISVComponent *pISVComponent = new ISVComponent(pAppData);
    177     if (!pISVComponent) {
    178         ALOGE("%s: failed to alloc isv omx component", __func__);
    179         pthread_mutex_unlock(&g_module_lock);
    180         return OMX_ErrorInsufficientResources;
    181     }
    182 
    183     OMX_CALLBACKTYPE *pISVCallBacks = pISVComponent->getCallBacks(pCallBacks);
    184     if (!pISVCallBacks) {
    185         ALOGE("%s: failed to get isv callback functions", __func__);
    186         pthread_mutex_unlock(&g_module_lock);
    187         return OMX_ErrorInsufficientResources;
    188     }
    189 
    190     /* find the real component*/
    191     for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
    192         if (g_cores[i].mLibHandle == NULL) {
    193             continue;
    194         }
    195 
    196         OMX_ERRORTYPE omx_res = (*(g_cores[i].mGetHandle))(
    197                 &tempHandle,
    198                 const_cast<char *>(cComponentName),
    199                 pAppData, pISVCallBacks);
    200         if(omx_res == OMX_ErrorNone) {
    201             pISVComponent->setComponent(static_cast<OMX_COMPONENTTYPE*>(tempHandle), &g_cores[i]);
    202             g_isv_components.push_back(pISVComponent);
    203             *pHandle = pISVComponent->getBaseComponent();
    204 
    205             ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle);
    206             pthread_mutex_unlock(&g_module_lock);
    207             return OMX_ErrorNone;
    208         }
    209     }
    210     pthread_mutex_unlock(&g_module_lock);
    211 
    212     delete pISVComponent;
    213     pISVComponent = NULL;
    214     ALOGD_IF(ISV_CORE_DEBUG, "%s(): exit failure, %s not found", __func__, cComponentName);
    215     return OMX_ErrorInvalidComponent;
    216 }
    217 
    218 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
    219     OMX_IN OMX_HANDLETYPE hComponent)
    220 {
    221     OMX_ERRORTYPE ret;
    222 
    223     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to free component hanle %p", __func__, hComponent);
    224     pthread_mutex_lock(&g_module_lock);
    225 
    226     for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
    227         ISVComponent *pComp = g_isv_components.itemAt(i);
    228         if (static_cast<OMX_HANDLETYPE>(pComp->getBaseComponent()) == hComponent) {
    229             OMX_ERRORTYPE omx_res = pComp->freeComponent();
    230             if (omx_res != OMX_ErrorNone) {
    231                 ALOGE("%s: free OMX handle %p failed", __func__, hComponent);
    232                 pthread_mutex_unlock(&g_module_lock);
    233                 return omx_res;
    234             }
    235             delete pComp;
    236             g_isv_components.removeAt(i);
    237             ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent);
    238             pthread_mutex_unlock(&g_module_lock);
    239             return OMX_ErrorNone;
    240         }
    241     }
    242     pthread_mutex_unlock(&g_module_lock);
    243     ALOGE("%s(): exit failure, component %p not found", __func__, hComponent);
    244     return OMX_ErrorInvalidComponent;
    245 }
    246 
    247 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
    248     OMX_IN OMX_HANDLETYPE __maybe_unused hOutput,
    249     OMX_IN OMX_U32 __maybe_unused nPortOutput,
    250     OMX_IN OMX_HANDLETYPE __maybe_unused hInput,
    251     OMX_IN OMX_U32 __maybe_unused nPortInput)
    252 {
    253     return OMX_ErrorNotImplemented;
    254 }
    255 
    256 OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
    257     OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe,
    258     OMX_IN OMX_STRING __maybe_unused szURI)
    259 {
    260     return OMX_ErrorNotImplemented;
    261 }
    262 
    263 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
    264     OMX_IN OMX_STRING __maybe_unused role,
    265     OMX_INOUT OMX_U32 __maybe_unused *pNumComps,
    266     OMX_INOUT OMX_U8  __maybe_unused **compNames)
    267 {
    268     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    269     return OMX_ErrorNotImplemented;
    270 }
    271 
    272 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
    273     OMX_IN OMX_STRING compName,
    274     OMX_INOUT OMX_U32 *pNumRoles,
    275     OMX_OUT OMX_U8 **roles)
    276 {
    277     ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
    278     pthread_mutex_lock(&g_module_lock);
    279     for (OMX_U32 j = 0; j < CORE_NUMBER; j++) {
    280         if (g_cores[j].mLibHandle == NULL) {
    281            continue;
    282         }
    283 
    284         OMX_U32 numRoles;
    285         OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    286                 const_cast<OMX_STRING>(compName), &numRoles, NULL);
    287 
    288         if (err != OMX_ErrorNone) {
    289             continue;
    290         }
    291 
    292         if (numRoles > 0) {
    293             OMX_U8 **array = new OMX_U8 *[numRoles];
    294             for (OMX_U32 i = 0; i < numRoles; ++i) {
    295                 array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
    296             }
    297 
    298             OMX_U32 numRoles2 = numRoles;
    299             err = (*(g_cores[j].mGetRolesOfComponentHandle))(
    300                     const_cast<OMX_STRING>(compName), &numRoles2, array);
    301 
    302             *pNumRoles = numRoles;
    303             for (OMX_U32 i = 0; i < numRoles; i++) {
    304                 if (i < numRoles-1)
    305                     roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE;
    306 
    307                 strncpy((OMX_STRING)&roles[i][0],
    308                         (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE);
    309                 delete[] array[i];
    310                 array[i] = NULL;
    311             }
    312 
    313             delete[] array;
    314             array = NULL;
    315         }
    316 
    317         pthread_mutex_unlock(&g_module_lock);
    318         ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
    319         return OMX_ErrorNone;
    320     }
    321     pthread_mutex_unlock(&g_module_lock);
    322 
    323     ALOGE("%s: invalid component", __func__);
    324     return OMX_ErrorInvalidComponent;
    325 }
    326 
    327