shithub: libvpx

Download patch

ref: 5c8431b9e4e0534f25031cf745b5d71b9492ee1e
parent: fdf04093ecb87f9342aa3a17b7efaaf7cbb1808d
author: angiebird <angiebird@google.com>
date: Tue May 26 08:00:36 EDT 2020

Make SetExternalGroupOfPicture support no arf mode

Rename external_arf_indexes by gop_map

Use kGopMapFlagStart to indicate the start of a gop in the gop_map.
Use kGopMapFlagUseAltRef to indicate whether to use altref in the
gop_map.

Change-Id: I743e3199a24b9ae1abd5acd290da1a1f8660e6ac

--- a/test/simple_encode_test.cc
+++ b/test/simple_encode_test.cc
@@ -291,35 +291,39 @@
 // Get QPs and arf locations from the first encode.
 // Set external arfs and QPs for the second encode.
 // Expect to get matched results.
-TEST(SimpleEncode, EncodeConsistencyTestUseExternalArfs) {
+TEST(SimpleEncode, EncodeConsistencySetExternalGroupOfPicture) {
   std::vector<int> quantize_index_list;
   std::vector<uint64_t> ref_sse_list;
   std::vector<double> ref_psnr_list;
   std::vector<size_t> ref_bit_size_list;
-  std::vector<int> external_arf_indexes(num_frames, 0);
+  std::vector<int> gop_map(num_frames, 0);
   {
     // The first encode.
     SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
                                target_bitrate, num_frames, infile_path);
     simple_encode.ComputeFirstPassStats();
-    const int num_coding_frames = simple_encode.GetCodingFrameNum();
     simple_encode.StartEncode();
-    for (int i = 0; i < num_coding_frames; ++i) {
-      EncodeFrameResult encode_frame_result;
-      simple_encode.EncodeFrame(&encode_frame_result);
-      quantize_index_list.push_back(encode_frame_result.quantize_index);
-      ref_sse_list.push_back(encode_frame_result.sse);
-      ref_psnr_list.push_back(encode_frame_result.psnr);
-      ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
-      if (encode_frame_result.frame_type == kFrameTypeKey) {
-        external_arf_indexes[encode_frame_result.show_idx] = 0;
-      } else if (encode_frame_result.frame_type == kFrameTypeAltRef) {
-        external_arf_indexes[encode_frame_result.show_idx] = 1;
-      } else {
-        // This has to be |= because we can't let overlay overwrites the
-        // arf type for the same frame.
-        external_arf_indexes[encode_frame_result.show_idx] |= 0;
+
+    int coded_show_frame_count = 0;
+    while (coded_show_frame_count < num_frames) {
+      const GroupOfPicture group_of_picture =
+          simple_encode.ObserveGroupOfPicture();
+      gop_map[coded_show_frame_count] |= kGopMapFlagStart;
+      if (group_of_picture.use_alt_ref) {
+        gop_map[coded_show_frame_count] |= kGopMapFlagUseAltRef;
       }
+      const std::vector<EncodeFrameInfo> &encode_frame_list =
+          group_of_picture.encode_frame_list;
+      for (size_t group_index = 0; group_index < encode_frame_list.size();
+           ++group_index) {
+        EncodeFrameResult encode_frame_result;
+        simple_encode.EncodeFrame(&encode_frame_result);
+        quantize_index_list.push_back(encode_frame_result.quantize_index);
+        ref_sse_list.push_back(encode_frame_result.sse);
+        ref_psnr_list.push_back(encode_frame_result.psnr);
+        ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
+      }
+      coded_show_frame_count += group_of_picture.show_frame_count;
     }
     simple_encode.EndEncode();
   }
@@ -329,7 +333,7 @@
     SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
                                target_bitrate, num_frames, infile_path);
     simple_encode.ComputeFirstPassStats();
-    simple_encode.SetExternalGroupOfPicture(external_arf_indexes);
+    simple_encode.SetExternalGroupOfPicture(gop_map);
     const int num_coding_frames = simple_encode.GetCodingFrameNum();
     EXPECT_EQ(static_cast<size_t>(num_coding_frames),
               quantize_index_list.size());
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -612,6 +612,9 @@
   group_of_picture->show_frame_count = coding_frame_count - use_alt_ref;
   group_of_picture->start_show_index = first_show_idx;
   group_of_picture->start_coding_index = start_coding_index;
+  group_of_picture->first_is_key_frame = first_is_key_frame;
+  group_of_picture->use_alt_ref = use_alt_ref;
+  group_of_picture->last_gop_use_alt_ref = last_gop_use_alt_ref;
 
   // We need to make a copy of start reference frame info because we
   // use it to simulate the ref frame update.
@@ -800,9 +803,8 @@
   return output_stats;
 }
 
-void SimpleEncode::SetExternalGroupOfPicture(
-    std::vector<int> external_arf_indexes) {
-  external_arf_indexes_ = external_arf_indexes;
+void SimpleEncode::SetExternalGroupOfPicture(std::vector<int> gop_map) {
+  gop_map_ = gop_map;
 }
 
 template <typename T>
@@ -816,15 +818,18 @@
 static GOP_COMMAND GetGopCommand(const std::vector<int> &gop_map,
                                  int start_show_index) {
   assert(static_cast<size_t>(start_show_index) < gop_map.size());
+  assert((gop_map[start_show_index] & kGopMapFlagStart) != 0);
   GOP_COMMAND gop_command;
   if (gop_map.size() > 0) {
     int end_show_index = start_show_index + 1;
+    // gop_map[end_show_index] & kGopMapFlagStart == 0 means this is
+    // the start of a gop.
     while (static_cast<size_t>(end_show_index) < gop_map.size() &&
-           gop_map[end_show_index] == 0) {
+           (gop_map[end_show_index] & kGopMapFlagStart) == 0) {
       ++end_show_index;
     }
     const int show_frame_count = end_show_index - start_show_index;
-    int use_alt_ref = 1;
+    int use_alt_ref = (gop_map[start_show_index] & kGopMapFlagUseAltRef) != 0;
     if (static_cast<size_t>(end_show_index) == gop_map.size()) {
       // This is the last gop group, there must be no altref.
       use_alt_ref = 0;
@@ -934,8 +939,7 @@
 
   IncreaseGroupOfPictureIndex(&group_of_picture_);
   if (IsGroupOfPictureFinished(group_of_picture_)) {
-    const GOP_COMMAND gop_command =
-        GetGopCommand(external_arf_indexes_, show_frame_count_);
+    const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_);
     encode_command_set_gop_command(&impl_ptr_->cpi->encode_command,
                                    gop_command);
     // This function needs to be called after ref_frame_info_ is updated
@@ -1040,8 +1044,8 @@
 
 int SimpleEncode::GetCodingFrameNum() const {
   assert(impl_ptr_->first_pass_stats.size() > 0);
-  if (external_arf_indexes_.size() > 0) {
-    return GetCodingFrameNumFromGopMap(external_arf_indexes_);
+  if (gop_map_.size() > 0) {
+    return GetCodingFrameNumFromGopMap(gop_map_);
   }
 
   // These are the default settings for now.
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -39,6 +39,14 @@
   kRefFrameTypeNone = -1,
 };
 
+enum GopMapFlag {
+  kGopMapFlagStart =
+      1 << 0,  // Indicate this location is the start of a group of pictures.
+  kGopMapFlagUseAltRef =
+      1 << 1,  // Indicate this group of pictures will use an alt ref. Only set
+               // this flag when kGopMapFlagStart is set.
+};
+
 // The frame is split to 4x4 blocks.
 // This structure contains the information of each 4x4 block.
 struct PartitionInfo {
@@ -255,6 +263,7 @@
   // triggered when the coded frame is the last one in the previous group of
   // pictures.
   std::vector<EncodeFrameInfo> encode_frame_list;
+
   // Indicates the index of the next coding frame in encode_frame_list.
   // In other words, EncodeFrameInfo of the next coding frame can be
   // obtained with encode_frame_list[next_encode_frame_index].
@@ -263,13 +272,25 @@
   // will be increased after each EncodeFrame()/EncodeFrameWithQuantizeIndex()
   // call.
   int next_encode_frame_index;
+
   // Number of show frames in this group of pictures.
   int show_frame_count;
+
   // The show index/timestamp of the earliest show frame in the group of
   // pictures.
   int start_show_index;
-  // The coding index of the first coding frame in the group of picture.
+
+  // The coding index of the first coding frame in the group of pictures.
   int start_coding_index;
+
+  // Indicates whether this group of pictures starts with a key frame.
+  int first_is_key_frame;
+
+  // Indicates whether this group of pictures uses an alt ref.
+  int use_alt_ref;
+
+  // Indicates whether previous group of pictures used an alt ref.
+  int last_gop_use_alt_ref;
 };
 
 class SimpleEncode {
@@ -293,13 +314,17 @@
   // values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h
   std::vector<std::vector<double>> ObserveFirstPassStats();
 
-  // Sets arf indexes for the video from external input.
-  // The arf index determines whether a frame is arf or not.
-  // Therefore it also determines the group of picture size.
-  // If set, VP9 will use the external arf index to make decision.
+  // Sets group of pictures map for coding the entire video.
+  // Each entry in the gop_map corresponds to a show frame in the video.
+  // Therefore, the size of gop_map should equal to the number of show frames in
+  // the entire video.
+  // If a given entry's kGopMapFlagStart is set, it means this is the start of a
+  // gop. Once kGopMapFlagStart is set, one can set kGopMapFlagUseAltRef to
+  // indicate whether this gop use altref.
+  // If a given entry is zero, it means it's in the middle of a gop.
   // This function should be called only once after ComputeFirstPassStats(),
   // before StartEncode().
-  void SetExternalGroupOfPicture(std::vector<int> external_arf_indexes);
+  void SetExternalGroupOfPicture(std::vector<int> gop_map);
 
   // Initializes the encoder for actual encoding.
   // This function should be called after ComputeFirstPassStats().
@@ -363,7 +388,7 @@
   std::FILE *out_file_;
   std::unique_ptr<EncodeImpl> impl_ptr_;
 
-  std::vector<int> external_arf_indexes_;
+  std::vector<int> gop_map_;
   GroupOfPicture group_of_picture_;
 
   // The key frame group size includes one key frame plus the number of