Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      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     Table of contents
     20 
     21      1. Include headers
     22      2. External compiler flags
     23      3. Module defines
     24      4. Local function prototypes
     25      5. Functions
     26           h264bsdProcessBlock
     27           h264bsdProcessLumaDc
     28           h264bsdProcessChromaDc
     29 
     30 ------------------------------------------------------------------------------*/
     31 
     32 /*------------------------------------------------------------------------------
     33     1. Include headers
     34 ------------------------------------------------------------------------------*/
     35 
     36 #include "basetype.h"
     37 #include "h264bsd_transform.h"
     38 #include "h264bsd_util.h"
     39 
     40 /*------------------------------------------------------------------------------
     41     2. External compiler flags
     42 --------------------------------------------------------------------------------
     43 
     44 --------------------------------------------------------------------------------
     45     3. Module defines
     46 ------------------------------------------------------------------------------*/
     47 
     48 /* Switch off the following Lint messages for this file:
     49  * Info 701: Shift left of signed quantity (int)
     50  * Info 702: Shift right of signed quantity (int)
     51  */
     52 /*lint -e701 -e702 */
     53 
     54 /* LevelScale function */
     55 static const i32 levelScale[6][3] = {
     56     {10,13,16}, {11,14,18}, {13,16,20}, {14,18,23}, {16,20,25}, {18,23,29}};
     57 
     58 /* qp % 6 as a function of qp */
     59 static const u8 qpMod6[52] = {0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,
     60     0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3};
     61 
     62 /* qp / 6 as a function of qp */
     63 static const u8 qpDiv6[52] = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,
     64     4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8};
     65 
     66 /*------------------------------------------------------------------------------
     67     4. Local function prototypes
     68 ------------------------------------------------------------------------------*/
     69 
     70 /*------------------------------------------------------------------------------
     71 
     72     Function: h264bsdProcessBlock
     73 
     74         Functional description:
     75             Function performs inverse zig-zag scan, inverse scaling and
     76             inverse transform for a luma or a chroma residual block
     77 
     78         Inputs:
     79             data            pointer to data to be processed
     80             qp              quantization parameter
     81             skip            skip processing of data[0], set to non-zero value
     82                             if dc coeff hanled separately
     83             coeffMap        16 lsb's indicate which coeffs are non-zero,
     84                             bit 0 (lsb) for coeff 0, bit 1 for coeff 1 etc.
     85 
     86         Outputs:
     87             data            processed data
     88 
     89         Returns:
     90             HANTRO_OK       success
     91             HANTRO_NOK      processed data not in valid range [-512, 511]
     92 
     93 ------------------------------------------------------------------------------*/
     94 u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap)
     95 {
     96 
     97 /* Variables */
     98 
     99     i32 tmp0, tmp1, tmp2, tmp3;
    100     i32 d1, d2, d3;
    101     u32 row,col;
    102     u32 qpDiv;
    103     i32 *ptr;
    104 
    105 /* Code */
    106 
    107     qpDiv = qpDiv6[qp];
    108     tmp1 = levelScale[qpMod6[qp]][0] << qpDiv;
    109     tmp2 = levelScale[qpMod6[qp]][1] << qpDiv;
    110     tmp3 = levelScale[qpMod6[qp]][2] << qpDiv;
    111 
    112     if (!skip)
    113         data[0] = (data[0] * tmp1);
    114 
    115     /* at least one of the rows 1, 2 or 3 contain non-zero coeffs, mask takes
    116      * the scanning order into account */
    117     if (coeffMap & 0xFF9C)
    118     {
    119         /* do the zig-zag scan and inverse quantization */
    120         d1 = data[1];
    121         d2 = data[14];
    122         d3 = data[15];
    123         data[1] = (d1 * tmp2);
    124         data[14] = (d2 * tmp2);
    125         data[15] = (d3 * tmp3);
    126 
    127         d1 = data[2];
    128         d2 = data[5];
    129         d3 = data[4];
    130         data[4] = (d1 * tmp2);
    131         data[2]  = (d2 * tmp1);
    132         data[5] = (d3 * tmp3);
    133 
    134         d1 = data[8];
    135         d2 = data[3];
    136         d3 = data[6];
    137         tmp0 = (d1 * tmp2);
    138         data[8] = (d2 * tmp1);
    139         data[3]  = (d3 * tmp2);
    140         d1 = data[7];
    141         d2 = data[12];
    142         d3 = data[9];
    143         data[6]  = (d1 * tmp2);
    144         data[7]  = (d2 * tmp3);
    145         data[12] = (d3 * tmp2);
    146         data[9]  = tmp0;
    147 
    148         d1 = data[10];
    149         d2 = data[11];
    150         d3 = data[13];
    151         data[13] = (d1 * tmp3);
    152         data[10] = (d2 * tmp1);
    153         data[11] = (d3 * tmp2);
    154 
    155         /* horizontal transform */
    156         for (row = 4, ptr = data; row--; ptr += 4)
    157         {
    158             tmp0 = ptr[0] + ptr[2];
    159             tmp1 = ptr[0] - ptr[2];
    160             tmp2 = (ptr[1] >> 1) - ptr[3];
    161             tmp3 = ptr[1] + (ptr[3] >> 1);
    162             ptr[0] = tmp0 + tmp3;
    163             ptr[1] = tmp1 + tmp2;
    164             ptr[2] = tmp1 - tmp2;
    165             ptr[3] = tmp0 - tmp3;
    166         }
    167 
    168         /*lint +e661 +e662*/
    169         /* then vertical transform */
    170         for (col = 4; col--; data++)
    171         {
    172             tmp0 = data[0] + data[8];
    173             tmp1 = data[0] - data[8];
    174             tmp2 = (data[4] >> 1) - data[12];
    175             tmp3 = data[4] + (data[12] >> 1);
    176             data[0 ] = (tmp0 + tmp3 + 32)>>6;
    177             data[4 ] = (tmp1 + tmp2 + 32)>>6;
    178             data[8 ] = (tmp1 - tmp2 + 32)>>6;
    179             data[12] = (tmp0 - tmp3 + 32)>>6;
    180             /* check that each value is in the range [-512,511] */
    181             if (((u32)(data[0] + 512) > 1023) ||
    182                 ((u32)(data[4] + 512) > 1023) ||
    183                 ((u32)(data[8] + 512) > 1023) ||
    184                 ((u32)(data[12] + 512) > 1023) )
    185                 return(HANTRO_NOK);
    186         }
    187     }
    188     else /* rows 1, 2 and 3 are zero */
    189     {
    190         /* only dc-coeff is non-zero, i.e. coeffs at original positions
    191          * 1, 5 and 6 are zero */
    192         if ((coeffMap & 0x62) == 0)
    193         {
    194             tmp0 = (data[0] + 32) >> 6;
    195             /* check that value is in the range [-512,511] */
    196             if ((u32)(tmp0 + 512) > 1023)
    197                 return(HANTRO_NOK);
    198             data[0] = data[1]  = data[2]  = data[3]  = data[4]  = data[5]  =
    199                       data[6]  = data[7]  = data[8]  = data[9]  = data[10] =
    200                       data[11] = data[12] = data[13] = data[14] = data[15] =
    201                       tmp0;
    202         }
    203         else /* at least one of the coeffs 1, 5 or 6 is non-zero */
    204         {
    205             data[1] = (data[1] * tmp2);
    206             data[2] = (data[5] * tmp1);
    207             data[3] = (data[6] * tmp2);
    208             tmp0 = data[0] + data[2];
    209             tmp1 = data[0] - data[2];
    210             tmp2 = (data[1] >> 1) - data[3];
    211             tmp3 = data[1] + (data[3] >> 1);
    212             data[0] = (tmp0 + tmp3 + 32)>>6;
    213             data[1] = (tmp1 + tmp2 + 32)>>6;
    214             data[2] = (tmp1 - tmp2 + 32)>>6;
    215             data[3] = (tmp0 - tmp3 + 32)>>6;
    216             data[4] = data[8] = data[12] = data[0];
    217             data[5] = data[9] = data[13] = data[1];
    218             data[6] = data[10] = data[14] = data[2];
    219             data[7] = data[11] = data[15] = data[3];
    220             /* check that each value is in the range [-512,511] */
    221             if (((u32)(data[0] + 512) > 1023) ||
    222                 ((u32)(data[1] + 512) > 1023) ||
    223                 ((u32)(data[2] + 512) > 1023) ||
    224                 ((u32)(data[3] + 512) > 1023) )
    225                 return(HANTRO_NOK);
    226         }
    227     }
    228 
    229     return(HANTRO_OK);
    230 
    231 }
    232 
    233 /*------------------------------------------------------------------------------
    234 
    235     Function: h264bsdProcessLumaDc
    236 
    237         Functional description:
    238             Function performs inverse zig-zag scan, inverse transform and
    239             inverse scaling for a luma DC coefficients block
    240 
    241         Inputs:
    242             data            pointer to data to be processed
    243             qp              quantization parameter
    244 
    245         Outputs:
    246             data            processed data
    247 
    248         Returns:
    249             none
    250 
    251 ------------------------------------------------------------------------------*/
    252 void h264bsdProcessLumaDc(i32 *data, u32 qp)
    253 {
    254 
    255 /* Variables */
    256 
    257     i32 tmp0, tmp1, tmp2, tmp3;
    258     u32 row,col;
    259     u32 qpMod, qpDiv;
    260     i32 levScale;
    261     i32 *ptr;
    262 
    263 /* Code */
    264 
    265     qpMod = qpMod6[qp];
    266     qpDiv = qpDiv6[qp];
    267 
    268     /* zig-zag scan */
    269     tmp0 = data[2];
    270     data[2]  = data[5];
    271     data[5] = data[4];
    272     data[4] = tmp0;
    273 
    274     tmp0 = data[8];
    275     data[8] = data[3];
    276     data[3]  = data[6];
    277     data[6]  = data[7];
    278     data[7]  = data[12];
    279     data[12] = data[9];
    280     data[9]  = tmp0;
    281 
    282     tmp0 = data[10];
    283     data[10] = data[11];
    284     data[11] = data[13];
    285     data[13] = tmp0;
    286 
    287     /* horizontal transform */
    288     for (row = 4, ptr = data; row--; ptr += 4)
    289     {
    290         tmp0 = ptr[0] + ptr[2];
    291         tmp1 = ptr[0] - ptr[2];
    292         tmp2 = ptr[1] - ptr[3];
    293         tmp3 = ptr[1] + ptr[3];
    294         ptr[0] = tmp0 + tmp3;
    295         ptr[1] = tmp1 + tmp2;
    296         ptr[2] = tmp1 - tmp2;
    297         ptr[3] = tmp0 - tmp3;
    298     }
    299 
    300     /*lint +e661 +e662*/
    301     /* then vertical transform and inverse scaling */
    302     levScale = levelScale[ qpMod ][0];
    303     if (qp >= 12)
    304     {
    305         levScale <<= (qpDiv-2);
    306         for (col = 4; col--; data++)
    307         {
    308             tmp0 = data[0] + data[8 ];
    309             tmp1 = data[0] - data[8 ];
    310             tmp2 = data[4] - data[12];
    311             tmp3 = data[4] + data[12];
    312             data[0 ] = ((tmp0 + tmp3)*levScale);
    313             data[4 ] = ((tmp1 + tmp2)*levScale);
    314             data[8 ] = ((tmp1 - tmp2)*levScale);
    315             data[12] = ((tmp0 - tmp3)*levScale);
    316         }
    317     }
    318     else
    319     {
    320         i32 tmp;
    321         tmp = ((1 - qpDiv) == 0) ? 1 : 2;
    322         for (col = 4; col--; data++)
    323         {
    324             tmp0 = data[0] + data[8 ];
    325             tmp1 = data[0] - data[8 ];
    326             tmp2 = data[4] - data[12];
    327             tmp3 = data[4] + data[12];
    328             data[0 ] = ((tmp0 + tmp3)*levScale+tmp) >> (2-qpDiv);
    329             data[4 ] = ((tmp1 + tmp2)*levScale+tmp) >> (2-qpDiv);
    330             data[8 ] = ((tmp1 - tmp2)*levScale+tmp) >> (2-qpDiv);
    331             data[12] = ((tmp0 - tmp3)*levScale+tmp) >> (2-qpDiv);
    332         }
    333     }
    334 
    335 }
    336 
    337 /*------------------------------------------------------------------------------
    338 
    339     Function: h264bsdProcessChromaDc
    340 
    341         Functional description:
    342             Function performs inverse transform and inverse scaling for a
    343             chroma DC coefficients block
    344 
    345         Inputs:
    346             data            pointer to data to be processed
    347             qp              quantization parameter
    348 
    349         Outputs:
    350             data            processed data
    351 
    352         Returns:
    353             none
    354 
    355 ------------------------------------------------------------------------------*/
    356 void h264bsdProcessChromaDc(i32 *data, u32 qp)
    357 {
    358 
    359 /* Variables */
    360 
    361     i32 tmp0, tmp1, tmp2, tmp3;
    362     u32 qpDiv;
    363     i32 levScale;
    364     u32 levShift;
    365 
    366 /* Code */
    367 
    368     qpDiv = qpDiv6[qp];
    369     levScale = levelScale[ qpMod6[qp] ][0];
    370 
    371     if (qp >= 6)
    372     {
    373         levScale <<= (qpDiv-1);
    374         levShift = 0;
    375     }
    376     else
    377     {
    378         levShift = 1;
    379     }
    380 
    381     tmp0 = data[0] + data[2];
    382     tmp1 = data[0] - data[2];
    383     tmp2 = data[1] - data[3];
    384     tmp3 = data[1] + data[3];
    385     data[0] = ((tmp0 + tmp3) * levScale) >> levShift;
    386     data[1] = ((tmp0 - tmp3) * levScale) >> levShift;
    387     data[2] = ((tmp1 + tmp2) * levScale) >> levShift;
    388     data[3] = ((tmp1 - tmp2) * levScale) >> levShift;
    389     tmp0 = data[4] + data[6];
    390     tmp1 = data[4] - data[6];
    391     tmp2 = data[5] - data[7];
    392     tmp3 = data[5] + data[7];
    393     data[4] = ((tmp0 + tmp3) * levScale) >> levShift;
    394     data[5] = ((tmp0 - tmp3) * levScale) >> levShift;
    395     data[6] = ((tmp1 + tmp2) * levScale) >> levShift;
    396     data[7] = ((tmp1 - tmp2) * levScale) >> levShift;
    397 
    398 }
    399 
    400 /*lint +e701 +e702 */
    401 
    402 
    403