shithub: libvpx

Download patch

ref: 86675d87a3d3b639fb2f93a42619638447fd5e90
parent: ccb06a9fb15b9c10099cef28ff1240eb9ffa9390
author: Cheng Chen <chengchen@google.com>
date: Thu Jan 2 12:22:21 EST 2020

Copy frame counts to the encode result.

Explicitly copy frame counts of each frame to the encode result
struct.

Change-Id: Icc18ac83a9e2be8d7a4819f2fffcfda6568b275c

--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -7100,11 +7100,130 @@
 }
 
 #if !CONFIG_REALTIME_ONLY
+#if CONFIG_RATE_CTRL
+static void copy_frame_counts(const FRAME_COUNTS *input_counts,
+                              FRAME_COUNTS *output_counts) {
+  int i, j, k, l, m, n;
+  for (i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
+    for (j = 0; j < INTRA_MODES; ++j) {
+      output_counts->y_mode[i][j] = input_counts->y_mode[i][j];
+    }
+  }
+  for (i = 0; i < INTRA_MODES; ++i) {
+    for (j = 0; j < INTRA_MODES; ++j) {
+      output_counts->uv_mode[i][j] = input_counts->uv_mode[i][j];
+    }
+  }
+  for (i = 0; i < PARTITION_CONTEXTS; ++i) {
+    for (j = 0; j < PARTITION_TYPES; ++j) {
+      output_counts->partition[i][j] = input_counts->partition[i][j];
+    }
+  }
+  for (i = 0; i < TX_SIZES; ++i) {
+    for (j = 0; j < PLANE_TYPES; ++j) {
+      for (k = 0; k < REF_TYPES; ++k) {
+        for (l = 0; l < COEF_BANDS; ++l) {
+          for (m = 0; m < COEFF_CONTEXTS; ++m) {
+            output_counts->eob_branch[i][j][k][l][m] =
+                input_counts->eob_branch[i][j][k][l][m];
+            for (n = 0; n < UNCONSTRAINED_NODES + 1; ++n) {
+              output_counts->coef[i][j][k][l][m][n] =
+                  input_counts->coef[i][j][k][l][m][n];
+            }
+          }
+        }
+      }
+    }
+  }
+  for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) {
+    for (j = 0; j < SWITCHABLE_FILTERS; ++j) {
+      output_counts->switchable_interp[i][j] =
+          input_counts->switchable_interp[i][j];
+    }
+  }
+  for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
+    for (j = 0; j < INTER_MODES; ++j) {
+      output_counts->inter_mode[i][j] = input_counts->inter_mode[i][j];
+    }
+  }
+  for (i = 0; i < INTRA_INTER_CONTEXTS; ++i) {
+    for (j = 0; j < 2; ++j) {
+      output_counts->intra_inter[i][j] = input_counts->intra_inter[i][j];
+    }
+  }
+  for (i = 0; i < COMP_INTER_CONTEXTS; ++i) {
+    for (j = 0; j < 2; ++j) {
+      output_counts->comp_inter[i][j] = input_counts->comp_inter[i][j];
+    }
+  }
+  for (i = 0; i < REF_CONTEXTS; ++i) {
+    for (j = 0; j < 2; ++j) {
+      for (k = 0; k < 2; ++k) {
+        output_counts->single_ref[i][j][k] = input_counts->single_ref[i][j][k];
+      }
+    }
+  }
+  for (i = 0; i < REF_CONTEXTS; ++i) {
+    for (j = 0; j < 2; ++j) {
+      output_counts->comp_ref[i][j] = input_counts->comp_ref[i][j];
+    }
+  }
+  for (i = 0; i < SKIP_CONTEXTS; ++i) {
+    for (j = 0; j < 2; ++j) {
+      output_counts->skip[i][j] = input_counts->skip[i][j];
+    }
+  }
+  for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
+    for (j = 0; j < TX_SIZES; j++) {
+      output_counts->tx.p32x32[i][j] = input_counts->tx.p32x32[i][j];
+    }
+    for (j = 0; j < TX_SIZES - 1; j++) {
+      output_counts->tx.p16x16[i][j] = input_counts->tx.p16x16[i][j];
+    }
+    for (j = 0; j < TX_SIZES - 2; j++) {
+      output_counts->tx.p8x8[i][j] = input_counts->tx.p8x8[i][j];
+    }
+  }
+  for (i = 0; i < TX_SIZES; i++) {
+    output_counts->tx.tx_totals[i] = input_counts->tx.tx_totals[i];
+  }
+  for (i = 0; i < MV_JOINTS; i++) {
+    output_counts->mv.joints[i] = input_counts->mv.joints[i];
+  }
+  for (k = 0; k < 2; k++) {
+    nmv_component_counts *const comps = &output_counts->mv.comps[k];
+    const nmv_component_counts *const comps_t = &input_counts->mv.comps[k];
+    for (i = 0; i < 2; i++) {
+      comps->sign[i] = comps_t->sign[i];
+      comps->class0_hp[i] = comps_t->class0_hp[i];
+      comps->hp[i] = comps_t->hp[i];
+    }
+    for (i = 0; i < MV_CLASSES; i++) {
+      comps->classes[i] = comps_t->classes[i];
+    }
+    for (i = 0; i < CLASS0_SIZE; i++) {
+      comps->class0[i] = comps_t->class0[i];
+      for (j = 0; j < MV_FP_SIZE; j++) {
+        comps->class0_fp[i][j] = comps_t->class0_fp[i][j];
+      }
+    }
+    for (i = 0; i < MV_OFFSET_BITS; i++) {
+      for (j = 0; j < 2; j++) {
+        comps->bits[i][j] = comps_t->bits[i][j];
+      }
+    }
+    for (i = 0; i < MV_FP_SIZE; i++) {
+      comps->fp[i] = comps_t->fp[i];
+    }
+  }
+}
+#endif  // CONFIG_RATE_CTRL
+
 static void update_encode_frame_result(
     int show_idx, FRAME_UPDATE_TYPE update_type,
     const YV12_BUFFER_CONFIG *source_frame,
     const YV12_BUFFER_CONFIG *coded_frame, int quantize_index,
-    uint32_t bit_depth, uint32_t input_bit_depth,
+    uint32_t bit_depth, uint32_t input_bit_depth, const FRAME_COUNTS *counts,
     ENCODE_FRAME_RESULT *encode_frame_result) {
 #if CONFIG_RATE_CTRL
   PSNR_STATS psnr;
@@ -7118,11 +7237,13 @@
 #endif  // CONFIG_VP9_HIGHBITDEPTH
   encode_frame_result->psnr = psnr.psnr[0];
   encode_frame_result->sse = psnr.sse[0];
+  copy_frame_counts(counts, &encode_frame_result->frame_counts);
 #else   // CONFIG_RATE_CTRL
   (void)bit_depth;
   (void)input_bit_depth;
   (void)source_frame;
   (void)coded_frame;
+  (void)counts;
 #endif  // CONFIG_RATE_CTRL
   encode_frame_result->show_idx = show_idx;
   encode_frame_result->update_type = update_type;
@@ -7424,7 +7545,8 @@
         source->show_idx,
         cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index],
         cpi->Source, get_frame_new_buffer(cm), vp9_get_quantizer(cpi),
