/Decoder/src/h264bsd_transform.c
https://github.com/mbebenita/Broadway · C · 402 lines · 223 code · 45 blank · 134 comment · 17 complexity · df050937a9519f10fc94be51639d4c16 MD5 · raw file
- /*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * 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.
- */
- /*------------------------------------------------------------------------------
- Table of contents
- 1. Include headers
- 2. External compiler flags
- 3. Module defines
- 4. Local function prototypes
- 5. Functions
- h264bsdProcessBlock
- h264bsdProcessLumaDc
- h264bsdProcessChromaDc
- ------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- 1. Include headers
- ------------------------------------------------------------------------------*/
- #include "basetype.h"
- #include "h264bsd_transform.h"
- #include "h264bsd_util.h"
- /*------------------------------------------------------------------------------
- 2. External compiler flags
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- 3. Module defines
- ------------------------------------------------------------------------------*/
- /* Switch off the following Lint messages for this file:
- * Info 701: Shift left of signed quantity (int)
- * Info 702: Shift right of signed quantity (int)
- */
- /*lint -e701 -e702 */
- /* LevelScale function */
- static const i32 levelScale[6][3] = {
- {10,13,16}, {11,14,18}, {13,16,20}, {14,18,23}, {16,20,25}, {18,23,29}};
- /* qp % 6 as a function of qp */
- 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,
- 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};
- /* qp / 6 as a function of qp */
- 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,
- 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};
- /*------------------------------------------------------------------------------
- 4. Local function prototypes
- ------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- Function: h264bsdProcessBlock
- Functional description:
- Function performs inverse zig-zag scan, inverse scaling and
- inverse transform for a luma or a chroma residual block
- Inputs:
- data pointer to data to be processed
- qp quantization parameter
- skip skip processing of data[0], set to non-zero value
- if dc coeff hanled separately
- coeffMap 16 lsb's indicate which coeffs are non-zero,
- bit 0 (lsb) for coeff 0, bit 1 for coeff 1 etc.
- Outputs:
- data processed data
- Returns:
- HANTRO_OK success
- HANTRO_NOK processed data not in valid range [-512, 511]
- ------------------------------------------------------------------------------*/
- u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap)
- {
- /* Variables */
- i32 tmp0, tmp1, tmp2, tmp3;
- i32 d1, d2, d3;
- u32 row,col;
- u32 qpDiv;
- i32 *ptr;
- /* Code */
- qpDiv = qpDiv6[qp];
- tmp1 = levelScale[qpMod6[qp]][0] << qpDiv;
- tmp2 = levelScale[qpMod6[qp]][1] << qpDiv;
- tmp3 = levelScale[qpMod6[qp]][2] << qpDiv;
- if (!skip)
- data[0] = (data[0] * tmp1);
- /* at least one of the rows 1, 2 or 3 contain non-zero coeffs, mask takes
- * the scanning order into account */
- if (coeffMap & 0xFF9C)
- {
- /* do the zig-zag scan and inverse quantization */
- d1 = data[1];
- d2 = data[14];
- d3 = data[15];
- data[1] = (d1 * tmp2);
- data[14] = (d2 * tmp2);
- data[15] = (d3 * tmp3);
- d1 = data[2];
- d2 = data[5];
- d3 = data[4];
- data[4] = (d1 * tmp2);
- data[2] = (d2 * tmp1);
- data[5] = (d3 * tmp3);
- d1 = data[8];
- d2 = data[3];
- d3 = data[6];
- tmp0 = (d1 * tmp2);
- data[8] = (d2 * tmp1);
- data[3] = (d3 * tmp2);
- d1 = data[7];
- d2 = data[12];
- d3 = data[9];
- data[6] = (d1 * tmp2);
- data[7] = (d2 * tmp3);
- data[12] = (d3 * tmp2);
- data[9] = tmp0;
- d1 = data[10];
- d2 = data[11];
- d3 = data[13];
- data[13] = (d1 * tmp3);
- data[10] = (d2 * tmp1);
- data[11] = (d3 * tmp2);
- /* horizontal transform */
- for (row = 4, ptr = data; row--; ptr += 4)
- {
- tmp0 = ptr[0] + ptr[2];
- tmp1 = ptr[0] - ptr[2];
- tmp2 = (ptr[1] >> 1) - ptr[3];
- tmp3 = ptr[1] + (ptr[3] >> 1);
- ptr[0] = tmp0 + tmp3;
- ptr[1] = tmp1 + tmp2;
- ptr[2] = tmp1 - tmp2;
- ptr[3] = tmp0 - tmp3;
- }
- /*lint +e661 +e662*/
- /* then vertical transform */
- for (col = 4; col--; data++)
- {
- tmp0 = data[0] + data[8];
- tmp1 = data[0] - data[8];
- tmp2 = (data[4] >> 1) - data[12];
- tmp3 = data[4] + (data[12] >> 1);
- data[0 ] = (tmp0 + tmp3 + 32)>>6;
- data[4 ] = (tmp1 + tmp2 + 32)>>6;
- data[8 ] = (tmp1 - tmp2 + 32)>>6;
- data[12] = (tmp0 - tmp3 + 32)>>6;
- /* check that each value is in the range [-512,511] */
- if (((u32)(data[0] + 512) > 1023) ||
- ((u32)(data[4] + 512) > 1023) ||
- ((u32)(data[8] + 512) > 1023) ||
- ((u32)(data[12] + 512) > 1023) )
- return(HANTRO_NOK);
- }
- }
- else /* rows 1, 2 and 3 are zero */
- {
- /* only dc-coeff is non-zero, i.e. coeffs at original positions
- * 1, 5 and 6 are zero */
- if ((coeffMap & 0x62) == 0)
- {
- tmp0 = (data[0] + 32) >> 6;
- /* check that value is in the range [-512,511] */
- if ((u32)(tmp0 + 512) > 1023)
- return(HANTRO_NOK);
- data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
- data[6] = data[7] = data[8] = data[9] = data[10] =
- data[11] = data[12] = data[13] = data[14] = data[15] =
- tmp0;
- }
- else /* at least one of the coeffs 1, 5 or 6 is non-zero */
- {
- data[1] = (data[1] * tmp2);
- data[2] = (data[5] * tmp1);
- data[3] = (data[6] * tmp2);
- tmp0 = data[0] + data[2];
- tmp1 = data[0] - data[2];
- tmp2 = (data[1] >> 1) - data[3];
- tmp3 = data[1] + (data[3] >> 1);
- data[0] = (tmp0 + tmp3 + 32)>>6;
- data[1] = (tmp1 + tmp2 + 32)>>6;
- data[2] = (tmp1 - tmp2 + 32)>>6;
- data[3] = (tmp0 - tmp3 + 32)>>6;
- data[4] = data[8] = data[12] = data[0];
- data[5] = data[9] = data[13] = data[1];
- data[6] = data[10] = data[14] = data[2];
- data[7] = data[11] = data[15] = data[3];
- /* check that each value is in the range [-512,511] */
- if (((u32)(data[0] + 512) > 1023) ||
- ((u32)(data[1] + 512) > 1023) ||
- ((u32)(data[2] + 512) > 1023) ||
- ((u32)(data[3] + 512) > 1023) )
- return(HANTRO_NOK);
- }
- }
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdProcessLumaDc
- Functional description:
- Function performs inverse zig-zag scan, inverse transform and
- inverse scaling for a luma DC coefficients block
- Inputs:
- data pointer to data to be processed
- qp quantization parameter
- Outputs:
- data processed data
- Returns:
- none
- ------------------------------------------------------------------------------*/
- void h264bsdProcessLumaDc(i32 *data, u32 qp)
- {
- /* Variables */
- i32 tmp0, tmp1, tmp2, tmp3;
- u32 row,col;
- u32 qpMod, qpDiv;
- i32 levScale;
- i32 *ptr;
- /* Code */
- qpMod = qpMod6[qp];
- qpDiv = qpDiv6[qp];
- /* zig-zag scan */
- tmp0 = data[2];
- data[2] = data[5];
- data[5] = data[4];
- data[4] = tmp0;
- tmp0 = data[8];
- data[8] = data[3];
- data[3] = data[6];
- data[6] = data[7];
- data[7] = data[12];
- data[12] = data[9];
- data[9] = tmp0;
- tmp0 = data[10];
- data[10] = data[11];
- data[11] = data[13];
- data[13] = tmp0;
- /* horizontal transform */
- for (row = 4, ptr = data; row--; ptr += 4)
- {
- tmp0 = ptr[0] + ptr[2];
- tmp1 = ptr[0] - ptr[2];
- tmp2 = ptr[1] - ptr[3];
- tmp3 = ptr[1] + ptr[3];
- ptr[0] = tmp0 + tmp3;
- ptr[1] = tmp1 + tmp2;
- ptr[2] = tmp1 - tmp2;
- ptr[3] = tmp0 - tmp3;
- }
- /*lint +e661 +e662*/
- /* then vertical transform and inverse scaling */
- levScale = levelScale[ qpMod ][0];
- if (qp >= 12)
- {
- levScale <<= (qpDiv-2);
- for (col = 4; col--; data++)
- {
- tmp0 = data[0] + data[8 ];
- tmp1 = data[0] - data[8 ];
- tmp2 = data[4] - data[12];
- tmp3 = data[4] + data[12];
- data[0 ] = ((tmp0 + tmp3)*levScale);
- data[4 ] = ((tmp1 + tmp2)*levScale);
- data[8 ] = ((tmp1 - tmp2)*levScale);
- data[12] = ((tmp0 - tmp3)*levScale);
- }
- }
- else
- {
- i32 tmp;
- tmp = ((1 - qpDiv) == 0) ? 1 : 2;
- for (col = 4; col--; data++)
- {
- tmp0 = data[0] + data[8 ];
- tmp1 = data[0] - data[8 ];
- tmp2 = data[4] - data[12];
- tmp3 = data[4] + data[12];
- data[0 ] = ((tmp0 + tmp3)*levScale+tmp) >> (2-qpDiv);
- data[4 ] = ((tmp1 + tmp2)*levScale+tmp) >> (2-qpDiv);
- data[8 ] = ((tmp1 - tmp2)*levScale+tmp) >> (2-qpDiv);
- data[12] = ((tmp0 - tmp3)*levScale+tmp) >> (2-qpDiv);
- }
- }
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdProcessChromaDc
- Functional description:
- Function performs inverse transform and inverse scaling for a
- chroma DC coefficients block
- Inputs:
- data pointer to data to be processed
- qp quantization parameter
- Outputs:
- data processed data
- Returns:
- none
- ------------------------------------------------------------------------------*/
- void h264bsdProcessChromaDc(i32 *data, u32 qp)
- {
- /* Variables */
- i32 tmp0, tmp1, tmp2, tmp3;
- u32 qpDiv;
- i32 levScale;
- u32 levShift;
- /* Code */
- qpDiv = qpDiv6[qp];
- levScale = levelScale[ qpMod6[qp] ][0];
- if (qp >= 6)
- {
- levScale <<= (qpDiv-1);
- levShift = 0;
- }
- else
- {
- levShift = 1;
- }
- tmp0 = data[0] + data[2];
- tmp1 = data[0] - data[2];
- tmp2 = data[1] - data[3];
- tmp3 = data[1] + data[3];
- data[0] = ((tmp0 + tmp3) * levScale) >> levShift;
- data[1] = ((tmp0 - tmp3) * levScale) >> levShift;
- data[2] = ((tmp1 + tmp2) * levScale) >> levShift;
- data[3] = ((tmp1 - tmp2) * levScale) >> levShift;
- tmp0 = data[4] + data[6];
- tmp1 = data[4] - data[6];
- tmp2 = data[5] - data[7];
- tmp3 = data[5] + data[7];
- data[4] = ((tmp0 + tmp3) * levScale) >> levShift;
- data[5] = ((tmp0 - tmp3) * levScale) >> levShift;
- data[6] = ((tmp1 + tmp2) * levScale) >> levShift;
- data[7] = ((tmp1 - tmp2) * levScale) >> levShift;
- }
- /*lint +e701 +e702 */