shithub: libvpx

Download patch

ref: 3ec043a795cdf4dfa4cf31a9a0c82cbeef52c866
parent: bb7a2ccc38475ce0e70be134b5bf862000a3fc82
author: angiebird <angiebird@google.com>
date: Mon Aug 3 15:49:43 EDT 2020

Add rq_history to encode_frame_result

Change-Id: Ic2a52dcf5e5a6d57b80d390a2c48ee498e89e7b2

--- a/test/simple_encode_test.cc
+++ b/test/simple_encode_test.cc
@@ -163,6 +163,40 @@
   simple_encode.EndEncode();
 }
 
+TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) {
+  SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+                             target_bitrate_, num_frames_,
+                             in_file_path_str_.c_str());
+  simple_encode.ComputeFirstPassStats();
+  const int num_coding_frames = simple_encode.GetCodingFrameNum();
+  simple_encode.StartEncode();
+  for (int i = 0; i < num_coding_frames; ++i) {
+    EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo();
+    int target_frame_bits = 20000;
+    if (encode_frame_info.frame_type == kFrameTypeKey ||
+        encode_frame_info.frame_type == kFrameTypeAltRef ||
+        encode_frame_info.frame_type == kFrameTypeGolden) {
+      target_frame_bits = 100000;
+    }
+    if (encode_frame_info.frame_type == kFrameTypeOverlay) {
+      target_frame_bits = 2000;
+    }
+
+    EncodeFrameResult encode_frame_result;
+    simple_encode.EncodeFrameWithTargetFrameBits(&encode_frame_result,
+                                                 target_frame_bits);
+    const int recode_count = encode_frame_result.recode_count;
+    // TODO(angiebird): Replace 7 by RATE_CTRL_MAX_RECODE_NUM
+    EXPECT_LE(recode_count, 7);
+    EXPECT_GE(recode_count, 1);
+
+    double diff = fabs((double)encode_frame_result.coding_data_bit_size -
+                       target_frame_bits);
+    EXPECT_LE(diff * 100 / target_frame_bits, 15);
+  }
+  simple_encode.EndEncode();
+}
+
 TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) {
   SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
                              target_bitrate_, num_frames_,
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4204,16 +4204,6 @@
 }
 
 #if CONFIG_RATE_CTRL
-#define RATE_CTRL_MAX_RECODE_NUM 7
-
-typedef struct RATE_QINDEX_HISTORY {
-  int recode_count;
-  int q_index_history[RATE_CTRL_MAX_RECODE_NUM];
-  int rate_history[RATE_CTRL_MAX_RECODE_NUM];
-  int q_index_high;
-  int q_index_low;
-} RATE_QINDEX_HISTORY;
-
 static void init_rq_history(RATE_QINDEX_HISTORY *rq_history) {
   rq_history->recode_count = 0;
   rq_history->q_index_high = 255;
@@ -4330,8 +4320,12 @@
 }
 #endif  // CONFIG_RATE_CTRL
 
-static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
-                                    uint8_t *dest) {
+static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
+#if CONFIG_RATE_CTRL
+                                    ,
+                                    RATE_QINDEX_HISTORY *rq_history
+#endif  // CONFIG_RATE_CTRL
+) {
   const VP9EncoderConfig *const oxcf = &cpi->oxcf;
   VP9_COMMON *const cm = &cpi->common;
   RATE_CONTROL *const rc = &cpi->rc;
@@ -4354,8 +4348,7 @@
       cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index];
   const ENCODE_FRAME_TYPE frame_type = get_encode_frame_type(update_type);
   RATE_QSTEP_MODEL *rq_model = &cpi->rq_model[frame_type];
