1 /* ==================================================================== 2 * Texas Instruments OMAP(TM) Platform Software 3 * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved. 4 * 5 * Use of this software is controlled by the terms and conditions found 6 * in the license agreement under which this software has been supplied. 7 * ==================================================================== */ 8 9 #include <dlfcn.h> /* For dynamic loading */ 10 #include <stdio.h> 11 #include <string.h> 12 #include <stdlib.h> 13 #include <pthread.h> 14 #include <utils/Log.h> 15 16 #undef LOG_TAG 17 #define LOG_TAG "TIOMX_CORE" 18 19 #include "OMX_Component.h" 20 #include "OMX_Core.h" 21 #include "OMX_ComponentRegistry.h" 22 23 #ifndef NO_OPENCORE 24 /** determine capabilities of a component before acually using it */ 25 #include "ti_omx_config_parser.h" 26 #endif 27 28 /** size for the array of allocated components. Sets the maximum 29 * number of components that can be allocated at once */ 30 #define MAXCOMP (50) 31 #define MAXNAMESIZE (130) 32 #define EMPTY_STRING "\0" 33 34 /** Determine the number of elements in an array */ 35 #define COUNTOF(x) (sizeof(x)/sizeof(x[0])) 36 37 /** Array to hold the DLL pointers for each allocated component */ 38 static void* pModules[MAXCOMP] = {0}; 39 40 /** Array to hold the component handles for each allocated component */ 41 static void* pComponents[COUNTOF(pModules)] = {0}; 42 43 /** count will be used as a reference counter for OMX_Init() 44 so all changes to count should be mutex protected */ 45 int count = 0; 46 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 47 48 int tableCount = 0; 49 ComponentTable componentTable[MAX_TABLE_SIZE]; 50 char * sRoleArray[60][20]; 51 char compName[60][200]; 52 53 char *tComponentName[MAXCOMP][2] = { 54 /*video and image components */ 55 //{"OMX.TI.JPEG.decoder", "image_decoder.jpeg" }, 56 {"OMX.TI.JPEG.Encoder", "image_encoder.jpeg"}, 57 //{"OMX.TI.Video.Decoder", "video_decoder.h263"}, 58 {"OMX.TI.Video.Decoder", "video_decoder.avc"}, 59 //{"OMX.TI.Video.Decoder", "video_decoder.mpeg2"}, 60 {"OMX.TI.Video.Decoder", "video_decoder.mpeg4"}, 61 {"OMX.TI.Video.Decoder", "video_decoder.wmv"}, 62 {"OMX.TI.Video.encoder", "video_encoder.mpeg4"}, 63 {"OMX.TI.Video.encoder", "video_encoder.h263"}, 64 {"OMX.TI.Video.encoder", "video_encoder.avc"}, 65 //{"OMX.TI.VPP", "iv_renderer.yuv.overlay"}, 66 //{"OMX.TI.Camera", "camera.yuv"}, 67 68 /* Speech components */ 69 /* {"OMX.TI.G729.encode", NULL}, 70 {"OMX.TI.G729.decode", NULL}, 71 {"OMX.TI.G722.encode", NULL}, 72 {"OMX.TI.G722.decode", NULL}, 73 {"OMX.TI.G711.encode", NULL}, 74 {"OMX.TI.G711.decode", NULL}, 75 {"OMX.TI.G723.encode", NULL}, 76 {"OMX.TI.G723.decode", NULL}, 77 {"OMX.TI.G726.encode", NULL}, 78 {"OMX.TI.G726.decode", NULL}, 79 {"OMX.TI.GSMFR.encode", NULL}, 80 {"OMX.TI.GSMFR.decode", NULL}, 81 */ 82 83 /* Audio components */ 84 #ifdef BUILD_WITH_TI_AUDIO 85 {"OMX.TI.MP3.decode", "audio_decoder.mp3"}, 86 {"OMX.TI.AAC.encode", "audio_encoder.aac"}, 87 {"OMX.TI.AAC.decode", "audio_decoder.aac"}, 88 {"OMX.TI.WMA.decode", "audio_decoder.wma"}, 89 {"OMX.TI.WBAMR.decode", "audio_decoder.amrwb"}, 90 {"OMX.TI.AMR.decode", "audio_decoder.amrnb"}, 91 {"OMX.TI.AMR.encode", "audio_encoder.amrnb"}, 92 {"OMX.TI.WBAMR.encode", "audio_encoder.amrwb"}, 93 #endif 94 /* {"OMX.TI.PCM.encode", NULL}, 95 {"OMX.TI.PCM.decode", NULL}, 96 {"OMX.TI.RAG.decode", "audio_decoder.ra"}, 97 {"OMX.TI.IMAADPCM.decode", NULL}, 98 {"OMX.TI.IMAADPCM.encode", NULL}, 99 */ 100 101 /* terminate the table */ 102 {NULL, NULL}, 103 }; 104 105 106 /******************************Public*Routine******************************\ 107 * OMX_Init() 108 * 109 * Description:This method will initialize the OMX Core. It is the 110 * responsibility of the application to call OMX_Init to ensure the proper 111 * set up of core resources. 112 * 113 * Returns: OMX_NOERROR Successful 114 * 115 * Note 116 * 117 \**************************************************************************/ 118 OMX_ERRORTYPE TIOMX_Init() 119 { 120 OMX_ERRORTYPE eError = OMX_ErrorNone; 121 122 if(pthread_mutex_lock(&mutex) != 0) 123 { 124 ALOGE("%d :: Core: Error in Mutex lock\n",__LINE__); 125 return OMX_ErrorUndefined; 126 } 127 128 count++; 129 ALOGD("init count = %d\n", count); 130 131 if (count == 1) 132 { 133 eError = TIOMX_BuildComponentTable(); 134 } 135 136 if(pthread_mutex_unlock(&mutex) != 0) 137 { 138 ALOGE("%d :: Core: Error in Mutex unlock\n",__LINE__); 139 return OMX_ErrorUndefined; 140 } 141 return eError; 142 } 143 /******************************Public*Routine******************************\ 144 * OMX_GetHandle 145 * 146 * Description: This method will create the handle of the COMPONENTTYPE 147 * If the component is currently loaded, this method will reutrn the 148 * hadle of existingcomponent or create a new instance of the component. 149 * It will call the OMX_ComponentInit function and then the setcallback 150 * method to initialize the callback functions 151 * Parameters: 152 * @param[out] pHandle Handle of the loaded components 153 * @param[in] cComponentName Name of the component to load 154 * @param[in] pAppData Used to identify the callbacks of component 155 * @param[in] pCallBacks Application callbacks 156 * 157 * @retval OMX_ErrorUndefined 158 * @retval OMX_ErrorInvalidComponentName 159 * @retval OMX_ErrorInvalidComponent 160 * @retval OMX_ErrorInsufficientResources 161 * @retval OMX_NOERROR Successful 162 * 163 * Note 164 * 165 \**************************************************************************/ 166 167 OMX_ERRORTYPE TIOMX_GetHandle( OMX_HANDLETYPE* pHandle, OMX_STRING cComponentName, 168 OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks) 169 { 170 static const char prefix[] = "lib"; 171 static const char postfix[] = ".so"; 172 OMX_ERRORTYPE (*pComponentInit)(OMX_HANDLETYPE*); 173 OMX_ERRORTYPE err = OMX_ErrorNone; 174 OMX_COMPONENTTYPE *componentType; 175 const char* pErr = dlerror(); 176 177 if(pthread_mutex_lock(&mutex) != 0) 178 { 179 ALOGE("%d :: Core: Error in Mutex lock\n",__LINE__); 180 return OMX_ErrorUndefined; 181 } 182 183 if ((NULL == cComponentName) || (NULL == pHandle) || (NULL == pCallBacks)) { 184 err = OMX_ErrorBadParameter; 185 goto UNLOCK_MUTEX; 186 } 187 188 /* Verify that the name is not too long and could cause a crash. Notice 189 * that the comparison is a greater than or equals. This is to make 190 * sure that there is room for the terminating NULL at the end of the 191 * name. */ 192 if(strlen(cComponentName) >= MAXNAMESIZE) { 193 err = OMX_ErrorInvalidComponentName; 194 goto UNLOCK_MUTEX; 195 } 196 /* Locate the first empty slot for a component. If no slots 197 * are available, error out */ 198 int i = 0; 199 for(i=0; i< COUNTOF(pModules); i++) { 200 if(pModules[i] == NULL) break; 201 } 202 if(i == COUNTOF(pModules)) { 203 err = OMX_ErrorInsufficientResources; 204 goto UNLOCK_MUTEX; 205 } 206 207 int refIndex = 0; 208 for (refIndex=0; refIndex < MAX_TABLE_SIZE; refIndex++) { 209 //get the index for the component in the table 210 if (strcmp(componentTable[refIndex].name, cComponentName) == 0) { 211 ALOGD("Found component %s with refCount %d\n", 212 cComponentName, componentTable[refIndex].refCount); 213 214 /* check if the component is already loaded */ 215 if (componentTable[refIndex].refCount >= MAX_CONCURRENT_INSTANCES) { 216 err = OMX_ErrorInsufficientResources; 217 ALOGE("Max instances of component %s already created.\n", cComponentName); 218 goto UNLOCK_MUTEX; 219 } else { // we have not reached the limit yet 220 /* do what was done before need to limit concurrent instances of each component */ 221 222 /* load the component and check for an error. If filename is not an 223 * absolute path (i.e., it does not begin with a "/"), then the 224 * file is searched for in the following locations: 225 * 226 * The LD_LIBRARY_PATH environment variable locations 227 * The library cache, /etc/ld.so.cache. 228 * /lib 229 * /usr/lib 230 * 231 * If there is an error, we can't go on, so set the error code and exit */ 232 233 /* the lengths are defined herein or have been 234 * checked already, so strcpy and strcat are 235 * are safe to use in this context. */ 236 char buf[sizeof(prefix) + MAXNAMESIZE + sizeof(postfix)]; 237 strcpy(buf, prefix); 238 strcat(buf, cComponentName); 239 strcat(buf, postfix); 240 241 pModules[i] = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); 242 if( pModules[i] == NULL ) { 243 ALOGE("dlopen %s failed because %s\n", buf, dlerror()); 244 err = OMX_ErrorComponentNotFound; 245 goto UNLOCK_MUTEX; 246 } 247 248 /* Get a function pointer to the "OMX_ComponentInit" function. If 249 * there is an error, we can't go on, so set the error code and exit */ 250 pComponentInit = dlsym(pModules[i], "OMX_ComponentInit"); 251 pErr = dlerror(); 252 if( (pErr != NULL) || (pComponentInit == NULL) ) { 253 ALOGE("%d:: dlsym failed for module %p\n", __LINE__, pModules[i]); 254 err = OMX_ErrorInvalidComponent; 255 goto CLEAN_UP; 256 } 257 258 /* We now can access the dll. So, we need to call the "OMX_ComponentInit" 259 * method to load up the "handle" (which is just a list of functions to 260 * call) and we should be all set.*/ 261 *pHandle = malloc(sizeof(OMX_COMPONENTTYPE)); 262 if(*pHandle == NULL) { 263 err = OMX_ErrorInsufficientResources; 264 ALOGE("%d:: malloc of pHandle* failed\n", __LINE__); 265 goto CLEAN_UP; 266 } 267 268 pComponents[i] = *pHandle; 269 componentType = (OMX_COMPONENTTYPE*) *pHandle; 270 componentType->nSize = sizeof(OMX_COMPONENTTYPE); 271 err = (*pComponentInit)(*pHandle); 272 if (OMX_ErrorNone == err) { 273 err = (componentType->SetCallbacks)(*pHandle, pCallBacks, pAppData); 274 if (err != OMX_ErrorNone) { 275 ALOGE("%d :: Core: SetCallBack failed %d\n",__LINE__, err); 276 goto CLEAN_UP; 277 } 278 /* finally, OMX_ComponentInit() was successful and 279 SetCallbacks was successful, we have a valid instance, 280 so no we increment refCount */ 281 componentTable[refIndex].pHandle[componentTable[refIndex].refCount] = *pHandle; 282 componentTable[refIndex].refCount += 1; 283 goto UNLOCK_MUTEX; // Component is found, and thus we are done 284 } 285 else if (err == OMX_ErrorInsufficientResources) { 286 ALOGE("%d :: Core: Insufficient Resources for Component %d\n",__LINE__, err); 287 goto CLEAN_UP; 288 } 289 } 290 } 291 } 292 293 // If we are here, we have not found the component 294 err = OMX_ErrorComponentNotFound; 295 goto UNLOCK_MUTEX; 296 CLEAN_UP: 297 if(*pHandle != NULL) 298 /* cover the case where we error out before malloc'd */ 299 { 300 free(*pHandle); 301 *pHandle = NULL; 302 } 303 pComponents[i] = NULL; 304 dlclose(pModules[i]); 305 pModules[i] = NULL; 306 307 UNLOCK_MUTEX: 308 if(pthread_mutex_unlock(&mutex) != 0) 309 { 310 ALOGE("%d :: Core: Error in Mutex unlock\n",__LINE__); 311 err = OMX_ErrorUndefined; 312 } 313 return (err); 314 } 315 316 317 /******************************Public*Routine******************************\ 318 * OMX_FreeHandle() 319 * 320 * Description:This method will unload the OMX component pointed by 321 * OMX_HANDLETYPE. It is the responsibility of the calling method to ensure that 322 * the Deinit method of the component has been called prior to unloading component 323 * 324 * Parameters: 325 * @param[in] hComponent the component to unload 326 * 327 * Returns: OMX_NOERROR Successful 328 * 329 * Note 330 * 331 \**************************************************************************/ 332 OMX_ERRORTYPE TIOMX_FreeHandle (OMX_HANDLETYPE hComponent) 333 { 334 335 OMX_ERRORTYPE retVal = OMX_ErrorUndefined; 336 OMX_COMPONENTTYPE *pHandle = (OMX_COMPONENTTYPE *)hComponent; 337 338 if(pthread_mutex_lock(&mutex) != 0) 339 { 340 ALOGE("%d :: Core: Error in Mutex lock\n",__LINE__); 341 return OMX_ErrorUndefined; 342 } 343 344 /* Locate the component handle in the array of handles */ 345 int i = 0; 346 for(i=0; i< COUNTOF(pModules); i++) { 347 if(pComponents[i] == hComponent) break; 348 } 349 350 if(i == COUNTOF(pModules)) { 351 ALOGE("%d :: Core: component %p is not found\n", __LINE__, hComponent); 352 retVal = OMX_ErrorBadParameter; 353 goto EXIT; 354 } 355 356 retVal = pHandle->ComponentDeInit(hComponent); 357 if (retVal != OMX_ErrorNone) { 358 ALOGE("%d :: ComponentDeInit failed %d\n",__LINE__, retVal); 359 goto EXIT; 360 } 361 362 int refIndex = 0, handleIndex = 0; 363 for (refIndex=0; refIndex < MAX_TABLE_SIZE; refIndex++) { 364 for (handleIndex=0; handleIndex < componentTable[refIndex].refCount; handleIndex++){ 365 /* get the position for the component in the table */ 366 if (componentTable[refIndex].pHandle[handleIndex] == hComponent){ 367 ALOGD("Found matching pHandle(%p) at index %d with refCount %d", 368 hComponent, refIndex, componentTable[refIndex].refCount); 369 if (componentTable[refIndex].refCount) { 370 componentTable[refIndex].refCount -= 1; 371 } 372 componentTable[refIndex].pHandle[handleIndex] = NULL; 373 dlclose(pModules[i]); 374 pModules[i] = NULL; 375 free(pComponents[i]); 376 pComponents[i] = NULL; 377 retVal = OMX_ErrorNone; 378 goto EXIT; 379 } 380 } 381 } 382 383 // If we are here, we have not found the matching component 384 retVal = OMX_ErrorComponentNotFound; 385 386 EXIT: 387 /* The unload is now complete, so set the error code to pass and exit */ 388 if(pthread_mutex_unlock(&mutex) != 0) 389 { 390 ALOGE("%d :: Core: Error in Mutex unlock\n",__LINE__); 391 return OMX_ErrorUndefined; 392 } 393 394 return retVal; 395 } 396 397 /******************************Public*Routine******************************\ 398 * OMX_DeInit() 399 * 400 * Description:This method will release the resources of the OMX Core. It is the 401 * responsibility of the application to call OMX_DeInit to ensure the clean up of these 402 * resources. 403 * 404 * Returns: OMX_NOERROR Successful 405 * 406 * Note 407 * 408 \**************************************************************************/ 409 OMX_ERRORTYPE TIOMX_Deinit() 410 { 411 if(pthread_mutex_lock(&mutex) != 0) { 412 ALOGE("%d :: Core: Error in Mutex lock\n",__LINE__); 413 return OMX_ErrorUndefined; 414 } 415 416 if (count) { 417 count--; 418 } 419 420 ALOGD("deinit count = %d\n", count); 421 422 if(pthread_mutex_unlock(&mutex) != 0) { 423 ALOGE("%d :: Core: Error in Mutex unlock\n",__LINE__); 424 return OMX_ErrorUndefined; 425 } 426 427 return OMX_ErrorNone; 428 } 429 430 /************************************************************************* 431 * OMX_SetupTunnel() 432 * 433 * Description: Setup the specified tunnel the two components 434 * 435 * Parameters: 436 * @param[in] hOutput Handle of the component to be accessed 437 * @param[in] nPortOutput Source port used in the tunnel 438 * @param[in] hInput Component to setup the tunnel with. 439 * @param[in] nPortInput Destination port used in the tunnel 440 * 441 * Returns: OMX_NOERROR Successful 442 * 443 * Note 444 * 445 **************************************************************************/ 446 /* OMX_SetupTunnel */ 447 OMX_API OMX_ERRORTYPE OMX_APIENTRY TIOMX_SetupTunnel( 448 OMX_IN OMX_HANDLETYPE hOutput, 449 OMX_IN OMX_U32 nPortOutput, 450 OMX_IN OMX_HANDLETYPE hInput, 451 OMX_IN OMX_U32 nPortInput) 452 { 453 OMX_ERRORTYPE eError = OMX_ErrorNotImplemented; 454 OMX_COMPONENTTYPE *pCompIn, *pCompOut; 455 OMX_TUNNELSETUPTYPE oTunnelSetup; 456 457 if (hOutput == NULL && hInput == NULL) 458 return OMX_ErrorBadParameter; 459 460 oTunnelSetup.nTunnelFlags = 0; 461 oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified; 462 463 pCompOut = (OMX_COMPONENTTYPE*)hOutput; 464 465 if (hOutput) 466 { 467 eError = pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, &oTunnelSetup); 468 } 469 470 471 if (eError == OMX_ErrorNone && hInput) 472 { 473 pCompIn = (OMX_COMPONENTTYPE*)hInput; 474 eError = pCompIn->ComponentTunnelRequest(hInput, nPortInput, hOutput, nPortOutput, &oTunnelSetup); 475 if (eError != OMX_ErrorNone && hOutput) 476 { 477 /* cancel tunnel request on output port since input port failed */ 478 pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, 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 **************************************************************************/ 500 OMX_API OMX_ERRORTYPE OMX_APIENTRY TIOMX_ComponentNameEnum( 501 OMX_OUT OMX_STRING cComponentName, 502 OMX_IN OMX_U32 nNameLength, 503 OMX_IN OMX_U32 nIndex) 504 { 505 OMX_ERRORTYPE eError = OMX_ErrorNone; 506 507 if (nIndex >= tableCount) 508 { 509 eError = OMX_ErrorNoMore; 510 } 511 else 512 { 513 strcpy(cComponentName, componentTable[nIndex].name); 514 } 515 516 return eError; 517 } 518 519 520 /************************************************************************* 521 * OMX_GetRolesOfComponent() 522 * 523 * Description: This method will query the component for its supported roles 524 * 525 *Parameters: 526 * @param[in] cComponentName The name of the component to query 527 * @param[in] pNumRoles The number of roles supported by the component 528 * @param[in] roles The roles of the component 529 * 530 * Returns: OMX_NOERROR Successful 531 * OMX_ErrorBadParameter Faliure due to a bad input parameter 532 * 533 * Note 534 * 535 **************************************************************************/ 536 OMX_API OMX_ERRORTYPE TIOMX_GetRolesOfComponent ( 537 OMX_IN OMX_STRING cComponentName, 538 OMX_INOUT OMX_U32 *pNumRoles, 539 OMX_OUT OMX_U8 **roles) 540 { 541 542 OMX_ERRORTYPE eError = OMX_ErrorNone; 543 OMX_U32 i = 0; 544 OMX_U32 j = 0; 545 OMX_BOOL bFound = OMX_FALSE; 546 547 if (cComponentName == NULL || pNumRoles == NULL) 548 { 549 if (cComponentName == NULL) 550 { 551 ALOGE("cComponentName is NULL\n"); 552 } 553 if (pNumRoles == NULL) 554 { 555 ALOGE("pNumRoles is NULL\n"); 556 } 557 eError = OMX_ErrorBadParameter; 558 goto EXIT; 559 } 560 while (i < tableCount) 561 { 562 if (strcmp(cComponentName, componentTable[i].name) == 0) 563 { 564 bFound = OMX_TRUE; 565 break; 566 } 567 i++; 568 } 569 if (!bFound) 570 { 571 eError = OMX_ErrorComponentNotFound; 572 ALOGE("component %s not found\n", cComponentName); 573 goto EXIT; 574 } 575 if (roles == NULL) 576 { 577 *pNumRoles = componentTable[i].nRoles; 578 } 579 else 580 { 581 /* must be second of two calls, 582 pNumRoles is input in this context. 583 If pNumRoles is < actual number of roles 584 than we return an error */ 585 if (*pNumRoles >= componentTable[i].nRoles) 586 { 587 for (j = 0; j<componentTable[i].nRoles; j++) 588 { 589 strcpy((OMX_STRING)roles[j], componentTable[i].pRoleArray[j]); 590 } 591 *pNumRoles = componentTable[i].nRoles; 592 } 593 else 594 { 595 eError = OMX_ErrorBadParameter; 596 ALOGE("pNumRoles (%d) is less than actual number (%d) of roles \ 597 for this component %s\n", *pNumRoles, componentTable[i].nRoles, cComponentName); 598 } 599 } 600 EXIT: 601 return eError; 602 } 603 604 /************************************************************************* 605 * OMX_GetComponentsOfRole() 606 * 607 * Description: This method will query the component for its supported roles 608 * 609 *Parameters: 610 * @param[in] role The role name to query for 611 * @param[in] pNumComps The number of components supporting the given role 612 * @param[in] compNames The names of the components supporting the given role 613 * 614 * Returns: OMX_NOERROR Successful 615 * 616 * Note 617 * 618 **************************************************************************/ 619 OMX_API OMX_ERRORTYPE TIOMX_GetComponentsOfRole ( 620 OMX_IN OMX_STRING role, 621 OMX_INOUT OMX_U32 *pNumComps, 622 OMX_INOUT OMX_U8 **compNames) 623 { 624 OMX_ERRORTYPE eError = OMX_ErrorNone; 625 OMX_U32 i = 0; 626 OMX_U32 j = 0; 627 OMX_U32 k = 0; 628 OMX_U32 compOfRoleCount = 0; 629 630 if (role == NULL || pNumComps == NULL) 631 { 632 if (role == NULL) 633 { 634 ALOGE("role is NULL"); 635 } 636 if (pNumComps == NULL) 637 { 638 ALOGE("pNumComps is NULL\n"); 639 } 640 eError = OMX_ErrorBadParameter; 641 goto EXIT; 642 } 643 644 /* This implies that the componentTable is not filled */ 645 if (!tableCount) 646 { 647 eError = OMX_ErrorUndefined; 648 ALOGE("Component table is empty. Please reload OMX Core\n"); 649 goto EXIT; 650 } 651 652 /* no matter, we always want to know number of matching components 653 so this will always run */ 654 for (i = 0; i < tableCount; i++) 655 { 656 for (j = 0; j < componentTable[i].nRoles; j++) 657 { 658 if (strcmp(componentTable[i].pRoleArray[j], role) == 0) 659 { 660 /* the first call to this function should only count the number 661 of roles 662 */ 663 compOfRoleCount++; 664 } 665 } 666 } 667 if (compOfRoleCount == 0) 668 { 669 eError = OMX_ErrorComponentNotFound; 670 ALOGE("Component supporting role %s was not found\n", role); 671 } 672 if (compNames == NULL) 673 { 674 /* must be the first of two calls */ 675 *pNumComps = compOfRoleCount; 676 } 677 else 678 { 679 /* must be the second of two calls */ 680 if (*pNumComps < compOfRoleCount) 681 { 682 /* pNumComps is input in this context, 683 it can not be less, this would indicate 684 the array is not large enough 685 */ 686 eError = OMX_ErrorBadParameter; 687 ALOGE("pNumComps (%d) is less than the actual number (%d) of components \ 688 supporting role %s\n", *pNumComps, compOfRoleCount, role); 689 } 690 else 691 { 692 k = 0; 693 for (i = 0; i < tableCount; i++) 694 { 695 for (j = 0; j < componentTable[i].nRoles; j++) 696 { 697 if (strcmp(componentTable[i].pRoleArray[j], role) == 0) 698 { 699 /* the second call compNames can be allocated 700 with the proper size for that number of roles. 701 */ 702 compNames[k] = (OMX_U8*)componentTable[i].name; 703 k++; 704 if (k == compOfRoleCount) 705 { 706 /* there are no more components of this role 707 so we can exit here */ 708 *pNumComps = k; 709 goto EXIT; 710 } 711 } 712 } 713 } 714 } 715 } 716 717 EXIT: 718 return eError; 719 } 720 721 722 OMX_ERRORTYPE TIOMX_BuildComponentTable() 723 { 724 OMX_ERRORTYPE eError = OMX_ErrorNone; 725 OMX_CALLBACKTYPE sCallbacks; 726 int j = 0; 727 int numFiles = 0; 728 int i; 729 730 for (i = 0, numFiles = 0; i < MAXCOMP; i ++) { 731 if (tComponentName[i][0] == NULL) { 732 break; 733 } 734 if (numFiles <= MAX_TABLE_SIZE){ 735 for (j = 0; j < numFiles; j ++) { 736 if (!strcmp(componentTable[j].name, tComponentName[i][0])) { 737 /* insert the role */ 738 if (tComponentName[i][1] != NULL) 739 { 740 componentTable[j].pRoleArray[componentTable[j].nRoles] = tComponentName[i][1]; 741 componentTable[j].pHandle[componentTable[j].nRoles] = NULL; //initilize the pHandle element 742 componentTable[j].nRoles ++; 743 } 744 break; 745 } 746 } 747 if (j == numFiles) { /* new component */ 748 if (tComponentName[i][1] != NULL){ 749 componentTable[numFiles].pRoleArray[0] = tComponentName[i][1]; 750 componentTable[numFiles].nRoles = 1; 751 } 752 strcpy(compName[numFiles], tComponentName[i][0]); 753 componentTable[numFiles].name = compName[numFiles]; 754 componentTable[numFiles].refCount = 0; //initialize reference counter. 755 numFiles ++; 756 } 757 } 758 } 759 tableCount = numFiles; 760 if (eError != OMX_ErrorNone){ 761 ALOGE("Could not build Component Table\n"); 762 } 763 764 return eError; 765 } 766 767 OMX_BOOL TIOMXConfigParserRedirect( 768 OMX_PTR aInputParameters, 769 OMX_PTR aOutputParameters) 770 771 { 772 OMX_BOOL Status = OMX_FALSE; 773 #ifndef NO_OPENCORE 774 Status = TIOMXConfigParser(aInputParameters, aOutputParameters); 775 #endif 776 return Status; 777 } 778