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