1 /** 2 * 3 * File Name: armCOMM.c 4 * OpenMAX DL: v1.0.2 5 * Revision: 9641 6 * Date: Thursday, February 7, 2008 7 * 8 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. 9 * 10 * 11 * 12 * Defines Common APIs used across OpenMAX API's 13 */ 14 15 #include "omxtypes.h" 16 #include "armCOMM.h" 17 18 /***********************************************************************/ 19 /* Miscellaneous Arithmetic operations */ 20 21 /** 22 * Function: armRoundFloatToS16 23 * 24 * Description: 25 * Converts a double precision value into a short int after rounding 26 * 27 * Parameters: 28 * [in] Value Float value to be converted 29 * 30 * Return Value: 31 * [out] converted value in OMX_S16 format 32 * 33 */ 34 35 OMX_S16 armRoundFloatToS16 (OMX_F64 Value) 36 { 37 if (Value > 0) 38 { 39 return (OMX_S16)(Value + .5); 40 } 41 else 42 { 43 return (OMX_S16)(Value - .5); 44 } 45 } 46 47 /** 48 * Function: armRoundFloatToS32 49 * 50 * Description: 51 * Converts a double precision value into a int after rounding 52 * 53 * Parameters: 54 * [in] Value Float value to be converted 55 * 56 * Return Value: 57 * [out] converted value in OMX_S32 format 58 * 59 */ 60 61 OMX_S32 armRoundFloatToS32 (OMX_F64 Value) 62 { 63 if (Value > 0) 64 { 65 return (OMX_S32)(Value + .5); 66 } 67 else 68 { 69 return (OMX_S32)(Value - .5); 70 } 71 } 72 /** 73 * Function: armSatRoundFloatToS16 74 * 75 * Description: 76 * Converts a double precision value into a short int after rounding and saturation 77 * 78 * Parameters: 79 * [in] Value Float value to be converted 80 * 81 * Return Value: 82 * [out] converted value in OMX_S16 format 83 * 84 */ 85 86 OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value) 87 { 88 if (Value > 0) 89 { 90 Value += 0.5; 91 92 if(Value > (OMX_S16)OMX_MAX_S16 ) 93 { 94 return (OMX_S16)OMX_MAX_S16; 95 } 96 else 97 { 98 return (OMX_S16)Value; 99 } 100 } 101 else 102 { 103 Value -= 0.5; 104 105 if(Value < (OMX_S16)OMX_MIN_S16 ) 106 { 107 return (OMX_S16)OMX_MIN_S16; 108 } 109 else 110 { 111 return (OMX_S16)Value; 112 } 113 } 114 } 115 116 /** 117 * Function: armSatRoundFloatToS32 118 * 119 * Description: 120 * Converts a double precision value into a int after rounding and saturation 121 * 122 * Parameters: 123 * [in] Value Float value to be converted 124 * 125 * Return Value: 126 * [out] converted value in OMX_S32 format 127 * 128 */ 129 130 OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value) 131 { 132 if (Value > 0) 133 { 134 Value += 0.5; 135 136 if(Value > (OMX_S32)OMX_MAX_S32 ) 137 { 138 return (OMX_S32)OMX_MAX_S32; 139 } 140 else 141 { 142 return (OMX_S32)Value; 143 } 144 } 145 else 146 { 147 Value -= 0.5; 148 149 if(Value < (OMX_S32)OMX_MIN_S32 ) 150 { 151 return (OMX_S32)OMX_MIN_S32; 152 } 153 else 154 { 155 return (OMX_S32)Value; 156 } 157 } 158 } 159 160 /** 161 * Function: armSatRoundFloatToU16 162 * 163 * Description: 164 * Converts a double precision value into a unsigned short int after rounding and saturation 165 * 166 * Parameters: 167 * [in] Value Float value to be converted 168 * 169 * Return Value: 170 * [out] converted value in OMX_U16 format 171 * 172 */ 173 174 OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value) 175 { 176 Value += 0.5; 177 178 if(Value > (OMX_U16)OMX_MAX_U16 ) 179 { 180 return (OMX_U16)OMX_MAX_U16; 181 } 182 else 183 { 184 return (OMX_U16)Value; 185 } 186 } 187 188 /** 189 * Function: armSatRoundFloatToU32 190 * 191 * Description: 192 * Converts a double precision value into a unsigned int after rounding and saturation 193 * 194 * Parameters: 195 * [in] Value Float value to be converted 196 * 197 * Return Value: 198 * [out] converted value in OMX_U32 format 199 * 200 */ 201 202 OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value) 203 { 204 Value += 0.5; 205 206 if(Value > (OMX_U32)OMX_MAX_U32 ) 207 { 208 return (OMX_U32)OMX_MAX_U32; 209 } 210 else 211 { 212 return (OMX_U32)Value; 213 } 214 } 215 216 /** 217 * Function: armRoundFloatToS64 218 * 219 * Description: 220 * Converts a double precision value into a 64 bit int after rounding 221 * 222 * Parameters: 223 * [in] Value Float value to be converted 224 * 225 * Return Value: 226 * [out] converted value in OMX_S64 format 227 * 228 */ 229 230 OMX_S64 armRoundFloatToS64 (OMX_F64 Value) 231 { 232 if (Value > 0) 233 { 234 return (OMX_S64)(Value + .5); 235 } 236 else 237 { 238 return (OMX_S64)(Value - .5); 239 } 240 } 241 242 /** 243 * Function: armSignCheck 244 * 245 * Description: 246 * Checks the sign of a variable: 247 * returns 1 if it is Positive 248 * returns 0 if it is 0 249 * returns -1 if it is Negative 250 * 251 * Remarks: 252 * 253 * Parameters: 254 * [in] var Variable to be checked 255 * 256 * Return Value: 257 * OMX_INT -- returns 1 if it is Positive 258 * returns 0 if it is 0 259 * returns -1 if it is Negative 260 */ 261 262 OMX_INT armSignCheck ( 263 OMX_S16 var 264 ) 265 266 { 267 OMX_INT Sign; 268 269 if (var < 0) 270 { 271 Sign = -1; 272 } 273 else if ( var > 0) 274 { 275 Sign = 1; 276 } 277 else 278 { 279 Sign = 0; 280 } 281 282 return Sign; 283 } 284 285 /** 286 * Function: armClip 287 * 288 * Description: Clips the input between MAX and MIN value 289 * 290 * 291 * Remarks: 292 * 293 * Parameters: 294 * [in] Min lower bound 295 * [in] Max upper bound 296 * [in] src variable to the clipped 297 * 298 * Return Value: 299 * OMX_S32 -- returns clipped value 300 */ 301 302 OMX_S32 armClip ( 303 OMX_INT min, 304 OMX_INT max, 305 OMX_S32 src 306 ) 307 308 { 309 if (src > max) 310 { 311 src = max; 312 } 313 else if (src < min) 314 { 315 src = min; 316 } 317 318 return src; 319 } 320 321 /** 322 * Function: armClip_F32 323 * 324 * Description: Clips the input between MAX and MIN value 325 * 326 * 327 * Remarks: 328 * 329 * Parameters: 330 * [in] Min lower bound 331 * [in] Max upper bound 332 * [in] src variable to the clipped 333 * 334 * Return Value: 335 * OMX_F32 -- returns clipped value 336 */ 337 338 OMX_F32 armClip_F32 ( 339 OMX_F32 min, 340 OMX_F32 max, 341 OMX_F32 src 342 ) 343 344 { 345 if (src > max) 346 { 347 src = max; 348 } 349 else if (src < min) 350 { 351 src = min; 352 } 353 354 return src; 355 } 356 357 /** 358 * Function: armShiftSat_F32 359 * 360 * Description: Divides a float value by 2^shift and 361 * saturates it for unsigned value range for satBits. 362 * Second parameter is like "shifting" the corresponding 363 * integer value. Takes care of rounding while clipping the final 364 * value. 365 * 366 * Parameters: 367 * [in] v Number to be operated upon 368 * [in] shift Divides the input "v" by "2^shift" 369 * [in] satBits Final range is [0, 2^satBits) 370 * 371 * Return Value: 372 * OMX_S32 -- returns "shifted" saturated value 373 */ 374 375 OMX_U32 armShiftSat_F32(OMX_F32 v, OMX_INT shift, OMX_INT satBits) 376 { 377 OMX_U32 allOnes = (OMX_U32)(-1); 378 OMX_U32 maxV = allOnes >> (32-satBits); 379 OMX_F32 vShifted, vRounded, shiftDiv = (OMX_F32)(1 << shift); 380 OMX_U32 vInt; 381 OMX_U32 vIntSat; 382 383 if(v <= 0) 384 return 0; 385 386 vShifted = v / shiftDiv; 387 vRounded = (OMX_F32)(vShifted + 0.5); 388 vInt = (OMX_U32)vRounded; 389 vIntSat = vInt; 390 if(vIntSat > maxV) 391 vIntSat = maxV; 392 return vIntSat; 393 } 394 395 /** 396 * Functions: armSwapElem 397 * 398 * Description: 399 * These function swaps two elements at the specified pointer locations. 400 * The size of each element could be anything as specified by <elemSize> 401 * 402 * Return Value: 403 * OMXResult -- Error status from the function 404 */ 405 OMXResult armSwapElem( 406 OMX_U8 *pBuf1, 407 OMX_U8 *pBuf2, 408 OMX_INT elemSize 409 ) 410 { 411 OMX_INT i; 412 OMX_U8 temp; 413 armRetArgErrIf(!pBuf1 || !pBuf2, OMX_Sts_BadArgErr); 414 415 for(i = 0; i < elemSize; i++) 416 { 417 temp = *(pBuf1 + i); 418 *(pBuf1 + i) = *(pBuf2 + i); 419 *(pBuf2 + i) = temp; 420 } 421 return OMX_Sts_NoErr; 422 } 423 424 /** 425 * Function: armMedianOf3 426 * 427 * Description: Finds the median of three numbers 428 * 429 * Remarks: 430 * 431 * Parameters: 432 * [in] fEntry First entry 433 * [in] sEntry second entry 434 * [in] tEntry Third entry 435 * 436 * Return Value: 437 * OMX_S32 -- returns the median value 438 */ 439 440 OMX_S32 armMedianOf3 ( 441 OMX_S32 fEntry, 442 OMX_S32 sEntry, 443 OMX_S32 tEntry 444 ) 445 { 446 OMX_S32 a, b, c; 447 448 a = armMin (fEntry, sEntry); 449 b = armMax (fEntry, sEntry); 450 c = armMin (b, tEntry); 451 return (armMax (a, c)); 452 } 453 454 /** 455 * Function: armLogSize 456 * 457 * Description: Finds the size of a positive value and returns the same 458 * 459 * Remarks: 460 * 461 * Parameters: 462 * [in] value Positive value 463 * 464 * Return Value: 465 * OMX_U8 -- Returns the minimum number of bits required to represent the positive value. 466 This is the smallest k>=0 such that that value is less than (1<<k). 467 */ 468 469 OMX_U8 armLogSize ( 470 OMX_U16 value 471 ) 472 { 473 OMX_U8 i; 474 for ( i = 0; value > 0; value = value >> 1) 475 { 476 i++; 477 } 478 return i; 479 } 480 481 /***********************************************************************/ 482 /* Saturating Arithmetic operations */ 483 484 /** 485 * Function :armSatAdd_S32() 486 * 487 * Description : 488 * Returns the result of saturated addition of the two inputs Value1, Value2 489 * 490 * Parametrs: 491 * [in] Value1 First Operand 492 * [in] Value2 Second Operand 493 * 494 * Return: 495 * [out] Result of operation 496 * 497 * 498 **/ 499 500 OMX_S32 armSatAdd_S32(OMX_S32 Value1,OMX_S32 Value2) 501 { 502 OMX_S32 Result; 503 504 Result = Value1 + Value2; 505 506 if( (Value1^Value2) >= 0) 507 { 508 /*Same sign*/ 509 if( (Result^Value1) >= 0) 510 { 511 /*Result has not saturated*/ 512 return Result; 513 } 514 else 515 { 516 if(Value1 >= 0) 517 { 518 /*Result has saturated in positive side*/ 519 return OMX_MAX_S32; 520 } 521 else 522 { 523 /*Result has saturated in negative side*/ 524 return OMX_MIN_S32; 525 } 526 527 } 528 529 } 530 else 531 { 532 return Result; 533 } 534 535 } 536 537 /** 538 * Function :armSatAdd_S64() 539 * 540 * Description : 541 * Returns the result of saturated addition of the two inputs Value1, Value2 542 * 543 * Parametrs: 544 * [in] Value1 First Operand 545 * [in] Value2 Second Operand 546 * 547 * Return: 548 * [out] Result of operation 549 * 550 * 551 **/ 552 553 OMX_S64 armSatAdd_S64(OMX_S64 Value1,OMX_S64 Value2) 554 { 555 OMX_S64 Result; 556 557 Result = Value1 + Value2; 558 559 if( (Value1^Value2) >= 0) 560 { 561 /*Same sign*/ 562 if( (Result^Value1) >= 0) 563 { 564 /*Result has not saturated*/ 565 return Result; 566 } 567 else 568 { 569 if(Value1 >= 0) 570 { 571 /*Result has saturated in positive side*/ 572 Result = OMX_MAX_S64; 573 return Result; 574 } 575 else 576 { 577 /*Result has saturated in negative side*/ 578 return OMX_MIN_S64; 579 } 580 581 } 582 583 } 584 else 585 { 586 return Result; 587 } 588 589 } 590 591 /** Function :armSatSub_S32() 592 * 593 * Description : 594 * Returns the result of saturated substraction of the two inputs Value1, Value2 595 * 596 * Parametrs: 597 * [in] Value1 First Operand 598 * [in] Value2 Second Operand 599 * 600 * Return: 601 * [out] Result of operation 602 * 603 **/ 604 605 OMX_S32 armSatSub_S32(OMX_S32 Value1,OMX_S32 Value2) 606 { 607 OMX_S32 Result; 608 609 Result = Value1 - Value2; 610 611 if( (Value1^Value2) < 0) 612 { 613 /*Opposite sign*/ 614 if( (Result^Value1) >= 0) 615 { 616 /*Result has not saturated*/ 617 return Result; 618 } 619 else 620 { 621 if(Value1 >= 0) 622 { 623 /*Result has saturated in positive side*/ 624 return OMX_MAX_S32; 625 } 626 else 627 { 628 /*Result has saturated in negative side*/ 629 return OMX_MIN_S32; 630 } 631 632 } 633 634 } 635 else 636 { 637 return Result; 638 } 639 640 } 641 642 /** 643 * Function :armSatMac_S32() 644 * 645 * Description : 646 * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated 647 * accumulation with Mac 648 * 649 * Parametrs: 650 * [in] Value1 First Operand 651 * [in] Value2 Second Operand 652 * [in] Mac Accumulator 653 * 654 * Return: 655 * [out] Result of operation 656 **/ 657 658 OMX_S32 armSatMac_S32(OMX_S32 Mac,OMX_S16 Value1,OMX_S16 Value2) 659 { 660 OMX_S32 Result; 661 662 Result = (OMX_S32)(Value1*Value2); 663 Result = armSatAdd_S32( Mac , Result ); 664 665 return Result; 666 } 667 668 /** 669 * Function :armSatMac_S16S32_S32 670 * 671 * Description : 672 * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac 673 * 674 * mac = mac + Saturate_in_32Bits(delayElem * filTap) 675 * 676 * Parametrs: 677 * [in] delayElem First 32 bit Operand 678 * [in] filTap Second 16 bit Operand 679 * [in] mac Result of MAC operation 680 * 681 * Return: 682 * [out] mac Result of operation 683 * 684 **/ 685 686 OMX_S32 armSatMac_S16S32_S32(OMX_S32 mac, OMX_S32 delayElem, OMX_S16 filTap ) 687 { 688 689 OMX_S32 result; 690 691 result = armSatMulS16S32_S32(filTap,delayElem); 692 693 if ( result > OMX_MAX_S16 ) 694 { 695 result = OMX_MAX_S32; 696 } 697 else if( result < OMX_MIN_S16 ) 698 { 699 result = OMX_MIN_S32; 700 } 701 else 702 { 703 result = delayElem * filTap; 704 } 705 706 mac = armSatAdd_S32(mac,result); 707 708 return mac; 709 } 710 711 712 /** 713 * Function :armSatRoundRightShift_S32_S16 714 * 715 * Description : 716 * Returns the result of rounded right shift operation of input by the scalefactor 717 * 718 * output = Saturate_in_16Bits( ( Right/LeftShift( (Round(input) , shift ) ) 719 * 720 * Parametrs: 721 * [in] input The input to be operated on 722 * [in] shift The shift number 723 * 724 * Return: 725 * [out] Result of operation 726 * 727 **/ 728 729 730 OMX_S16 armSatRoundRightShift_S32_S16(OMX_S32 input, OMX_INT shift) 731 { 732 input = armSatRoundLeftShift_S32(input,-shift); 733 734 if ( input > OMX_MAX_S16 ) 735 { 736 return (OMX_S16)OMX_MAX_S16; 737 } 738 else if (input < OMX_MIN_S16) 739 { 740 return (OMX_S16)OMX_MIN_S16; 741 } 742 else 743 { 744 return (OMX_S16)input; 745 } 746 747 } 748 749 /** 750 * Function :armSatRoundLeftShift_S32() 751 * 752 * Description : 753 * Returns the result of saturating left-shift operation on input 754 * Or rounded Right shift if the input Shift is negative. 755 * 756 * Parametrs: 757 * [in] Value Operand 758 * [in] Shift Operand for shift operation 759 * 760 * Return: 761 * [out] Result of operation 762 * 763 **/ 764 765 OMX_S32 armSatRoundLeftShift_S32(OMX_S32 Value, OMX_INT Shift) 766 { 767 OMX_INT i; 768 769 if (Shift < 0) 770 { 771 Shift = -Shift; 772 Value = armSatAdd_S32(Value, (1 << (Shift - 1))); 773 Value = Value >> Shift; 774 } 775 else 776 { 777 for (i = 0; i < Shift; i++) 778 { 779 Value = armSatAdd_S32(Value, Value); 780 } 781 } 782 return Value; 783 } 784 785 /** 786 * Function :armSatRoundLeftShift_S64() 787 * 788 * Description : 789 * Returns the result of saturating left-shift operation on input 790 * Or rounded Right shift if the input Shift is negative. 791 * 792 * Parametrs: 793 * [in] Value Operand 794 * [in] shift Operand for shift operation 795 * 796 * Return: 797 * [out] Result of operation 798 * 799 **/ 800 801 OMX_S64 armSatRoundLeftShift_S64(OMX_S64 Value, OMX_INT Shift) 802 { 803 OMX_INT i; 804 805 if (Shift < 0) 806 { 807 Shift = -Shift; 808 Value = armSatAdd_S64(Value, ((OMX_S64)1 << (Shift - 1))); 809 Value = Value >> Shift; 810 } 811 else 812 { 813 for (i = 0; i < Shift; i++) 814 { 815 Value = armSatAdd_S64(Value, Value); 816 } 817 } 818 return Value; 819 } 820 821 /** 822 * Function :armSatMulS16S32_S32() 823 * 824 * Description : 825 * Returns the result of a S16 data type multiplied with an S32 data type 826 * in a S32 container 827 * 828 * Parametrs: 829 * [in] input1 Operand 1 830 * [in] input2 Operand 2 831 * 832 * Return: 833 * [out] Result of operation 834 * 835 **/ 836 837 838 OMX_S32 armSatMulS16S32_S32(OMX_S16 input1,OMX_S32 input2) 839 { 840 OMX_S16 hi2,lo1; 841 OMX_U16 lo2; 842 843 OMX_S32 temp1,temp2; 844 OMX_S32 result; 845 846 lo1 = input1; 847 848 hi2 = ( input2 >> 16 ); 849 lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 ); 850 851 temp1 = hi2 * lo1; 852 temp2 = ( lo2* lo1 ) >> 16; 853 854 result = armSatAdd_S32(temp1,temp2); 855 856 return result; 857 } 858 859 /** 860 * Function :armSatMulS32S32_S32() 861 * 862 * Description : 863 * Returns the result of a S32 data type multiplied with an S32 data type 864 * in a S32 container 865 * 866 * Parametrs: 867 * [in] input1 Operand 1 868 * [in] input2 Operand 2 869 * 870 * Return: 871 * [out] Result of operation 872 * 873 **/ 874 875 OMX_S32 armSatMulS32S32_S32(OMX_S32 input1,OMX_S32 input2) 876 { 877 OMX_S16 hi1,hi2; 878 OMX_U16 lo1,lo2; 879 880 OMX_S32 temp1,temp2,temp3; 881 OMX_S32 result; 882 883 hi1 = ( input1 >> 16 ); 884 lo1 = ( (OMX_U32)( input1 << 16 ) >> 16 ); 885 886 hi2 = ( input2 >> 16 ); 887 lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 ); 888 889 temp1 = hi1 * hi2; 890 temp2 = ( hi1* lo2 ) >> 16; 891 temp3 = ( hi2* lo1 ) >> 16; 892 893 result = armSatAdd_S32(temp1,temp2); 894 result = armSatAdd_S32(result,temp3); 895 896 return result; 897 } 898 899 /** 900 * Function :armIntDivAwayFromZero() 901 * 902 * Description : Integer division with rounding to the nearest integer. 903 * Half-integer values are rounded away from zero 904 * unless otherwise specified. For example 3//2 is rounded 905 * to 2, and -3//2 is rounded to -2. 906 * 907 * Parametrs: 908 * [in] Num Operand 1 909 * [in] Deno Operand 2 910 * 911 * Return: 912 * [out] Result of operation input1//input2 913 * 914 **/ 915 916 OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno) 917 { 918 OMX_F64 result; 919 920 result = ((OMX_F64)Num)/((OMX_F64)Deno); 921 922 if (result >= 0) 923 { 924 result += 0.5; 925 } 926 else 927 { 928 result -= 0.5; 929 } 930 931 return (OMX_S32)(result); 932 } 933 934 935 /*End of File*/ 936 937