/* ------------------------------------------------------------------ * 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_