]> granicus.if.org Git - libvpx/commitdiff
Refactor ref mv stack system
authorJingning Han <jingning@google.com>
Sat, 12 Dec 2015 06:39:40 +0000 (22:39 -0800)
committerJingning Han <jingning@google.com>
Mon, 11 Jan 2016 20:39:29 +0000 (12:39 -0800)
This commit re-works the reference motion vector stack process
and make it support extended context set. It unifies reference
motion vector checking process for row and column scan, as well as
for single block scan.

Change-Id: I68c05cde93cf8b0ca2ef4d1523399f405bd0a337

vp10/common/blockd.h
vp10/common/mv.h
vp10/common/mvref_common.c
vp10/common/mvref_common.h

index 66e29d41b2dcfdc410703e4bf300e76f27693f74..7b951486bf36a2712c9426277bfa9eb20ac444bb 100644 (file)
@@ -83,6 +83,10 @@ typedef struct {
 
 typedef int8_t MV_REFERENCE_FRAME;
 
+#if CONFIG_REF_MV
+#define MODE_CTX_REF_FRAMES (MAX_REF_FRAMES + (ALTREF_FRAME - LAST_FRAME))
+#endif
+
 typedef struct {
   // Number of base colors for Y (0) and UV (1)
   uint8_t palette_size[2];
index 289c591ed8a37900f9bdce5a3ccf40acac0b1f4f..904d372f941854df32633c844cc007ed07f6feb4 100644 (file)
@@ -37,6 +37,7 @@ typedef struct mv32 {
 #if CONFIG_REF_MV
 typedef struct candidate_mv {
   int_mv this_mv;
+  int_mv comp_mv;
   int weight;
 } CANDIDATE_MV;
 #endif
index 319ef4a7eb42fd3271cab54f3df1292907fcd1c1..cd1ea38b659272a20e98c3358f59d9df4cbf7036 100644 (file)
 #include "vp10/common/mvref_common.h"
 
 #if CONFIG_REF_MV
-static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
-                             const int mi_row, const int mi_col, int block,
-                             const MV_REFERENCE_FRAME ref_frame,
-                             int row_offset,
-                             CANDIDATE_MV *ref_mv_stack,
-                             uint8_t *refmv_count) {
-  const TileInfo *const tile = &xd->tile;
-  int i;
-  uint8_t newmv_count = 0;
+static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
+                                    const MB_MODE_INFO *const candidate,
+                                    const MV_REFERENCE_FRAME rf[2],
+                                    uint8_t *refmv_count,
+                                    CANDIDATE_MV *ref_mv_stack,
+                                    int len, int block, int col) {
+  const int weight = len;
+  int index = 0, ref;
+  int newmv_count = 0;
+
+  if (rf[1] == NONE) {
+    // single reference frame
+    for (ref = 0; ref < 2; ++ref) {
+      if (candidate->ref_frame[ref] == rf[0]) {
+        int_mv this_refmv =
+            get_sub_block_mv(candidate_mi, ref, col, block);
+        for (index = 0; index < *refmv_count; ++index)
+          if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
+            break;
 
-  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
-    POSITION mi_pos;
-    mi_pos.row = row_offset;
-    mi_pos.col = i;
+        if (index < *refmv_count)
+          ref_mv_stack[index].weight += 2 * weight;
 
-    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
-      const MODE_INFO *const candidate_mi =
-          xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
-      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
-      const int len = VPXMIN(xd->n8_w,
-                             num_8x8_blocks_wide_lookup[candidate->sb_type]);
-      const int weight = len;
-      int index = 0, ref;
+        // Add a new item to the list.
+        if (index == *refmv_count) {
+          ref_mv_stack[index].this_mv = this_refmv;
+          ref_mv_stack[index].weight = 2 * weight;
+          ++(*refmv_count);
 
-      for (ref = 0; ref < 2; ++ref) {
-        if (candidate->ref_frame[ref] == ref_frame) {
-          int_mv this_refmv =
-              get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
+          if (candidate->mode == NEWMV)
+            ++newmv_count;
+        }
+
+        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
+          int alt_block = 3 - block;
+          this_refmv =
+              get_sub_block_mv(candidate_mi, ref, col, alt_block);
           for (index = 0; index < *refmv_count; ++index)
             if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
               break;
@@ -58,6 +67,89 @@ static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
           }
         }
       }
+    }
+  } else {
+    // compound reference frame
+    if (candidate->ref_frame[0] == rf[0] &&
+        candidate->ref_frame[1] == rf[1]) {
+      int_mv this_refmv[2] = {
+          get_sub_block_mv(candidate_mi, 0, col, block),
+          get_sub_block_mv(candidate_mi, 1, col, block)
+      };
+
+      for (index = 0; index < *refmv_count; ++index)
+        if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
+            (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
+          break;
+
+      if (index < *refmv_count)
+        ref_mv_stack[index].weight += 2 * weight;
+
+      // Add a new item to the list.
+      if (index == *refmv_count) {
+        ref_mv_stack[index].this_mv = this_refmv[0];
+        ref_mv_stack[index].comp_mv = this_refmv[1];
+        ref_mv_stack[index].weight = 2 * weight;
+        ++(*refmv_count);
+
+        if (candidate->mode == NEWMV)
+          ++newmv_count;
+      }
+
+      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
+        int alt_block = 3 - block;
+        this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
+        this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);
+
+        for (index = 0; index < *refmv_count; ++index)
+          if (ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int &&
+              ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int)
+            break;
+
+        if (index < *refmv_count)
+          ref_mv_stack[index].weight += weight;
+
+        // Add a new item to the list.
+        if (index == *refmv_count) {
+          ref_mv_stack[index].this_mv = this_refmv[0];
+          ref_mv_stack[index].comp_mv = this_refmv[1];
+          ref_mv_stack[index].weight = weight;
+          ++(*refmv_count);
+
+          if (candidate->mode == NEWMV)
+            ++newmv_count;
+        }
+      }
+    }
+  }
+  return newmv_count;
+}
+
+static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
+                             const int mi_row, const int mi_col, int block,
+                             const MV_REFERENCE_FRAME rf[2],
+                             int row_offset,
+                             CANDIDATE_MV *ref_mv_stack,
+                             uint8_t *refmv_count) {
+  const TileInfo *const tile = &xd->tile;
+  int i;
+  uint8_t newmv_count = 0;
+
+  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
+    POSITION mi_pos;
+    mi_pos.row = row_offset;
+    mi_pos.col = i;
+
+    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
+      const MODE_INFO *const candidate_mi =
+          xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
+      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
+      const int len = VPXMIN(xd->n8_w,
+                             num_8x8_blocks_wide_lookup[candidate->sb_type]);
+
+      newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
+                                          refmv_count, ref_mv_stack, len,
+                                          block, mi_pos.col);
       i += len;
     } else {
       ++i;
@@ -69,7 +161,7 @@ static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
 
 static uint8_t scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                              const int mi_row, const int mi_col, int block,
-                             const MV_REFERENCE_FRAME ref_frame,
+                             const MV_REFERENCE_FRAME rf[2],
                              int col_offset,
                              CANDIDATE_MV *ref_mv_stack,
                              uint8_t *refmv_count) {
@@ -88,30 +180,10 @@ static uint8_t scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
       const int len = VPXMIN(xd->n8_h,
                        num_8x8_blocks_high_lookup[candidate->sb_type]);
-      const int weight = len;
-      int index = 0, ref;
-
-      for (ref = 0; ref < 2; ++ref) {
-        if (candidate->ref_frame[ref] == ref_frame) {
-          int_mv this_refmv =
-              get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
-          for (index = 0; index < *refmv_count; ++index)
-            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
-              break;
 
-          if (index < *refmv_count)
-            ref_mv_stack[index].weight += weight;
-
-          if (index == *refmv_count) {
-            ref_mv_stack[index].this_mv = this_refmv;
-            ref_mv_stack[index].weight = weight;
-            ++(*refmv_count);
-
-            if (candidate->mode == NEWMV)
-              ++newmv_count;
-          }
-        }
-      }
+      newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
+                                          refmv_count, ref_mv_stack, len,
+                                          block, mi_pos.col);
       i += len;
     } else {
       ++i;
@@ -123,7 +195,7 @@ static uint8_t scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
 
 static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                              const int mi_row, const int mi_col, int block,
-                             const MV_REFERENCE_FRAME ref_frame,
+                             const MV_REFERENCE_FRAME rf[2],
                              int row_offset, int col_offset,
                              CANDIDATE_MV *ref_mv_stack,
                              uint8_t *refmv_count) {
@@ -140,49 +212,10 @@ static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
         xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
     const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     const int len = 1;
-    const int weight = len;
-    int index = 0, ref;
-
-    for (ref = 0; ref < 2; ++ref) {
-      if (candidate->ref_frame[ref] == ref_frame) {
-        int_mv this_refmv =
-            get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
-        for (index = 0; index < *refmv_count; ++index)
-          if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
-            break;
-
-        if (index < *refmv_count)
-          ref_mv_stack[index].weight += weight;
-
-        if (index == *refmv_count) {
-          ref_mv_stack[index].this_mv = this_refmv;
-          ref_mv_stack[index].weight = weight;
-          ++(*refmv_count);
-
-          if (candidate->mode == NEWMV)
-            ++newmv_count;
-        }
-
-        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
-          int alt_block = 3 - block;
-          this_refmv =
-              get_sub_block_mv(candidate_mi, ref, mi_pos.col, alt_block);
-          for (index = 0; index < *refmv_count; ++index)
-            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
-              break;
 
-          if (index < *refmv_count)
-            ref_mv_stack[index].weight += weight;
-
-          // Add a new item to the list.
-          if (index == *refmv_count) {
-            ref_mv_stack[index].this_mv = this_refmv;
-            ref_mv_stack[index].weight = weight;
-            ++(*refmv_count);
-          }
-        }
-      }
-    }
+    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
+                                        refmv_count, ref_mv_stack, len,
+                                        block, mi_pos.col);
   }  // Analyze a single 8x8 block motion information.
   return newmv_count;
 }
