avcodec/dolby_e_parse: Merge ff_dolby_e_parse_init/header

These two functions are always called after another; after all, what
ff_dolby_e_parse_init does is obviously part of parsing the frame header.

Also move the DolbyEHeaderInfo into DBEContext so that parsing the frame
header only needs one struct (both users used a DBEContext immediately
followed by a separate DolbyEHeaderInfo).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
Andreas Rheinhardt 2021-01-26 15:46:15 +01:00
parent fa3ab43fec
commit 8cbff41583
4 changed files with 76 additions and 96 deletions

View File

@ -73,8 +73,6 @@ typedef struct DBEDecodeContext {
AVCodecContext *avctx;
DBEContext dectx;
DolbyEHeaderInfo metadata;
DBEChannel channels[MAX_SEGMENTS][MAX_CHANNELS];
DECLARE_ALIGNED(32, float, history)[MAX_CHANNELS][256];
@ -667,8 +665,8 @@ static int convert_input(DBEContext *s, int nb_words, int key)
static int parse_metadata_ext(DBEDecodeContext *s1)
{
DBEContext *s = &s1->dectx;
if (s1->metadata.mtd_ext_size)
return skip_input(s, s->key_present + s1->metadata.mtd_ext_size + 1);
if (s->metadata.mtd_ext_size)
return skip_input(s, s->key_present + s->metadata.mtd_ext_size + 1);
return 0;
}
@ -830,7 +828,7 @@ static int parse_bit_alloc(DBEDecodeContext *s1, DBEChannel *c)
for (i = 0, p = NULL, g = c->groups; i < c->nb_groups; i++, p = g, g++) {
if (c->exp_strategy[i] || bap_strategy[i]) {
bit_allocate(g->nb_exponent, g->imdct_idx, s1->metadata.fr_code,
bit_allocate(g->nb_exponent, g->imdct_idx, s->metadata.fr_code,
c->exponents + g->exp_ofs, c->bap + g->exp_ofs,
fg_spc[i], fg_ofs[i], msk_mod[i], snr_ofs);
} else {
@ -936,12 +934,12 @@ static int parse_channel(DBEDecodeContext *s1, int ch, int seg_id)
DBEChannel *c = &s1->channels[seg_id][ch];
int i, ret;
if (s1->metadata.rev_id[ch] > 1) {
avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s1->metadata.rev_id[ch]);
if (s->metadata.rev_id[ch] > 1) {
avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s->metadata.rev_id[ch]);
return AVERROR_PATCHWELCOME;
}
if (ch == lfe_channel_tab[s1->metadata.prog_conf]) {
if (ch == lfe_channel_tab[s->metadata.prog_conf]) {
c->gr_code = 3;
c->bw_code = 29;
} else {
@ -990,18 +988,18 @@ static int parse_audio(DBEDecodeContext *s1, int start, int end, int seg_id)
return key;
for (ch = start; ch < end; ch++) {
if (!s1->metadata.ch_size[ch]) {
if (!s->metadata.ch_size[ch]) {
s1->channels[seg_id][ch].nb_groups = 0;
continue;
}
if ((ret = convert_input(s, s1->metadata.ch_size[ch], key)) < 0)
if ((ret = convert_input(s, s->metadata.ch_size[ch], key)) < 0)
return ret;
if ((ret = parse_channel(s1, ch, seg_id)) < 0) {
if (s1->avctx->err_recognition & AV_EF_EXPLODE)
return ret;
s1->channels[seg_id][ch].nb_groups = 0;
}
if ((ret = skip_input(s, s1->metadata.ch_size[ch])) < 0)
if ((ret = skip_input(s, s->metadata.ch_size[ch])) < 0)
return ret;
}
@ -1011,8 +1009,8 @@ static int parse_audio(DBEDecodeContext *s1, int start, int end, int seg_id)
static int parse_meter(DBEDecodeContext *s1)
{
DBEContext *s = &s1->dectx;
if (s1->metadata.meter_size)
return skip_input(s, s->key_present + s1->metadata.meter_size + 1);
if (s->metadata.meter_size)
return skip_input(s, s->key_present + s->metadata.meter_size + 1);
return 0;
}
@ -1086,14 +1084,15 @@ static void apply_gain(DBEDecodeContext *s, int begin, int end, float *output)
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
{
const DolbyEHeaderInfo *const metadata = &s->dectx.metadata;
const uint8_t *reorder;
int ch, ret;
if (s->metadata.nb_channels == 4)
if (metadata->nb_channels == 4)
reorder = ch_reorder_4;
else if (s->metadata.nb_channels == 6)
else if (metadata->nb_channels == 6)
reorder = ch_reorder_6;
else if (s->metadata.nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE))
else if (metadata->nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE))
reorder = ch_reorder_8;
else
reorder = ch_reorder_n;
@ -1102,11 +1101,11 @@ static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
if ((ret = ff_get_buffer(s->avctx, frame, 0)) < 0)
return ret;
for (ch = 0; ch < s->metadata.nb_channels; ch++) {
for (ch = 0; ch < metadata->nb_channels; ch++) {
float *output = (float *)frame->extended_data[reorder[ch]];
transform(s, &s->channels[0][ch], s->history[ch], output);
transform(s, &s->channels[1][ch], s->history[ch], output + FRAME_SAMPLES / 2);
apply_gain(s, s->metadata.begin_gain[ch], s->metadata.end_gain[ch], output);
apply_gain(s, metadata->begin_gain[ch], metadata->end_gain[ch], output);
}
return 0;
@ -1119,19 +1118,17 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
DBEContext *s = &s1->dectx;
int i, j, ret;
if ((ret = ff_dolby_e_parse_init(s, avpkt->data, avpkt->size)) < 0)
if ((ret = ff_dolby_e_parse_header(s, avpkt->data, avpkt->size)) < 0)
return ret;
if ((ret = ff_dolby_e_parse_header(s, &s1->metadata)) < 0)
return ret;
if (s1->metadata.nb_programs > 1 && !s1->metadata.multi_prog_warned) {
if (s->metadata.nb_programs > 1 && !s->metadata.multi_prog_warned) {
av_log(avctx, AV_LOG_WARNING, "Stream has %d programs (configuration %d), "
"channels will be output in native order.\n", s1->metadata.nb_programs, s1->metadata.prog_conf);
s1->metadata.multi_prog_warned = 1;
"channels will be output in native order.\n",
s->metadata.nb_programs, s->metadata.prog_conf);
s->metadata.multi_prog_warned = 1;
}
switch (s1->metadata.nb_channels) {
switch (s->metadata.nb_channels) {
case 4:
avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
break;
@ -1143,12 +1140,12 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
break;
}
avctx->channels = s1->metadata.nb_channels;
avctx->sample_rate = sample_rate_tab[s1->metadata.fr_code];
avctx->channels = s->metadata.nb_channels;
avctx->sample_rate = sample_rate_tab[s->metadata.fr_code];
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
i = s1->metadata.nb_channels / 2;
j = s1->metadata.nb_channels;
i = s->metadata.nb_channels / 2;
j = s->metadata.nb_channels;
if ((ret = parse_audio(s1, 0, i, 0)) < 0)
return ret;
if ((ret = parse_audio(s1, i, j, 0)) < 0)
@ -1290,7 +1287,7 @@ static av_cold int dolby_e_init(AVCodecContext *avctx)
if (!(s->fdsp = avpriv_float_dsp_alloc(0)))
return AVERROR(ENOMEM);
s->metadata.multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE);
s->dectx.metadata.multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE);
s->dectx.avctx = s->avctx = avctx;
return 0;
}

View File

@ -30,24 +30,6 @@
#define MAX_PROGRAMS 8
#define MAX_CHANNELS 8
/**
* @struct DBEContext
* Dolby E reading context used by decoder and parser.
*/
typedef struct DBEContext {
void *avctx;
GetBitContext gb;
const uint8_t *input;
int input_size;
int word_bits;
int word_bytes;
int key_present;
uint8_t buffer[1024 * 3 + AV_INPUT_BUFFER_PADDING_SIZE];
} DBEContext;
/**
* @struct DolbyEHeaderInfo
* Coded Dolby E header values up to end_gain element, plus derived values.
@ -79,26 +61,38 @@ typedef struct DolbyEHeaderInfo {
/** @} */
} DolbyEHeaderInfo;
/**
* @struct DBEContext
* Dolby E reading context used by decoder and parser.
*/
typedef struct DBEContext {
void *avctx;
GetBitContext gb;
const uint8_t *input;
int input_size;
int word_bits;
int word_bytes;
int key_present;
DolbyEHeaderInfo metadata;
uint8_t buffer[1024 * 3 + AV_INPUT_BUFFER_PADDING_SIZE];
} DBEContext;
static const uint16_t sample_rate_tab[16] = {
0, 42965, 43008, 44800, 53706, 53760
};
/**
* Initialize DBEContext.
* Set word_bits/word_bytes, input, input_size, key_present.
* Initialize DBEContext and parse Dolby E metadata.
* Set word_bits/word_bytes, input, input_size, key_present
* and parse the header up to the end_gain element.
* @param[out] s DBEContext.
* @param[in] buf raw input buffer.
* @param[in] buf_size must be 3 bytes at least.
* @return Returns 0 on success, AVERROR_INVALIDDATA on error
*/
int ff_dolby_e_parse_init(DBEContext *s, const uint8_t *buf, int buf_size);
/**
* Parse Dolby E metadata.
* Parse the header up to the end_gain element.
* @param[in] s DBEContext .
* @param[out] hdr Pointer to struct where header info is written.
* @return Returns 0 on success, AVERROR_INVALIDDATA on error
*/
int ff_dolby_e_parse_header(DBEContext *s, DolbyEHeaderInfo *hdr);
int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size);
#endif

View File

@ -88,9 +88,10 @@ static int convert_input(DBEContext *s, int nb_words, int key)
return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits);
}
int ff_dolby_e_parse_init(DBEContext *s, const uint8_t *buf, int buf_size)
int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size)
{
int hdr;
DolbyEHeaderInfo *const header = &s->metadata;
int hdr, ret, key, mtd_size;
if (buf_size < 3)
return AVERROR_INVALIDDATA;
@ -113,13 +114,6 @@ int ff_dolby_e_parse_init(DBEContext *s, const uint8_t *buf, int buf_size)
s->input_size = buf_size / s->word_bytes - 1;
s->key_present = hdr >> 24 - s->word_bits & 1;
return 0;
}
int ff_dolby_e_parse_header(DBEContext *s, DolbyEHeaderInfo *hdr)
{
int i, ret, key, mtd_size;
if ((key = parse_key(s)) < 0)
return key;
if ((ret = convert_input(s, 1, key)) < 0)
@ -137,37 +131,37 @@ int ff_dolby_e_parse_header(DBEContext *s, DolbyEHeaderInfo *hdr)
return ret;
skip_bits(&s->gb, 14);
hdr->prog_conf = get_bits(&s->gb, 6);
if (hdr->prog_conf > MAX_PROG_CONF) {
header->prog_conf = get_bits(&s->gb, 6);
if (header->prog_conf > MAX_PROG_CONF) {
if (s->avctx)
av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n");
return AVERROR_INVALIDDATA;
}
hdr->nb_channels = nb_channels_tab[hdr->prog_conf];
hdr->nb_programs = nb_programs_tab[hdr->prog_conf];
header->nb_channels = nb_channels_tab[header->prog_conf];
header->nb_programs = nb_programs_tab[header->prog_conf];
hdr->fr_code = get_bits(&s->gb, 4);
hdr->fr_code_orig = get_bits(&s->gb, 4);
if (!sample_rate_tab[hdr->fr_code] ||
!sample_rate_tab[hdr->fr_code_orig]) {
header->fr_code = get_bits(&s->gb, 4);
header->fr_code_orig = get_bits(&s->gb, 4);
if (!sample_rate_tab[header->fr_code] ||
!sample_rate_tab[header->fr_code_orig]) {
if (s->avctx)
av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n");
return AVERROR_INVALIDDATA;
}
skip_bits_long(&s->gb, 88);
for (i = 0; i < hdr->nb_channels; i++)
hdr->ch_size[i] = get_bits(&s->gb, 10);
hdr->mtd_ext_size = get_bits(&s->gb, 8);
hdr->meter_size = get_bits(&s->gb, 8);
for (int i = 0; i < header->nb_channels; i++)
header->ch_size[i] = get_bits(&s->gb, 10);
header->mtd_ext_size = get_bits(&s->gb, 8);
header->meter_size = get_bits(&s->gb, 8);
skip_bits_long(&s->gb, 10 * hdr->nb_programs);
for (i = 0; i < hdr->nb_channels; i++) {
hdr->rev_id[i] = get_bits(&s->gb, 4);
skip_bits_long(&s->gb, 10 * header->nb_programs);
for (int i = 0; i < header->nb_channels; i++) {
header->rev_id[i] = get_bits(&s->gb, 4);
skip_bits1(&s->gb);
hdr->begin_gain[i] = get_bits(&s->gb, 10);
hdr->end_gain[i] = get_bits(&s->gb, 10);
header->begin_gain[i] = get_bits(&s->gb, 10);
header->end_gain[i] = get_bits(&s->gb, 10);
}
if (get_bits_left(&s->gb) < 0) {

View File

@ -24,8 +24,6 @@
typedef struct DBEParseContext {
DBEContext dectx;
DolbyEHeaderInfo metadata;
} DBEParseContext;
static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx,
@ -36,14 +34,11 @@ static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx,
DBEContext *s = &s1->dectx;
int ret;
if ((ret = ff_dolby_e_parse_init(s, buf, buf_size)) < 0)
goto end;
if ((ret = ff_dolby_e_parse_header(s, &s1->metadata)) < 0)
if ((ret = ff_dolby_e_parse_header(s, buf, buf_size)) < 0)
goto end;
s2->duration = FRAME_SAMPLES;
switch (s1->metadata.nb_channels) {
switch (s->metadata.nb_channels) {
case 4:
avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
break;
@ -55,8 +50,8 @@ static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx,
break;
}
avctx->channels = s1->metadata.nb_channels;
avctx->sample_rate = sample_rate_tab[s1->metadata.fr_code];
avctx->channels = s->metadata.nb_channels;
avctx->sample_rate = sample_rate_tab[s->metadata.fr_code];
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
end: