vp9: fix memory alloc for adaptive_rd_thresh_row_mt.
authorJerome Jiang <jianj@google.com>
Mon, 13 Aug 2018 18:01:31 +0000 (11:01 -0700)
committerJerome Jiang <jianj@google.com>
Tue, 14 Aug 2018 17:55:31 +0000 (10:55 -0700)
When the feature is enabled and the memory is not available, allocate
it. There was a case where speed feature changed in the middle of stream
but the number of tiles stayed the same, memory was not re-allocated.

Another case is where speed for base layer is different than that of
higher quality layers (same resolution). Removed the speed constraints
forcing base layer using same speed setting.

Thus the memory for adaptive_rd_thresh_row_mt stayed NULL but the
feature was enabled.

Add an end to end test to cover this case.

Change-Id: I2f1f802ef98a554571b30094d3600b9439228457

test/svc_datarate_test.cc
test/svc_test.cc
test/vp9_end_to_end_test.cc
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_multi_thread.c
vp9/encoder/vp9_multi_thread.h

index 6858b325f571fa5ba00cd53f15929412759fc689..d8b5915115949d83f01707329dd00c90b2100f03 100644 (file)
@@ -532,7 +532,6 @@ TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL1TLScreenContent1) {
   cfg_.rc_target_bitrate = 500;
   ResetModel();
   tune_content_ = 1;
-  base_speed_setting_ = speed_setting_;
   AssignLayerBitrates();
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
   CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
@@ -1337,7 +1336,6 @@ TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2QL1TLScreen) {
   top_sl_height_ = 480;
   ResetModel();
   tune_content_ = 1;
-  base_speed_setting_ = speed_setting_;
   // Set the layer bitrates, for 2 spatial layers, 1 temporal.
   cfg_.rc_target_bitrate = 400;
   cfg_.ss_target_bitrate[0] = 100;
index f7e6db4112ba67f1b3557673507e9d8b0bcc1be1..1bfde4ad43a6d1ca3d85f29f86900e11012d84c7 100644 (file)
@@ -27,7 +27,6 @@ void OnePassCbrSvc::PreEncodeFrameHookSetup(::libvpx_test::VideoSource *video,
     encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
     encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
     encoder->Control(VP9E_SET_AQ_MODE, 3);
-    encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
     encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
     encoder->Control(VP9E_SET_TILE_COLUMNS, get_msb(cfg_.g_threads));
     encoder->Control(VP9E_SET_ROW_MT, 1);
index 90a60c2f3c67e38cce53b7601fa5294dfde43764..2f711bc5b207360685c821bfbfd6d8de9aa4df36 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "test/codec_factory.h"
 #include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
 #include "test/util.h"
 #include "test/y4m_video_source.h"
 #include "test/yuv_video_source.h"
@@ -74,6 +75,43 @@ int is_extension_y4m(const char *filename) {
   }
 }
 
+class EndToEndTestAdaptiveRDThresh
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<int, int> {
+ protected:
+  EndToEndTestAdaptiveRDThresh()
+      : EncoderTest(GET_PARAM(0)), cpu_used_start_(GET_PARAM(1)),
+        cpu_used_end_(GET_PARAM(2)) {}
+
+  virtual ~EndToEndTestAdaptiveRDThresh() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(::libvpx_test::kRealTime);
+    cfg_.g_lag_in_frames = 0;
+    cfg_.rc_end_usage = VPX_CBR;
+    cfg_.rc_buf_sz = 1000;
+    cfg_.rc_buf_initial_sz = 500;
+    cfg_.rc_buf_optimal_sz = 600;
+    dec_cfg_.threads = 4;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_start_);
+      encoder->Control(VP9E_SET_ROW_MT, 1);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
+    }
+    if (video->frame() == 100)
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_end_);
+  }
+
+ private:
+  int cpu_used_start_;
+  int cpu_used_end_;
+};
+
 class EndToEndTestLarge
     : public ::libvpx_test::EncoderTest,
       public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode,
@@ -205,8 +243,21 @@ TEST_P(EndToEndTestLarge, EndtoEndPSNRDenoiserAQTest) {
   EXPECT_GT(psnr, GetPsnrThreshold());
 }
 
+TEST_P(EndToEndTestAdaptiveRDThresh, EndtoEndAdaptiveRDThreshRowMT) {
+  cfg_.rc_target_bitrate = kBitrate;
+  cfg_.g_error_resilient = 0;
+  cfg_.g_threads = 2;
+  ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+                                       0, 400);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
 VP9_INSTANTIATE_TEST_CASE(EndToEndTestLarge,
                           ::testing::ValuesIn(kEncodingModeVectors),
                           ::testing::ValuesIn(kTestVectors),
                           ::testing::ValuesIn(kCpuUsedVectors));
