blob: 986bbb78d006fc74d08798b87f0f303bd5ea9416 [file]
/******************************************************************************
* *
* Copyright (C) 2023 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
*/
#include <math.h>
#include <stdlib.h>
#include "ixheaac_type_def.h"
#include "ixheaac_constants.h"
#include "ixheaace_aac_constants.h"
#include "ixheaac_error_standards.h"
#include "ixheaace_error_codes.h"
#include "ixheaace_psy_const.h"
#include "ixheaace_tns.h"
#include "ixheaace_tns_params.h"
#include "ixheaace_rom.h"
#include "ixheaace_common_rom.h"
#include "ixheaace_quant.h"
#include "ixheaace_block_switch.h"
#include "ixheaace_bitbuffer.h"
#include "ixheaac_basic_ops32.h"
#include "ixheaac_basic_ops16.h"
#include "ixheaac_basic_ops40.h"
#include "ixheaac_basic_ops.h"
#include "ixheaace_tns.h"
#include "ixheaace_psy_data.h"
#include "ixheaace_interface.h"
#include "ixheaace_adjust_threshold_data.h"
#include "ixheaace_dynamic_bits.h"
#include "ixheaace_qc_data.h"
#include "ixheaace_adjust_threshold.h"
#include "ixheaace_sf_estimation.h"
#include "ixheaace_static_bits.h"
#include "ixheaace_bits_count.h"
#include "ixheaace_channel_map.h"
#include "ixheaace_write_bitstream.h"
#include "ixheaace_psy_configuration.h"
#include "ixheaace_psy_mod.h"
#include "ixheaace_tns_params.h"
#include "ixheaace_stereo_preproc.h"
#include "ixheaace_enc_main.h"
#include "ixheaace_qc_util.h"
#include "ixheaace_common_utils.h"
IA_ERRORCODE ia_enhaacplus_enc_qc_main(
ixheaace_qc_state *pstr_qc_state, WORD32 num_channels, ixheaace_element_bits *pstr_el_bits,
ixheaace_psy_out_channel **psy_out_ch,
ixheaace_psy_out_element *pstr_psy_out_element,
ixheaace_qc_out_channel **pstr_qc_out_ch,
ixheaace_qc_out_element *pstr_qc_out_element, WORD32 ancillary_data_bytes,
ixheaace_aac_tables *pstr_aac_tables, WORD32 adts_flag, WORD32 aot, WORD32 stat_bits_flag,
WORD32 flag_last_element, WORD32 frame_len_long, WORD8 *ptr_scratch,
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited) {
IA_ERRORCODE err_code;
WORD32 ch;
WORD32 i = 0;
WORD32 k = 0;
WORD32 j = 0;
WORD32 iterations = 0;
WORD32 constraints_fulfilled;
WORD32 ch_dyn_bits;
WORD32 max_ch_dyn_bits[IXHEAACE_MAX_CH_IN_BS_ELE];
FLOAT32 ch_bit_dist[IXHEAACE_MAX_CH_IN_BS_ELE];
ixheaace_qc_stack *ptr_stack = (ixheaace_qc_stack *)ptr_scratch;
ptr_scratch += sizeof(ixheaace_qc_stack);
ia_adj_thr_elem_struct *pstr_adj_thr_elem = &pstr_qc_state->str_adj_thr.str_adj_thr_ele;
WORD32 gain;
if (pstr_el_bits->bit_res_level < 0) {
return IA_EXHEAACE_EXE_FATAL_INVALID_BIT_RES_LEVEL;
}
if (pstr_el_bits->bit_res_level > pstr_el_bits->max_bit_res_bits) {
return IA_EXHEAACE_EXE_FATAL_INVALID_BIT_RES_LEVEL;
}
pstr_qc_out_element->static_bits_used =
ia_enhaacplus_enc_count_static_bitdemand(psy_out_ch, pstr_psy_out_element, num_channels,
aot, adts_flag, stat_bits_flag, flag_last_element);
if (ancillary_data_bytes) {
pstr_qc_out_element->anc_bits_used =
7 + 8 * (ancillary_data_bytes + (ancillary_data_bytes >= 15));
} else {
pstr_qc_out_element->anc_bits_used = 0;
}
for (ch = 0; ch < num_channels; ch++) {
iaace_calc_form_fac_per_chan(ptr_stack->sfb_form_fac[ch],
ptr_stack->sfb_num_relevant_lines[ch], psy_out_ch[ch],
ptr_stack->sfb_ld_energy[ch]);
}
iaace_adjust_threshold(
&pstr_qc_state->str_adj_thr, pstr_adj_thr_elem, psy_out_ch, ch_bit_dist,
pstr_qc_out_element,
pstr_el_bits->average_bits - pstr_qc_out_element->static_bits_used -
pstr_qc_out_element->anc_bits_used,
pstr_el_bits->bit_res_level, pstr_el_bits->max_bit_res_bits,
pstr_qc_out_element->static_bits_used + pstr_qc_out_element->anc_bits_used,
&pstr_qc_state->max_bit_fac, ptr_stack->sfb_num_relevant_lines[0],
ptr_stack->sfb_ld_energy[0], num_channels, 0, aot, ptr_scratch);
iaace_estimate_scfs_chan(psy_out_ch, pstr_qc_out_ch, ptr_stack->sfb_form_fac,
ptr_stack->sfb_num_relevant_lines, num_channels, 0, frame_len_long);
for (ch = 0; ch < num_channels; ch++) {
max_ch_dyn_bits[ch] =
(pstr_el_bits->average_bits + pstr_el_bits->bit_res_level - 7 -
pstr_qc_out_element->static_bits_used - pstr_qc_out_element->anc_bits_used);
max_ch_dyn_bits[ch] = (WORD32)floor(ch_bit_dist[ch] * (FLOAT32)(max_ch_dyn_bits[ch]));
}
pstr_qc_out_element->dyn_bits_used = 0;
for (ch = 0; ch < num_channels; ch++) {
/* now loop until bitstream constraints (ch_dyn_bits < maxChDynBits)
are fulfilled */
WORD32 spec_idx, sfb_offs, sfb;
iterations = 0;
gain = 0;
for (spec_idx = 0; spec_idx < frame_len_long; spec_idx++) {
ptr_stack->exp_spec[spec_idx] = (FLOAT32)psy_out_ch[ch]->ptr_spec_coeffs[spec_idx];
ptr_stack->mdct_spec_float[spec_idx] = (FLOAT32)psy_out_ch[ch]->ptr_spec_coeffs[spec_idx];
}
do {
WORD32 max_val;
constraints_fulfilled = 1;
WORD32 quant_spec_is_zero = 1;
if (iterations > 0) {
for (sfb_offs = 0; sfb_offs < psy_out_ch[ch]->sfb_count;
sfb_offs += psy_out_ch[ch]->sfb_per_group) {
for (sfb = 0; sfb < psy_out_ch[ch]->max_sfb_per_grp; sfb++) {
WORD32 scalefactor = pstr_qc_out_ch[ch]->scalefactor[sfb + sfb_offs];
gain = MAX(gain, pstr_qc_out_ch[ch]->global_gain - scalefactor);
iaace_quantize_lines(
pstr_qc_out_ch[ch]->global_gain - scalefactor,
psy_out_ch[ch]->sfb_offsets[sfb_offs + sfb + 1] -
psy_out_ch[ch]->sfb_offsets[sfb_offs + sfb],
ptr_stack->exp_spec + psy_out_ch[ch]->sfb_offsets[sfb_offs + sfb],
pstr_qc_out_ch[ch]->quant_spec + psy_out_ch[ch]->sfb_offsets[sfb_offs + sfb],
ptr_stack->mdct_spec_float + psy_out_ch[ch]->sfb_offsets[sfb_offs + sfb]);
}
}
}
max_val = iaace_calc_max_val_in_sfb(
psy_out_ch[ch]->sfb_count, psy_out_ch[ch]->max_sfb_per_grp,
psy_out_ch[ch]->sfb_per_group,
psy_out_ch[ch]->sfb_offsets, pstr_qc_out_ch[ch]->quant_spec,
pstr_qc_out_ch[ch]->max_val_in_sfb);
if (max_val > MAXIMUM_QUANT) {
constraints_fulfilled = 0;
}
for (k = 0; ((k < psy_out_ch[ch]->sfb_count) && (quant_spec_is_zero));
k += psy_out_ch[ch]->sfb_per_group) {
for (i = 0; ((i < psy_out_ch[ch]->max_sfb_per_grp) && (quant_spec_is_zero)); i++) {
for (j = psy_out_ch[ch]->sfb_offsets[i+k]; j < psy_out_ch[ch]->sfb_offsets[i+k+1]; j++)
{
if (pstr_qc_out_ch[ch]->quant_spec[j] != 0) {
quant_spec_is_zero = 0;
break;
}
}
}
}
err_code = ia_enhaacplus_enc_dyn_bitcount(
pstr_qc_out_ch[ch]->quant_spec, pstr_qc_out_ch[ch]->max_val_in_sfb,
pstr_qc_out_ch[ch]->scalefactor, psy_out_ch[ch]->window_sequence,
psy_out_ch[ch]->sfb_count, psy_out_ch[ch]->max_sfb_per_grp,
psy_out_ch[ch]->sfb_per_group,
psy_out_ch[ch]->sfb_offsets, &pstr_qc_out_ch[ch]->section_data,
pstr_qc_state->side_info_tab_long, pstr_qc_state->side_info_tab_short,
pstr_aac_tables->pstr_huff_tab, pstr_qc_state->qc_scr.shared_buffer_2, aot,
&ch_dyn_bits);
if (err_code != IA_NO_ERROR) {
return err_code;
}
if (ch_dyn_bits >= max_ch_dyn_bits[ch]) {
constraints_fulfilled = 0;
}
if (quant_spec_is_zero == 1) {
constraints_fulfilled = 1;
/*Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as spectrum is zero. Hence breaking the quantization loop. */
if (iterations > 0) {
*is_quant_spec_zero = 1;
ch_dyn_bits = max_ch_dyn_bits[ch];
}
}
if ((gain == MAX_GAIN_INDEX) && (constraints_fulfilled == 0)) {
/* Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as gain has reached the maximum value. Hence breaking the quantization
loop. */
constraints_fulfilled = 1;
*is_gain_limited = 1;
ch_dyn_bits = max_ch_dyn_bits[ch];
}
if (!constraints_fulfilled) {
pstr_qc_out_ch[ch]->global_gain++;
}
iterations++;
} while (!constraints_fulfilled);
pstr_qc_out_element->dyn_bits_used += ch_dyn_bits;
pstr_qc_out_ch[ch]->grouping_mask = psy_out_ch[ch]->grouping_mask;
pstr_qc_out_ch[ch]->win_shape = psy_out_ch[ch]->window_shape;
}
pstr_adj_thr_elem->dyn_bits_last = pstr_qc_out_element->dyn_bits_used;
{
WORD32 bit_res_space = pstr_el_bits->max_bit_res_bits - pstr_el_bits->bit_res_level;
WORD32 delta_bit_res = pstr_el_bits->average_bits - (pstr_qc_out_element->static_bits_used +
pstr_qc_out_element->dyn_bits_used +
pstr_qc_out_element->anc_bits_used);
pstr_qc_out_element->fill_bits = MAX(0, (delta_bit_res - bit_res_space));
}
return IA_NO_ERROR;
}
WORD32 iaace_calc_max_val_in_sfb(WORD32 sfb_count, WORD32 max_sfb_per_grp, WORD32 ptr_sfb_per_grp,
WORD32 *ptr_sfb_offset, WORD16 *ptr_quant_spec,
UWORD16 *ptr_max_value) {
WORD32 sfb;
WORD32 max = 0;
WORD32 sfb_offs;
for (sfb_offs = 0; sfb_offs < sfb_count; sfb_offs += ptr_sfb_per_grp) {
for (sfb = 0; sfb < max_sfb_per_grp; sfb++) {
WORD32 line;
WORD32 local_max = 0;
for (line = ptr_sfb_offset[sfb + sfb_offs]; line < ptr_sfb_offset[sfb + sfb_offs + 1];
line++) {
if (abs(ptr_quant_spec[line]) > local_max) {
local_max = abs(ptr_quant_spec[line]);
}
}
ptr_max_value[sfb_offs + sfb] = (UWORD16)local_max;
if (local_max > max) {
max = local_max;
}
}
}
return max;
}