shithub: libvpx

Download patch

ref: 2c04e85d06ea03d49e6b3c8823f33b08ff6396da
parent: 82dc1332af4b16d3e4ad3c4358498820637b7add
parent: aaabbd67b240e0dd581902b857fc040c94275190
author: Pengchong Jin <pengchong@google.com>
date: Wed Jul 2 04:36:22 EDT 2014

Merge "Store/read 16x16 block statistics obtained from the first pass"

--- a/configure
+++ b/configure
@@ -274,6 +274,7 @@
     multiple_arf
     spatial_svc
     denoising
+    fp_mb_stats
 "
 CONFIG_LIST="
     external_build
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -199,6 +199,13 @@
     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) {
@@ -765,6 +772,17 @@
                     vpx_calloc(cm->MBs *
                                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;
 
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -348,6 +348,10 @@
   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;
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -106,6 +106,34 @@
   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 @@
   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 @@
       // 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 @@
 
           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 @@
     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 @@
 
   // 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) {
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -18,7 +18,19 @@
 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;
   double coded_error;
@@ -75,6 +87,10 @@
   double modified_error_left;
   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;