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