Home | History | Annotate | Download | only in src
      1 /* ====================================================================
      2 *             Texas Instruments OMAP(TM) Platform Software
      3 * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved.
      4 *
      5 * Use of this software is controlled by the terms and conditions found
      6 * in the license agreement under which this software has been supplied.
      7 * ==================================================================== */
      8 
      9 #include <dlfcn.h>   /* For dynamic loading */
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include <stdlib.h>
     13 #include <pthread.h>
     14 #include <utils/Log.h>
     15 
     16 #undef LOG_TAG
     17 #define LOG_TAG "TIOMX_CORE"
     18 
     19 #include "OMX_Component.h"
     20 #include "OMX_Core.h"
     21 #include "OMX_ComponentRegistry.h"
     22 
     23 #ifndef NO_OPENCORE
     24 /** determine capabilities of a component before acually using it */
     25 #include "ti_omx_config_parser.h"
     26 #endif
     27 
     28 /** size for the array of allocated components.  Sets the maximum
     29  * number of components that can be allocated at once */
     30 #define MAXCOMP (50)
     31 #define MAXNAMESIZE (130)
     32 #define EMPTY_STRING "\0"
     33 
     34 /** Determine the number of elements in an array */
     35 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
     36 
     37 /** Array to hold the DLL pointers for each allocated component */
     38 static void* pModules[MAXCOMP] = {0};
     39 
     40 /** Array to hold the component handles for each allocated component */
     41 static void* pComponents[COUNTOF(pModules)] = {0};
     42 
     43 /** count will be used as a reference counter for OMX_Init()
     44     so all changes to count should be mutex protected */
     45 int count = 0;
     46 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     47 
     48 int tableCount = 0;
     49 ComponentTable componentTable[MAX_TABLE_SIZE];
     50 char * sRoleArray[60][20];
     51 char compName[60][200];
     52 
     53 char *tComponentName[MAXCOMP][2] = {
     54     /*video and image components */
     55     //{"OMX.TI.JPEG.decoder", "image_decoder.jpeg" },
     56     {"OMX.TI.JPEG.Encoder", "image_encoder.jpeg"},
     57     //{"OMX.TI.Video.Decoder", "video_decoder.h263"},
     58     {"OMX.TI.Video.Decoder", "video_decoder.avc"},
     59     //{"OMX.TI.Video.Decoder", "video_decoder.mpeg2"},
     60     {"OMX.TI.Video.Decoder", "video_decoder.mpeg4"},
     61     {"OMX.TI.Video.Decoder", "video_decoder.wmv"},
     62     {"OMX.TI.Video.encoder", "video_encoder.mpeg4"},
     63     {"OMX.TI.Video.encoder", "video_encoder.h263"},
     64     {"OMX.TI.Video.encoder", "video_encoder.avc"},
     65     //{"OMX.TI.VPP", "iv_renderer.yuv.overlay"},
     66     //{"OMX.TI.Camera", "camera.yuv"},
     67 
     68     /* Speech components */
     69 /*  {"OMX.TI.G729.encode", NULL},
     70     {"OMX.TI.G729.decode", NULL},
     71     {"OMX.TI.G722.encode", NULL},
     72     {"OMX.TI.G722.decode", NULL},
     73     {"OMX.TI.G711.encode", NULL},
     74     {"OMX.TI.G711.decode", NULL},
     75     {"OMX.TI.G723.encode", NULL},
     76     {"OMX.TI.G723.decode", NULL},
     77     {"OMX.TI.G726.encode", NULL},
     78     {"OMX.TI.G726.decode", NULL},
     79     {"OMX.TI.GSMFR.encode", NULL},
     80     {"OMX.TI.GSMFR.decode", NULL},
     81 */
     82 
     83     /* Audio components */
     84 #ifdef BUILD_WITH_TI_AUDIO
     85     {"OMX.TI.MP3.decode", "audio_decoder.mp3"},
     86     {"OMX.TI.AAC.encode", "audio_encoder.aac"},
     87     {"OMX.TI.AAC.decode", "audio_decoder.aac"},
     88     {"OMX.TI.WMA.decode", "audio_decoder.wma"},
     89     {"OMX.TI.WBAMR.decode", "audio_decoder.amrwb"},
     90     {"OMX.TI.AMR.decode", "audio_decoder.amrnb"},
     91     {"OMX.TI.AMR.encode", "audio_encoder.amrnb"},
     92     {"OMX.TI.WBAMR.encode", "audio_encoder.amrwb"},
     93 #endif
     94 /*  {"OMX.TI.PCM.encode", NULL},
     95     {"OMX.TI.PCM.decode", NULL},
     96     {"OMX.TI.RAG.decode", "audio_decoder.ra"},
     97     {"OMX.TI.IMAADPCM.decode", NULL},
     98     {"OMX.TI.IMAADPCM.encode", NULL},
     99 */
    100 
    101     /* terminate the table */
    102     {NULL, NULL},
    103 };
    104 
    105 
    106 /******************************Public*Routine******************************\
    107 * OMX_Init()
    108 *
    109 * Description:This method will initialize the OMX Core.  It is the
    110 * responsibility of the application to call OMX_Init to ensure the proper
    111 * set up of core resources.
    112 *
    113 * Returns:    OMX_NOERROR          Successful
    114 *
    115 * Note
    116 *
    117 \**************************************************************************/
    118 OMX_ERRORTYPE TIOMX_Init()
    119 {
    120     OMX_ERRORTYPE eError = OMX_ErrorNone;
    121 
    122     if(pthread_mutex_lock(&mutex) != 0)
    123     {
    124         LOGE("%d :: Core: Error in Mutex lock\n",__LINE__);
    125         return OMX_ErrorUndefined;
    126     }
    127 
    128     count++;
    129     LOGD("init count = %d\n", count);
    130 
    131     if (count == 1)
    132     {
    133         eError = TIOMX_BuildComponentTable();
    134     }
    135 
    136     if(pthread_mutex_unlock(&mutex) != 0)
    137     {
    138         LOGE("%d :: Core: Error in Mutex unlock\n",__LINE__);
    139         return OMX_ErrorUndefined;
    140     }
    141     return eError;
    142 }
    143 /******************************Public*Routine******************************\
    144 * OMX_GetHandle
    145 *
    146 * Description: This method will create the handle of the COMPONENTTYPE
    147 * If the component is currently loaded, this method will reutrn the
    148 * hadle of existingcomponent or create a new instance of the component.
    149 * It will call the OMX_ComponentInit function and then the setcallback
    150 * method to initialize the callback functions
    151 * Parameters:
    152 * @param[out] pHandle            Handle of the loaded components
    153 * @param[in] cComponentName     Name of the component to load
    154 * @param[in] pAppData           Used to identify the callbacks of component
    155 * @param[in] pCallBacks         Application callbacks
    156 *
    157 * @retval OMX_ErrorUndefined
    158 * @retval OMX_ErrorInvalidComponentName
    159 * @retval OMX_ErrorInvalidComponent
    160 * @retval OMX_ErrorInsufficientResources
    161 * @retval OMX_NOERROR                      Successful
    162 *
    163 * Note
    164 *
    165 \**************************************************************************/
    166 
    167 OMX_ERRORTYPE TIOMX_GetHandle( OMX_HANDLETYPE* pHandle, OMX_STRING cComponentName,
    168     OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks)
    169 {
    170     static const char prefix[] = "lib";
    171     static const char postfix[] = ".so";
    172     OMX_ERRORTYPE (*pComponentInit)(OMX_HANDLETYPE*);
    173     OMX_ERRORTYPE err = OMX_ErrorNone;
    174     OMX_COMPONENTTYPE *componentType;
    175     const char* pErr = dlerror();
    176 
    177     if(pthread_mutex_lock(&mutex) != 0)
    178     {
    179         LOGE("%d :: Core: Error in Mutex lock\n",__LINE__);
    180         return OMX_ErrorUndefined;
    181     }
    182 
    183     if ((NULL == cComponentName) || (NULL == pHandle) || (NULL == pCallBacks)) {
    184         err = OMX_ErrorBadParameter;
    185         goto UNLOCK_MUTEX;
    186     }
    187 
    188     /* Verify that the name is not too long and could cause a crash.  Notice
    189      * that the comparison is a greater than or equals.  This is to make
    190      * sure that there is room for the terminating NULL at the end of the
    191      * name. */
    192     if(strlen(cComponentName) >= MAXNAMESIZE) {
    193         err = OMX_ErrorInvalidComponentName;
    194         goto UNLOCK_MUTEX;
    195     }
    196     /* Locate the first empty slot for a component.  If no slots
    197      * are available, error out */
    198     int i = 0;
    199     for(i=0; i< COUNTOF(pModules); i++) {
    200         if(pModules[i] == NULL) break;
    201     }
    202     if(i == COUNTOF(pModules)) {
    203         err = OMX_ErrorInsufficientResources;
    204         goto UNLOCK_MUTEX;
    205     }
    206 
    207     int refIndex = 0;
    208     for (refIndex=0; refIndex < MAX_TABLE_SIZE; refIndex++) {
    209         //get the index for the component in the table
    210         if (strcmp(componentTable[refIndex].name, cComponentName) == 0) {
    211             LOGD("Found component %s with refCount %d\n",
    212                   cComponentName, componentTable[refIndex].refCount);
    213 
    214             /* check if the component is already loaded */
    215             if (componentTable[refIndex].refCount >= MAX_CONCURRENT_INSTANCES) {
    216                 err = OMX_ErrorInsufficientResources;
    217                 LOGE("Max instances of component %s already created.\n", cComponentName);
    218                 goto UNLOCK_MUTEX;
    219             } else {  // we have not reached the limit yet
    220                 /* do what was done before need to limit concurrent instances of each component */
    221 
    222                 /* load the component and check for an error.  If filename is not an
    223                  * absolute path (i.e., it does not  begin with a "/"), then the
    224                  * file is searched for in the following locations:
    225                  *
    226                  *     The LD_LIBRARY_PATH environment variable locations
    227                  *     The library cache, /etc/ld.so.cache.
    228                  *     /lib
    229                  *     /usr/lib
    230                  *
    231                  * If there is an error, we can't go on, so set the error code and exit */
    232 
    233                 /* the lengths are defined herein or have been
    234                  * checked already, so strcpy and strcat are
    235                  * are safe to use in this context. */
    236                 char buf[sizeof(prefix) + MAXNAMESIZE + sizeof(postfix)];
    237                 strcpy(buf, prefix);
    238                 strcat(buf, cComponentName);
    239                 strcat(buf, postfix);
    240 
    241                 pModules[i] = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
    242                 if( pModules[i] == NULL ) {
    243                     LOGE("dlopen %s failed because %s\n", buf, dlerror());
    244                     err = OMX_ErrorComponentNotFound;
    245                     goto UNLOCK_MUTEX;
    246                 }
    247 
    248                 /* Get a function pointer to the "OMX_ComponentInit" function.  If
    249                  * there is an error, we can't go on, so set the error code and exit */
    250                 pComponentInit = dlsym(pModules[i], "OMX_ComponentInit");
    251                 pErr = dlerror();
    252                 if( (pErr != NULL) || (pComponentInit == NULL) ) {
    253                     LOGE("%d:: dlsym failed for module %p\n", __LINE__, pModules[i]);
    254                     err = OMX_ErrorInvalidComponent;
    255                     goto CLEAN_UP;
    256                 }
    257 
    258                /* We now can access the dll.  So, we need to call the "OMX_ComponentInit"
    259                 * method to load up the "handle" (which is just a list of functions to
    260                 * call) and we should be all set.*/
    261                 *pHandle = malloc(sizeof(OMX_COMPONENTTYPE));
    262                 if(*pHandle == NULL) {
    263                     err = OMX_ErrorInsufficientResources;
    264                     LOGE("%d:: malloc of pHandle* failed\n", __LINE__);
    265                     goto CLEAN_UP;
    266                 }
    267 
    268                 pComponents[i] = *pHandle;
    269                 componentType = (OMX_COMPONENTTYPE*) *pHandle;
    270                 componentType->nSize = sizeof(OMX_COMPONENTTYPE);
    271                 err = (*pComponentInit)(*pHandle);
    272                 if (OMX_ErrorNone == err) {
    273                     err = (componentType->SetCallbacks)(*pHandle, pCallBacks, pAppData);
    274                     if (err != OMX_ErrorNone) {
    275                         LOGE("%d :: Core: SetCallBack failed %d\n",__LINE__, err);
    276                         goto CLEAN_UP;
    277                     }
    278                     /* finally, OMX_ComponentInit() was successful and
    279                        SetCallbacks was successful, we have a valid instance,
    280                        so no we increment refCount */
    281                     componentTable[refIndex].pHandle[componentTable[refIndex].refCount] = *pHandle;
    282                     componentTable[refIndex].refCount += 1;
    283                     goto UNLOCK_MUTEX;  // Component is found, and thus we are done
    284                 }
    285                 else if (err == OMX_ErrorInsufficientResources) {
    286                         LOGE("%d :: Core: Insufficient Resources for Component %d\n",__LINE__, err);
    287                         goto CLEAN_UP;
    288                 }
    289             }
    290         }
    291     }
    292 
    293     // If we are here, we have not found the component
    294     err = OMX_ErrorComponentNotFound;
    295     goto UNLOCK_MUTEX;
    296 CLEAN_UP:
    297     if(*pHandle != NULL)
    298     /* cover the case where we error out before malloc'd */
    299     {
    300         free(*pHandle);
    301         *pHandle = NULL;
    302     }
    303     pComponents[i] = NULL;
    304     dlclose(pModules[i]);
    305     pModules[i] = NULL;
    306 
    307 UNLOCK_MUTEX:
    308     if(pthread_mutex_unlock(&mutex) != 0)
    309     {
    310         LOGE("%d :: Core: Error in Mutex unlock\n",__LINE__);
    311         err = OMX_ErrorUndefined;
    312     }
    313     return (err);
    314 }
    315 
    316 
    317 /******************************Public*Routine******************************\
    318 * OMX_FreeHandle()
    319 *
    320 * Description:This method will unload the OMX component pointed by
    321 * OMX_HANDLETYPE. It is the responsibility of the calling method to ensure that
    322 * the Deinit method of the component has been called prior to unloading component
    323 *
    324 * Parameters:
    325 * @param[in] hComponent the component to unload
    326 *
    327 * Returns:    OMX_NOERROR          Successful
    328 *
    329 * Note
    330 *
    331 \**************************************************************************/
    332 OMX_ERRORTYPE TIOMX_FreeHandle (OMX_HANDLETYPE hComponent)
    333 {
    334 
    335     OMX_ERRORTYPE retVal = OMX_ErrorUndefined;
    336     OMX_COMPONENTTYPE *pHandle = (OMX_COMPONENTTYPE *)hComponent;
    337 
    338     if(pthread_mutex_lock(&mutex) != 0)
    339     {
    340         LOGE("%d :: Core: Error in Mutex lock\n",__LINE__);
    341         return OMX_ErrorUndefined;
    342     }
    343 
    344     /* Locate the component handle in the array of handles */
    345     int i = 0;
    346     for(i=0; i< COUNTOF(pModules); i++) {
    347         if(pComponents[i] == hComponent) break;
    348     }
    349 
    350     if(i == COUNTOF(pModules)) {
    351         LOGE("%d :: Core: component %p is not found\n", __LINE__, hComponent);
    352         retVal = OMX_ErrorBadParameter;
    353         goto EXIT;
    354     }
    355 
    356     retVal = pHandle->ComponentDeInit(hComponent);
    357     if (retVal != OMX_ErrorNone) {
    358         LOGE("%d :: ComponentDeInit failed %d\n",__LINE__, retVal);
    359         goto EXIT;
    360     }
    361 
    362     int refIndex = 0, handleIndex = 0;
    363     for (refIndex=0; refIndex < MAX_TABLE_SIZE; refIndex++) {
    364         for (handleIndex=0; handleIndex < componentTable[refIndex].refCount; handleIndex++){
    365             /* get the position for the component in the table */
    366             if (componentTable[refIndex].pHandle[handleIndex] == hComponent){
    367                 LOGD("Found matching pHandle(%p) at index %d with refCount %d",
    368                       hComponent, refIndex, componentTable[refIndex].refCount);
    369                 if (componentTable[refIndex].refCount) {
    370                     componentTable[refIndex].refCount -= 1;
    371                 }
    372                 componentTable[refIndex].pHandle[handleIndex] = NULL;
    373                 dlclose(pModules[i]);
    374                 pModules[i] = NULL;
    375                 free(pComponents[i]);
    376                 pComponents[i] = NULL;
    377                 retVal = OMX_ErrorNone;
    378                 goto EXIT;
    379             }
    380         }
    381     }
    382 
    383     // If we are here, we have not found the matching component
    384     retVal = OMX_ErrorComponentNotFound;
    385 
    386 EXIT:
    387     /* The unload is now complete, so set the error code to pass and exit */
    388     if(pthread_mutex_unlock(&mutex) != 0)
    389     {
    390         LOGE("%d :: Core: Error in Mutex unlock\n",__LINE__);
    391         return OMX_ErrorUndefined;
    392     }
    393 
    394     return retVal;
    395 }
    396 
    397 /******************************Public*Routine******************************\
    398 * OMX_DeInit()
    399 *
    400 * Description:This method will release the resources of the OMX Core.  It is the
    401 * responsibility of the application to call OMX_DeInit to ensure the clean up of these
    402 * resources.
    403 *
    404 * Returns:    OMX_NOERROR          Successful
    405 *
    406 * Note
    407 *
    408 \**************************************************************************/
    409 OMX_ERRORTYPE TIOMX_Deinit()
    410 {
    411     if(pthread_mutex_lock(&mutex) != 0) {
    412         LOGE("%d :: Core: Error in Mutex lock\n",__LINE__);
    413         return OMX_ErrorUndefined;
    414     }
    415 
    416     if (count) {
    417         count--;
    418     }
    419 
    420     LOGD("deinit count = %d\n", count);
    421 
    422     if(pthread_mutex_unlock(&mutex) != 0) {
    423         LOGE("%d :: Core: Error in Mutex unlock\n",__LINE__);
    424         return OMX_ErrorUndefined;
    425     }
    426 
    427     return OMX_ErrorNone;
    428 }
    429 
    430 /*************************************************************************
    431 * OMX_SetupTunnel()
    432 *
    433 * Description: Setup the specified tunnel the two components
    434 *
    435 * Parameters:
    436 * @param[in] hOutput     Handle of the component to be accessed
    437 * @param[in] nPortOutput Source port used in the tunnel
    438 * @param[in] hInput      Component to setup the tunnel with.
    439 * @param[in] nPortInput  Destination port used in the tunnel
    440 *
    441 * Returns:    OMX_NOERROR          Successful
    442 *
    443 * Note
    444 *
    445 **************************************************************************/
    446 /* OMX_SetupTunnel */
    447 OMX_API OMX_ERRORTYPE OMX_APIENTRY TIOMX_SetupTunnel(
    448     OMX_IN  OMX_HANDLETYPE hOutput,
    449     OMX_IN  OMX_U32 nPortOutput,
    450     OMX_IN  OMX_HANDLETYPE hInput,
    451     OMX_IN  OMX_U32 nPortInput)
    452 {
    453     OMX_ERRORTYPE eError = OMX_ErrorNotImplemented;
    454     OMX_COMPONENTTYPE *pCompIn, *pCompOut;
    455     OMX_TUNNELSETUPTYPE oTunnelSetup;
    456 
    457     if (hOutput == NULL && hInput == NULL)
    458         return OMX_ErrorBadParameter;
    459 
    460     oTunnelSetup.nTunnelFlags = 0;
    461     oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified;
    462 
    463     pCompOut = (OMX_COMPONENTTYPE*)hOutput;
    464 
    465     if (hOutput)
    466     {
    467         eError = pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, &oTunnelSetup);
    468     }
    469 
    470 
    471     if (eError == OMX_ErrorNone && hInput)
    472     {
    473         pCompIn = (OMX_COMPONENTTYPE*)hInput;
    474         eError = pCompIn->ComponentTunnelRequest(hInput, nPortInput, hOutput, nPortOutput, &oTunnelSetup);
    475         if (eError != OMX_ErrorNone && hOutput)
    476         {
    477             /* cancel tunnel request on output port since input port failed */
    478             pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, NULL, 0, NULL);
    479         }
    480     }
    481 
    482     return eError;
    483 }
    484 
    485 /*************************************************************************
    486 * OMX_ComponentNameEnum()
    487 *
    488 * Description: This method will provide the name of the component at the given nIndex
    489 *
    490 *Parameters:
    491 * @param[out] cComponentName       The name of the component at nIndex
    492 * @param[in] nNameLength                The length of the component name
    493 * @param[in] nIndex                         The index number of the component
    494 *
    495 * Returns:    OMX_NOERROR          Successful
    496 *
    497 * Note
    498 *
    499 **************************************************************************/
    500 OMX_API OMX_ERRORTYPE OMX_APIENTRY TIOMX_ComponentNameEnum(
    501     OMX_OUT OMX_STRING cComponentName,
    502     OMX_IN  OMX_U32 nNameLength,
    503     OMX_IN  OMX_U32 nIndex)
    504 {
    505     OMX_ERRORTYPE eError = OMX_ErrorNone;
    506 
    507     if (nIndex >=  tableCount)
    508     {
    509         eError = OMX_ErrorNoMore;
    510      }
    511     else
    512     {
    513         strcpy(cComponentName, componentTable[nIndex].name);
    514     }
    515 
    516     return eError;
    517 }
    518 
    519 
    520 /*************************************************************************
    521 * OMX_GetRolesOfComponent()
    522 *
    523 * Description: This method will query the component for its supported roles
    524 *
    525 *Parameters:
    526 * @param[in] cComponentName     The name of the component to query
    527 * @param[in] pNumRoles     The number of roles supported by the component
    528 * @param[in] roles		The roles of the component
    529 *
    530 * Returns:    OMX_NOERROR          Successful
    531 *                 OMX_ErrorBadParameter		Faliure due to a bad input parameter
    532 *
    533 * Note
    534 *
    535 **************************************************************************/
    536 OMX_API OMX_ERRORTYPE TIOMX_GetRolesOfComponent (
    537     OMX_IN      OMX_STRING cComponentName,
    538     OMX_INOUT   OMX_U32 *pNumRoles,
    539     OMX_OUT     OMX_U8 **roles)
    540 {
    541 
    542     OMX_ERRORTYPE eError = OMX_ErrorNone;
    543     OMX_U32 i = 0;
    544     OMX_U32 j = 0;
    545     OMX_BOOL bFound = OMX_FALSE;
    546 
    547     if (cComponentName == NULL || pNumRoles == NULL)
    548     {
    549         if (cComponentName == NULL)
    550         {
    551             LOGE("cComponentName is NULL\n");
    552         }
    553         if (pNumRoles == NULL)
    554         {
    555             LOGE("pNumRoles is NULL\n");
    556         }
    557         eError = OMX_ErrorBadParameter;
    558         goto EXIT;
    559     }
    560     while (i < tableCount)
    561     {
    562         if (strcmp(cComponentName, componentTable[i].name) == 0)
    563         {
    564             bFound = OMX_TRUE;
    565             break;
    566         }
    567         i++;
    568     }
    569     if (!bFound)
    570     {
    571         eError = OMX_ErrorComponentNotFound;
    572         LOGE("component %s not found\n", cComponentName);
    573         goto EXIT;
    574     }
    575     if (roles == NULL)
    576     {
    577         *pNumRoles = componentTable[i].nRoles;
    578     }
    579     else
    580     {
    581         /* must be second of two calls,
    582            pNumRoles is input in this context.
    583            If pNumRoles is < actual number of roles
    584            than we return an error */
    585         if (*pNumRoles >= componentTable[i].nRoles)
    586         {
    587             for (j = 0; j<componentTable[i].nRoles; j++)
    588             {
    589                 strcpy((OMX_STRING)roles[j], componentTable[i].pRoleArray[j]);
    590             }
    591             *pNumRoles = componentTable[i].nRoles;
    592         }
    593         else
    594         {
    595             eError = OMX_ErrorBadParameter;
    596             LOGE("pNumRoles (%d) is less than actual number (%d) of roles \
    597                    for this component %s\n", *pNumRoles, componentTable[i].nRoles, cComponentName);
    598         }
    599     }
    600     EXIT:
    601     return eError;
    602 }
    603 
    604 /*************************************************************************
    605 * OMX_GetComponentsOfRole()
    606 *
    607 * Description: This method will query the component for its supported roles
    608 *
    609 *Parameters:
    610 * @param[in] role     The role name to query for
    611 * @param[in] pNumComps     The number of components supporting the given role
    612 * @param[in] compNames      The names of the components supporting the given role
    613 *
    614 * Returns:    OMX_NOERROR          Successful
    615 *
    616 * Note
    617 *
    618 **************************************************************************/
    619 OMX_API OMX_ERRORTYPE TIOMX_GetComponentsOfRole (
    620     OMX_IN      OMX_STRING role,
    621     OMX_INOUT   OMX_U32 *pNumComps,
    622     OMX_INOUT   OMX_U8  **compNames)
    623 {
    624     OMX_ERRORTYPE eError = OMX_ErrorNone;
    625     OMX_U32 i = 0;
    626     OMX_U32 j = 0;
    627     OMX_U32 k = 0;
    628     OMX_U32 compOfRoleCount = 0;
    629 
    630     if (role == NULL || pNumComps == NULL)
    631     {
    632        if (role == NULL)
    633        {
    634            LOGE("role is NULL");
    635        }
    636        if (pNumComps == NULL)
    637        {
    638            LOGE("pNumComps is NULL\n");
    639        }
    640        eError = OMX_ErrorBadParameter;
    641        goto EXIT;
    642     }
    643 
    644    /* This implies that the componentTable is not filled */
    645     if (!tableCount)
    646     {
    647         eError = OMX_ErrorUndefined;
    648         LOGE("Component table is empty. Please reload OMX Core\n");
    649         goto EXIT;
    650     }
    651 
    652     /* no matter, we always want to know number of matching components
    653        so this will always run */
    654     for (i = 0; i < tableCount; i++)
    655     {
    656         for (j = 0; j < componentTable[i].nRoles; j++)
    657         {
    658             if (strcmp(componentTable[i].pRoleArray[j], role) == 0)
    659             {
    660                 /* the first call to this function should only count the number
    661                    of roles
    662                 */
    663                 compOfRoleCount++;
    664             }
    665         }
    666     }
    667     if (compOfRoleCount == 0)
    668     {
    669         eError = OMX_ErrorComponentNotFound;
    670         LOGE("Component supporting role %s was not found\n", role);
    671     }
    672     if (compNames == NULL)
    673     {
    674         /* must be the first of two calls */
    675         *pNumComps = compOfRoleCount;
    676     }
    677     else
    678     {
    679         /* must be the second of two calls */
    680         if (*pNumComps < compOfRoleCount)
    681         {
    682             /* pNumComps is input in this context,
    683                it can not be less, this would indicate
    684                the array is not large enough
    685             */
    686             eError = OMX_ErrorBadParameter;
    687             LOGE("pNumComps (%d) is less than the actual number (%d) of components \
    688                   supporting role %s\n", *pNumComps, compOfRoleCount, role);
    689         }
    690         else
    691         {
    692             k = 0;
    693             for (i = 0; i < tableCount; i++)
    694             {
    695                 for (j = 0; j < componentTable[i].nRoles; j++)
    696                 {
    697                     if (strcmp(componentTable[i].pRoleArray[j], role) == 0)
    698                     {
    699                         /*  the second call compNames can be allocated
    700                             with the proper size for that number of roles.
    701                         */
    702                         compNames[k] = (OMX_U8*)componentTable[i].name;
    703                         k++;
    704                         if (k == compOfRoleCount)
    705                         {
    706                             /* there are no more components of this role
    707                                so we can exit here */
    708                             *pNumComps = k;
    709                             goto EXIT;
    710                         }
    711                     }
    712                 }
    713             }
    714         }
    715     }
    716 
    717     EXIT:
    718     return eError;
    719 }
    720 
    721 
    722 OMX_ERRORTYPE TIOMX_BuildComponentTable()
    723 {
    724     OMX_ERRORTYPE eError = OMX_ErrorNone;
    725     OMX_CALLBACKTYPE sCallbacks;
    726     int j = 0;
    727     int numFiles = 0;
    728     int i;
    729 
    730     for (i = 0, numFiles = 0; i < MAXCOMP; i ++) {
    731         if (tComponentName[i][0] == NULL) {
    732             break;
    733         }
    734         if (numFiles <= MAX_TABLE_SIZE){
    735             for (j = 0; j < numFiles; j ++) {
    736                 if (!strcmp(componentTable[j].name, tComponentName[i][0])) {
    737                     /* insert the role */
    738                     if (tComponentName[i][1] != NULL)
    739                     {
    740                         componentTable[j].pRoleArray[componentTable[j].nRoles] = tComponentName[i][1];
    741                         componentTable[j].pHandle[componentTable[j].nRoles] = NULL; //initilize the pHandle element
    742                         componentTable[j].nRoles ++;
    743                     }
    744                     break;
    745                 }
    746             }
    747             if (j == numFiles) { /* new component */
    748                 if (tComponentName[i][1] != NULL){
    749                     componentTable[numFiles].pRoleArray[0] = tComponentName[i][1];
    750                     componentTable[numFiles].nRoles = 1;
    751                 }
    752                 strcpy(compName[numFiles], tComponentName[i][0]);
    753                 componentTable[numFiles].name = compName[numFiles];
    754                 componentTable[numFiles].refCount = 0; //initialize reference counter.
    755                 numFiles ++;
    756             }
    757         }
    758     }
    759     tableCount = numFiles;
    760     if (eError != OMX_ErrorNone){
    761         LOGE("Could not build Component Table\n");
    762     }
    763 
    764     return eError;
    765 }
    766 
    767 OMX_BOOL TIOMXConfigParserRedirect(
    768     OMX_PTR aInputParameters,
    769     OMX_PTR aOutputParameters)
    770 
    771 {
    772     OMX_BOOL Status = OMX_FALSE;
    773 #ifndef NO_OPENCORE
    774     Status = TIOMXConfigParser(aInputParameters, aOutputParameters);
    775 #endif
    776     return Status;
    777 }
    778