From: Jerome Jiang Date: Tue, 15 Jun 2021 19:54:13 +0000 (-0700) Subject: vp9 rc: add vbr to rtc rate control library X-Git-Tag: v1.11.0-rc1~23^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1f45e7b07ec839dae7a90455e00c3b2d553ea772;p=platform%2Fupstream%2Flibvpx.git vp9 rc: add vbr to rtc rate control library Change-Id: I3d2565572c2b905966d60bcaa6e5e6f057b1bd51 --- diff --git a/test/ratectrl_rtc_test.cc b/test/ratectrl_rtc_test.cc index 58bfac3..e9a9f15 100644 --- a/test/ratectrl_rtc_test.cc +++ b/test/ratectrl_rtc_test.cc @@ -32,6 +32,7 @@ struct FrameInfo { info.bytes_used; return is; } + int frame_id; int spatial_id; int temporal_id; @@ -48,24 +49,32 @@ struct FrameInfo { // This test runs the rate control interface and compare against ground truth // generated by encoders. // Settings for the encoder: -// For 1 layer: +// For 1 layer CBR: +// - AQ_Mode 0 +// - Disable golden refresh +// - Bitrate x 2 at frame/superframe 200 +// - Bitrate / 4 at frame/superframe 400 +// examples/vpx_temporal_svc_encoder gipsrec_motion1.1280_720.yuv out vp9 +// 1280 720 1 30 7 0 0 1 0 1000 // +// For 1 layer VBR: +// - Set rc_end_usage to VPX_VBR +// - AQ Mode 0 +// - Disable vp9_compute_frame_low_motion in vp9_encoder.c // examples/vpx_temporal_svc_encoder gipsrec_motion1.1280_720.yuv out vp9 // 1280 720 1 30 7 0 0 1 0 1000 // // For SVC (3 temporal layers, 3 spatial layers): -// +// - AQ_Mode 0 +// - Disable golden refresh +// - Bitrate x 2 at frame/superframe 200 +// - Bitrate / 4 at frame/superframe 400 // examples/vp9_spatial_svc_encoder -f 10000 -w 1280 -h 720 -t 1/30 -sl 3 // -k 10000 -bl 100,140,200,250,350,500,450,630,900 -b 1600 --rc-end-usage=1 // --lag-in-frames=0 --passes=1 --speed=7 --threads=1 // --temporal-layering-mode=3 -aq 1 -rcstat 1 // gipsrec_motion1.1280_720.yuv -o out.webm // -// - AQ_Mode 0 -// - Disable golden refresh -// - Bitrate x 2 at frame/superframe 200 -// - Bitrate / 4 at frame/superframe 400 -// // The generated file includes: // frame number, spatial layer ID, temporal layer ID, base QP, target // bandwidth, buffer level, loopfilter level, encoded frame size @@ -77,8 +86,8 @@ class RcInterfaceTest : public ::testing::Test { virtual ~RcInterfaceTest() {} protected: - void RunOneLayer() { - SetConfigOneLayer(); + void RunOneLayerCBR() { + SetConfigOneLayerCBR(); rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_); FrameInfo frame_info; libvpx::VP9FrameParamsQpRTC frame_params; @@ -144,8 +153,58 @@ class RcInterfaceTest : public ::testing::Test { } } + void RunOneLayerVBR() { + SetConfigOneLayerVBR(); + rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_); + FrameInfo frame_info; + libvpx::VP9FrameParamsQpRTC frame_params; + frame_params.frame_type = KEY_FRAME; + frame_params.spatial_layer_id = 0; + frame_params.temporal_layer_id = 0; + std::ifstream one_layer_file; + one_layer_file.open(libvpx_test::GetDataPath() + + "/rc_interface_test_one_layer_vbr"); + ASSERT_TRUE(one_layer_file.good()); + for (size_t i = 0; i < kNumFrame; i++) { + one_layer_file >> frame_info; + if (frame_info.frame_id > 0) frame_params.frame_type = INTER_FRAME; + ASSERT_EQ(frame_info.spatial_id, 0); + ASSERT_EQ(frame_info.temporal_id, 0); + rc_api_->ComputeQP(frame_params); + ASSERT_EQ(rc_api_->GetQP(), frame_info.base_q); + ASSERT_EQ(rc_api_->GetLoopfilterLevel(), frame_info.filter_level_); + rc_api_->PostEncodeUpdate(frame_info.bytes_used); + } + } + + void RunOneLayerVBRPeriodicKey() { + SetConfigOneLayerVBRPeriodicKey(); + rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_); + FrameInfo frame_info; + libvpx::VP9FrameParamsQpRTC frame_params; + frame_params.frame_type = KEY_FRAME; + frame_params.spatial_layer_id = 0; + frame_params.temporal_layer_id = 0; + std::ifstream one_layer_file; + one_layer_file.open(libvpx_test::GetDataPath() + + "/rc_interface_test_one_layer_vbr_periodic_key"); + ASSERT_TRUE(one_layer_file.good()); + for (size_t i = 0; i < kNumFrame; i++) { + one_layer_file >> frame_info; + if (frame_info.frame_id > 0) frame_params.frame_type = INTER_FRAME; + if (frame_info.frame_id % rc_cfg_.key_freq == 0) + frame_params.frame_type = KEY_FRAME; + ASSERT_EQ(frame_info.spatial_id, 0); + ASSERT_EQ(frame_info.temporal_id, 0); + rc_api_->ComputeQP(frame_params); + ASSERT_EQ(rc_api_->GetQP(), frame_info.base_q); + ASSERT_EQ(rc_api_->GetLoopfilterLevel(), frame_info.filter_level_); + rc_api_->PostEncodeUpdate(frame_info.bytes_used); + } + } + private: - void SetConfigOneLayer() { + void SetConfig() { rc_cfg_.width = 1280; rc_cfg_.height = 720; rc_cfg_.max_quantizer = 52; @@ -167,6 +226,24 @@ class RcInterfaceTest : public ::testing::Test { rc_cfg_.min_quantizers[0] = 2; } + void SetConfigOneLayerCBR() { + SetConfig(); + rc_cfg_.rc_mode = VPX_CBR; + rc_cfg_.key_freq = 3000; + } + + void SetConfigOneLayerVBR() { + SetConfig(); + rc_cfg_.rc_mode = VPX_VBR; + rc_cfg_.key_freq = 3000; + } + + void SetConfigOneLayerVBRPeriodicKey() { + SetConfig(); + rc_cfg_.rc_mode = VPX_VBR; + rc_cfg_.key_freq = 300; + } + void SetConfigSVC() { rc_cfg_.width = 1280; rc_cfg_.height = 720; @@ -182,6 +259,7 @@ class RcInterfaceTest : public ::testing::Test { rc_cfg_.framerate = 30.0; rc_cfg_.ss_number_layers = 3; rc_cfg_.ts_number_layers = 3; + rc_cfg_.rc_mode = VPX_CBR; rc_cfg_.scaling_factor_num[0] = 1; rc_cfg_.scaling_factor_den[0] = 4; @@ -217,7 +295,11 @@ class RcInterfaceTest : public ::testing::Test { libvpx::VP9RateControlRtcConfig rc_cfg_; }; -TEST_F(RcInterfaceTest, OneLayer) { RunOneLayer(); } +TEST_F(RcInterfaceTest, OneLayerCBR) { RunOneLayerCBR(); } + +TEST_F(RcInterfaceTest, OneLayerVBR) { RunOneLayerVBR(); } + +TEST_F(RcInterfaceTest, OneLayerVBRPeriodicKey) { RunOneLayerVBRPeriodicKey(); } TEST_F(RcInterfaceTest, SVC) { RunSVC(); } } // namespace diff --git a/test/test-data.mk b/test/test-data.mk index 744901b..379fc6e 100644 --- a/test/test-data.mk +++ b/test/test-data.mk @@ -28,6 +28,8 @@ LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rc_interface_test_one_layer +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rc_interface_test_one_layer_vbr +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rc_interface_test_one_layer_vbr_periodic_key LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rc_interface_test_svc LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += bus_352x288_420_f20_b8.yuv diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 3775d22..dbbd458 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -39,9 +39,6 @@ #define MAX_MB_RATE 250 #define MAXRATE_1080P 4000000 -#define DEFAULT_KF_BOOST 2000 -#define DEFAULT_GF_BOOST 2000 - #define LIMIT_QRANGE_FOR_ALTREF_AND_KEY 1 #define MIN_BPB_FACTOR 0.005 diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 8ef10c9..bdddd2d 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -27,6 +27,9 @@ extern "C" { // Bits Per MB at different Q (Multiplied by 512) #define BPER_MB_NORMBITS 9 +#define DEFAULT_KF_BOOST 2000 +#define DEFAULT_GF_BOOST 2000 + #define MIN_GF_INTERVAL 4 #define MAX_GF_INTERVAL 16 #define FIXED_GF_INTERVAL 8 // Used in some testing modes only diff --git a/vp9/ratectrl_rtc.cc b/vp9/ratectrl_rtc.cc index 8f77fc8..8455ca9 100644 --- a/vp9/ratectrl_rtc.cc +++ b/vp9/ratectrl_rtc.cc @@ -38,13 +38,16 @@ void VP9RateControlRTC::InitRateControl(const VP9RateControlRtcConfig &rc_cfg) { cm->profile = PROFILE_0; cm->bit_depth = VPX_BITS_8; cm->show_frame = 1; - oxcf->rc_mode = VPX_CBR; oxcf->profile = cm->profile; oxcf->bit_depth = cm->bit_depth; + oxcf->rc_mode = rc_cfg.rc_mode; oxcf->pass = 0; oxcf->aq_mode = NO_AQ; oxcf->content = VP9E_CONTENT_DEFAULT; oxcf->drop_frames_water_mark = 0; + cm->current_video_frame = 0; + oxcf->key_freq = rc_cfg.key_freq; + rc->kf_boost = DEFAULT_KF_BOOST; UpdateRateControl(rc_cfg); @@ -57,8 +60,8 @@ void VP9RateControlRTC::InitRateControl(const VP9RateControlRtcConfig &rc_cfg) { rc->rc_2_frame = 0; vp9_rc_init_minq_luts(); vp9_rc_init(oxcf, 0, rc); + rc->frames_to_key = oxcf->key_freq; cpi_->sf.use_nonrd_pick_mode = 1; - cm->current_video_frame = 0; } void VP9RateControlRTC::UpdateRateControl( @@ -75,6 +78,7 @@ void VP9RateControlRTC::UpdateRateControl( oxcf->best_allowed_q = vp9_quantizer_to_qindex(rc_cfg.min_quantizer); rc->worst_quality = oxcf->worst_allowed_q; rc->best_quality = oxcf->best_allowed_q; + oxcf->init_framerate = rc_cfg.framerate; oxcf->target_bandwidth = 1000 * rc_cfg.target_bandwidth; oxcf->starting_buffer_level_ms = rc_cfg.buf_initial_sz; oxcf->optimal_buffer_level_ms = rc_cfg.buf_optimal_sz; @@ -140,11 +144,24 @@ void VP9RateControlRTC::ComputeQP(const VP9FrameParamsQpRTC &frame_params) { cpi_->sf.use_nonrd_pick_mode = 1; if (cpi_->svc.number_spatial_layers == 1 && cpi_->svc.number_temporal_layers == 1) { - int target; - if (frame_is_intra_only(cm)) - target = vp9_calc_iframe_target_size_one_pass_cbr(cpi_); - else - target = vp9_calc_pframe_target_size_one_pass_cbr(cpi_); + int target = 0; + if (cpi_->oxcf.rc_mode == VPX_CBR) { + if (frame_is_intra_only(cm)) + target = vp9_calc_iframe_target_size_one_pass_cbr(cpi_); + else + target = vp9_calc_pframe_target_size_one_pass_cbr(cpi_); + } else if (cpi_->oxcf.rc_mode == VPX_VBR) { + if (cm->frame_type == KEY_FRAME) { + cpi_->rc.this_key_frame_forced = + cm->current_video_frame != 0 && cpi_->rc.frames_to_key == 0; + cpi_->rc.frames_to_key = cpi_->oxcf.key_freq; + } + vp9_set_gf_update_one_pass_vbr(cpi_); + if (frame_is_intra_only(cm)) + target = vp9_calc_iframe_target_size_one_pass_vbr(cpi_); + else + target = vp9_calc_pframe_target_size_one_pass_vbr(cpi_); + } vp9_rc_set_frame_target(cpi_, target); vp9_update_buffer_level_preencode(cpi_); } else { diff --git a/vp9/ratectrl_rtc.h b/vp9/ratectrl_rtc.h index 72ea40f..a1f2767 100644 --- a/vp9/ratectrl_rtc.h +++ b/vp9/ratectrl_rtc.h @@ -49,6 +49,10 @@ struct VP9RateControlRtcConfig { int scaling_factor_den[VPX_SS_MAX_LAYERS]; int layer_target_bitrate[VPX_MAX_LAYERS]; int ts_rate_decimator[VPX_TS_MAX_LAYERS]; + // vbr, cbr + enum vpx_rc_mode rc_mode; + // key frame frequency + int key_freq; }; struct VP9FrameParamsQpRTC {