545 files changed, 230976 insertions, 0 deletions
diff --git a/audio_codec/libfaad/decoder.c b/audio_codec/libfaad/decoder.c new file mode 100644 index 0000000..88edad5 --- a/dev/null +++ b/audio_codec/libfaad/decoder.c @@ -0,0 +1,2266 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: decoder.c,v 1.117 2009/02/05 00:51:03 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> + +#include "mp4.h" +#include "syntax.h" +#include "error.h" +#include "output.h" +#include "filtbank.h" +#include "drc.h" +#ifdef SBR_DEC +#include "sbr_dec.h" +#include "sbr_syntax.h" +#endif +#ifdef SSR_DEC +#include "ssr.h" +#include "ssr_fb.h" +#endif + +#ifdef USE_HELIX_AAC_DECODER +#include "aaccommon.h" +#include "aacdec.h" +int AACDataSource = 1; +static HAACDecoder hAACDecoder; +static short dec_buffer[1024 * 6 * 2]; +static short output_buffer[1024 * 2 * 2]; +static int adts_sample_rates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0}; + +static int FindAdtsSRIndex(int sr) +{ + int i; + + for (i = 0; i < 16; i++) { + if (sr == adts_sample_rates[i]) { + return i; + } + } + return 16 - 1; +} +static void MakeAdtsHeader(NeAACDecFrameInfo *hInfo, unsigned char *adts_header, int channel) +{ + unsigned char *data; + int old_format = 0; + int profile = hInfo->object_type; + if (profile == 5) { //sbr + profile = 2; + } + profile = (profile - 1) & 0x3; + int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ? + FindAdtsSRIndex(hInfo->samplerate / 2) : FindAdtsSRIndex(hInfo->samplerate); + int skip = (old_format) ? 8 : 7; + int framesize = skip + hInfo->bytesconsumed; + + if (hInfo->header_type == ADTS) { + framesize -= skip; + } + + // audio_codec_print("MakeAdtsHeader profile %d ,ch %d,sr_index %d\n",profile,channel,sr_index); + + data = adts_header; + memset(data, 0, 7 * sizeof(unsigned char)); + + data[0] += 0xFF; /* 8b: syncword */ + + data[1] += 0xF0; /* 4b: syncword */ + /* 1b: mpeg id = 0 */ + /* 2b: layer = 0 */ + data[1] += 1; /* 1b: protection absent */ + + data[2] += ((profile << 6) & 0xC0); /* 2b: profile */ + data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */ + /* 1b: private = 0 */ + data[2] += ((channel >> 2) & 0x1); /* 1b: channel_configuration */ + + data[3] += ((channel << 6) & 0xC0); /* 2b: channel_configuration */ + /* 1b: original */ + /* 1b: home */ + /* 1b: copyright_id */ + /* 1b: copyright_id_start */ + data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */ + + data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */ + + data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */ + data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */ + + data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */ + /* 2b: num_raw_data_blocks */ + +} +#endif + +#ifdef ANALYSIS +uint16_t dbg_count; +#endif + +#define faad_log_info audio_codec_print + + +#ifdef NEW_CODE_CHECK_LATM +static unsigned char temp_bufer[200 * 1024]; +static int temp_size = 0; +#define LATM_LOG audio_codec_print +static const int pi_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350, 0, 0, 0 +}; +static int LOASSyncInfo(uint8_t p_header[LOAS_HEADER_SIZE], unsigned int *pi_header_size) +{ + *pi_header_size = 3; + return ((p_header[1] & 0x1f) << 8) + p_header[2]; +} + +static int Mpeg4GAProgramConfigElement(bitfile *ld,mpeg4_cfg_t *p_cfg) +{ + /* TODO compute channels count ? */ + int i_tag = faad_getbits(ld, 4); + //if (i_tag != 0x05) { + // return -1; + //} + faad_getbits(ld, 2 + 4); // object type + sampling index + int i_num_front = faad_getbits(ld, 4); + int i_num_side = faad_getbits(ld, 4); + int i_num_back = faad_getbits(ld, 4); + int i_num_lfe = faad_getbits(ld, 2); + int i_num_assoc_data = faad_getbits(ld, 3); + int i_num_valid_cc = faad_getbits(ld, 4); + int i,tmp; + if (faad_getbits(ld, 1)) { + faad_getbits(ld, 4); // mono downmix + } + if (faad_getbits(ld, 1)) { + faad_getbits(ld, 4); // stereo downmix + } + if (faad_getbits(ld, 1)) { + faad_getbits(ld, 2 + 1); // matrix downmix + pseudo_surround + } + + for (i = 0; i < i_num_front; i++) { + tmp = faad_get1bit(ld DEBUGVAR(1, 26, "program_config_element(): front_element_is_cpe")); + faad_getbits(ld, 4 DEBUGVAR(1, 27, "program_config_element(): front_element_tag_select")); + + if (tmp & 1) { + p_cfg->i_channel += 2; + } else { + p_cfg->i_channel++; + } + } + + for (i = 0; i < i_num_side; i++) { + tmp = faad_get1bit(ld DEBUGVAR(1, 28, "program_config_element(): side_element_is_cpe")); + faad_getbits(ld, 4 DEBUGVAR(1, 29, "program_config_element(): side_element_tag_select")); + + if (tmp & 1) { + p_cfg->i_channel += 2; + } else { + p_cfg->i_channel++; + } + } + + for (i = 0; i < i_num_back; i++) { + tmp = faad_get1bit(ld DEBUGVAR(1, 30, "program_config_element(): back_element_is_cpe")); + faad_getbits(ld, 4 DEBUGVAR(1, 31, "program_config_element(): back_element_tag_select")); + + if (tmp & 1) { + p_cfg->i_channel += 2; + } else { + p_cfg->i_channel++; + } + } + + for (i = 0; i < i_num_lfe; i++) { + tmp = (uint8_t)faad_getbits(ld, 4 DEBUGVAR(1, 32, "program_config_element(): lfe_element_tag_select")); + p_cfg->i_channel++; + } + + for (i = 0; i < i_num_assoc_data; i++) + faad_getbits(ld, 4 DEBUGVAR(1, 33, "program_config_element(): assoc_data_element_tag_select")); + + for (i = 0; i < i_num_valid_cc; i++) { + faad_get1bit(ld DEBUGVAR(1, 34, "program_config_element(): cc_element_is_ind_sw")); + faad_getbits(ld, 4 DEBUGVAR(1, 35, "program_config_element(): valid_cc_element_tag_select")); + } + faad_byte_align(ld); + int i_comment = faad_getbits(ld, 8); + faad_getbits(ld, i_comment * 8); + return 0; +} + +static int Mpeg4GASpecificConfig(mpeg4_cfg_t *p_cfg, bitfile *ld) +{ + p_cfg->i_frame_length = faad_getbits(ld, 1) ? 960 : 1024; + + if (faad_getbits(ld, 1)) { // depend on core coder + faad_getbits(ld, 14); // core coder delay + } + + int i_extension_flag = faad_getbits(ld, 1); + if (p_cfg->i_channel == 0) { + Mpeg4GAProgramConfigElement(ld,p_cfg); + } + if (p_cfg->i_object_type == 6 || p_cfg->i_object_type == 20) { + faad_getbits(ld, 3); // layer + } + + if (i_extension_flag) { + if (p_cfg->i_object_type == 22) { + faad_getbits(ld, 5 + 11); // numOfSubFrame + layer length + } + if (p_cfg->i_object_type == 17 || p_cfg->i_object_type == 19 || + p_cfg->i_object_type == 20 || p_cfg->i_object_type == 23) { + faad_getbits(ld, 1 + 1 + 1); // ER data : section scale spectral */ + } + if (faad_getbits(ld, 1)) { // extension 3 + LATM_LOG("Mpeg4GASpecificConfig: error 1\n"); + } + } + return 0; +} + +static int Mpeg4ReadAudioObjectType(bitfile *ld) +{ + int i_type = faad_getbits(ld, 5); + if (i_type == 31) { + i_type = 32 + faad_getbits(ld, 6); + } + return i_type; +} + +static int Mpeg4ReadAudioSamplerate(bitfile *ld) +{ + int i_index = faad_getbits(ld, 4); + if (i_index != 0x0f) { + return pi_sample_rates[i_index]; + } + return faad_getbits(ld, 24); +} + +static int Mpeg4ReadAudioSpecificInfo(mpeg4_cfg_t *p_cfg, int *pi_extra, uint8_t *p_extra, bitfile *ld, int i_max_size) +{ +#if 0 + static const char *ppsz_otype[] = { + "NULL", + "AAC Main", "AAC LC", "AAC SSR", "AAC LTP", "SBR", "AAC Scalable", + "TwinVQ", + "CELP", "HVXC", + "Reserved", "Reserved", + "TTSI", + "Main Synthetic", "Wavetables Synthesis", "General MIDI", + "Algorithmic Synthesis and Audio FX", + "ER AAC LC", + "Reserved", + "ER AAC LTP", "ER AAC Scalable", "ER TwinVQ", "ER BSAC", "ER AAC LD", + "ER CELP", "ER HVXC", "ER HILN", "ER Parametric", + "SSC", + "PS", "Reserved", "Escape", + "Layer 1", "Layer 2", "Layer 3", + "DST", + }; +#endif + const int i_pos_start = faad_get_processed_bits(ld); + bitfile s_sav = *ld; + int i_bits; + int i; + + memset(p_cfg, 0, sizeof(*p_cfg)); + *pi_extra = 0; + + p_cfg->i_object_type = Mpeg4ReadAudioObjectType(ld); + p_cfg->i_samplerate = Mpeg4ReadAudioSamplerate(ld); + + p_cfg->i_channel = faad_getbits(ld, 4); + if (p_cfg->i_channel == 7) { + p_cfg->i_channel = 8; // 7.1 + } else if (p_cfg->i_channel >= 8) { + p_cfg->i_channel = -1; + } + + p_cfg->i_sbr = -1; + p_cfg->i_ps = -1; + p_cfg->extension.i_object_type = 0; + p_cfg->extension.i_samplerate = 0; + if (p_cfg->i_object_type == 5 || (p_cfg->i_object_type == 29/*&&(faad_showbits(ld, 3) & 0x03 && !(faad_showbits(ld, 9) & 0x3F))*/)) { + p_cfg->i_sbr = 1; + if (p_cfg->i_object_type == 29) { + p_cfg->i_ps = 1; + } + p_cfg->extension.i_object_type = 5; + p_cfg->extension.i_samplerate = Mpeg4ReadAudioSamplerate(ld); + + p_cfg->i_object_type = Mpeg4ReadAudioObjectType(ld); + } + + switch (p_cfg->i_object_type) { + case 1: + case 2: + case 3: + case 4: + case 6: + case 7: + case 17: + case 19: + case 20: + case 21: + case 22: + case 23: + Mpeg4GASpecificConfig(p_cfg, ld); + break; + case 8: + // CelpSpecificConfig(); + break; + case 9: + // HvxcSpecificConfig(); + break; + case 12: + // TTSSSpecificConfig(); + break; + case 13: + case 14: + case 15: + case 16: + // StructuredAudioSpecificConfig(); + break; + case 24: + // ERCelpSpecificConfig(); + break; + case 25: + // ERHvxcSpecificConfig(); + break; + case 26: + case 27: + // ParametricSpecificConfig(); + break; + case 28: + // SSCSpecificConfig(); + break; + case 32: + case 33: + case 34: + // MPEG_1_2_SpecificConfig(); + break; + case 35: + // DSTSpecificConfig(); + break; + case 36: + // ALSSpecificConfig(); + break; + default: + // error + break; + } + switch (p_cfg->i_object_type) { + case 17: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: { + int epConfig = faad_getbits(ld, 2); + if (epConfig == 2 || epConfig == 3) + //ErrorProtectionSpecificConfig(); + if (epConfig == 3) + if (faad_getbits(ld, 1)) { + // TODO : directMapping + } + break; + } + default: + break; + } + + if (p_cfg->extension.i_object_type != 5 && i_max_size > 0 && i_max_size - (faad_get_processed_bits(ld) - i_pos_start) >= 16 && + faad_getbits(ld, 11) == 0x2b7) { + p_cfg->extension.i_object_type = Mpeg4ReadAudioObjectType(ld); + if (p_cfg->extension.i_object_type == 5) { + p_cfg->i_sbr = faad_getbits(ld, 1); + if (p_cfg->i_sbr == 1) { + p_cfg->extension.i_samplerate = Mpeg4ReadAudioSamplerate(ld); + if (i_max_size > 0 && i_max_size - (faad_get_processed_bits(ld) - i_pos_start) >= 12 && faad_getbits(ld, 11) == 0x548) { + p_cfg->i_ps = faad_getbits(ld, 1); + } + } + } + } + + //fprintf(stderr, "Mpeg4ReadAudioSpecificInfo: t=%s(%d)f=%d c=%d sbr=%d\n", + // ppsz_otype[p_cfg->i_object_type], p_cfg->i_object_type, p_cfg->i_samplerate, p_cfg->i_channel, p_cfg->i_sbr); + + i_bits = faad_get_processed_bits(ld) - i_pos_start; + + *pi_extra = min((i_bits + 7) / 8, LATM_MAX_EXTRA_SIZE); + for (i = 0; i < *pi_extra; i++) { + const int i_read = min(8, i_bits - 8 * i); + p_extra[i] = faad_getbits(&s_sav, i_read) << (8 - i_read); + } + return i_bits; +} + +static int LatmGetValue(bitfile *ld) +{ + int i_bytes = faad_getbits(ld, 2); + int v = 0; + int i; + for (i = 0; i < i_bytes; i++) { + v = (v << 8) + faad_getbits(ld, 8); + } + + return v; +} + +static int LatmReadStreamMuxConfiguration(latm_mux_t *m, bitfile *ld) +{ + int i_mux_version; + int i_mux_versionA; + + i_mux_version = faad_getbits(ld, 1); + i_mux_versionA = 0; + if (i_mux_version) { + i_mux_versionA = faad_getbits(ld, 1); + } + + if (i_mux_versionA != 0) { /* support only A=0 */ + return -1; + } + + memset(m, 0, sizeof(*m)); + + if (i_mux_versionA == 0) + if (i_mux_version == 1) { + LatmGetValue(ld); /* taraBufferFullness */ + } + + m->b_same_time_framing = faad_getbits(ld, 1); + m->i_sub_frames = 1 + faad_getbits(ld, 6); + m->i_programs = 1 + faad_getbits(ld, 4); + if (m->i_programs > 1) { + return -1; + } + int i_program; + for (i_program = 0; i_program < m->i_programs; i_program++) { + m->pi_layers[i_program] = 1 + faad_getbits(ld, 3); + if (m->pi_layers[0] > 1) { + return -1; + } + int i_layer; + for (i_layer = 0; i_layer < m->pi_layers[i_program]; i_layer++) { + latm_stream_t *st = &m->stream[m->i_streams]; + unsigned char b_previous_cfg; + + m->pi_stream[i_program][i_layer] = m->i_streams; + st->i_program = i_program; + st->i_layer = i_layer; + + b_previous_cfg = 0; + if (i_program != 0 || i_layer != 0) { + b_previous_cfg = faad_getbits(ld, 1); + } + + if (b_previous_cfg) { + if (m->i_streams <= 0) { + LATM_LOG("assert failed \n"); + while (1) { + ; + } + } + st->cfg = m->stream[m->i_streams - 1].cfg; + } else { + int i_cfg_size = 0; + if (i_mux_version == 1) { + i_cfg_size = LatmGetValue(ld); + } + i_cfg_size -= Mpeg4ReadAudioSpecificInfo(&st->cfg, &st->i_extra, st->extra, ld, i_cfg_size); + if (i_cfg_size > 0) { + faad_flushbits(ld, i_cfg_size); + } + } + + st->i_frame_length_type = faad_getbits(ld, 3); + switch (st->i_frame_length_type) { + case 0: { + faad_flushbits(ld, 8); /* latmBufferFullnes */ + if (!m->b_same_time_framing) + if (st->cfg.i_object_type == 6 || st->cfg.i_object_type == 20 || + st->cfg.i_object_type == 8 || st->cfg.i_object_type == 24) { + faad_flushbits(ld, 6); /* eFrameOffset */ + } + break; + } + case 1: + st->i_frame_length = faad_getbits(ld, 9); + break; + case 3: + case 4: + case 5: + st->i_frame_length_index = faad_getbits(ld, 6); // celp + break; + case 6: + case 7: + st->i_frame_length_index = faad_getbits(ld, 1); // hvxc + default: + break; + } + /* Next stream */ + m->i_streams++; + } + } + + /* other data */ + if (faad_getbits(ld, 1)) { + if (i_mux_version == 1) { + m->i_other_data = LatmGetValue(ld); + } else { + int b_continue; + do { + b_continue = faad_getbits(ld, 1); + m->i_other_data = (m->i_other_data << 8) + faad_getbits(ld, 8); + } while (b_continue); + } + } + + /* crc */ + m->i_crc = -1; + if (faad_getbits(ld, 1)) { + m->i_crc = faad_getbits(ld, 8); + } + + return 0; +} +static int LOASParse(uint8_t *p_buffer, int i_buffer, decoder_sys_t *p_sys) +{ + bitfile ld = {0}; + int i_accumulated = 0; + const latm_stream_t *st; + faad_initbits(&ld, p_buffer, i_buffer); + int ret = 0; + //bs_init(&s, p_buffer, i_buffer); + + /* Read the stream mux configuration if present */ + if (!faad_getbits(&ld, 1) && !(ret = LatmReadStreamMuxConfiguration(&p_sys->latm, &ld)) && + p_sys->latm.i_streams > 0) { + st = &p_sys->latm.stream[0]; + + p_sys->i_channels = st->cfg.i_channel; + p_sys->i_rate = st->cfg.i_samplerate; + p_sys->i_frame_length = st->cfg.i_frame_length; + // LATM_LOG("ch %d, rate %d,frame len %d \n",p_sys->i_channels,p_sys->i_rate,p_sys->i_frame_length); + /* FIXME And if it changes ? */ + if (p_sys->i_channels && p_sys->i_rate && p_sys->i_frame_length > 0) { +#if 0 + if (!p_dec->fmt_out.i_extra && st->i_extra > 0) { + p_dec->fmt_out.i_extra = st->i_extra; + p_dec->fmt_out.p_extra = malloc(st->i_extra); + if (!p_dec->fmt_out.p_extra) { + p_dec->fmt_out.i_extra = 0; + return 0; + } + memcpy(p_dec->fmt_out.p_extra, st->extra, st->i_extra); + } +#endif + p_sys->b_latm_cfg = 1; + } + } + + /* Wait for the configuration */ + if (!p_sys->b_latm_cfg || ret < 0) { + return 0; + } + + /* FIXME do we need to split the subframe into independent packet ? */ + if (p_sys->latm.i_sub_frames > 1) { + printf("latm sub frames not yet supported, please send a sample"); + } + int i_sub; + for (i_sub = 0; i_sub < p_sys->latm.i_sub_frames; i_sub++) { + int pi_payload[LATM_MAX_PROGRAM][LATM_MAX_LAYER]; + if (p_sys->latm.b_same_time_framing) { + /* Payload length */ + int i_program, i_layer; + for (i_program = 0; i_program < p_sys->latm.i_programs; i_program++) { + for (i_layer = 0; i_layer < p_sys->latm.pi_layers[i_program]; i_layer++) { + latm_stream_t *st = &p_sys->latm.stream[p_sys->latm.pi_stream[i_program][i_layer]]; + if (st->i_frame_length_type == 0) { + int i_payload = 0; + for (;;) { + int i_tmp = faad_getbits(&ld, 8); + i_payload += i_tmp; + if (i_tmp != 255) { + break; + } + } + pi_payload[i_program][i_layer] = i_payload; + } else if (st->i_frame_length_type == 1) { + pi_payload[i_program][i_layer] = st->i_frame_length / 8; /* XXX not correct */ + } else if ((st->i_frame_length_type == 3) || + (st->i_frame_length_type == 5) || + (st->i_frame_length_type == 7)) { + faad_getbits(&ld, 2); // muxSlotLengthCoded + pi_payload[i_program][i_layer] = 0; /* TODO */ + } else { + pi_payload[i_program][i_layer] = 0; /* TODO */ + } + } + } + + /* Payload Data */ + // int i_program,i_layer; + for (i_program = 0; i_program < p_sys->latm.i_programs; i_program++) { + for (i_layer = 0; i_layer < p_sys->latm.pi_layers[i_program]; i_layer++) { + /* XXX we only extract 1 stream */ + if (i_program != 0 || i_layer != 0) { + break; + } + + if (pi_payload[i_program][i_layer] <= 0) { + continue; + } + + /* FIXME that's slow (and a bit ugly to write in place) */ + int i; + for (i = 0; i < pi_payload[i_program][i_layer]; i++) { + if (i_accumulated >= i_buffer) { + return 0; + } + p_buffer[i_accumulated++] = faad_getbits(&ld, 8); + } + } + } + } else { + const int i_chunks = faad_getbits(&ld, 4); + int pi_program[16]; + int pi_layer[16]; + + // printf( "latm without same time frameing not yet supported, please send a sample"); + int i_chunk; + for (i_chunk = 0; i_chunk < i_chunks; i_chunk++) { + const int streamIndex = faad_getbits(&ld, 4); + latm_stream_t *st = &p_sys->latm.stream[streamIndex]; + const int i_program = st->i_program; + const int i_layer = st->i_layer; + + pi_program[i_chunk] = i_program; + pi_layer[i_chunk] = i_layer; + + if (st->i_frame_length_type == 0) { + int i_payload = 0; + for (;;) { + int i_tmp = faad_getbits(&ld, 8); + i_payload += i_tmp; + if (i_tmp != 255) { + break; + } + } + pi_payload[i_program][i_layer] = i_payload; + faad_getbits(&ld, 1); // auEndFlag + } else if (st->i_frame_length_type == 1) { + pi_payload[i_program][i_layer] = st->i_frame_length / 8; /* XXX not correct */ + } else if ((st->i_frame_length_type == 3) || + (st->i_frame_length_type == 5) || + (st->i_frame_length_type == 7)) { + faad_getbits(&ld, 2); // muxSlotLengthCoded + } + } + // int i_chunk; + for (i_chunk = 0; i_chunk < i_chunks; i_chunk++) { + //const int i_program = pi_program[i_chunk]; + //const int i_layer = pi_layer[i_chunk]; + + /* TODO ? Payload */ + } + } + } + +#if 0 + if (p_sys->latm.i_other_data > 0) { + ; // TODO + } +#endif + faad_byte_align(&ld); + + return i_accumulated; +} + + +#endif + +/* static function declarations */ +static void* aac_frame_decode(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer2, + unsigned long sample_buffer_size); +static void create_channel_config(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo); + + +char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode) +{ + if (errcode >= NUM_ERROR_MESSAGES) { + return NULL; + } + return err_msg[errcode]; +} + +unsigned long NEAACDECAPI NeAACDecGetCapabilities(void) +{ + uint32_t cap = 0; + + /* can't do without it */ + cap += LC_DEC_CAP; + +#ifdef MAIN_DEC + cap += MAIN_DEC_CAP; +#endif +#ifdef LTP_DEC + cap += LTP_DEC_CAP; +#endif +#ifdef LD_DEC + cap += LD_DEC_CAP; +#endif +#ifdef ERROR_RESILIENCE + cap += ERROR_RESILIENCE_CAP; +#endif +#ifdef FIXED_POINT + cap += FIXED_POINT_CAP; +#endif + + return cap; +} + +const unsigned char mes[] = { 0x67, 0x20, 0x61, 0x20, 0x20, 0x20, 0x6f, 0x20, 0x72, 0x20, 0x65, 0x20, 0x6e, 0x20, 0x20, 0x20, 0x74, 0x20, 0x68, 0x20, 0x67, 0x20, 0x69, 0x20, 0x72, 0x20, 0x79, 0x20, 0x70, 0x20, 0x6f, 0x20, 0x63 }; +NeAACDecHandle NEAACDECAPI NeAACDecOpen(void) +{ + uint8_t i; + NeAACDecStruct *hDecoder = NULL; + + if ((hDecoder = (NeAACDecStruct*)faad_malloc(sizeof(NeAACDecStruct))) == NULL) { + return NULL; + } + + memset(hDecoder, 0, sizeof(NeAACDecStruct)); + + hDecoder->cmes = mes; + hDecoder->config.outputFormat = FAAD_FMT_16BIT; + hDecoder->config.defObjectType = MAIN; + hDecoder->config.defSampleRate = 44100; /* Default: 44.1kHz */ + hDecoder->config.downMatrix = 0x01; + hDecoder->adts_header_present = 0; + hDecoder->adif_header_present = 0; + hDecoder->latm_header_present = 0; +#ifdef ERROR_RESILIENCE + hDecoder->aacSectionDataResilienceFlag = 0; + hDecoder->aacScalefactorDataResilienceFlag = 0; + hDecoder->aacSpectralDataResilienceFlag = 0; +#endif + hDecoder->frameLength = 1024; + + hDecoder->frame = 0; + hDecoder->sample_buffer = NULL; + + hDecoder->__r1 = 1; + hDecoder->__r2 = 1; + + for (i = 0; i < MAX_CHANNELS; i++) { + hDecoder->window_shape_prev[i] = 0; + hDecoder->time_out[i] = NULL; + hDecoder->fb_intermed[i] = NULL; +#ifdef SSR_DEC + hDecoder->ssr_overlap[i] = NULL; + hDecoder->prev_fmd[i] = NULL; +#endif +#ifdef MAIN_DEC + hDecoder->pred_stat[i] = NULL; +#endif +#ifdef LTP_DEC + hDecoder->ltp_lag[i] = 0; + hDecoder->lt_pred_stat[i] = NULL; +#endif + } + +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) { + hDecoder->sbr[i] = NULL; + } +#endif + + hDecoder->drc = drc_init(REAL_CONST(1.0), REAL_CONST(1.0)); + hDecoder->last_ch_configure = -1; + hDecoder->last_sf_index = -1; + return hDecoder; +} + +NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hpDecoder) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder) { + NeAACDecConfigurationPtr config = &(hDecoder->config); + + return config; + } + + return NULL; +} + +unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hpDecoder, + NeAACDecConfigurationPtr config) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder && config) { + /* check if we can decode this object type */ + if (can_decode_ot(config->defObjectType) < 0) { + return 0; + } + hDecoder->config.defObjectType = config->defObjectType; + + /* samplerate: anything but 0 should be possible */ + if (config->defSampleRate == 0) { + return 0; + } + hDecoder->config.defSampleRate = config->defSampleRate; + + /* check output format */ +#ifdef FIXED_POINT + if ((config->outputFormat < 1) || (config->outputFormat > 4)) { + return 0; + } +#else + if ((config->outputFormat < 1) || (config->outputFormat > 5)) { + return 0; + } +#endif + hDecoder->config.outputFormat = config->outputFormat; + + if (config->downMatrix > 1) { + return 0; + } + hDecoder->config.downMatrix = config->downMatrix; + + /* OK */ + return 1; + } + + return 0; +} + + +static int latmCheck(latm_header *latm, bitfile *ld) +{ + uint32_t good = 0, bad = 0, bits, m; + + while (ld->bytes_left) { + bits = faad_latm_frame(latm, ld); + if (bits == -1U) { + bad++; + } else { + good++; + while (bits > 0) { + m = min(bits, 8); + faad_getbits(ld, m DEBUGVAR(print, var, dbg)); + bits -= m; + } + } + } + + return (good > 0); +} + +#define SKIP_LATM_BYTE 16*4*2 +static int latm_check_internal(unsigned char *buffer, unsigned buffer_size, unsigned *byte_cost) +{ + latm_header l = {0}; + int is_latm = 0; + bitfile ld; + int byte_consumed = 0; + int byte_left = buffer_size; +retry: + memset(&l, 0, sizeof(latm_header)); + faad_initbits(&ld, buffer + byte_consumed, buffer_size - byte_consumed); + is_latm = latmCheck(&l, &ld); + if (is_latm && l.ASCbits > 0) { + is_latm = 1; + } else { + is_latm = 0; + byte_consumed += SKIP_LATM_BYTE; + byte_left -= SKIP_LATM_BYTE; + + } + if (is_latm == 0 && byte_left > 400) { + goto retry; + } +exit: + *byte_cost = byte_consumed; + return is_latm; +} + +long NEAACDECAPI NeAACDecInit(NeAACDecHandle hpDecoder, + unsigned char *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + unsigned char *channels, + int is_latm_external, + int *skipbytes) +{ + uint32_t bits = 0; + bitfile ld; + adif_header adif; + adts_header adts; + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + faad_log_info("enter NeAACDecInit \r\n"); +#ifdef NEW_CODE_CHECK_LATM + int i_frame_size; + if (buffer_size > sizeof(temp_bufer)) { + LATM_LOG("init input buffer size tooo big %d, buffer size %d \n", buffer_size, sizeof(temp_bufer)); + buffer_size = sizeof(temp_bufer); + } + if (buffer_size > 0) { + memcpy(temp_bufer, buffer, buffer_size); + temp_size = buffer_size; + buffer = temp_bufer; + } + unsigned char *pbuffer = buffer; + int pbuffer_size = buffer_size; + decoder_sys_t *p_sys = &hDecoder->dec_sys; + latm_mux_t *m = &p_sys->latm; + latm_stream_t *st = NULL; +#endif + + if ((hDecoder == NULL) || (samplerate == NULL) || (channels == NULL)) { + return -1; + } + //memset(latm_payload,0,sizeof(latm_payload)); + hDecoder->sf_index = get_sr_index(hDecoder->config.defSampleRate); + hDecoder->object_type = hDecoder->config.defObjectType; + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = 1; + *samplerate = 0; + *channels = 0; + int latm_audio = 0; + unsigned byte_cost = 0; + if (buffer != NULL) { + int is_latm; + latm_header *l = &hDecoder->latm_config; + faad_initbits(&ld, buffer, buffer_size); +#ifdef NEW_CODE_CHECK_LATM + memset(&hDecoder->dec_sys, 0, sizeof(decoder_sys_t)); +NEXT_CHECK: + while (pbuffer_size >= 2) { + if (pbuffer[0] == 0x56 && (pbuffer[1] & 0xe0) == 0xe0) { //LOAS sync word detected + // LATM_LOG("find LOAS sync word pos %d\n",buffer_size-pbuffer_size); + break; + } + pbuffer++; + pbuffer_size--; + } + if (pbuffer_size < LOAS_HEADER_SIZE) { + LATM_LOG("check the loas frame failed\n"); + *skipbytes = buffer_size-pbuffer_size; + goto exit_check; + } + /* Check if frame is valid and get frame info */ + i_frame_size = ((pbuffer[1] & 0x1f) << 8) + pbuffer[2]; + if (i_frame_size <= 0 || i_frame_size > 6 * 768) { + LATM_LOG("i_frame_size/%d error\n",i_frame_size); + pbuffer++; + pbuffer_size--; + goto NEXT_CHECK; + } + if (pbuffer_size < (LOAS_HEADER_SIZE + i_frame_size)) { + LATM_LOG("[%s %d]buffer size %d small then frame size %d,\n", __FUNCTION__,__LINE__,pbuffer_size, i_frame_size+LOAS_HEADER_SIZE); + *skipbytes = buffer_size-pbuffer_size; + goto exit_check; + } +#if 1 + if (pbuffer[LOAS_HEADER_SIZE + i_frame_size] != 0x56 || (pbuffer[LOAS_HEADER_SIZE + i_frame_size + 1] & 0xe0) != 0xe0) { // next frame LOAS sync header detected + LATM_LOG("emulated sync word no (sync on following frame) \n"); + pbuffer++; + pbuffer_size--; + goto NEXT_CHECK; + } +#endif + pbuffer += LOAS_HEADER_SIZE; //skip header + pbuffer_size = pbuffer_size - LOAS_HEADER_SIZE; + //parse the playload of one real LOAS aac frame + i_frame_size = LOASParse(pbuffer, i_frame_size, p_sys); + if (i_frame_size <= 0) { + LATM_LOG("[%s %d]invalid i_frame_size/%d ,go on next check!...\n", __FUNCTION__, __LINE__, i_frame_size); + goto NEXT_CHECK; + } else { + LATM_LOG("latm detected\n"); + hDecoder->latm_header_present = 1; + } + //assue latm detected. start init code +exit_check: + if (m->i_streams > 0) { + st = &m->stream[m->i_streams - 1]; + } + memset(l, 0, sizeof(latm_header)); + if (st && st->i_extra || is_latm_external) { + int32_t x; + + hDecoder->latm_header_present = 1; + if (st && st->i_extra) { + x = NeAACDecInit2(hDecoder, st->extra, st->i_extra, samplerate, channels); + } else { + x = -1; + } + if (x != 0) { + hDecoder->latm_header_present = 0; + } +#ifdef USE_HELIX_AAC_DECODER + else { + hAACDecoder = AACInitDecoder(); + if (!hAACDecoder) { + faad_log_info("fatal error,helix aac decoder init failed\n"); + return -1; + } else { + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + if (aacDecInfo) { + aacDecInfo->format = AAC_FF_ADTS; + aacDecInfo->nChans = *channels; + } else { + LATM_LOG("aacDecInfo NULL\n"); + return NULL; + } + } + } +#endif + LATM_LOG("latm init ret %d \n", x); + return x; + } else +#else + memset(l, 0, sizeof(latm_header)); + is_latm = latmCheck(l, &ld); + l->inited = 0; + l->frameLength = 0; + faad_rewindbits(&ld); + if (is_latm && l->ASCbits > 0) { + int32_t x; + hDecoder->latm_header_present = 1; + x = NeAACDecInit2(hDecoder, l->ASC, (l->ASCbits + 7) / 8, samplerate, channels); + if (x != 0) { + hDecoder->latm_header_present = 0; + } + return x; + } else +#endif + /* Check if an ADIF header is present */ + if ((buffer[0] == 'A') && (buffer[1] == 'D') && + (buffer[2] == 'I') && (buffer[3] == 'F')) { + hDecoder->adif_header_present = 1; + faad_log_info("[%s %d]ADIF aac file detected\n", __FUNCTION__, __LINE__); + get_adif_header(&adif, &ld); + faad_byte_align(&ld); + + hDecoder->sf_index = adif.pce[0].sf_index; + hDecoder->object_type = adif.pce[0].object_type + 1; + + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = adif.pce[0].channels; + + memcpy(&(hDecoder->pce), &(adif.pce[0]), sizeof(program_config)); + hDecoder->pce_set = 1; + + bits = bit2byte(faad_get_processed_bits(&ld)); + + /* Check if an ADTS header is present */ + } else if (faad_showbits(&ld, 12) == 0xfff) { + hDecoder->adts_header_present = 1; + + adts.old_format = hDecoder->config.useOldADTSFormat; + adts_frame(&adts, &ld); + + hDecoder->sf_index = adts.sf_index; + hDecoder->object_type = adts.profile + 1; + if (adts.sf_index >= 0 && adts.sf_index < 12 && adts.channel_configuration > 0 && adts.channel_configuration <= 8) { + hDecoder->last_sf_index = hDecoder->sf_index; + hDecoder->last_ch_configure = adts.channel_configuration; + } + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = (adts.channel_configuration > 6) ? + 2 : adts.channel_configuration; + } else { + /*we guess it is a ADTS aac files and try to resync from the error*/ + int ii; + int adts_err = 0; + faad_log_info("[%s %d]guess it is a ADTS aac files and try to resync\n", __FUNCTION__, __LINE__); + faad_initbits(&ld, buffer, buffer_size); + for (ii = 0; ii < buffer_size; ii++) { + if ((faad_showbits(&ld, 16) & 0xfff6) != 0xFFF0) { + faad_getbits(&ld, 8 + DEBUGVAR(0, 0, "")); + } else { + bits = bit2byte(faad_get_processed_bits(&ld)); + hDecoder->adts_header_present = 1; + faad_log_info("[%s %d]resync and got ADTS header\n", __FUNCTION__, __LINE__); + adts.old_format = hDecoder->config.useOldADTSFormat; + adts_err = adts_frame(&adts, &ld); + if (adts_err == 5) { + return -1; + } + hDecoder->sf_index = adts.sf_index; + hDecoder->object_type = adts.profile + 1; + faad_log_info("sf index %d,object type %d \n", hDecoder->sf_index, hDecoder->object_type); + if (adts.sf_index >= 0 && adts.sf_index < 12 && adts.channel_configuration > 0 && adts.channel_configuration <= 8) { + hDecoder->last_sf_index = hDecoder->sf_index; + hDecoder->last_ch_configure = adts.channel_configuration; + } + *samplerate = get_sample_rate(hDecoder->sf_index); + if (*samplerate > 96000 || adts.channel_configuration > 6 || hDecoder->sf_index >= 12) { + return -1; + } + *channels = (adts.channel_configuration > 6) ? 2 : adts.channel_configuration; + faad_log_info("[%s %d]resync adts info:FS/%d object_type/%d chnum/%d\n", __FUNCTION__, __LINE__, *samplerate, hDecoder->object_type, channels); + break; + } + } + if (ii == buffer_size) { + faad_log_info("[%s %d]sync for adts frame failed\n", __FUNCTION__, __LINE__); + return -1; + } + } + } + if (ld.error) { + faad_endbits(&ld); + return -1; + } + faad_endbits(&ld); + +#if (defined(PS_DEC) || defined(DRM_PS)) + /* check if we have a mono file */ + if (*channels == 1) { + /* upMatrix to 2 channels for implicit signalling of PS */ + *channels = 2; + } +#endif + + hDecoder->channelConfiguration = *channels; + +#ifdef SBR_DEC + /* implicit signalling */ + if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) { + *samplerate *= 2; + hDecoder->forceUpSampling = 1; + } else if (*samplerate > 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) { + hDecoder->downSampledSBR = 1; + } +#endif + + /* must be done before frameLength is divided by 2 for LD */ +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) { + hDecoder->fb = ssr_filter_bank_init(hDecoder->frameLength / SSR_BANDS); + } else +#endif + hDecoder->fb = filter_bank_init(hDecoder->frameLength); + +#ifdef LD_DEC + if (hDecoder->object_type == LD) { + hDecoder->frameLength >>= 1; + } +#endif + + if (can_decode_ot(hDecoder->object_type) < 0) { + faad_log_info("[%s %d]object_type/%d can not support\n", __FUNCTION__, __LINE__, hDecoder->object_type); + return -1; + } + faad_log_info("[%s %d]aac init finished. cost bits%d\n", __FUNCTION__, __LINE__, bits); + return bits; +} + +/* Init the library using a DecoderSpecificInfo */ +int NEAACDECAPI NeAACDecInit2(NeAACDecHandle hpDecoder, + unsigned char *pBuffer, + unsigned long SizeOfDecoderSpecificInfo, + unsigned long *samplerate, + unsigned char *channels) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + int8_t rc; + mp4AudioSpecificConfig mp4ASC; + faad_log_info("enter NeAACDecInit2 \r\n"); + faad_log_info("extra data size %d\r\n", SizeOfDecoderSpecificInfo); + if ((hDecoder == NULL) + || (pBuffer == NULL) + || (SizeOfDecoderSpecificInfo < 2) + || (samplerate == NULL) + || (channels == NULL)) { + return -1; + } + + hDecoder->adif_header_present = 0; + hDecoder->adts_header_present = 0; + + /* decode the audio specific config */ + rc = AudioSpecificConfig2(pBuffer, SizeOfDecoderSpecificInfo, &mp4ASC, + &(hDecoder->pce), hDecoder->latm_header_present); + + /* copy the relevant info to the decoder handle */ + *samplerate = mp4ASC.samplingFrequency; + if (mp4ASC.channelsConfiguration) { + *channels = mp4ASC.channelsConfiguration; + } else { + *channels = hDecoder->pce.channels; + hDecoder->pce_set = 1; + } +#if (defined(PS_DEC) || defined(DRM_PS)) + /* check if we have a mono file */ + if (*channels == 1) { + /* upMatrix to 2 channels for implicit signalling of PS */ + *channels = 2; + } +#endif + hDecoder->sf_index = mp4ASC.samplingFrequencyIndex; + hDecoder->object_type = mp4ASC.objectTypeIndex; +#ifdef ERROR_RESILIENCE + hDecoder->aacSectionDataResilienceFlag = mp4ASC.aacSectionDataResilienceFlag; + hDecoder->aacScalefactorDataResilienceFlag = mp4ASC.aacScalefactorDataResilienceFlag; + hDecoder->aacSpectralDataResilienceFlag = mp4ASC.aacSpectralDataResilienceFlag; +#endif +#ifdef SBR_DEC + hDecoder->sbr_present_flag = mp4ASC.sbr_present_flag; + hDecoder->downSampledSBR = mp4ASC.downSampledSBR; + if (hDecoder->config.dontUpSampleImplicitSBR == 0) { + hDecoder->forceUpSampling = mp4ASC.forceUpSampling; + } else { + hDecoder->forceUpSampling = 0; + } + + /* AAC core decoder samplerate is 2 times as low */ + if (((hDecoder->sbr_present_flag == 1) && (!hDecoder->downSampledSBR)) || hDecoder->forceUpSampling == 1) { + hDecoder->sf_index = get_sr_index(mp4ASC.samplingFrequency / 2); + } +#endif + + if (rc != 0) { + return rc; + } + hDecoder->channelConfiguration = mp4ASC.channelsConfiguration; + if (mp4ASC.frameLengthFlag) +#ifdef ALLOW_SMALL_FRAMELENGTH + hDecoder->frameLength = 960; +#else + return -1; +#endif + + /* must be done before frameLength is divided by 2 for LD */ +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) { + hDecoder->fb = ssr_filter_bank_init(hDecoder->frameLength / SSR_BANDS); + } else +#endif + hDecoder->fb = filter_bank_init(hDecoder->frameLength); + +#ifdef LD_DEC + if (hDecoder->object_type == LD) { + hDecoder->frameLength >>= 1; + } +#endif + faad_log_info("aac init2 finished\r\n"); + return 0; +} + +#ifdef DRM +char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hpDecoder, + unsigned long samplerate, + unsigned char channels) +{ + NeAACDecStruct** hDecoder = (NeAACDecStruct**)hpDecoder; + if (hDecoder == NULL) { + return 1; /* error */ + } + + NeAACDecClose(*hDecoder); + + *hDecoder = NeAACDecOpen(); + + /* Special object type defined for DRM */ + (*hDecoder)->config.defObjectType = DRM_ER_LC; + + (*hDecoder)->config.defSampleRate = samplerate; +#ifdef ERROR_RESILIENCE // This shoudl always be defined for DRM + (*hDecoder)->aacSectionDataResilienceFlag = 1; /* VCB11 */ + (*hDecoder)->aacScalefactorDataResilienceFlag = 0; /* no RVLC */ + (*hDecoder)->aacSpectralDataResilienceFlag = 1; /* HCR */ +#endif + (*hDecoder)->frameLength = 960; + (*hDecoder)->sf_index = get_sr_index((*hDecoder)->config.defSampleRate); + (*hDecoder)->object_type = (*hDecoder)->config.defObjectType; + + if ((channels == DRMCH_STEREO) || (channels == DRMCH_SBR_STEREO)) { + (*hDecoder)->channelConfiguration = 2; + } else { + (*hDecoder)->channelConfiguration = 1; + } + +#ifdef SBR_DEC + if ((channels == DRMCH_MONO) || (channels == DRMCH_STEREO)) { + (*hDecoder)->sbr_present_flag = 0; + } else { + (*hDecoder)->sbr_present_flag = 1; + } +#endif + + (*hDecoder)->fb = filter_bank_init((*hDecoder)->frameLength); + + return 0; +} +#endif + +void NEAACDECAPI NeAACDecClose(NeAACDecHandle hpDecoder) +{ + uint8_t i; + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; +#ifdef USE_HELIX_AAC_DECODER + if (hAACDecoder) { + AACFreeDecoder(hAACDecoder); + hAACDecoder = NULL; + } +#endif + if (hDecoder == NULL) { + return; + } + +#ifdef PROFILE + //printk("AAC decoder total: %I64d cycles\n", hDecoder->cycles); + //printk("requant: %I64d cycles\n", hDecoder->requant_cycles); + //printk("spectral_data: %I64d cycles\n", hDecoder->spectral_cycles); + //printk("scalefactors: %I64d cycles\n", hDecoder->scalefac_cycles); + //printk("output: %I64d cycles\n", hDecoder->output_cycles); +#endif + + for (i = 0; i < MAX_CHANNELS; i++) { + if (hDecoder->time_out[i]) { + faad_free(hDecoder->time_out[i]); + } + if (hDecoder->fb_intermed[i]) { + faad_free(hDecoder->fb_intermed[i]); + } +#ifdef SSR_DEC + if (hDecoder->ssr_overlap[i]) { + faad_free(hDecoder->ssr_overlap[i]); + } + if (hDecoder->prev_fmd[i]) { + faad_free(hDecoder->prev_fmd[i]); + } +#endif +#ifdef MAIN_DEC + if (hDecoder->pred_stat[i]) { + faad_free(hDecoder->pred_stat[i]); + } +#endif +#ifdef LTP_DEC + if (hDecoder->lt_pred_stat[i]) { + faad_free(hDecoder->lt_pred_stat[i]); + } +#endif + } + +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) { + ssr_filter_bank_end(hDecoder->fb); + } else +#endif + filter_bank_end(hDecoder->fb); + + drc_end(hDecoder->drc); + + if (hDecoder->sample_buffer) { + faad_free(hDecoder->sample_buffer); + } + + + if (hDecoder->sample_buffer_all) { + faad_free(hDecoder->sample_buffer_all); + } + +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) { + if (hDecoder->sbr[i]) { + sbrDecodeEnd(hDecoder->sbr[i]); + } + } +#endif + //why not free before? + if (hDecoder) { + faad_free(hDecoder); + } +} + +void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hpDecoder, long frame) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder) { + hDecoder->postSeekResetFlag = 1; + + if (frame != -1) { + hDecoder->frame = frame; + } + } +} + +static void create_channel_config(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo) +{ + hInfo->num_front_channels = 0; + hInfo->num_side_channels = 0; + hInfo->num_back_channels = 0; + hInfo->num_lfe_channels = 0; + memset(hInfo->channel_position, 0, MAX_CHANNELS * sizeof(uint8_t)); + + if (hDecoder->downMatrix) { + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; + return; + } + + /* check if there is a PCE */ + if (hDecoder->pce_set) { + uint8_t i, chpos = 0; + uint8_t chdir, back_center = 0; + + hInfo->num_front_channels = hDecoder->pce.num_front_channels; + hInfo->num_side_channels = hDecoder->pce.num_side_channels; + hInfo->num_back_channels = hDecoder->pce.num_back_channels; + hInfo->num_lfe_channels = hDecoder->pce.num_lfe_channels; + + chdir = hInfo->num_front_channels; + if (chdir & 1) { +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT; +#else + hInfo->channel_position[chpos++] = FRONT_CHANNEL_CENTER; + chdir--; +#endif + } + for (i = 0; i < chdir; i += 2) { + hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT; + } + + for (i = 0; i < hInfo->num_side_channels; i += 2) { + hInfo->channel_position[chpos++] = SIDE_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = SIDE_CHANNEL_RIGHT; + } + + chdir = hInfo->num_back_channels; + if (chdir & 1) { + back_center = 1; + chdir--; + } + for (i = 0; i < chdir; i += 2) { + hInfo->channel_position[chpos++] = BACK_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = BACK_CHANNEL_RIGHT; + } + if (back_center) { + hInfo->channel_position[chpos++] = BACK_CHANNEL_CENTER; + } + + for (i = 0; i < hInfo->num_lfe_channels; i++) { + hInfo->channel_position[chpos++] = LFE_CHANNEL; + } + + } else { + switch (hDecoder->channelConfiguration) { + case 1: +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; +#else + hInfo->num_front_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; +#endif + break; + case 2: + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; + break; + case 3: + hInfo->num_front_channels = 3; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + break; + case 4: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_CENTER; + break; + case 5: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_LEFT; + hInfo->channel_position[4] = BACK_CHANNEL_RIGHT; + break; + case 6: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 2; + hInfo->num_lfe_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_LEFT; + hInfo->channel_position[4] = BACK_CHANNEL_RIGHT; + hInfo->channel_position[5] = LFE_CHANNEL; + break; + case 7: + hInfo->num_front_channels = 3; + hInfo->num_side_channels = 2; + hInfo->num_back_channels = 2; + hInfo->num_lfe_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = SIDE_CHANNEL_LEFT; + hInfo->channel_position[4] = SIDE_CHANNEL_RIGHT; + hInfo->channel_position[5] = BACK_CHANNEL_LEFT; + hInfo->channel_position[6] = BACK_CHANNEL_RIGHT; + hInfo->channel_position[7] = LFE_CHANNEL; + break; + default: { /* channelConfiguration == 0 || channelConfiguration > 7 */ + uint8_t i; + uint8_t ch = hDecoder->fr_channels - hDecoder->has_lfe; + if (ch & 1) { /* there's either a center front or a center back channel */ + uint8_t ch1 = (ch - 1) / 2; + if (hDecoder->first_syn_ele == ID_SCE) { + hInfo->num_front_channels = ch1 + 1; + hInfo->num_back_channels = ch1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + for (i = 1; i <= ch1; i += 2) { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1 + 1; i < ch; i += 2) { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = BACK_CHANNEL_RIGHT; + } + } else { + hInfo->num_front_channels = ch1; + hInfo->num_back_channels = ch1 + 1; + for (i = 0; i < ch1; i += 2) { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1; i < ch - 1; i += 2) { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = BACK_CHANNEL_RIGHT; + } + hInfo->channel_position[ch - 1] = BACK_CHANNEL_CENTER; + } + } else { + uint8_t ch1 = (ch) / 2; + hInfo->num_front_channels = ch1; + hInfo->num_back_channels = ch1; + if (ch1 & 1) { + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + for (i = 1; i <= ch1; i += 2) { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1 + 1; i < ch - 1; i += 2) { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = BACK_CHANNEL_RIGHT; + } + hInfo->channel_position[ch - 1] = BACK_CHANNEL_CENTER; + } else { + for (i = 0; i < ch1; i += 2) { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1; i < ch; i += 2) { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i + 1] = BACK_CHANNEL_RIGHT; + } + } + } + hInfo->num_lfe_channels = hDecoder->has_lfe; + for (i = ch; i < hDecoder->fr_channels; i++) { + hInfo->channel_position[i] = LFE_CHANNEL; + } + } + break; + } + } +} + +void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hpDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + return aac_frame_decode(hDecoder, hInfo, buffer, buffer_size, NULL, 0); +} + +void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hpDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer, + unsigned long sample_buffer_size) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if ((sample_buffer == NULL) || (sample_buffer_size == 0)) { + hInfo->error = 27; + return NULL; + } + + return aac_frame_decode(hDecoder, hInfo, buffer, buffer_size, + sample_buffer, sample_buffer_size); +} + +#ifdef DRM + +#define ERROR_STATE_INIT 6 + +static void conceal_output(NeAACDecStruct *hDecoder, uint16_t frame_len, + uint8_t out_ch, void *sample_buffer) +{ + return; +} +#endif + +static int multi_sub_frame(NeAACDecStruct *hDecoder) +{ +#ifdef NEW_CODE_CHECK_LATM + int i_frame_size; + decoder_sys_t *p_sys = &hDecoder->dec_sys; + + if (hDecoder->latm_header_present && p_sys->latm.i_sub_frames > 1) + return 1; +#endif + + return 0; +} + +static void* aac_frame_decode(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer2, + unsigned long sample_buffer_size) +{ + uint16_t i; + uint8_t channels = 0; + uint8_t output_channels = 0; + bitfile ld = {0}; + uint32_t bitsconsumed; + uint16_t frame_len; + void *sample_buffer; + uint32_t startbit = 0, endbit = 0, payload_bits = 0; + int b_multi_sub_frame; + int mux_length = 0; +#ifdef NEW_CODE_CHECK_LATM + int i_frame_size; + decoder_sys_t *p_sys = &hDecoder->dec_sys; +#endif +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + /* safety checks */ + if ((hDecoder == NULL) || (hInfo == NULL) || (buffer == NULL)) { + return NULL; + } + + frame_len = hDecoder->frameLength; + memset(hInfo, 0, sizeof(NeAACDecFrameInfo)); + memset(hDecoder->internal_channel, 0, MAX_CHANNELS * sizeof(hDecoder->internal_channel[0])); + +#ifdef USE_TIME_LIMIT + if ((TIME_LIMIT * get_sample_rate(hDecoder->sf_index)) > hDecoder->TL_count) { + hDecoder->TL_count += 1024; + } else { + hInfo->error = (NUM_ERROR_MESSAGES - 1); + goto error; + } +#endif + + + /* check for some common metadata tag types in the bitstream + * No need to return an error + */ + /* ID3 */ + if (buffer_size >= 128) { + if (memcmp(buffer, "TAG", 3) == 0) { + /* found it */ + hInfo->bytesconsumed = 128; /* 128 bytes fixed size */ + /* no error, but no output either */ + return NULL; + } + } +#ifdef NEW_CODE_CHECK_LATM + if (buffer_size > sizeof(temp_bufer)) { + LATM_LOG("input buffer size tooo big %d, buffer size %d \n", buffer_size, sizeof(temp_bufer)); + buffer_size = sizeof(temp_bufer); + } + if (buffer_size > 0) { + memcpy(temp_bufer, buffer, buffer_size); + temp_size = buffer_size; + buffer = temp_bufer; + } +NEXT_CHECK: + if (hDecoder->latm_header_present) { + while (buffer_size >= 7) { + if (buffer[0] == 0x56 && (buffer[1] & 0xe0) == 0xe0) { + + break; + } + buffer++; + buffer_size--; + } + if (buffer_size <= 2) { + LATM_LOG("check the loas frame failed\n"); + return NULL; + } + /* Check if frame is valid and get frame info */ + i_frame_size = ((buffer[1] & 0x1f) << 8) + buffer[2]; + //LATM_LOG("i_frame_size %d \n",i_frame_size); + mux_length = i_frame_size + 3; + if (i_frame_size <= 0) { + LATM_LOG("i_frame_size error\n"); + return NULL; + } + if (buffer_size < (LOAS_HEADER_SIZE + i_frame_size)) { + hInfo->error = 35; + LATM_LOG("buffer size small then frame size,need more data\n"); + return NULL; + } +#if 1 + if (buffer[3 + i_frame_size] != 0x56 || (buffer[3 + i_frame_size + 1] & 0xe0) != 0xe0) { + + LATM_LOG("emulated sync word (no sync on following frame) \n"); + buffer++; + buffer_size--; + goto NEXT_CHECK; + } +#endif + buffer += LOAS_HEADER_SIZE; //skip header + buffer_size = buffer_size - LOAS_HEADER_SIZE; + i_frame_size = LOASParse(buffer, i_frame_size, p_sys); + if (i_frame_size <= 0) { + goto NEXT_CHECK; + } else { + // LATM_LOG("latm detected\n"); + } + + } + + b_multi_sub_frame = multi_sub_frame(hDecoder); + + /* check if we want to use internal sample_buffer */ + if (sample_buffer_size == 0 && b_multi_sub_frame) { + if (hDecoder->sample_buffer_all) { + faad_free(hDecoder->sample_buffer_all); + } + hDecoder->sample_buffer_all = NULL; + } +#endif + +start_decode: + + /* initialize the bitstream */ + faad_initbits(&ld, buffer, buffer_size); + +#ifndef NEW_CODE_CHECK_LATM + if (hDecoder->latm_header_present) { + payload_bits = faad_latm_frame(&hDecoder->latm_config, &ld); + startbit = faad_get_processed_bits(&ld); + if (payload_bits == -1U) { + hInfo->error = 1; + goto error; + } + } +#endif +#ifdef DRM + if (hDecoder->object_type == DRM_ER_LC) { + /* We do not support stereo right now */ + if (0) { //(hDecoder->channelConfiguration == 2) + hInfo->error = 28; // Throw CRC error + goto error; + } + + faad_getbits(&ld, 8 + DEBUGVAR(1, 1, "NeAACDecDecode(): skip CRC")); + } +#endif + + if (hDecoder->adts_header_present) { + adts_header adts; + + adts.old_format = hDecoder->config.useOldADTSFormat; + if ((hInfo->error = adts_frame(&adts, &ld)) > 0) { + goto error; + } + if (adts.aac_frame_length > buffer_size) { + hInfo->error = 35; //more data needed + audio_codec_print("decoder need more data for adts frame,frame len %d,have %d \n", adts.aac_frame_length, buffer_size); + if (adts.aac_frame_length > 6 * 768) { + audio_codec_print("adts frame len exceed aac spec \n"); + hInfo->error = 36;// + goto error; + + } + //here need return to get more input data for decoder + faad_endbits(&ld); + return NULL; + } + if (adts.sf_index >= 12 || adts.channel_configuration > 6) { + audio_codec_print("adts sf/ch error,sf %d,ch config %d \n", adts.sf_index, adts.channel_configuration); + hDecoder->sf_index = 3; + hInfo->error = 12; + goto error; + } + hDecoder->sf_index = adts.sf_index; + if (adts.sf_index != hDecoder->last_sf_index && adts.channel_configuration != hDecoder->last_ch_configure) { + if (adts.sf_index >= 0 && adts.sf_index < 12 && adts.channel_configuration > 0 && adts.channel_configuration <= 8) { + hInfo->error = 34; + audio_codec_print("[%s %d]last_sf_index/%d,Ch/%d,Now %d/%d\n", __FUNCTION__, __LINE__, hDecoder->last_sf_index, hDecoder->last_ch_configure, adts.sf_index, adts.channel_configuration); + hDecoder->last_sf_index = hDecoder->sf_index; + hDecoder->last_ch_configure = adts.channel_configuration; + goto error; + } + } + } + +#ifdef ANALYSIS + dbg_count = 0; +#endif + + /* decode the complete bitstream */ +#ifdef DRM + if (/*(hDecoder->object_type == 6) ||*/ (hDecoder->object_type == DRM_ER_LC)) { + DRM_aac_scalable_main_element(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); + } else { +#endif + raw_data_block(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); +#ifdef DRM + } +#endif +#ifndef NEW_CODE_CHECK_LATM + if (hDecoder->latm_header_present) { + endbit = faad_get_processed_bits(&ld); + if (endbit - startbit > payload_bits) + DEBUG("[%s %d]ERROR, too many payload bits read: %u > %d. Please. report with a link to a sample\n", + __FUNCTION__, __LINE__, endbit - startbit, payload_bits); + if (hDecoder->latm_config.otherDataLenBits > 0) { + faad_getbits(&ld, hDecoder->latm_config.otherDataLenBits); + } + faad_byte_align(&ld); + } +#endif + + channels = hDecoder->fr_channels; + + if (hInfo->error > 0) { + goto error; + } + + /* safety check */ + if (channels == 0 || channels > MAX_CHANNELS) { + DEBUG("[%s %d]invalid Channels/%d\n", __FUNCTION__, __LINE__, channels); + hInfo->error = 12; + goto error; + } + + /* no more bit reading after this */ + bitsconsumed = faad_get_processed_bits(&ld); + hInfo->bytesconsumed = bit2byte(bitsconsumed); + if (mux_length && hDecoder->latm_header_present && !ld.error) { + if (p_sys->latm.i_sub_frames <= 1) + hInfo->bytesconsumed = mux_length; + } + if (ld.error) { + hInfo->error = 14; + goto error; + } + faad_endbits(&ld); + + + if (!hDecoder->adts_header_present && !hDecoder->adif_header_present +#if 1 + && !hDecoder->latm_header_present +#endif + ) { + if (hDecoder->channelConfiguration == 0) { + hDecoder->channelConfiguration = channels; + } + + if (channels == 8) { /* 7.1 */ + hDecoder->channelConfiguration = 7; + } + if (channels == 7) { /* not a standard channelConfiguration */ + hDecoder->channelConfiguration = 0; + } + } + + if ((channels == 5 || channels == 6) && hDecoder->config.downMatrix) { + hDecoder->downMatrix = 1; + output_channels = 2; + } else { + // output_channels = channels; + if (channels == 6 || channels == 4) { + output_channels = 2; + } else if (channels == 3 && hDecoder->config.downMatrix) { + output_channels = 2; + } else { + output_channels = channels; + } + } + +#if (defined(PS_DEC) || defined(DRM_PS)) + hDecoder->upMatrix = 0; + /* check if we have a mono file */ + if (output_channels == 1) { + /* upMatrix to 2 channels for implicit signalling of PS */ + hDecoder->upMatrix = 1; + output_channels = 2; + } +#endif + + /* Make a channel configuration based on either a PCE or a channelConfiguration */ + create_channel_config(hDecoder, hInfo); + + /* number of samples in this frame */ + hInfo->samples = frame_len * output_channels; + /* number of channels in this frame */ + hInfo->channels = output_channels; + /* samplerate */ + hInfo->samplerate = get_sample_rate(hDecoder->sf_index); + /* object type */ + hInfo->object_type = hDecoder->object_type; + /* sbr */ + hInfo->sbr = NO_SBR; + /* header type */ + hInfo->header_type = RAW; + if (hDecoder->adif_header_present) { + hInfo->header_type = ADIF; + } + if (hDecoder->adts_header_present) { + hInfo->header_type = ADTS; + } +#if 1 + if (hDecoder->latm_header_present) { + hInfo->header_type = LATM; + } +#endif +#if (defined(PS_DEC) || defined(DRM_PS)) + hInfo->ps = hDecoder->ps_used_global; +#endif + + /* check if frame has channel elements */ + if (channels == 0) { + hDecoder->frame++; + return NULL; + } + + /* allocate the buffer for the final samples */ + if ((hDecoder->sample_buffer == NULL) || + (hDecoder->alloced_channels != output_channels)) { + static const uint8_t str[] = { sizeof(int16_t), sizeof(int32_t), sizeof(int32_t), + sizeof(float32_t), sizeof(double), sizeof(int16_t), sizeof(int16_t), + sizeof(int16_t), sizeof(int16_t), 0, 0, 0 + }; + uint8_t stride = str[hDecoder->config.outputFormat - 1]; +#ifdef SBR_DEC + if (((hDecoder->sbr_present_flag == 1) && (!hDecoder->downSampledSBR)) || (hDecoder->forceUpSampling == 1)) { + stride = 2 * stride; + } +#endif + /* check if we want to use internal sample_buffer */ + if (sample_buffer_size == 0) { + if (hDecoder->sample_buffer) { + faad_free(hDecoder->sample_buffer); + } + hDecoder->sample_buffer = NULL; + hDecoder->sample_buffer = faad_malloc(frame_len * output_channels * stride); + } else if (sample_buffer_size < frame_len * output_channels * stride) { + /* provided sample buffer is not big enough */ + hInfo->error = 27; + return NULL; + } + hDecoder->alloced_channels = output_channels; + } + + if (sample_buffer_size == 0) { + sample_buffer = hDecoder->sample_buffer; + } else { + sample_buffer = *sample_buffer2; + } + +#ifdef SBR_DEC + if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) { + uint8_t ele; + + /* this data is different when SBR is used or when the data is upsampled */ + if (!hDecoder->downSampledSBR) { + frame_len *= 2; + hInfo->samples *= 2; + hInfo->samplerate *= 2; + } + + /* check if every element was provided with SBR data */ + for (ele = 0; ele < hDecoder->fr_ch_ele; ele++) { + if (hDecoder->sbr[ele] == NULL) { + hInfo->error = 25; + goto error; + } + } + + /* sbr */ + if (hDecoder->sbr_present_flag == 1) { + hInfo->object_type = HE_AAC; + hInfo->sbr = SBR_UPSAMPLED; + } else { + hInfo->sbr = NO_SBR_UPSAMPLED; + } + if (hDecoder->downSampledSBR) { + hInfo->sbr = SBR_DOWNSAMPLED; + } + } +#endif + + if (b_multi_sub_frame && sample_buffer_size == 0 && + hDecoder->sample_buffer_all == NULL) { + + hDecoder->sample_buffer_all = faad_malloc(p_sys->latm.i_sub_frames * hInfo->samples * 2); + } + + sample_buffer = output_to_PCM(hDecoder, hDecoder->time_out, sample_buffer, + output_channels, frame_len, hDecoder->config.outputFormat); + + if (b_multi_sub_frame && i_frame_size > 0 && sample_buffer_size == 0) { + + memcpy(hDecoder->sample_buffer_all,sample_buffer,hInfo->samples * 2); + hDecoder->sample_buffer_all += hInfo->samples * 2; + i_frame_size -= hInfo->bytesconsumed; + buffer += hInfo->bytesconsumed; + buffer_size -= hInfo->bytesconsumed; + if (i_frame_size > 0) + goto start_decode; + } + + if (b_multi_sub_frame && sample_buffer_size == 0) { + // calculate all sub_frames as one samples + hInfo->samples = hInfo->samples * p_sys->latm.i_sub_frames; + hDecoder->sample_buffer_all -= hInfo->samples * 2; + hInfo->bytesconsumed = mux_length; + return hDecoder->sample_buffer_all; + } + + +#ifdef DRM + //conceal_output(hDecoder, frame_len, output_channels, sample_buffer); +#endif + + + hDecoder->postSeekResetFlag = 0; + + hDecoder->frame++; +#ifdef LD_DEC + if (hDecoder->object_type != LD) { +#endif + if (hDecoder->frame <= 1) { + hInfo->samples = 0; + } +#ifdef LD_DEC + } else { + /* LD encoders will give lower delay */ + if (hDecoder->frame <= 0) { + hInfo->samples = 0; + } + } +#endif + + /* cleanup */ +#ifdef ANALYSIS + fflush(stdout); +#endif + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->cycles += count; +#endif + +#ifdef USE_HELIX_AAC_DECODER + /* Channel definitions */ +#define FRONT_CENTER (0) +#define FRONT_LEFT (1) +#define FRONT_RIGHT (2) +#define SIDE_LEFT (3) +#define SIDE_RIGHT (4) +#define BACK_LEFT (5) +#define LFE_CHANNEL (6) + + if (hDecoder->latm_header_present && !hInfo->error) { + unsigned char *dec_buf = buffer; + int dec_size = hInfo->bytesconsumed ; + int err; + int ch_num; + int sample_out; + int sum; + unsigned ch_map_scale[6] = {2, 4, 4, 2, 2, 0}; //full scale == 8 + short *ouput = dec_buffer; + unsigned char adts_header[7]; + unsigned char *pbuf = NULL; + unsigned char *inbuf = NULL; +#ifdef PS_DEC + if (hDecoder->ps_used_global) { + // LATM_LOG("decoder ps channel %d \n",channels); + if (channels == 2) { + channels = 1; + } + } +#endif + MakeAdtsHeader(hInfo, adts_header, channels); + pbuf = malloc(7 + dec_size); + if (!pbuf) { + LATM_LOG("malloc decoder buffer failed %d \n", dec_size); + return NULL; + } + dec_size += 7; + memcpy(pbuf, adts_header, 7); + memcpy(pbuf + 7, buffer, hInfo->bytesconsumed); + inbuf = pbuf; + err = AACDecode(hAACDecoder, &inbuf, &dec_size, dec_buffer); + if (pbuf) { + free(pbuf); + pbuf = NULL; + } + if (err == 0) { + AACFrameInfo aacFrameInfo = {0}; + AACGetLastFrameInfo(hAACDecoder, &aacFrameInfo); + hInfo->error = 0; + hInfo->bytesconsumed = mux_length; + hInfo->channels = aacFrameInfo.nChans > 2 ? 2 : aacFrameInfo.nChans; + hInfo->samplerate = aacFrameInfo.sampRateOut;; + if (aacFrameInfo.nChans > 2) { //should do downmix to 2ch output. + ch_num = aacFrameInfo.nChans; + sample_out = aacFrameInfo.outputSamps / ch_num * 2 * 2; //ch_num*sample_num*16bit + if (ch_num == 3 || ch_num == 4) { + ch_map_scale[0] = 4; //50% + ch_map_scale[1] = 4;//50% + ch_map_scale[2] = 4;//50% + ch_map_scale[3] = 0; + ch_map_scale[4] = 0; + ch_map_scale[5] = 0; + } + for (i = 0; i < aacFrameInfo.outputSamps / ch_num; i++) { + if (ch_num == 5 || ch_num == 6) { + output_buffer[i * 2] = ((int)(ouput[ch_num * i + FRONT_LEFT]) + + ((int)((((int)ouput[ch_num * i + FRONT_CENTER]) - + ((int)ouput[ch_num * i + SIDE_LEFT]) - + ((int)ouput[ch_num * i + SIDE_RIGHT])) * 707 / 1000))); + output_buffer[2 * i + 1] = ((int)(ouput[ch_num * i + FRONT_RIGHT]) + + ((int)((((int)ouput[ch_num * i + FRONT_CENTER]) + + ((int)ouput[ch_num * i + SIDE_LEFT]) + + ((int)ouput[ch_num * i + SIDE_RIGHT])) * 707 / 1000))); + } else { + sum = ((int)ouput[ch_num * i + FRONT_LEFT] * ch_map_scale[FRONT_LEFT] + (int)ouput[ch_num * i + FRONT_CENTER] * ch_map_scale[FRONT_CENTER] + (int)ouput[ch_num * i + BACK_LEFT] * ch_map_scale[BACK_LEFT]); + output_buffer[i * 2] = sum >> 3; + sum = ((int)ouput[ch_num * i + FRONT_RIGHT] * ch_map_scale[FRONT_RIGHT] + (int)ouput[ch_num * i + FRONT_CENTER] * ch_map_scale[FRONT_CENTER] + (int)ouput[ch_num * i + BACK_LEFT] * ch_map_scale[BACK_LEFT]); + output_buffer[2 * i + 1] = sum >> 3; + } + } + } else { + sample_out = aacFrameInfo.outputSamps * 2; //ch_num*sample_num*16bit + memcpy(output_buffer, dec_buffer, sample_out); + + } + hInfo->samples = sample_out / 2; + return output_buffer; + + } else { + LATM_LOG("decoder error id %d \n", err); + hInfo->error = err > 0 ? err : -err; + return NULL; + } + } +#endif + return sample_buffer; + +error: + + +#ifdef DRM + hDecoder->error_state = ERROR_STATE_INIT; +#endif + + /* reset filterbank state */ + for (i = 0; i < MAX_CHANNELS; i++) { + if (hDecoder->fb_intermed[i] != NULL) { + memset(hDecoder->fb_intermed[i], 0, hDecoder->frameLength * sizeof(real_t)); + } + } +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) { + if (hDecoder->sbr[i] != NULL) { + sbrReset(hDecoder->sbr[i]); + } + } +#endif + faad_endbits(&ld); + /* cleanup */ +#ifdef ANALYSIS + fflush(stdout); +#endif + + return NULL; +} + +int is_latm_aac(NeAACDecHandle hpDecoder) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + return hDecoder->latm_header_present; + +} + |