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