-  RATE_QINDEX_HISTORY rq_history;
-  init_rq_history(&rq_history);
+  init_rq_history(rq_history);
 #endif  // CONFIG_RATE_CTRL
 
   if (cm->show_existing_frame) {
@@ -4406,8 +4399,7 @@
 
 #if CONFIG_RATE_CTRL
     if (cpi->encode_command.use_external_target_frame_bits) {
-      q = rq_model_predict_q_index(rq_model, &rq_history,
-                                   rc->this_frame_target);
+      q = rq_model_predict_q_index(rq_model, rq_history, rc->this_frame_target);
     }
 #endif  // CONFIG_RATE_CTRL
     // Decide frame size bounds first time through.
@@ -4507,16 +4499,16 @@
     if (cpi->encode_command.use_external_target_frame_bits) {
       const double percent_diff = get_bits_percent_diff(
           rc->this_frame_target, rc->projected_frame_size);
-      update_rq_history(&rq_history, rc->this_frame_target,
+      update_rq_history(rq_history, rc->this_frame_target,
                         rc->projected_frame_size, q);
       loop_count += 1;
 
-      rq_model_update(&rq_history, rc->this_frame_target, rq_model);
+      rq_model_update(rq_history, rc->this_frame_target, rq_model);
 
       // Check if we hit the target bitrate.
       if (percent_diff <= 15 ||
-          rq_history.recode_count >= RATE_CTRL_MAX_RECODE_NUM ||
-          rq_history.q_index_low >= rq_history.q_index_high) {
+          rq_history->recode_count >= RATE_CTRL_MAX_RECODE_NUM ||
+          rq_history->q_index_low >= rq_history->q_index_high) {
         break;
       }
 
@@ -5374,8 +5366,12 @@
     if (!encode_without_recode_loop(cpi, size, dest)) return;
   } else {
 #if !CONFIG_REALTIME_ONLY
+#if CONFIG_RATE_CTRL
+    encode_with_recode_loop(cpi, size, dest, &encode_frame_result->rq_history);
+#else   // CONFIG_RATE_CTRL
     encode_with_recode_loop(cpi, size, dest);
-#endif
+#endif  // CONFIG_RATE_CTRL
+#endif  // !CONFIG_REALTIME_ONLY
   }
 
   // TODO(jingning): When using show existing frame mode, we assume that the
@@ -7561,6 +7557,7 @@
   encode_frame_result->frame_coding_index = -1;
   vp9_zero(encode_frame_result->coded_frame);
   encode_frame_result->coded_frame.allocated = 0;
+  init_rq_history(&encode_frame_result->rq_history);
 #endif  // CONFIG_RATE_CTRL
 }
 
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -1041,6 +1041,17 @@
   int plane_height[3];
   uint8_t *plane_buffer[3];
 } IMAGE_BUFFER;
+
+#define RATE_CTRL_MAX_RECODE_NUM 7
+
+typedef struct RATE_QINDEX_HISTORY {
+  int recode_count;
+  int q_index_history[RATE_CTRL_MAX_RECODE_NUM];
+  int rate_history[RATE_CTRL_MAX_RECODE_NUM];
+  int q_index_high;
+  int q_index_low;
+} RATE_QINDEX_HISTORY;
+
 #endif  // CONFIG_RATE_CTRL
 
 typedef struct ENCODE_FRAME_RESULT {
@@ -1056,6 +1067,7 @@
   const PARTITION_INFO *partition_info;
   const MOTION_VECTOR_INFO *motion_vector_info;
   IMAGE_BUFFER coded_frame;
+  RATE_QINDEX_HISTORY rq_history;
 #endif  // CONFIG_RATE_CTRL
   int quantize_index;
 } ENCODE_FRAME_RESULT;
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -485,6 +485,18 @@
                            frame_height, img_fmt);
 }
 
+static void encode_frame_result_update_rq_history(
+    const RATE_QINDEX_HISTORY *rq_history,
+    EncodeFrameResult *encode_frame_result) {
+  encode_frame_result->recode_count = rq_history->recode_count;
+  for (int i = 0; i < encode_frame_result->recode_count; ++i) {
+    const int q_index = rq_history->q_index_history[i];
+    const int rate = rq_history->rate_history[i];
+    encode_frame_result->q_index_history.push_back(q_index);
+    encode_frame_result->rate_history.push_back(rate);
+  }
+}
+
 static void update_encode_frame_result(
     EncodeFrameResult *encode_frame_result,
     const ENCODE_FRAME_RESULT *encode_frame_info) {
@@ -514,6 +526,8 @@
                             &encode_frame_result->motion_vector_info[0]);
   update_frame_counts(&encode_frame_info->frame_counts,
                       &encode_frame_result->frame_counts);
+  encode_frame_result_update_rq_history(&encode_frame_info->rq_history,
+                                        encode_frame_result);
 }
 
 static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) {
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -256,6 +256,12 @@
   // share the same motion vector information.
   std::vector<MotionVectorInfo> motion_vector_info;
   ImageBuffer coded_frame;
+
+  // recode_count, q_index_history and rate_history are only available when
+  // EncodeFrameWithTargetFrameBits() is used.
+  int recode_count;
+  std::vector<int> q_index_history;
+  std::vector<int> rate_history;
 };
 
 struct GroupOfPicture {