shithub: libvpx

Download patch

ref: 29a487c77f81a4c864b8f9dd07325d10f0515a98
parent: 29beeff11dd957af3f28d52fea9433ec43603bc7
author: Alex Converse <aconverse@google.com>
date: Fri Mar 7 13:15:33 EST 2014

Add a conservative RD based active map in vp9.

Change-Id: I47b3c38aadfd8f3ea08515a18a5948aa1375c650

--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -154,7 +154,7 @@
 
   int encode_breakout;
 
-  unsigned char *active_ptr;
+  int in_active_map;
 
   // note that token_costs is the cost when eob node is skipped
   vp9_coeff_cost token_costs[TX_SIZES];
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -571,6 +571,32 @@
                      x->e_mbd.plane[i].subsampling_y);
 }
 
+static int is_block_in_mb_map(VP9_COMP *cpi, int mi_row, int mi_col,
+                              BLOCK_SIZE bsize) {
+  VP9_COMMON *const cm = &cpi->common;
+  const int mb_rows = cm->mb_rows;
+  const int mb_cols = cm->mb_cols;
+  const int mb_row = mi_row >> 1;
+  const int mb_col = mi_col >> 1;
+  const int mb_width = num_8x8_blocks_wide_lookup[bsize] >> 1;
+  const int mb_height = num_8x8_blocks_high_lookup[bsize] >> 1;
+  int r, c;
+  if (bsize <= BLOCK_16X16) {
+    return cpi->active_map[mb_row * mb_cols + mb_col];
+  }
+  for (r = 0; r < mb_height; ++r) {
+    for (c = 0; c < mb_width; ++c) {
+      int row = mb_row + r;
+      int col = mb_col + c;
+      if (row >= mb_rows || col >= mb_cols)
+        continue;
+      if (cpi->active_map[row * mb_cols + col])
+        return 1;
+    }
+  }
+  return 0;
+}
+
 static void set_offsets(VP9_COMP *cpi, const TileInfo *const tile,
                         int mi_row, int mi_col, BLOCK_SIZE bsize) {
   MACROBLOCK *const x = &cpi->mb;
@@ -589,8 +615,13 @@
 
   // Activity map pointer
   x->mb_activity_ptr = &cpi->mb_activity_map[idx_map];
-  x->active_ptr = cpi->active_map + idx_map;
 
+  if (cpi->active_map_enabled && !x->e_mbd.lossless) {
+    x->in_active_map = is_block_in_mb_map(cpi, mi_row, mi_col, bsize);
+  } else {
+    x->in_active_map = 1;
+  }
+
   xd->mi_8x8 = cm->mi_grid_visible + idx_str;
   xd->prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
 
@@ -1772,6 +1803,10 @@
           do_rect = 0;
         }
       }
+    }
+    if (!x->in_active_map) {
+      do_split = 0;
+      do_rect = 0;
     }
     restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
   }
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -248,7 +248,7 @@
   x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
 
   x->skip = 0;
-  if (cpi->active_map_enabled && x->active_ptr[0] == 0)
+  if (!x->in_active_map)
     x->skip = 1;
 
   // initialize mode decisions
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2917,9 +2917,12 @@
     *rate2 += get_switchable_rate(x);
 
   if (!is_comp_pred) {
-    if (cpi->active_map_enabled && x->active_ptr[0] == 0)
+    if (!x->in_active_map) {
+      if (psse)
+        *psse = 0;
+      *distortion = 0;
       x->skip = 1;
-    else if (cpi->allow_encode_breakout && x->encode_breakout) {
+    } else if (cpi->allow_encode_breakout && x->encode_breakout) {
       const BLOCK_SIZE y_size = get_plane_block_size(bsize, &xd->plane[0]);
       const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
       unsigned int var, sse;
@@ -3162,7 +3165,7 @@
   const int bhs = num_8x8_blocks_high_lookup[bsize] / 2;
   int best_skip2 = 0;
   int mode_skip_mask = 0;
-  const int mode_skip_start = cpi->sf.mode_skip_start + 1;
+  int mode_skip_start = cpi->sf.mode_skip_start + 1;
   const int *const rd_threshes = cpi->rd_threshes[segment_id][bsize];
   const int *const rd_thresh_freq_fact = cpi->rd_thresh_freq_fact[bsize];
   const int mode_search_skip_flags = cpi->sf.mode_search_skip_flags;
@@ -3271,6 +3274,19 @@
     mode_skip_mask |= 0xFF30808;
   }
 
+  if (!x->in_active_map) {
+    int mode_index;
+    assert(cpi->ref_frame_flags & VP9_LAST_FLAG);
+    if (frame_mv[NEARESTMV][LAST_FRAME].as_int == 0)
+      mode_index = THR_NEARESTMV;
+    else if (frame_mv[NEARMV][LAST_FRAME].as_int == 0)
+      mode_index = THR_NEARMV;
+    else
+      mode_index = THR_ZEROMV;
+    mode_skip_mask = ~(1 << mode_index);
+    mode_skip_start = MAX_MODES;
+  }
+
   for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
     int mode_excluded = 0;
     int64_t this_rd = INT64_MAX;
@@ -3360,8 +3376,11 @@
         }
       }
     } else {
+      // TODO(aconverse): Find out if this is still productive then clean up or
+      // remove
       // if we're near/nearest and mv == 0,0, compare to zeromv
-      if (!(disable_inter_mode_mask & (1 << INTER_OFFSET(ZEROMV))) &&
+      if (x->in_active_map &&
+          !(disable_inter_mode_mask & (1 << INTER_OFFSET(ZEROMV))) &&
           (this_mode == NEARMV || this_mode == NEARESTMV ||
           this_mode == ZEROMV) &&
           frame_mv[this_mode][ref_frame].as_int == 0 &&
@@ -3400,7 +3419,7 @@
     }
 
     mbmi->mode = this_mode;
-    mbmi->uv_mode = DC_PRED;
+    mbmi->uv_mode = x->in_active_map ? DC_PRED : this_mode;
     mbmi->ref_frame[0] = ref_frame;
     mbmi->ref_frame[1] = second_ref_frame;
     // Evaluate all sub-pel filters irrespective of whether we can use
@@ -3744,6 +3763,16 @@
   } else {
     vp9_zero(best_filter_diff);
     vp9_zero(best_tx_diff);
+  }
+
+  if (!x->in_active_map) {
+    assert(mbmi->ref_frame[0] == LAST_FRAME);
+    assert(mbmi->ref_frame[1] == NONE);
+    assert(mbmi->mode == NEARESTMV ||
+           mbmi->mode == NEARMV ||
+           mbmi->mode == ZEROMV);
+    assert(frame_mv[mbmi->mode][LAST_FRAME].as_int == 0);
+    assert(mbmi->mode == mbmi->uv_mode);
   }
 
   set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -1003,8 +1003,17 @@
 static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
-  // TODO(yaowu): Need to re-implement and test for VP9.
-  return VPX_CODEC_INVALID_PARAM;
+  vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
+
+  if (data) {
+    vpx_active_map_t *map = (vpx_active_map_t *)data;
+    if (!vp9_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
+      return VPX_CODEC_OK;
+    else
+      return VPX_CODEC_INVALID_PARAM;
+  } else {
+    return VPX_CODEC_INVALID_PARAM;
+  }
 }
 
 static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,