shithub: libvpx

Download patch

ref: 1f45e7b07ec839dae7a90455e00c3b2d553ea772
parent: 338013712e516d07388651437918e6328ea909f5
author: Jerome Jiang <jianj@google.com>
date: Tue Jun 15 08:54:13 EDT 2021

vp9 rc: add vbr to rtc rate control library

Change-Id: I3d2565572c2b905966d60bcaa6e5e6f057b1bd51

--- a/test/ratectrl_rtc_test.cc
+++ b/test/ratectrl_rtc_test.cc
@@ -32,6 +32,7 @@
         info.bytes_used;
     return is;
   }
+
   int frame_id;
   int spatial_id;
   int temporal_id;
@@ -48,13 +49,26 @@
 // 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
@@ -61,11 +75,6 @@
 // --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 @@
   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 @@
     }
   }
 
+  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 @@
     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 @@
     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 @@
   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
--- a/test/test-data.mk
+++ b/test/test-data.mk
@@ -28,6 +28,8 @@
 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
 
--- 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
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -27,6 +27,9 @@
 // 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
--- a/vp9/ratectrl_rtc.cc
+++ b/vp9/ratectrl_rtc.cc
@@ -38,13 +38,16 @@
   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 @@
   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 @@
   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 @@
   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 {
--- a/vp9/ratectrl_rtc.h
+++ b/vp9/ratectrl_rtc.h
@@ -49,6 +49,10 @@
   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 {