@@ -260,19 +293,22 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
   int bs = VPXMAX(xd->n8_w, xd->n8_h);
   int has_tr = has_top_right(xd, mi_row, mi_col, bs);
 
+  MV_REFERENCE_FRAME rf[2];
+  vp10_set_ref_frame(rf, ref_frame);
+
   mode_context[ref_frame] = 0;
   *refmv_count = 0;
 
   // Scan the first above row mode info.
-  newmv_count = scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  newmv_count = scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
                               -1, ref_mv_stack, refmv_count);
   // Scan the first left column mode info.
-  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
                                -1, ref_mv_stack, refmv_count);
 
   // Check top-right boundary
   if (has_tr)
-    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
                                  -1, 1, ref_mv_stack, refmv_count);
 
   nearest_refmv_count = *refmv_count;
@@ -301,12 +337,12 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                 break;
 
             if (idx < *refmv_count)
-              ref_mv_stack[idx].weight += 1;
+              ref_mv_stack[idx].weight += 2;
 
             if (idx == *refmv_count &&
                 *refmv_count < MAX_REF_MV_STACK_SIZE) {
               ref_mv_stack[idx].this_mv.as_int = prev_frame_mvs->mv[ref].as_int;
-              ref_mv_stack[idx].weight = 1;
+              ref_mv_stack[idx].weight = 2;
               ++(*refmv_count);
 
               if (abs(ref_mv_stack[idx].this_mv.as_mv.row) >= 8 ||
@@ -327,22 +363,22 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
 //                -1, -1, ref_mv_stack, refmv_count);
 
   // Scan the second outer area.
-  scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -2, ref_mv_stack, refmv_count);
-  scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -2, ref_mv_stack, refmv_count);
 
   // Scan the third outer area.
