#include "libavutil/crc.h"
#include "libavutil/downmix_info.h"
#include "libavutil/opt.h"
+#include "libavutil/thread.h"
#include "bswapdsp.h"
#include "internal.h"
#include "aac_ac3_parser.h"
*/
static av_cold int ac3_decode_init(AVCodecContext *avctx)
{
+ static AVOnce init_static_once = AV_ONCE_INIT;
AC3DecodeContext *s = avctx->priv_data;
- int i;
+ int i, ret;
s->avctx = avctx;
- ac3_tables_init();
- ff_mdct_init(&s->imdct_256, 8, 1, 1.0);
- ff_mdct_init(&s->imdct_512, 9, 1, 1.0);
+ if ((ret = ff_mdct_init(&s->imdct_256, 8, 1, 1.0)) < 0 ||
+ (ret = ff_mdct_init(&s->imdct_512, 9, 1, 1.0)) < 0)
+ return ret;
AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256);
ff_bswapdsp_init(&s->bdsp);
#if (USE_FIXED)
s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
#else
- s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
ff_fmt_convert_init(&s->fmt_conv, avctx);
+ s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
#endif
+ if (!s->fdsp)
+ return AVERROR(ENOMEM);
ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
av_lfg_init(&s->dith_state, 0);
s->dlyptr[i] = s->delay[i];
}
+ ff_thread_once(&init_static_once, ac3_tables_init);
+
return 0;
}
s->fbw_channels = s->channels - s->lfe_on;
s->lfe_ch = s->fbw_channels + 1;
s->frame_size = hdr.frame_size;
+ s->superframe_size += hdr.frame_size;
s->preferred_downmix = AC3_DMIXMOD_NOTINDICATED;
s->center_mix_level = hdr.center_mix_level;
s->center_mix_level_ltrt = 4; // -3.0dB
prevexp += dexp[i] - 2;
if (prevexp > 24U) {
av_log(s->avctx, AV_LOG_ERROR, "exponent %d is out-of-range\n", prevexp);
- return -1;
+ return AVERROR_INVALIDDATA;
}
switch (group_size) {
case 4: dexps[j++] = prevexp;
* Convert frequency domain coefficients to time-domain audio samples.
* reference: Section 7.9.4 Transformation Equations
*/
-static inline void do_imdct(AC3DecodeContext *s, int channels)
+static inline void do_imdct(AC3DecodeContext *s, int channels, int offset)
{
int ch;
x[i] = s->transform_coeffs[ch][2 * i];
s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x);
#if USE_FIXED
- s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
+ s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
s->tmp_output, s->window, 128, 8);
#else
- s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+ s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
s->tmp_output, s->window, 128);
#endif
for (i = 0; i < 128; i++)
x[i] = s->transform_coeffs[ch][2 * i + 1];
- s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x);
+ s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1 + offset], x);
} else {
s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]);
#if USE_FIXED
- s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
+ s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
s->tmp_output, s->window, 128, 8);
#else
- s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+ s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
s->tmp_output, s->window, 128);
#endif
- memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample));
+ memcpy(s->delay[ch - 1 + offset], s->tmp_output + 128, 128 * sizeof(FFTSample));
}
}
}
/**
* Decode a single audio block from the AC-3 bitstream.
*/
-static int decode_audio_block(AC3DecodeContext *s, int blk)
+static int decode_audio_block(AC3DecodeContext *s, int blk, int offset)
{
int fbw_channels = s->fbw_channels;
int channel_mode = s->channel_mode;
ac3_upmix_delay(s);
}
- do_imdct(s, s->channels);
+ do_imdct(s, s->channels, offset);
if (downmix_output) {
#if USE_FIXED
s->out_channels, s->fbw_channels, 128);
}
- do_imdct(s, s->out_channels);
+ do_imdct(s, s->out_channels, offset);
}
return 0;
{
AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
+ int buf_size, full_buf_size = avpkt->size;
AC3DecodeContext *s = avctx->priv_data;
- int blk, ch, err, ret;
+ int blk, ch, err, offset, ret;
+ int i;
+ int skip = 0, got_independent_frame = 0;
const uint8_t *channel_map;
+ uint8_t extended_channel_map[EAC3_MAX_CHANNELS];
const SHORTFLOAT *output[AC3_MAX_CHANNELS];
enum AVMatrixEncoding matrix_encoding;
AVDownmixInfo *downmix_info;
+ s->superframe_size = 0;
+
+ buf_size = full_buf_size;
+ for (i = 1; i < buf_size; i += 2) {
+ if (buf[i] == 0x77 || buf[i] == 0x0B) {
+ if ((buf[i] ^ buf[i-1]) == (0x77 ^ 0x0B)) {
+ i--;
+ break;
+ } else if ((buf[i] ^ buf[i+1]) == (0x77 ^ 0x0B)) {
+ break;
+ }
+ }
+ }
+ if (i >= buf_size)
+ return AVERROR_INVALIDDATA;
+ if (i > 10)
+ return i;
+ buf += i;
+ buf_size -= i;
+
/* copy input buffer to decoder context to avoid reading past the end
of the buffer, which can be caused by a damaged input stream. */
if (buf_size >= 2 && AV_RB16(buf) == 0x770B) {
av_lfg_init_from_data(&s->dith_state, s->input_buffer, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
buf = s->input_buffer;
+dependent_frame:
/* initialize the GetBitContext with the start of valid AC-3 Frame */
if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
return ret;
break;
case AAC_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) {
+ /* TODO: add support for substreams */
+ if (s->substreamid) {
av_log(avctx, AV_LOG_DEBUG,
- "unsupported frame type %d: skipping frame\n",
- s->frame_type);
+ "unsupported substream %d: skipping frame\n",
+ s->substreamid);
*got_frame_ptr = 0;
return buf_size;
} else {
}
}
- /* if frame is ok, set audio parameters */
- if (!err) {
- avctx->sample_rate = s->sample_rate;
- avctx->bit_rate = s->bit_rate;
+ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT && !got_independent_frame) {
+ av_log(avctx, AV_LOG_WARNING, "Ignoring dependent frame without independent frame.\n");
+ *got_frame_ptr = 0;
+ return FFMIN(full_buf_size, s->frame_size);
}
/* channel config */
if (s->bitstream_mode == 0x7 && s->channels > 1)
avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
- /* get output buffer */
- frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE;
- if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
- return ret;
-
/* decode the audio blocks */
channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
+ offset = s->frame_type == EAC3_FRAME_TYPE_DEPENDENT ? AC3_MAX_CHANNELS : 0;
for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
- output[ch] = s->output[ch];
- s->outptr[ch] = s->output[ch];
+ output[ch] = s->output[ch + offset];
+ s->outptr[ch] = s->output[ch + offset];
}
for (ch = 0; ch < s->channels; ch++) {
if (ch < s->out_channels)
- s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch];
+ s->outptr[channel_map[ch]] = s->output_buffer[ch + offset];
}
for (blk = 0; blk < s->num_blocks; blk++) {
- if (!err && decode_audio_block(s, blk)) {
+ if (!err && decode_audio_block(s, blk, offset)) {
av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n");
err = 1;
}
if (err)
for (ch = 0; ch < s->out_channels; ch++)
- memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+ memcpy(s->output_buffer[ch + offset] + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
for (ch = 0; ch < s->out_channels; ch++)
output[ch] = s->outptr[channel_map[ch]];
for (ch = 0; ch < s->out_channels; ch++) {
}
}
- frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0;
-
/* keep last block for error concealment in next frame */
for (ch = 0; ch < s->out_channels; ch++)
- memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+ memcpy(s->output[ch + offset], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+
+ /* check if there is dependent frame */
+ if (buf_size > s->frame_size) {
+ AC3HeaderInfo hdr;
+ int err;
+
+ if (buf_size - s->frame_size <= 16) {
+ skip = buf_size - s->frame_size;
+ goto skip;
+ }
+
+ if ((ret = init_get_bits8(&s->gbc, buf + s->frame_size, buf_size - s->frame_size)) < 0)
+ return ret;
+
+ err = ff_ac3_parse_header(&s->gbc, &hdr);
+ if (err)
+ return err;
+
+ if (hdr.frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
+ if (hdr.num_blocks != s->num_blocks || s->sample_rate != hdr.sample_rate) {
+ av_log(avctx, AV_LOG_WARNING, "Ignoring non-compatible dependent frame.\n");
+ } else {
+ buf += s->frame_size;
+ buf_size -= s->frame_size;
+ s->prev_output_mode = s->output_mode;
+ s->prev_bit_rate = s->bit_rate;
+ got_independent_frame = 1;
+ goto dependent_frame;
+ }
+ }
+ }
+skip:
+
+ frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0;
+
+ /* if frame is ok, set audio parameters */
+ if (!err) {
+ avctx->sample_rate = s->sample_rate;
+ avctx->bit_rate = s->bit_rate + s->prev_bit_rate;
+ }
+
+ for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++)
+ extended_channel_map[ch] = ch;
+
+ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
+ uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON];
+ int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on;
+ uint64_t channel_layout;
+ int extend = 0;
+
+ if (s->prev_output_mode & AC3_OUTPUT_LFEON)
+ ich_layout |= AV_CH_LOW_FREQUENCY;
+
+ channel_layout = ich_layout;
+ for (ch = 0; ch < 16; ch++) {
+ if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) {
+ channel_layout |= ff_eac3_custom_channel_map_locations[ch][1];
+ }
+ }
+ if (av_get_channel_layout_nb_channels(channel_layout) > EAC3_MAX_CHANNELS) {
+ av_log(avctx, AV_LOG_ERROR, "Too many channels (%d) coded\n",
+ av_get_channel_layout_nb_channels(channel_layout));
+ return AVERROR_INVALIDDATA;
+ }
+
+ avctx->channel_layout = channel_layout;
+ avctx->channels = av_get_channel_layout_nb_channels(channel_layout);
+
+ for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) {
+ if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) {
+ if (ff_eac3_custom_channel_map_locations[ch][0]) {
+ int index = av_get_channel_layout_channel_index(channel_layout,
+ ff_eac3_custom_channel_map_locations[ch][1]);
+ if (index < 0)
+ return AVERROR_INVALIDDATA;
+ if (extend >= channel_map_size)
+ return AVERROR_INVALIDDATA;
+
+ extended_channel_map[index] = offset + channel_map[extend++];
+ } else {
+ int i;
+
+ for (i = 0; i < 64; i++) {
+ if ((1ULL << i) & ff_eac3_custom_channel_map_locations[ch][1]) {
+ int index = av_get_channel_layout_channel_index(channel_layout,
+ 1ULL << i);
+ if (index < 0)
+ return AVERROR_INVALIDDATA;
+ if (extend >= channel_map_size)
+ return AVERROR_INVALIDDATA;
+
+ extended_channel_map[index] = offset + channel_map[extend++];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* get output buffer */
+ frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ for (ch = 0; ch < avctx->channels; ch++) {
+ int map = extended_channel_map[ch];
+ av_assert0(ch>=AV_NUM_DATA_POINTERS || frame->extended_data[ch] == frame->data[ch]);
+ memcpy((SHORTFLOAT *)frame->extended_data[ch],
+ s->output_buffer[map],
+ s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT));
+ }
/*
* AVMatrixEncoding
*got_frame_ptr = 1;
- return FFMIN(buf_size, s->frame_size);
+ if (!s->superframe_size)
+ return FFMIN(full_buf_size, s->frame_size + skip);
+
+ return FFMIN(full_buf_size, s->superframe_size + skip);
}
/**