From 18b2ecc24778140c2bc798ed64842dc8feb6dc3a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Feb 2023 20:19:14 +0100 Subject: [PATCH] avcodec/wavarc: add 5elp mode support --- libavcodec/wavarc.c | 349 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 348 insertions(+), 1 deletion(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 7bfc276df4..6daad6a5a1 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -30,6 +30,8 @@ #include "unary.h" typedef struct WavArcContext { + AVClass *av_class; + GetBitContext gb; int shift; @@ -47,6 +49,16 @@ typedef struct WavArcContext { int pred[2][70]; int filter[2][70]; int samples[2][640]; + uint8_t model[256]; + uint16_t freqs[257]; + uint16_t ac_value; + uint16_t ac_low; + uint16_t ac_high; + uint16_t range_high; + uint16_t range_low; + uint16_t freq_range; + int ac_pred[70]; + int ac_out[570]; } WavArcContext; static av_cold int wavarc_init(AVCodecContext *avctx) @@ -90,6 +102,7 @@ static av_cold int wavarc_init(AVCodecContext *avctx) case MKTAG('2','S','L','P'): case MKTAG('3','N','L','P'): case MKTAG('4','A','L','P'): + case MKTAG('5','E','L','P'): s->nb_samples = 570; s->offset = 70; break; @@ -343,7 +356,7 @@ static int decode_2slp(AVCodecContext *avctx, break; case 0: order = get_urice(gb, 2); - if ((unsigned)order >= FF_ARRAY_ELEMS(s->filter[ch])) + if ((unsigned)order > FF_ARRAY_ELEMS(s->filter[ch])) return AVERROR_INVALIDDATA; for (int o = 0; o < order; o++) s->filter[ch][o] = get_srice(gb, 2); @@ -378,6 +391,337 @@ static int decode_2slp(AVCodecContext *avctx, return 0; } +static int ac_init(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + s->ac_low = 0; + s->ac_high = 0xffffu; + s->ac_value = get_bits(gb, 16); + + s->freq_range = s->freqs[256]; + if (!s->freq_range) + return AVERROR_INVALIDDATA; + return 0; +} + +static unsigned ac_get_prob(WavArcContext *s) +{ + return ((s->freq_range - 1) + ((unsigned)s->ac_value - (unsigned)s->ac_low) * + (unsigned)s->freq_range) / (((unsigned)s->ac_high - (unsigned)s->ac_low) + 1) & 0xffffu; +} + +static unsigned ac_map_symbol(WavArcContext *s, unsigned prob) +{ + int idx = 255; + + while (prob < s->freqs[idx]) + idx--; + + s->range_high = s->freqs[idx + 1]; + s->range_low = s->freqs[idx]; + + return idx; +} + +static int ac_normalize(AVCodecContext *avctx, WavArcContext *s, GetBitContext *gb) +{ + int range; + + range = (unsigned)s->ac_high - (unsigned)s->ac_low + 1; + s->ac_high = (int16_t)((range * (unsigned)s->range_high) / (unsigned)s->freq_range) + -1 + s->ac_low; + s->ac_low += (int16_t)((range * (unsigned)s->range_low) / (unsigned)s->freq_range); + + for (;;) { + if ((s->ac_high & 0x8000) != (s->ac_low & 0x8000)) { + if ((s->ac_low & 0x4000) == 0 || (s->ac_high & 0x4000) != 0) + return 0; + s->ac_value ^= 0x4000; + s->ac_low &= 0x3fff; + s->ac_high |= 0x4000; + } + + s->ac_low = s->ac_low << 1; + s->ac_high = s->ac_high * 2 + 1; + if (s->ac_high < s->ac_low) { + av_log(avctx, AV_LOG_ERROR, "invalid state\n"); + return AVERROR_INVALIDDATA; + } + + if (get_bits_left(gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, "overread in arithmetic coder\n"); + return AVERROR_INVALIDDATA; + } + + s->ac_value = s->ac_value * 2 + get_bits1(gb); + } +} + +static void ac_init_model(WavArcContext *s) +{ + memset(s->freqs, 0, sizeof(s->freqs)); + + for (int n = 0; n < 256; n++) + s->freqs[n+1] = s->model[n] + s->freqs[n]; +} + +static int ac_read_model(AVCodecContext *avctx, + WavArcContext *s, + GetBitContext *gb) +{ + unsigned start, end; + + memset(s->model, 0, sizeof(s->model)); + + start = get_bits(gb, 8); + end = get_bits(gb, 8); + + for (;;) { + while (start <= end) + s->model[start++] = get_bits(gb, 8); + + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + + start = get_bits(gb, 8); + if (!start) + break; + + end = get_bits(gb, 8); + } + + ac_init_model(s); + + return 0; +} + +static int decode_5elp(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + int ch, finished, fill, correlated, order = 0; + + ch = 0; + finished = 0; + while (!finished) { + int *samples = s->samples[ch]; + int *ac_pred = s->ac_pred; + int *ac_out = s->ac_out; + int k, block_type; + + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + memset(s->ac_out, 0, sizeof(s->ac_out)); + + block_type = get_urice(gb, 1); + av_log(avctx, AV_LOG_DEBUG, "block_type : %d\n", block_type); + + if (block_type >= 0 && block_type <= 7) { + k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); + k = get_urice(gb, k) + 1; + } + + if (block_type <= 2 || block_type == 6 || block_type == 13 || + block_type == 14 || block_type == 15 || block_type == 19) { + order = get_urice(gb, 2); + if ((unsigned)order > FF_ARRAY_ELEMS(s->filter[ch])) + return AVERROR_INVALIDDATA; + for (int o = 0; o < order; o++) + s->filter[ch][o] = get_srice(gb, 2); + } + + if (block_type >= 0 && block_type <= 7) { + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k); + } else { + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = 0; + } + + if (block_type >= 13 && block_type <= 20) { + const int ac_size = get_bits(gb, 12); + const int ac_pos = get_bits_count(gb); + GetBitContext ac_gb = *gb; + int ret; + + skip_bits_long(gb, ac_size); + ret = ac_read_model(avctx, s, &ac_gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "bad arithmetic model\n"); + return ret; + } + + ret = ac_init(avctx, s, &ac_gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "cannot init arithmetic decoder\n"); + return ret; + } + + for (int n = 0; n < s->nb_samples; n++) { + unsigned prob = ac_get_prob(s); + prob = ac_map_symbol(s, prob); + ac_out[n] = prob - 0x80; + if ((ret = ac_normalize(avctx, s, &ac_gb)) < 0) + return ret; + } + + if (get_bits_count(&ac_gb) != ac_pos + ac_size) { + av_log(avctx, AV_LOG_DEBUG, "over/under-read in arithmetic coder: %d\n", + ac_pos + ac_size - get_bits_count(&ac_gb)); + } + } + + switch (block_type) { + case 12: + s->eof = 1; + return AVERROR_EOF; + case 11: + s->nb_samples = get_urice(gb, 8); + if (s->nb_samples > 570) { + s->nb_samples = 570; + return AVERROR_INVALIDDATA; + } + continue; + case 10: + s->shift = get_urice(gb, 2); + continue; + case 9: + if (avctx->sample_fmt == AV_SAMPLE_FMT_U8P) { + fill = (int8_t)get_bits(gb, 8); + fill -= 0x80; + } else { + fill = (int16_t)get_bits(gb, 16); + fill -= 0x8000; + } + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = fill; + finished = 1; + break; + case 8: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = 0; + finished = 1; + break; + case 20: + case 7: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69] * 3 - samples[n + 68] * 3 + samples[n + 67]; + finished = 1; + break; + case 19: + case 6: + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + finished = 1; + break; + case 18: + case 5: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69] * 2 - samples[n + 68]; + finished = 1; + break; + case 17: + case 4: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n]; + finished = 1; + break; + case 16: + case 3: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69]; + finished = 1; + break; + case 15: + case 2: + for (int n = 0; n < 70; n++) { + ac_pred[n] = samples[n]; + samples[n] = 0; + } + + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + + for (int n = 0; n < 70; n++) + samples[n] = ac_pred[n]; + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] += samples[n + 69] * 2 - samples[n + 68]; + + finished = 1; + break; + case 14: + case 1: + for (int n = 0; n < 70; n++) { + ac_pred[n] = samples[n]; + samples[n] = 0; + } + + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + + for (int n = 0; n < 70; n++) + samples[n] = ac_pred[n]; + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] += samples[n + 69]; + + finished = 1; + break; + case 13: + case 0: + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + finished = 1; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (finished == 1 && avctx->ch_layout.nb_channels == 2) { + if (ch == 0) + correlated = get_bits1(gb); + finished = ch != 0; + do_stereo(s, ch, correlated, 70); + ch = 1; + } + } + + if (avctx->ch_layout.nb_channels == 1) { + for (int n = 0; n < 70; n++) + s->samples[0][n] = s->samples[0][s->nb_samples + n]; + } + + return 0; +} + static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { @@ -424,6 +768,9 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, case MKTAG('4','A','L','P'): ret = decode_2slp(avctx, s, gb); break; + case MKTAG('5','E','L','P'): + ret = decode_5elp(avctx, s, gb); + break; default: ret = AVERROR_INVALIDDATA; }