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