shithub: libvpx

Download patch

ref: adbfc4308a7dfe4c31478ca36dc2719fcf21cfff
parent: 3d6b0cb825d18fba31649c4ada500b9ed15b0d4a
author: Jerome Jiang <jianj@google.com>
date: Tue Jul 11 07:31:01 EDT 2017

vp9: Remove isolated skin & non-skin blocks.

0.007% regression on rtc and 0.004% gain on rtc_derf.
1 thread on QVGA,VGA and HD has ~0.2% speed regression while 2 threads has
~0.2% speed gain on Google Pixel.

Change-Id: Ia4a6ec904df670d7001e35e070b01e34149d23dc

--- a/vp9/encoder/vp9_skin_detection.c
+++ b/vp9/encoder/vp9_skin_detection.c
@@ -53,18 +53,22 @@
   const int fac = y_bsize / 8;
   const int y_shift = src_ystride * (mi_row << 3) + (mi_col << 3);
   const int uv_shift = src_uvstride * (mi_row << 2) + (mi_col << 2);
+  const int mi_row_limit = VPXMIN(mi_row + 8, cm->mi_rows - 2);
+  const int mi_col_limit = VPXMIN(mi_col + 8, cm->mi_cols - 2);
   src_y += y_shift;
   src_u += uv_shift;
   src_v += uv_shift;
 
-  for (i = mi_row; i < VPXMIN(mi_row + 7, cm->mi_rows - 1); i += fac) {
+  for (i = mi_row; i < mi_row_limit; i += fac) {
     num_bl = 0;
-    for (j = mi_col; j < VPXMIN(mi_col + 7, cm->mi_cols - 1); j += fac) {
+    for (j = mi_col; j < mi_col_limit; j += fac) {
       int consec_zeromv = 0;
       int bl_index = i * cm->mi_cols + j;
       int bl_index1 = bl_index + 1;
       int bl_index2 = bl_index + cm->mi_cols;
       int bl_index3 = bl_index2 + 1;
+      // Don't detect skin on the boundary.
+      if (i == 0 || j == 0) continue;
       if (bsize == BLOCK_8X8)
         consec_zeromv = cpi->consec_zero_mv[bl_index];
       else
@@ -83,6 +87,42 @@
     src_y += (src_ystride << shy) - (num_bl << shy);
     src_u += (src_uvstride << shuv) - (num_bl << shuv);
     src_v += (src_uvstride << shuv) - (num_bl << shuv);
+  }
+
+  // Remove isolated skin blocks (none of its neighbors are skin) and isolated
+  // non-skin blocks (all of its neighbors are skin).
+  // Skip 4 corner blocks which have only 3 neighbors to remove isolated skin
+  // blocks. Skip superblock borders to remove isolated non-skin blocks.
+  for (i = mi_row; i < mi_row_limit; i += fac) {
+    for (j = mi_col; j < mi_col_limit; j += fac) {
+      int bl_index = i * cm->mi_cols + j;
+      int num_neighbor = 0;
+      int mi, mj;
+      int non_skin_threshold = 8;
+      // Skip 4 corners.
+      if ((i == mi_row && (j == mi_col || j == mi_col_limit - fac)) ||
+          (i == mi_row_limit - fac && (j == mi_col || j == mi_col_limit - fac)))
+        continue;
+      // There are only 5 neighbors for non-skin blocks on the border.
+      if (i == mi_row || i == mi_row_limit - fac || j == mi_col ||
+          j == mi_col_limit - fac)
+        non_skin_threshold = 5;
+
+      for (mi = -fac; mi <= fac; mi += fac) {
+        for (mj = -fac; mj <= fac; mj += fac) {
+          if (i + mi >= mi_row && i + mi < mi_row_limit && j + mj >= mi_col &&
+              j + mj < mi_col_limit) {
+            int bl_neighbor_index = (i + mi) * cm->mi_cols + j + mj;
+            if (cpi->skin_map[bl_neighbor_index]) num_neighbor++;
+          }
+        }
+      }
+
+      if (cpi->skin_map[bl_index] && num_neighbor < 2)
+        cpi->skin_map[bl_index] = 0;
+      if (!cpi->skin_map[bl_index] && num_neighbor == non_skin_threshold)
+        cpi->skin_map[bl_index] = 1;
+    }
   }
 }