Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      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
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /*********************************************************************************/
     19 /*  Filename: fastquant_inline.h                                                        */
     20 /*  Description: Implementation for in-line functions used in dct.cpp           */
     21 /*  Modified:                                                                   */
     22 /*********************************************************************************/
     23 #ifndef _FASTQUANT_INLINE_H_
     24 #define _FASTQUANT_INLINE_H_
     25 
     26 #include "mp4def.h"
     27 
     28 #if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER  */
     29 
     30 __inline int32 aan_scale(int32 q_value, int32 coeff, int32 round, int32 QPdiv2)
     31 {
     32     q_value = coeff * q_value + round;
     33     coeff = q_value >> 16;
     34     if (coeff < 0)  coeff += QPdiv2;
     35     else            coeff -= QPdiv2;
     36 
     37     return coeff;
     38 }
     39 
     40 
     41 __inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
     42 {
     43     int32 q_value;
     44 
     45     q_value = coeff * q_scale;      //q_value = -((-(coeff + QPdiv2)*q_scale)>>LSL);
     46     q_value >>= shift;                  //q_value = (((coeff - QPdiv2)*q_scale)>>LSL );
     47     q_value += ((UInt)q_value >> 31); /* add one if negative */
     48 
     49     return q_value;
     50 }
     51 
     52 __inline int32  coeff_clip(int32 q_value, int32 ac_clip)
     53 {
     54     int32 coeff = q_value + ac_clip;
     55 
     56     if ((UInt)coeff > (UInt)(ac_clip << 1))
     57         q_value = ac_clip ^(q_value >> 31);
     58 
     59     return q_value;
     60 }
     61 
     62 __inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
     63 {
     64     int32 coeff;
     65 
     66     OSCL_UNUSED_ARG(tmp);
     67 
     68     if (q_value < 0)
     69     {
     70         coeff = q_value * QPx2 - Addition;
     71         if (coeff < -2048)
     72             coeff = -2048;
     73     }
     74     else
     75     {
     76         coeff = q_value * QPx2 + Addition;
     77         if (coeff > 2047)
     78             coeff = 2047;
     79     }
     80     return coeff;
     81 }
     82 
     83 __inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
     84 {
     85     q_value = coeff * q_value + round;
     86 
     87     return q_value;
     88 }
     89 
     90 __inline int32 smulbb(int32 q_scale, int32 coeff)
     91 {
     92     int32 q_value;
     93 
     94     q_value = coeff * q_scale;
     95 
     96     return q_value;
     97 }
     98 
     99 __inline int32 aan_dc_scale(int32 coeff, int32 QP)
    100 {
    101 
    102     if (coeff < 0)  coeff += (QP >> 1);
    103     else            coeff -= (QP >> 1);
    104 
    105     return coeff;
    106 }
    107 
    108 __inline int32 clip_2047(int32 q_value, int32 tmp)
    109 {
    110     OSCL_UNUSED_ARG(tmp);
    111 
    112     if (q_value < -2048)
    113     {
    114         q_value = -2048;
    115     }
    116     else if (q_value > 2047)
    117     {
    118         q_value = 2047;
    119     }
    120 
    121     return q_value;
    122 }
    123 
    124 __inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
    125 {
    126     int32 coeff;
    127 
    128     OSCL_UNUSED_ARG(tmp);
    129 
    130     coeff = q_value << 1;
    131     stepsize *= QP;
    132     if (coeff > 0)
    133     {
    134         q_value = (coeff + 1) * stepsize;
    135         q_value >>= 4;
    136         if (q_value > 2047) q_value = 2047;
    137     }
    138     else
    139     {
    140         q_value = (coeff - 1) * stepsize;
    141         q_value += 15;
    142         q_value >>= 4;
    143         if (q_value < -2048)    q_value = -2048;
    144     }
    145 
    146     return q_value;
    147 }
    148 
    149 __inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
    150 {
    151     OSCL_UNUSED_ARG(tmp);
    152 
    153     q_value <<= 1;
    154     if (q_value > 0)
    155     {
    156         q_value >>= 4;
    157         if (q_value > 2047) q_value = 2047;
    158     }
    159     else
    160     {
    161         q_value += 15;
    162         q_value >>= 4;
    163         if (q_value < -2048) q_value = -2048;
    164     }
    165 
    166     return q_value;
    167 }
    168 
    169 #elif defined(__CC_ARM)  /* only work with arm v5 */
    170 
    171 #if defined(__TARGET_ARCH_5TE)
    172 
    173 __inline int32 aan_scale(int32 q_value, int32 coeff,
    174                          int32 round, int32 QPdiv2)
    175 {
    176     __asm
    177     {
    178         smlabb q_value, coeff, q_value, round
    179         movs       coeff, q_value, asr #16
    180         addle   coeff, coeff, QPdiv2
    181         subgt   coeff, coeff, QPdiv2
    182     }
    183 
    184     return coeff;
    185 }
    186 
    187 __inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
    188 {
    189     int32 q_value;
    190 
    191     __asm
    192     {
    193         smulbb  q_value, q_scale, coeff    /*mov    coeff, coeff, lsl #14*/
    194         mov     coeff, q_value, asr shift   /*smull tmp, coeff, q_scale, coeff*/
    195         add q_value, coeff, coeff, lsr #31
    196     }
    197 
    198 
    199     return q_value;
    200 }
    201 
    202 __inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
    203 {
    204     int32 coeff;
    205 
    206     __asm
    207     {
    208         cmp     q_value, #0
    209         smulbb  coeff, q_value, QPx2
    210         sublt   coeff, coeff, Addition
    211         addge   coeff, coeff, Addition
    212         add     q_value, coeff, tmp
    213         subs    q_value, q_value, #3840
    214         subcss  q_value, q_value, #254
    215         eorhi   coeff, tmp, coeff, asr #31
    216     }
    217 
    218     return coeff;
    219 }
    220 
    221 __inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
    222 {
    223     __asm
    224     {
    225         smlabb q_value, coeff, q_value, round
    226     }
    227 
    228     return q_value;
    229 }
    230 
    231 __inline int32 smulbb(int32 q_scale, int32 coeff)
    232 {
    233     int32 q_value;
    234 
    235     __asm
    236     {
    237         smulbb  q_value, q_scale, coeff
    238     }
    239 
    240     return q_value;
    241 }
    242 
    243 __inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
    244 {
    245     /* tmp must have value of 2047 */
    246     int32 coeff;
    247     __asm
    248     {
    249         movs    coeff, q_value, lsl #1
    250         smulbb  stepsize, stepsize, QP
    251         addgt   coeff, coeff, #1
    252         sublt   coeff, coeff, #1
    253         smulbb  q_value, coeff, stepsize
    254         addlt   q_value, q_value, #15
    255         mov     q_value, q_value, asr #4
    256         add     coeff, q_value, tmp
    257         subs    coeff, coeff, #0xf00
    258         subcss  coeff, coeff, #0xfe
    259         eorhi   q_value, tmp, q_value, asr #31
    260     }
    261 
    262     return q_value;
    263 }
    264 
    265 
    266 #else // not ARMV5TE
    267 
    268 __inline int32 aan_scale(int32 q_value, int32 coeff,
    269                          int32 round, int32 QPdiv2)
    270 {
    271     __asm
    272     {
    273         mla q_value, coeff, q_value, round
    274         movs       coeff, q_value, asr #16
    275         addle   coeff, coeff, QPdiv2
    276         subgt   coeff, coeff, QPdiv2
    277     }
    278 
    279     return coeff;
    280 }
    281 
    282 __inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
    283 {
    284     int32 q_value;
    285 
    286     __asm
    287     {
    288         mul q_value, q_scale, coeff    /*mov    coeff, coeff, lsl #14*/
    289         mov     coeff, q_value, asr shift   /*smull tmp, coeff, q_scale, coeff*/
    290         add q_value, coeff, coeff, lsr #31
    291     }
    292 
    293 
    294     return q_value;
    295 }
    296 
    297 
    298 __inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
    299 {
    300     int32 coeff;
    301 
    302     __asm
    303     {
    304         cmp     q_value, #0
    305         mul coeff, q_value, QPx2
    306         sublt   coeff, coeff, Addition
    307         addge   coeff, coeff, Addition
    308         add     q_value, coeff, tmp
    309         subs    q_value, q_value, #3840
    310         subcss  q_value, q_value, #254
    311         eorhi   coeff, tmp, coeff, asr #31
    312     }
    313 
    314     return coeff;
    315 }
    316 
    317 __inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
    318 {
    319     __asm
    320     {
    321         mla q_value, coeff, q_value, round
    322     }
    323 
    324     return q_value;
    325 }
    326 
    327 __inline int32 smulbb(int32 q_scale, int32 coeff)
    328 {
    329     int32 q_value;
    330 
    331     __asm
    332     {
    333         mul q_value, q_scale, coeff
    334     }
    335 
    336     return q_value;
    337 }
    338 
    339 
    340 __inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
    341 {
    342     /* tmp must have value of 2047 */
    343     int32 coeff;
    344     __asm
    345     {
    346         movs    coeff, q_value, lsl #1
    347         mul  stepsize, stepsize, QP
    348         addgt   coeff, coeff, #1
    349         sublt   coeff, coeff, #1
    350         mul q_value, coeff, stepsize
    351         addlt   q_value, q_value, #15
    352         mov     q_value, q_value, asr #4
    353         add     coeff, q_value, tmp
    354         subs    coeff, coeff, #0xf00
    355         subcss  coeff, coeff, #0xfe
    356         eorhi   q_value, tmp, q_value, asr #31
    357     }
    358 
    359     return q_value;
    360 }
    361 
    362 
    363 #endif
    364 
    365 __inline int32  coeff_clip(int32 q_value, int32 ac_clip)
    366 {
    367     int32 coeff;
    368 
    369     __asm
    370     {
    371         add     coeff, q_value, ac_clip
    372         subs    coeff, coeff, ac_clip, lsl #1
    373         eorhi   q_value, ac_clip, q_value, asr #31
    374     }
    375 
    376     return q_value;
    377 }
    378 
    379 __inline int32 aan_dc_scale(int32 coeff, int32 QP)
    380 {
    381 
    382     __asm
    383     {
    384         cmp   coeff, #0
    385         addle   coeff, coeff, QP, asr #1
    386         subgt   coeff, coeff, QP, asr #1
    387     }
    388 
    389     return coeff;
    390 }
    391 
    392 __inline int32 clip_2047(int32 q_value, int32 tmp)
    393 {
    394     /* tmp must have value of 2047 */
    395     int32 coeff;
    396 
    397     __asm
    398     {
    399         add     coeff, q_value, tmp
    400         subs    coeff, coeff, #0xf00
    401         subcss  coeff, coeff, #0xfe
    402         eorhi   q_value, tmp, q_value, asr #31
    403     }
    404 
    405     return q_value;
    406 }
    407 
    408 __inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
    409 {
    410     int32 coeff;
    411 
    412     __asm
    413     {
    414         movs    q_value, q_value, lsl #1
    415         addlt   q_value, q_value, #15
    416         mov     q_value, q_value, asr #4
    417         add     coeff, q_value, tmp
    418         subs    coeff, coeff, #0xf00
    419         subcss  coeff, coeff, #0xfe
    420         eorhi   q_value, tmp, q_value, asr #31
    421     }
    422 
    423     return q_value;
    424 }
    425 
    426 #elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER  */
    427 
    428 __inline int32 aan_scale(int32 q_value, int32 coeff,
    429                          int32 round, int32 QPdiv2)
    430 {
    431     register int32 out;
    432     register int32 qv = q_value;
    433     register int32 cf = coeff;
    434     register int32 rr = round;
    435     register int32 qp = QPdiv2;
    436 
    437     asm volatile("smlabb %0, %2, %1, %3\n\t"
    438                  "movs %0, %0, asr #16\n\t"
    439                  "addle %0, %0, %4\n\t"
    440                  "subgt %0, %0, %4"
    441              : "=&r"(out)
    442                          : "r"(qv),
    443                          "r"(cf),
    444                          "r"(rr),
    445                          "r"(qp));
    446     return out;
    447 }
    448 
    449 __inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
    450 {
    451     register int32 out;
    452     register int32 temp1;
    453     register int32 cc = coeff;
    454     register int32 qs = q_scale;
    455     register int32 ss = shift;
    456 
    457     asm volatile("smulbb %0, %3, %2\n\t"
    458                  "mov %1, %0, asr %4\n\t"
    459                  "add %0, %1, %1, lsr #31"
    460              : "=&r"(out),
    461                  "=&r"(temp1)
    462                          : "r"(cc),
    463                          "r"(qs),
    464                          "r"(ss));
    465 
    466     return out;
    467 }
    468 
    469 __inline int32 coeff_clip(int32 q_value, int32 ac_clip)
    470 {
    471     register int32 coeff;
    472 
    473     asm volatile("add   %1, %0, %2\n\t"
    474                  "subs  %1, %1, %2, lsl #1\n\t"
    475                  "eorhi %0, %2, %0, asr #31"
    476              : "+r"(q_value),
    477                  "=&r"(coeff)
    478                          : "r"(ac_clip));
    479 
    480     return q_value;
    481 }
    482 
    483 __inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
    484 {
    485     register int32 out;
    486     register int32 temp1;
    487     register int32 qv = q_value;
    488     register int32 qp = QPx2;
    489     register int32 aa = Addition;
    490     register int32 tt = tmp;
    491 
    492     asm volatile("cmp    %2, #0\n\t"
    493                  "mul    %0, %2, %3\n\t"
    494                  "sublt  %0, %0, %4\n\t"
    495                  "addge  %0, %0, %4\n\t"
    496                  "add    %1, %0, %5\n\t"
    497                  "subs   %1, %1, #3840\n\t"
    498                  "subcss %1, %1, #254\n\t"
    499                  "eorhi  %0, %5, %0, asr #31"
    500              : "=&r"(out),
    501                  "=&r"(temp1)
    502                          : "r"(qv),
    503                          "r"(qp),
    504                          "r"(aa),
    505                          "r"(tt));
    506 
    507     return out;
    508 }
    509 
    510 __inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
    511 {
    512     register int32 out;
    513     register int32 aa = (int32)q_value;
    514     register int32 bb = (int32)coeff;
    515     register int32 cc = (int32)round;
    516 
    517     asm volatile("smlabb %0, %1, %2, %3"
    518              : "=&r"(out)
    519                          : "r"(aa),
    520                          "r"(bb),
    521                          "r"(cc));
    522     return out;
    523 }
    524 
    525 __inline int32 smulbb(int32 q_scale, int32 coeff)
    526 {
    527     register int32 out;
    528     register int32 aa = (int32)q_scale;
    529     register int32 bb = (int32)coeff;
    530 
    531     asm volatile("smulbb %0, %1, %2"
    532              : "=&r"(out)
    533                          : "r"(aa),
    534                          "r"(bb));
    535     return out;
    536 }
    537 
    538 __inline int32 aan_dc_scale(int32 coeff, int32 QP)
    539 {
    540     register int32 out;
    541     register int32 cc = coeff;
    542     register int32 qp = QP;
    543 
    544     asm volatile("cmp %1, #0\n\t"
    545                  "addle %0, %1, %2, asr #1\n\t"
    546                  "subgt %0, %1, %2, asr #1"
    547              : "=&r"(out)
    548                          : "r"(cc),
    549                          "r"(qp));
    550     return out;
    551 }
    552 
    553 __inline int32 clip_2047(int32 q_value, int32 tmp)
    554 {
    555     register int32 coeff;
    556     asm volatile("add    %1, %0, %2\n\t"
    557                  "subs   %1, %1, #0xF00\n\t"
    558                  "subcss %1, %1, #0xFE\n\t"
    559                  "eorhi  %0, %2, %0, asr #31"
    560              : "+r"(q_value),
    561                  "=&r"(coeff)
    562                          : "r"(tmp));
    563 
    564     return q_value;
    565 }
    566 
    567 __inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
    568 {
    569     register int32 out;
    570     register int32 temp1;
    571     register int32 qv = q_value;
    572     register int32 ss = stepsize;
    573     register int32 qp = QP;
    574     register int32 tt = tmp;
    575 
    576     asm volatile("movs    %1, %2, lsl #1\n\t"
    577                  "mul     %0, %3, %4\n\t"
    578                  "addgt   %1, %1, #1\n\t"
    579                  "sublt   %1, %1, #1\n\t"
    580                  "mul     %0, %1, %0\n\t"
    581                  "addlt   %0, %0, #15\n\t"
    582                  "mov     %0, %0, asr #4\n\t"
    583                  "add     %1, %0, %5\n\t"
    584                  "subs    %1, %1, #0xF00\n\t"
    585                  "subcss  %1, %1, #0xFE\n\t"
    586                  "eorhi   %0, %5, %0, asr #31"
    587              : "=&r"(out),
    588                  "=&r"(temp1)
    589                          : "r"(qv),
    590                          "r"(ss),
    591                          "r"(qp),
    592                          "r"(tt));
    593 
    594     return out;
    595 
    596 }
    597 
    598 __inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
    599 {
    600     register int32 out;
    601     register int32 temp1;
    602     register int32 qv = q_value;
    603     register int32 tt = tmp;
    604 
    605     asm volatile("movs    %1, %2, lsl #1\n\t"
    606                  "addlt   %1, %1, #15\n\t"
    607                  "mov     %0, %1, asr #4\n\t"
    608                  "add     %1, %0, %3\n\t"
    609                  "subs    %1, %1, #0xF00\n\t"
    610                  "subcss  %1, %1, #0xFE\n\t"
    611                  "eorhi   %0, %3, %0, asr #31"
    612              : "=&r"(out),
    613                  "=&r"(temp1)
    614                          : "r"(qv),
    615                          "r"(tt));
    616     return out;
    617 }
    618 
    619 
    620 #endif // Platform
    621 
    622 
    623 #endif //_FASTQUANT_INLINE_H_
    624 
    625 
    626