From 0a23e12394843688df13f8ff5121c26424e5eb7a Mon Sep 17 00:00:00 2001
From: Paul Wilkins <[EMAIL REDACTED]>
Date: Tue, 23 Jan 2024 16:58:32 +0000
Subject: [PATCH] Fix divide by zero.
Raised in issue Issue # 3523:
Explicitly check p_rc->rolling_target_bits > 0 for the identified case.
Also:-
When initializing p_rc->rolling_actual_bits and
p_rc->rolling_target_bits force to max(1,x).
In the encoder interface range check target rate > 0.
Bug: aomedia:3523
Change-Id: If7ba7e98af627227498443c2e9a739c65ec8d68b
(cherry picked from commit 77cf417565ad2c527d5c351927f11db3764fd93c)
---
av1/av1_cx_iface.c | 6 ++++++
av1/encoder/pass2_strategy.c | 3 ++-
av1/encoder/ratectrl.c | 8 ++++----
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 1175a32ef6..0ad6f439e4 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -623,6 +623,11 @@ static aom_codec_err_t allocate_and_set_string(const char *src,
ERROR(#memb " out of range [" #lo ".." #hi "]"); \
} while (0)
+#define RANGE_CHECK_LO(p, memb, lo) \
+ do { \
+ if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \
+ } while (0)
+
#define RANGE_CHECK_HI(p, memb, hi) \
do { \
if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
@@ -662,6 +667,7 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
RANGE_CHECK_HI(cfg, g_profile, MAX_PROFILES - 1);
+ RANGE_CHECK_LO(cfg, rc_target_bitrate, 1);
RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
RANGE_CHECK_BOOL(extra_cfg, lossless);
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index d85440df5e..68b10567b4 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -4228,7 +4228,8 @@ void av1_twopass_postencode_update(AV1_COMP *cpi) {
twopass->kf_group_bits = AOMMAX(twopass->kf_group_bits, 0);
// If the rate control is drifting consider adjustment to min or maxq.
- if ((rc_cfg->mode != AOM_Q) && !cpi->rc.is_src_frame_alt_ref) {
+ if ((rc_cfg->mode != AOM_Q) && !cpi->rc.is_src_frame_alt_ref &&
+ (p_rc->rolling_target_bits > 0)) {
int minq_adj_limit;
int maxq_adj_limit;
minq_adj_limit =
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 9062136aad..1f1ff81386 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -404,10 +404,10 @@ void av1_primary_rc_init(const AV1EncoderConfig *oxcf,
p_rc->rate_correction_factors[KF_STD] = 1.0;
p_rc->bits_off_target = p_rc->starting_buffer_level;
- p_rc->rolling_target_bits =
- (int)(oxcf->rc_cfg.target_bandwidth / oxcf->input_cfg.init_framerate);
- p_rc->rolling_actual_bits =
- (int)(oxcf->rc_cfg.target_bandwidth / oxcf->input_cfg.init_framerate);
+ p_rc->rolling_target_bits = AOMMAX(
+ 1, (int)(oxcf->rc_cfg.target_bandwidth / oxcf->input_cfg.init_framerate));
+ p_rc->rolling_actual_bits = AOMMAX(
+ 1, (int)(oxcf->rc_cfg.target_bandwidth / oxcf->input_cfg.init_framerate));
}
void av1_rc_init(const AV1EncoderConfig *oxcf, RATE_CONTROL *rc) {