-        cpi->oxcf.input_bit_depth, cm->bit_depth, encode_frame_result);
+        cpi->oxcf.input_bit_depth, cm->bit_depth, cpi->td.counts,
+        encode_frame_result);
     vp9_twopass_postencode_update(cpi);
   } else if (cpi->use_svc) {
     SvcEncode(cpi, size, dest, frame_flags);
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -856,6 +856,7 @@
 #if CONFIG_RATE_CTRL
   double psnr;
   uint64_t sse;
+  FRAME_COUNTS frame_counts;
 #endif  // CONFIG_RATE_CTRL
   int quantize_index;
 } ENCODE_FRAME_RESULT;
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -1,4 +1,6 @@
 #include <vector>
+#include "vp9/common/vp9_entropymode.h"
+#include "vp9/common/vp9_enums.h"
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/vp9_iface_common.h"
 #include "vp9/encoder/vp9_encoder.h"
@@ -89,6 +91,227 @@
   }
 }
 
+static void update_frame_counts(const FRAME_COUNTS *input_counts,
+                                FrameCounts *output_counts) {
+  // Init array sizes.
+  output_counts->y_mode.resize(BLOCK_SIZE_GROUPS);
+  for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
+    output_counts->y_mode[i].resize(INTRA_MODES);
+  }
+
+  output_counts->uv_mode.resize(INTRA_MODES);
+  for (int i = 0; i < INTRA_MODES; ++i) {
+    output_counts->uv_mode[i].resize(INTRA_MODES);
+  }
+
+  output_counts->partition.resize(PARTITION_CONTEXTS);
+  for (int i = 0; i < PARTITION_CONTEXTS; ++i) {
+    output_counts->partition[i].resize(PARTITION_TYPES);
+  }
+
+  output_counts->coef.resize(TX_SIZES);
+  output_counts->eob_branch.resize(TX_SIZES);
+  for (int i = 0; i < TX_SIZES; ++i) {
+    output_counts->coef[i].resize(PLANE_TYPES);
+    output_counts->eob_branch[i].resize(PLANE_TYPES);
+    for (int j = 0; j < PLANE_TYPES; ++j) {
+      output_counts->coef[i][j].resize(REF_TYPES);
+      output_counts->eob_branch[i][j].resize(REF_TYPES);
+      for (int k = 0; k < REF_TYPES; ++k) {
+        output_counts->coef[i][j][k].resize(COEF_BANDS);
+        output_counts->eob_branch[i][j][k].resize(COEF_BANDS);
+        for (int l = 0; l < COEF_BANDS; ++l) {
+          output_counts->coef[i][j][k][l].resize(COEFF_CONTEXTS);
+          output_counts->eob_branch[i][j][k][l].resize(COEFF_CONTEXTS);
+          for (int m = 0; m < COEFF_CONTEXTS; ++m) {
+            output_counts->coef[i][j][k][l][m].resize(UNCONSTRAINED_NODES + 1);
+          }
+        }
+      }
+    }
+  }
+
+  output_counts->switchable_interp.resize(SWITCHABLE_FILTER_CONTEXTS);
+  for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) {
+    output_counts->switchable_interp[i].resize(SWITCHABLE_FILTERS);
+  }
+
+  output_counts->inter_mode.resize(INTER_MODE_CONTEXTS);
+  for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) {
+    output_counts->inter_mode[i].resize(INTER_MODES);
+  }
+
+  output_counts->intra_inter.resize(INTRA_INTER_CONTEXTS);
+  for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) {
+    output_counts->intra_inter[i].resize(2);
+  }
+
+  output_counts->comp_inter.resize(COMP_INTER_CONTEXTS);
+  for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) {
+    output_counts->comp_inter[i].resize(2);
+  }
+
+  output_counts->single_ref.resize(REF_CONTEXTS);
+  for (int i = 0; i < REF_CONTEXTS; ++i) {
+    output_counts->single_ref[i].resize(2);
+    for (int j = 0; j < 2; ++j) {
+      output_counts->single_ref[i][j].resize(2);
+    }
+  }
+
+  output_counts->comp_ref.resize(REF_CONTEXTS);
+  for (int i = 0; i < REF_CONTEXTS; ++i) {
+    output_counts->comp_ref[i].resize(2);
+  }
+
+  output_counts->skip.resize(SKIP_CONTEXTS);
+  for (int i = 0; i < SKIP_CONTEXTS; ++i) {
+    output_counts->skip[i].resize(2);
+  }
+
+  output_counts->tx.p32x32.resize(TX_SIZE_CONTEXTS);
+  output_counts->tx.p16x16.resize(TX_SIZE_CONTEXTS);
+  output_counts->tx.p8x8.resize(TX_SIZE_CONTEXTS);
+  for (int i = 0; i < TX_SIZE_CONTEXTS; i++) {
+    output_counts->tx.p32x32[i].resize(TX_SIZES);
+    output_counts->tx.p16x16[i].resize(TX_SIZES - 1);
+    output_counts->tx.p8x8[i].resize(TX_SIZES - 2);
+  }
+  output_counts->tx.tx_totals.resize(TX_SIZES);
+
+  output_counts->mv.joints.resize(MV_JOINTS);
+  output_counts->mv.comps.resize(2);
+  for (int i = 0; i < 2; ++i) {
+    output_counts->mv.comps[i].sign.resize(2);
+    output_counts->mv.comps[i].classes.resize(MV_CLASSES);
+    output_counts->mv.comps[i].class0.resize(CLASS0_SIZE);
+    output_counts->mv.comps[i].bits.resize(MV_OFFSET_BITS);
+    for (int j = 0; j < MV_OFFSET_BITS; ++j) {
+      output_counts->mv.comps[i].bits[j].resize(2);
+    }
+    output_counts->mv.comps[i].class0_fp.resize(CLASS0_SIZE);
+    for (int j = 0; j < CLASS0_SIZE; ++j) {
+      output_counts->mv.comps[i].class0_fp[j].resize(MV_FP_SIZE);
+    }
+    output_counts->mv.comps[i].fp.resize(MV_FP_SIZE);
+    output_counts->mv.comps[i].class0_hp.resize(2);
+    output_counts->mv.comps[i].hp.resize(2);
+  }
+
+  // Populate counts.
+  for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
+    for (int j = 0; j < INTRA_MODES; ++j) {
+      output_counts->y_mode[i][j] = input_counts->y_mode[i][j];
+    }
+  }
+  for (int i = 0; i < INTRA_MODES; ++i) {
+    for (int j = 0; j < INTRA_MODES; ++j) {
+      output_counts->uv_mode[i][j] = input_counts->uv_mode[i][j];
+    }
+  }
+  for (int i = 0; i < PARTITION_CONTEXTS; ++i) {
+    for (int j = 0; j < PARTITION_TYPES; ++j) {
+      output_counts->partition[i][j] = input_counts->partition[i][j];
+    }
+  }
+  for (int i = 0; i < TX_SIZES; ++i) {
+    for (int j = 0; j < PLANE_TYPES; ++j) {
+      for (int k = 0; k < REF_TYPES; ++k) {
+        for (int l = 0; l < COEF_BANDS; ++l) {
+          for (int m = 0; m < COEFF_CONTEXTS; ++m) {
+            output_counts->eob_branch[i][j][k][l][m] =
+                input_counts->eob_branch[i][j][k][l][m];
+            for (int n = 0; n < UNCONSTRAINED_NODES + 1; n++) {
+              output_counts->coef[i][j][k][l][m][n] =
+                  input_counts->coef[i][j][k][l][m][n];
+            }
+          }
+        }
+      }
+    }
+  }
+  for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) {
+    for (int j = 0; j < SWITCHABLE_FILTERS; ++j) {
+      output_counts->switchable_interp[i][j] =
+          input_counts->switchable_interp[i][j];
+    }
+  }
+  for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) {
+    for (int j = 0; j < INTER_MODES; ++j) {
+      output_counts->inter_mode[i][j] = input_counts->inter_mode[i][j];
+    }
+  }
+  for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      output_counts->intra_inter[i][j] = input_counts->intra_inter[i][j];
+    }
+  }
+  for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      output_counts->comp_inter[i][j] = input_counts->comp_inter[i][j];
+    }
+  }
+  for (int i = 0; i < REF_CONTEXTS; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      for (int k = 0; k < 2; ++k) {
+        output_counts->single_ref[i][j][k] = input_counts->single_ref[i][j][k];
+      }
+    }
+  }
+  for (int i = 0; i < REF_CONTEXTS; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      output_counts->comp_ref[i][j] = input_counts->comp_ref[i][j];
+    }
+  }
+  for (int i = 0; i < SKIP_CONTEXTS; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      output_counts->skip[i][j] = input_counts->skip[i][j];
+    }
+  }
+  for (int i = 0; i < TX_SIZE_CONTEXTS; i++) {
+    for (int j = 0; j < TX_SIZES; j++) {
+      output_counts->tx.p32x32[i][j] = input_counts->tx.p32x32[i][j];
+    }
+    for (int j = 0; j < TX_SIZES - 1; j++) {
+      output_counts->tx.p16x16[i][j] = input_counts->tx.p16x16[i][j];
+    }
+    for (int j = 0; j < TX_SIZES - 2; j++) {
+      output_counts->tx.p8x8[i][j] = input_counts->tx.p8x8[i][j];
+    }
+  }
+  for (int i = 0; i < TX_SIZES; i++) {
+    output_counts->tx.tx_totals[i] = input_counts->tx.tx_totals[i];
+  }
+  for (int i = 0; i < MV_JOINTS; i++) {
+    output_counts->mv.joints[i] = input_counts->mv.joints[i];
+  }
+  for (int k = 0; k < 2; k++) {
+    const nmv_component_counts *const comps_t = &input_counts->mv.comps[k];
+    for (int i = 0; i < 2; i++) {
+      output_counts->mv.comps[k].sign[i] = comps_t->sign[i];
+      output_counts->mv.comps[k].class0_hp[i] = comps_t->class0_hp[i];
+      output_counts->mv.comps[k].hp[i] = comps_t->hp[i];
+    }
+    for (int i = 0; i < MV_CLASSES; i++) {
+      output_counts->mv.comps[k].classes[i] = comps_t->classes[i];
+    }
+    for (int i = 0; i < CLASS0_SIZE; i++) {
+      output_counts->mv.comps[k].class0[i] = comps_t->class0[i];
+      for (int j = 0; j < MV_FP_SIZE; j++) {
+        output_counts->mv.comps[k].class0_fp[i][j] = comps_t->class0_fp[i][j];
+      }
+    }
+    for (int i = 0; i < MV_OFFSET_BITS; i++) {
+      for (int j = 0; j < 2; j++) {
+        output_counts->mv.comps[k].bits[i][j] = comps_t->bits[i][j];
+      }
+    }
+    for (int i = 0; i < MV_FP_SIZE; i++) {
+      output_counts->mv.comps[k].fp[i] = comps_t->fp[i];
+    }
+  }
+}
+
 static void update_encode_frame_result(
     EncodeFrameResult *encode_frame_result,
     const ENCODE_FRAME_RESULT *encode_frame_info) {
@@ -100,6 +323,8 @@
   encode_frame_result->psnr = encode_frame_info->psnr;
   encode_frame_result->sse = encode_frame_info->sse;
   encode_frame_result->quantize_index = encode_frame_info->quantize_index;
+  update_frame_counts(&encode_frame_info->frame_counts,
+                      &encode_frame_result->frame_counts);
 }
 
 static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) {
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -30,6 +30,53 @@
   FrameType frame_type;
 };
 
