Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 2010, Texas Instruments Incorporated
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * *  Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  *
     12  * *  Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * *  Neither the name of Texas Instruments Incorporated nor the names of
     17  *    its contributors may be used to endorse or promote products derived
     18  *    from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <dlfcn.h>		/* For dynamic loading */
     34 #include <stdio.h>
     35 #include <string.h>
     36 #include <stdlib.h>
     37 #include <pthread.h>
     38 
     39 
     40 /* #include "OMX_RegLib.h" */
     41 #include "OMX_Component.h"
     42 #include "OMX_Core.h"
     43 #include "OMX_ComponentRegistry.h"
     44 
     45 #include "timm_osal_types.h"
     46 #include "timm_osal_error.h"
     47 #include "timm_osal_trace.h"
     48 #include "timm_osal_mutex.h"
     49 
     50 #ifdef CHECK_SECURE_STATE
     51 #include <sys/ioctl.h>
     52 #include <errno.h>
     53 #include <fcntl.h>
     54 #endif
     55 
     56 /** size for the array of allocated components.  Sets the maximum
     57  * number of components that can be allocated at once */
     58 #define MAXCOMP (50)
     59 #define MAXNAMESIZE (128)
     60 #define EMPTY_STRING "\0"
     61 
     62 /** Determine the number of elements in an array */
     63 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
     64 
     65 /** Array to hold the DLL pointers for each allocated component */
     66 static void *pModules[MAXCOMP] = { 0 };
     67 
     68 /** Array to hold the component handles for each allocated component */
     69 static void *pComponents[COUNTOF(pModules)] = { 0 };
     70 
     71 /* count for call OMX_Init() */
     72 int count = 0;
     73 pthread_mutex_t mutex;
     74 TIMM_OSAL_PTR pCoreInitMutex = NULL;
     75 
     76 int tableCount = 0;
     77 ComponentTable componentTable[MAX_TABLE_SIZE];
     78 char *sRoleArray[60][20];
     79 char compName[60][200];
     80 
     81 
     82 char *tComponentName[MAXCOMP][MAX_ROLES] = {
     83     /*video and image components */
     84     {"OMX.TI.DUCATI1.VIDEO.DECODER",
     85         "video_decoder.mpeg4",
     86         "video_decoder.avc",
     87         "video_decoder.h263",
     88         "video_decoder.wmv",
     89         "video_decoder.mpeg2",
     90         "video_decoder.svc",
     91         "video_decoder.sorspk", NULL},
     92     {"OMX.TI.DUCATI1.VIDEO.DECODER.secure",
     93         "video_decoder.mpeg4",
     94         "video_decoder.avc",
     95         "video_decoder.h263", NULL},
     96     {"OMX.TI.DUCATI1.VIDEO.H264E",
     97          "video_encoder.avc", NULL},
     98     {"OMX.TI.DUCATI1.VIDEO.MPEG4E",
     99          "video_encoder.mpeg4",
    100          "video_encoder.h263",NULL},
    101     {"OMX.TI.DUCATI1.VIDEO.CAMERA",  "camera.omx", NULL},
    102 #ifdef USE_ITTIAM_AAC
    103     {"OMX.ITTIAM.AAC.decode", "audio_decoder.aac", NULL},
    104     {"OMX.ITTIAM.BSAC.decode", "audio_decoder.aac", NULL},
    105 #endif
    106     {"OMX.ITTIAM.WMA.decode",  "audio_decoder.wma", NULL},
    107     {"OMX.ITTIAM.WMALSL.decode", "audio_decoder.wmalsl", NULL},
    108     {"OMX.ITTIAM.WMAPRO.decode", "audio_decoder.wmapro", NULL},
    109     /* terminate the table */
    110     {NULL, NULL},
    111 };
    112 
    113 //AD
    114 extern OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent);
    115 
    116 #define CORE_assert  CORE_paramCheck
    117 #define CORE_require CORE_paramCheck
    118 #define CORE_ensure  CORE_paramCheck
    119 
    120 #define CORE_paramCheck(C, V, S) do {\
    121     if (!(C)) { eError = V;\
    122     TIMM_OSAL_Error("failed check: " #C);\
    123     TIMM_OSAL_Error(" - returning error: " #V);\
    124     if(S) TIMM_OSAL_Error(" - %s", S);\
    125     goto EXIT; }\
    126     } while(0)
    127 
    128 /******************************Public*Routine******************************\
    129 * OMX_Init()
    130 *
    131 * Description:This method will initialize the OMX Core.  It is the
    132 * responsibility of the application to call OMX_Init to ensure the proper
    133 * set up of core resources.
    134 *
    135 * Returns:    OMX_NOERROR          Successful
    136 *
    137 * Note
    138 *
    139 \**************************************************************************/
    140 OMX_ERRORTYPE OMX_Init()
    141 {
    142 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    143 	TIMM_OSAL_ERRORTYPE eOsalError = TIMM_OSAL_ERR_NONE;
    144 
    145 	eOsalError = TIMM_OSAL_MutexObtain(pCoreInitMutex, TIMM_OSAL_SUSPEND);
    146 	CORE_assert(eOsalError == TIMM_OSAL_ERR_NONE,
    147 	    OMX_ErrorInsufficientResources, "Mutex lock failed");
    148 
    149 	count++;
    150 
    151 	if (count == 1)
    152 	{
    153 		pthread_mutex_init(&mutex, NULL);
    154 		eError = OMX_BuildComponentTable();
    155 	}
    156 
    157 	eOsalError = TIMM_OSAL_MutexRelease(pCoreInitMutex);
    158 	CORE_assert(eOsalError == TIMM_OSAL_ERR_NONE,
    159 	    OMX_ErrorInsufficientResources, "Mutex release failed");
    160       EXIT:
    161 	return eError;
    162 }
    163 
    164 /******************************Public*Routine******************************\
    165 * OMX_GetHandle
    166 *
    167 * Description: This method will create the handle of the COMPONENTTYPE
    168 * If the component is currently loaded, this method will reutrn the
    169 * hadle of existingcomponent or create a new instance of the component.
    170 * It will call the OMX_ComponentInit function and then the setcallback
    171 * method to initialize the callback functions
    172 * Parameters:
    173 * @param[out] pHandle            Handle of the loaded components
    174 * @param[in] cComponentName     Name of the component to load
    175 * @param[in] pAppData           Used to identify the callbacks of component
    176 * @param[in] pCallBacks         Application callbacks
    177 *
    178 * @retval OMX_ErrorUndefined
    179 * @retval OMX_ErrorInvalidComponentName
    180 * @retval OMX_ErrorInvalidComponent
    181 * @retval OMX_ErrorInsufficientResources
    182 * @retval OMX_NOERROR                      Successful
    183 *
    184 * Note
    185 *
    186 \**************************************************************************/
    187 
    188 OMX_ERRORTYPE OMX_GetHandle(OMX_HANDLETYPE * pHandle,
    189     OMX_STRING cComponentName, OMX_PTR pAppData,
    190     OMX_CALLBACKTYPE * pCallBacks)
    191 {
    192 	static const char prefix[] = "lib";
    193 	static const char postfix[] = ".so";
    194 	OMX_ERRORTYPE(*pComponentInit) (OMX_HANDLETYPE *);
    195 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    196 	OMX_COMPONENTTYPE *componentType;
    197 	int i;
    198 	char buf[sizeof(prefix) + MAXNAMESIZE + sizeof(postfix)];
    199 	const char *pErr = dlerror();
    200 	char *dlError = NULL;
    201 #ifdef CHECK_SECURE_STATE
    202         int secure_misc_drv_fd,ret;
    203         OMX_U8 mode, enable=1;
    204 #endif
    205 	if (pthread_mutex_lock(&mutex) != 0)
    206 	{
    207 		TIMM_OSAL_Error("Core: Error in Mutex lock");
    208 	}
    209 
    210 	CORE_require(NULL != cComponentName, OMX_ErrorBadParameter, NULL);
    211 	CORE_require(NULL != pHandle, OMX_ErrorBadParameter, NULL);
    212 	CORE_require(NULL != pCallBacks, OMX_ErrorBadParameter, NULL);
    213 	CORE_require(count > 0, OMX_ErrorUndefined,
    214 	    "OMX_GetHandle called without calling OMX_Init first");
    215 
    216 	/* Verify that the name is not too long and could cause a crash.  Notice
    217 	 * that the comparison is a greater than or equals.  This is to make
    218 	 * sure that there is room for the terminating NULL at the end of the
    219 	 * name. */
    220 	CORE_require(strlen(cComponentName) < MAXNAMESIZE,
    221 	    OMX_ErrorInvalidComponentName, NULL);
    222 
    223 	/* Locate the first empty slot for a component.  If no slots
    224 	 * are available, error out */
    225 	for (i = 0; i < (int)COUNTOF(pModules); i++)
    226 	{
    227 		if (pModules[i] == NULL)
    228 			break;
    229 	}
    230 	CORE_assert(i != COUNTOF(pModules), OMX_ErrorInsufficientResources,
    231 	    NULL);
    232 
    233 	/* load the component and check for an error.  If filename is not an
    234 	 * absolute path (i.e., it does not  begin with a "/"), then the
    235 	 * file is searched for in the following locations:
    236 	 *
    237 	 *     The LD_LIBRARY_PATH environment variable locations
    238 	 *     The library cache, /etc/ld.so.cache.
    239 	 *     /lib
    240 	 *     /usr/lib
    241 	 *
    242 	 * If there is an error, we can't go on, so set the error code and exit */
    243 	strcpy(buf, prefix);	/* the lengths are defined herein or have been */
    244 	strcat(buf, cComponentName);	/* checked already, so strcpy and strcat are  */
    245 	strcat(buf, postfix);	/* are safe to use in this context. */
    246 
    247 #ifdef CHECK_SECURE_STATE
    248         //Dont return errors from misc driver to the user if any.
    249         //Since this affects all usecases, secure and non-secure.
    250         //Do log the errors though.
    251         secure_misc_drv_fd = open("/dev/rproc_user", O_SYNC | O_RDONLY);
    252 	if (secure_misc_drv_fd < 0)
    253 	{
    254 		TIMM_OSAL_Error("Can't open misc driver device 0x%x\n", errno);
    255 	}
    256         else
    257         {
    258             ret = read(secure_misc_drv_fd, &mode, sizeof(mode));
    259             if (ret != sizeof(mode))
    260             {
    261                 TIMM_OSAL_Error("Can't read from the misc driver");
    262             }
    263             else
    264             {
    265                 if(mode == enable && strstr(cComponentName,"secure") == NULL)
    266                 {
    267                     TIMM_OSAL_Error("non-secure component not supported in secure mode");
    268                     eError = OMX_ErrorComponentNotFound;
    269                 }
    270             }
    271             ret = close(secure_misc_drv_fd);
    272             if (ret < 0)
    273             {
    274                 TIMM_OSAL_Error("Can't close the misc driver");
    275             }
    276         }
    277         /* Don't allow non-secure usecases if we are in secure state.
    278          * Else some of the memory regions will be unexpected firewalled.
    279          * This provides a clean exit in case we are in secure mode. */
    280         if (eError == OMX_ErrorComponentNotFound)
    281         {
    282             goto EXIT;
    283         }
    284 #endif //CHECK_SECURE_STATE
    285 
    286 
    287 //#if 0
    288 	pModules[i] = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
    289 	if (pModules[i] == NULL)
    290 	{
    291 		dlError = (char *)dlerror();
    292 		TIMM_OSAL_Error("Failed because %s", dlError);
    293 		eError = OMX_ErrorComponentNotFound;
    294 		goto EXIT;
    295 	}
    296 
    297 	/* Get a function pointer to the "OMX_ComponentInit" function.  If
    298 	 * there is an error, we can't go on, so set the error code and exit */
    299 	pComponentInit = dlsym(pModules[i], "OMX_ComponentInit");
    300 	pErr = dlerror();
    301 	CORE_assert(((pErr == NULL) && (pComponentInit != NULL)),
    302 	    OMX_ErrorInvalidComponent, NULL);
    303 //#endif
    304 
    305 	/* We now can access the dll.  So, we need to call the "OMX_ComponentInit"
    306 	 * method to load up the "handle" (which is just a list of functions to
    307 	 * call) and we should be all set.*/
    308 	*pHandle = malloc(sizeof(OMX_COMPONENTTYPE));
    309 	CORE_assert((*pHandle != NULL), OMX_ErrorInsufficientResources,
    310 	    "Malloc of pHandle* failed");
    311 
    312 	pComponents[i] = *pHandle;
    313 	componentType = (OMX_COMPONENTTYPE *) * pHandle;
    314 	componentType->nSize = sizeof(OMX_COMPONENTTYPE);
    315 
    316 	componentType->nVersion.s.nVersionMajor = 1;
    317 	componentType->nVersion.s.nVersionMinor = 1;
    318 	componentType->nVersion.s.nRevision = 0;
    319 	componentType->nVersion.s.nStep = 0;
    320 
    321 	eError = (*pComponentInit) (*pHandle);
    322 //eError = OMX_ComponentInit(*pHandle);
    323 	if (OMX_ErrorNone == eError)
    324 	{
    325 		eError =
    326 		    (componentType->SetCallbacks) (*pHandle, pCallBacks,
    327 		    pAppData);
    328 		CORE_assert(eError == OMX_ErrorNone, eError,
    329 		    "Core: Error returned from component SetCallBack");
    330 	} else
    331 	{
    332 		/* when the component fails to initialize, release the
    333 		   component handle structure */
    334 		free(*pHandle);
    335 		/* mark the component handle as NULL to prevent the caller from
    336 		   actually trying to access the component with it, should they
    337 		   ignore the return code */
    338 		*pHandle = NULL;
    339 		pComponents[i] = NULL;
    340 		dlclose(pModules[i]);
    341 		goto EXIT;
    342 	}
    343 	eError = OMX_ErrorNone;
    344       EXIT:
    345 	if (pthread_mutex_unlock(&mutex) != 0)
    346 	{
    347 		TIMM_OSAL_Error("Core: Error in Mutex unlock");
    348 	}
    349 	return (eError);
    350 }
    351 
    352 
    353 /******************************Public*Routine******************************\
    354 * OMX_FreeHandle()
    355 *
    356 * Description:This method will unload the OMX component pointed by
    357 * OMX_HANDLETYPE. It is the responsibility of the calling method to ensure that
    358 * the Deinit method of the component has been called prior to unloading component
    359 *
    360 * Parameters:
    361 * @param[in] hComponent the component to unload
    362 *
    363 * Returns:    OMX_NOERROR          Successful
    364 *
    365 * Note
    366 *
    367 \**************************************************************************/
    368 OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent)
    369 {
    370 
    371 	OMX_ERRORTYPE eError = OMX_ErrorUndefined;
    372 	OMX_COMPONENTTYPE *pHandle = (OMX_COMPONENTTYPE *) hComponent;
    373 	int i;
    374 
    375 	if (pthread_mutex_lock(&mutex) != 0)
    376 	{
    377 		TIMM_OSAL_Error("Core: Error in Mutex lock");
    378 	}
    379 
    380 	CORE_require(pHandle != NULL, OMX_ErrorBadParameter, NULL);
    381 	CORE_require(count > 0, OMX_ErrorUndefined,
    382 	    "OMX_FreeHandle called without calling OMX_Init first");
    383 
    384 	/* Locate the component handle in the array of handles */
    385 	for (i = 0; i < (int)COUNTOF(pModules); i++)
    386 	{
    387 		if (pComponents[i] == hComponent)
    388 			break;
    389 	}
    390 
    391 	CORE_assert(i != COUNTOF(pModules), OMX_ErrorBadParameter, NULL);
    392 
    393 	eError = pHandle->ComponentDeInit(hComponent);
    394 	if (eError != OMX_ErrorNone)
    395 	{
    396 		TIMM_OSAL_Error("Error From ComponentDeInit..");
    397 	}
    398 
    399 	/* release the component and the component handle */
    400 	dlclose(pModules[i]);
    401 	pModules[i] = NULL;
    402 	free(pComponents[i]);
    403 
    404 	pComponents[i] = NULL;
    405 	eError = OMX_ErrorNone;
    406 
    407       EXIT:
    408 	/* The unload is now complete, so set the error code to pass and exit */
    409 	if (pthread_mutex_unlock(&mutex) != 0)
    410 	{
    411 		TIMM_OSAL_Error("Core: Error in Mutex unlock");
    412 	}
    413 
    414 	return eError;
    415 }
    416 
    417 /******************************Public*Routine******************************\
    418 * OMX_DeInit()
    419 *
    420 * Description:This method will release the resources of the OMX Core.  It is the
    421 * responsibility of the application to call OMX_DeInit to ensure the clean up of these
    422 * resources.
    423 *
    424 * Returns:    OMX_NOERROR          Successful
    425 *
    426 * Note
    427 *
    428 \**************************************************************************/
    429 OMX_ERRORTYPE OMX_Deinit()
    430 {
    431 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    432 	TIMM_OSAL_ERRORTYPE eOsalError = TIMM_OSAL_ERR_NONE;
    433 
    434 	eOsalError = TIMM_OSAL_MutexObtain(pCoreInitMutex, TIMM_OSAL_SUSPEND);
    435 	if (eOsalError != TIMM_OSAL_ERR_NONE)
    436 	{
    437 		TIMM_OSAL_Error("Mutex lock failed");
    438 	}
    439 	/*Returning error none because of OMX spec limitation on error codes that
    440 	   can be returned by OMX_Deinit */
    441 	CORE_assert(count > 0, OMX_ErrorNone,
    442 	    "OMX_Deinit being called without a corresponding OMX_Init");
    443 	count--;
    444 
    445 	if (pthread_mutex_lock(&mutex) != 0)
    446 		TIMM_OSAL_Error("Core: Error in Mutex lock");
    447 
    448 	if (count == 0)
    449 	{
    450 		if (pthread_mutex_unlock(&mutex) != 0)
    451 			TIMM_OSAL_Error("Core: Error in Mutex unlock");
    452 		if (pthread_mutex_destroy(&mutex) != 0)
    453 		{
    454 			/*printf("%d :: Core: Error in Mutex destroy\n",__LINE__); */
    455 		}
    456 	} else
    457 	{
    458 		if (pthread_mutex_unlock(&mutex) != 0)
    459 			TIMM_OSAL_Error("Core: Error in Mutex unlock");
    460 	}
    461 
    462       EXIT:
    463 	eOsalError = TIMM_OSAL_MutexRelease(pCoreInitMutex);
    464 	if (eOsalError != TIMM_OSAL_ERR_NONE)
    465 	{
    466 		TIMM_OSAL_Error("Mutex release failed");
    467 	}
    468 	return eError;
    469 }
    470 
    471 /*************************************************************************
    472 * OMX_SetupTunnel()
    473 *
    474 * Description: Setup the specified tunnel the two components
    475 *
    476 * Parameters:
    477 * @param[in] hOutput     Handle of the component to be accessed
    478 * @param[in] nPortOutput Source port used in the tunnel
    479 * @param[in] hInput      Component to setup the tunnel with.
    480 * @param[in] nPortInput  Destination port used in the tunnel
    481 *
    482 * Returns:    OMX_NOERROR          Successful
    483 *
    484 * Note
    485 *
    486 **************************************************************************/
    487 /* OMX_SetupTunnel */
    488 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE
    489     hOutput, OMX_IN OMX_U32 nPortOutput, OMX_IN OMX_HANDLETYPE hInput,
    490     OMX_IN OMX_U32 nPortInput)
    491 {
    492 	OMX_ERRORTYPE eError = OMX_ErrorNotImplemented;
    493 	OMX_COMPONENTTYPE *pCompIn, *pCompOut;
    494 	OMX_TUNNELSETUPTYPE oTunnelSetup;
    495 
    496 	if (hOutput == NULL && hInput == NULL)
    497 		return OMX_ErrorBadParameter;
    498 
    499 	oTunnelSetup.nTunnelFlags = 0;
    500 	oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified;
    501 
    502 	pCompOut = (OMX_COMPONENTTYPE *) hOutput;
    503 
    504 	if (hOutput)
    505 	{
    506 		eError =
    507 		    pCompOut->ComponentTunnelRequest(hOutput, nPortOutput,
    508 		    hInput, nPortInput, &oTunnelSetup);
    509 	}
    510 
    511 
    512 	if (eError == OMX_ErrorNone && hInput)
    513 	{
    514 		pCompIn = (OMX_COMPONENTTYPE *) hInput;
    515 		eError =
    516 		    pCompIn->ComponentTunnelRequest(hInput, nPortInput,
    517 		    hOutput, nPortOutput, &oTunnelSetup);
    518 		if (eError != OMX_ErrorNone && hOutput)
    519 		{
    520 			/* cancel tunnel request on output port since input port failed */
    521 			pCompOut->ComponentTunnelRequest(hOutput, nPortOutput,
    522 			    NULL, 0, NULL);
    523 		}
    524 	}
    525 
    526 	return eError;
    527 }
    528 
    529 /*************************************************************************
    530 * OMX_ComponentNameEnum()
    531 *
    532 * Description: This method will provide the name of the component at the given nIndex
    533 *
    534 *Parameters:
    535 * @param[out] cComponentName       The name of the component at nIndex
    536 * @param[in] nNameLength                The length of the component name
    537 * @param[in] nIndex                         The index number of the component
    538 *
    539 * Returns:    OMX_NOERROR          Successful
    540 *
    541 * Note
    542 *
    543 **************************************************************************/
    544 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(OMX_OUT OMX_STRING
    545     cComponentName, OMX_IN OMX_U32 nNameLength, OMX_IN OMX_U32 nIndex)
    546 {
    547 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    548 
    549 	CORE_require(cComponentName != NULL, OMX_ErrorBadParameter, NULL);
    550 	CORE_require(count > 0, OMX_ErrorUndefined,
    551 	    "OMX_GetHandle called without calling OMX_Init first");
    552 
    553 	if (nIndex >= (OMX_U32)tableCount)
    554 	{
    555 		eError = OMX_ErrorNoMore;
    556 	} else
    557 	{
    558 		strcpy(cComponentName, componentTable[nIndex].name);
    559 	}
    560       EXIT:
    561 	return eError;
    562 }
    563 
    564 
    565 /*************************************************************************
    566 * OMX_GetRolesOfComponent()
    567 *
    568 * Description: This method will query the component for its supported roles
    569 *
    570 *Parameters:
    571 * @param[in] cComponentName     The name of the component to query
    572 * @param[in] pNumRoles     The number of roles supported by the component
    573 * @param[in] roles		The roles of the component
    574 *
    575 * Returns:    OMX_NOERROR          Successful
    576 *                 OMX_ErrorBadParameter		Faliure due to a bad input parameter
    577 *
    578 * Note
    579 *
    580 **************************************************************************/
    581 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_IN OMX_STRING
    582     cComponentName, OMX_INOUT OMX_U32 * pNumRoles, OMX_OUT OMX_U8 ** roles)
    583 {
    584 
    585 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    586 	OMX_U32 i = 0;
    587 	OMX_U32 j = 0;
    588 	OMX_BOOL bFound = OMX_FALSE;
    589 
    590 	CORE_require(cComponentName != NULL, OMX_ErrorBadParameter, NULL);
    591 	CORE_require(pNumRoles != NULL, OMX_ErrorBadParameter, NULL);
    592 	CORE_require(strlen(cComponentName) < MAXNAMESIZE,
    593 	    OMX_ErrorInvalidComponentName, NULL);
    594 	CORE_require(count > 0, OMX_ErrorUndefined,
    595 	    "OMX_GetHandle called without calling OMX_Init first");
    596 
    597 	while (!bFound && i < (OMX_U32)tableCount)
    598 	{
    599 		if (strcmp(cComponentName, componentTable[i].name) == 0)
    600 		{
    601 			bFound = OMX_TRUE;
    602 		} else
    603 		{
    604 			i++;
    605 		}
    606 	}
    607 	if (roles == NULL)
    608 	{
    609 		*pNumRoles = componentTable[i].nRoles;
    610 		goto EXIT;
    611 	} else
    612 	{
    613 		if (bFound && (*pNumRoles == componentTable[i].nRoles))
    614 		{
    615 			for (j = 0; j < componentTable[i].nRoles; j++)
    616 			{
    617 				strcpy((OMX_STRING) roles[j],
    618 				    componentTable[i].pRoleArray[j]);
    619 			}
    620 		}
    621 	}
    622       EXIT:
    623 	return eError;
    624 }
    625 
    626 /*************************************************************************
    627 * OMX_GetComponentsOfRole()
    628 *
    629 * Description: This method will query the component for its supported roles
    630 *
    631 *Parameters:
    632 * @param[in] role     The role name to query for
    633 * @param[in] pNumComps     The number of components supporting the given role
    634 * @param[in] compNames      The names of the components supporting the given role
    635 *
    636 * Returns:    OMX_NOERROR          Successful
    637 *
    638 * Note
    639 *
    640 **************************************************************************/
    641 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_IN OMX_STRING role,
    642     OMX_INOUT OMX_U32 * pNumComps, OMX_INOUT OMX_U8 ** compNames)
    643 {
    644 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    645 	OMX_U32 i = 0;
    646 	OMX_U32 j = 0;
    647 	OMX_U32 k = 0;
    648 
    649 	CORE_require(role != NULL, OMX_ErrorBadParameter, NULL);
    650 	CORE_require(pNumComps != NULL, OMX_ErrorBadParameter, NULL);
    651 	CORE_require(count > 0, OMX_ErrorUndefined,
    652 	    "OMX_GetHandle called without calling OMX_Init first");
    653 
    654 	/* This implies that the componentTable is not filled */
    655 	CORE_assert(componentTable[i].pRoleArray[j] != NULL,
    656 	    OMX_ErrorBadParameter, NULL);
    657 
    658 	for (i = 0; i < (OMX_U32)tableCount; i++)
    659 	{
    660 		for (j = 0; j < componentTable[i].nRoles; j++)
    661 		{
    662 			if (strcmp(componentTable[i].pRoleArray[j],
    663 				role) == 0)
    664 			{
    665 				/* the first call to this function should only count the number
    666 				   of roles so that for the second call compNames can be allocated
    667 				   with the proper size for that number of roles */
    668 				if (compNames != NULL)
    669 				{
    670 					strncpy((OMX_STRING) (compNames[k]),
    671 					    (OMX_STRING) componentTable[i].
    672 					    name, MAXNAMESIZE);
    673 				}
    674 				k++;
    675 			}
    676 		}
    677 		*pNumComps = k;
    678 	}
    679 
    680       EXIT:
    681 	return eError;
    682 }
    683 
    684 
    685 /***************************************
    686 PRINT TABLE FOR DEBUGGING PURPOSES ONLY
    687 ***************************************/
    688 
    689 OMX_API OMX_ERRORTYPE OMX_PrintComponentTable()
    690 {
    691 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    692 	int i = 0;
    693 	int j = 0;
    694 
    695 	TIMM_OSAL_Info
    696 	    ("--------Component Table:: %d Components found-------------",
    697 	    tableCount);
    698 
    699 	for (i = 0; i < tableCount; i++)
    700 	{
    701 		TIMM_OSAL_Info("%i:: %s", i, componentTable[i].name);
    702 		for (j = 0; j < componentTable[i].nRoles; j++)
    703 		{
    704 			TIMM_OSAL_Info("        %s",
    705 			    componentTable[i].pRoleArray[j]);
    706 		}
    707 	}
    708 
    709 	TIMM_OSAL_Info
    710 	    ("-----------------End Component Table ------------------");
    711 
    712 	return eError;
    713 
    714 }
    715 
    716 
    717 OMX_ERRORTYPE OMX_BuildComponentTable()
    718 {
    719 	OMX_ERRORTYPE eError = OMX_ErrorNone;
    720 	OMX_CALLBACKTYPE sCallbacks;
    721 #ifndef STATIC_TABLE
    722 	OMX_HANDLETYPE hComp = 0;
    723 	OMX_U8 cRole[MAXNAMESIZE];
    724 	OMX_STRING tempName = NULL;
    725 	OMX_STRING temp = NULL;
    726 	static OMX_STRING namePrefix = "OMX";
    727 	static OMX_STRING filePrefix = "libOMX.";
    728 	static OMX_STRING suffix = ".so";
    729 #endif
    730 	int j = 0;
    731 	int numFiles = 0;
    732 	int i, k;
    733 	int componentfound = 0;
    734 
    735 	/* set up dummy call backs */
    736 	sCallbacks.EventHandler = ComponentTable_EventHandler;
    737 	sCallbacks.EmptyBufferDone = ComponentTable_EmptyBufferDone;
    738 	sCallbacks.FillBufferDone = ComponentTable_FillBufferDone;
    739 
    740 #ifndef STATIC_TABLE
    741 	/* allocate the name table */
    742 	/*
    743 	   compName = (OMX_STRING *) malloc(MAX_TABLE_SIZE * sizeof(OMX_STRING));
    744 	   sRoleArray = (OMX_STRING**) malloc(MAX_TABLE_SIZE * sizeof(OMX_STRING));
    745 	 */
    746 
    747 	/* scan the target/lib directory and create a list of files in the directory */
    748 	numFiles = scandir(libdir, &namelist, 0, 0);
    749 	tableCount = 0;
    750 	while (numFiles--)
    751 	{
    752 		/*  check if the file is an OMX component */
    753 		if (strncmp(namelist[numFiles]->d_name, filePrefix,
    754 			strlen(filePrefix)) == 0)
    755 		{
    756 
    757 			/* if the file is an OMX component, trim the prefix and suffix */
    758 			tempName = (OMX_STRING) malloc(sizeof(namelist[numFiles]->d_name) + 1);	/* adding one ensures */
    759 			memset(tempName, 0x00, sizeof(namelist[numFiles]->d_name) + 1);	/*  that a null terminator will */
    760 			/*  always be present */
    761 			/* copy only the name without the suffix */
    762 			strncpy(tempName, namelist[numFiles]->d_name,
    763 			    strlen(namelist[numFiles]->d_name) -
    764 			    strlen(suffix));
    765 			/* set a pointer to be after the lib prefix, i.e the beginning of the component name */
    766 			temp = strstr(tempName, namePrefix);
    767 
    768 			/* then copy the component name to the table */
    769 			/*
    770 			   compName[tableCount]= (OMX_STRING) malloc(MAXNAMESIZE);
    771 			 */
    772 			strncpy(compName[tableCount], temp, strlen(temp) + 1);
    773 			componentTable[tableCount].name =
    774 			    compName[tableCount];
    775 
    776 			/* get the handle for the component and query for the roles of each component */
    777 			eError =
    778 			    OMX_GetHandle(&hComp,
    779 			    componentTable[tableCount].name, 0x0,
    780 			    &sCallbacks);
    781 			if (eError == OMX_ErrorNone)
    782 			{
    783 				j = 0;
    784 				while (eError != OMX_ErrorNoMore)
    785 				{
    786 					eError =
    787 					    ((OMX_COMPONENTTYPE *) hComp)->
    788 					    ComponentRoleEnum(hComp, cRole,
    789 					    j++);
    790 					if (eError == OMX_ErrorNotImplemented)
    791 					{
    792 						j = 1;
    793 						break;
    794 					}
    795 				}
    796 				nRoles = j - 1;
    797 				componentTable[tableCount].nRoles = nRoles;
    798 				/* sRoleArray[tableCount] = (OMX_STRING *) malloc(nRoles * sizeof(OMX_STRING)); */
    799 				if (nRoles > 0)
    800 				{
    801 					/* sRoleArray[tableCount] = (OMX_STRING *) malloc(nRoles * sizeof(OMX_STRING)); */
    802 					for (j = 0; j < nRoles; j++)
    803 					{
    804 						sRoleArray[tableCount][j] =
    805 						    (OMX_STRING)
    806 						    malloc(sizeof(OMX_U8) *
    807 						    MAXNAMESIZE);
    808 						((OMX_COMPONENTTYPE *)
    809 						    hComp)->
    810 						    ComponentRoleEnum(hComp,
    811 						    (OMX_U8 *)
    812 						    sRoleArray[tableCount][j],
    813 						    j);
    814 						componentTable[tableCount].
    815 						    pRoleArray[j] =
    816 						    sRoleArray[tableCount][j];
    817 					}
    818 				} else
    819 				{
    820 					/* sRoleArray[tableCount] = (OMX_STRING *) malloc(sizeof(OMX_STRING));    */
    821 					sRoleArray[tableCount][j] =
    822 					    (OMX_STRING) malloc(sizeof(OMX_U8)
    823 					    * MAXNAMESIZE);
    824 					strcpy(sRoleArray[tableCount][j],
    825 					    EMPTY_STRING);
    826 					componentTable[tableCount].
    827 					    pRoleArray[j] =
    828 					    sRoleArray[tableCount][j];
    829 				}
    830 			}
    831 			if (hComp)
    832 			{
    833 				/* free the component handle */
    834 				eError = OMX_FreeHandle(hComp);
    835 				if (eError != OMX_ErrorNone)
    836 				{
    837 					goto EXIT;
    838 				}
    839 			}
    840 			/* increment the table counter index only if above was successful */
    841 			tableCount++;
    842 			if (tempName != NULL)
    843 			{
    844 				free(tempName);
    845 			}
    846 
    847 		}
    848 	}
    849 
    850 #endif
    851 
    852 	for (i = 0, numFiles = 0; i < MAXCOMP; i++)
    853 	{
    854 		if (tComponentName[i][0] == NULL)
    855 		{
    856 			break;
    857 		}
    858 
    859 		for (j = 0; j < numFiles; j++)
    860 		{
    861 			if (!strcmp(componentTable[j].name,
    862 				tComponentName[i][0]))
    863 			{
    864 				componentfound = 1;
    865 				break;
    866 			}
    867 		}
    868 		if (componentfound == 1)
    869 		{
    870 			continue;
    871 		}
    872 
    873 		if (j == numFiles)
    874 		{		/* new component */
    875 			k = 1;
    876 			while (tComponentName[i][k] != NULL)
    877 			{
    878 				componentTable[numFiles].pRoleArray[k - 1] =
    879 				    tComponentName[i][k];
    880 				k++;
    881 			}
    882 			componentTable[numFiles].nRoles = k - 1;
    883 			strcpy(compName[numFiles], tComponentName[i][0]);
    884 			componentTable[numFiles].name = compName[numFiles];
    885 			numFiles++;
    886 		}
    887 	}
    888 	tableCount = numFiles;
    889 
    890 	CORE_assert(eError == OMX_ErrorNone, eError,
    891 	    "Could not build Component Table");
    892       EXIT:
    893 	return eError;
    894 }
    895 
    896 OMX_ERRORTYPE ComponentTable_EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
    897     OMX_IN OMX_PTR pAppData,
    898     OMX_IN OMX_EVENTTYPE eEvent,
    899     OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, OMX_IN OMX_PTR pEventData)
    900 {
    901 	return OMX_ErrorNotImplemented;
    902 }
    903 
    904 OMX_ERRORTYPE ComponentTable_EmptyBufferDone(OMX_OUT OMX_HANDLETYPE
    905     hComponent, OMX_OUT OMX_PTR pAppData,
    906     OMX_OUT OMX_BUFFERHEADERTYPE * pBuffer)
    907 {
    908 	return OMX_ErrorNotImplemented;
    909 }
    910 
    911 OMX_ERRORTYPE ComponentTable_FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent,
    912     OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE * pBuffer)
    913 {
    914 	return OMX_ErrorNotImplemented;
    915 }
    916 
    917 
    918 
    919 /*===============================================================*/
    920 /** @fn Core_Setup : This function is called when the the OMX Core library is
    921  *                  loaded. It creates a mutex, which is used during OMX_Init()
    922  */
    923 /*===============================================================*/
    924 void __attribute__ ((constructor)) Core_Setup(void)
    925 {
    926 	TIMM_OSAL_ERRORTYPE eError = TIMM_OSAL_ERR_NONE;
    927 
    928 	eError = TIMM_OSAL_MutexCreate(&pCoreInitMutex);
    929 	if (eError != TIMM_OSAL_ERR_NONE)
    930 	{
    931 		TIMM_OSAL_Error("Creation of default mutex failed");
    932 	}
    933 }
    934 
    935 
    936 
    937 /*===============================================================*/
    938 /** @fn Core_Destroy : This function is called when the the OMX Core library is
    939  *                    unloaded. It destroys the mutex which was created by
    940  *                    Core_Setup().
    941  *
    942  */
    943 /*===============================================================*/
    944 void __attribute__ ((destructor)) Core_Destroy(void)
    945 {
    946 	TIMM_OSAL_ERRORTYPE eError = TIMM_OSAL_ERR_NONE;
    947 
    948 	eError = TIMM_OSAL_MutexDelete(pCoreInitMutex);
    949 	if (eError != TIMM_OSAL_ERR_NONE)
    950 	{
    951 		TIMM_OSAL_Error("Destruction of default mutex failed");
    952 	}
    953 }
    954