ffmpeg | branch: master | Paul B Mahol <one...@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: _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog To unsubscribe, visit link above, or email ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".