blob: 50a0e088637caedc1f2f9b1fd0fdf8675e23d1ee [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2018 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.
*
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
/**
*******************************************************************************
* @file
* ihevc_quant_iquant_ssd.c
*
* @brief
* Contains function definitions for quantization, followed by Inverse
* quantization to find transform domain SSD
*
* @author
* 100453, 100578
*
* @par List of Functions:
* - ihevc_quant_iquant_ssd()
* - ihevc_quant_iquant_ssd_flat_scale_mat()
*
* @remarks
* None
*
*******************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ihevc_typedefs.h"
#include "ihevc_macros.h"
#include "ihevc_platform_macros.h"
#include "ihevc_defs.h"
#include "ihevc_debug.h"
#include "ihevc_trans_tables.h"
#include "ihevc_quant_iquant_ssd.h"
#include "ihevc_func_selector.h"
#include "ihevc_trans_macros.h"
#include <assert.h>
/*****************************************************************************/
/* Globals */
/*****************************************************************************/
/**
*******************************************************************************
*
* @brief
* This function performs quantization, followed by Inverse
* quantization to find transform domain SSD
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_quant_iquant_ssd
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
WORD32 ssd_cost = 0;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/* Quantization */
QUANT(pi2_q_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
/*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization, followed by Inverse
* quantization
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_quant_iquant
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)pi8_cost;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/* Quantization */
QUANT(pi2_q_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
shift_iq,
qp_div);
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization, followed by Inverse
* quantization to find transform domain SSD
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_quant_iquant_ssd_rdoq
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
WORD32 ssd_cost = 0;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/* Quantization */
QUANT(pi2_q_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
if (abs(pi2_q_dst[j]) > 1)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
/*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
WORD32 ihevc_quant_iquant_rdoq
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)pi8_cost;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/* Quantization */
QUANT(pi2_q_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
if (abs(pi2_q_dst[j]) > 1)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
shift_iq,
qp_div);
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization(using flat scale matrix), followed by
* inverse quantization to find transform domain SSD
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_quant_iquant_ssd_flat_scale_mat
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
/* Initialize cost to zero */
WORD32 ssd_cost = 0;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/*QUANT(pi2_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);*/
/* modified by 1028 */
/* Quantization */
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
if(pi2_q_dst[j] == 0)
{
pi2_iq_dst[j] = 0;
}
else
{
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem], /*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
}
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
WORD32 ihevc_quant_iquant_flat_scale_mat
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)pi8_cost;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/* Quantization */
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
if(pi2_q_dst[j] == 0)
{
pi2_iq_dst[j] = 0;
}
else
{
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem], /*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
}
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization(using flat scale matrix), followed by
* inverse quantization to find transform domain SSD; when we perform RDOQ.
* In case the quantized value turns out to be grater than 1, we then requantize
* use half rounding.
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_quant_iquant_ssd_flat_scale_mat_rdoq
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
/* Initialize cost to zero */
WORD32 ssd_cost = 0;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
WORD16 i2_temp1;
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/*QUANT(pi2_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);*/
/* modified by 1028 */
/* Quantization */
if (1)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
}
else
{ \
WORD16 inp = pi2_coeffs[j],out = pi2_q_dst[j];
WORD32 quant_coeff = g_ihevc_quant_scales[qp_rem];
WORD32 log2_trans_size = log2_size;
WORD32 tmp; \
WORD32 sign; \
WORD32 bit_depth,transform_shift; \
WORD32 q_bits, quant_multiplier; \
\
/* q_bits and q_add calculation*/ \
/* To be moved outside in neon. To be computer once per transform call */ \
bit_depth = 8; \
transform_shift = MAX_TR_DYNAMIC_RANGE - bit_depth - log2_trans_size; \
quant_multiplier = 4 ; /* because quant_coeff are multiplied by 16. Instead of multiplying, we can reduce the division factor q_bits by 4 */ \
q_bits = QUANT_SHIFT + qp_div + transform_shift + SCALING_Q_SHIFT - quant_multiplier - FLAT_RESCALE_MAT_Q_SHIFT /* 2048 */; \
\
sign = (inp)<0 ? -1:1; \
\
tmp = (WORD32)(abs(inp)); \
tmp = tmp * (quant_coeff); \
tmp = tmp + (((WORD32)q_add) << (q_bits - QUANT_ROUND_FACTOR_Q)); \
tmp = tmp >> q_bits; \
\
tmp = tmp * sign; \
out = (WORD16) CLIP_S16(tmp); \
}
i2_temp1 = pi2_q_dst[j];
if (abs(pi2_q_dst[j]) > 1)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], i2_temp,
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
ASSERT(abs(i2_temp1-pi2_q_dst[j]) <= 1);
ASSERT(abs(i2_temp1) <= abs(pi2_q_dst[j]));
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem], /*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
WORD32 ihevc_quant_iquant_flat_scale_mat_rdoq
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)pi8_cost;
(void)pi4_quant_round_factor_0_1;
(void)pi4_quant_round_factor_1_2;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
WORD16 i2_temp1;
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);
i2_temp1 = pi2_q_dst[j];
if (abs(pi2_q_dst[j]) > 1)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], i2_temp,
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
ASSERT(abs(i2_temp1-pi2_q_dst[j]) <= 1);
ASSERT(abs(i2_temp1) <= abs(pi2_q_dst[j]));
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem], /*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization, followed by Inverse
* quantization to find transform domain SSD
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_q_iq_ssd_var_rnd_fact
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
//WORD16 i2_temp_1;
/* Initialize cost to zero */
WORD32 ssd_cost = 0;
(void)q_add;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
{
/* Quantization */
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, 0);
if (abs(pi2_q_dst[j]) >= 2)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
else if (abs(pi2_q_dst[j]) >= 1)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_1_2);
}
else
{
/* Quantization */
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_0_1);
}
}
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
/*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
pi4_quant_round_factor_0_1++;
pi4_quant_round_factor_1_2++;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
WORD32 ihevc_q_iq_var_rnd_fact
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)q_add;
(void)pi8_cost;
pi2_q_dst_orig = pi2_q_dst;
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
i2_temp = pi2_coeffs[j];
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, 0);
if (abs(pi2_q_dst[j]) >= 2)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
else if (abs(pi2_q_dst[j]) >= 1)
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_1_2);
}
else
{
QUANT(pi2_q_dst[j],i2_temp,
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_0_1);
}
}
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
shift_iq,
qp_div);
pi4_quant_round_factor_0_1++;
pi4_quant_round_factor_1_2++;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
/**
*******************************************************************************
*
* @brief
* This function performs quantization(using flat scale matrix), followed by
* inverse quantization to find transform domain SSD; when we perform RDOQ.
* In case the quantized value turns out to be grater than 1, we then requantize
* use half rounding.
*
* @par Description:
* Performs quantization on coeffs
*
* @param[in] pi2_coeffs
* 4x4 Coeffs
*
* @param[in] pi2_quant_coeff
* Scaling Matrix
*
* @param[out] pi2_dst
* Output 4x4 coefficients
*
* @param[in] qp_div
* Quantization parameter / 6
*
* @param[in] qp_rem
* Quantization parameter % 6
*
* @param[in] src_strd
* Input stride
*
* @param[in] dst_strd
* Output Stride
*
* @param[out] csbf
* coded sub block flag
*
* @param[in] csbf_strd
* coded sub block flag
*
* @param[out] zero_col
* zero column flag
*
* @param[out] zero_row
* zero column flag
*
* @returns cbf
* coded block flag
*
* @remarks
* None
*
*******************************************************************************
*/
WORD32 ihevc_q_iq_ssd_flat_scale_mat_var_rnd_fact
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD32 val;
WORD16 i2_temp;
/* Initialize cost to zero */
WORD32 ssd_cost = 0;
(void)q_add;
pi2_q_dst_orig = pi2_q_dst;
/* Quant initialization */
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
WORD16 i2_temp1;
/* Back up the coefficients before Quantization */
i2_temp = pi2_coeffs[j];
/*QUANT(pi2_dst[j], pi2_coeffs[j],
pi2_quant_coeff[j] * g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, q_add);*/
/* modified by 1028 */
/* Quantization */
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, 0);
i2_temp1 = pi2_q_dst[j];
if (abs(pi2_q_dst[j]) >= 2)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], i2_temp,
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
else if (abs(pi2_q_dst[j]) >= 1)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_1_2);
}
else
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_0_1);
}
}
ASSERT(abs(i2_temp1-pi2_q_dst[j]) <= 1);
/* Inverse Quantization */
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem], /*pi2_dequant_coeff[index*trans_size] * g_ihevc_iquant_scales[qp_rem] */
shift_iq,
qp_div);
/* SSD Computation & Accumulation */
val = i2_temp - pi2_iq_dst[j];
ssd_cost += val*val;
pi4_quant_round_factor_0_1++;
pi4_quant_round_factor_1_2++;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* Store the cost */
*pi8_cost = ssd_cost;
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}
WORD32 ihevc_q_iq_flat_scale_mat_var_rnd_fact
(
WORD16 *pi2_coeffs,
WORD16 *pi2_quant_coeff,
WORD16 *pi2_q_dst,
WORD16 *pi2_iq_dst,
WORD32 trans_size,
WORD32 qp_div,/* qpscaled / 6 */
WORD32 qp_rem,/* qpscaled % 6 */
WORD32 q_add,
WORD32 *pi4_quant_round_factor_0_1,
WORD32 *pi4_quant_round_factor_1_2,
WORD32 src_strd,
WORD32 dst_q_strd,
WORD32 dst_iq_strd,
UWORD8 *csbf,
WORD32 csbf_strd,
WORD32 *zero_col,
WORD32 *zero_row,
WORD16 *pi2_dequant_coeff,
LWORD64 *pi8_cost
)
{
WORD32 i, j;
WORD32 log2_size;
WORD16 *pi2_q_dst_orig;
WORD32 cbf = 0;
WORD32 bit_depth,shift_iq;
WORD16 i2_temp;
(void)q_add;
(void)pi8_cost;
pi2_q_dst_orig = pi2_q_dst;
GETRANGE(log2_size, trans_size);
log2_size -= 1;
bit_depth = 8 + 0;
shift_iq = bit_depth + log2_size - 5;
for(i = 0; i < trans_size; i++)
{
for(j = 0; j < trans_size; j++)
{
WORD16 i2_temp1;
i2_temp = pi2_coeffs[j];
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, 0);
i2_temp1 = pi2_q_dst[j];
if (abs(pi2_q_dst[j]) >= 2)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], i2_temp,
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, ((1 << QUANT_ROUND_FACTOR_Q)/2));
}
else if (abs(pi2_q_dst[j]) >= 1)
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_1_2);
}
else
{
QUANT_NO_WEIGHTMAT(pi2_q_dst[j], pi2_coeffs[j],
g_ihevc_quant_scales[qp_rem], qp_div,
log2_size, *pi4_quant_round_factor_0_1);
}
}
ASSERT(abs(i2_temp1-pi2_q_dst[j]) <= 1);
IQUANT(pi2_iq_dst[j],
pi2_q_dst[j], /*pi2_src[index*src_strd]*/
pi2_dequant_coeff[j]*g_ihevc_iquant_scales[qp_rem],
shift_iq,
qp_div);
pi4_quant_round_factor_0_1++;
pi4_quant_round_factor_1_2++;
}
pi2_q_dst += dst_q_strd;
pi2_iq_dst += dst_iq_strd;
pi2_quant_coeff += trans_size;
pi2_coeffs += src_strd;
pi2_dequant_coeff += trans_size;
}
/* CSBF update */
{
WORD32 block_row, block_col;
WORD32 row, col;
WORD16 *pi2_block;
UWORD32 temp_zero_col = 0;
UWORD32 temp_zero_row = 0;
pi2_q_dst = pi2_q_dst_orig;
for(block_row = 0; block_row < trans_size; block_row += 4)
{
//block_col is incrementing by 1 for easy update of csbf pointer
for(block_col = 0; block_col < trans_size / 4; block_col++)
{
pi2_block = pi2_q_dst + block_row * dst_q_strd + block_col * 4;
*(csbf + block_col) = 0;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(pi2_block[row * dst_q_strd + col] != 0)
{
*(csbf + block_col) = 1;
break;
}
}
if(*(csbf + block_col) == 1)
{
/* zero_col update *//* temp_zero_col = ~zero_col */
temp_zero_col = (temp_zero_col) | (0xFU << block_col * 4);
// zero col can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 colums of 4x4 block
// even if any 4x4 csbf is set
/* zero row update */ /* temp_zero_row = ~zero_row */
temp_zero_row = (temp_zero_row) | (0xFU << block_row);
// zero row can be optimized further. Now clearing the
// entire 4 bits corresponding to 4 rows of 4x4 block
// even if any 4x4 csbf is set
break;
}
}
cbf = cbf || (*(csbf + block_col)); // cbf update
}
csbf += csbf_strd;
}
*zero_col = ~temp_zero_col; //final zero_col storing
*zero_row = ~temp_zero_row; //final zero_row storing
}
return cbf;
}