armCOMM.c revision 78e52bfac041d71ce53b5b13c2abf78af742b09d
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