armCOMM.c revision 0c1bc742181ded4930842b46e9507372f0b1b963
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
35OMX_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
61OMX_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
86OMX_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
130OMX_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
174OMX_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
202OMX_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
230OMX_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
262OMX_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
302OMX_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
338OMX_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
375OMX_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 */
405OMXResult 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
440OMX_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
469OMX_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
500OMX_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
553OMX_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
605OMX_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
658OMX_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
686OMX_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
730OMX_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
765OMX_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
801OMX_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
838OMX_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
875OMX_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
916OMX_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