* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
*
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-ffmpeg@jannau.net>
+ *
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* Y filterbank - standard
* N (code in SoC repo) filterbank - Scalable Sample Rate
* Y Temporal Noise Shaping
- * N (code in SoC repo) Long Term Prediction
+ * Y Long Term Prediction
* Y intensity stereo
* Y channel coupling
* Y frequency domain prediction
#include "get_bits.h"
#include "dsputil.h"
#include "fft.h"
+#include "fmtconvert.h"
#include "lpc.h"
+#include "kbdwin.h"
+#include "sinewin.h"
#include "aac.h"
#include "aactab.h"
#include "sbr.h"
#include "aacsbr.h"
#include "mpeg4audio.h"
-#include "aac_parser.h"
+#include "aacadtsdec.h"
#include <assert.h>
#include <errno.h>
static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
{
- /* Some buggy encoders appear to set all elem_ids to zero and rely on
- channels always occurring in the same order. This is expressly forbidden
- by the spec but we will try to work around it.
- */
- int err_printed = 0;
- while (ac->tags_seen_this_frame[type][elem_id] && elem_id < MAX_ELEM_ID) {
- if (ac->output_configured < OC_LOCKED && !err_printed) {
- av_log(ac->avctx, AV_LOG_WARNING, "Duplicate channel tag found, attempting to remap.\n");
- err_printed = 1;
- }
- elem_id++;
- }
- if (elem_id == MAX_ELEM_ID)
- return NULL;
- ac->tags_seen_this_frame[type][elem_id] = 1;
-
- if (ac->tag_che_map[type][elem_id]) {
+ // For PCE based channel configurations map the channels solely based on tags.
+ if (!ac->m4ac.chan_config) {
return ac->tag_che_map[type][elem_id];
}
- if (ac->tags_mapped >= tags_per_config[ac->m4ac.chan_config]) {
- return NULL;
- }
+ // For indexed channel configurations map the channels solely based on position.
switch (ac->m4ac.chan_config) {
case 7:
if (ac->tags_mapped == 3 && type == TYPE_CPE) {
* @return Returns error status. 0 - OK, !0 - error
*/
static av_cold int che_configure(AACContext *ac,
- enum ChannelPosition che_pos[4][MAX_ELEM_ID],
- int type, int id,
- int *channels)
+ enum ChannelPosition che_pos[4][MAX_ELEM_ID],
+ int type, int id, int *channels)
{
if (che_pos[type][id]) {
if (!ac->che[type][id] && !(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))
* @return Returns error status. 0 - OK, !0 - error
*/
static av_cold int output_configure(AACContext *ac,
- enum ChannelPosition che_pos[4][MAX_ELEM_ID],
- enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
- int channel_config, enum OCStatus oc_type)
+ enum ChannelPosition che_pos[4][MAX_ELEM_ID],
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+ int channel_config, enum OCStatus oc_type)
{
AVCodecContext *avctx = ac->avctx;
int i, type, channels = 0, ret;
return ret;
}
- memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
- ac->tags_mapped = 0;
+ memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
avctx->channel_layout = aac_channel_layout[channel_config - 1];
} else {
}
memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
- ac->tags_mapped = 4 * MAX_ELEM_ID;
avctx->channel_layout = 0;
}
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
GetBitContext *gb)
{
int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index;
skip_bits(gb, 2); // object_type
sampling_index = get_bits(gb, 4);
- if (ac->m4ac.sampling_index != sampling_index)
- av_log(ac->avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");
+ if (m4ac->sampling_index != sampling_index)
+ av_log(avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");
num_front = get_bits(gb, 4);
num_side = get_bits(gb, 4);
/* comment field, first byte is length */
comment_len = get_bits(gb, 8) * 8;
if (get_bits_left(gb) < comment_len) {
- av_log(ac->avctx, AV_LOG_ERROR, overread_err);
+ av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
skip_bits_long(gb, comment_len);
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static av_cold int set_default_channel_config(AACContext *ac,
- enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
- int channel_config)
+static av_cold int set_default_channel_config(AVCodecContext *avctx,
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+ int channel_config)
{
if (channel_config < 1 || channel_config > 7) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n",
+ av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n",
channel_config);
return -1;
}
/**
* Decode GA "General Audio" specific configuration; reference: table 4.1.
*
+ * @param ac pointer to AACContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ *
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_ga_specific_config(AACContext *ac, GetBitContext *gb,
+static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ MPEG4AudioConfig *m4ac,
int channel_config)
{
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
int extension_flag, ret;
if (get_bits1(gb)) { // frameLengthFlag
- av_log_missing_feature(ac->avctx, "960/120 MDCT window is", 1);
+ av_log_missing_feature(avctx, "960/120 MDCT window is", 1);
return -1;
}
skip_bits(gb, 14); // coreCoderDelay
extension_flag = get_bits1(gb);
- if (ac->m4ac.object_type == AOT_AAC_SCALABLE ||
- ac->m4ac.object_type == AOT_ER_AAC_SCALABLE)
+ if (m4ac->object_type == AOT_AAC_SCALABLE ||
+ m4ac->object_type == AOT_ER_AAC_SCALABLE)
skip_bits(gb, 3); // layerNr
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
if (channel_config == 0) {
skip_bits(gb, 4); // element_instance_tag
- if ((ret = decode_pce(ac, new_che_pos, gb)))
+ if ((ret = decode_pce(avctx, m4ac, new_che_pos, gb)))
return ret;
} else {
- if ((ret = set_default_channel_config(ac, new_che_pos, channel_config)))
+ if ((ret = set_default_channel_config(avctx, new_che_pos, channel_config)))
return ret;
}
- if ((ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR)))
+ if (ac && (ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR)))
return ret;
if (extension_flag) {
- switch (ac->m4ac.object_type) {
+ switch (m4ac->object_type) {
case AOT_ER_BSAC:
skip_bits(gb, 5); // numOfSubFrame
skip_bits(gb, 11); // layer_length
/**
* Decode audio specific configuration; reference: table 1.13.
*
+ * @param ac pointer to AACContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ * @param m4ac pointer to MPEG4AudioConfig, used for parsing
* @param data pointer to AVCodecContext extradata
* @param data_size size of AVCCodecContext extradata
*
- * @return Returns error status. 0 - OK, !0 - error
+ * @return Returns error status or number of consumed bits. <0 - error
*/
-static int decode_audio_specific_config(AACContext *ac, void *data,
- int data_size)
+static int decode_audio_specific_config(AACContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ const uint8_t *data, int data_size)
{
GetBitContext gb;
int i;
+ av_dlog(avctx, "extradata size %d\n", avctx->extradata_size);
+ for (i = 0; i < avctx->extradata_size; i++)
+ av_dlog(avctx, "%02x ", avctx->extradata[i]);
+ av_dlog(avctx, "\n");
+
init_get_bits(&gb, data, data_size * 8);
- if ((i = ff_mpeg4audio_get_config(&ac->m4ac, data, data_size)) < 0)
+ if ((i = ff_mpeg4audio_get_config(m4ac, data, data_size)) < 0)
return -1;
- if (ac->m4ac.sampling_index > 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->m4ac.sampling_index);
+ if (m4ac->sampling_index > 12) {
+ av_log(avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", m4ac->sampling_index);
return -1;
}
- if (ac->m4ac.sbr == 1 && ac->m4ac.ps == -1)
- ac->m4ac.ps = 1;
+ if (m4ac->sbr == 1 && m4ac->ps == -1)
+ m4ac->ps = 1;
skip_bits_long(&gb, i);
- switch (ac->m4ac.object_type) {
+ switch (m4ac->object_type) {
case AOT_AAC_MAIN:
case AOT_AAC_LC:
- if (decode_ga_specific_config(ac, &gb, ac->m4ac.chan_config))
+ case AOT_AAC_LTP:
+ if (decode_ga_specific_config(ac, avctx, &gb, m4ac, m4ac->chan_config))
return -1;
break;
default:
- av_log(ac->avctx, AV_LOG_ERROR, "Audio object type %s%d is not supported.\n",
- ac->m4ac.sbr == 1? "SBR+" : "", ac->m4ac.object_type);
+ av_log(avctx, AV_LOG_ERROR, "Audio object type %s%d is not supported.\n",
+ m4ac->sbr == 1? "SBR+" : "", m4ac->object_type);
return -1;
}
- return 0;
+
+ av_dlog(avctx, "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
+ m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
+ m4ac->sample_rate, m4ac->sbr, m4ac->ps);
+
+ return get_bits_count(&gb);
}
/**
static av_cold int aac_decode_init(AVCodecContext *avctx)
{
AACContext *ac = avctx->priv_data;
- int i;
ac->avctx = avctx;
ac->m4ac.sample_rate = avctx->sample_rate;
if (avctx->extradata_size > 0) {
- if (decode_audio_specific_config(ac, avctx->extradata, avctx->extradata_size))
+ if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac,
+ avctx->extradata,
+ avctx->extradata_size) < 0)
return -1;
}
- avctx->sample_fmt = SAMPLE_FMT_S16;
+ avctx->sample_fmt = avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT ?
+ AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16;
AAC_INIT_VLC_STATIC( 0, 304);
AAC_INIT_VLC_STATIC( 1, 270);
ff_aac_sbr_init();
dsputil_init(&ac->dsp, avctx);
+ ff_fmt_convert_init(&ac->fmt_conv, avctx);
ac->random_state = 0x1f2e3d4c;
// -1024 - Compensate wrong IMDCT method.
- // 32768 - Required to scale values to the correct range for the bias method
- // for float to int16 conversion.
-
- if (ac->dsp.float_to_int16_interleave == ff_float_to_int16_interleave_c) {
- ac->add_bias = 385.0f;
- ac->sf_scale = 1. / (-1024. * 32768.);
- ac->sf_offset = 0;
- } else {
- ac->add_bias = 0.0f;
- ac->sf_scale = 1. / -1024.;
- ac->sf_offset = 60;
- }
+ // 60 - Required to scale values to the correct range [-32768,32767]
+ // for float to int16 conversion. (1 << (60 / 4)) == 32768
+ ac->sf_scale = 1. / -1024.;
+ ac->sf_offset = 60;
-#if !CONFIG_HARDCODED_TABLES
- for (i = 0; i < 428; i++)
- ff_aac_pow2sf_tab[i] = pow(2, (i - 200) / 4.);
-#endif /* CONFIG_HARDCODED_TABLES */
+ ff_aac_tableinit();
INIT_VLC_STATIC(&vlc_scalefactors,7,FF_ARRAY_ELEMS(ff_aac_scalefactor_code),
ff_aac_scalefactor_bits, sizeof(ff_aac_scalefactor_bits[0]), sizeof(ff_aac_scalefactor_bits[0]),
ff_aac_scalefactor_code, sizeof(ff_aac_scalefactor_code[0]), sizeof(ff_aac_scalefactor_code[0]),
352);
- ff_mdct_init(&ac->mdct, 11, 1, 1.0);
- ff_mdct_init(&ac->mdct_small, 8, 1, 1.0);
+ ff_mdct_init(&ac->mdct, 11, 1, 1.0);
+ ff_mdct_init(&ac->mdct_small, 8, 1, 1.0);
+ ff_mdct_init(&ac->mdct_ltp, 11, 0, 1.0);
// window initialization
ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024);
ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128);
return 0;
}
+/**
+ * Decode Long Term Prediction data; reference: table 4.xx.
+ */
+static void decode_ltp(AACContext *ac, LongTermPrediction *ltp,
+ GetBitContext *gb, uint8_t max_sfb)
+{
+ int sfb;
+
+ ltp->lag = get_bits(gb, 11);
+ ltp->coef = ltp_coef[get_bits(gb, 3)] * ac->sf_scale;
+ for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ ltp->used[sfb] = get_bits1(gb);
+}
+
/**
* Decode Individual Channel Stream info; reference: table 4.6.
*
memset(ics, 0, sizeof(IndividualChannelStream));
return -1;
} else {
- av_log_missing_feature(ac->avctx, "Predictor bit set but LTP is", 1);
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ if ((ics->ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
}
}
}
union float754 s = { .f = *scale };
union float754 t;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>2 & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>4 & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>6 & 3] * t.f;
return dst;
const int c = 1024 / ics->num_windows;
const uint16_t *offsets = ics->swb_offset;
float *coef_base = coef;
- int err_idx;
for (g = 0; g < ics->num_windows; g++)
memset(coef + g * 128 + offsets[ics->max_sfb], 0, sizeof(float) * (c - offsets[ics->max_sfb]));
const float *vq = ff_aac_codebook_vector_vals[cbt_m1];
const uint16_t *cb_vector_idx = ff_aac_codebook_vector_idx[cbt_m1];
VLC_TYPE (*vlc_tab)[2] = vlc_spectral[cbt_m1].table;
- const int cb_size = ff_aac_spectral_sizes[cbt_m1];
OPEN_READER(re, gb);
switch (cbt_m1 >> 1) {
UPDATE_CACHE(re, gb);
GET_VLC(code, re, gb, vlc_tab, 8, 2);
-
- if (code >= cb_size) {
- err_idx = code;
- goto err_cb_overflow;
- }
-
cb_idx = cb_vector_idx[code];
cf = VMUL4(cf, vq, cb_idx, sf + idx);
} while (len -= 4);
UPDATE_CACHE(re, gb);
GET_VLC(code, re, gb, vlc_tab, 8, 2);
-
- if (code >= cb_size) {
- err_idx = code;
- goto err_cb_overflow;
- }
-
-#if MIN_CACHE_BITS < 20
- UPDATE_CACHE(re, gb);
-#endif
cb_idx = cb_vector_idx[code];
nnz = cb_idx >> 8 & 15;
bits = SHOW_UBITS(re, gb, nnz) << (32-nnz);
UPDATE_CACHE(re, gb);
GET_VLC(code, re, gb, vlc_tab, 8, 2);
-
- if (code >= cb_size) {
- err_idx = code;
- goto err_cb_overflow;
- }
-
cb_idx = cb_vector_idx[code];
cf = VMUL2(cf, vq, cb_idx, sf + idx);
} while (len -= 2);
UPDATE_CACHE(re, gb);
GET_VLC(code, re, gb, vlc_tab, 8, 2);
-
- if (code >= cb_size) {
- err_idx = code;
- goto err_cb_overflow;
- }
-
cb_idx = cb_vector_idx[code];
nnz = cb_idx >> 8 & 15;
sign = SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12);
continue;
}
- if (code >= cb_size) {
- err_idx = code;
- goto err_cb_overflow;
- }
-
cb_idx = cb_vector_idx[code];
nnz = cb_idx >> 12;
nzt = cb_idx >> 8;
return -1;
}
-#if MIN_CACHE_BITS < 21
- LAST_SKIP_BITS(re, gb, b + 1);
- UPDATE_CACHE(re, gb);
-#else
SKIP_BITS(re, gb, b + 1);
-#endif
b += 4;
n = (1 << b) + SHOW_UBITS(re, gb, b);
LAST_SKIP_BITS(re, gb, b);
- *icf++ = cbrt_tab[n] | (bits & 1<<31);
+ *icf++ = cbrt_tab[n] | (bits & 1U<<31);
bits <<= 1;
} else {
unsigned v = ((const uint32_t*)vq)[cb_idx & 15];
- *icf++ = (bits & 1<<31) | v;
+ *icf++ = (bits & 1U<<31) | v;
bits <<= !!v;
}
cb_idx >>= 4;
}
}
return 0;
-
-err_cb_overflow:
- av_log(ac->avctx, AV_LOG_ERROR,
- "Read beyond end of ff_aac_codebook_vectors[%d][]. index %d >= %d\n",
- band_type[idx], err_idx, ff_aac_spectral_sizes[band_type[idx]]);
- return -1;
}
static av_always_inline float flt16_round(float pf)
return pun.f;
}
-static av_always_inline void predict(AACContext *ac, PredictorState *ps, float *coef,
- int output_enable)
+static av_always_inline void predict(PredictorState *ps, float *coef,
+ float sf_scale, float inv_sf_scale,
+ int output_enable)
{
const float a = 0.953125; // 61.0 / 64
const float alpha = 0.90625; // 29.0 / 32
float e0, e1;
float pv;
float k1, k2;
+ float r0 = ps->r0, r1 = ps->r1;
+ float cor0 = ps->cor0, cor1 = ps->cor1;
+ float var0 = ps->var0, var1 = ps->var1;
- k1 = ps->var0 > 1 ? ps->cor0 * flt16_even(a / ps->var0) : 0;
- k2 = ps->var1 > 1 ? ps->cor1 * flt16_even(a / ps->var1) : 0;
+ k1 = var0 > 1 ? cor0 * flt16_even(a / var0) : 0;
+ k2 = var1 > 1 ? cor1 * flt16_even(a / var1) : 0;
- pv = flt16_round(k1 * ps->r0 + k2 * ps->r1);
+ pv = flt16_round(k1 * r0 + k2 * r1);
if (output_enable)
- *coef += pv * ac->sf_scale;
+ *coef += pv * sf_scale;
- e0 = *coef / ac->sf_scale;
- e1 = e0 - k1 * ps->r0;
+ e0 = *coef * inv_sf_scale;
+ e1 = e0 - k1 * r0;
- ps->cor1 = flt16_trunc(alpha * ps->cor1 + ps->r1 * e1);
- ps->var1 = flt16_trunc(alpha * ps->var1 + 0.5 * (ps->r1 * ps->r1 + e1 * e1));
- ps->cor0 = flt16_trunc(alpha * ps->cor0 + ps->r0 * e0);
- ps->var0 = flt16_trunc(alpha * ps->var0 + 0.5 * (ps->r0 * ps->r0 + e0 * e0));
+ ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1);
+ ps->var1 = flt16_trunc(alpha * var1 + 0.5f * (r1 * r1 + e1 * e1));
+ ps->cor0 = flt16_trunc(alpha * cor0 + r0 * e0);
+ ps->var0 = flt16_trunc(alpha * var0 + 0.5f * (r0 * r0 + e0 * e0));
- ps->r1 = flt16_trunc(a * (ps->r0 - k1 * e0));
+ ps->r1 = flt16_trunc(a * (r0 - k1 * e0));
ps->r0 = flt16_trunc(a * e0);
}
static void apply_prediction(AACContext *ac, SingleChannelElement *sce)
{
int sfb, k;
+ float sf_scale = ac->sf_scale, inv_sf_scale = 1 / ac->sf_scale;
if (!sce->ics.predictor_initialized) {
reset_all_predictors(sce->predictor_state);
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->m4ac.sampling_index]; sfb++) {
for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) {
- predict(ac, &sce->predictor_state[k], &sce->coeffs[k],
+ predict(&sce->predictor_state[k], &sce->coeffs[k],
+ sf_scale, inv_sf_scale,
sce->ics.predictor_present && sce->ics.prediction_used[sfb]);
}
}
* [1] mask is decoded from bitstream; [2] mask is all 1s;
* [3] reserved for scalable AAC
*/
-static void apply_intensity_stereo(ChannelElement *cpe, int ms_present)
+static void apply_intensity_stereo(AACContext *ac, ChannelElement *cpe, int ms_present)
{
const IndividualChannelStream *ics = &cpe->ch[1].ics;
SingleChannelElement *sce1 = &cpe->ch[1];
float *coef0 = cpe->ch[0].coeffs, *coef1 = cpe->ch[1].coeffs;
const uint16_t *offsets = ics->swb_offset;
- int g, group, i, k, idx = 0;
+ int g, group, i, idx = 0;
int c;
float scale;
for (g = 0; g < ics->num_window_groups; g++) {
c *= 1 - 2 * cpe->ms_mask[idx];
scale = c * sce1->sf[idx];
for (group = 0; group < ics->group_len[g]; group++)
- for (k = offsets[i]; k < offsets[i + 1]; k++)
- coef1[group * 128 + k] = scale * coef0[group * 128 + k];
+ ac->dsp.vector_fmul_scalar(coef1 + group * 128 + offsets[i],
+ coef0 + group * 128 + offsets[i],
+ scale,
+ offsets[i + 1] - offsets[i]);
}
} else {
int bt_run_end = sce1->band_type_run_end[idx];
/**
* Decode a channel_pair_element; reference: table 4.4.
*
- * @param elem_id Identifies the instance of a syntax element.
- *
* @return Returns error status. 0 - OK, !0 - error
*/
static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe)
i = cpe->ch[1].ics.use_kb_window[0];
cpe->ch[1].ics = cpe->ch[0].ics;
cpe->ch[1].ics.use_kb_window[1] = i;
+ if (cpe->ch[1].ics.predictor_present && (ac->m4ac.object_type != AOT_AAC_MAIN))
+ if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
ms_present = get_bits(gb, 2);
if (ms_present == 3) {
av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
}
}
- apply_intensity_stereo(cpe, ms_present);
+ apply_intensity_stereo(ac, cpe, ms_present);
return 0;
}
+static const float cce_scale[] = {
+ 1.09050773266525765921, //2^(1/8)
+ 1.18920711500272106672, //2^(1/4)
+ M_SQRT2,
+ 2,
+};
+
/**
* Decode coupling_channel_element; reference: table 4.8.
*
- * @param elem_id Identifies the instance of a syntax element.
- *
* @return Returns error status. 0 - OK, !0 - error
*/
static int decode_cce(AACContext *ac, GetBitContext *gb, ChannelElement *che)
coup->coupling_point += get_bits1(gb) || (coup->coupling_point >> 1);
sign = get_bits(gb, 1);
- scale = pow(2., pow(2., (int)get_bits(gb, 2) - 3));
+ scale = cce_scale[get_bits(gb, 2)];
if ((ret = decode_ics(ac, sce, gb, 0, 0)))
return ret;
if (c) {
cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0;
- gain_cache = pow(scale, -gain);
+ gain_cache = powf(scale, -gain);
}
if (coup->coupling_point == AFTER_IMDCT) {
coup->gain[c][0] = gain_cache;
s -= 2 * (t & 0x1);
t >>= 1;
}
- gain_cache = pow(scale, -t) * s;
+ gain_cache = powf(scale, -t) * s;
}
}
coup->gain[c][idx] = gain_cache;
int w, filt, m, i;
int bottom, top, order, start, end, size, inc;
float lpc[TNS_MAX_ORDER];
+ float tmp[TNS_MAX_ORDER];
for (w = 0; w < ics->num_windows; w++) {
bottom = ics->num_swb;
}
start += w * 128;
- // ar filter
- for (m = 0; m < size; m++, start += inc)
- for (i = 1; i <= FFMIN(m, order); i++)
- coef[start] -= coef[start - i * inc] * lpc[i - 1];
+ if (decode) {
+ // ar filter
+ for (m = 0; m < size; m++, start += inc)
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] -= coef[start - i * inc] * lpc[i - 1];
+ } else {
+ // ma filter
+ for (m = 0; m < size; m++, start += inc) {
+ tmp[0] = coef[start];
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] += tmp[i] * lpc[i - 1];
+ for (i = order; i > 0; i--)
+ tmp[i] = tmp[i - 1];
+ }
+ }
}
}
}
+/**
+ * Apply windowing and MDCT to obtain the spectral
+ * coefficient from the predicted sample by LTP.
+ */
+static void windowing_and_mdct_ltp(AACContext *ac, float *out,
+ float *in, IndividualChannelStream *ics)
+{
+ const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
+ const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
+
+ if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
+ ac->dsp.vector_fmul(in, in, lwindow_prev, 1024);
+ } else {
+ memset(in, 0, 448 * sizeof(float));
+ ac->dsp.vector_fmul(in + 448, in + 448, swindow_prev, 128);
+ memcpy(in + 576, in + 576, 448 * sizeof(float));
+ }
+ if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
+ ac->dsp.vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
+ } else {
+ memcpy(in + 1024, in + 1024, 448 * sizeof(float));
+ ac->dsp.vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
+ memset(in + 1024 + 576, 0, 448 * sizeof(float));
+ }
+ ac->mdct_ltp.mdct_calc(&ac->mdct_ltp, out, in);
+}
+
+/**
+ * Apply the long term prediction
+ */
+static void apply_ltp(AACContext *ac, SingleChannelElement *sce)
+{
+ const LongTermPrediction *ltp = &sce->ics.ltp;
+ const uint16_t *offsets = sce->ics.swb_offset;
+ int i, sfb;
+
+ if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
+ float *predTime = sce->ret;
+ float *predFreq = ac->buf_mdct;
+ int16_t num_samples = 2048;
+
+ if (ltp->lag < 1024)
+ num_samples = ltp->lag + 1024;
+ for (i = 0; i < num_samples; i++)
+ predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef;
+ memset(&predTime[i], 0, (2048 - i) * sizeof(float));
+
+ windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
+
+ if (sce->tns.present)
+ apply_tns(predFreq, &sce->tns, &sce->ics, 0);
+
+ for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ if (ltp->used[sfb])
+ for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
+ sce->coeffs[i] += predFreq[i];
+ }
+}
+
+/**
+ * Update the LTP buffer for next frame
+ */
+static void update_ltp(AACContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ float *saved = sce->saved;
+ float *saved_ltp = sce->coeffs;
+ const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
+ int i;
+
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ memcpy(saved_ltp, saved, 512 * sizeof(float));
+ memset(saved_ltp + 576, 0, 448 * sizeof(float));
+ ac->dsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
+ } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
+ memcpy(saved_ltp, ac->buf_mdct + 512, 448 * sizeof(float));
+ memset(saved_ltp + 576, 0, 448 * sizeof(float));
+ ac->dsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
+ } else { // LONG_STOP or ONLY_LONG
+ ac->dsp.vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512);
+ for (i = 0; i < 512; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * lwindow[511 - i];
+ }
+
+ memcpy(sce->ltp_state, &sce->ltp_state[1024], 1024 * sizeof(int16_t));
+ ac->fmt_conv.float_to_int16(&(sce->ltp_state[1024]), sce->ret, 1024);
+ ac->fmt_conv.float_to_int16(&(sce->ltp_state[2048]), saved_ltp, 1024);
+}
+
/**
* Conduct IMDCT and windowing.
*/
-static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce, float bias)
+static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
float *in = sce->coeffs;
// imdct
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- if (ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE)
- av_log(ac->avctx, AV_LOG_WARNING,
- "Transition from an ONLY_LONG or LONG_STOP to an EIGHT_SHORT sequence detected. "
- "If you heard an audible artifact, please submit the sample to the FFmpeg developers.\n");
for (i = 0; i < 1024; i += 128)
- ff_imdct_half(&ac->mdct_small, buf + i, in + i);
+ ac->mdct_small.imdct_half(&ac->mdct_small, buf + i, in + i);
} else
- ff_imdct_half(&ac->mdct, buf, in);
+ ac->mdct.imdct_half(&ac->mdct, buf, in);
/* window overlapping
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
*/
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
- ac->dsp.vector_fmul_window( out, saved, buf, lwindow_prev, bias, 512);
+ ac->dsp.vector_fmul_window( out, saved, buf, lwindow_prev, 512);
} else {
- for (i = 0; i < 448; i++)
- out[i] = saved[i] + bias;
+ memcpy( out, saved, 448 * sizeof(float));
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- ac->dsp.vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, bias, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64);
+ ac->dsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64);
memcpy( out + 448 + 4*128, temp, 64 * sizeof(float));
} else {
- ac->dsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, bias, 64);
- for (i = 576; i < 1024; i++)
- out[i] = buf[i-512] + bias;
+ ac->dsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
+ memcpy( out + 576, buf + 64, 448 * sizeof(float));
}
}
// buffer update
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- for (i = 0; i < 64; i++)
- saved[i] = temp[64 + i] - bias;
- ac->dsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 0, 64);
- ac->dsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 0, 64);
- ac->dsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 0, 64);
+ memcpy( saved, temp + 64, 64 * sizeof(float));
+ ac->dsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
+ ac->dsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
+ ac->dsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(float));
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
memcpy( saved, buf + 512, 448 * sizeof(float));
{
int i;
const float gain = cce->coup.gain[index][0];
- const float bias = ac->add_bias;
const float *src = cce->ch[0].ret;
float *dest = target->ret;
const int len = 1024 << (ac->m4ac.sbr == 1);
for (i = 0; i < len; i++)
- dest[i] += gain * (src[i] - bias);
+ dest[i] += gain * src[i];
}
/**
* channel coupling transformation interface
*
- * @param index index into coupling gain array
* @param apply_coupling_method pointer to (in)dependent coupling function
*/
static void apply_channel_coupling(AACContext *ac, ChannelElement *cc,
static void spectral_to_sample(AACContext *ac)
{
int i, type;
- float imdct_bias = (ac->m4ac.sbr <= 0) ? ac->add_bias : 0.0f;
for (type = 3; type >= 0; type--) {
for (i = 0; i < MAX_ELEM_ID; i++) {
ChannelElement *che = ac->che[type][i];
if (che) {
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
+ if (ac->m4ac.object_type == AOT_AAC_LTP) {
+ if (che->ch[0].ics.predictor_present) {
+ if (che->ch[0].ics.ltp.present)
+ apply_ltp(ac, &che->ch[0]);
+ if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
+ apply_ltp(ac, &che->ch[1]);
+ }
+ }
if (che->ch[0].tns.present)
apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
if (che->ch[1].tns.present)
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
- imdct_and_windowing(ac, &che->ch[0], imdct_bias);
+ imdct_and_windowing(ac, &che->ch[0]);
+ if (ac->m4ac.object_type == AOT_AAC_LTP)
+ update_ltp(ac, &che->ch[0]);
if (type == TYPE_CPE) {
- imdct_and_windowing(ac, &che->ch[1], imdct_bias);
+ imdct_and_windowing(ac, &che->ch[1]);
+ if (ac->m4ac.object_type == AOT_AAC_LTP)
+ update_ltp(ac, &che->ch[1]);
}
if (ac->m4ac.sbr > 0) {
ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret);
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
ac->m4ac.chan_config = hdr_info.chan_config;
- if (set_default_channel_config(ac, new_che_pos, hdr_info.chan_config))
+ if (set_default_channel_config(ac->avctx, new_che_pos, hdr_info.chan_config))
return -7;
if (output_configure(ac, ac->che_pos, new_che_pos, hdr_info.chan_config, OC_TRIAL_FRAME))
return -7;
return size;
}
-static int aac_decode_frame(AVCodecContext *avctx, void *data,
- int *data_size, AVPacket *avpkt)
+static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
+ int *data_size, GetBitContext *gb)
{
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
AACContext *ac = avctx->priv_data;
ChannelElement *che = NULL, *che_prev = NULL;
- GetBitContext gb;
enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
int err, elem_id, data_size_tmp;
- int buf_consumed;
int samples = 0, multiplier;
- int buf_offset;
- init_get_bits(&gb, buf, buf_size * 8);
-
- if (show_bits(&gb, 12) == 0xfff) {
- if (parse_adts_frame_header(ac, &gb) < 0) {
+ if (show_bits(gb, 12) == 0xfff) {
+ if (parse_adts_frame_header(ac, gb) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
return -1;
}
}
}
- memset(ac->tags_seen_this_frame, 0, sizeof(ac->tags_seen_this_frame));
+ ac->tags_mapped = 0;
// parse
- while ((elem_type = get_bits(&gb, 3)) != TYPE_END) {
- elem_id = get_bits(&gb, 4);
+ while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
+ elem_id = get_bits(gb, 4);
if (elem_type < TYPE_DSE) {
if (!(che=get_che(ac, elem_type, elem_id))) {
switch (elem_type) {
case TYPE_SCE:
- err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], gb, 0, 0);
break;
case TYPE_CPE:
- err = decode_cpe(ac, &gb, che);
+ err = decode_cpe(ac, gb, che);
break;
case TYPE_CCE:
- err = decode_cce(ac, &gb, che);
+ err = decode_cce(ac, gb, che);
break;
case TYPE_LFE:
- err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], gb, 0, 0);
break;
case TYPE_DSE:
- err = skip_data_stream_element(ac, &gb);
+ err = skip_data_stream_element(ac, gb);
break;
case TYPE_PCE: {
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
- if ((err = decode_pce(ac, new_che_pos, &gb)))
+ if ((err = decode_pce(avctx, &ac->m4ac, new_che_pos, gb)))
break;
if (ac->output_configured > OC_TRIAL_PCE)
av_log(avctx, AV_LOG_ERROR,
case TYPE_FIL:
if (elem_id == 15)
- elem_id += get_bits(&gb, 8) - 1;
- if (get_bits_left(&gb) < 8 * elem_id) {
+ elem_id += get_bits(gb, 8) - 1;
+ if (get_bits_left(gb) < 8 * elem_id) {
av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
while (elem_id > 0)
- elem_id -= decode_extension_payload(ac, &gb, elem_id, che_prev, elem_type_prev);
+ elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, elem_type_prev);
err = 0; /* FIXME */
break;
if (err)
return err;
- if (get_bits_left(&gb) < 3) {
+ if (get_bits_left(gb) < 3) {
av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
avctx->frame_size = samples;
}
- data_size_tmp = samples * avctx->channels * sizeof(int16_t);
+ data_size_tmp = samples * avctx->channels;
+ data_size_tmp *= avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? sizeof(float) : sizeof(int16_t);
if (*data_size < data_size_tmp) {
av_log(avctx, AV_LOG_ERROR,
"Output buffer too small (%d) or trying to output too many samples (%d) for this frame.\n",
}
*data_size = data_size_tmp;
- if (samples)
- ac->dsp.float_to_int16_interleave(data, (const float **)ac->output_data, samples, avctx->channels);
+ if (samples) {
+ if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {
+ float_interleave(data, (const float **)ac->output_data, samples, avctx->channels);
+ } else
+ ac->fmt_conv.float_to_int16_interleave(data, (const float **)ac->output_data, samples, avctx->channels);
+ }
if (ac->output_configured)
ac->output_configured = OC_LOCKED;
+ return 0;
+}
+
+static int aac_decode_frame(AVCodecContext *avctx, void *data,
+ int *data_size, AVPacket *avpkt)
+{
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ GetBitContext gb;
+ int buf_consumed;
+ int buf_offset;
+ int err;
+
+ init_get_bits(&gb, buf, buf_size * 8);
+
+ if ((err = aac_decode_frame_int(avctx, data, data_size, &gb)) < 0)
+ return err;
+
buf_consumed = (get_bits_count(&gb) + 7) >> 3;
for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
if (buf[buf_offset])
ff_mdct_end(&ac->mdct);
ff_mdct_end(&ac->mdct_small);
+ ff_mdct_end(&ac->mdct_ltp);
+ return 0;
+}
+
+
+#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
+
+struct LATMContext {
+ AACContext aac_ctx; ///< containing AACContext
+ int initialized; ///< initilized after a valid extradata was seen
+
+ // parser data
+ int audio_mux_version_A; ///< LATM syntax version
+ int frame_length_type; ///< 0/1 variable/fixed frame length
+ int frame_length; ///< frame length for fixed frame length
+};
+
+static inline uint32_t latm_get_value(GetBitContext *b)
+{
+ int length = get_bits(b, 2);
+
+ return get_bits_long(b, (length+1)*8);
+}
+
+static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ AVCodecContext *avctx = latmctx->aac_ctx.avctx;
+ MPEG4AudioConfig m4ac;
+ int config_start_bit = get_bits_count(gb);
+ int bits_consumed, esize;
+
+ if (config_start_bit % 8) {
+ av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific "
+ "config not byte aligned.\n", 1);
+ return AVERROR_INVALIDDATA;
+ } else {
+ bits_consumed =
+ decode_audio_specific_config(NULL, avctx, &m4ac,
+ gb->buffer + (config_start_bit / 8),
+ get_bits_left(gb) / 8);
+
+ if (bits_consumed < 0)
+ return AVERROR_INVALIDDATA;
+
+ esize = (bits_consumed+7) / 8;
+
+ if (avctx->extradata_size <= esize) {
+ av_free(avctx->extradata);
+ avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->extradata_size = esize;
+ memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize);
+ memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ skip_bits_long(gb, bits_consumed);
+ }
+
+ return bits_consumed;
+}
+
+static int read_stream_mux_config(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ int ret, audio_mux_version = get_bits(gb, 1);
+
+ latmctx->audio_mux_version_A = 0;
+ if (audio_mux_version)
+ latmctx->audio_mux_version_A = get_bits(gb, 1);
+
+ if (!latmctx->audio_mux_version_A) {
+
+ if (audio_mux_version)
+ latm_get_value(gb); // taraFullness
+
+ skip_bits(gb, 1); // allStreamSameTimeFraming
+ skip_bits(gb, 6); // numSubFrames
+ // numPrograms
+ if (get_bits(gb, 4)) { // numPrograms
+ av_log_missing_feature(latmctx->aac_ctx.avctx,
+ "multiple programs are not supported\n", 1);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for each program (which there is only on in DVB)
+
+ // for each layer (which there is only on in DVB)
+ if (get_bits(gb, 3)) { // numLayer
+ av_log_missing_feature(latmctx->aac_ctx.avctx,
+ "multiple layers are not supported\n", 1);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for all but first stream: use_same_config = get_bits(gb, 1);
+ if (!audio_mux_version) {
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
+ return ret;
+ } else {
+ int ascLen = latm_get_value(gb);
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
+ return ret;
+ ascLen -= ret;
+ skip_bits_long(gb, ascLen);
+ }
+
+ latmctx->frame_length_type = get_bits(gb, 3);
+ switch (latmctx->frame_length_type) {
+ case 0:
+ skip_bits(gb, 8); // latmBufferFullness
+ break;
+ case 1:
+ latmctx->frame_length = get_bits(gb, 9);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ skip_bits(gb, 6); // CELP frame length table index
+ break;
+ case 6:
+ case 7:
+ skip_bits(gb, 1); // HVXC frame length table index
+ break;
+ }
+
+ if (get_bits(gb, 1)) { // other data
+ if (audio_mux_version) {
+ latm_get_value(gb); // other_data_bits
+ } else {
+ int esc;
+ do {
+ esc = get_bits(gb, 1);
+ skip_bits(gb, 8);
+ } while (esc);
+ }
+ }
+
+ if (get_bits(gb, 1)) // crc present
+ skip_bits(gb, 8); // config_crc
+ }
+
+ return 0;
+}
+
+static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb)
+{
+ uint8_t tmp;
+
+ if (ctx->frame_length_type == 0) {
+ int mux_slot_length = 0;
+ do {
+ tmp = get_bits(gb, 8);
+ mux_slot_length += tmp;
+ } while (tmp == 255);
+ return mux_slot_length;
+ } else if (ctx->frame_length_type == 1) {
+ return ctx->frame_length;
+ } else if (ctx->frame_length_type == 3 ||
+ ctx->frame_length_type == 5 ||
+ ctx->frame_length_type == 7) {
+ skip_bits(gb, 2); // mux_slot_length_coded
+ }
return 0;
}
-AVCodec aac_decoder = {
+static int read_audio_mux_element(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ int err;
+ uint8_t use_same_mux = get_bits(gb, 1);
+ if (!use_same_mux) {
+ if ((err = read_stream_mux_config(latmctx, gb)) < 0)
+ return err;
+ } else if (!latmctx->aac_ctx.avctx->extradata) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG,
+ "no decoder config found\n");
+ return AVERROR(EAGAIN);
+ }
+ if (latmctx->audio_mux_version_A == 0) {
+ int mux_slot_length_bytes = read_payload_length_info(latmctx, gb);
+ if (mux_slot_length_bytes * 8 > get_bits_left(gb)) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n");
+ return AVERROR_INVALIDDATA;
+ } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
+ "frame length mismatch %d << %d\n",
+ mux_slot_length_bytes * 8, get_bits_left(gb));
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ return 0;
+}
+
+
+static int latm_decode_frame(AVCodecContext *avctx, void *out, int *out_size,
+ AVPacket *avpkt)
+{
+ struct LATMContext *latmctx = avctx->priv_data;
+ int muxlength, err;
+ GetBitContext gb;
+
+ if (avpkt->size == 0)
+ return 0;
+
+ init_get_bits(&gb, avpkt->data, avpkt->size * 8);
+
+ // check for LOAS sync word
+ if (get_bits(&gb, 11) != LOAS_SYNC_WORD)
+ return AVERROR_INVALIDDATA;
+
+ muxlength = get_bits(&gb, 13) + 3;
+ // not enough data, the parser should have sorted this
+ if (muxlength > avpkt->size)
+ return AVERROR_INVALIDDATA;
+
+ if ((err = read_audio_mux_element(latmctx, &gb)) < 0)
+ return err;
+
+ if (!latmctx->initialized) {
+ if (!avctx->extradata) {
+ *out_size = 0;
+ return avpkt->size;
+ } else {
+ if ((err = aac_decode_init(avctx)) < 0)
+ return err;
+ latmctx->initialized = 1;
+ }
+ }
+
+ if (show_bits(&gb, 12) == 0xfff) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
+ "ADTS header detected, probably as result of configuration "
+ "misparsing\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((err = aac_decode_frame_int(avctx, out, out_size, &gb)) < 0)
+ return err;
+
+ return muxlength;
+}
+
+av_cold static int latm_decode_init(AVCodecContext *avctx)
+{
+ struct LATMContext *latmctx = avctx->priv_data;
+ int ret;
+
+ ret = aac_decode_init(avctx);
+
+ if (avctx->extradata_size > 0) {
+ latmctx->initialized = !ret;
+ } else {
+ latmctx->initialized = 0;
+ }
+
+ return ret;
+}
+
+
+AVCodec ff_aac_decoder = {
"aac",
AVMEDIA_TYPE_AUDIO,
CODEC_ID_AAC,
aac_decode_close,
aac_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"),
- .sample_fmts = (const enum SampleFormat[]) {
- SAMPLE_FMT_S16,SAMPLE_FMT_NONE
+ .sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE
+ },
+ .channel_layouts = aac_channel_layout,
+};
+
+/*
+ Note: This decoder filter is intended to decode LATM streams transferred
+ in MPEG transport streams which only contain one program.
+ To do a more complex LATM demuxing a separate LATM demuxer should be used.
+*/
+AVCodec ff_aac_latm_decoder = {
+ .name = "aac_latm",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = CODEC_ID_AAC_LATM,
+ .priv_data_size = sizeof(struct LATMContext),
+ .init = latm_decode_init,
+ .close = aac_decode_close,
+ .decode = latm_decode_frame,
+ .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Codec LATM syntax)"),
+ .sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE
},
.channel_layouts = aac_channel_layout,
};