/*
* AC-3 Audio Decoder
- * This code is developed as part of Google Summer of Code 2006 Program.
+ * This code was developed as part of Google Summer of Code 2006.
+ * E-AC-3 support was added as part of Google Summer of Code 2007.
*
* Copyright (c) 2006 Kartikey Mahendra BHATT (bhattkm at gmail dot com).
+ * Copyright (c) 2007-2008 Bartlomiej Wolowiec <bartek.wolowiec@gmail.com>
* Copyright (c) 2007 Justin Ruggles <justin.ruggles@gmail.com>
*
* Portions of this code are derived from liba52
s->channel_in_cpl[s->lfe_ch] = 0;
}
- if(hdr.bitstream_id > 10)
+ if (hdr.bitstream_id <= 10) {
+ s->eac3 = 0;
+ s->snr_offset_strategy = 2;
+ s->block_switch_syntax = 1;
+ s->dither_flag_syntax = 1;
+ s->bit_allocation_syntax = 1;
+ s->fast_gain_syntax = 0;
+ s->first_cpl_leak = 0;
+ s->dba_syntax = 1;
+ s->skip_syntax = 1;
+ memset(s->channel_uses_aht, 0, sizeof(s->channel_uses_aht));
+ return ac3_parse_header(s);
+ } else {
+ /*s->eac3 = 1;
+ return ff_eac3_parse_header(s);*/
return AC3_PARSE_ERROR_BSID;
-
- return ac3_parse_header(s);
+ }
}
/**
* Get the transform coefficients for a particular channel
* reference: Section 7.3 Quantization and Decoding of Mantissas
*/
-static void get_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, mant_groups *m)
+static void ac3_decode_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, mant_groups *m)
{
GetBitContext *gbc = &s->gbc;
int i, gcode, tbap, start, end;
}
}
+static void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk, int ch,
+ mant_groups *m)
+{
+ if (!s->channel_uses_aht[ch]) {
+ ac3_decode_transform_coeffs_ch(s, ch, m);
+ } else {
+ /* if AHT is used, mantissas for all blocks are encoded in the first
+ block of the frame. */
+ int bin;
+ /*
+ if (!blk)
+ ff_eac3_decode_transform_coeffs_aht_ch(s, ch);
+ */
+ for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
+ s->fixed_coeffs[ch][bin] = s->pre_mantissa[ch][bin][blk] >> s->dexps[ch][bin];
+ }
+ }
+}
+
/**
* Get the transform coefficients.
*/
-static void get_transform_coeffs(AC3DecodeContext *s)
+static void decode_transform_coeffs(AC3DecodeContext *s, int blk)
{
int ch, end;
int got_cplchan = 0;
for (ch = 1; ch <= s->channels; ch++) {
/* transform coefficients for full-bandwidth channel */
- get_transform_coeffs_ch(s, ch, &m);
+ decode_transform_coeffs_ch(s, blk, ch, &m);
/* tranform coefficients for coupling channel come right after the
coefficients for the first coupled channel*/
if (s->channel_in_cpl[ch]) {
if (!got_cplchan) {
- get_transform_coeffs_ch(s, CPL_CH, &m);
+ decode_transform_coeffs_ch(s, blk, CPL_CH, &m);
calc_transform_coeffs_cpl(s);
got_cplchan = 1;
}
*/
static void ac3_upmix_delay(AC3DecodeContext *s)
{
- int channel_data_size = 128*sizeof(float);
+ int channel_data_size = sizeof(s->delay[0]);
switch(s->channel_mode) {
case AC3_CHMODE_DUALMONO:
case AC3_CHMODE_STEREO:
/* block switch flags */
different_transforms = 0;
- for (ch = 1; ch <= fbw_channels; ch++) {
- s->block_switch[ch] = get_bits1(gbc);
- if(ch > 1 && s->block_switch[ch] != s->block_switch[1])
- different_transforms = 1;
+ if (s->block_switch_syntax) {
+ for (ch = 1; ch <= fbw_channels; ch++) {
+ s->block_switch[ch] = get_bits1(gbc);
+ if(ch > 1 && s->block_switch[ch] != s->block_switch[1])
+ different_transforms = 1;
+ }
}
/* dithering flags */
- s->dither_all = 1;
- for (ch = 1; ch <= fbw_channels; ch++) {
- s->dither_flag[ch] = get_bits1(gbc);
- if(!s->dither_flag[ch])
- s->dither_all = 0;
+ if (s->dither_flag_syntax) {
+ s->dither_all = 1;
+ for (ch = 1; ch <= fbw_channels; ch++) {
+ s->dither_flag[ch] = get_bits1(gbc);
+ if(!s->dither_flag[ch])
+ s->dither_all = 0;
+ }
}
/* dynamic range */
}
} while(i--);
+ /* spectral extension strategy */
+ if (s->eac3 && (!blk || get_bits1(gbc))) {
+ if (get_bits1(gbc)) {
+ av_log_missing_feature(s->avctx, "Spectral extension", 1);
+ return -1;
+ }
+ /* TODO: parse spectral extension strategy info */
+ }
+
+ /* TODO: spectral extension coordinates */
+
/* coupling strategy */
if (get_bits1(gbc)) {
memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
- s->cpl_in_use[blk] = get_bits1(gbc);
+ if (!s->eac3)
+ s->cpl_in_use[blk] = get_bits1(gbc);
if (s->cpl_in_use[blk]) {
/* coupling in use */
int cpl_begin_freq, cpl_end_freq;
return -1;
}
+ /* check for enhanced coupling */
+ if (s->eac3 && get_bits1(gbc)) {
+ /* TODO: parse enhanced coupling strategy info */
+ av_log_missing_feature(s->avctx, "Enhanced coupling", 1);
+ return -1;
+ }
+
/* determine which channels are coupled */
- for (ch = 1; ch <= fbw_channels; ch++)
- s->channel_in_cpl[ch] = get_bits1(gbc);
+ if (s->eac3 && s->channel_mode == AC3_CHMODE_STEREO) {
+ s->channel_in_cpl[1] = 1;
+ s->channel_in_cpl[2] = 1;
+ } else {
+ for (ch = 1; ch <= fbw_channels; ch++)
+ s->channel_in_cpl[ch] = get_bits1(gbc);
+ }
/* phase flags in use */
if (channel_mode == AC3_CHMODE_STEREO)
s->phase_flags_in_use = get_bits1(gbc);
- /* coupling frequency range and band structure */
+ /* coupling frequency range */
+ /* TODO: modify coupling end freq if spectral extension is used */
cpl_begin_freq = get_bits(gbc, 4);
cpl_end_freq = get_bits(gbc, 4);
if (3 + cpl_end_freq - cpl_begin_freq < 0) {
s->num_cpl_bands = s->num_cpl_subbands = 3 + cpl_end_freq - cpl_begin_freq;
s->start_freq[CPL_CH] = cpl_begin_freq * 12 + 37;
s->end_freq[CPL_CH] = cpl_end_freq * 12 + 73;
- for (bnd = 0; bnd < s->num_cpl_subbands - 1; bnd++) {
- if (get_bits1(gbc)) {
- s->cpl_band_struct[bnd] = 1;
- s->num_cpl_bands--;
+
+ /* coupling band structure */
+ if (!s->eac3 || get_bits1(gbc)) {
+ for (bnd = 0; bnd < s->num_cpl_subbands - 1; bnd++) {
+ s->cpl_band_struct[bnd] = get_bits1(gbc);
}
+ } else if (!blk) {
}
s->cpl_band_struct[s->num_cpl_subbands-1] = 0;
+
+ /* calculate number of coupling bands based on band structure */
+ for (bnd = 0; bnd < s->num_cpl_subbands-1; bnd++) {
+ s->num_cpl_bands -= s->cpl_band_struct[bnd];
+ }
} else {
/* coupling not in use */
- for (ch = 1; ch <= fbw_channels; ch++)
+ for (ch = 1; ch <= fbw_channels; ch++) {
s->channel_in_cpl[ch] = 0;
+ s->first_cpl_coords[ch] = 1;
+ }
+ s->first_cpl_leak = s->eac3;
+ s->phase_flags_in_use = 0;
+ }
+ } else if (!s->eac3) {
+ if(!blk) {
+ av_log(s->avctx, AV_LOG_ERROR, "new coupling strategy must be present in block 0\n");
+ return -1;
+ } else {
+ s->cpl_in_use[blk] = s->cpl_in_use[blk-1];
}
- } else if (!blk) {
- av_log(s->avctx, AV_LOG_ERROR, "new coupling strategy must be present in block 0\n");
- return -1;
- } else {
- s->cpl_in_use[blk] = s->cpl_in_use[blk-1];
}
cpl_in_use = s->cpl_in_use[blk];
/* stereo rematrixing strategy and band structure */
if (channel_mode == AC3_CHMODE_STEREO) {
- if (get_bits1(gbc)) {
+ if ((s->eac3 && !blk) || get_bits1(gbc)) {
s->num_rematrixing_bands = 4;
if(cpl_in_use && s->start_freq[CPL_CH] <= 61)
s->num_rematrixing_bands -= 1 + (s->start_freq[CPL_CH] == 37);
}
/* bit allocation information */
- if (get_bits1(gbc)) {
- s->bit_alloc_params.slow_decay = ff_ac3_slow_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift;
- s->bit_alloc_params.fast_decay = ff_ac3_fast_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift;
- s->bit_alloc_params.slow_gain = ff_ac3_slow_gain_tab[get_bits(gbc, 2)];
- s->bit_alloc_params.db_per_bit = ff_ac3_db_per_bit_tab[get_bits(gbc, 2)];
- s->bit_alloc_params.floor = ff_ac3_floor_tab[get_bits(gbc, 3)];
- for(ch=!cpl_in_use; ch<=s->channels; ch++)
- bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
- } else if (!blk) {
- av_log(s->avctx, AV_LOG_ERROR, "new bit allocation info must be present in block 0\n");
- return -1;
+ if (s->bit_allocation_syntax) {
+ if (get_bits1(gbc)) {
+ s->bit_alloc_params.slow_decay = ff_ac3_slow_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift;
+ s->bit_alloc_params.fast_decay = ff_ac3_fast_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift;
+ s->bit_alloc_params.slow_gain = ff_ac3_slow_gain_tab[get_bits(gbc, 2)];
+ s->bit_alloc_params.db_per_bit = ff_ac3_db_per_bit_tab[get_bits(gbc, 2)];
+ s->bit_alloc_params.floor = ff_ac3_floor_tab[get_bits(gbc, 3)];
+ for(ch=!cpl_in_use; ch<=s->channels; ch++)
+ bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
+ } else if (!blk) {
+ av_log(s->avctx, AV_LOG_ERROR, "new bit allocation info must be present in block 0\n");
+ return -1;
+ }
}
/* signal-to-noise ratio offsets and fast gains (signal-to-mask ratios) */
return -1;
}
+ /* fast gain (E-AC-3 only) */
+ if (s->fast_gain_syntax && get_bits1(gbc)) {
+ for (ch = !cpl_in_use; ch <= s->channels; ch++) {
+ int prev = s->fast_gain[ch];
+ s->fast_gain[ch] = ff_ac3_fast_gain_tab[get_bits(gbc, 3)];
+ /* run last 2 bit allocation stages if fast gain changes */
+ if(blk && prev != s->fast_gain[ch])
+ bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
+ }
+ } else if (s->eac3 && !blk) {
+ for (ch = !cpl_in_use; ch <= s->channels; ch++)
+ s->fast_gain[ch] = ff_ac3_fast_gain_tab[4];
+ }
+
+ /* E-AC-3 to AC-3 converter SNR offset */
+ if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && get_bits1(gbc)) {
+ skip_bits(gbc, 10); // skip converter snr offset
+ }
+
/* coupling leak information */
if (cpl_in_use) {
if (get_bits1(gbc)) {
}
/* delta bit allocation information */
- if (get_bits1(gbc)) {
+ if (s->dba_syntax && get_bits1(gbc)) {
/* delta bit allocation exists (strategy) */
for (ch = !cpl_in_use; ch <= fbw_channels; ch++) {
s->dba_mode[ch] = get_bits(gbc, 2);
}
if(bit_alloc_stages[ch] > 0) {
/* Compute bit allocation */
+ const uint8_t *bap_tab = s->channel_uses_aht[ch] ?
+ ff_eac3_hebap_tab : ff_ac3_bap_tab;
ff_ac3_bit_alloc_calc_bap(s->mask[ch], s->psd[ch],
s->start_freq[ch], s->end_freq[ch],
s->snr_offset[ch],
s->bit_alloc_params.floor,
- ff_ac3_bap_tab, s->bap[ch]);
+ bap_tab, s->bap[ch]);
}
}
/* unused dummy data */
- if (get_bits1(gbc)) {
+ if (s->skip_syntax && get_bits1(gbc)) {
int skipl = get_bits(gbc, 9);
while(skipl--)
skip_bits(gbc, 8);
/* unpack the transform coefficients
this also uncouples channels if coupling is in use. */
- get_transform_coeffs(s);
+ decode_transform_coeffs(s, blk);
+
+ /* TODO: generate enhanced coupling coordinates and uncouple */
+
+ /* TODO: apply spectral extension */
/* recover coefficients if rematrixing is in use */
if(s->channel_mode == AC3_CHMODE_STEREO)
.init = ac3_decode_init,
.close = ac3_decode_end,
.decode = ac3_decode_frame,
- .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 / AC-3"),
+ .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 (AC-3, E-AC-3)"),
};