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 */
66static void *pModules[MAXCOMP] = { 0 };
67
68/** Array to hold the component handles for each allocated component */
69static void *pComponents[COUNTOF(pModules)] = { 0 };
70
71/* count for call OMX_Init() */
72int count = 0;
73pthread_mutex_t mutex;
74TIMM_OSAL_PTR pCoreInitMutex = NULL;
75
76int tableCount = 0;
77ComponentTable componentTable[MAX_TABLE_SIZE];
78char *sRoleArray[60][20];
79char compName[60][200];
80
81
82char *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
114extern 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\**************************************************************************/
140OMX_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
188OMX_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\**************************************************************************/
368OMX_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\**************************************************************************/
429OMX_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 */
488OMX_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**************************************************************************/
544OMX_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**************************************************************************/
581OMX_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**************************************************************************/
641OMX_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/***************************************
686PRINT TABLE FOR DEBUGGING PURPOSES ONLY
687***************************************/
688
689OMX_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
717OMX_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
896OMX_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
904OMX_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
911OMX_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/*===============================================================*/
924void __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/*===============================================================*/
944void __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