Add new compound modes using single reference
The hookup with the encoder-decoder pipeline will be in the following
CLs. This is under the experiment of compound-singleref, with ext-
inter enabled.
Change-Id: I6523a1a6525539eb7c6aa6c5e11724a694e8bf6c
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 8f7761e..86a068e 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -119,7 +119,11 @@
static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWMV;
}
-
+#if CONFIG_COMPOUND_SINGLEREF
+static INLINE int is_inter_singleref_comp_mode(PREDICTION_MODE mode) {
+ return mode >= SR_NEAREST_NEARMV && mode <= SR_NEW_NEWMV;
+}
+#endif // CONFIG_COMPOUND_SINGLEREF
static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) {
return mode >= NEAREST_NEARESTMV && mode <= NEW_NEWMV;
}
@@ -143,16 +147,23 @@
MB_MODE_COUNT, // NEARMV
MB_MODE_COUNT, // ZEROMV
MB_MODE_COUNT, // NEWMV
- NEARESTMV, // NEAREST_NEARESTMV
- NEARESTMV, // NEAREST_NEARMV
- NEARMV, // NEAR_NEARESTMV
- NEARMV, // NEAR_NEARMV
- NEARESTMV, // NEAREST_NEWMV
- NEWMV, // NEW_NEARESTMV
- NEARMV, // NEAR_NEWMV
- NEWMV, // NEW_NEARMV
- ZEROMV, // ZERO_ZEROMV
- NEWMV, // NEW_NEWMV
+#if CONFIG_COMPOUND_SINGLEREF
+ NEARESTMV, // SR_NEAREST_NEARMV
+ NEARESTMV, // SR_NEAREST_NEWMV
+ NEARMV, // SR_NEAR_NEWMV
+ ZEROMV, // SR_ZERO_NEWMV
+ NEWMV, // SR_NEW_NEWMV
+#endif // CONFIG_COMPOUND_SINGLEREF
+ NEARESTMV, // NEAREST_NEARESTMV
+ NEARESTMV, // NEAREST_NEARMV
+ NEARMV, // NEAR_NEARESTMV
+ NEARMV, // NEAR_NEARMV
+ NEARESTMV, // NEAREST_NEWMV
+ NEWMV, // NEW_NEARESTMV
+ NEARMV, // NEAR_NEWMV
+ NEWMV, // NEW_NEARMV
+ ZEROMV, // ZERO_ZEROMV
+ NEWMV, // NEW_NEWMV
};
assert(is_inter_compound_mode(mode));
return lut[mode];
@@ -177,16 +188,23 @@
MB_MODE_COUNT, // NEARMV
MB_MODE_COUNT, // ZEROMV
MB_MODE_COUNT, // NEWMV
- NEARESTMV, // NEAREST_NEARESTMV
- NEARMV, // NEAREST_NEARMV
- NEARESTMV, // NEAR_NEARESTMV
- NEARMV, // NEAR_NEARMV
- NEWMV, // NEAREST_NEWMV
- NEARESTMV, // NEW_NEARESTMV
- NEWMV, // NEAR_NEWMV
- NEARMV, // NEW_NEARMV
- ZEROMV, // ZERO_ZEROMV
- NEWMV, // NEW_NEWMV
+#if CONFIG_COMPOUND_SINGLEREF
+ NEARMV, // SR_NEAREST_NEARMV
+ NEWMV, // SR_NEAREST_NEWMV
+ NEWMV, // SR_NEAR_NEWMV
+ NEWMV, // SR_ZERO_NEWMV
+ NEWMV, // SR_NEW_NEWMV
+#endif // CONFIG_COMPOUND_SINGLEREF
+ NEARESTMV, // NEAREST_NEARESTMV
+ NEARMV, // NEAREST_NEARMV
+ NEARESTMV, // NEAR_NEARESTMV
+ NEARMV, // NEAR_NEARMV
+ NEWMV, // NEAREST_NEWMV
+ NEARESTMV, // NEW_NEARESTMV
+ NEWMV, // NEAR_NEWMV
+ NEARMV, // NEW_NEARMV
+ ZEROMV, // ZERO_ZEROMV
+ NEWMV, // NEW_NEWMV
};
assert(is_inter_compound_mode(mode));
return lut[mode];
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index d3568d6..0fcf762 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -772,6 +772,21 @@
{ 25, 29, 50, 192, 64, 192, 128, 180, 180 }, // 6 = two intra neighbours
};
+#if CONFIG_COMPOUND_SINGLEREF
+// TODO(zoeliu): Default values to be further adjusted based on the collected
+// stats.
+static const aom_prob default_inter_singleref_comp_mode_probs
+ [INTER_MODE_CONTEXTS][INTER_SINGLEREF_COMP_MODES - 1] = {
+ { 2, 173, 68, 180 }, // 0 = both zero mv
+ { 7, 145, 160, 180 }, // 1 = 1 zero + 1 predicted
+ { 7, 166, 126, 180 }, // 2 = two predicted mvs
+ { 7, 94, 132, 180 }, // 3 = 1 pred/zero, 1 new
+ { 8, 64, 64, 180 }, // 4 = two new mvs
+ { 17, 81, 52, 180 }, // 5 = one intra neighbour
+ { 25, 29, 50, 180 }, // 6 = two intra neighbours
+ };
+#endif // CONFIG_COMPOUND_SINGLEREF
+
#if CONFIG_COMPOUND_SEGMENT && CONFIG_WEDGE
static const aom_prob
default_compound_type_probs[BLOCK_SIZES][COMPOUND_TYPES - 1] = {
@@ -992,6 +1007,17 @@
-INTER_COMPOUND_OFFSET(NEAR_NEWMV), -INTER_COMPOUND_OFFSET(NEW_NEARMV)
};
+#if CONFIG_COMPOUND_SINGLEREF
+const aom_tree_index av1_inter_singleref_comp_mode_tree
+ [TREE_SIZE(INTER_SINGLEREF_COMP_MODES)] = {
+ -INTER_SINGLEREF_COMP_OFFSET(SR_ZERO_NEWMV), 2,
+ -INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEARMV), 4,
+ 6, -INTER_SINGLEREF_COMP_OFFSET(SR_NEW_NEWMV),
+ -INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEWMV),
+ -INTER_SINGLEREF_COMP_OFFSET(SR_NEAR_NEWMV)
+};
+#endif // CONFIG_COMPOUND_SINGLEREF
+
#if CONFIG_COMPOUND_SEGMENT && CONFIG_WEDGE
const aom_tree_index av1_compound_type_tree[TREE_SIZE(COMPOUND_TYPES)] = {
-COMPOUND_AVERAGE, 2, -COMPOUND_WEDGE, -COMPOUND_SEG
@@ -1066,6 +1092,14 @@
#endif // CONFIG_EXT_REFS
};
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+// TODO(zoeliu): Default values to be further adjusted based on the collected
+// stats.
+static const aom_prob default_comp_inter_mode_p[COMP_INTER_MODE_CONTEXTS] = {
+ 41, 119, 187, 225
+};
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+
#if CONFIG_PALETTE
// Tree to code palette size (number of colors in a palette) and the
@@ -3226,6 +3260,9 @@
av1_copy(fc->comp_bwdref_prob, default_comp_bwdref_p);
#endif // CONFIG_EXT_REFS
av1_copy(fc->single_ref_prob, default_single_ref_p);
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+ av1_copy(fc->comp_inter_mode_prob, default_comp_inter_mode_p);
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
av1_copy(fc->tx_size_probs, default_tx_size_prob);
#if CONFIG_VAR_TX
av1_copy(fc->txfm_partition_prob, default_txfm_partition_probs);
@@ -3246,6 +3283,10 @@
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
av1_copy(fc->inter_compound_mode_probs, default_inter_compound_mode_probs);
+#if CONFIG_COMPOUND_SINGLEREF
+ av1_copy(fc->inter_singleref_comp_mode_probs,
+ default_inter_singleref_comp_mode_probs);
+#endif // CONFIG_COMPOUND_SINGLEREF
av1_copy(fc->compound_type_prob, default_compound_type_probs);
av1_copy(fc->interintra_prob, default_interintra_prob);
av1_copy(fc->interintra_mode_prob, default_interintra_mode_prob);
@@ -3420,6 +3461,7 @@
for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
fc->intra_inter_prob[i] = av1_mode_mv_merge_probs(
pre_fc->intra_inter_prob[i], counts->intra_inter[i]);
+
for (i = 0; i < COMP_INTER_CONTEXTS; i++)
fc->comp_inter_prob[i] = av1_mode_mv_merge_probs(pre_fc->comp_inter_prob[i],
counts->comp_inter[i]);
@@ -3445,6 +3487,13 @@
fc->single_ref_prob[i][j] = av1_mode_mv_merge_probs(
pre_fc->single_ref_prob[i][j], counts->single_ref[i][j]);
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+ for (i = 0; i < COMP_INTER_MODE_CONTEXTS; i++)
+ fc->comp_inter_mode_prob[i] = av1_mode_mv_merge_probs(
+ pre_fc->comp_inter_mode_prob[i], counts->comp_inter_mode[i]);
+
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+
#if CONFIG_REF_MV
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
fc->newmv_prob[i] =
@@ -3490,6 +3539,13 @@
aom_tree_merge_probs(
av1_inter_compound_mode_tree, pre_fc->inter_compound_mode_probs[i],
counts->inter_compound_mode[i], fc->inter_compound_mode_probs[i]);
+#if CONFIG_COMPOUND_SINGLEREF
+ for (i = 0; i < INTER_MODE_CONTEXTS; i++)
+ aom_tree_merge_probs(av1_inter_singleref_comp_mode_tree,
+ pre_fc->inter_singleref_comp_mode_probs[i],
+ counts->inter_singleref_comp_mode[i],
+ fc->inter_singleref_comp_mode_probs[i]);
+#endif // CONFIG_COMPOUND_SINGLEREF
for (i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
if (is_interintra_allowed_bsize_group(i))
fc->interintra_prob[i] = av1_mode_mv_merge_probs(
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 71be25f..9c3a78d 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -34,6 +34,9 @@
#define INTER_OFFSET(mode) ((mode)-NEARESTMV)
#if CONFIG_EXT_INTER
+#if CONFIG_COMPOUND_SINGLEREF
+#define INTER_SINGLEREF_COMP_OFFSET(mode) ((mode)-SR_NEAREST_NEARMV)
+#endif // CONFIG_COMPOUND_SINGLEREF
#define INTER_COMPOUND_OFFSET(mode) ((mode)-NEAREST_NEARESTMV)
#endif // CONFIG_EXT_INTER
@@ -193,6 +196,10 @@
#if CONFIG_EXT_INTER
aom_prob inter_compound_mode_probs[INTER_MODE_CONTEXTS]
[INTER_COMPOUND_MODES - 1];
+#if CONFIG_COMPOUND_SINGLEREF
+ aom_prob inter_singleref_comp_mode_probs[INTER_MODE_CONTEXTS]
+ [INTER_SINGLEREF_COMP_MODES - 1];
+#endif // CONFIG_COMPOUND_SINGLEREF
aom_prob compound_type_prob[BLOCK_SIZES][COMPOUND_TYPES - 1];
aom_prob interintra_prob[BLOCK_SIZE_GROUPS];
aom_prob interintra_mode_prob[BLOCK_SIZE_GROUPS][INTERINTRA_MODES - 1];
@@ -213,6 +220,9 @@
#else
aom_prob comp_ref_prob[REF_CONTEXTS][COMP_REFS - 1];
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+ aom_prob comp_inter_mode_prob[COMP_INTER_MODE_CONTEXTS];
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
aom_prob tx_size_probs[MAX_TX_DEPTH][TX_SIZE_CONTEXTS][MAX_TX_DEPTH];
#if CONFIG_VAR_TX
aom_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS];
@@ -360,6 +370,10 @@
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
#if CONFIG_EXT_INTER
unsigned int inter_compound_mode[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES];
+#if CONFIG_COMPOUND_SINGLEREF
+ unsigned int inter_singleref_comp_mode[INTER_MODE_CONTEXTS]
+ [INTER_SINGLEREF_COMP_MODES];
+#endif // CONFIG_COMPOUND_SINGLEREF
unsigned int interintra[BLOCK_SIZE_GROUPS][2];
unsigned int interintra_mode[BLOCK_SIZE_GROUPS][INTERINTRA_MODES];
unsigned int wedge_interintra[BLOCK_SIZES][2];
@@ -380,6 +394,9 @@
#else
unsigned int comp_ref[REF_CONTEXTS][COMP_REFS - 1][2];
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+ unsigned int comp_inter_mode[COMP_INTER_MODE_CONTEXTS][2];
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
// TODO(any): tx_size_totals is only used by the encoder to decide whether
// to use forward updates for the coeff probs, and as such it does not really
// belong into this structure.
@@ -475,6 +492,10 @@
av1_interintra_mode_tree[TREE_SIZE(INTERINTRA_MODES)];
extern const aom_tree_index
av1_inter_compound_mode_tree[TREE_SIZE(INTER_COMPOUND_MODES)];
+#if CONFIG_COMPOUND_SINGLEREF
+extern const aom_tree_index
+ av1_inter_singleref_comp_mode_tree[TREE_SIZE(INTER_SINGLEREF_COMP_MODES)];
+#endif // CONFIG_COMPOUND_SINGLEREF
extern const aom_tree_index av1_compound_type_tree[TREE_SIZE(COMPOUND_TYPES)];
#endif // CONFIG_EXT_INTER
extern const aom_tree_index av1_partition_tree[TREE_SIZE(PARTITION_TYPES)];
diff --git a/av1/common/enums.h b/av1/common/enums.h
index b684eb0..6f00635 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -321,6 +321,15 @@
ZEROMV,
NEWMV,
#if CONFIG_EXT_INTER
+#if CONFIG_COMPOUND_SINGLEREF
+ // Single ref compound modes
+ SR_NEAREST_NEARMV,
+ SR_NEAREST_NEWMV,
+ SR_NEAR_NEWMV,
+ SR_ZERO_NEWMV,
+ SR_NEW_NEWMV,
+#endif // CONFIG_COMPOUND_SINGLEREF
+ // Compound ref compound modes
NEAREST_NEARESTMV,
NEAREST_NEARMV,
NEAR_NEARESTMV,
@@ -401,6 +410,10 @@
#define INTER_MODES (1 + NEWMV - NEARESTMV)
#if CONFIG_EXT_INTER
+#if CONFIG_COMPOUND_SINGLEREF
+#define INTER_SINGLEREF_COMP_MODES (1 + SR_NEW_NEWMV - SR_NEAREST_NEARMV)
+#endif // CONFIG_COMPOUND_SINGLEREF
+
#define INTER_COMPOUND_MODES (1 + NEW_NEWMV - NEAREST_NEARESTMV)
#endif // CONFIG_EXT_INTER
@@ -454,6 +467,9 @@
#define INTRA_INTER_CONTEXTS 4
#define COMP_INTER_CONTEXTS 5
#define REF_CONTEXTS 5
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+#define COMP_INTER_MODE_CONTEXTS 4
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if CONFIG_VAR_TX
#define TXFM_PARTITION_CONTEXTS ((TX_SIZES - TX_8X8) * 6 - 2)
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index 7c1161d..01f74b7 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -64,6 +64,13 @@
3, // ZEROMV
1, // NEWMV
#if CONFIG_EXT_INTER
+#if CONFIG_COMPOUND_SINGLEREF
+ 0, // SR_NEAREST_NEARMV
+ 1, // SR_NEAREST_NEWMV
+ 1, // SR_NEAR_NEWMV
+ 3, // SR_ZERO_NEWMV
+ 1, // SR_NEW_NEWMV
+#endif // CONFIG_COMPOUND_SINGLEREF
0, // NEAREST_NEARESTMV
0, // NEAREST_NEARMV
0, // NEAR_NEARESTMV
diff --git a/av1/common/pred_common.c b/av1/common/pred_common.c
index f8041f8..e139e14 100644
--- a/av1/common/pred_common.c
+++ b/av1/common/pred_common.c
@@ -177,6 +177,35 @@
}
}
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+// The compound/single mode info data structure has one element border above and
+// to the left of the entries corresponding to real macroblocks.
+// The prediction flags in these dummy entries are initialized to 0.
+// 0 - single/single
+// 1 - single/--, --/single, --/--
+// 2 - single/comp, comp/single
+// 3 - comp/comp, comp/--, --/comp
+int av1_get_inter_mode_context(const MACROBLOCKD *xd) {
+ const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
+ const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
+ const int has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ if (has_above && has_left) { // both edges available (0/2/3)
+ const int above_inter_comp_mode = is_inter_compound_mode(above_mbmi->mode);
+ const int left_inter_comp_mode = is_inter_compound_mode(left_mbmi->mode);
+ return (above_inter_comp_mode && left_inter_comp_mode)
+ ? 3
+ : (above_inter_comp_mode || left_inter_comp_mode) * 2;
+ } else if (has_above || has_left) { // one edge available (1/3)
+ const MB_MODE_INFO *const edge_mbmi = has_above ? above_mbmi : left_mbmi;
+ return is_inter_compound_mode(edge_mbmi->mode) ? 3 : 1;
+ } else { // no edge available (1)
+ return 1;
+ }
+}
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+
#if CONFIG_EXT_REFS
#define CHECK_BACKWARD_REFS(ref_frame) \
(((ref_frame) >= BWDREF_FRAME) && ((ref_frame) <= ALTREF_FRAME))
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h
index 7825f3c..e16ad70 100644
--- a/av1/common/pred_common.h
+++ b/av1/common/pred_common.h
@@ -168,6 +168,15 @@
}
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+int av1_get_inter_mode_context(const MACROBLOCKD *xd);
+
+static INLINE aom_prob av1_get_inter_mode_prob(const AV1_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ return cm->fc->comp_inter_mode_prob[av1_get_inter_mode_context(xd)];
+}
+#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
+
// Returns a context number for the given MB prediction signal
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real blocks.