329 lines
11 KiB
C
329 lines
11 KiB
C
/******************************************************************************
|
|
*
|
|
* 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 ihevce_enc_sbh_funcs.c
|
|
*
|
|
* \brief
|
|
* This file contains utility functions for sbh
|
|
*
|
|
* \date
|
|
* 31/08/2012
|
|
*
|
|
* \author
|
|
* Ittiam
|
|
*
|
|
* List of Functions
|
|
* ihevce_sign_data_hiding()
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*****************************************************************************/
|
|
/* File Includes */
|
|
/*****************************************************************************/
|
|
/* System include files */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
|
|
/* User include files */
|
|
#include "ihevc_typedefs.h"
|
|
#include "itt_video_api.h"
|
|
#include "ihevce_api.h"
|
|
|
|
#include "rc_cntrl_param.h"
|
|
#include "rc_frame_info_collector.h"
|
|
#include "rc_look_ahead_params.h"
|
|
|
|
#include "ihevc_defs.h"
|
|
#include "ihevc_structs.h"
|
|
#include "ihevc_platform_macros.h"
|
|
#include "ihevc_deblk.h"
|
|
#include "ihevc_itrans_recon.h"
|
|
#include "ihevc_chroma_itrans_recon.h"
|
|
#include "ihevc_chroma_intra_pred.h"
|
|
#include "ihevc_intra_pred.h"
|
|
#include "ihevc_inter_pred.h"
|
|
#include "ihevc_mem_fns.h"
|
|
#include "ihevc_padding.h"
|
|
#include "ihevc_weighted_pred.h"
|
|
#include "ihevc_sao.h"
|
|
#include "ihevc_resi_trans.h"
|
|
#include "ihevc_quant_iquant_ssd.h"
|
|
#include "ihevc_cabac_tables.h"
|
|
#include "ihevc_trans_tables.h"
|
|
#include "ihevc_trans_macros.h"
|
|
|
|
#include "ihevce_defs.h"
|
|
#include "ihevce_lap_enc_structs.h"
|
|
#include "ihevce_multi_thrd_structs.h"
|
|
#include "ihevce_multi_thrd_funcs.h"
|
|
#include "ihevce_me_common_defs.h"
|
|
#include "ihevce_had_satd.h"
|
|
#include "ihevce_error_codes.h"
|
|
#include "ihevce_bitstream.h"
|
|
#include "ihevce_cabac.h"
|
|
#include "ihevce_rdoq_macros.h"
|
|
#include "ihevce_function_selector.h"
|
|
#include "ihevce_enc_structs.h"
|
|
#include "ihevce_global_tables.h"
|
|
#include "ihevce_enc_sbh_utils.h"
|
|
|
|
/*****************************************************************************/
|
|
/* Function Definitions */
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function find the coefficient that needs to be modified for SBH
|
|
* for each sub block, if required
|
|
*
|
|
* @par Description:
|
|
* Checks the validity for applying SBH
|
|
*
|
|
* @param[inout] ps_rdoq_sbh_params
|
|
* All the necessary parameters for SBH
|
|
*
|
|
* @returns None
|
|
*
|
|
* @remarks None
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void ihevce_sign_data_hiding(rdoq_sbh_ctxt_t *ps_rdoq_sbh_params)
|
|
{
|
|
WORD32 i, trans_unit_idx;
|
|
UWORD8 *pu1_trans_table = NULL;
|
|
UWORD8 *pu1_csb_table;
|
|
WORD32 shift_value, mask_value;
|
|
WORD32 blk_row, blk_col;
|
|
|
|
WORD32 x_pos, y_pos;
|
|
WORD16 i2_quant_coeff;
|
|
WORD32 best_pos = -1;
|
|
|
|
WORD16 *pi2_quant_coeffs = ps_rdoq_sbh_params->pi2_quant_coeffs;
|
|
WORD16 *pi2_iquant_data = ps_rdoq_sbh_params->pi2_iquant_coeffs;
|
|
WORD16 *pi2_tr_coeffs = ps_rdoq_sbh_params->pi2_trans_values;
|
|
WORD32 *pi4_subBlock2csbfId_map = ps_rdoq_sbh_params->pi4_subBlock2csbfId_map;
|
|
WORD16 *pi2_dequant_coeff = ps_rdoq_sbh_params->pi2_dequant_coeff;
|
|
UWORD8 *pu1_csbf_buf = ps_rdoq_sbh_params->pu1_csbf_buf;
|
|
WORD32 dst_iq_strd = ps_rdoq_sbh_params->i4_iq_data_strd;
|
|
WORD32 dst_q_strd = ps_rdoq_sbh_params->i4_q_data_strd;
|
|
|
|
WORD32 scan_idx = ps_rdoq_sbh_params->i4_scan_idx;
|
|
WORD32 qp_div = ps_rdoq_sbh_params->i4_qp_div;
|
|
WORD32 trans_size = ps_rdoq_sbh_params->i4_trans_size;
|
|
WORD32 qp_rem = ps_rdoq_sbh_params->i2_qp_rem;
|
|
LWORD64 ssd_cost = ps_rdoq_sbh_params->i8_ssd_cost;
|
|
|
|
WORD32 last_cg = -1;
|
|
|
|
WORD32 log2_size, bit_depth, shift_iq;
|
|
|
|
GETRANGE(log2_size, trans_size);
|
|
log2_size -= 1;
|
|
bit_depth = ps_rdoq_sbh_params->i4_bit_depth;
|
|
shift_iq = bit_depth + log2_size - 5;
|
|
|
|
/* Select proper order for your transform unit and csb based on scan_idx*/
|
|
/* and the trans_size */
|
|
|
|
/* scan order inside a csb */
|
|
pu1_csb_table = (UWORD8 *)&(g_u1_scan_table_4x4[scan_idx][0]);
|
|
|
|
/* GETRANGE will give the log_2 of trans_size to shift_value */
|
|
GETRANGE(shift_value, trans_size);
|
|
shift_value = shift_value - 3; /* for finding. row no. from scan index */
|
|
mask_value = (trans_size / 4) - 1; /*for finding the col. no. from scan index*/
|
|
switch(trans_size)
|
|
{
|
|
case 32:
|
|
pu1_trans_table = (UWORD8 *)&(g_u1_scan_table_8x8[scan_idx][0]);
|
|
break;
|
|
case 16:
|
|
pu1_trans_table = (UWORD8 *)&(g_u1_scan_table_4x4[scan_idx][0]);
|
|
break;
|
|
case 8:
|
|
pu1_trans_table = (UWORD8 *)&(g_u1_scan_table_2x2[scan_idx][0]);
|
|
break;
|
|
case 4:
|
|
pu1_trans_table = (UWORD8 *)&(g_u1_scan_table_1x1[0]);
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
for(trans_unit_idx = (trans_size * trans_size / 16) - 1; trans_unit_idx >= 0; trans_unit_idx--)
|
|
{
|
|
WORD32 last_scan_pos = -1, first_scan_pos = 16, sign_first_coeff, sum_abs_level = 0,
|
|
quant_coeff_first;
|
|
|
|
if(pu1_csbf_buf[pi4_subBlock2csbfId_map[pu1_trans_table[trans_unit_idx]]])
|
|
{
|
|
/* row of csb */
|
|
blk_row = (pu1_trans_table[trans_unit_idx] >> shift_value) * 4;
|
|
/* col of csb */
|
|
blk_col = (pu1_trans_table[trans_unit_idx] & mask_value) * 4;
|
|
|
|
if(last_cg == -1)
|
|
{
|
|
last_cg = 1;
|
|
}
|
|
|
|
for(i = 15; i >= 0; i--)
|
|
{
|
|
x_pos = (pu1_csb_table[i] & 0x3) + blk_col;
|
|
y_pos = (pu1_csb_table[i] >> 2) + blk_row;
|
|
|
|
i2_quant_coeff = pi2_quant_coeffs[x_pos + (y_pos * trans_size)];
|
|
|
|
if(i2_quant_coeff)
|
|
{
|
|
first_scan_pos = i;
|
|
if(-1 == last_scan_pos)
|
|
{
|
|
last_scan_pos = i;
|
|
}
|
|
|
|
sum_abs_level += abs(i2_quant_coeff);
|
|
}
|
|
}
|
|
|
|
if((last_scan_pos - first_scan_pos) >= 4)
|
|
{
|
|
x_pos = (pu1_csb_table[first_scan_pos] & 0x3) + blk_col;
|
|
y_pos = (pu1_csb_table[first_scan_pos] >> 2) + blk_row;
|
|
|
|
quant_coeff_first = pi2_quant_coeffs[x_pos + (y_pos * trans_size)];
|
|
|
|
sign_first_coeff = (quant_coeff_first > 0) ? 0 : 1;
|
|
|
|
if(sign_first_coeff != (sum_abs_level & 0x1))
|
|
{
|
|
WORD32 q_err;
|
|
WORD32 min_cost = MAX_INT;
|
|
WORD32 final_change = 0, cur_cost = 0, cur_change = 0;
|
|
WORD16 i2_tr_coeff;
|
|
WORD16 i2_iquant_coeff;
|
|
|
|
for(i = (last_cg == 1) ? last_scan_pos : 15; i >= 0; i--)
|
|
{
|
|
x_pos = (pu1_csb_table[i] & 0x3) + blk_col;
|
|
y_pos = (pu1_csb_table[i] >> 2) + blk_row;
|
|
|
|
i2_quant_coeff = pi2_quant_coeffs[x_pos + (y_pos * trans_size)];
|
|
i2_tr_coeff = pi2_tr_coeffs[x_pos + (y_pos * trans_size)];
|
|
i2_iquant_coeff = pi2_iquant_data[x_pos + (y_pos * dst_iq_strd)];
|
|
|
|
q_err = abs(i2_tr_coeff) - abs(i2_iquant_coeff);
|
|
|
|
if(i2_quant_coeff != 0)
|
|
{
|
|
cur_cost = -1 * SIGN(q_err) * q_err;
|
|
|
|
if(q_err <= 0)
|
|
{
|
|
if(i == first_scan_pos && abs(i2_quant_coeff) == 1)
|
|
{
|
|
cur_cost = MAX_INT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cur_cost = -q_err;
|
|
if(i < first_scan_pos)
|
|
{
|
|
WORD32 sign_bit = (i2_tr_coeff >= 0 ? 0 : 1);
|
|
|
|
if(sign_first_coeff != sign_bit)
|
|
{
|
|
cur_cost = MAX_INT;
|
|
}
|
|
}
|
|
}
|
|
|
|
cur_change = (i2_quant_coeff == 0) ? 1 : (q_err > 0 ? 1 : -1);
|
|
|
|
if(cur_cost < min_cost)
|
|
{
|
|
min_cost = cur_cost;
|
|
final_change = cur_change;
|
|
best_pos = i;
|
|
}
|
|
}
|
|
if((i2_quant_coeff == 32767) || (i2_quant_coeff == -32768))
|
|
{
|
|
final_change = -1;
|
|
}
|
|
|
|
x_pos = (pu1_csb_table[best_pos] & 0x3) + blk_col;
|
|
y_pos = (pu1_csb_table[best_pos] >> 2) + blk_row;
|
|
i2_iquant_coeff = pi2_iquant_data[x_pos + (y_pos * dst_iq_strd)];
|
|
i2_tr_coeff = pi2_tr_coeffs[x_pos + (y_pos * trans_size)];
|
|
|
|
if(i2_tr_coeff >= 0)
|
|
{
|
|
pi2_quant_coeffs[x_pos + (y_pos * trans_size)] += final_change;
|
|
}
|
|
else
|
|
{
|
|
pi2_quant_coeffs[x_pos + (y_pos * trans_size)] -= final_change;
|
|
}
|
|
|
|
{
|
|
WORD32 i4_err1, i4_err2;
|
|
|
|
/* Inverse Quantization */
|
|
IQUANT(
|
|
pi2_iquant_data[y_pos * dst_iq_strd + x_pos],
|
|
pi2_quant_coeffs[y_pos * dst_q_strd + x_pos],
|
|
pi2_dequant_coeff[y_pos * trans_size + x_pos] *
|
|
g_ihevc_iquant_scales[qp_rem],
|
|
shift_iq,
|
|
qp_div);
|
|
|
|
i4_err1 = (i2_tr_coeff - i2_iquant_coeff);
|
|
i4_err1 = i4_err1 * i4_err1;
|
|
ssd_cost = ssd_cost - i4_err1;
|
|
i4_err2 = (i2_tr_coeff - pi2_iquant_data[y_pos * dst_iq_strd + x_pos]);
|
|
i4_err2 = i4_err2 * i4_err2;
|
|
ssd_cost = ssd_cost + i4_err2;
|
|
}
|
|
}
|
|
}
|
|
if(last_cg == 1)
|
|
{
|
|
last_cg = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
ps_rdoq_sbh_params->i8_ssd_cost = ssd_cost;
|
|
}
|