#define AC3_OUTPUT_LFEON 8
typedef struct {
+ int num_blocks; ///< number of audio blocks
int channel_mode; ///< channel mode (acmod)
int block_switch[AC3_MAX_CHANNELS]; ///< block switch flags
int dither_flag[AC3_MAX_CHANNELS]; ///< dither flags
int sample_rate; ///< sample frequency, in Hz
int bit_rate; ///< stream bit rate, in bits-per-second
+ int frame_type; ///< frame type (strmtyp)
+ int substreamid; ///< substream identification
int frame_size; ///< current frame size, in bytes
int channels; ///< number of total channels
int end_freq[AC3_MAX_CHANNELS]; ///< end frequency bin
AC3BitAllocParameters bit_alloc_params; ///< bit allocation parameters
+ int num_exp_groups[AC3_MAX_CHANNELS]; ///< Number of exponent groups
int8_t dexps[AC3_MAX_CHANNELS][256]; ///< decoded exponents
uint8_t bap[AC3_MAX_CHANNELS][256]; ///< bit allocation pointers
int16_t psd[AC3_MAX_CHANNELS][256]; ///< scaled exponents
s->frame_size = hdr.frame_size;
s->center_mix_level = hdr.center_mix_level;
s->surround_mix_level = hdr.surround_mix_level;
+ s->num_blocks = hdr.num_blocks;
+ s->frame_type = hdr.frame_type;
+ s->substreamid = hdr.substreamid;
+
+ if(s->lfe_on) {
+ s->start_freq[s->lfe_ch] = 0;
+ s->end_freq[s->lfe_ch] = 7;
+ s->num_exp_groups[s->lfe_ch] = 2;
+ s->channel_in_cpl[s->lfe_ch] = 0;
+ }
/* read the rest of the bsi. read twice for dual mono mode. */
i = !(s->channel_mode);
s->exp_strategy[CPL_CH] = EXP_REUSE;
s->exp_strategy[s->lfe_ch] = EXP_REUSE;
for (ch = !s->cpl_in_use; ch <= s->channels; ch++) {
- if(ch == s->lfe_ch)
- s->exp_strategy[ch] = get_bits(gbc, 1);
- else
- s->exp_strategy[ch] = get_bits(gbc, 2);
+ s->exp_strategy[ch] = get_bits(gbc, 2 - (ch == s->lfe_ch));
if(s->exp_strategy[ch] != EXP_REUSE)
bit_alloc_stages[ch] = 3;
}
for (ch = 1; ch <= fbw_channels; ch++) {
s->start_freq[ch] = 0;
if (s->exp_strategy[ch] != EXP_REUSE) {
+ int group_size;
int prev = s->end_freq[ch];
if (s->channel_in_cpl[ch])
s->end_freq[ch] = s->start_freq[CPL_CH];
}
s->end_freq[ch] = bandwidth_code * 3 + 73;
}
+ group_size = 3 << (s->exp_strategy[ch] - 1);
+ s->num_exp_groups[ch] = (s->end_freq[ch]+group_size-4) / group_size;
if(blk > 0 && s->end_freq[ch] != prev)
memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
}
}
- s->start_freq[s->lfe_ch] = 0;
- s->end_freq[s->lfe_ch] = 7;
+ if (s->cpl_in_use && s->exp_strategy[CPL_CH] != EXP_REUSE) {
+ s->num_exp_groups[CPL_CH] = (s->end_freq[CPL_CH] - s->start_freq[CPL_CH]) /
+ (3 << (s->exp_strategy[CPL_CH] - 1));
+ }
/* decode exponents for each channel */
for (ch = !s->cpl_in_use; ch <= s->channels; ch++) {
if (s->exp_strategy[ch] != EXP_REUSE) {
- int group_size, num_groups;
- group_size = 3 << (s->exp_strategy[ch] - 1);
- if(ch == CPL_CH)
- num_groups = (s->end_freq[ch] - s->start_freq[ch]) / group_size;
- else if(ch == s->lfe_ch)
- num_groups = 2;
- else
- num_groups = (s->end_freq[ch] + group_size - 4) / group_size;
s->dexps[ch][0] = get_bits(gbc, 4) << !ch;
- decode_exponents(gbc, s->exp_strategy[ch], num_groups, s->dexps[ch][0],
+ decode_exponents(gbc, s->exp_strategy[ch],
+ s->num_exp_groups[ch], s->dexps[ch][0],
&s->dexps[ch][s->start_freq[ch]+!!ch]);
if(ch != CPL_CH && ch != s->lfe_ch)
skip_bits(gbc, 2); /* skip gainrng */
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=!s->cpl_in_use; ch<=s->channels; ch++) {
+ for(ch=!s->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;
}
}
- /* parse the syncinfo */
if(err && err != AC3_PARSE_ERROR_CRC) {
switch(err) {
case AC3_PARSE_ERROR_SYNC:
av_log(avctx, AV_LOG_ERROR, "frame sync error\n");
- break;
+ return -1;
case AC3_PARSE_ERROR_BSID:
av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n");
break;
av_log(avctx, AV_LOG_ERROR, "invalid frame size\n");
break;
case AC3_PARSE_ERROR_FRAME_TYPE:
+ /* skip frame if CRC is ok. otherwise use error concealment. */
+ /* TODO: add support for substreams and dependent frames */
+ if(s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) {
+ av_log(avctx, AV_LOG_ERROR, "unsupported frame type : skipping frame\n");
+ return s->frame_size;
+ } else {
av_log(avctx, AV_LOG_ERROR, "invalid frame type\n");
+ }
break;
default:
av_log(avctx, AV_LOG_ERROR, "invalid header\n");
}
/* parse the audio blocks */
- for (blk = 0; blk < NB_BLOCKS; blk++) {
+ for (blk = 0; blk < s->num_blocks; blk++) {
if (!err && ac3_parse_audio_block(s, blk)) {
av_log(avctx, AV_LOG_ERROR, "error parsing the audio block\n");
}
+
+ /* interleave output samples */
for (i = 0; i < 256; i++)
for (ch = 0; ch < s->out_channels; ch++)
*(out_samples++) = s->int_output[ch][i];
}
- *data_size = NB_BLOCKS * 256 * avctx->channels * sizeof (int16_t);
+ *data_size = s->num_blocks * 256 * avctx->channels * sizeof (int16_t);
return s->frame_size;
}