Newer
Older
Alex Converse
committed
Justin Ruggles
committed
dest[i] += gain * src[i];
Robert Swain
committed
}
/**
* channel coupling transformation interface
*
* @param apply_coupling_method pointer to (in)dependent coupling function
*/
static void apply_channel_coupling(AACContext *ac, ChannelElement *cc,
enum RawDataBlockType type, int elem_id,
enum CouplingPoint coupling_point,
void (*apply_coupling_method)(AACContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
int i, c;
for (i = 0; i < MAX_ELEM_ID; i++) {
ChannelElement *cce = ac->che[TYPE_CCE][i];
int index = 0;
if (cce && cce->coup.coupling_point == coupling_point) {
for (c = 0; c <= coup->num_coupled; c++) {
if (coup->type[c] == type && coup->id_select[c] == elem_id) {
if (coup->ch_select[c] != 1) {
apply_coupling_method(ac, &cc->ch[0], cce, index);
if (coup->ch_select[c] != 0)
index++;
}
if (coup->ch_select[c] != 2)
apply_coupling_method(ac, &cc->ch[1], cce, index++);
} else
index += 1 + (coup->ch_select[c] == 3);
}
}
}
}
/**
* Convert spectral data to float samples, applying all supported tools as appropriate.
*/
static void spectral_to_sample(AACContext *ac)
{
int i, type;
for (type = 3; type >= 0; type--) {
for (i = 0; i < MAX_ELEM_ID; i++) {
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]);
}
}
apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
Justin Ruggles
committed
imdct_and_windowing(ac, &che->ch[0]);
if (ac->m4ac.object_type == AOT_AAC_LTP)
update_ltp(ac, &che->ch[0]);
Justin Ruggles
committed
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);
}
apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling);
static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
{
Robert Swain
committed
int size;
AACADTSHeaderInfo hdr_info;
size = avpriv_aac_parse_header(gb, &hdr_info);
Robert Swain
committed
if (size > 0) {
if (hdr_info.chan_config) {
Alex Converse
committed
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
Robert Swain
committed
ac->m4ac.chan_config = hdr_info.chan_config;
if (set_default_channel_config(ac->avctx, new_che_pos, hdr_info.chan_config))
Alex Converse
committed
return -7;
if (output_configure(ac, ac->che_pos, new_che_pos, hdr_info.chan_config,
FFMAX(ac->output_configured, OC_TRIAL_FRAME)))
Alex Converse
committed
return -7;
Alex Converse
committed
} else if (ac->output_configured != OC_LOCKED) {
ac->m4ac.chan_config = 0;
Alex Converse
committed
ac->output_configured = OC_NONE;
Alex Converse
committed
}
if (ac->output_configured != OC_LOCKED) {
Alex Converse
committed
ac->m4ac.sbr = -1;
Alex Converse
committed
ac->m4ac.sample_rate = hdr_info.sample_rate;
ac->m4ac.sampling_index = hdr_info.sampling_index;
ac->m4ac.object_type = hdr_info.object_type;
if (!ac->avctx->sample_rate)
ac->avctx->sample_rate = hdr_info.sample_rate;
if (hdr_info.num_aac_frames == 1) {
if (!hdr_info.crc_absent)
skip_bits(gb, 16);
} else {
av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0);
Alex Converse
committed
}
Robert Swain
committed
return size;
}
static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
ChannelElement *che = NULL, *che_prev = NULL;
enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
int samples = 0, multiplier, audio_found = 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");
Robert Swain
committed
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);
Robert Swain
committed
}
ac->tags_mapped = 0;
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))) {
av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
elem_type, elem_id);
return -1;
}
switch (elem_type) {
case TYPE_SCE:
err = decode_ics(ac, &che->ch[0], gb, 0, 0);
err = decode_cpe(ac, gb, che);
err = decode_cce(ac, gb, che);
err = decode_ics(ac, &che->ch[0], gb, 0, 0);
err = skip_data_stream_element(ac, gb);
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(avctx, &ac->m4ac, new_che_pos, gb)))
if (ac->output_configured > OC_TRIAL_PCE)
Alex Converse
committed
"Not evaluating a further program_config_element as this construct is dubious at best.\n");
else
Alex Converse
committed
err = output_configure(ac, ac->che_pos, new_che_pos, 0, OC_TRIAL_PCE);
break;
}
case TYPE_FIL:
if (elem_id == 15)
elem_id += get_bits(gb, 8) - 1;
if (get_bits_left(gb) < 8 * elem_id) {
av_log(avctx, AV_LOG_ERROR, overread_err);
elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, elem_type_prev);
err = 0; /* FIXME */
break;
default:
err = -1; /* should not happen, but keeps compiler happy */
break;
}
che_prev = che;
elem_type_prev = elem_type;
if (get_bits_left(gb) < 3) {
av_log(avctx, AV_LOG_ERROR, overread_err);
}
spectral_to_sample(ac);
multiplier = (ac->m4ac.sbr == 1) ? ac->m4ac.ext_sample_rate > ac->m4ac.sample_rate : 0;
samples <<= multiplier;
if (ac->output_configured < OC_LOCKED) {
avctx->sample_rate = ac->m4ac.sample_rate << multiplier;
avctx->frame_size = samples;
}
Justin Ruggles
committed
if (samples) {
/* get output buffer */
ac->frame.nb_samples = samples;
if ((err = avctx->get_buffer(avctx, &ac->frame)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return err;
}
Justin Ruggles
committed
if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT)
ac->fmt_conv.float_interleave((float *)ac->frame.data[0],
(const float **)ac->output_data,
Justin Ruggles
committed
samples, avctx->channels);
else
ac->fmt_conv.float_to_int16_interleave((int16_t *)ac->frame.data[0],
(const float **)ac->output_data,
Justin Ruggles
committed
samples, avctx->channels);
Justin Ruggles
committed
}
if (ac->output_configured && audio_found)
Alex Converse
committed
ac->output_configured = OC_LOCKED;
return 0;
}
static int aac_decode_frame(AVCodecContext *avctx, void *data,
AACContext *ac = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
GetBitContext gb;
int buf_consumed;
int buf_offset;
int err;
int new_extradata_size;
const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
AV_PKT_DATA_NEW_EXTRADATA,
&new_extradata_size);
if (new_extradata) {
av_free(avctx->extradata);
avctx->extradata = av_mallocz(new_extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
return AVERROR(ENOMEM);
avctx->extradata_size = new_extradata_size;
memcpy(avctx->extradata, new_extradata, new_extradata_size);
if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac,
avctx->extradata,
avctx->extradata_size*8, 1) < 0)
return AVERROR_INVALIDDATA;
}
init_get_bits(&gb, buf, buf_size * 8);
if ((err = aac_decode_frame_int(avctx, data, got_frame_ptr, &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])
break;
return buf_size > buf_offset ? buf_consumed : buf_size;
static av_cold int aac_decode_close(AVCodecContext *avctx)
Robert Swain
committed
for (i = 0; i < MAX_ELEM_ID; i++) {
for (type = 0; type < 4; type++) {
if (ac->che[type][i])
ff_aac_sbr_ctx_close(&ac->che[type][i]->sbr);
}
ff_mdct_end(&ac->mdct);
ff_mdct_end(&ac->mdct_small);
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
#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, int asclen)
AACContext *ac = &latmctx->aac_ctx;
AVCodecContext *avctx = ac->avctx;
MPEG4AudioConfig m4ac = {0};
int config_start_bit = get_bits_count(gb);
int sync_extension = 0;
int bits_consumed, esize;
if (asclen) {
sync_extension = 1;
asclen = FFMIN(asclen, get_bits_left(gb));
} else
asclen = get_bits_left(gb);
if (config_start_bit % 8) {
av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific "
"config not byte aligned.\n", 1);
return AVERROR_INVALIDDATA;
}
bits_consumed = decode_audio_specific_config(NULL, avctx, &m4ac,
gb->buffer + (config_start_bit / 8),
if (bits_consumed < 0)
return AVERROR_INVALIDDATA;
if (ac->m4ac.sample_rate != m4ac.sample_rate ||
ac->m4ac.chan_config != m4ac.chan_config) {
av_log(avctx, AV_LOG_INFO, "audio config changed\n");
latmctx->initialized = 0;
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);
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
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)) < 0)
return ret;
} else {
int ascLen = latm_get_value(gb);
if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0)
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
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;
}
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 *got_frame_ptr, AVPacket *avpkt)
{
struct LATMContext *latmctx = avctx->priv_data;
int muxlength, err;
GetBitContext gb;
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) {
if ((err = decode_audio_specific_config(
&latmctx->aac_ctx, avctx, &latmctx->aac_ctx.m4ac,
avctx->extradata, avctx->extradata_size*8, 1)) < 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, got_frame_ptr, &gb)) < 0)
return err;
return muxlength;
}
av_cold static int latm_decode_init(AVCodecContext *avctx)
{
struct LATMContext *latmctx = avctx->priv_data;
latmctx->initialized = !ret;
return ret;
}
Diego Elio Pettenò
committed
AVCodec ff_aac_decoder = {
.name = "aac",
.type = AVMEDIA_TYPE_AUDIO,
.id = CODEC_ID_AAC,
.priv_data_size = sizeof(AACContext),
.init = aac_decode_init,
.close = aac_decode_close,
.decode = aac_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"),
.sample_fmts = (const enum AVSampleFormat[]) {
Justin Ruggles
committed
AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
.capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.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.
*/
Diego Elio Pettenò
committed
AVCodec ff_aac_latm_decoder = {
.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[]) {
Justin Ruggles
committed
AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
.capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.channel_layouts = aac_channel_layout,
};