-  scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -3, ref_mv_stack, refmv_count);
-  scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -3, ref_mv_stack, refmv_count);
 
   // Scan the fourth outer area.
-  scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -4, ref_mv_stack, refmv_count);
   // Scan the third left row mode info.
-  scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
+  scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -4, ref_mv_stack, refmv_count);
 
   switch (nearest_refmv_count) {
@@ -630,6 +666,7 @@ void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
   CANDIDATE_MV tmp_mv;
   uint8_t ref_mv_count = 0, idx;
   uint8_t above_count = 0, left_count = 0;
+  MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE };
 #endif
 
   assert(MAX_MV_REF_CANDIDATES == 2);
@@ -638,11 +675,11 @@ void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
                    mi_row, mi_col, NULL, NULL, NULL);
 
 #if CONFIG_REF_MV
-  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, mi->mbmi.ref_frame[ref],
+  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 -1, 0, ref_mv_stack, &ref_mv_count);
   above_count = ref_mv_count;
 
-  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, mi->mbmi.ref_frame[ref],
+  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
                 0, -1, ref_mv_stack, &ref_mv_count);
   left_count = ref_mv_count - above_count;
 
index 39684690642186759ddfaa9feaf00ac64fc6fe83..1f388c19e4e29529fe6d540b19a02f6682a74694 100644 (file)
@@ -196,6 +196,24 @@ static INLINE int is_inside(const TileInfo *const tile,
 }
 
 #if CONFIG_REF_MV
+static int8_t vp10_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
+  if (rf[1] > INTRA_FRAME)
+    return rf[0] + ALTREF_FRAME;
+
+  return rf[0];
+}
+
+static void vp10_set_ref_frame(MV_REFERENCE_FRAME *rf, int8_t ref_frame_type) {
+  if (ref_frame_type > ALTREF_FRAME) {
+    rf[0] = ref_frame_type - ALTREF_FRAME;
+    rf[1] = ALTREF_FRAME;
+  } else {
+    rf[0] = ref_frame_type;
+    rf[1] = NONE;
+    assert(ref_frame_type > INTRA_FRAME && ref_frame_type < MAX_REF_FRAMES);
+  }
+}
+
 static int16_t vp10_mode_context_analyzer(const int16_t *const mode_context,
                                           const MV_REFERENCE_FRAME *const rf,
                                           BLOCK_SIZE bsize, int block) {