OMX_Core.c revision 689f12aeb126c2a2da2286bfbcd1e51016de1b0f
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.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\**************************************************************************/
118OMX_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
167OMX_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;
296CLEAN_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
307UNLOCK_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\**************************************************************************/
332OMX_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
386EXIT:
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\**************************************************************************/
409OMX_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 */
447OMX_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**************************************************************************/
500OMX_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**************************************************************************/
536OMX_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**************************************************************************/
619OMX_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
722OMX_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
767OMX_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