Enable variable block size test in non-RD mode decision
authorJingning Han <jingning@google.com>
Wed, 19 Mar 2014 18:25:40 +0000 (11:25 -0700)
committerJingning Han <jingning@google.com>
Wed, 19 Mar 2014 23:10:29 +0000 (16:10 -0700)
This is an initial attempt to allow variable block size partition
in non-RD coding flow. It tests 8x8, 16x16 and 32x32 block size per
64x64 block, all using non-RD mode decision and the associated rate
distortion costs from modeling, then selects the best block size to
encode the entire 64x64 block. Such operations are triggered every
other 3 frames. The blocks of intermediate frames will reuse the
collocated block's partition type.

It improves the compression performance by 13.2%. Note that the gains
are not evenly distributed. For many hard clips, the compression
performance is improved by 20% to 28%. Local speed test shows that
it will also increase runtime by 50%, as compared to speed -7. It is
now enabled in speed -6 setting.

Change-Id: Ib4fb8659d21621c9075b3c369ddaa9ecb0a4b204

vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_onyx_int.h
vp9/encoder/vp9_pickmode.c

index a385922..257abde 100644 (file)
@@ -2693,6 +2693,7 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
   MACROBLOCKD *const xd = &x->e_mbd;
   set_offsets(cpi, tile, mi_row, mi_col, bsize);
   xd->mi_8x8[0]->mbmi.sb_type = bsize;
+
   if (!frame_is_intra_only(cm)) {
     vp9_pick_inter_mode(cpi, x, tile, mi_row, mi_col,
                         rate, dist, bsize);
@@ -2825,6 +2826,8 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
     int64_t dummy_dist;
     const int idx_str = cm->mode_info_stride * mi_row + mi_col;
     MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
+    MODE_INFO **prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
+
     BLOCK_SIZE bsize = cpi->sf.partition_search_type == FIXED_PARTITION ?
         cpi->sf.always_this_block_size :
         get_nonrd_var_based_fixed_partition(cpi, mi_row, mi_col);
@@ -2834,6 +2837,47 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
     // Set the partition type of the 64X64 block
     if (cpi->sf.partition_search_type == VAR_BASED_PARTITION)
       choose_partitioning(cpi, tile, mi_row, mi_col);
+    else if (cpi->sf.partition_search_type == REFERENCE_PARTITION) {
+      if (cpi->sf.partition_check) {
+        MACROBLOCK *x = &cpi->mb;
+        int rate1, rate2, rate3;
+        int64_t dist1, dist2, dist3;
+        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, BLOCK_8X8);
+        nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
+                            0, &rate1, &dist1);
+        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, BLOCK_16X16);
+        nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
+                            0, &rate2, &dist2);
+        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, BLOCK_32X32);
+        nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
+                            0, &rate3, &dist3);
+
+        if (RDCOST(x->rdmult, x->rddiv, rate1, dist1) <
+            RDCOST(x->rdmult, x->rddiv, rate2, dist2)) {
+          if (RDCOST(x->rdmult, x->rddiv, rate1, dist1) <
+              RDCOST(x->rdmult, x->rddiv, rate3, dist3))
+            set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col,
+                                   BLOCK_8X8);
+          else
+            set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col,
+                                   BLOCK_32X32);
+        } else {
+          if (RDCOST(x->rdmult, x->rddiv, rate2, dist2) <
+              RDCOST(x->rdmult, x->rddiv, rate3, dist3))
+            set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col,
+                                   BLOCK_16X16);
+          else
+            set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col,
+                                   BLOCK_32X32);
+        }
+
+      } else {
+        if (!sb_has_motion(cm, prev_mi_8x8))
+          copy_partitioning(cm, mi_8x8, prev_mi_8x8);
+        else
+          set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, bsize);
+      }
+    }
     else
       set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, bsize);
 
index b0e5e1a..7236893 100644 (file)
@@ -874,8 +874,11 @@ static void set_rt_speed_feature(VP9_COMMON *cm,
     sf->max_intra_bsize = BLOCK_32X32;
   }
   if (speed >= 6) {
-    sf->partition_search_type = VAR_BASED_FIXED_PARTITION;
-    sf->search_method = HEX;
+    sf->partition_check =
+        (cm->current_video_frame % sf->last_partitioning_redo_frequency == 1);
+    sf->partition_search_type = REFERENCE_PARTITION;
+    sf->use_nonrd_pick_mode = 1;
+    sf->search_method = FAST_DIAMOND;
   }
   if (speed >= 7) {
     sf->partition_search_type = VAR_BASED_FIXED_PARTITION;
index ad1dd9b..c7abff9 100644 (file)
@@ -213,6 +213,8 @@ typedef enum {
   // determined based on source variance
   VAR_BASED_FIXED_PARTITION = 2,
 
+  REFERENCE_PARTITION = 3,
+
   // Use an arbitrary partitioning scheme based on source variance within
   // a 64X64 SB
   VAR_BASED_PARTITION
@@ -357,6 +359,10 @@ typedef struct {
   // was selected, and 2 means we use 8 tap if no 8x8 filter mode was selected.
   int adaptive_pred_interp_filter;
 
+  // Search through variable block partition types in non-RD mode decision
+  // encoding process for RTC.
+  int partition_check;
+
   // Implements various heuristics to skip searching modes
   // The heuristics selected are based on  flags
   // defined in the MODE_SEARCH_SKIP_HEURISTICS enum
index 0a396ff..ae66746 100644 (file)
@@ -233,12 +233,16 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
   int64_t best_rd = INT64_MAX;
   int64_t this_rd = INT64_MAX;
 
-  const int64_t inter_mode_thresh = 300;
-  const int64_t intra_mode_cost = 50;
-
   int rate = INT_MAX;
   int64_t dist = INT64_MAX;
 
+  VP9_COMMON *cm = &cpi->common;
+  int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
+
+  const int64_t inter_mode_thresh = RDCOST(x->rdmult, x->rddiv,
+                                           intra_cost_penalty, 0);
+  const int64_t intra_mode_cost = 50;
+
   x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
 
   x->skip = 0;
@@ -345,6 +349,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 
       model_rd_for_sb_y(cpi, bsize, x, xd, &rate, &dist);
       rate += x->mbmode_cost[this_mode];
+      rate += intra_cost_penalty;
       this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
 
       if (this_rd + intra_mode_cost < best_rd) {