blob: 4eb6dd09013f60fc37803a5a708eb71aa3ec63f9 [file] [log] [blame]
/*
* 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 */