+
+VP9_INSTANTIATE_TEST_CASE(EndToEndTestAdaptiveRDThresh,
+                          ::testing::Values(5, 6, 7), ::testing::Values(8, 9));
 }  // namespace
index cb5cb19017241ff79dffe2b9686206143f1673ed..1b854eacbd4a18d068f7847a0d53aee8a199c71f 100644 (file)
@@ -42,6 +42,7 @@
 #include "vp9/encoder/vp9_encodemv.h"
 #include "vp9/encoder/vp9_ethread.h"
 #include "vp9/encoder/vp9_extend.h"
+#include "vp9/encoder/vp9_multi_thread.h"
 #include "vp9/encoder/vp9_pickmode.h"
 #include "vp9/encoder/vp9_rd.h"
 #include "vp9/encoder/vp9_rdopt.h"
@@ -5360,6 +5361,9 @@ void vp9_init_tile_data(VP9_COMP *cpi) {
     for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
       TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
       TileInfo *tile_info = &this_tile->tile_info;
+      if (cpi->sf.adaptive_rd_thresh_row_mt &&
+          this_tile->row_base_thresh_freq_fact == NULL)
+        vp9_row_mt_alloc_rd_thresh(cpi, this_tile);
       vp9_tile_init(tile_info, cm, tile_row, tile_col);
 
       cpi->tile_tok[tile_row][tile_col] = pre_tok + tile_tok;
index 381edca996c52c7d7259a93e50991f43e325c4d0..c8a80563a55e885e45d14bc7484adb35a1f39fab 100644 (file)
@@ -50,6 +50,20 @@ void *vp9_enc_grp_get_next_job(MultiThreadHandle *multi_thread_ctxt,
   return job_info;
 }
 
+void vp9_row_mt_alloc_rd_thresh(VP9_COMP *const cpi,
+                                TileDataEnc *const this_tile) {
+  VP9_COMMON *const cm = &cpi->common;
+  const int sb_rows =
+      (mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2) + 1;
+  int i;
+
+  this_tile->row_base_thresh_freq_fact =
+      (int *)vpx_calloc(sb_rows * BLOCK_SIZES * MAX_MODES,
+                        sizeof(*(this_tile->row_base_thresh_freq_fact)));
+  for (i = 0; i < sb_rows * BLOCK_SIZES * MAX_MODES; i++)
+    this_tile->row_base_thresh_freq_fact[i] = RD_THRESH_INIT_FACT;
+}
+
 void vp9_row_mt_mem_alloc(VP9_COMP *cpi) {
   struct VP9Common *cm = &cpi->common;
   MultiThreadHandle *multi_thread_ctxt = &cpi->multi_thread_ctxt;
@@ -83,14 +97,11 @@ void vp9_row_mt_mem_alloc(VP9_COMP *cpi) {
     TileDataEnc *this_tile = &cpi->tile_data[tile_col];
     vp9_row_mt_sync_mem_alloc(&this_tile->row_mt_sync, cm, jobs_per_tile_col);
     if (cpi->sf.adaptive_rd_thresh_row_mt) {
-      const int sb_rows =
-          (mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2) + 1;
-      int i;
-      this_tile->row_base_thresh_freq_fact =
-          (int *)vpx_calloc(sb_rows * BLOCK_SIZES * MAX_MODES,
-                            sizeof(*(this_tile->row_base_thresh_freq_fact)));
-      for (i = 0; i < sb_rows * BLOCK_SIZES * MAX_MODES; i++)
-        this_tile->row_base_thresh_freq_fact[i] = RD_THRESH_INIT_FACT;
+      if (this_tile->row_base_thresh_freq_fact != NULL) {
+        vpx_free(this_tile->row_base_thresh_freq_fact);
+        this_tile->row_base_thresh_freq_fact = NULL;
+      }
+      vp9_row_mt_alloc_rd_thresh(cpi, this_tile);
     }
   }
 
index bfc0c0ae4f693fda2823a3b3aaf5ee7c3d35938b..f59ad183344fe57f33a8bf1076095911158fccac 100644 (file)
@@ -29,6 +29,9 @@ void vp9_multi_thread_tile_init(VP9_COMP *cpi);
 
 void vp9_row_mt_mem_alloc(VP9_COMP *cpi);
 
+void vp9_row_mt_alloc_rd_thresh(VP9_COMP *const cpi,
+                                TileDataEnc *const this_tile);
+
 void vp9_row_mt_mem_dealloc(VP9_COMP *cpi);
 
 int vp9_get_tiles_proc_status(MultiThreadHandle *multi_thread_ctxt,