avcodec/eac3: add support for dependent stream

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol
2018-03-29 10:19:03 +02:00
parent e5819fa629
commit ae92970976
8 changed files with 167 additions and 53 deletions
+145 -34
View File
@@ -106,6 +106,25 @@ static const uint8_t ac3_default_coeffs[8][5][2] = {
{ { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, },
};
static const uint64_t custom_channel_map_locations[16][2] = {
{ 1, AV_CH_FRONT_LEFT },
{ 1, AV_CH_FRONT_CENTER },
{ 1, AV_CH_FRONT_RIGHT },
{ 1, AV_CH_SIDE_LEFT },
{ 1, AV_CH_SIDE_RIGHT },
{ 0, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
{ 0, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
{ 0, AV_CH_BACK_CENTER },
{ 0, AV_CH_TOP_CENTER },
{ 0, AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT },
{ 0, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
{ 0, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT},
{ 0, AV_CH_TOP_FRONT_CENTER },
{ 0, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
{ 0, AV_CH_LOW_FREQUENCY_2 },
{ 1, AV_CH_LOW_FREQUENCY },
};
/**
* Symmetrical Dequantization
* reference: Section 7.3.3 Expansion of Mantissas for Symmetrical Quantization
@@ -317,6 +336,7 @@ static int parse_frame_header(AC3DecodeContext *s)
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
@@ -683,7 +703,7 @@ static void do_rematrixing(AC3DecodeContext *s)
* 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;
@@ -695,25 +715,25 @@ static inline void do_imdct(AC3DecodeContext *s, int channels)
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));
}
}
}
@@ -1063,7 +1083,7 @@ static inline int coupling_coordinates(AC3DecodeContext *s, int blk)
/**
* 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;
@@ -1426,7 +1446,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
ac3_upmix_delay(s);
}
do_imdct(s, s->channels);
do_imdct(s, s->channels, offset);
if (downmix_output) {
#if USE_FIXED
@@ -1449,7 +1469,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
s->out_channels, s->fbw_channels, 128);
}
do_imdct(s, s->out_channels);
do_imdct(s, s->out_channels, offset);
}
return 0;
@@ -1463,14 +1483,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
{
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 got_independent_frame = 0;
const uint8_t *channel_map;
uint8_t extended_channel_map[AC3_MAX_CHANNELS * 2];
const SHORTFLOAT *output[AC3_MAX_CHANNELS];
enum AVMatrixEncoding matrix_encoding;
AVDownmixInfo *downmix_info;
s->superframe_size = 0;
buf_size = full_buf_size;
/* 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) {
@@ -1488,6 +1513,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
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;
@@ -1511,11 +1537,11 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
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 {
@@ -1546,10 +1572,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
}
}
/* 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 */
@@ -1594,29 +1620,25 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
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++) {
@@ -1625,11 +1647,100 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
}
}
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 ((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;
}
}
}
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 < 16; 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];
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 << (15 - ch))) {
channel_layout |= custom_channel_map_locations[ch][1];
}
}
avctx->channel_layout = channel_layout;
avctx->channels = av_get_channel_layout_nb_channels(channel_layout);
for (ch = 0; ch < 16; ch++) {
if (s->channel_map & (1 << (15 - ch))) {
if (custom_channel_map_locations[ch][0]) {
int index = av_get_channel_layout_channel_index(channel_layout,
custom_channel_map_locations[ch][1]);
if (index < 0)
return AVERROR_INVALIDDATA;
extended_channel_map[index] = offset + channel_map[extend++];
} else {
int i;
for (i = 0; i < 64; i++) {
if ((1LL << i) & custom_channel_map_locations[ch][1]) {
int index = av_get_channel_layout_channel_index(channel_layout,
1LL << i);
if (index < 0)
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];
memcpy((SHORTFLOAT *)frame->data[ch], s->output_buffer[map],
s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT));
}
/*
* AVMatrixEncoding
@@ -1689,7 +1800,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
*got_frame_ptr = 1;
return FFMIN(buf_size, s->frame_size);
return FFMIN(full_buf_size, s->superframe_size);
}
/**