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