]> granicus.if.org Git - libvpx/commitdiff
Store/read 16x16 block statistics obtained from the first pass
authorPengchong Jin <pengchong@google.com>
Mon, 30 Jun 2014 16:52:27 +0000 (09:52 -0700)
committerPengchong Jin <pengchong@google.com>
Tue, 1 Jul 2014 23:47:17 +0000 (16:47 -0700)
Add a conditional compile flag for this feature. Also add a
switch to enable the encoder to use these statistics in the
second pass. Currently, the switch is turned off.

Change-Id: Ia1c858c35ec90e36f19f5cffe156b97ddaa04922

configure
vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_encoder.h
vp9/encoder/vp9_firstpass.c
vp9/encoder/vp9_firstpass.h

index 0dca4c33c22fe65773ab927ea9013cc384c11e7d..b98480ecb20df16b6055571e37b1997df0239e71 100755 (executable)
--- a/configure
+++ b/configure
@@ -274,6 +274,7 @@ EXPERIMENT_LIST="
     multiple_arf
     spatial_svc
     denoising
+    fp_mb_stats
 "
 CONFIG_LIST="
     external_build
index 54fb68bb6cb3b72255ab04d0ce257a5f61d1a668..4f17a15a9c9450e4e1c5ca5f3e15164396e7b5ad 100644 (file)
@@ -199,6 +199,13 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
     vpx_free(cpi->source_diff_var);
     cpi->source_diff_var = NULL;
   }
+
+#if CONFIG_FP_MB_STATS
+  if (cpi->use_fp_mb_stats) {
+    vpx_free(cpi->twopass.this_frame_mb_stats.mb_stats);
+    cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
+  }
+#endif
 }
 
 static void save_coding_context(VP9_COMP *cpi) {
@@ -766,6 +773,17 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
                                sizeof(*cpi->mbgraph_stats[i].mb_stats), 1));
   }
 
+#if CONFIG_FP_MB_STATS
+  cpi->use_fp_mb_stats = 0;
+  if (cpi->use_fp_mb_stats) {
+    // a place holder for the mb stats obtained from the first pass
+    CHECK_MEM_ERROR(cm, cpi->twopass.this_frame_mb_stats.mb_stats,
+                    vpx_calloc(cm->MBs * sizeof(FIRSTPASS_MB_STATS), 1));
+  } else {
+    cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
+  }
+#endif
+
   cpi->refresh_alt_ref_frame = 0;
 
   // Note that at the moment multi_arf will not work with svc.
index 5e8430a91d73e4db2e510b1fa13d2e9d090da6df..b38f9c2460f02897110d7afcb3fe4aa53c612f80 100644 (file)
@@ -348,6 +348,10 @@ typedef struct VP9_COMP {
   uint64_t time_pick_lpf;
   uint64_t time_encode_sb_row;
 
+#if CONFIG_FP_MB_STATS
+  int use_fp_mb_stats;
+#endif
+
   TWO_PASS twopass;
 
   YV12_BUFFER_CONFIG alt_ref_buffer;
index 971b159313c0a4bff0418167c366375170838136..f90c9df5e26274a8823223f5a2de37c4f82dd8c0 100644 (file)
@@ -106,6 +106,34 @@ static int read_frame_stats(const TWO_PASS *p,
   return 1;
 }
 
+#if CONFIG_FP_MB_STATS
+static int input_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats,
+                          const VP9_COMMON *const cm) {
+  FILE *fpfile;
+  int ret;
+
+  fpfile = fopen("firstpass_mb.stt", "r");
+  fseek(fpfile, cm->current_video_frame * cm->MBs * sizeof(FIRSTPASS_MB_STATS),
+        SEEK_SET);
+  ret = fread(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs,
+              fpfile);
+  fclose(fpfile);
+  if (ret < cm->MBs) {
+    return EOF;
+  }
+  return 1;
+}
+
+static void output_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats,
+                          const VP9_COMMON *const cm) {
+  FILE *fpfile;
+
+  fpfile = fopen("firstpass_mb.stt", "a");
+  fwrite(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, fpfile);
+  fclose(fpfile);
+}
+#endif
+
 static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) {
   if (p->stats_in >= p->stats_in_end)
     return EOF;
@@ -452,6 +480,10 @@ void vp9_first_pass(VP9_COMP *cpi) {
   const MV zero_mv = {0, 0};
   const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
 
+#if CONFIG_FP_MB_STATS
+  FIRSTPASS_FRAME_MB_STATS *this_frame_mb_stats = &twopass->this_frame_mb_stats;
+#endif
+
   vp9_clear_system_state();
 
   set_first_pass_params(cpi);
@@ -579,6 +611,17 @@ void vp9_first_pass(VP9_COMP *cpi) {
       // Accumulate the intra error.
       intra_error += (int64_t)this_error;
 
+#if CONFIG_FP_MB_STATS
+      if (cpi->use_fp_mb_stats) {
+        this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode =
+            DC_PRED;
+        this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err =
+            this_error;
+        this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.as_int
+            = 0;
+      }
+#endif
+
       // Set up limit values for motion vectors to prevent them extending
       // outside the UMV borders.
       x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
@@ -704,6 +747,17 @@ void vp9_first_pass(VP9_COMP *cpi) {
 
           best_ref_mv.as_int = mv.as_int;
 
+#if CONFIG_FP_MB_STATS
+          if (cpi->use_fp_mb_stats) {
+            this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode =
+                NEWMV;
+            this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err =
+                motion_error;
+            this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.
+                as_int = mv.as_int;
+          }
+#endif
+
           if (mv.as_int) {
             ++mvcount;
 
@@ -808,6 +862,12 @@ void vp9_first_pass(VP9_COMP *cpi) {
     twopass->this_frame_stats = fps;
     output_stats(&twopass->this_frame_stats, cpi->output_pkt_list);
     accumulate_stats(&twopass->total_stats, &fps);
+
+#if CONFIG_FP_MB_STATS
+    if (cpi->use_fp_mb_stats) {
+      output_mb_stats(this_frame_mb_stats, cm);
+    }
+#endif
   }
 
   // Copy the previous Last Frame back into gf and and arf buffers if
@@ -2167,6 +2227,12 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
 
   // Update the total stats remaining structure.
   subtract_stats(&twopass->total_left_stats, &this_frame);
+
+#if CONFIG_FP_MB_STATS
+  if (cpi->use_fp_mb_stats) {
+    input_mb_stats(&twopass->this_frame_mb_stats, cm);
+  }
+#endif
 }
 
 void vp9_twopass_postencode_update(VP9_COMP *cpi) {
index 1ee56a3a700fae458cfc2d64bd4c6ab01dfb22c4..7e4c9ee20fe366edcf3f0cb0393843bf90291fcf 100644 (file)
 extern "C" {
 #endif
 
+#if CONFIG_FP_MB_STATS
+typedef struct {
+  PREDICTION_MODE mode;
+  int err;
+  int_mv mv;
+} FIRSTPASS_MB_STATS;
+
+typedef struct {
+  FIRSTPASS_MB_STATS *mb_stats;
+} FIRSTPASS_FRAME_MB_STATS;
+#endif
+
 typedef struct {
   double frame;
   double intra_error;
@@ -76,6 +88,10 @@ typedef struct {
   double kf_intra_err_min;
   double gf_intra_err_min;
 
+#if CONFIG_FP_MB_STATS
+  FIRSTPASS_FRAME_MB_STATS this_frame_mb_stats;
+#endif
+
   // Projected total bits available for a key frame group of frames
   int64_t kf_group_bits;