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