blob: 1118744fa6e756ce8da37eebc7cacc15bf117369 [file] [log] [blame]
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*
* This file was originally licensed as follows. It has been
* relicensed with permission from the copyright holders.
*/
/**
*
* File Name: armCOMM.c
* OpenMAX DL: v1.0.2
* Revision: 10586
* Date: Wednesday, March 5, 2008
*
* (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
*
*
*
* Defines Common APIs used across OpenMAX API's
*/
#include "omxtypes.h"
#include "armCOMM.h"
/***********************************************************************/
/* Miscellaneous Arithmetic operations */
/**
* Function: armRoundFloatToS16
*
* Description:
* Converts a double precision value into a short int after rounding
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_S16 format
*
*/
OMX_S16 armRoundFloatToS16 (OMX_F64 Value)
{
if (Value > 0)
{
return (OMX_S16)(Value + .5);
}
else
{
return (OMX_S16)(Value - .5);
}
}
/**
* Function: armRoundFloatToS32
*
* Description:
* Converts a double precision value into a int after rounding
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_S32 format
*
*/
OMX_S32 armRoundFloatToS32 (OMX_F64 Value)
{
if (Value > 0)
{
return (OMX_S32)(Value + .5);
}
else
{
return (OMX_S32)(Value - .5);
}
}
/**
* Function: armSatRoundFloatToS16
*
* Description:
* Converts a double precision value into a short int after rounding and saturation
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_S16 format
*
*/
OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value)
{
if (Value > 0)
{
Value += 0.5;
if(Value > (OMX_S16)OMX_MAX_S16 )
{
return (OMX_S16)OMX_MAX_S16;
}
else
{
return (OMX_S16)Value;
}
}
else
{
Value -= 0.5;
if(Value < (OMX_S16)OMX_MIN_S16 )
{
return (OMX_S16)OMX_MIN_S16;
}
else
{
return (OMX_S16)Value;
}
}
}
/**
* Function: armSatRoundFloatToS32
*
* Description:
* Converts a double precision value into a int after rounding and saturation
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_S32 format
*
*/
OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value)
{
if (Value > 0)
{
Value += 0.5;
if(Value > (OMX_S32)OMX_MAX_S32 )
{
return (OMX_S32)OMX_MAX_S32;
}
else
{
return (OMX_S32)Value;
}
}
else
{
Value -= 0.5;
if(Value < (OMX_S32)OMX_MIN_S32 )
{
return (OMX_S32)OMX_MIN_S32;
}
else
{
return (OMX_S32)Value;
}
}
}
/**
* Function: armSatRoundFloatToU16
*
* Description:
* Converts a double precision value into a unsigned short int after rounding and saturation
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_U16 format
*
*/
OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value)
{
Value += 0.5;
if(Value > (OMX_U16)OMX_MAX_U16 )
{
return (OMX_U16)OMX_MAX_U16;
}
else
{
return (OMX_U16)Value;
}
}
/**
* Function: armSatRoundFloatToU32
*
* Description:
* Converts a double precision value into a unsigned int after rounding and saturation
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_U32 format
*
*/
OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value)
{
Value += 0.5;
if(Value > (OMX_U32)OMX_MAX_U32 )
{
return (OMX_U32)OMX_MAX_U32;
}
else
{
return (OMX_U32)Value;
}
}
/**
* Function: armRoundFloatToS64
*
* Description:
* Converts a double precision value into a 64 bit int after rounding
*
* Parameters:
* [in] Value Float value to be converted
*
* Return Value:
* [out] converted value in OMX_S64 format
*
*/
OMX_S64 armRoundFloatToS64 (OMX_F64 Value)
{
if (Value > 0)
{
return (OMX_S64)(Value + .5);
}
else
{
return (OMX_S64)(Value - .5);
}
}
/**
* Function: armSignCheck
*
* Description:
* Checks the sign of a variable:
* returns 1 if it is Positive
* returns 0 if it is 0
* returns -1 if it is Negative
*
* Remarks:
*
* Parameters:
* [in] var Variable to be checked
*
* Return Value:
* OMX_INT -- returns 1 if it is Positive
* returns 0 if it is 0
* returns -1 if it is Negative
*/
OMX_INT armSignCheck (
OMX_S16 var
)
{
OMX_INT Sign;
if (var < 0)
{
Sign = -1;
}
else if ( var > 0)
{
Sign = 1;
}
else
{
Sign = 0;
}
return Sign;
}
/**
* Function: armClip
*
* Description: Clips the input between MAX and MIN value
*
*
* Remarks:
*
* Parameters:
* [in] Min lower bound
* [in] Max upper bound
* [in] src variable to the clipped
*
* Return Value:
* OMX_S32 -- returns clipped value
*/
OMX_S32 armClip (
OMX_INT min,
OMX_INT max,
OMX_S32 src
)
{
if (src > max)
{
src = max;
}
else if (src < min)
{
src = min;
}
return src;
}
/**
* Function: armClip_F32
*
* Description: Clips the input between MAX and MIN value
*
*
* Remarks:
*
* Parameters:
* [in] Min lower bound
* [in] Max upper bound
* [in] src variable to the clipped
*
* Return Value:
* OMX_F32 -- returns clipped value
*/
OMX_F32 armClip_F32 (
OMX_F32 min,
OMX_F32 max,
OMX_F32 src
)
{
if (src > max)
{
src = max;
}
else if (src < min)
{
src = min;
}
return src;
}
/**
* Function: armShiftSat_F32
*
* Description: Divides a float value by 2^shift and
* saturates it for unsigned value range for satBits.
* Second parameter is like "shifting" the corresponding
* integer value. Takes care of rounding while clipping the final
* value.
*
* Parameters:
* [in] v Number to be operated upon
* [in] shift Divides the input "v" by "2^shift"
* [in] satBits Final range is [0, 2^satBits)
*
* Return Value:
* OMX_S32 -- returns "shifted" saturated value
*/
OMX_U32 armShiftSat_F32(OMX_F32 v, OMX_INT shift, OMX_INT satBits)
{
OMX_U32 allOnes = (OMX_U32)(-1);
OMX_U32 maxV = allOnes >> (32-satBits);
OMX_F32 vShifted, vRounded, shiftDiv = (OMX_F32)(1 << shift);
OMX_U32 vInt;
OMX_U32 vIntSat;
if(v <= 0)
return 0;
vShifted = v / shiftDiv;
vRounded = (OMX_F32)(vShifted + 0.5);
vInt = (OMX_U32)vRounded;
vIntSat = vInt;
if(vIntSat > maxV)
vIntSat = maxV;
return vIntSat;
}
/**
* Functions: armSwapElem
*
* Description:
* These function swaps two elements at the specified pointer locations.
* The size of each element could be anything as specified by <elemSize>
*
* Return Value:
* OMXResult -- Error status from the function
*/
OMXResult armSwapElem(
OMX_U8 *pBuf1,
OMX_U8 *pBuf2,
OMX_INT elemSize
)
{
OMX_INT i;
OMX_U8 temp;
armRetArgErrIf(!pBuf1 || !pBuf2, OMX_Sts_BadArgErr);
for(i = 0; i < elemSize; i++)
{
temp = *(pBuf1 + i);
*(pBuf1 + i) = *(pBuf2 + i);
*(pBuf2 + i) = temp;
}
return OMX_Sts_NoErr;
}
/**
* Function: armMedianOf3
*
* Description: Finds the median of three numbers
*
* Remarks:
*
* Parameters:
* [in] fEntry First entry
* [in] sEntry second entry
* [in] tEntry Third entry
*
* Return Value:
* OMX_S32 -- returns the median value
*/
OMX_S32 armMedianOf3 (
OMX_S32 fEntry,
OMX_S32 sEntry,
OMX_S32 tEntry
)
{
OMX_S32 a, b, c;
a = armMin (fEntry, sEntry);
b = armMax (fEntry, sEntry);
c = armMin (b, tEntry);
return (armMax (a, c));
}
/**
* Function: armLogSize
*
* Description: Finds the size of a positive value and returns the same
*
* Remarks:
*
* Parameters:
* [in] value Positive value
*
* Return Value:
* OMX_U8 -- Returns the minimum number of bits required to represent the positive value.
This is the smallest k>=0 such that that value is less than (1<<k).
*/
OMX_U8 armLogSize (
OMX_U16 value
)
{
OMX_U8 i;
for ( i = 0; value > 0; value = value >> 1)
{
i++;
}
return i;
}
/***********************************************************************/
/* Saturating Arithmetic operations */
/**
* Function :armSatAdd_S32()
*
* Description :
* Returns the result of saturated addition of the two inputs Value1, Value2
*
* Parametrs:
* [in] Value1 First Operand
* [in] Value2 Second Operand
*
* Return:
* [out] Result of operation
*
*
**/
OMX_S32 armSatAdd_S32(OMX_S32 Value1,OMX_S32 Value2)
{
OMX_S32 Result;
Result = Value1 + Value2;
if( (Value1^Value2) >= 0)
{
/*Same sign*/
if( (Result^Value1) >= 0)
{
/*Result has not saturated*/
return Result;
}
else
{
if(Value1 >= 0)
{
/*Result has saturated in positive side*/
return OMX_MAX_S32;
}
else
{
/*Result has saturated in negative side*/
return OMX_MIN_S32;
}
}
}
else
{
return Result;
}
}
/**
* Function :armSatAdd_S64()
*
* Description :
* Returns the result of saturated addition of the two inputs Value1, Value2
*
* Parametrs:
* [in] Value1 First Operand
* [in] Value2 Second Operand
*
* Return:
* [out] Result of operation
*
*
**/
OMX_S64 armSatAdd_S64(OMX_S64 Value1,OMX_S64 Value2)
{
OMX_S64 Result;
Result = Value1 + Value2;
if( (Value1^Value2) >= 0)
{
/*Same sign*/
if( (Result^Value1) >= 0)
{
/*Result has not saturated*/
return Result;
}
else
{
if(Value1 >= 0)
{
/*Result has saturated in positive side*/
Result = OMX_MAX_S64;
return Result;
}
else
{
/*Result has saturated in negative side*/
return OMX_MIN_S64;
}
}
}
else
{
return Result;
}
}
/** Function :armSatSub_S32()
*
* Description :
* Returns the result of saturated substraction of the two inputs Value1, Value2
*
* Parametrs:
* [in] Value1 First Operand
* [in] Value2 Second Operand
*
* Return:
* [out] Result of operation
*
**/
OMX_S32 armSatSub_S32(OMX_S32 Value1,OMX_S32 Value2)
{
OMX_S32 Result;
Result = Value1 - Value2;
if( (Value1^Value2) < 0)
{
/*Opposite sign*/
if( (Result^Value1) >= 0)
{
/*Result has not saturated*/
return Result;
}
else
{
if(Value1 >= 0)
{
/*Result has saturated in positive side*/
return OMX_MAX_S32;
}
else
{
/*Result has saturated in negative side*/
return OMX_MIN_S32;
}
}
}
else
{
return Result;
}
}
/**
* Function :armSatMac_S32()
*
* Description :
* Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
* accumulation with Mac
*
* Parametrs:
* [in] Value1 First Operand
* [in] Value2 Second Operand
* [in] Mac Accumulator
*
* Return:
* [out] Result of operation
**/
OMX_S32 armSatMac_S32(OMX_S32 Mac,OMX_S16 Value1,OMX_S16 Value2)
{
OMX_S32 Result;
Result = (OMX_S32)(Value1*Value2);
Result = armSatAdd_S32( Mac , Result );
return Result;
}
/**
* Function :armSatMac_S16S32_S32
*
* Description :
* Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
*
* mac = mac + Saturate_in_32Bits(delayElem * filTap)
*
* Parametrs:
* [in] delayElem First 32 bit Operand
* [in] filTap Second 16 bit Operand
* [in] mac Result of MAC operation
*
* Return:
* [out] mac Result of operation
*
**/
OMX_S32 armSatMac_S16S32_S32(OMX_S32 mac, OMX_S32 delayElem, OMX_S16 filTap )
{
OMX_S32 result;
result = armSatMulS16S32_S32(filTap,delayElem);
if ( result > OMX_MAX_S16 )
{
result = OMX_MAX_S32;
}
else if( result < OMX_MIN_S16 )
{
result = OMX_MIN_S32;
}
else
{
result = delayElem * filTap;
}
mac = armSatAdd_S32(mac,result);
return mac;
}
/**
* Function :armSatRoundRightShift_S32_S16
*
* Description :
* Returns the result of rounded right shift operation of input by the scalefactor
*
* output = Saturate_in_16Bits( ( Right/LeftShift( (Round(input) , shift ) )
*
* Parametrs:
* [in] input The input to be operated on
* [in] shift The shift number
*
* Return:
* [out] Result of operation
*
**/
OMX_S16 armSatRoundRightShift_S32_S16(OMX_S32 input, OMX_INT shift)
{
input = armSatRoundLeftShift_S32(input,-shift);
if ( input > OMX_MAX_S16 )
{
return (OMX_S16)OMX_MAX_S16;
}
else if (input < OMX_MIN_S16)
{
return (OMX_S16)OMX_MIN_S16;
}
else
{
return (OMX_S16)input;
}
}
/**
* Function :armSatRoundLeftShift_S32()
*
* Description :
* Returns the result of saturating left-shift operation on input
* Or rounded Right shift if the input Shift is negative.
*
* Parametrs:
* [in] Value Operand
* [in] Shift Operand for shift operation
*
* Return:
* [out] Result of operation
*
**/
OMX_S32 armSatRoundLeftShift_S32(OMX_S32 Value, OMX_INT Shift)
{
OMX_INT i;
if (Shift < 0)
{
Shift = -Shift;
Value = armSatAdd_S32(Value, (1 << (Shift - 1)));
Value = Value >> Shift;
}
else
{
for (i = 0; i < Shift; i++)
{
Value = armSatAdd_S32(Value, Value);
}
}
return Value;
}
/**
* Function :armSatRoundLeftShift_S64()
*
* Description :
* Returns the result of saturating left-shift operation on input
* Or rounded Right shift if the input Shift is negative.
*
* Parametrs:
* [in] Value Operand
* [in] shift Operand for shift operation
*
* Return:
* [out] Result of operation
*
**/
OMX_S64 armSatRoundLeftShift_S64(OMX_S64 Value, OMX_INT Shift)
{
OMX_INT i;
if (Shift < 0)
{
Shift = -Shift;
Value = armSatAdd_S64(Value, ((OMX_S64)1 << (Shift - 1)));
Value = Value >> Shift;
}
else
{
for (i = 0; i < Shift; i++)
{
Value = armSatAdd_S64(Value, Value);
}
}
return Value;
}
/**
* Function :armSatMulS16S32_S32()
*
* Description :
* Returns the result of a S16 data type multiplied with an S32 data type
* in a S32 container
*
* Parametrs:
* [in] input1 Operand 1
* [in] input2 Operand 2
*
* Return:
* [out] Result of operation
*
**/
OMX_S32 armSatMulS16S32_S32(OMX_S16 input1,OMX_S32 input2)
{
OMX_S16 hi2,lo1;
OMX_U16 lo2;
OMX_S32 temp1,temp2;
OMX_S32 result;
lo1 = input1;
hi2 = ( input2 >> 16 );
lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
temp1 = hi2 * lo1;
temp2 = ( lo2* lo1 ) >> 16;
result = armSatAdd_S32(temp1,temp2);
return result;
}
/**
* Function :armSatMulS32S32_S32()
*
* Description :
* Returns the result of a S32 data type multiplied with an S32 data type
* in a S32 container
*
* Parametrs:
* [in] input1 Operand 1
* [in] input2 Operand 2
*
* Return:
* [out] Result of operation
*
**/
OMX_S32 armSatMulS32S32_S32(OMX_S32 input1,OMX_S32 input2)
{
OMX_S16 hi1,hi2;
OMX_U16 lo1,lo2;
OMX_S32 temp1,temp2,temp3;
OMX_S32 result;
hi1 = ( input1 >> 16 );
lo1 = ( (OMX_U32)( input1 << 16 ) >> 16 );
hi2 = ( input2 >> 16 );
lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
temp1 = hi1 * hi2;
temp2 = ( hi1* lo2 ) >> 16;
temp3 = ( hi2* lo1 ) >> 16;
result = armSatAdd_S32(temp1,temp2);
result = armSatAdd_S32(result,temp3);
return result;
}
/**
* Function :armIntDivAwayFromZero()
*
* Description : Integer division with rounding to the nearest integer.
* Half-integer values are rounded away from zero
* unless otherwise specified. For example 3//2 is rounded
* to 2, and -3//2 is rounded to -2.
*
* Parametrs:
* [in] Num Operand 1
* [in] Deno Operand 2
*
* Return:
* [out] Result of operation input1//input2
*
**/
OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno)
{
OMX_F64 result;
result = ((OMX_F64)Num)/((OMX_F64)Deno);
if (result >= 0)
{
result += 0.5;
}
else
{
result -= 0.5;
}
return (OMX_S32)(result);
}
/*End of File*/