[FFmpeg-cvslog] avcodec/wavarc: fix bugs in arithmetic coding mode
Paul B Mahol
git at videolan.org
Sat Sep 2 22:15:31 EEST 2023
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sat Sep 2 15:46:24 2023 +0200| [9c2206a13bb19591ff2fd80bbbe0c35700bf89b2] | committer: Paul B Mahol
avcodec/wavarc: fix bugs in arithmetic coding mode
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=9c2206a13bb19591ff2fd80bbbe0c35700bf89b2
---
libavcodec/wavarc.c | 74 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 48 insertions(+), 26 deletions(-)
diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c
index 4bdd548d5f..b954e8800c 100644
--- a/libavcodec/wavarc.c
+++ b/libavcodec/wavarc.c
@@ -412,13 +412,13 @@ static int ac_init(AVCodecContext *avctx,
return 0;
}
-static unsigned ac_get_prob(WavArcContext *s)
+static uint16_t 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;
+ return ((s->freq_range - 1) + (s->ac_value - s->ac_low) * s->freq_range) /
+ ((s->ac_high - s->ac_low) + 1U);
}
-static unsigned ac_map_symbol(WavArcContext *s, unsigned prob)
+static uint8_t ac_map_symbol(WavArcContext *s, uint16_t prob)
{
int idx = 255;
@@ -435,33 +435,43 @@ static int ac_normalize(AVCodecContext *avctx, WavArcContext *s, GetBitContext *
{
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);
+ if (s->ac_high < s->ac_low)
+ goto fail;
+
+ range = (s->ac_high - s->ac_low) + 1;
+ s->ac_high = (range * s->range_high) / s->freq_range + s->ac_low - 1;
+ s->ac_low += (range * s->range_low) / s->freq_range;
+
+ if (s->ac_high < s->ac_low)
+ goto fail;
for (;;) {
if ((s->ac_high & 0x8000) != (s->ac_low & 0x8000)) {
- if ((s->ac_low & 0x4000) == 0 || (s->ac_high & 0x4000) != 0)
+ 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;
- }
+ s->ac_low = s->ac_low * 2;
+ s->ac_high = s->ac_high * 2 | 1;
+ if (s->ac_high < s->ac_low)
+ goto fail;
if (get_bits_left(gb) <= 0) {
av_log(avctx, AV_LOG_ERROR, "overread in arithmetic coder\n");
- return AVERROR_INVALIDDATA;
+ goto fail;
}
s->ac_value = s->ac_value * 2 + get_bits1(gb);
+ if (s->ac_low > s->ac_value || s->ac_high < s->ac_value)
+ goto fail;
}
+
+fail:
+ av_log(avctx, AV_LOG_ERROR, "invalid state\n");
+ return AVERROR_INVALIDDATA;
}
static void ac_init_model(WavArcContext *s)
@@ -484,11 +494,11 @@ static int ac_read_model(AVCodecContext *avctx,
end = get_bits(gb, 8);
for (;;) {
- while (start <= end)
+ while (start <= end) {
+ if (get_bits_left(gb) < 8)
+ return AVERROR_INVALIDDATA;
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;
@@ -568,9 +578,9 @@ static int decode_5elp(AVCodecContext *avctx,
}
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;
+ uint16_t prob = ac_get_prob(s);
+ int ac = ac_map_symbol(s, prob);
+ ac_out[n] = ac - 0x80;
if ((ret = ac_normalize(avctx, s, &ac_gb)) < 0)
return ret;
}
@@ -620,11 +630,16 @@ static int decode_5elp(AVCodecContext *avctx,
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];
+ 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 < 70; n++) {
+ ac_pred[n] = samples[n];
+ samples[n] = 0;
+ }
+
for (int n = 0; n < s->nb_samples; n++) {
int sum = 15;
@@ -633,24 +648,31 @@ static int decode_5elp(AVCodecContext *avctx,
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] += ac_out[n] + samples[n + 69] * 3 - samples[n + 68] * 3 + samples[n + 67];
+
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];
+ 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];
+ 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];
+ samples[n + 70] += ac_out[n] + samples[n + 69];
finished = 1;
break;
case 15:
More information about the ffmpeg-cvslog
mailing list