/****************************************************************************** * * * 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 "ixheaac_type_def.h" #include "ixheaace_sbr_header.h" #include "ixheaace_sbr_def.h" #include "ixheaace_resampler.h" #include "ixheaace_sbr_rom.h" #include "ixheaace_common_rom.h" #include "ixheaace_bitbuffer.h" #include "ixheaace_sbr_main.h" #include "ixheaace_sbr_hybrid.h" #include "ixheaace_sbr_ps_enc.h" #include "ixheaace_sbr_ps_bitenc.h" #include "ixheaace_env_bit.h" static WORD32 iexheaax_append_bitstream(ixheaace_bit_buf_handle hdl_bitbuf_write, ixheaace_bit_buf_handle hdl_bitbuf_read, UWORD8 num_bits) { WORD32 idx; UWORD32 value; if (num_bits > 16) { WORD32 cnt; UWORD8 rem; cnt = num_bits >> 4; rem = num_bits % 16; for (idx = 0; idx < cnt; idx++) { value = ixheaace_readbits(hdl_bitbuf_read, 16); ixheaace_write_bits(hdl_bitbuf_write, value, 16); } if (rem) { value = ixheaace_readbits(hdl_bitbuf_read, rem); ixheaace_write_bits(hdl_bitbuf_write, value, rem); } } else { value = ixheaace_readbits(hdl_bitbuf_read, num_bits); ixheaace_write_bits(hdl_bitbuf_write, value, num_bits); } return num_bits; } WORD32 ixheaace_enc_write_ps_data(ixheaace_pstr_ps_enc pstr_ps_handle, WORD32 b_header_active, ixheaace_str_ps_tab *ps_tables) { WORD32 tmp_var, gr; const WORD32 *aa_huff_book_iid_c; const WORD16 *aa_huff_book_icc_c; const WORD8 *aa_huff_book_iid_l; const WORD8 *aa_huff_book_icc_l; WORD32 *aa_delta_iid; WORD32 *aa_delta_icc; WORD8 index, last_index; WORD32 no_bits_f = 0; WORD32 no_bits_t = 0; WORD32 aa_delta_iid_t[NUMBER_OF_IID_BINS] = {0}; WORD32 aa_delta_icc_t[NUMBER_OF_ICC_BINS] = {0}; WORD32 aa_delta_iid_f[NUMBER_OF_IID_BINS] = {0}; WORD32 aa_delta_icc_f[NUMBER_OF_ICC_BINS] = {0}; WORD32 ab_dt_flag_iid; WORD32 ab_dt_flag_icc; WORD32 b_send_header; UWORD32 b_zero_iid = 1; UWORD32 b_zero_icc = 1; UWORD32 b_keep_params = 1; ixheaace_bit_buf_handle bb = &pstr_ps_handle->ps_bit_buf; tmp_var = ia_enhaacplus_enc_get_bits_available(bb); /* bit buffer shall be empty */ if (tmp_var != 0) { return -1; } if (b_header_active) { b_keep_params = 0; } last_index = 0; for (gr = 0; gr < pstr_ps_handle->iid_icc_bins; gr++) { WORD IID_flag; FLOAT32 pan_value = pstr_ps_handle->aaa_IID_data_buf[gr][SYSTEMLOOKAHEAD]; IID_flag = 0; if ((pan_value >= -ps_tables->pan_class[0]) && (pan_value <= ps_tables->pan_class[0])) { IID_flag = 1; } if (IID_flag) { index = 0; } else { if (pan_value < 0) { for (index = NO_IID_STEPS - 1; pan_value > -ps_tables->pan_class[index]; index--) { } index = -index - 1; } else { for (index = NO_IID_STEPS - 1; pan_value < ps_tables->pan_class[index]; index--) { } index++; } b_zero_iid = 0; } if (gr == 0) { aa_delta_iid_f[gr] = index; no_bits_t = 0; no_bits_f = ps_tables->a_book_ps_iid_freq_length[index + CODE_BCK_LAV_IID]; } else { aa_delta_iid_f[gr] = index - last_index; no_bits_f += ps_tables->a_book_ps_iid_freq_length[aa_delta_iid_f[gr] + CODE_BCK_LAV_IID]; } last_index = index; aa_delta_iid_t[gr] = index - pstr_ps_handle->a_last_iid_index[gr]; pstr_ps_handle->a_last_iid_index[gr] = index; no_bits_t += ps_tables->a_book_ps_iid_time_length[aa_delta_iid_t[gr] + CODE_BCK_LAV_IID]; if (aa_delta_iid_t[gr] != 0) { b_keep_params = 0; } } if (no_bits_t < no_bits_f && !b_header_active) { ab_dt_flag_iid = 1; aa_delta_iid = aa_delta_iid_t; aa_huff_book_iid_c = ps_tables->a_book_ps_iid_time_code; aa_huff_book_iid_l = ps_tables->a_book_ps_iid_time_length; } else { ab_dt_flag_iid = 0; aa_delta_iid = aa_delta_iid_f; aa_huff_book_iid_c = ps_tables->a_book_ps_iid_freq_code; aa_huff_book_iid_l = ps_tables->a_book_ps_iid_freq_length; } last_index = 0; for (gr = 0; gr < pstr_ps_handle->iid_icc_bins; gr++) { WORD ICC_flag; FLOAT32 sa_value = pstr_ps_handle->aaa_ICC_data_buf[gr][SYSTEMLOOKAHEAD]; ICC_flag = 0; if (sa_value <= ps_tables->sa_class[0]) { ICC_flag = 1; } if (ICC_flag) { index = 0; } else { for (index = NO_ICC_STEPS - 2; sa_value < ps_tables->sa_class[index]; index--) { } index++; b_zero_icc = 0; } if (gr == 0) { aa_delta_icc_f[gr] = index; no_bits_f = ps_tables->a_book_ps_icc_freq_length[index + CODE_BCK_LAV_ICC]; no_bits_t = 0; } else { aa_delta_icc_f[gr] = index - last_index; no_bits_f += ps_tables->a_book_ps_icc_freq_length[aa_delta_icc_f[gr] + CODE_BCK_LAV_ICC]; } last_index = index; aa_delta_icc_t[gr] = index - pstr_ps_handle->a_last_icc_index[gr]; pstr_ps_handle->a_last_icc_index[gr] = index; no_bits_t += ps_tables->a_book_ps_icc_time_length[aa_delta_icc_t[gr] + CODE_BCK_LAV_ICC]; if (aa_delta_icc_t[gr] != 0) { b_keep_params = 0; } } if (no_bits_t < no_bits_f && !b_header_active) { ab_dt_flag_icc = 1; aa_delta_icc = aa_delta_icc_t; aa_huff_book_icc_c = ps_tables->a_book_ps_icc_time_code; aa_huff_book_icc_l = ps_tables->a_book_ps_icc_time_length; } else { ab_dt_flag_icc = 0; aa_delta_icc = aa_delta_icc_f; aa_huff_book_icc_c = ps_tables->a_book_ps_icc_freq_code; aa_huff_book_icc_l = ps_tables->a_book_ps_icc_freq_length; } { static WORD32 initheader = 0; if (!initheader || b_header_active) { initheader = 1; pstr_ps_handle->b_enable_header = 1; } else { pstr_ps_handle->b_enable_header = 0; } } b_send_header = pstr_ps_handle->b_enable_header || pstr_ps_handle->b_prev_zero_iid != b_zero_iid || pstr_ps_handle->b_prev_zero_icc != b_zero_icc; ixheaace_write_bits(bb, b_send_header, 1); if (b_send_header) { ixheaace_write_bits(bb, !b_zero_iid, 1); if (!b_zero_iid) { ixheaace_write_bits(bb, (pstr_ps_handle->b_hi_freq_res_iid_icc) ? 1 : 0, 3); } ixheaace_write_bits(bb, !b_zero_icc, 1); if (!b_zero_icc) { ixheaace_write_bits(bb, (pstr_ps_handle->b_hi_freq_res_iid_icc) ? 1 : 0, 3); } ixheaace_write_bits(bb, 0, 1); } ixheaace_write_bits(bb, 0, 1); ixheaace_write_bits(bb, 1 - b_keep_params, 2); if (!b_keep_params) { if (!b_zero_iid) { ixheaace_write_bits(bb, ab_dt_flag_iid, 1); for (gr = 0; gr < pstr_ps_handle->iid_icc_bins; gr++) { ixheaace_write_bits(bb, aa_huff_book_iid_c[aa_delta_iid[gr] + CODE_BCK_LAV_IID], aa_huff_book_iid_l[aa_delta_iid[gr] + CODE_BCK_LAV_IID]); } } } if (!b_keep_params) { if (!b_zero_icc) { ixheaace_write_bits(bb, ab_dt_flag_icc, 1); for (gr = 0; gr < pstr_ps_handle->iid_icc_bins; gr++) { ixheaace_write_bits(bb, aa_huff_book_icc_c[aa_delta_icc[gr] + CODE_BCK_LAV_ICC], aa_huff_book_icc_l[aa_delta_icc[gr] + CODE_BCK_LAV_ICC]); } } } pstr_ps_handle->b_prev_zero_iid = b_zero_iid; pstr_ps_handle->b_prev_zero_icc = b_zero_icc; return ia_enhaacplus_enc_get_bits_available(bb); } WORD32 ixheaace_append_ps_bitstream(ixheaace_pstr_ps_enc pstr_ps_handle, ixheaace_bit_buf_handle hdl_bs, WORD32 *sbr_hdr_bits) { if (!pstr_ps_handle) { return 0; } if (!hdl_bs) { return ia_enhaacplus_enc_get_bits_available(&pstr_ps_handle->ps_bit_buf); } else { UWORD8 num_bits = (UWORD8)ia_enhaacplus_enc_get_bits_available(&pstr_ps_handle->ps_bit_buf); ixheaace_write_bits(hdl_bs, EXTENSION_ID_PS_CODING, SI_SBR_EXTENSION_ID_BITS); iexheaax_append_bitstream(hdl_bs, &pstr_ps_handle->ps_bit_buf, num_bits); pstr_ps_handle->bit_buf_read_offset = (WORD32)(pstr_ps_handle->ps_bit_buf.ptr_read_next - pstr_ps_handle->ps_bit_buf.ptr_bit_buf_base); pstr_ps_handle->bit_buf_write_offset = (WORD32)(pstr_ps_handle->ps_bit_buf.ptr_write_next - pstr_ps_handle->ps_bit_buf.ptr_bit_buf_base); return ia_enhaacplus_enc_get_bits_available(hdl_bs) - (*sbr_hdr_bits) - SI_FILL_EXTENTION_BITS; } }