+// This structure is a copy of vp9 |nmv_component_counts|.
+struct NewMotionvectorComponentCounts {
+  std::vector<unsigned int> sign;
+  std::vector<unsigned int> classes;
+  std::vector<unsigned int> class0;
+  std::vector<std::vector<unsigned int>> bits;
+  std::vector<std::vector<unsigned int>> class0_fp;
+  std::vector<unsigned int> fp;
+  std::vector<unsigned int> class0_hp;
+  std::vector<unsigned int> hp;
+};
+
+// This structure is a copy of vp9 |nmv_context_counts|.
+struct NewMotionVectorContextCounts {
+  std::vector<unsigned int> joints;
+  std::vector<NewMotionvectorComponentCounts> comps;
+};
+
+// This structure is a copy of vp9 |tx_counts|.
+struct TransformSizeCounts {
+  std::vector<std::vector<unsigned int>> p32x32;
+  std::vector<std::vector<unsigned int>> p16x16;
+  std::vector<std::vector<unsigned int>> p8x8;
+  std::vector<unsigned int> tx_totals;
+};
+
+// This structure is a copy of vp9 |FRAME_COUNTS|.
+struct FrameCounts {
+  std::vector<std::vector<unsigned int>> y_mode;
+  std::vector<std::vector<unsigned int>> uv_mode;
+  std::vector<std::vector<unsigned int>> partition;
+  std::vector<std::vector<
+      std::vector<std::vector<std::vector<std::vector<unsigned int>>>>>>
+      coef;
+  std::vector<std::vector<std::vector<std::vector<std::vector<unsigned int>>>>>
+      eob_branch;
+  std::vector<std::vector<unsigned int>> switchable_interp;
+  std::vector<std::vector<unsigned int>> inter_mode;
+  std::vector<std::vector<unsigned int>> intra_inter;
+  std::vector<std::vector<unsigned int>> comp_inter;
+  std::vector<std::vector<std::vector<unsigned int>>> single_ref;
+  std::vector<std::vector<unsigned int>> comp_ref;
+  std::vector<std::vector<unsigned int>> skip;
+  TransformSizeCounts tx;
+  NewMotionVectorContextCounts mv;
+};
+
 struct EncodeFrameResult {
   int show_idx;
   FrameType frame_type;
@@ -41,6 +88,7 @@
   double psnr;
   uint64_t sse;
   int quantize_index;
+  FrameCounts frame_counts;
 };
 
 struct GroupOfPicture {