blob: 79d0ebf8c26b14877d25eb2fe3a82ed23c54495a [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*********************************************************************************/
/* Filename: fastquant_inline.h */
/* Description: Implementation for in-line functions used in dct.cpp */
/* Modified: */
/*********************************************************************************/
#ifndef _FASTQUANT_INLINE_H_
#define _FASTQUANT_INLINE_H_
#include "mp4def.h"
#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER */
__inline int32 aan_scale(int32 q_value, int32 coeff, int32 round, int32 QPdiv2)
{
q_value = coeff * q_value + round;
coeff = q_value >> 16;
if (coeff < 0) coeff += QPdiv2;
else coeff -= QPdiv2;
return coeff;
}
__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
{
int32 q_value;
q_value = coeff * q_scale; //q_value = -((-(coeff + QPdiv2)*q_scale)>>LSL);
q_value >>= shift; //q_value = (((coeff - QPdiv2)*q_scale)>>LSL );
q_value += ((UInt)q_value >> 31); /* add one if negative */
return q_value;
}
__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
{
int32 coeff = q_value + ac_clip;
if ((UInt)coeff > (UInt)(ac_clip << 1))
q_value = ac_clip ^(q_value >> 31);
return q_value;
}
__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
{
int32 coeff;
OSCL_UNUSED_ARG(tmp);
if (q_value < 0)
{
coeff = q_value * QPx2 - Addition;
if (coeff < -2048)
coeff = -2048;
}
else
{
coeff = q_value * QPx2 + Addition;
if (coeff > 2047)
coeff = 2047;
}
return coeff;
}
__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
{
q_value = coeff * q_value + round;
return q_value;
}
__inline int32 smulbb(int32 q_scale, int32 coeff)
{
int32 q_value;
q_value = coeff * q_scale;
return q_value;
}
__inline int32 aan_dc_scale(int32 coeff, int32 QP)
{
if (coeff < 0) coeff += (QP >> 1);
else coeff -= (QP >> 1);
return coeff;
}
__inline int32 clip_2047(int32 q_value, int32 tmp)
{
OSCL_UNUSED_ARG(tmp);
if (q_value < -2048)
{
q_value = -2048;
}
else if (q_value > 2047)
{
q_value = 2047;
}
return q_value;
}
__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
{
int32 coeff;
OSCL_UNUSED_ARG(tmp);
coeff = q_value << 1;
stepsize *= QP;
if (coeff > 0)
{
q_value = (coeff + 1) * stepsize;
q_value >>= 4;
if (q_value > 2047) q_value = 2047;
}
else
{
q_value = (coeff - 1) * stepsize;
q_value += 15;
q_value >>= 4;
if (q_value < -2048) q_value = -2048;
}
return q_value;
}
__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
{
OSCL_UNUSED_ARG(tmp);
q_value <<= 1;
if (q_value > 0)
{
q_value >>= 4;
if (q_value > 2047) q_value = 2047;
}
else
{
q_value += 15;
q_value >>= 4;
if (q_value < -2048) q_value = -2048;
}
return q_value;
}
#elif defined(__CC_ARM) /* only work with arm v5 */
#if defined(__TARGET_ARCH_5TE)
__inline int32 aan_scale(int32 q_value, int32 coeff,
int32 round, int32 QPdiv2)
{
__asm
{
smlabb q_value, coeff, q_value, round
movs coeff, q_value, asr #16
addle coeff, coeff, QPdiv2
subgt coeff, coeff, QPdiv2
}
return coeff;
}
__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
{
int32 q_value;
__asm
{
smulbb q_value, q_scale, coeff /*mov coeff, coeff, lsl #14*/
mov coeff, q_value, asr shift /*smull tmp, coeff, q_scale, coeff*/
add q_value, coeff, coeff, lsr #31
}
return q_value;
}
__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
{
int32 coeff;
__asm
{
cmp q_value, #0
smulbb coeff, q_value, QPx2
sublt coeff, coeff, Addition
addge coeff, coeff, Addition
add q_value, coeff, tmp
subs q_value, q_value, #3840
subcss q_value, q_value, #254
eorhi coeff, tmp, coeff, asr #31
}
return coeff;
}
__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
{
__asm
{
smlabb q_value, coeff, q_value, round
}
return q_value;
}
__inline int32 smulbb(int32 q_scale, int32 coeff)
{
int32 q_value;
__asm
{
smulbb q_value, q_scale, coeff
}
return q_value;
}
__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
{
/* tmp must have value of 2047 */
int32 coeff;
__asm
{
movs coeff, q_value, lsl #1
smulbb stepsize, stepsize, QP
addgt coeff, coeff, #1
sublt coeff, coeff, #1
smulbb q_value, coeff, stepsize
addlt q_value, q_value, #15
mov q_value, q_value, asr #4
add coeff, q_value, tmp
subs coeff, coeff, #0xf00
subcss coeff, coeff, #0xfe
eorhi q_value, tmp, q_value, asr #31
}
return q_value;
}
#else // not ARMV5TE
__inline int32 aan_scale(int32 q_value, int32 coeff,
int32 round, int32 QPdiv2)
{
__asm
{
mla q_value, coeff, q_value, round
movs coeff, q_value, asr #16
addle coeff, coeff, QPdiv2
subgt coeff, coeff, QPdiv2
}
return coeff;
}
__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
{
int32 q_value;
__asm
{
mul q_value, q_scale, coeff /*mov coeff, coeff, lsl #14*/
mov coeff, q_value, asr shift /*smull tmp, coeff, q_scale, coeff*/
add q_value, coeff, coeff, lsr #31
}
return q_value;
}
__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
{
int32 coeff;
__asm
{
cmp q_value, #0
mul coeff, q_value, QPx2
sublt coeff, coeff, Addition
addge coeff, coeff, Addition
add q_value, coeff, tmp
subs q_value, q_value, #3840
subcss q_value, q_value, #254
eorhi coeff, tmp, coeff, asr #31
}
return coeff;
}
__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
{
__asm
{
mla q_value, coeff, q_value, round
}
return q_value;
}
__inline int32 smulbb(int32 q_scale, int32 coeff)
{
int32 q_value;
__asm
{
mul q_value, q_scale, coeff
}
return q_value;
}
__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
{
/* tmp must have value of 2047 */
int32 coeff;
__asm
{
movs coeff, q_value, lsl #1
mul stepsize, stepsize, QP
addgt coeff, coeff, #1
sublt coeff, coeff, #1
mul q_value, coeff, stepsize
addlt q_value, q_value, #15
mov q_value, q_value, asr #4
add coeff, q_value, tmp
subs coeff, coeff, #0xf00
subcss coeff, coeff, #0xfe
eorhi q_value, tmp, q_value, asr #31
}
return q_value;
}
#endif
__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
{
int32 coeff;
__asm
{
add coeff, q_value, ac_clip
subs coeff, coeff, ac_clip, lsl #1
eorhi q_value, ac_clip, q_value, asr #31
}
return q_value;
}
__inline int32 aan_dc_scale(int32 coeff, int32 QP)
{
__asm
{
cmp coeff, #0
addle coeff, coeff, QP, asr #1
subgt coeff, coeff, QP, asr #1
}
return coeff;
}
__inline int32 clip_2047(int32 q_value, int32 tmp)
{
/* tmp must have value of 2047 */
int32 coeff;
__asm
{
add coeff, q_value, tmp
subs coeff, coeff, #0xf00
subcss coeff, coeff, #0xfe
eorhi q_value, tmp, q_value, asr #31
}
return q_value;
}
__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
{
int32 coeff;
__asm
{
movs q_value, q_value, lsl #1
addlt q_value, q_value, #15
mov q_value, q_value, asr #4
add coeff, q_value, tmp
subs coeff, coeff, #0xf00
subcss coeff, coeff, #0xfe
eorhi q_value, tmp, q_value, asr #31
}
return q_value;
}
#elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER */
__inline int32 aan_scale(int32 q_value, int32 coeff,
int32 round, int32 QPdiv2)
{
register int32 out;
register int32 qv = q_value;
register int32 cf = coeff;
register int32 rr = round;
register int32 qp = QPdiv2;
asm volatile("smlabb %0, %2, %1, %3\n\t"
"movs %0, %0, asr #16\n\t"
"addle %0, %0, %4\n\t"
"subgt %0, %0, %4"
: "=&r"(out)
: "r"(qv),
"r"(cf),
"r"(rr),
"r"(qp));
return out;
}
__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
{
register int32 out;
register int32 temp1;
register int32 cc = coeff;
register int32 qs = q_scale;
register int32 ss = shift;
asm volatile("smulbb %0, %3, %2\n\t"
"mov %1, %0, asr %4\n\t"
"add %0, %1, %1, lsr #31"
: "=&r"(out),
"=&r"(temp1)
: "r"(cc),
"r"(qs),
"r"(ss));
return out;
}
__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
{
register int32 coeff;
asm volatile("add %1, %0, %2\n\t"
"subs %1, %1, %2, lsl #1\n\t"
"eorhi %0, %2, %0, asr #31"
: "+r"(q_value),
"=&r"(coeff)
: "r"(ac_clip));
return q_value;
}
__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
{
register int32 out;
register int32 temp1;
register int32 qv = q_value;
register int32 qp = QPx2;
register int32 aa = Addition;
register int32 tt = tmp;
asm volatile("cmp %2, #0\n\t"
"mul %0, %2, %3\n\t"
"sublt %0, %0, %4\n\t"
"addge %0, %0, %4\n\t"
"add %1, %0, %5\n\t"
"subs %1, %1, #3840\n\t"
"subcss %1, %1, #254\n\t"
"eorhi %0, %5, %0, asr #31"
: "=&r"(out),
"=&r"(temp1)
: "r"(qv),
"r"(qp),
"r"(aa),
"r"(tt));
return out;
}
__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
{
register int32 out;
register int32 aa = (int32)q_value;
register int32 bb = (int32)coeff;
register int32 cc = (int32)round;
asm volatile("smlabb %0, %1, %2, %3"
: "=&r"(out)
: "r"(aa),
"r"(bb),
"r"(cc));
return out;
}
__inline int32 smulbb(int32 q_scale, int32 coeff)
{
register int32 out;
register int32 aa = (int32)q_scale;
register int32 bb = (int32)coeff;
asm volatile("smulbb %0, %1, %2"
: "=&r"(out)
: "r"(aa),
"r"(bb));
return out;
}
__inline int32 aan_dc_scale(int32 coeff, int32 QP)
{
register int32 out;
register int32 cc = coeff;
register int32 qp = QP;
asm volatile("cmp %1, #0\n\t"
"addle %0, %1, %2, asr #1\n\t"
"subgt %0, %1, %2, asr #1"
: "=&r"(out)
: "r"(cc),
"r"(qp));
return out;
}
__inline int32 clip_2047(int32 q_value, int32 tmp)
{
register int32 coeff;
asm volatile("add %1, %0, %2\n\t"
"subs %1, %1, #0xF00\n\t"
"subcss %1, %1, #0xFE\n\t"
"eorhi %0, %2, %0, asr #31"
: "+r"(q_value),
"=&r"(coeff)
: "r"(tmp));
return q_value;
}
__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
{
register int32 out;
register int32 temp1;
register int32 qv = q_value;
register int32 ss = stepsize;
register int32 qp = QP;
register int32 tt = tmp;
asm volatile("movs %1, %2, lsl #1\n\t"
"mul %0, %3, %4\n\t"
"addgt %1, %1, #1\n\t"
"sublt %1, %1, #1\n\t"
"mul %0, %1, %0\n\t"
"addlt %0, %0, #15\n\t"
"mov %0, %0, asr #4\n\t"
"add %1, %0, %5\n\t"
"subs %1, %1, #0xF00\n\t"
"subcss %1, %1, #0xFE\n\t"
"eorhi %0, %5, %0, asr #31"
: "=&r"(out),
"=&r"(temp1)
: "r"(qv),
"r"(ss),
"r"(qp),
"r"(tt));
return out;
}
__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
{
register int32 out;
register int32 temp1;
register int32 qv = q_value;
register int32 tt = tmp;
asm volatile("movs %1, %2, lsl #1\n\t"
"addlt %1, %1, #15\n\t"
"mov %0, %1, asr #4\n\t"
"add %1, %0, %3\n\t"
"subs %1, %1, #0xF00\n\t"
"subcss %1, %1, #0xFE\n\t"
"eorhi %0, %3, %0, asr #31"
: "=&r"(out),
"=&r"(temp1)
: "r"(qv),
"r"(tt));
return out;
}
#endif // Platform
#endif //_FASTQUANT_INLINE_H_