/****************************************************************************** * * * 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 "ixheaac_constants.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_bitbuffer.h" #include "ixheaace_aac_constants.h" #include "ixheaace_write_adts_adif.h" #include "ixheaac_basic_ops32.h" #include "ixheaac_basic_ops16.h" #include "ixheaac_basic_ops40.h" #include "ixheaac_basic_ops.h" #include "ixheaace_common_utils.h" static VOID ia_enhaacplus_enc_putbit(ixheaace_bitstream_params *pstr_bitstream, UWORD32 data, WORD32 num_bit) { WORD32 num, max_num, curr_num; WORD32 num_used, idx; unsigned long bits; WORD32 current_bitstream_bit; UWORD8 *bitstream_data; if (num_bit == 0) return; current_bitstream_bit = pstr_bitstream->current_bit; bitstream_data = pstr_bitstream->data; /* Functionality of Writing bits to the bitstream is split into 3 stages. */ /* Stage #1: Write remainder bits to the partially filled byte */ num = 0; num_used = current_bitstream_bit & 7; max_num = BYTE_NUMBIT - num_used; curr_num = MIN(num_bit, max_num); bits = data >> (num_bit - curr_num); idx = (current_bitstream_bit >> 3); if (num_used == 0) bitstream_data[idx] = 0; bitstream_data[idx] |= (bits & ((1 << curr_num) - 1)) << (max_num - curr_num); current_bitstream_bit += curr_num; num += curr_num; /* Stage #2: At this point, (num + num_used), will be a multiple of 8 Now the bytes can be written directly to bitstream_data[], as long as (num + 8) < num_bit */ while ((num + 8) < num_bit) { num += 8; current_bitstream_bit += 8; bits = data >> (num_bit - num); bitstream_data[++idx] = (UWORD8)bits; } /* Stage #3: Write remainder bits from the data */ if (num < num_bit) { curr_num = num_bit - num; num_used = current_bitstream_bit & 7; max_num = BYTE_NUMBIT - num_used; idx = current_bitstream_bit >> 3; if (num_used == 0) bitstream_data[idx] = 0; bitstream_data[idx] |= (data & ((1 << curr_num) - 1)) << (max_num - curr_num); current_bitstream_bit += curr_num; } pstr_bitstream->current_bit = current_bitstream_bit; pstr_bitstream->num_bit = current_bitstream_bit; } static WORD16 ia_enhaacplus_enc_get_sample_rate_index(WORD32 sample_rate) { if (92017 <= sample_rate) { return 0; } if (75132 <= sample_rate) { return 1; } if (55426 <= sample_rate) { return 2; } if (46009 <= sample_rate) { return 3; } if (37566 <= sample_rate) { return 4; } if (27713 <= sample_rate) { return 5; } if (23004 <= sample_rate) { return 6; } if (18783 <= sample_rate) { return 7; } if (13856 <= sample_rate) { return 8; } if (11502 <= sample_rate) { return 9; } if (9391 <= sample_rate) { return 10; } return 11; } WORD32 ia_enhaacplus_enc_write_pce(WORD32 samp_rate, WORD32 ch_mask, WORD32 num_core_coder_chans, ixheaace_bit_buf_handle pstr_bit_stream_handle) { UWORD32 object_type = 0; UWORD8 buffer[200]; ixheaace_bitstream_params bitstream_temp; ixheaace_bitstream_params *pstr_bitstream = &bitstream_temp; WORD32 write_flag = 1; WORD32 start_bits = pstr_bit_stream_handle->cnt_bits, end_bits; pstr_bitstream->data = buffer; pstr_bitstream->num_bit = 8; pstr_bitstream->current_bit = 0; object_type = 01; if (write_flag) { WORD32 i; WORD32 num_front_chan_ele, num_side_chan_ele, num_back_chan_ele, num_lfe_chan_ele; /* element instance tag can be anything... writing 0 */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 4); /* object type --> LC / LTP / any other */ ixheaace_write_bits(pstr_bit_stream_handle, object_type, 2); /* sampling freq index */ ixheaace_write_bits(pstr_bit_stream_handle, ia_enhaacplus_enc_get_sample_rate_index(samp_rate), 4); /* num_front_channel_elements --> only this present for mono / stereo */ num_front_chan_ele = 0; if (ch_mask & 0x3) { num_front_chan_ele++; /*Front Left and Right Present*/ } if (ch_mask & 0x4) { num_front_chan_ele++; /*Front Center Present*/ } ixheaace_write_bits(pstr_bit_stream_handle, num_front_chan_ele, 4); /* num_side_channel_elements 4 */ num_side_chan_ele = 0; if (ch_mask & 0xC0) { num_side_chan_ele++; /*Back Left and Right Present*/ } ixheaace_write_bits(pstr_bit_stream_handle, num_side_chan_ele, 4); /* num_back_channel_elements 4 */ num_back_chan_ele = 0; if (ch_mask & 0x30) { num_back_chan_ele++; /*Back Left and Right of center Present*/ } ixheaace_write_bits(pstr_bit_stream_handle, num_back_chan_ele, 4); /* num_lfe_channel_elements 2 */ num_lfe_chan_ele = 0; if (ch_mask & 0x8) { num_lfe_chan_ele++; /*LFE channel Present*/ } ixheaace_write_bits(pstr_bit_stream_handle, num_lfe_chan_ele, 2); /* num_assoc_data_elements 3 */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 3); /* num_valid_cc_elements 4 */ ixheaace_write_bits(pstr_bit_stream_handle, num_core_coder_chans, 4); /* mono mix down is zero */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); /* mono_mixdown_element_number 4 if mono_mixdown_present == 1 */ /* stereo_mixdown_present is zero */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); /* stereo_mixdown_element_number 4 if stereo_mixdown_present == 1 */ /* matrix_mixdown_idx_present is zero */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); { /* stereo --> 1 mono --> 0 */ if (ch_mask & 0x4) { ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 4); } if (ch_mask & 0x3) { if ((ch_mask & 0x3) == 0x3) { /* stereo channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x01, 1); } else { /* mono channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); } /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 4); } } for (i = 0; i < num_side_chan_ele; i++) { if ((ch_mask & 0xC0) == 0xC0) { /* stereo channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x01, 1); } else { /* mono channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); } /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, 0x02, 4); } for (i = 0; i < num_back_chan_ele; i++) { if ((ch_mask & 0x30) == 0x30) { /* stereo channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x01, 1); } else { /* mono channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 1); } /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, 0x01, 4); } for (i = 0; i < num_lfe_chan_ele; i++) { /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 4); } /* loop for independent coupling elements */ for (i = 0; i < num_core_coder_chans; i++) { /* It is independent coupling channel */ ixheaace_write_bits(pstr_bit_stream_handle, 0x01, 1); /* element tag select */ ixheaace_write_bits(pstr_bit_stream_handle, num_core_coder_chans - i - 1, 4); } /* byte align the stream */ ixheaace_write_bits(pstr_bit_stream_handle, 0, (UWORD8)((8 - (pstr_bit_stream_handle->cnt_bits % 8)) % 8)); /* comment field types --> do not quite know what this is */ ixheaace_write_bits(pstr_bit_stream_handle, 0x00, 8); } end_bits = pstr_bit_stream_handle->cnt_bits; return (end_bits - start_bits); } WORD32 ia_enhaacplus_enc_write_ADTS_header(pUWORD8 buffer, WORD32 bytes_used, WORD32 samp_rate, WORD32 num_ch) { WORD32 bits = 56; UWORD32 object_type = 0; ixheaace_bitstream_params bitstream_temp; ixheaace_bitstream_params *pstr_bitstream = &bitstream_temp; WORD32 write_flag = 1; pstr_bitstream->data = buffer; pstr_bitstream->num_bit = 8; pstr_bitstream->current_bit = 0; ; object_type = 01; if (write_flag) { /* Fixed ADTS header */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0xFFFF, 12); /* 12 bit Syncword */ ia_enhaacplus_enc_putbit(pstr_bitstream, 1 /*aacStateStruct->aacConfigSturct.mpegVersion*/, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 2); /* layer == 0 */ ia_enhaacplus_enc_putbit(pstr_bitstream, 1, 1); /* protection absent */ ia_enhaacplus_enc_putbit(pstr_bitstream, object_type, 2); /* profile */ ia_enhaacplus_enc_putbit( pstr_bitstream, ia_enhaacplus_enc_get_sample_rate_index(samp_rate) /*aacStateStruct->sampleRateIdx*/, 4); /* sampling rate */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 1); /* private bit */ ia_enhaacplus_enc_putbit(pstr_bitstream, num_ch /*aacStateStruct->aacConfigSturct.ch*/, 3); /* ch. aacConfigSturct (must be > 0) */ /* simply using num_channels only works for 6 channels or less, else a channel configuration should be written */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 1); /* original/copy */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 1); /* home */ /* Variable ADTS header */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 1); /* copyr. id. bit */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 1); /* copyr. id. start */ ia_enhaacplus_enc_putbit(pstr_bitstream, /*aacStateStruct->*/ bytes_used + 7, 13); ia_enhaacplus_enc_putbit(pstr_bitstream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */ ia_enhaacplus_enc_putbit(pstr_bitstream, 0, 2); /* raw data blocks (0+1=1) */ } /* * MPEG2 says byte_aligment() here, but ADTS always is multiple of 8 bits * MPEG4 has no byte_alignment() here */ return bits / 8; }