From 3e833ddaef3fa2909cd0917d7724f75746d0c103 Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Tue, 7 Jul 2020 17:44:13 -0700 Subject: [PATCH] Cap target bitrate to raw rate internally BUG=webm:1685 Change-Id: Ida72fe854fadb19c3745724e74b67d88087eb83c (cherry picked from commit baefbe85d09f7b884923437d9413b3e6ba4a1c7d) --- test/realtime_test.cc | 7 +------ vp8/encoder/bitstream.c | 2 +- vp8/encoder/onyx_if.c | 7 ++++++- vp9/encoder/vp9_pickmode.c | 2 +- vp9/encoder/vp9_ratectrl.c | 6 ++++-- vp9/vp9_cx_iface.c | 11 +++++++++-- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/test/realtime_test.cc b/test/realtime_test.cc index 25a933b..63a5347 100644 --- a/test/realtime_test.cc +++ b/test/realtime_test.cc @@ -63,15 +63,10 @@ TEST_P(RealtimeTest, RealtimeFirstPassProducesFrames) { EXPECT_EQ(kFramesToEncode, frame_packets_); } -// TODO(https://crbug.com/webm/1685): the following passes -fsanitize=undefined -// with bitrate set to 140000000 for vp8 and 128000 for vp9. There are -// additional failures with lower bitrates using -fsanitize=integer. -TEST_P(RealtimeTest, DISABLED_IntegerOverflow) { +TEST_P(RealtimeTest, IntegerOverflow) { ::libvpx_test::RandomVideoSource video; video.SetSize(800, 480); video.set_limit(20); - // TODO(https://crbug.com/webm/1685): this should be silently capped - // internally to the raw yuv rate or below. cfg_.rc_target_bitrate = 140000000; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); } diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 3daa4e2..80cbb88 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -222,7 +222,7 @@ void vp8_pack_tokens(vp8_writer *w, const TOKENEXTRA *p, int xcount) { validate_buffer(w->buffer + w->pos, 1, w->buffer_end, w->error); - w->buffer[w->pos++] = (lowvalue >> (24 - offset)); + w->buffer[w->pos++] = (lowvalue >> (24 - offset)) & 0xff; lowvalue <<= offset; shift = count; lowvalue &= 0xffffff; diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index dccc6eb..aeed719 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -1430,6 +1430,7 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) { VP8_COMMON *cm = &cpi->common; int last_w, last_h; unsigned int prev_number_of_layers; + unsigned int raw_target_rate; if (!cpi) return; @@ -1570,6 +1571,10 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) { cpi->oxcf.maximum_buffer_size_in_ms = 240000; } + raw_target_rate = (unsigned int)((int64_t)cpi->oxcf.Width * cpi->oxcf.Height * + 8 * 3 * cpi->framerate / 1000); + if (cpi->oxcf.target_bandwidth > raw_target_rate) + cpi->oxcf.target_bandwidth = raw_target_rate; /* Convert target bandwidth from Kbit/s to Bit/s */ cpi->oxcf.target_bandwidth *= 1000; @@ -3615,7 +3620,7 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, if (cpi->this_key_frame_forced) { if (cpi->active_best_quality > cpi->avg_frame_qindex * 7 / 8) { cpi->active_best_quality = cpi->avg_frame_qindex * 7 / 8; - } else if (cpi->active_best_qualityavg_frame_qindex>> 2) { + } else if (cpi->active_best_quality < (cpi->avg_frame_qindex >> 2)) { cpi->active_best_quality = cpi->avg_frame_qindex >> 2; } } diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index 23c943c..695fd48 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -1127,7 +1127,7 @@ static INLINE void update_thresh_freq_fact_row_mt( } static INLINE void update_thresh_freq_fact( - VP9_COMP *cpi, TileDataEnc *tile_data, int source_variance, + VP9_COMP *cpi, TileDataEnc *tile_data, unsigned int source_variance, BLOCK_SIZE bsize, MV_REFERENCE_FRAME ref_frame, THR_MODES best_mode_idx, PREDICTION_MODE mode) { THR_MODES thr_mode_idx = mode_idx[ref_frame][mode_offset(mode)]; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 2d03bad..e9b5a23 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1695,8 +1695,10 @@ void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi, int frame_target, } else { // For very small rate targets where the fractional adjustment // may be tiny make sure there is at least a minimum range. - const int tol_low = (cpi->sf.recode_tolerance_low * frame_target) / 100; - const int tol_high = (cpi->sf.recode_tolerance_high * frame_target) / 100; + const int tol_low = + (int)(((int64_t)cpi->sf.recode_tolerance_low * frame_target) / 100); + const int tol_high = + (int)(((int64_t)cpi->sf.recode_tolerance_high * frame_target) / 100); *frame_under_shoot_limit = VPXMAX(frame_target - tol_low - 100, 0); *frame_over_shoot_limit = VPXMIN(frame_target + tol_high + 100, cpi->rc.max_frame_bandwidth); diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 15aa7e6..9074e1b 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -470,10 +470,11 @@ static vpx_rational64_t get_g_timebase_in_ts(vpx_rational_t g_timebase) { } static vpx_codec_err_t set_encoder_config( - VP9EncoderConfig *oxcf, const vpx_codec_enc_cfg_t *cfg, + VP9EncoderConfig *oxcf, vpx_codec_enc_cfg_t *cfg, const struct vp9_extracfg *extra_cfg) { const int is_vbr = cfg->rc_end_usage == VPX_VBR; int sl, tl; + unsigned int raw_target_rate; oxcf->profile = cfg->g_profile; oxcf->max_threads = (int)cfg->g_threads; oxcf->width = cfg->g_w; @@ -500,8 +501,14 @@ static vpx_codec_err_t set_encoder_config( cfg->g_pass == VPX_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames; oxcf->rc_mode = cfg->rc_end_usage; + raw_target_rate = + (unsigned int)((int64_t)oxcf->width * oxcf->height * oxcf->bit_depth * 3 * + oxcf->init_framerate / 1000); + // Cap target bitrate to raw rate + cfg->rc_target_bitrate = VPXMIN(raw_target_rate, cfg->rc_target_bitrate); + // Convert target bandwidth from Kbit/s to Bit/s - oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate; + oxcf->target_bandwidth = 1000 * (int64_t)cfg->rc_target_bitrate; oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct; oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct; oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct; -- 2.7.4