1/*-------------------------------------------------------------------------- 2Copyright (c) 2009, Code Aurora Forum. All rights reserved. 3 4Redistribution and use in source and binary forms, with or without 5modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the name of Code Aurora nor 12 the names of its contributors may be used to endorse or promote 13 products derived from this software without specific prior written 14 permission. 15 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27--------------------------------------------------------------------------*/ 28/*============================================================================ 29 O p e n M A X w r a p p e r s 30 O p e n M A X C o r e 31 32 This module contains the implementation of the OpenMAX core. 33 34*//*========================================================================*/ 35 36////////////////////////////////////////////////////////////////////////////// 37// Include Files 38////////////////////////////////////////////////////////////////////////////// 39 40#include <dlfcn.h> // dynamic library 41#include <sys/types.h> 42#include <sys/stat.h> 43#include <unistd.h> 44#include <string.h> 45#include <stdio.h> 46#include <pthread.h> 47 48#include "qc_omx_core.h" 49#include "omx_core_cmp.h" 50 51extern omx_core_cb_type core[]; 52extern const unsigned int SIZE_OF_CORE; 53static pthread_mutex_t lock_core = PTHREAD_MUTEX_INITIALIZER; 54 55/* ====================================================================== 56FUNCTION 57 omx_core_load_cmp_library 58 59DESCRIPTION 60 Loads up the libary name mentioned in the argument 61 62PARAMETERS 63 None 64 65RETURN VALUE 66 Constructor for creating component instances. 67========================================================================== */ 68static create_qc_omx_component 69omx_core_load_cmp_library(char *libname, void **handle_ptr) 70{ 71 create_qc_omx_component fn_ptr = NULL; 72 if(handle_ptr) 73 { 74 DEBUG_PRINT("Dynamically Loading the library : %s\n",libname); 75 *handle_ptr = dlopen(libname,RTLD_NOW); 76 if(*handle_ptr) 77 { 78 fn_ptr = dlsym(*handle_ptr, "get_omx_component_factory_fn"); 79 80 if(fn_ptr == NULL) 81 { 82 DEBUG_PRINT("Error: Library %s incompatible as QCOM OMX component loader - %s\n", 83 libname, dlerror()); 84 *handle_ptr = NULL; 85 } 86 } 87 else 88 { 89 DEBUG_PRINT("Error: Couldn't load %s: %s\n",libname,dlerror()); 90 } 91 } 92 return fn_ptr; 93} 94 95/* ====================================================================== 96FUNCTION 97 OMX_Init 98 99DESCRIPTION 100 This is the first function called by the application. 101 There is nothing to do here since components shall be loaded 102 whenever the get handle method is called. 103 104PARAMETERS 105 None 106 107RETURN VALUE 108 None. 109========================================================================== */ 110OMX_API OMX_ERRORTYPE OMX_APIENTRY 111OMX_Init() 112{ 113 DEBUG_PRINT("OMXCORE API - OMX_Init \n"); 114 /* Nothing to do here ; shared objects shall be loaded at the get handle method */ 115 return OMX_ErrorNone; 116} 117 118/* ====================================================================== 119FUNCTION 120 get_cmp_index 121 122DESCRIPTION 123 Obtains the index associated with the name. 124 125PARAMETERS 126 None 127 128RETURN VALUE 129 Error None. 130========================================================================== */ 131static int get_cmp_index(char *cmp_name) 132{ 133 int rc = -1,i=0; 134 DEBUG_PRINT("before get_cmp_index **********%d\n", rc); 135 136 for(i=0; i< (int)SIZE_OF_CORE; i++) 137 { 138 DEBUG_PRINT("get_cmp_index: cmp_name = %s , core[i].name = %s ,count = %d \n",cmp_name,core[i].name,i); 139 140 if(!strcmp(cmp_name, core[i].name)) 141 { 142 rc = i; 143 break; 144 } 145 } 146 DEBUG_PRINT("returning index %d\n", rc); 147 return rc; 148} 149 150/* ====================================================================== 151FUNCTION 152 clear_cmp_handle 153 154DESCRIPTION 155 Clears the component handle from the component table. 156 157PARAMETERS 158 None 159 160RETURN VALUE 161 None. 162========================================================================== */ 163static void clear_cmp_handle(OMX_HANDLETYPE inst) 164{ 165 unsigned i = 0,j=0; 166 167 if(NULL == inst) 168 return; 169 170 for(i=0; i< SIZE_OF_CORE; i++) 171 { 172 for(j=0; j< OMX_COMP_MAX_INST; j++) 173 { 174 if(inst == core[i].inst[j]) 175 { 176 core[i].inst[j] = NULL; 177 return; 178 } 179 } 180 } 181 return; 182} 183/* ====================================================================== 184FUNCTION 185 is_cmp_handle_exists 186 187DESCRIPTION 188 Check if the component handle already exists or not. 189 190PARAMETERS 191 None 192 193RETURN VALUE 194 index pointer if the handle exists 195 negative value otherwise 196========================================================================== */ 197static int is_cmp_handle_exists(OMX_HANDLETYPE inst) 198{ 199 unsigned i=0,j=0; 200 int rc = -1; 201 202 if(NULL == inst) 203 return rc; 204 205 pthread_mutex_lock(&lock_core); 206 for(i=0; i< SIZE_OF_CORE; i++) 207 { 208 for(j=0; j< OMX_COMP_MAX_INST; j++) 209 { 210 if(inst == core[i].inst[j]) 211 { 212 rc = i; 213 goto finish; 214 } 215 } 216 } 217finish: 218 pthread_mutex_unlock(&lock_core); 219 return rc; 220} 221 222/* ====================================================================== 223FUNCTION 224 get_comp_handle_index 225 226DESCRIPTION 227 Gets the index to store the next handle for specified component name. 228 229PARAMETERS 230 cmp_name : Component Name 231 232RETURN VALUE 233 Index of next handle to be stored 234========================================================================== */ 235static int get_comp_handle_index(char *cmp_name) 236{ 237 unsigned i=0,j=0; 238 int rc = -1; 239 for(i=0; i< SIZE_OF_CORE; i++) 240 { 241 if(!strcmp(cmp_name, core[i].name)) 242 { 243 for(j=0; j< OMX_COMP_MAX_INST; j++) 244 { 245 if(NULL == core[i].inst[j]) 246 { 247 rc = j; 248 DEBUG_PRINT("free handle slot exists %d\n", rc); 249 return rc; 250 } 251 } 252 break; 253 } 254 } 255 return rc; 256} 257 258/* ====================================================================== 259FUNCTION 260 check_lib_unload 261 262DESCRIPTION 263 Check if any component instance is using the library 264 265PARAMETERS 266 index: Component Index in core array. 267 268RETURN VALUE 269 1: Library Unused and can be unloaded. 270 0: Library used and shouldnt be unloaded. 271========================================================================== */ 272static int check_lib_unload(int index) 273{ 274 unsigned i=0; 275 int rc = 1; 276 277 for(i=0; i< OMX_COMP_MAX_INST; i++) 278 { 279 if(core[index].inst[i]) 280 { 281 rc = 0; 282 DEBUG_PRINT("Library Used \n"); 283 break; 284 } 285 } 286 return rc; 287} 288/* ====================================================================== 289FUNCTION 290 is_cmp_already_exists 291 292DESCRIPTION 293 Check if the component already exists or not. Used in the 294 management of component handles. 295 296PARAMETERS 297 None 298 299RETURN VALUE 300 Error None. 301========================================================================== */ 302static int is_cmp_already_exists(char *cmp_name) 303{ 304 unsigned i =0,j=0; 305 int rc = -1; 306 for(i=0; i< SIZE_OF_CORE; i++) 307 { 308 if(!strcmp(cmp_name, core[i].name)) 309 { 310 for(j=0; j< OMX_COMP_MAX_INST; j++) 311 { 312 if(core[i].inst[j]) 313 { 314 rc = i; 315 DEBUG_PRINT("Component exists %d\n", rc); 316 return rc; 317 } 318 } 319 break; 320 } 321 } 322 return rc; 323} 324 325/* ====================================================================== 326FUNCTION 327 get_cmp_handle 328 329DESCRIPTION 330 Get component handle. 331 332PARAMETERS 333 None 334 335RETURN VALUE 336 Error None. 337========================================================================== */ 338void* get_cmp_handle(char *cmp_name) 339{ 340 unsigned i =0,j=0; 341 342 DEBUG_PRINT("get_cmp_handle \n"); 343 for(i=0; i< SIZE_OF_CORE; i++) 344 { 345 if(!strcmp(cmp_name, core[i].name)) 346 { 347 for(j=0; j< OMX_COMP_MAX_INST; j++) 348 { 349 if(core[i].inst[j]) 350 { 351 DEBUG_PRINT("get_cmp_handle match\n"); 352 return core[i].inst[j]; 353 } 354 } 355 } 356 } 357 DEBUG_PRINT("get_cmp_handle returning NULL \n"); 358 return NULL; 359} 360 361/* ====================================================================== 362FUNCTION 363 OMX_DeInit 364 365DESCRIPTION 366 DeInitialize all the the relevant OMX components. 367 368PARAMETERS 369 None 370 371RETURN VALUE 372 Error None. 373========================================================================== */ 374OMX_API OMX_ERRORTYPE OMX_APIENTRY 375OMX_Deinit() 376{ 377 return OMX_ErrorNone; 378} 379 380/* ====================================================================== 381FUNCTION 382 OMX_GetHandle 383 384DESCRIPTION 385 Constructs requested component. Relevant library is loaded if needed. 386 387PARAMETERS 388 None 389 390RETURN VALUE 391 Error None if everything goes fine. 392========================================================================== */ 393 394 OMX_API OMX_ERRORTYPE OMX_APIENTRY 395OMX_GetHandle(OMX_OUT OMX_HANDLETYPE* handle, 396 OMX_IN OMX_STRING componentName, 397 OMX_IN OMX_PTR appData, 398 OMX_IN OMX_CALLBACKTYPE* callBacks) 399{ 400 OMX_ERRORTYPE eRet = OMX_ErrorNone; 401 int cmp_index = -1; 402 int hnd_index = -1; 403 404 DEBUG_PRINT("OMXCORE API : Get Handle %x %s %x\n",(unsigned) handle, 405 componentName, 406 (unsigned) appData); 407 pthread_mutex_lock(&lock_core); 408 if(handle) 409 { 410 struct stat sd; 411 412 *handle = NULL; 413 414 cmp_index = get_cmp_index(componentName); 415 416 if(cmp_index >= 0) 417 { 418 DEBUG_PRINT("getting fn pointer\n"); 419 420 // dynamically load the so 421 core[cmp_index].fn_ptr = 422 omx_core_load_cmp_library(core[cmp_index].so_lib_name, 423 &core[cmp_index].so_lib_handle); 424 425 if(core[cmp_index].fn_ptr) 426 { 427 // Construct the component requested 428 // Function returns the opaque handle 429 void* pThis = (*(core[cmp_index].fn_ptr))(); 430 if(pThis) 431 { 432 void *hComp = NULL; 433 hComp = qc_omx_create_component_wrapper((OMX_PTR)pThis); 434 if((eRet = qc_omx_component_init(hComp, core[cmp_index].name)) != 435 OMX_ErrorNone) 436 { 437 DEBUG_PRINT("Component not created succesfully\n"); 438 pthread_mutex_unlock(&lock_core); 439 return eRet; 440 441 } 442 qc_omx_component_set_callbacks(hComp,callBacks,appData); 443 hnd_index = get_comp_handle_index(componentName); 444 if(hnd_index >= 0) 445 { 446 core[cmp_index].inst[hnd_index]= *handle = (OMX_HANDLETYPE) hComp; 447 } 448 else 449 { 450 DEBUG_PRINT("OMX_GetHandle:NO free slot available to store Component Handle\n"); 451 pthread_mutex_unlock(&lock_core); 452 return OMX_ErrorInsufficientResources; 453 } 454 DEBUG_PRINT("Component %x Successfully created\n",(unsigned)*handle); 455 } 456 else 457 { 458 eRet = OMX_ErrorInsufficientResources; 459 DEBUG_PRINT("Component Creation failed\n"); 460 } 461 } 462 else 463 { 464 eRet = OMX_ErrorNotImplemented; 465 DEBUG_PRINT("library couldnt return create instance fn\n"); 466 } 467 468 } 469 else 470 { 471 eRet = OMX_ErrorNotImplemented; 472 DEBUG_PRINT("ERROR: Already another instance active ;rejecting \n"); 473 } 474 } 475 else 476 { 477 eRet = OMX_ErrorBadParameter; 478 DEBUG_PRINT("\n OMX_GetHandle: NULL handle \n"); 479 } 480 pthread_mutex_unlock(&lock_core); 481 return eRet; 482} 483/* ====================================================================== 484FUNCTION 485 OMX_FreeHandle 486 487DESCRIPTION 488 Destructs the component handles. 489 490PARAMETERS 491 None 492 493RETURN VALUE 494 Error None. 495========================================================================== */ 496OMX_API OMX_ERRORTYPE OMX_APIENTRY 497OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp) 498{ 499 OMX_ERRORTYPE eRet = OMX_ErrorNone; 500 int err = 0, i = 0; 501 DEBUG_PRINT("OMXCORE API : Free Handle %x\n",(unsigned) hComp); 502 503 // 0. Check that we have an active instance 504 if((i=is_cmp_handle_exists(hComp)) >=0) 505 { 506 // 1. Delete the component 507 if ((eRet = qc_omx_component_deinit(hComp)) == OMX_ErrorNone) 508 { 509 pthread_mutex_lock(&lock_core); 510 /* Unload component library */ 511 if( (i < SIZE_OF_CORE) && core[i].so_lib_handle) 512 { 513 if(check_lib_unload(i)) 514 { 515 DEBUG_PRINT_ERROR(" Unloading the dynamic library for %s\n", 516 core[i].name); 517 err = dlclose(core[i].so_lib_handle); 518 if(err) 519 { 520 DEBUG_PRINT_ERROR("Error %d in dlclose of lib %s\n", 521 err,core[i].name); 522 } 523 core[i].so_lib_handle = NULL; 524 } 525 } 526 clear_cmp_handle(hComp); 527 pthread_mutex_unlock(&lock_core); 528 } 529 else 530 { 531 DEBUG_PRINT(" OMX_FreeHandle failed on %x\n",(unsigned) hComp); 532 return eRet; 533 } 534 } 535 else 536 { 537 DEBUG_PRINT_ERROR("OMXCORE Warning: Free Handle called with no active instances\n"); 538 } 539 return OMX_ErrorNone; 540} 541/* ====================================================================== 542FUNCTION 543 OMX_SetupTunnel 544 545DESCRIPTION 546 Not Implemented. 547 548PARAMETERS 549 None 550 551RETURN VALUE 552 None. 553========================================================================== */ 554OMX_API OMX_ERRORTYPE OMX_APIENTRY 555OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent, 556 OMX_IN OMX_U32 outputPort, 557 OMX_IN OMX_HANDLETYPE inputComponent, 558 OMX_IN OMX_U32 inputPort) 559{ 560 /* Not supported right now */ 561 DEBUG_PRINT("OMXCORE API: OMX_SetupTunnel Not implemented \n"); 562 return OMX_ErrorNotImplemented; 563} 564/* ====================================================================== 565FUNCTION 566 OMX_GetContentPipe 567 568DESCRIPTION 569 Not Implemented. 570 571PARAMETERS 572 None 573 574RETURN VALUE 575 None. 576========================================================================== */ 577OMX_API OMX_ERRORTYPE 578OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe, 579 OMX_IN OMX_STRING uri) 580{ 581 /* Not supported right now */ 582 DEBUG_PRINT("OMXCORE API: OMX_GetContentPipe Not implemented \n"); 583 return OMX_ErrorNotImplemented; 584} 585 586/* ====================================================================== 587FUNCTION 588 OMX_GetComponentNameEnum 589 590DESCRIPTION 591 Returns the component name associated with the index. 592 593PARAMETERS 594 None 595 596RETURN VALUE 597 None. 598========================================================================== */ 599OMX_API OMX_ERRORTYPE OMX_APIENTRY 600OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName, 601 OMX_IN OMX_U32 nameLen, 602 OMX_IN OMX_U32 index) 603{ 604 OMX_ERRORTYPE eRet = OMX_ErrorNone; 605 DEBUG_PRINT("OMXCORE API - OMX_ComponentNameEnum %x %d %d\n",(unsigned) componentName 606 ,(unsigned)nameLen 607 ,(unsigned)index); 608 if(index < SIZE_OF_CORE) 609 { 610 #ifdef _ANDROID_ 611 strlcpy(componentName, core[index].name,nameLen); 612 #else 613 strncpy(componentName, core[index].name,nameLen); 614 #endif 615 } 616 else 617 { 618 eRet = OMX_ErrorNoMore; 619 } 620 return eRet; 621} 622 623/* ====================================================================== 624FUNCTION 625 OMX_GetComponentsOfRole 626 627DESCRIPTION 628 Returns the component name which can fulfill the roles passed in the 629 argument. 630 631PARAMETERS 632 None 633 634RETURN VALUE 635 None. 636========================================================================== */ 637OMX_API OMX_ERRORTYPE 638OMX_GetComponentsOfRole(OMX_IN OMX_STRING role, 639 OMX_INOUT OMX_U32* numComps, 640 OMX_INOUT OMX_U8** compNames) 641{ 642 OMX_ERRORTYPE eRet = OMX_ErrorNone; 643 unsigned i,j,namecount=0; 644 645 printf(" Inside OMX_GetComponentsOfRole \n"); 646 647 /*If CompNames is NULL then return*/ 648 if (compNames == NULL) 649 { 650 if (numComps == NULL) 651 { 652 eRet = OMX_ErrorBadParameter; 653 } 654 else 655 { 656 *numComps = 0; 657 for (i=0; i<SIZE_OF_CORE;i++) 658 { 659 for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++) 660 { 661 if(!strcmp(role,core[i].roles[j])) 662 { 663 (*numComps)++; 664 } 665 } 666 } 667 } 668 return eRet; 669 } 670 671 if(numComps) 672 { 673 namecount = *numComps; 674 675 if (namecount == 0) 676 { 677 return OMX_ErrorBadParameter; 678 } 679 680 *numComps = 0; 681 682 for (i=0; i<SIZE_OF_CORE;i++) 683 { 684 for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++) 685 { 686 if(!strcmp(role,core[i].roles[j])) 687 { 688 #ifdef _ANDROID_ 689 strlcpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE); 690 #else 691 strncpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE); 692 #endif 693 (*numComps)++; 694 break; 695 } 696 } 697 if (*numComps == namecount) 698 { 699 break; 700 } 701 } 702 } 703 else 704 { 705 eRet = OMX_ErrorBadParameter; 706 } 707 708 printf(" Leaving OMX_GetComponentsOfRole \n"); 709 return eRet; 710} 711/* ====================================================================== 712FUNCTION 713 OMX_GetRolesOfComponent 714 715DESCRIPTION 716 Returns the primary role of the components supported. 717 718PARAMETERS 719 None 720 721RETURN VALUE 722 None. 723========================================================================== */ 724OMX_API OMX_ERRORTYPE 725OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName, 726 OMX_INOUT OMX_U32* numRoles, 727 OMX_OUT OMX_U8** roles) 728{ 729 /* Not supported right now */ 730 OMX_ERRORTYPE eRet = OMX_ErrorNone; 731 unsigned i,j,numofroles = 0;; 732 DEBUG_PRINT("GetRolesOfComponent %s\n",compName); 733 734 if (roles == NULL) 735 { 736 if (numRoles == NULL) 737 { 738 eRet = OMX_ErrorBadParameter; 739 } 740 else 741 { 742 *numRoles = 0; 743 for(i=0; i< SIZE_OF_CORE; i++) 744 { 745 if(!strcmp(compName,core[i].name)) 746 { 747 for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++) 748 { 749 (*numRoles)++; 750 } 751 break; 752 } 753 } 754 755 } 756 return eRet; 757 } 758 759 if(numRoles) 760 { 761 if (*numRoles == 0) 762 { 763 return OMX_ErrorBadParameter; 764 } 765 766 numofroles = *numRoles; 767 *numRoles = 0; 768 for(i=0; i< SIZE_OF_CORE; i++) 769 { 770 if(!strcmp(compName,core[i].name)) 771 { 772 for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++) 773 { 774 if(roles && roles[*numRoles]) 775 { 776 #ifdef _ANDROID_ 777 strlcpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE); 778 #else 779 strncpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE); 780 #endif 781 } 782 (*numRoles)++; 783 if (numofroles == *numRoles) 784 { 785 break; 786 } 787 } 788 break; 789 } 790 } 791 } 792 else 793 { 794 DEBUG_PRINT("ERROR: Both Roles and numRoles Invalid\n"); 795 eRet = OMX_ErrorBadParameter; 796 } 797 return eRet; 798} 799 800OMX_API OMX_BOOL 801OMXConfigParser( 802 OMX_PTR aInputParameters, 803 OMX_PTR aOutputParameters) 804{ 805 OMX_BOOL Status = OMX_TRUE; 806 VideoOMXConfigParserOutputs *aOmxOutputParameters; 807 OMXConfigParserInputs *aOmxInputParameters; 808 aOmxOutputParameters = (VideoOMXConfigParserOutputs *)aOutputParameters; 809 aOmxInputParameters = (OMXConfigParserInputs *)aInputParameters; 810 811 aOmxOutputParameters->width = 176; //setting width to QCIF 812 aOmxOutputParameters->height = 144; //setting height to QCIF 813 814 //TODO 815 //Qcom component do not use the level/profile from IL client .They are parsing the first buffer 816 //sent in ETB so for now setting the defalut values . Going farward we can call 817 //QC parser here. 818 if (0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.avc")) 819 { 820 aOmxOutputParameters->profile = 66; //minimum supported h264 profile - setting to baseline profile 821 aOmxOutputParameters->level = 0; // minimum supported h264 level 822 } 823 else if ((0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.mpeg4")) || (0 == strcmp(aOmxInputParameters ->cComponentRole, (OMX_STRING)"video_decoder.h263"))) 824 { 825 aOmxOutputParameters->profile = 8; //minimum supported h263/mpeg4 profile 826 aOmxOutputParameters->level = 0; // minimum supported h263/mpeg4 level 827 } 828 829 return Status; 830} 831