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