]> granicus.if.org Git - libvpx/commitdiff
Add rq_history to encode_frame_result
authorangiebird <angiebird@google.com>
Tue, 4 Aug 2020 02:49:43 +0000 (19:49 -0700)
committerangiebird <angiebird@google.com>
Fri, 7 Aug 2020 23:48:08 +0000 (16:48 -0700)
Change-Id: Ic2a52dcf5e5a6d57b80d390a2c48ee498e89e7b2

test/simple_encode_test.cc
vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_encoder.h
vp9/simple_encode.cc
vp9/simple_encode.h

index 1790b56ac31836976d386a33d8de682172d50706..c5674466d7088d75ea5f9a2cc9aa54c593f98f3c 100644 (file)
@@ -163,6 +163,40 @@ TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) {
   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_,
index 169cd190eb511ff8e7333ba71182d2b7569907e0..4820b2529f0ac598c6b9ea42a58ad54746abf1f9 100644 (file)
@@ -4204,16 +4204,6 @@ static int get_qstep_adj(int rate_excess, int rate_limit) {
 }
 
 #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 @@ static void rq_model_update(const RATE_QINDEX_HISTORY *rq_history,
 }
 #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 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
       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 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
 
 #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 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
     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 @@ static void encode_frame_to_data_rate(
     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 @@ void vp9_init_encode_frame_result(ENCODE_FRAME_RESULT *encode_frame_result) {
   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
 }
 
index 3758ea3aea9397696ceaac8a039bb24529cdd9f8..0d537ca972c8a2562efb07cad9ede80762d9ab8b 100644 (file)
@@ -1041,6 +1041,17 @@ typedef struct IMAGE_BUFFER {
   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 @@ typedef struct ENCODE_FRAME_RESULT {
   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;
index 4ee0bd2e8461a9e185f703d0a4699c6a5289c1d1..da9c4e10aaec18349a38ca1448e24fc522476a4f 100644 (file)
@@ -485,6 +485,18 @@ static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result,
                            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 @@ static void update_encode_frame_result(
                             &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) {
index 6c66aafda425ea589d6f230b170957113a16094c..702895e05cb95f4cbfa9f624deff63db67a7dc1a 100644 (file)
@@ -256,6 +256,12 @@ struct EncodeFrameResult {
   // 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 {