Further work on ext-comp-refs for ref frame coding
(1) Work with var-refs to remove redundant bits in ref frame
coding;
(2) Add a new uni-directional compound reference pair:
(LAST_FRAME, LAST3_FRAME);
(3) Redesign the contexts for encoding uni-directional reference frame
pairs;
(4) Use aom_entropy_optimizer to collect stats for all the default
probability setups related to the coding of reference frames.
Compared against the baseline (default enabled tools excluding ext-tx
and global-motion for encoder speed concern) with one-sided-compound,
the coding gain of ext-comp-refs + var-refs - one-sided-compound is:
lowres: avg_psnr -0.385%; ovr_psnr -0.378% ssim -0.344%
midres: avg_psnr -0.466%; ovr_psnr -0.447% ssim -0.513%
AWCY - High Latency:
PSNR | PSNR Cb | PSNR Cr | PSNR HVS | SSIM | MS SSIM | CIEDE 2000
-0.2758 | -0.1526 | -0.0965 | -0.2581 | -0.2492 | -0.2534 | -0.2118
AWCY - Low Latency:
PSNR | PSNR Cb | PSNR Cr | PSNR HVS | SSIM | MS SSIM | CIEDE 2000
-1.0467 | -1.4500 | -0.9732 | -0.9928 | -1.0407 | -1.0180 | -1.0049
Compared against the baseline (default enabled tools excluding ext-tx
and global-motion for encoder speed concern) without
one-sided-compound, the coding gain of
ext-comp-refs + var-refs - one-sided-compound is:
lowres: avg_psnr -0.875%; ovr_psnr -0.877% ssim -0.895%
midres: avg_psnr -0.824%; ovr_psnr -0.802% ssim -0.843%
Change-Id: I8de774c9a74c20632ea93ccb0c17779fa94431cb
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 6bf892a..bfdf48b 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -518,6 +518,7 @@
static INLINE MV_REFERENCE_FRAME comp_ref0(int ref_idx) {
static const MV_REFERENCE_FRAME lut[] = {
LAST_FRAME, // LAST_LAST2_FRAMES,
+ LAST_FRAME, // LAST_LAST3_FRAMES,
LAST_FRAME, // LAST_GOLDEN_FRAMES,
BWDREF_FRAME, // BWDREF_ALTREF_FRAMES,
};
@@ -528,6 +529,7 @@
static INLINE MV_REFERENCE_FRAME comp_ref1(int ref_idx) {
static const MV_REFERENCE_FRAME lut[] = {
LAST2_FRAME, // LAST_LAST2_FRAMES,
+ LAST3_FRAME, // LAST_LAST3_FRAMES,
GOLDEN_FRAME, // LAST_GOLDEN_FRAMES,
ALTREF_FRAME, // BWDREF_ALTREF_FRAMES,
};
@@ -621,8 +623,6 @@
YV12_BUFFER_CONFIG *buf;
struct scale_factors sf;
#if CONFIG_VAR_REFS
- // TODO(zoeliu): To evaluate whether "is_valid" is needed or the use of it can
- // be simply replaced by checking the "idx".
int is_valid;
#endif // CONFIG_VAR_REFS
} RefBuffer;
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index bc88555..5c0ea7b 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -1040,44 +1040,94 @@
#endif
static const aom_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
- 216, 170, 131, 92, 42,
+#if !CONFIG_EXT_COMP_REFS
+ 216, 170, 131, 92, 42
+#else // CONFIG_EXT_COMP_REFS
+ 206, 182, 117, 104, 32
+#endif // !CONFIG_EXT_COMP_REFS
};
+
#if CONFIG_NEW_MULTISYMBOL
-static const aom_cdf_prob default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(
- 2)] = { { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
- { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 },
- { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
- { AOM_ICDF(92 * 128), AOM_ICDF(32768), 0 },
- { AOM_ICDF(42 * 128), AOM_ICDF(32768), 0 } };
-#endif
+static const aom_cdf_prob
+ default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)] = {
+#if !CONFIG_EXT_COMP_REFS
+ { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(92 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(42 * 128), AOM_ICDF(32768), 0 }
+#else // CONFIG_EXT_COMP_REFS
+ { AOM_ICDF(206 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(182 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(117 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(104 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(32 * 128), AOM_ICDF(32768), 0 }
+#endif // !CONFIG_EXT_COMP_REFS
+ };
+#endif // CONFIG_NEW_MULTISYMBOL
#if CONFIG_EXT_COMP_REFS
static const aom_prob default_comp_ref_type_p[COMP_REF_TYPE_CONTEXTS] = {
- 30, 75, 120, 170, 230
+ 8, 20, 78, 91, 194
};
-
static const aom_prob
default_uni_comp_ref_p[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1] = {
- { 30, 20 }, { 75, 70 }, { 130, 130 }, { 165, 165 }, { 215, 220 }
+ { 88, 30, 28 }, { 218, 97, 105 }, { 254, 180, 196 }
};
+
+#if CONFIG_NEW_MULTISYMBOL
+static const aom_cdf_prob
+ default_comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_ICDF(8 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(20 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(78 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(91 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(194 * 128), AOM_ICDF(32768), 0 }
+ };
+static const aom_cdf_prob
+ default_uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
+ [CDF_SIZE(2)] = {
+ { { AOM_ICDF(88 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(30 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(28 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(218 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(97 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(105 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(254 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(180 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(196 * 128), AOM_ICDF(32768), 0 } }
+ };
+#endif // CONFIG_NEW_MULTISYMBOL
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_REFS
static const aom_prob default_comp_ref_p[REF_CONTEXTS][FWD_REFS - 1] = {
- // TODO(zoeliu): To adjust the initial prob values.
+#if !CONFIG_EXT_COMP_REFS
{ 33, 16, 16 },
{ 77, 74, 74 },
{ 142, 142, 142 },
{ 172, 170, 170 },
{ 238, 247, 247 }
+#else // CONFIG_EXT_COMP_REFS
+ { 21, 7, 5 },
+ { 68, 20, 16 },
+ { 128, 56, 36 },
+ { 197, 111, 139 },
+ { 238, 131, 136 }
+#endif // !CONFIG_EXT_COMP_REFS
};
static const aom_prob default_comp_bwdref_p[REF_CONTEXTS][BWD_REFS - 1] = {
+#if !CONFIG_EXT_COMP_REFS
{ 16 }, { 74 }, { 142 }, { 170 }, { 247 }
+#else // CONFIG_EXT_COMP_REFS
+ { 7 }, { 56 }, { 29 }, { 230 }, { 220 }
+#endif // CONFIG_EXT_COMP_REFS
};
+
#if CONFIG_NEW_MULTISYMBOL
static const aom_cdf_prob
default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = {
- // TODO(zoeliu): To adjust the initial prob values.
+#if !CONFIG_EXT_COMP_REFS
{ { AOM_ICDF(33 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
@@ -1093,17 +1143,42 @@
{ { AOM_ICDF(238 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
+#else // CONFIG_EXT_COMP_REFS
+ { { AOM_ICDF(21 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(7 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(5 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(68 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(20 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(128 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(56 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(36 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(197 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(111 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(139 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(238 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(136 * 128), AOM_ICDF(32768), 0 } }
+#endif // !CONFIG_EXT_COMP_REFS
};
static const aom_cdf_prob
default_comp_bwdref_cdf[REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = {
+#if !CONFIG_EXT_COMP_REFS
{ { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
{ { AOM_ICDF(74 * 128), AOM_ICDF(32768), 0 } },
{ { AOM_ICDF(142 * 128), AOM_ICDF(32768), 0 } },
{ { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 } },
{ { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
+#else // CONFIG_EXT_COMP_REFS
+ { { AOM_ICDF(7 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(56 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(29 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(230 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(220 * 128), AOM_ICDF(32768), 0 } }
+#endif // !CONFIG_EXT_COMP_REFS
};
#endif // CONFIG_NEW_MULTISYMBOL
-#else
+#else // !CONFIG_EXT_REFS
static const aom_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
{ 43 }, { 100 }, { 137 }, { 212 }, { 229 },
};
@@ -1121,19 +1196,29 @@
static const aom_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
#if CONFIG_EXT_REFS
+#if !CONFIG_EXT_COMP_REFS
{ 33, 16, 16, 16, 16 },
{ 77, 74, 74, 74, 74 },
{ 142, 142, 142, 142, 142 },
{ 172, 170, 170, 170, 170 },
{ 238, 247, 247, 247, 247 }
-#else
+#else // CONFIG_EXT_COMP_REFS
+ { 36, 2, 28, 58, 9 },
+ { 64, 22, 60, 122, 40 },
+ { 153, 69, 126, 179, 71 },
+ { 128, 174, 189, 216, 101 },
+ { 233, 252, 228, 246, 200 }
+#endif // !CONFIG_EXT_COMP_REFS
+#else // !CONFIG_EXT_REFS
{ 31, 25 }, { 72, 80 }, { 147, 148 }, { 197, 191 }, { 235, 247 },
#endif // CONFIG_EXT_REFS
};
+
#if CONFIG_NEW_MULTISYMBOL
static const aom_cdf_prob
default_single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)] = {
#if CONFIG_EXT_REFS
+#if !CONFIG_EXT_COMP_REFS
{ { AOM_ICDF(33 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
@@ -1159,7 +1244,34 @@
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
-#else
+#else // CONFIG_EXT_COMP_REFS
+ { { AOM_ICDF(36 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(2 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(28 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(58 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(9 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(64 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(22 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(60 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(122 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(40 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(153 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(69 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(126 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(179 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(71 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(128 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(174 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(189 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(101 * 128), AOM_ICDF(32768), 0 } },
+ { { AOM_ICDF(233 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(252 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(228 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(246 * 128), AOM_ICDF(32768), 0 },
+ { AOM_ICDF(200 * 128), AOM_ICDF(32768), 0 } }
+#endif // !CONFIG_EXT_COMP_REFS
+#else // CONFIG_EXT_REFS
{ { AOM_ICDF(31 * 128), AOM_ICDF(32768), 0 },
{ AOM_ICDF(25 * 128), AOM_ICDF(32768), 0 } },
{ { AOM_ICDF(72 * 128), AOM_ICDF(32768), 0 },
@@ -1172,7 +1284,7 @@
{ AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
#endif // CONFIG_EXT_REFS
};
-#endif
+#endif // CONFIG_NEW_MULTISYMBOL
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): Default values to be further adjusted based on the collected
@@ -4560,6 +4672,10 @@
#if CONFIG_EXT_COMP_REFS
av1_copy(fc->comp_ref_type_prob, default_comp_ref_type_p);
av1_copy(fc->uni_comp_ref_prob, default_uni_comp_ref_p);
+#if CONFIG_NEW_MULTISYMBOL
+ av1_copy(fc->comp_ref_type_cdf, default_comp_ref_type_cdf);
+ av1_copy(fc->uni_comp_ref_cdf, default_uni_comp_ref_cdf);
+#endif // CONFIG_NEW_MULTISYMBOL
#endif // CONFIG_EXT_COMP_REFS
av1_copy(fc->comp_ref_prob, default_comp_ref_p);
#if CONFIG_NEW_MULTISYMBOL
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 18d4aa2..5036ac0 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -248,6 +248,11 @@
#if CONFIG_EXT_COMP_REFS
aom_prob comp_ref_type_prob[COMP_REF_TYPE_CONTEXTS];
aom_prob uni_comp_ref_prob[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1];
+#if CONFIG_NEW_MULTISYMBOL
+ aom_cdf_prob comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)];
+ aom_cdf_prob uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
+ [CDF_SIZE(2)];
+#endif // CONFIG_NEW_MULTISYMBOL
#endif // CONFIG_EXT_COMP_REFS
aom_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS - 1];
#if CONFIG_EXT_REFS
diff --git a/av1/common/enums.h b/av1/common/enums.h
index 1b59ce0..bd1ba7c 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -532,7 +532,7 @@
#if CONFIG_EXT_COMP_REFS
#define COMP_REF_TYPE_CONTEXTS 5
-#define UNI_COMP_REF_CONTEXTS 5
+#define UNI_COMP_REF_CONTEXTS 3
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
@@ -577,6 +577,7 @@
#if CONFIG_EXT_COMP_REFS
typedef enum {
LAST_LAST2_FRAMES, // { LAST_FRAME, LAST2_FRAME }
+ LAST_LAST3_FRAMES, // { LAST_FRAME, LAST3_FRAME }
LAST_GOLDEN_FRAMES, // { LAST_FRAME, GOLDEN_FRAME }
BWDREF_ALTREF_FRAMES, // { BWDREF_FRAME, ALTREF_FRAME }
UNIDIR_COMP_REFS
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index acba436..63318f4 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -289,8 +289,8 @@
// TODO(zoeliu): Temporarily disable uni-directional comp refs
#if CONFIG_EXT_COMP_REFS
- , { LAST_FRAME, LAST2_FRAME }, { LAST_FRAME, GOLDEN_FRAME },
- { BWDREF_FRAME, ALTREF_FRAME }
+ , { LAST_FRAME, LAST2_FRAME }, { LAST_FRAME, LAST3_FRAME },
+ { LAST_FRAME, GOLDEN_FRAME }, { BWDREF_FRAME, ALTREF_FRAME }
#endif // CONFIG_EXT_COMP_REFS
#else // !CONFIG_EXT_REFS
{ LAST_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME }
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 6133edf..61574dd 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -522,6 +522,8 @@
#define L_OR_L2(cm) (LAST_IS_VALID(cm) || LAST2_IS_VALID(cm))
#define L_AND_L2(cm) (LAST_IS_VALID(cm) && LAST2_IS_VALID(cm))
+#define L_AND_L3(cm) (LAST_IS_VALID(cm) && LAST3_IS_VALID(cm))
+#define L_AND_G(cm) (LAST_IS_VALID(cm) && GOLDEN_IS_VALID(cm))
#define L3_OR_G(cm) (LAST3_IS_VALID(cm) || GOLDEN_IS_VALID(cm))
#define L3_AND_G(cm) (LAST3_IS_VALID(cm) && GOLDEN_IS_VALID(cm))
diff --git a/av1/common/pred_common.c b/av1/common/pred_common.c
index 01e7f41..4b98a8c 100644
--- a/av1/common/pred_common.c
+++ b/av1/common/pred_common.c
@@ -263,6 +263,9 @@
#define IS_BACKWARD_REF_FRAME(ref_frame) ((ref_frame) == cm->comp_fixed_ref)
#endif // CONFIG_EXT_REFS
+#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
+ (((ref_frame) == GOLDEN_FRAME) || ((ref_frame) == LAST3_FRAME))
+
int av1_get_reference_mode_context(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
int ctx;
@@ -313,16 +316,15 @@
#if CONFIG_EXT_COMP_REFS
#define CHECK_BWDREF_OR_ALTREF(ref_frame) \
((ref_frame) == BWDREF_FRAME || (ref_frame) == ALTREF_FRAME)
-int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
- const MACROBLOCKD *xd) {
+// TODO(zoeliu): To try on the design of 3 contexts, instead of 5:
+// COMP_REF_TYPE_CONTEXTS = 3
+int av1_get_comp_reference_type_context(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
- (void)cm;
-
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
@@ -388,197 +390,165 @@
}
// Returns a context number for the given MB prediction signal
-// Signal the uni-directional compound reference frame pair as
-// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
+//
+// Signal the uni-directional compound reference frame pair as either
+// (BWDREF, ALTREF), or (LAST, LAST2) / (LAST, LAST3) / (LAST, GOLDEN),
// conditioning on the pair is known as uni-directional.
-int av1_get_pred_context_uni_comp_ref_p(const AV1_COMMON *cm,
- const MACROBLOCKD *xd) {
+//
+// 3 contexts: Voting is used to compare the count of forward references with
+// that of backward references from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
- (void)cm;
+ // Count of forward references (L, L2, L3, or G)
+ int frf_count = 0;
+ // Count of backward references (B or A)
+ int brf_count = 0;
- if (above_in_image && left_in_image) { // both edges available
- const int above_intra = !is_inter_block(above_mbmi);
- const int left_intra = !is_inter_block(left_mbmi);
-
- if (above_intra && left_intra) { // intra/intra
- pred_context = 2;
- } else if (above_intra || left_intra) { // intra/inter
- const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
-
- if (!has_second_ref(inter_mbmi)) { // single pred
- pred_context =
- 1 + 2 * (!CHECK_BWDREF_OR_ALTREF(inter_mbmi->ref_frame[0]));
- } else { // comp pred
- if (has_uni_comp_refs(inter_mbmi)) // comp unidir
- pred_context = 4 * (inter_mbmi->ref_frame[0] != BWDREF_FRAME);
- else // comp_bidir
- pred_context = 2;
- }
- } else { // inter/inter
- const int a_sg = !has_second_ref(above_mbmi);
- const int l_sg = !has_second_ref(left_mbmi);
- const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
- const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
-
- if (CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_BWDREF_OR_ALTREF(frfl)) {
- pred_context = 0;
- } else if (a_sg && l_sg) { // single/single
- pred_context = 2 + (!CHECK_BWDREF_OR_ALTREF(frfa) &&
- !CHECK_BWDREF_OR_ALTREF(frfl));
- } else if (l_sg || a_sg) { // single/comp
- const MV_REFERENCE_FRAME frfc = a_sg ? frfl : frfa;
- const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
- const int uni_rfc =
- a_sg ? has_uni_comp_refs(left_mbmi) : has_uni_comp_refs(above_mbmi);
-
- if (uni_rfc && (frfc == BWDREF_FRAME))
- pred_context = 1;
- else if (uni_rfc && (frfc == LAST_FRAME))
- pred_context = 3 + (!CHECK_BWDREF_OR_ALTREF(rfs));
- else if (CHECK_BWDREF_OR_ALTREF(rfs))
- pred_context = 2;
- else
- pred_context = 3;
- } else { // comp/comp
- const int a_uni_rfc = has_uni_comp_refs(above_mbmi);
- const int l_uni_rfc = has_uni_comp_refs(left_mbmi);
-
- if (a_uni_rfc && l_uni_rfc)
- pred_context = 2 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
- else if (a_uni_rfc || l_uni_rfc)
- pred_context = 1 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
- else
- pred_context = 2;
- }
+ if (above_in_image && is_inter_block(above_mbmi)) {
+ if (above_mbmi->ref_frame[0] <= GOLDEN_FRAME)
+ ++frf_count;
+ else
+ ++brf_count;
+ if (has_second_ref(above_mbmi)) {
+ if (above_mbmi->ref_frame[1] <= GOLDEN_FRAME)
+ ++frf_count;
+ else
+ ++brf_count;
}
- } else if (above_in_image || left_in_image) { // one edge available
- const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
-
- if (!is_inter_block(edge_mbmi)) { // intra
- pred_context = 2;
- } else { // inter
- if (!has_second_ref(edge_mbmi)) { // single pred
- pred_context =
- 1 + 2 * (!CHECK_BWDREF_OR_ALTREF(edge_mbmi->ref_frame[0]));
- } else { // comp pred
- if (has_uni_comp_refs(edge_mbmi)) // comp unidir
- pred_context = 4 * (edge_mbmi->ref_frame[0] != BWDREF_FRAME);
- else // comp bidir
- pred_context = 2;
- }
- }
- } else { // no edges available
- pred_context = 2;
}
+ if (left_in_image && is_inter_block(left_mbmi)) {
+ if (left_mbmi->ref_frame[0] <= GOLDEN_FRAME)
+ ++frf_count;
+ else
+ ++brf_count;
+ if (has_second_ref(left_mbmi)) {
+ if (left_mbmi->ref_frame[1] <= GOLDEN_FRAME)
+ ++frf_count;
+ else
+ ++brf_count;
+ }
+ }
+
+ pred_context =
+ (frf_count == brf_count) ? 1 : ((frf_count < brf_count) ? 0 : 2);
+
assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
+//
// Signal the uni-directional compound reference frame pair as
-// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
-// conditioning on the pair is known as uni-directional.
-#define CHECK_LAST2_OR_GOLDEN(ref_frame) \
- ((ref_frame) == LAST2_FRAME || (ref_frame) == GOLDEN_FRAME)
-int av1_get_pred_context_uni_comp_ref_p1(const AV1_COMMON *cm,
- const MACROBLOCKD *xd) {
+// either (LAST, LAST2), or (LAST, LAST3) / (LAST, GOLDEN),
+// conditioning on the pair is known as one of the above three.
+//
+// 3 contexts: Voting is used to compare the count of LAST2_FRAME with the
+// total count of LAST3/GOLDEN from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
- (void)cm;
+ // Count of LAST2
+ int last2_count = 0;
+ // Count of LAST3 or GOLDEN
+ int last3_or_gld_count = 0;
- if (above_in_image && left_in_image) { // both edges available
- const int above_intra = !is_inter_block(above_mbmi);
- const int left_intra = !is_inter_block(left_mbmi);
-
- if (above_intra && left_intra) { // intra/intra
- pred_context = 2;
- } else if (above_intra || left_intra) { // intra/inter
- const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
-
- if (!has_second_ref(inter_mbmi)) { // single pred
- if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[0]))
- pred_context = 1 + 2 * (inter_mbmi->ref_frame[0] == LAST2_FRAME);
- else
- pred_context = 2;
- } else { // comp pred
- if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[1]))
- pred_context = 4 * (inter_mbmi->ref_frame[1] == LAST2_FRAME);
- else
- pred_context = 2;
- }
- } else { // inter/inter
- const int a_sg = !has_second_ref(above_mbmi);
- const int l_sg = !has_second_ref(left_mbmi);
- const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
- const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
- const MV_REFERENCE_FRAME brfa = above_mbmi->ref_frame[1];
- const MV_REFERENCE_FRAME brfl = left_mbmi->ref_frame[1];
-
- if (a_sg && l_sg) { // single/single
- if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
- pred_context = 1 + 2 * (frfa == LAST2_FRAME);
- else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
- pred_context = 1 + 2 * (frfl == LAST2_FRAME);
- else
- pred_context = 2;
- } else if (l_sg || a_sg) { // single/comp
- const MV_REFERENCE_FRAME brfc = a_sg ? brfl : brfa;
-
- if (CHECK_LAST2_OR_GOLDEN(brfc))
- pred_context = 4 * (brfc == LAST2_FRAME);
- if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
- pred_context = 1 + 2 * (frfa == LAST2_FRAME);
- else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
- pred_context = 1 + 2 * (frfl == LAST2_FRAME);
- else
- pred_context = 2;
- } else { // comp/comp
- if (CHECK_LAST2_OR_GOLDEN(brfa) &&
- (brfa == brfl || !CHECK_LAST2_OR_GOLDEN(brfl)))
- pred_context = 4 * (brfa == LAST2_FRAME);
- else if (!CHECK_LAST2_OR_GOLDEN(brfa) && CHECK_LAST2_OR_GOLDEN(brfl))
- pred_context = 4 * (brfl == LAST2_FRAME);
- else if (CHECK_LAST2_OR_GOLDEN(frfa) &&
- (frfa == frfl || frfl == LAST_FRAME))
- pred_context = 1 + 2 * (frfa == LAST2_FRAME);
- else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
- pred_context = 1 + 2 * (frfl == LAST2_FRAME);
- else
- pred_context = 2;
- }
+ if (above_in_image && is_inter_block(above_mbmi)) {
+ last2_count = (above_mbmi->ref_frame[0] == LAST2_FRAME) ? last2_count + 1
+ : last2_count;
+ last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(above_mbmi->ref_frame[0])
+ ? last3_or_gld_count + 1
+ : last3_or_gld_count;
+ if (has_second_ref(above_mbmi)) {
+ last2_count = (above_mbmi->ref_frame[1] == LAST2_FRAME) ? last2_count + 1
+ : last2_count;
+ last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(above_mbmi->ref_frame[1])
+ ? last3_or_gld_count + 1
+ : last3_or_gld_count;
}
- } else if (above_in_image || left_in_image) { // one edge available
- const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
-
- if (!is_inter_block(edge_mbmi)) { // intra
- pred_context = 2;
- } else { // inter
- if (!has_second_ref(edge_mbmi)) { // single pred
- if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[0]))
- pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == LAST2_FRAME);
- else
- pred_context = 2;
- } else { // comp pred
- if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[1]))
- pred_context = 4 * (edge_mbmi->ref_frame[1] == LAST2_FRAME);
- else
- pred_context = 2;
- }
- }
- } else { // no edges available
- pred_context = 2;
}
+ if (left_in_image && is_inter_block(left_mbmi)) {
+ last2_count = (left_mbmi->ref_frame[0] == LAST2_FRAME) ? last2_count + 1
+ : last2_count;
+ last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(left_mbmi->ref_frame[0])
+ ? last3_or_gld_count + 1
+ : last3_or_gld_count;
+ if (has_second_ref(left_mbmi)) {
+ last2_count = (left_mbmi->ref_frame[1] == LAST2_FRAME) ? last2_count + 1
+ : last2_count;
+ last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(left_mbmi->ref_frame[1])
+ ? last3_or_gld_count + 1
+ : last3_or_gld_count;
+ }
+ }
+
+ pred_context = (last2_count == last3_or_gld_count)
+ ? 1
+ : ((last2_count < last3_or_gld_count) ? 0 : 2);
+
+ assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
+ return pred_context;
+}
+
+// Returns a context number for the given MB prediction signal
+//
+// Signal the uni-directional compound reference frame pair as
+// either (LAST, LAST3) or (LAST, GOLDEN),
+// conditioning on the pair is known as one of the above two.
+//
+// 3 contexts: Voting is used to compare the count of LAST3_FRAME with the
+// total count of GOLDEN_FRAME from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd) {
+ int pred_context;
+ const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
+ const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
+ const int above_in_image = xd->up_available;
+ const int left_in_image = xd->left_available;
+
+ // Count of LAST3
+ int last3_count = 0;
+ // Count of GOLDEN
+ int gld_count = 0;
+
+ if (above_in_image && is_inter_block(above_mbmi)) {
+ last3_count = (above_mbmi->ref_frame[0] == LAST3_FRAME) ? last3_count + 1
+ : last3_count;
+ gld_count =
+ (above_mbmi->ref_frame[0] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+ if (has_second_ref(above_mbmi)) {
+ last3_count = (above_mbmi->ref_frame[1] == LAST3_FRAME) ? last3_count + 1
+ : last3_count;
+ gld_count = (above_mbmi->ref_frame[1] == GOLDEN_FRAME) ? gld_count + 1
+ : gld_count;
+ }
+ }
+
+ if (left_in_image && is_inter_block(left_mbmi)) {
+ last3_count = (left_mbmi->ref_frame[0] == LAST3_FRAME) ? last3_count + 1
+ : last3_count;
+ gld_count =
+ (left_mbmi->ref_frame[0] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+ if (has_second_ref(left_mbmi)) {
+ last3_count = (left_mbmi->ref_frame[1] == LAST3_FRAME) ? last3_count + 1
+ : last3_count;
+ gld_count =
+ (left_mbmi->ref_frame[1] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+ }
+ }
+
+ pred_context =
+ (last3_count == gld_count) ? 1 : ((last3_count < gld_count) ? 0 : 2);
+
assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
return pred_context;
}
@@ -592,9 +562,6 @@
#define CHECK_LAST_OR_LAST2(ref_frame) \
((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
-#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
- ((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME))
-
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode be either
// GOLDEN/LAST3, or LAST/LAST2.
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h
index a4f2482..610a2c3 100644
--- a/av1/common/pred_common.h
+++ b/av1/common/pred_common.h
@@ -109,32 +109,62 @@
#endif
#if CONFIG_EXT_COMP_REFS
-int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
- const MACROBLOCKD *xd);
+int av1_get_comp_reference_type_context(const MACROBLOCKD *xd);
static INLINE aom_prob av1_get_comp_reference_type_prob(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
- return cm->fc
- ->comp_ref_type_prob[av1_get_comp_reference_type_context(cm, xd)];
+ return cm->fc->comp_ref_type_prob[av1_get_comp_reference_type_context(xd)];
}
-int av1_get_pred_context_uni_comp_ref_p(const AV1_COMMON *cm,
- const MACROBLOCKD *xd);
+int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd);
static INLINE aom_prob av1_get_pred_prob_uni_comp_ref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
- const int pred_context = av1_get_pred_context_uni_comp_ref_p(cm, xd);
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p(xd);
return cm->fc->uni_comp_ref_prob[pred_context][0];
}
-int av1_get_pred_context_uni_comp_ref_p1(const AV1_COMMON *cm,
- const MACROBLOCKD *xd);
+int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd);
static INLINE aom_prob
av1_get_pred_prob_uni_comp_ref_p1(const AV1_COMMON *cm, const MACROBLOCKD *xd) {
- const int pred_context = av1_get_pred_context_uni_comp_ref_p1(cm, xd);
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p1(xd);
return cm->fc->uni_comp_ref_prob[pred_context][1];
}
+
+int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd);
+
+static INLINE aom_prob
+av1_get_pred_prob_uni_comp_ref_p2(const AV1_COMMON *cm, const MACROBLOCKD *xd) {
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p2(xd);
+ return cm->fc->uni_comp_ref_prob[pred_context][2];
+}
+
+#if CONFIG_NEW_MULTISYMBOL
+static INLINE aom_cdf_prob *av1_get_comp_reference_type_cdf(
+ const MACROBLOCKD *xd) {
+ const int pred_context = av1_get_comp_reference_type_context(xd);
+ return xd->tile_ctx->comp_ref_type_cdf[pred_context];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p(
+ const MACROBLOCKD *xd) {
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p(xd);
+ return xd->tile_ctx->uni_comp_ref_cdf[pred_context][0];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p1(
+ const MACROBLOCKD *xd) {
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p1(xd);
+ return xd->tile_ctx->uni_comp_ref_cdf[pred_context][1];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p2(
+ const MACROBLOCKD *xd) {
+ const int pred_context = av1_get_pred_context_uni_comp_ref_p2(xd);
+ return xd->tile_ctx->uni_comp_ref_cdf[pred_context][2];
+}
+#endif // CONFIG_NEW_MULTISYMBOL
#endif // CONFIG_EXT_COMP_REFS
int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,