shithub: libvpx

Download patch

ref: fdf04093ecb87f9342aa3a17b7efaaf7cbb1808d
parent: 3bc58f13cc4ae0881ce483a8dcd7789a2d6f325d
author: angiebird <angiebird@google.com>
date: Sat May 23 12:28:40 EDT 2020

Add GOP_COMMAND

Send GOP_COMMAND to vp9 for setting gop decisions on the fly.
GOP_COMMAND has three members.
use: use this command to set gop or use vp9's gop decision.
show_frame_count: number of show frames in this gop.
use_alt_ref: use alt ref frame or not.

Move the logic of processing external_arf_indexes_ from
get_gop_coding_frame_num() to GetGopCommand() and
GetCodingFrameNumFromGopMap().

Change-Id: Ic1942c7a4cf6eecdf3507864577688350c7ef0cf

--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -532,12 +532,38 @@
   int_mv mv[2];
 } MOTION_VECTOR_INFO;
 
+typedef struct GOP_COMMAND {
+  int use;  // use this command to set gop or not. If not, use vp9's decision.
+  int show_frame_count;
+  int use_alt_ref;
+} GOP_COMMAND;
+
+static INLINE void gop_command_on(GOP_COMMAND *gop_command,
+                                  int show_frame_count, int use_alt_ref) {
+  gop_command->use = 1;
+  gop_command->show_frame_count = show_frame_count;
+  gop_command->use_alt_ref = use_alt_ref;
+}
+
+static INLINE void gop_command_off(GOP_COMMAND *gop_command) {
+  gop_command->use = 0;
+  gop_command->show_frame_count = 0;
+  gop_command->use_alt_ref = 0;
+}
+
+static INLINE int gop_command_coding_frame_count(
+    const GOP_COMMAND *gop_command) {
+  if (gop_command->use == 0) {
+    assert(0);
+    return -1;
+  }
+  return gop_command->show_frame_count + gop_command->use_alt_ref;
+}
+
 typedef struct ENCODE_COMMAND {
   int use_external_quantize_index;
   int external_quantize_index;
-  // A list of binary flags set from the external controller.
-  // Each binary flag indicates whether the frame is an arf or not.
-  const int *external_arf_indexes;
+  GOP_COMMAND gop_command;
 } ENCODE_COMMAND;
 
 static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) {
@@ -544,12 +570,12 @@
   vp9_zero(*encode_command);
   encode_command->use_external_quantize_index = 0;
   encode_command->external_quantize_index = -1;
-  encode_command->external_arf_indexes = NULL;
+  gop_command_off(&encode_command->gop_command);
 }
 
-static INLINE void encode_command_set_external_arf_indexes(
-    ENCODE_COMMAND *encode_command, const int *external_arf_indexes) {
-  encode_command->external_arf_indexes = external_arf_indexes;
+static INLINE void encode_command_set_gop_command(
+    ENCODE_COMMAND *encode_command, GOP_COMMAND gop_command) {
+  encode_command->gop_command = gop_command;
 }
 
 static INLINE void encode_command_set_external_quantize_index(
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2508,9 +2508,6 @@
  * structs.
  */
 static int get_gop_coding_frame_num(
-#if CONFIG_RATE_CTRL
-    const int *external_arf_indexes,
-#endif
     int *use_alt_ref, const FRAME_INFO *frame_info,
     const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc,
     int gf_start_show_idx, const RANGE *active_gf_interval,
@@ -2526,25 +2523,7 @@
       (frame_info->frame_height + frame_info->frame_width) / 4.0;
   double zero_motion_accumulator = 1.0;
   int gop_coding_frames;
-#if CONFIG_RATE_CTRL
-  (void)mv_ratio_accumulator_thresh;
-  (void)active_gf_interval;
-  (void)gop_intra_factor;
 
-  if (external_arf_indexes != NULL && rc->frames_to_key > 1) {
-    // gop_coding_frames = 1 is necessary to filter out the overlay frame,
-    // since the arf is in this group of picture and its overlay is in the next.
-    gop_coding_frames = 1;
-    *use_alt_ref = 1;
-    while (gop_coding_frames < rc->frames_to_key) {
-      const int frame_index = gf_start_show_idx + gop_coding_frames;
-      ++gop_coding_frames;
-      if (external_arf_indexes[frame_index] == 1) break;
-    }
-    return gop_coding_frames;
-  }
-#endif  // CONFIG_RATE_CTRL
-
   *use_alt_ref = 1;
   gop_coding_frames = 0;
   while (gop_coding_frames < rc->static_scene_max_gf_interval &&
@@ -2770,15 +2749,26 @@
     gop_intra_factor = 1.0;
   }
 
-  {
-    gop_coding_frames = get_gop_coding_frame_num(
 #if CONFIG_RATE_CTRL
-        cpi->encode_command.external_arf_indexes,
-#endif
-        &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
-        &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
-    use_alt_ref &= allow_alt_ref;
+  {
+    const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
+    assert(allow_alt_ref == 1);
+    if (gop_command->use) {
+      gop_coding_frames = gop_command_coding_frame_count(gop_command);
+      use_alt_ref = gop_command->use_alt_ref;
+    } else {
+      gop_coding_frames = get_gop_coding_frame_num(
+          &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
+          &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
+      use_alt_ref &= allow_alt_ref;
+    }
   }
+#else
+  gop_coding_frames = get_gop_coding_frame_num(
+      &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
+      &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
+  use_alt_ref &= allow_alt_ref;
+#endif
 
   // Was the group length constrained by the requirement for a new KF?
   rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0;
@@ -3704,6 +3694,7 @@
                                    int *use_alt_ref, int *coding_frame_count,
                                    int *first_show_idx,
                                    int *last_gop_use_alt_ref) {
+  const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
   // We make a copy of rc here because we want to get information from the
   // encoder without changing its state.
   // TODO(angiebird): Avoid copying rc here.
@@ -3726,14 +3717,19 @@
     *first_is_key_frame = 1;
   }
 
-  *coding_frame_count = vp9_get_gop_coding_frame_count(
-      cpi->encode_command.external_arf_indexes, &cpi->oxcf, &cpi->frame_info,
-      &cpi->twopass.first_pass_info, &rc, *first_show_idx, multi_layer_arf,
-      allow_alt_ref, *first_is_key_frame, *last_gop_use_alt_ref, use_alt_ref);
+  if (gop_command->use) {
+    *coding_frame_count = gop_command_coding_frame_count(gop_command);
+    *use_alt_ref = gop_command->use_alt_ref;
+    assert(*coding_frame_count < rc.frames_to_key);
+  } else {
+    *coding_frame_count = vp9_get_gop_coding_frame_count(
+        &cpi->oxcf, &cpi->frame_info, &cpi->twopass.first_pass_info, &rc,
+        *first_show_idx, multi_layer_arf, allow_alt_ref, *first_is_key_frame,
+        *last_gop_use_alt_ref, use_alt_ref);
+  }
 }
 
-int vp9_get_gop_coding_frame_count(const int *external_arf_indexes,
-                                   const VP9EncoderConfig *oxcf,
+int vp9_get_gop_coding_frame_count(const VP9EncoderConfig *oxcf,
                                    const FRAME_INFO *frame_info,
                                    const FIRST_PASS_INFO *first_pass_info,
                                    const RATE_CONTROL *rc, int show_idx,
@@ -3756,9 +3752,6 @@
   }
 
   frame_count = get_gop_coding_frame_num(
-#if CONFIG_RATE_CTRL
-      external_arf_indexes,
-#endif
       use_alt_ref, frame_info, first_pass_info, rc, show_idx,
       &active_gf_interval, gop_intra_factor, oxcf->lag_in_frames);
   *use_alt_ref &= allow_alt_ref;
@@ -3767,8 +3760,7 @@
 
 // Under CONFIG_RATE_CTRL, once the first_pass_info is ready, the number of
 // coding frames (including show frame and alt ref) can be determined.
-int vp9_get_coding_frame_num(const int *external_arf_indexes,
-                             const VP9EncoderConfig *oxcf,
+int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf,
                              const FRAME_INFO *frame_info,
                              const FIRST_PASS_INFO *first_pass_info,
                              int multi_layer_arf, int allow_alt_ref) {
@@ -3792,9 +3784,8 @@
     }
 
     gop_coding_frame_count = vp9_get_gop_coding_frame_count(
-        external_arf_indexes, oxcf, frame_info, first_pass_info, &rc, show_idx,
-        multi_layer_arf, allow_alt_ref, first_is_key_frame,
-        last_gop_use_alt_ref, &use_alt_ref);
+        oxcf, frame_info, first_pass_info, &rc, show_idx, multi_layer_arf,
+        allow_alt_ref, first_is_key_frame, last_gop_use_alt_ref, &use_alt_ref);
 
     rc.source_alt_ref_active = use_alt_ref;
     last_gop_use_alt_ref = use_alt_ref;
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -264,7 +264,6 @@
 
 /*!\brief Call this function before coding a new group of pictures to get
  * information about it.
- * \param[in] external_arf_indexes External arf indexs passed in
  * \param[in] oxcf                 Encoder config
  * \param[in] frame_info           Frame info
  * \param[in] first_pass_info      First pass stats
@@ -279,8 +278,7 @@
  *
  * \return Returns coding frame count
  */
-int vp9_get_gop_coding_frame_count(const int *external_arf_indexes,
-                                   const struct VP9EncoderConfig *oxcf,
+int vp9_get_gop_coding_frame_count(const struct VP9EncoderConfig *oxcf,
                                    const FRAME_INFO *frame_info,
                                    const FIRST_PASS_INFO *first_pass_info,
                                    const RATE_CONTROL *rc, int show_idx,
@@ -288,8 +286,7 @@
                                    int first_is_key_frame,
                                    int last_gop_use_alt_ref, int *use_alt_ref);
 
-int vp9_get_coding_frame_num(const int *external_arf_indexes,
-                             const struct VP9EncoderConfig *oxcf,
+int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf,
                              const FRAME_INFO *frame_info,
                              const FIRST_PASS_INFO *first_pass_info,
                              int multi_layer_arf, int allow_alt_ref);
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -813,6 +813,29 @@
   return const_cast<T *>(v.data());
 }
 
+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());
+  GOP_COMMAND gop_command;
+  if (gop_map.size() > 0) {
+    int end_show_index = start_show_index + 1;
+    while (static_cast<size_t>(end_show_index) < gop_map.size() &&
+           gop_map[end_show_index] == 0) {
+      ++end_show_index;
+    }
+    const int show_frame_count = end_show_index - start_show_index;
+    int use_alt_ref = 1;
+    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;
+    }
+    gop_command_on(&gop_command, show_frame_count, use_alt_ref);
+  } else {
+    gop_command_off(&gop_command);
+  }
+  return gop_command;
+}
+
 void SimpleEncode::StartEncode() {
   assert(impl_ptr_->first_pass_stats.size() > 0);
   vpx_rational_t frame_rate =
@@ -834,9 +857,6 @@
   frame_coding_index_ = 0;
   show_frame_count_ = 0;
 
-  encode_command_set_external_arf_indexes(&impl_ptr_->cpi->encode_command,
-                                          GetVectorData(external_arf_indexes_));
-
   UpdateKeyFrameGroup(show_frame_count_);
 
   UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
@@ -914,6 +934,10 @@
 
   IncreaseGroupOfPictureIndex(&group_of_picture_);
   if (IsGroupOfPictureFinished(group_of_picture_)) {
+    const GOP_COMMAND gop_command =
+        GetGopCommand(external_arf_indexes_, 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
     // properly in PostUpdateRefFrameInfo() and UpdateKeyFrameGroup().
     UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
@@ -1002,8 +1026,24 @@
   encode_command_reset_external_quantize_index(&impl_ptr_->cpi->encode_command);
 }
 
+static int GetCodingFrameNumFromGopMap(const std::vector<int> &gop_map) {
+  int start_show_index = 0;
+  int coding_frame_count = 0;
+  while (static_cast<size_t>(start_show_index) < gop_map.size()) {
+    const GOP_COMMAND gop_command = GetGopCommand(gop_map, start_show_index);
+    start_show_index += gop_command.show_frame_count;
+    coding_frame_count += gop_command_coding_frame_count(&gop_command);
+  }
+  assert(start_show_index == gop_map.size());
+  return coding_frame_count;
+}
+
 int SimpleEncode::GetCodingFrameNum() const {
-  assert(impl_ptr_->first_pass_stats.size() - 1 > 0);
+  assert(impl_ptr_->first_pass_stats.size() > 0);
+  if (external_arf_indexes_.size() > 0) {
+    return GetCodingFrameNumFromGopMap(external_arf_indexes_);
+  }
+
   // These are the default settings for now.
   const int multi_layer_arf = 0;
   const int allow_alt_ref = 1;
@@ -1017,8 +1057,7 @@
   fps_init_first_pass_info(&first_pass_info,
                            GetVectorData(impl_ptr_->first_pass_stats),
                            num_frames_);
-  return vp9_get_coding_frame_num(external_arf_indexes_.data(), &oxcf,
-                                  &frame_info, &first_pass_info,
+  return vp9_get_coding_frame_num(&oxcf, &frame_info, &first_pass_info,
                                   multi_layer_arf, allow_alt_ref);
 }