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