shithub: libvpx

Download patch

ref: 7dbdada49f0d63d18173fa91d9510fc5f17bb21a
parent: d1cdda88bd3d98b4e8c84dafa3dfecfebbfb8c88
parent: 36eabb1c3cf182173109643a7031e4c5ed2c7114
author: Yunqing Wang <[email protected]>
date: Wed May 6 13:12:10 EDT 2015

Merge "Add intra mode early termination in non-rd mode"

--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -923,7 +923,7 @@
 }
 
 static const THR_MODES mode_idx[MAX_REF_FRAMES - 1][4] = {
-  {THR_DC, THR_H_PRED, THR_V_PRED, THR_TM},
+  {THR_DC, THR_V_PRED, THR_H_PRED, THR_TM},
   {THR_NEARESTMV, THR_NEARMV, THR_ZEROMV, THR_NEWMV},
   {THR_NEARESTG, THR_NEARG, THR_ZEROG, THR_NEWG},
 };
@@ -932,6 +932,40 @@
   DC_PRED, V_PRED, H_PRED, TM_PRED
 };
 
+static int mode_offset(const PREDICTION_MODE mode) {
+  if (mode >= NEARESTMV) {
+    return INTER_OFFSET(mode);
+  } else {
+    switch (mode) {
+      case DC_PRED:
+        return 0;
+      case V_PRED:
+        return 1;
+      case H_PRED:
+        return 2;
+      case TM_PRED:
+        return 3;
+      default:
+        return -1;
+    }
+  }
+}
+
+static INLINE void update_thresh_freq_fact(VP9_COMP *cpi,
+                                           TileDataEnc *tile_data,
+                                           BLOCK_SIZE bsize,
+                                           MV_REFERENCE_FRAME ref_frame,
+                                           THR_MODES best_mode_idx,
+                                           PREDICTION_MODE mode) {
+  THR_MODES thr_mode_idx = mode_idx[ref_frame][mode_offset(mode)];
+  int *freq_fact = &tile_data->thresh_freq_fact[bsize][thr_mode_idx];
+  if (thr_mode_idx == best_mode_idx)
+    *freq_fact -= (*freq_fact >> 4);
+  else
+    *freq_fact = MIN(*freq_fact + RD_THRESH_INC,
+        cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT);
+}
+
 void vp9_pick_intra_mode(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost,
                          BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) {
   MACROBLOCKD *const xd = &x->e_mbd;
@@ -1489,8 +1523,16 @@
 
     for (i = 0; i < 4; ++i) {
       const PREDICTION_MODE this_mode = intra_mode_list[i];
+      THR_MODES mode_index = mode_idx[INTRA_FRAME][mode_offset(this_mode)];
+      int mode_rd_thresh = rd_threshes[mode_index];
+
       if (!((1 << this_mode) & cpi->sf.intra_y_mode_bsize_mask[bsize]))
         continue;
+
+      if (rd_less_than_thresh(best_rdc.rdcost, mode_rd_thresh,
+                              rd_thresh_freq_fact[mode_index]))
+        continue;
+
       mbmi->mode = this_mode;
       mbmi->ref_frame[0] = INTRA_FRAME;
       args.mode = this_mode;
@@ -1551,20 +1593,28 @@
   }
 
   if (cpi->sf.adaptive_rd_thresh) {
-    THR_MODES best_mode_idx = is_inter_block(mbmi) ?
-        mode_idx[best_ref_frame][INTER_OFFSET(mbmi->mode)] :
-        mode_idx[INTRA_FRAME][mbmi->mode];
+    THR_MODES best_mode_idx = mode_idx[best_ref_frame][mode_offset(mbmi->mode)];
     PREDICTION_MODE this_mode;
-    for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) {
-      if (best_ref_frame != ref_frame) continue;
-      for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
-        THR_MODES thr_mode_idx = mode_idx[ref_frame][INTER_OFFSET(this_mode)];
-        int *freq_fact = &tile_data->thresh_freq_fact[bsize][thr_mode_idx];
-        if (thr_mode_idx == best_mode_idx)
-          *freq_fact -= (*freq_fact >> 4);
-        else
-          *freq_fact = MIN(*freq_fact + RD_THRESH_INC,
-                           cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT);
+
+    if (best_ref_frame == INTRA_FRAME) {
+      // Only consider the modes that are included in the intra_mode_list.
+      int intra_modes = sizeof(intra_mode_list)/sizeof(PREDICTION_MODE);
+      int i;
+
+      // TODO(yunqingwang): Check intra mode mask and only update freq_fact
+      // for those valid modes.
+      for (i = 0; i < intra_modes; i++) {
+        PREDICTION_MODE this_mode = intra_mode_list[i];
+        update_thresh_freq_fact(cpi, tile_data, bsize, INTRA_FRAME,
+                                best_mode_idx, this_mode);
+      }
+    } else {
+      for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) {
+        if (best_ref_frame != ref_frame) continue;
+        for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
+          update_thresh_freq_fact(cpi, tile_data, bsize, ref_frame,
+                                  best_mode_idx, this_mode);
+        }
       }
     }
   }