avcodec/dolby_e: Add a parser
This commit is contained in:
parent
a2a06029cf
commit
0bf18db26a
@ -57,6 +57,7 @@ version <next>:
|
|||||||
- tmidequalizer filter
|
- tmidequalizer filter
|
||||||
- estdif filter
|
- estdif filter
|
||||||
- epx filter
|
- epx filter
|
||||||
|
- Dolby E parser
|
||||||
|
|
||||||
|
|
||||||
version 4.3:
|
version 4.3:
|
||||||
|
@ -26,12 +26,14 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "get_bits.h"
|
#include "get_bits.h"
|
||||||
#include "put_bits.h"
|
#include "put_bits.h"
|
||||||
|
#include "parser.h"
|
||||||
#include "dolby_e.h"
|
#include "dolby_e.h"
|
||||||
#include "fft.h"
|
#include "fft.h"
|
||||||
|
|
||||||
static int skip_input(DBEContext *s, int nb_words)
|
static int skip_input(DBEContext *s, int nb_words)
|
||||||
{
|
{
|
||||||
if (nb_words > s->input_size) {
|
if (nb_words > s->input_size) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -44,7 +46,7 @@ static int skip_input(DBEContext *s, int nb_words)
|
|||||||
static int parse_key(DBEContext *s)
|
static int parse_key(DBEContext *s)
|
||||||
{
|
{
|
||||||
if (s->key_present) {
|
if (s->key_present) {
|
||||||
uint8_t *key = s->input;
|
const uint8_t *key = s->input;
|
||||||
int ret = skip_input(s, 1);
|
int ret = skip_input(s, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -55,7 +57,7 @@ static int parse_key(DBEContext *s)
|
|||||||
|
|
||||||
static int convert_input(DBEContext *s, int nb_words, int key)
|
static int convert_input(DBEContext *s, int nb_words, int key)
|
||||||
{
|
{
|
||||||
uint8_t *src = s->input;
|
const uint8_t *src = s->input;
|
||||||
uint8_t *dst = s->buffer;
|
uint8_t *dst = s->buffer;
|
||||||
PutBitContext pb;
|
PutBitContext pb;
|
||||||
int i;
|
int i;
|
||||||
@ -63,6 +65,7 @@ static int convert_input(DBEContext *s, int nb_words, int key)
|
|||||||
av_assert0(nb_words <= 1024u);
|
av_assert0(nb_words <= 1024u);
|
||||||
|
|
||||||
if (nb_words > s->input_size) {
|
if (nb_words > s->input_size) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -89,7 +92,7 @@ static int convert_input(DBEContext *s, int nb_words, int key)
|
|||||||
return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits);
|
return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_metadata(DBEContext *s)
|
static int parse_metadata(DBEContext *s, DolbyEHeaderInfo *hdr)
|
||||||
{
|
{
|
||||||
int i, ret, key, mtd_size;
|
int i, ret, key, mtd_size;
|
||||||
|
|
||||||
@ -101,6 +104,7 @@ static int parse_metadata(DBEContext *s)
|
|||||||
skip_bits(&s->gb, 4);
|
skip_bits(&s->gb, 4);
|
||||||
mtd_size = get_bits(&s->gb, 10);
|
mtd_size = get_bits(&s->gb, 10);
|
||||||
if (!mtd_size) {
|
if (!mtd_size) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -109,38 +113,41 @@ static int parse_metadata(DBEContext *s)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
skip_bits(&s->gb, 14);
|
skip_bits(&s->gb, 14);
|
||||||
s->prog_conf = get_bits(&s->gb, 6);
|
hdr->prog_conf = get_bits(&s->gb, 6);
|
||||||
if (s->prog_conf > MAX_PROG_CONF) {
|
if (hdr->prog_conf > MAX_PROG_CONF) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->nb_channels = nb_channels_tab[s->prog_conf];
|
hdr->nb_channels = nb_channels_tab[hdr->prog_conf];
|
||||||
s->nb_programs = nb_programs_tab[s->prog_conf];
|
hdr->nb_programs = nb_programs_tab[hdr->prog_conf];
|
||||||
|
|
||||||
s->fr_code = get_bits(&s->gb, 4);
|
hdr->fr_code = get_bits(&s->gb, 4);
|
||||||
s->fr_code_orig = get_bits(&s->gb, 4);
|
hdr->fr_code_orig = get_bits(&s->gb, 4);
|
||||||
if (!sample_rate_tab[s->fr_code] ||
|
if (!sample_rate_tab[hdr->fr_code] ||
|
||||||
!sample_rate_tab[s->fr_code_orig]) {
|
!sample_rate_tab[hdr->fr_code_orig]) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_bits_long(&s->gb, 88);
|
skip_bits_long(&s->gb, 88);
|
||||||
for (i = 0; i < s->nb_channels; i++)
|
for (i = 0; i < hdr->nb_channels; i++)
|
||||||
s->ch_size[i] = get_bits(&s->gb, 10);
|
hdr->ch_size[i] = get_bits(&s->gb, 10);
|
||||||
s->mtd_ext_size = get_bits(&s->gb, 8);
|
hdr->mtd_ext_size = get_bits(&s->gb, 8);
|
||||||
s->meter_size = get_bits(&s->gb, 8);
|
hdr->meter_size = get_bits(&s->gb, 8);
|
||||||
|
|
||||||
skip_bits_long(&s->gb, 10 * s->nb_programs);
|
skip_bits_long(&s->gb, 10 * hdr->nb_programs);
|
||||||
for (i = 0; i < s->nb_channels; i++) {
|
for (i = 0; i < hdr->nb_channels; i++) {
|
||||||
s->rev_id[i] = get_bits(&s->gb, 4);
|
hdr->rev_id[i] = get_bits(&s->gb, 4);
|
||||||
skip_bits1(&s->gb);
|
skip_bits1(&s->gb);
|
||||||
s->begin_gain[i] = get_bits(&s->gb, 10);
|
hdr->begin_gain[i] = get_bits(&s->gb, 10);
|
||||||
s->end_gain[i] = get_bits(&s->gb, 10);
|
hdr->end_gain[i] = get_bits(&s->gb, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_bits_left(&s->gb) < 0) {
|
if (get_bits_left(&s->gb) < 0) {
|
||||||
|
if (s->avctx)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -148,10 +155,11 @@ static int parse_metadata(DBEContext *s)
|
|||||||
return skip_input(s, mtd_size + 1);
|
return skip_input(s, mtd_size + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_metadata_ext(DBEContext *s)
|
static int parse_metadata_ext(DBEDecodeContext *s1)
|
||||||
{
|
{
|
||||||
if (s->mtd_ext_size)
|
DBEContext *s = &s1->dectx;
|
||||||
return skip_input(s, s->key_present + s->mtd_ext_size + 1);
|
if (s1->metadata.mtd_ext_size)
|
||||||
|
return skip_input(s, s->key_present + s1->metadata.mtd_ext_size + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,8 +287,9 @@ static void bit_allocate(int nb_exponent, int nb_code, int fr_code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_bit_alloc(DBEContext *s, DBEChannel *c)
|
static int parse_bit_alloc(DBEDecodeContext *s1, DBEChannel *c)
|
||||||
{
|
{
|
||||||
|
DBEContext *s = &s1->dectx;
|
||||||
DBEGroup *p, *g;
|
DBEGroup *p, *g;
|
||||||
int bap_strategy[MAX_GROUPS], fg_spc[MAX_GROUPS];
|
int bap_strategy[MAX_GROUPS], fg_spc[MAX_GROUPS];
|
||||||
int fg_ofs[MAX_GROUPS], msk_mod[MAX_GROUPS];
|
int fg_ofs[MAX_GROUPS], msk_mod[MAX_GROUPS];
|
||||||
@ -312,7 +321,7 @@ static int parse_bit_alloc(DBEContext *s, DBEChannel *c)
|
|||||||
|
|
||||||
for (i = 0, p = NULL, g = c->groups; i < c->nb_groups; i++, p = g, g++) {
|
for (i = 0, p = NULL, g = c->groups; i < c->nb_groups; i++, p = g, g++) {
|
||||||
if (c->exp_strategy[i] || bap_strategy[i]) {
|
if (c->exp_strategy[i] || bap_strategy[i]) {
|
||||||
bit_allocate(g->nb_exponent, g->imdct_idx, s->fr_code,
|
bit_allocate(g->nb_exponent, g->imdct_idx, s1->metadata.fr_code,
|
||||||
c->exponents + g->exp_ofs, c->bap + g->exp_ofs,
|
c->exponents + g->exp_ofs, c->bap + g->exp_ofs,
|
||||||
fg_spc[i], fg_ofs[i], msk_mod[i], snr_ofs);
|
fg_spc[i], fg_ofs[i], msk_mod[i], snr_ofs);
|
||||||
} else {
|
} else {
|
||||||
@ -412,17 +421,18 @@ static int parse_mantissas(DBEContext *s, DBEChannel *c)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_channel(DBEContext *s, int ch, int seg_id)
|
static int parse_channel(DBEDecodeContext *s1, int ch, int seg_id)
|
||||||
{
|
{
|
||||||
DBEChannel *c = &s->channels[seg_id][ch];
|
DBEContext *s = &s1->dectx;
|
||||||
|
DBEChannel *c = &s1->channels[seg_id][ch];
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
if (s->rev_id[ch] > 1) {
|
if (s1->metadata.rev_id[ch] > 1) {
|
||||||
avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s->rev_id[ch]);
|
avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s1->metadata.rev_id[ch]);
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == lfe_channel_tab[s->prog_conf]) {
|
if (ch == lfe_channel_tab[s1->metadata.prog_conf]) {
|
||||||
c->gr_code = 3;
|
c->gr_code = 3;
|
||||||
c->bw_code = 29;
|
c->bw_code = 29;
|
||||||
} else {
|
} else {
|
||||||
@ -447,7 +457,7 @@ static int parse_channel(DBEContext *s, int ch, int seg_id)
|
|||||||
|
|
||||||
if ((ret = parse_exponents(s, c)) < 0)
|
if ((ret = parse_exponents(s, c)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_bit_alloc(s, c)) < 0)
|
if ((ret = parse_bit_alloc(s1, c)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_indices(s, c)) < 0)
|
if ((ret = parse_indices(s, c)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -462,42 +472,44 @@ static int parse_channel(DBEContext *s, int ch, int seg_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_audio(DBEContext *s, int start, int end, int seg_id)
|
static int parse_audio(DBEDecodeContext *s1, int start, int end, int seg_id)
|
||||||
{
|
{
|
||||||
|
DBEContext *s = &s1->dectx;
|
||||||
int ch, ret, key;
|
int ch, ret, key;
|
||||||
|
|
||||||
if ((key = parse_key(s)) < 0)
|
if ((key = parse_key(s)) < 0)
|
||||||
return key;
|
return key;
|
||||||
|
|
||||||
for (ch = start; ch < end; ch++) {
|
for (ch = start; ch < end; ch++) {
|
||||||
if (!s->ch_size[ch]) {
|
if (!s1->metadata.ch_size[ch]) {
|
||||||
s->channels[seg_id][ch].nb_groups = 0;
|
s1->channels[seg_id][ch].nb_groups = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((ret = convert_input(s, s->ch_size[ch], key)) < 0)
|
if ((ret = convert_input(s, s1->metadata.ch_size[ch], key)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_channel(s, ch, seg_id)) < 0) {
|
if ((ret = parse_channel(s1, ch, seg_id)) < 0) {
|
||||||
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
if (s1->avctx->err_recognition & AV_EF_EXPLODE)
|
||||||
return ret;
|
return ret;
|
||||||
s->channels[seg_id][ch].nb_groups = 0;
|
s1->channels[seg_id][ch].nb_groups = 0;
|
||||||
}
|
}
|
||||||
if ((ret = skip_input(s, s->ch_size[ch])) < 0)
|
if ((ret = skip_input(s, s1->metadata.ch_size[ch])) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return skip_input(s, 1);
|
return skip_input(s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_meter(DBEContext *s)
|
static int parse_meter(DBEDecodeContext *s1)
|
||||||
{
|
{
|
||||||
if (s->meter_size)
|
DBEContext *s = &s1->dectx;
|
||||||
return skip_input(s, s->key_present + s->meter_size + 1);
|
if (s1->metadata.meter_size)
|
||||||
|
return skip_input(s, s->key_present + s1->metadata.meter_size + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imdct_calc(DBEContext *s, DBEGroup *g, float *result, float *values)
|
static void imdct_calc(DBEDecodeContext *s1, DBEGroup *g, float *result, float *values)
|
||||||
{
|
{
|
||||||
FFTContext *imdct = &s->imdct[g->imdct_idx];
|
FFTContext *imdct = &s1->imdct[g->imdct_idx];
|
||||||
int n = 1 << imdct_bits_tab[g->imdct_idx];
|
int n = 1 << imdct_bits_tab[g->imdct_idx];
|
||||||
int n2 = n >> 1;
|
int n2 = n >> 1;
|
||||||
int i;
|
int i;
|
||||||
@ -521,7 +533,7 @@ static void imdct_calc(DBEContext *s, DBEGroup *g, float *result, float *values)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transform(DBEContext *s, DBEChannel *c, float *history, float *output)
|
static void transform(DBEDecodeContext *s1, DBEChannel *c, float *history, float *output)
|
||||||
{
|
{
|
||||||
LOCAL_ALIGNED_32(float, buffer, [2048]);
|
LOCAL_ALIGNED_32(float, buffer, [2048]);
|
||||||
LOCAL_ALIGNED_32(float, result, [1152]);
|
LOCAL_ALIGNED_32(float, result, [1152]);
|
||||||
@ -534,8 +546,8 @@ static void transform(DBEContext *s, DBEChannel *c, float *history, float *outpu
|
|||||||
float *dst = result + g->dst_ofs;
|
float *dst = result + g->dst_ofs;
|
||||||
float *win = window + g->win_ofs;
|
float *win = window + g->win_ofs;
|
||||||
|
|
||||||
imdct_calc(s, g, buffer, c->mantissas + g->mnt_ofs);
|
imdct_calc(s1, g, buffer, c->mantissas + g->mnt_ofs);
|
||||||
s->fdsp->vector_fmul_add(dst, src, win, dst, g->win_len);
|
s1->fdsp->vector_fmul_add(dst, src, win, dst, g->win_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
@ -546,7 +558,7 @@ static void transform(DBEContext *s, DBEChannel *c, float *history, float *outpu
|
|||||||
history[i] = result[896 + i];
|
history[i] = result[896 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_gain(DBEContext *s, int begin, int end, float *output)
|
static void apply_gain(DBEDecodeContext *s, int begin, int end, float *output)
|
||||||
{
|
{
|
||||||
if (begin == 960 && end == 960)
|
if (begin == 960 && end == 960)
|
||||||
return;
|
return;
|
||||||
@ -563,16 +575,16 @@ static void apply_gain(DBEContext *s, int begin, int end, float *output)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int filter_frame(DBEContext *s, AVFrame *frame)
|
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
|
||||||
{
|
{
|
||||||
const uint8_t *reorder;
|
const uint8_t *reorder;
|
||||||
int ch, ret;
|
int ch, ret;
|
||||||
|
|
||||||
if (s->nb_channels == 4)
|
if (s->metadata.nb_channels == 4)
|
||||||
reorder = ch_reorder_4;
|
reorder = ch_reorder_4;
|
||||||
else if (s->nb_channels == 6)
|
else if (s->metadata.nb_channels == 6)
|
||||||
reorder = ch_reorder_6;
|
reorder = ch_reorder_6;
|
||||||
else if (s->nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE))
|
else if (s->metadata.nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE))
|
||||||
reorder = ch_reorder_8;
|
reorder = ch_reorder_8;
|
||||||
else
|
else
|
||||||
reorder = ch_reorder_n;
|
reorder = ch_reorder_n;
|
||||||
@ -581,26 +593,24 @@ static int filter_frame(DBEContext *s, AVFrame *frame)
|
|||||||
if ((ret = ff_get_buffer(s->avctx, frame, 0)) < 0)
|
if ((ret = ff_get_buffer(s->avctx, frame, 0)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for (ch = 0; ch < s->nb_channels; ch++) {
|
for (ch = 0; ch < s->metadata.nb_channels; ch++) {
|
||||||
float *output = (float *)frame->extended_data[reorder[ch]];
|
float *output = (float *)frame->extended_data[reorder[ch]];
|
||||||
transform(s, &s->channels[0][ch], s->history[ch], output);
|
transform(s, &s->channels[0][ch], s->history[ch], output);
|
||||||
transform(s, &s->channels[1][ch], s->history[ch], output + FRAME_SAMPLES / 2);
|
transform(s, &s->channels[1][ch], s->history[ch], output + FRAME_SAMPLES / 2);
|
||||||
apply_gain(s, s->begin_gain[ch], s->end_gain[ch], output);
|
apply_gain(s, s->metadata.begin_gain[ch], s->metadata.end_gain[ch], output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
|
static int dolby_e_sync(DBEContext *s, const uint8_t *buf, int buf_size)
|
||||||
int *got_frame_ptr, AVPacket *avpkt)
|
|
||||||
{
|
{
|
||||||
DBEContext *s = avctx->priv_data;
|
int hdr;
|
||||||
int i, j, hdr, ret;
|
|
||||||
|
|
||||||
if (avpkt->size < 3)
|
if (buf_size < 3)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
hdr = AV_RB24(avpkt->data);
|
hdr = AV_RB24(buf);
|
||||||
if ((hdr & 0xfffffe) == 0x7888e) {
|
if ((hdr & 0xfffffe) == 0x7888e) {
|
||||||
s->word_bits = 24;
|
s->word_bits = 24;
|
||||||
} else if ((hdr & 0xffffe0) == 0x788e0) {
|
} else if ((hdr & 0xffffe0) == 0x788e0) {
|
||||||
@ -608,25 +618,35 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
} else if ((hdr & 0xfffe00) == 0x78e00) {
|
} else if ((hdr & 0xfffe00) == 0x78e00) {
|
||||||
s->word_bits = 16;
|
s->word_bits = 16;
|
||||||
} else {
|
} else {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n");
|
if (s->avctx)
|
||||||
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid frame header\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->word_bytes = s->word_bits + 7 >> 3;
|
s->word_bytes = s->word_bits + 7 >> 3;
|
||||||
s->input = avpkt->data + s->word_bytes;
|
s->input = buf + s->word_bytes;
|
||||||
s->input_size = avpkt->size / s->word_bytes - 1;
|
s->input_size = buf_size / s->word_bytes - 1;
|
||||||
s->key_present = hdr >> 24 - s->word_bits & 1;
|
s->key_present = hdr >> 24 - s->word_bits & 1;
|
||||||
|
|
||||||
if ((ret = parse_metadata(s)) < 0)
|
return 0;
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (s->nb_programs > 1 && !s->multi_prog_warned) {
|
|
||||||
av_log(avctx, AV_LOG_WARNING, "Stream has %d programs (configuration %d), "
|
|
||||||
"channels will be output in native order.\n", s->nb_programs, s->prog_conf);
|
|
||||||
s->multi_prog_warned = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (s->nb_channels) {
|
static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx,
|
||||||
|
const uint8_t **poutbuf, int *poutbuf_size,
|
||||||
|
const uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
DBEParseContext *s1 = s2->priv_data;
|
||||||
|
DBEContext *s = &s1->dectx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = dolby_e_sync(s, buf, buf_size)) < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if ((ret = parse_metadata(s, &s1->metadata)) < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
s2->duration = FRAME_SAMPLES;
|
||||||
|
switch (s1->metadata.nb_channels) {
|
||||||
case 4:
|
case 4:
|
||||||
avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
|
avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
|
||||||
break;
|
break;
|
||||||
@ -638,25 +658,68 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
avctx->channels = s->nb_channels;
|
avctx->channels = s1->metadata.nb_channels;
|
||||||
avctx->sample_rate = sample_rate_tab[s->fr_code];
|
avctx->sample_rate = sample_rate_tab[s1->metadata.fr_code];
|
||||||
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||||
|
|
||||||
i = s->nb_channels / 2;
|
end:
|
||||||
j = s->nb_channels;
|
/* always return the full packet. this parser isn't doing any splitting or
|
||||||
if ((ret = parse_audio(s, 0, i, 0)) < 0)
|
combining, only packet analysis */
|
||||||
|
*poutbuf = buf;
|
||||||
|
*poutbuf_size = buf_size;
|
||||||
|
return buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
|
||||||
|
int *got_frame_ptr, AVPacket *avpkt)
|
||||||
|
{
|
||||||
|
DBEDecodeContext *s1 = avctx->priv_data;
|
||||||
|
DBEContext *s = &s1->dectx;
|
||||||
|
int i, j, ret;
|
||||||
|
|
||||||
|
if ((ret = dolby_e_sync(s, avpkt->data, avpkt->size)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_audio(s, i, j, 0)) < 0)
|
|
||||||
|
if ((ret = parse_metadata(s, &s1->metadata)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_metadata_ext(s)) < 0)
|
|
||||||
|
if (s1->metadata.nb_programs > 1 && !s1->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (s1->metadata.nb_channels) {
|
||||||
|
case 4:
|
||||||
|
avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
avctx->channel_layout = AV_CH_LAYOUT_5POINT1;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
avctx->channel_layout = AV_CH_LAYOUT_7POINT1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
avctx->channels = s1->metadata.nb_channels;
|
||||||
|
avctx->sample_rate = sample_rate_tab[s1->metadata.fr_code];
|
||||||
|
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||||
|
|
||||||
|
i = s1->metadata.nb_channels / 2;
|
||||||
|
j = s1->metadata.nb_channels;
|
||||||
|
if ((ret = parse_audio(s1, 0, i, 0)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_audio(s, 0, i, 1)) < 0)
|
if ((ret = parse_audio(s1, i, j, 0)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_audio(s, i, j, 1)) < 0)
|
if ((ret = parse_metadata_ext(s1)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = parse_meter(s)) < 0)
|
if ((ret = parse_audio(s1, 0, i, 1)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = filter_frame(s, data)) < 0)
|
if ((ret = parse_audio(s1, i, j, 1)) < 0)
|
||||||
|
return ret;
|
||||||
|
if ((ret = parse_meter(s1)) < 0)
|
||||||
|
return ret;
|
||||||
|
if ((ret = filter_frame(s1, data)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*got_frame_ptr = 1;
|
*got_frame_ptr = 1;
|
||||||
@ -665,14 +728,14 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
|
|
||||||
static av_cold void dolby_e_flush(AVCodecContext *avctx)
|
static av_cold void dolby_e_flush(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
DBEContext *s = avctx->priv_data;
|
DBEDecodeContext *s = avctx->priv_data;
|
||||||
|
|
||||||
memset(s->history, 0, sizeof(s->history));
|
memset(s->history, 0, sizeof(s->history));
|
||||||
}
|
}
|
||||||
|
|
||||||
static av_cold int dolby_e_close(AVCodecContext *avctx)
|
static av_cold int dolby_e_close(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
DBEContext *s = avctx->priv_data;
|
DBEDecodeContext *s = avctx->priv_data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
@ -772,7 +835,7 @@ static av_cold void init_tables(void)
|
|||||||
static av_cold int dolby_e_init(AVCodecContext *avctx)
|
static av_cold int dolby_e_init(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
static AVOnce init_once = AV_ONCE_INIT;
|
static AVOnce init_once = AV_ONCE_INIT;
|
||||||
DBEContext *s = avctx->priv_data;
|
DBEDecodeContext *s = avctx->priv_data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (ff_thread_once(&init_once, init_tables))
|
if (ff_thread_once(&init_once, init_tables))
|
||||||
@ -785,17 +848,24 @@ static av_cold int dolby_e_init(AVCodecContext *avctx)
|
|||||||
if (!(s->fdsp = avpriv_float_dsp_alloc(0)))
|
if (!(s->fdsp = avpriv_float_dsp_alloc(0)))
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
s->multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE);
|
s->metadata.multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE);
|
||||||
s->avctx = avctx;
|
s->dectx.avctx = s->avctx = avctx;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AVCodecParser ff_dolby_e_parser = {
|
||||||
|
.codec_ids = { AV_CODEC_ID_DOLBY_E },
|
||||||
|
.priv_data_size = sizeof(DBEParseContext),
|
||||||
|
.parser_parse = dolby_e_parse,
|
||||||
|
.parser_close = ff_parse_close,
|
||||||
|
};
|
||||||
|
|
||||||
AVCodec ff_dolby_e_decoder = {
|
AVCodec ff_dolby_e_decoder = {
|
||||||
.name = "dolby_e",
|
.name = "dolby_e",
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("Dolby E"),
|
.long_name = NULL_IF_CONFIG_SMALL("Dolby E"),
|
||||||
.type = AVMEDIA_TYPE_AUDIO,
|
.type = AVMEDIA_TYPE_AUDIO,
|
||||||
.id = AV_CODEC_ID_DOLBY_E,
|
.id = AV_CODEC_ID_DOLBY_E,
|
||||||
.priv_data_size = sizeof(DBEContext),
|
.priv_data_size = sizeof(DBEDecodeContext),
|
||||||
.init = dolby_e_init,
|
.init = dolby_e_init,
|
||||||
.decode = dolby_e_decode_frame,
|
.decode = dolby_e_decode_frame,
|
||||||
.close = dolby_e_close,
|
.close = dolby_e_close,
|
||||||
|
@ -75,16 +75,27 @@ typedef struct DBEChannel {
|
|||||||
} DBEChannel;
|
} DBEChannel;
|
||||||
|
|
||||||
typedef struct DBEContext {
|
typedef struct DBEContext {
|
||||||
AVCodecContext *avctx;
|
void *avctx;
|
||||||
GetBitContext gb;
|
GetBitContext gb;
|
||||||
|
|
||||||
uint8_t *input;
|
const uint8_t *input;
|
||||||
int input_size;
|
int input_size;
|
||||||
|
|
||||||
int word_bits;
|
int word_bits;
|
||||||
int word_bytes;
|
int word_bytes;
|
||||||
int key_present;
|
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.
|
||||||
|
*/
|
||||||
|
typedef struct DolbyEHeaderInfo {
|
||||||
|
/** @name Coded elements
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
int prog_conf;
|
int prog_conf;
|
||||||
int nb_channels;
|
int nb_channels;
|
||||||
int nb_programs;
|
int nb_programs;
|
||||||
@ -99,8 +110,27 @@ typedef struct DBEContext {
|
|||||||
int rev_id[MAX_CHANNELS];
|
int rev_id[MAX_CHANNELS];
|
||||||
int begin_gain[MAX_CHANNELS];
|
int begin_gain[MAX_CHANNELS];
|
||||||
int end_gain[MAX_CHANNELS];
|
int end_gain[MAX_CHANNELS];
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @name Derived values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
int multi_prog_warned;
|
int multi_prog_warned;
|
||||||
|
/** @} */
|
||||||
|
} DolbyEHeaderInfo;
|
||||||
|
|
||||||
|
typedef struct DBEParseContext {
|
||||||
|
ParseContext pc;
|
||||||
|
DBEContext dectx;
|
||||||
|
|
||||||
|
DolbyEHeaderInfo metadata;
|
||||||
|
} DBEParseContext;
|
||||||
|
|
||||||
|
typedef struct DBEDecodeContext {
|
||||||
|
AVCodecContext *avctx;
|
||||||
|
DBEContext dectx;
|
||||||
|
|
||||||
|
DolbyEHeaderInfo metadata;
|
||||||
|
|
||||||
DBEChannel channels[MAX_SEGMENTS][MAX_CHANNELS];
|
DBEChannel channels[MAX_SEGMENTS][MAX_CHANNELS];
|
||||||
|
|
||||||
@ -108,9 +138,7 @@ typedef struct DBEContext {
|
|||||||
|
|
||||||
FFTContext imdct[3];
|
FFTContext imdct[3];
|
||||||
AVFloatDSPContext *fdsp;
|
AVFloatDSPContext *fdsp;
|
||||||
|
} DBEDecodeContext;
|
||||||
uint8_t buffer[1024 * 3 + AV_INPUT_BUFFER_PADDING_SIZE];
|
|
||||||
} DBEContext;
|
|
||||||
|
|
||||||
static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = {
|
static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = {
|
||||||
2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1
|
2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1
|
||||||
|
@ -36,6 +36,7 @@ extern AVCodecParser ff_cook_parser;
|
|||||||
extern AVCodecParser ff_dca_parser;
|
extern AVCodecParser ff_dca_parser;
|
||||||
extern AVCodecParser ff_dirac_parser;
|
extern AVCodecParser ff_dirac_parser;
|
||||||
extern AVCodecParser ff_dnxhd_parser;
|
extern AVCodecParser ff_dnxhd_parser;
|
||||||
|
extern AVCodecParser ff_dolby_e_parser;
|
||||||
extern AVCodecParser ff_dpx_parser;
|
extern AVCodecParser ff_dpx_parser;
|
||||||
extern AVCodecParser ff_dvaudio_parser;
|
extern AVCodecParser ff_dvaudio_parser;
|
||||||
extern AVCodecParser ff_dvbsub_parser;
|
extern AVCodecParser ff_dvbsub_parser;
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 58
|
#define LIBAVCODEC_VERSION_MAJOR 58
|
||||||
#define LIBAVCODEC_VERSION_MINOR 117
|
#define LIBAVCODEC_VERSION_MINOR 118
|
||||||
#define LIBAVCODEC_VERSION_MICRO 101
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user