blob: 08f1e3d7069b61b358da1c802d92b5db3ba1d58a [file] [log] [blame]
/*
** 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 <android/log.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 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
#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
};
#if 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];
}
#endif
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;
}
#if 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);
}
#endif
#define SKIP_LATM_BYTE 16*4*2
#if 0
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;
}
#endif
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;
unsigned char* temp_bufer = hDecoder->temp_bufer;
int temp_size = 0;
memset(&ld, 0 , sizeof(ld));
faad_log_info("enter NeAACDecInit \r\n");
#ifdef NEW_CODE_CHECK_LATM
int i_frame_size;
if (buffer_size > TMP_BUF_SIZE) {
LATM_LOG("init input buffer size too big %lu, buffer size %d \n", buffer_size,TMP_BUF_SIZE);
//buffer_size = sizeof(temp_bufer);
buffer_size = TMP_BUF_SIZE ;
}
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) {
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)) {
if (0 == is_latm_external)
{
goto adts_check;
}
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;
return -1;
}
#if 0
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
int is_latm;
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
adts_check:
/* 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 < 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 < (int)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 < 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/%lu object_type/%d chnum/%d\n", __FUNCTION__, __LINE__, *samplerate, hDecoder->object_type, *channels);
break;
}
}
if (ii == (int)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 %lu\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;
short* dec_buffer = hDecoder->dec_buffer;
short* output_buffer = hDecoder->output_buffer;
unsigned char* temp_bufer = hDecoder->temp_bufer;
int temp_size = 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 > TMP_BUF_SIZE) {
LATM_LOG("input buffer size tooo big %lu, buffer size %d \n", buffer_size,TMP_BUF_SIZE);
//buffer_size = sizeof(temp_bufer);
buffer_size = TMP_BUF_SIZE;
}
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 ((int)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 0
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 %lu \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 < 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);
char * tmp = (char *)(hDecoder->sample_buffer_all);
tmp += 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;
char * tmp = (char *)(hDecoder->sample_buffer_all);
tmp -= 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;
}