Added 3 more reference frames for inter prediction.
Under the experiment of EXT_REFS: LAST2_FRAME, LAST3_FRAME, and
LAST4_FRAME.
Coding efficiency: derflr +1.601%; hevchr +1.895%
Speed: Encoder slowed down by ~75%
Change-Id: Ifeee5f049c2c1f7cb29bc897622ef88897082ecf
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index bb94397..9974da9 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -65,9 +65,18 @@
#define NONE -1
#define INTRA_FRAME 0
#define LAST_FRAME 1
+#if CONFIG_EXT_REFS
+#define LAST2_FRAME 2
+#define LAST3_FRAME 3
+#define LAST4_FRAME 4
+#define GOLDEN_FRAME 5
+#define ALTREF_FRAME 6
+#define MAX_REF_FRAMES 7
+#else
#define GOLDEN_FRAME 2
#define ALTREF_FRAME 3
#define MAX_REF_FRAMES 4
+#endif // CONFIG_EXT_REFS
typedef int8_t MV_REFERENCE_FRAME;
typedef struct {
diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c
index 9142d6a..3061258 100644
--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -215,16 +215,33 @@
239, 183, 119, 96, 41
};
-static const vpx_prob default_comp_ref_p[REF_CONTEXTS] = {
- 50, 126, 123, 221, 226
+static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
+#if CONFIG_EXT_REFS
+ // TODO(zoeliu): To adjust the initial prob values.
+ { 33, 16, 16, 16 },
+ { 77, 74, 74, 74 },
+ { 142, 142, 142, 142 },
+ { 172, 170, 170, 170 },
+ { 238, 247, 247, 247 }
+#else
+ { 50 }, { 126 }, { 123 }, { 221 }, { 226 }
+#endif // CONFIG_EXT_REFS
};
-static const vpx_prob default_single_ref_p[REF_CONTEXTS][2] = {
+static const vpx_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
+#if CONFIG_EXT_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
{ 33, 16 },
{ 77, 74 },
{ 142, 142 },
{ 172, 170 },
{ 238, 247 }
+#endif // CONFIG_EXT_REFS
};
static const struct tx_probs default_tx_probs = {
@@ -1109,10 +1126,11 @@
fc->comp_inter_prob[i] = mode_mv_merge_probs(pre_fc->comp_inter_prob[i],
counts->comp_inter[i]);
for (i = 0; i < REF_CONTEXTS; i++)
- fc->comp_ref_prob[i] = mode_mv_merge_probs(pre_fc->comp_ref_prob[i],
- counts->comp_ref[i]);
+ for (j = 0; j < (COMP_REFS - 1); j++)
+ fc->comp_ref_prob[i][j] = mode_mv_merge_probs(pre_fc->comp_ref_prob[i][j],
+ counts->comp_ref[i][j]);
for (i = 0; i < REF_CONTEXTS; i++)
- for (j = 0; j < 2; j++)
+ for (j = 0; j < (SINGLE_REFS - 1); j++)
fc->single_ref_prob[i][j] = mode_mv_merge_probs(
pre_fc->single_ref_prob[i][j], counts->single_ref[i][j]);
@@ -1233,6 +1251,11 @@
lf->ref_deltas[INTRA_FRAME] = 1;
lf->ref_deltas[LAST_FRAME] = 0;
+#if CONFIG_EXT_REFS
+ lf->ref_deltas[LAST2_FRAME] = lf->ref_deltas[LAST_FRAME];
+ lf->ref_deltas[LAST3_FRAME] = lf->ref_deltas[LAST_FRAME];
+ lf->ref_deltas[LAST4_FRAME] = lf->ref_deltas[LAST_FRAME];
+#endif // CONFIG_EXT_REFS
lf->ref_deltas[GOLDEN_FRAME] = -1;
lf->ref_deltas[ALTREF_FRAME] = -1;
diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h
index 0d2ed50..52c3630 100644
--- a/vp10/common/entropymode.h
+++ b/vp10/common/entropymode.h
@@ -63,8 +63,8 @@
vpx_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1];
vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS];
- vpx_prob single_ref_prob[REF_CONTEXTS][2];
- vpx_prob comp_ref_prob[REF_CONTEXTS];
+ vpx_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS-1];
+ vpx_prob comp_ref_prob[REF_CONTEXTS][COMP_REFS-1];
struct tx_probs tx_probs;
#if CONFIG_VAR_TX
vpx_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS];
@@ -96,8 +96,8 @@
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
- unsigned int single_ref[REF_CONTEXTS][2][2];
- unsigned int comp_ref[REF_CONTEXTS][2];
+ unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2];
+ unsigned int comp_ref[REF_CONTEXTS][COMP_REFS-1][2];
struct tx_counts tx;
#if CONFIG_VAR_TX
unsigned int txfm_partition[TXFM_PARTITION_CONTEXTS][2];
diff --git a/vp10/common/enums.h b/vp10/common/enums.h
index 3f9395e..1cd6e7a 100644
--- a/vp10/common/enums.h
+++ b/vp10/common/enums.h
@@ -123,8 +123,16 @@
typedef enum {
VP9_LAST_FLAG = 1 << 0,
+#if CONFIG_EXT_REFS
+ VP9_LAST2_FLAG = 1 << 1,
+ VP9_LAST3_FLAG = 1 << 2,
+ VP9_LAST4_FLAG = 1 << 3,
+ VP9_GOLD_FLAG = 1 << 4,
+ VP9_ALT_FLAG = 1 << 5,
+#else
VP9_GOLD_FLAG = 1 << 1,
VP9_ALT_FLAG = 1 << 2,
+#endif // CONFIG_EXT_REFS
} VP9_REFFRAME;
typedef enum {
@@ -210,6 +218,14 @@
typedef TX_SIZE TXFM_CONTEXT;
#endif
+#if CONFIG_EXT_REFS
+#define SINGLE_REFS 6
+#define COMP_REFS 5
+#else
+#define SINGLE_REFS 3
+#define COMP_REFS 2
+#endif // CONFIG_EXT_REFS
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp10/common/loopfilter.h b/vp10/common/loopfilter.h
index 513fbe3..3d76439 100644
--- a/vp10/common/loopfilter.h
+++ b/vp10/common/loopfilter.h
@@ -43,7 +43,8 @@
uint8_t mode_ref_delta_enabled;
uint8_t mode_ref_delta_update;
- // 0 = Intra, Last, GF, ARF
+ // 0 = Intra, Last, Last2+Last3+LAST4(CONFIG_EXT_REFS),
+ // GF, ARF
signed char ref_deltas[MAX_REF_FRAMES];
signed char last_ref_deltas[MAX_REF_FRAMES];
diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h
index e3fef90..86ec7d8 100644
--- a/vp10/common/onyxc_int.h
+++ b/vp10/common/onyxc_int.h
@@ -174,6 +174,12 @@
#endif
FRAME_TYPE last_frame_type; /* last frame's frame type for motion search.*/
+#if CONFIG_EXT_REFS
+ // frame type of the frame before last frame
+ FRAME_TYPE last2_frame_type;
+ // frame type of the frame two frames before last frame
+ FRAME_TYPE last3_frame_type;
+#endif // CONFIG_EXT_REFS
FRAME_TYPE frame_type;
int show_frame;
@@ -260,7 +266,7 @@
// Context probabilities for reference frame prediction
MV_REFERENCE_FRAME comp_fixed_ref;
- MV_REFERENCE_FRAME comp_var_ref[2];
+ MV_REFERENCE_FRAME comp_var_ref[COMP_REFS];
REFERENCE_MODE reference_mode;
FRAME_CONTEXT *fc; /* this frame entropy */
diff --git a/vp10/common/pred_common.c b/vp10/common/pred_common.c
index 2e79e0d..9c42794 100644
--- a/vp10/common/pred_common.c
+++ b/vp10/common/pred_common.c
@@ -103,9 +103,424 @@
return ctx;
}
+#if CONFIG_EXT_REFS
+
+// TODO(zoeliu): Future work will be conducted to optimize the context design
+// for the coding of the reference frames.
+
+#define CHECK_LAST_OR_LAST2(ref_frame) \
+ ((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
+
+#define CHECK_GOLDEN_LAST3_LAST4(ref_frame) \
+ ((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME) || \
+ (ref_frame == LAST4_FRAME))
+
+// Returns a context number for the given MB prediction signal
+// Signal the first reference frame for a compound mode is either
+// GOLDEN/LAST3/LAST4, or LAST/LAST2.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is either
+// GOLDEN_FRAME/LAST3_FRAME/LAST4_FRAME.
+int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
+ 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;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+ const int var_ref_idx = !fix_ref_idx;
+
+ 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 (2)
+ pred_context = 2;
+ } else if (above_intra || left_intra) { // intra/inter
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+
+ if (!has_second_ref(edge_mbmi)) // single pred (1/3)
+ pred_context = 1 +
+ 2 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]));
+ else // comp pred (1/3)
+ pred_context = 1 +
+ 2 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[var_ref_idx]));
+ } else { // inter/inter
+ const int l_sg = !has_second_ref(left_mbmi);
+ const int a_sg = !has_second_ref(above_mbmi);
+ const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
+ : above_mbmi->ref_frame[var_ref_idx];
+ const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
+ : left_mbmi->ref_frame[var_ref_idx];
+
+ if (vrfa == vrfl && CHECK_GOLDEN_LAST3_LAST4(vrfa)) {
+ pred_context = 0;
+ } else if (l_sg && a_sg) { // single/single
+ if ((vrfa == ALTREF_FRAME && CHECK_LAST_OR_LAST2(vrfl)) ||
+ (vrfl == ALTREF_FRAME && CHECK_LAST_OR_LAST2(vrfa))) {
+ pred_context = 4;
+ } else if (vrfa == vrfl || (CHECK_LAST_OR_LAST2(vrfa) &&
+ CHECK_LAST_OR_LAST2(vrfl))) {
+ pred_context = 3;
+ } else { // Either vrfa or vrfl is GOLDEN / LAST3 / LAST4
+ // NOTE(zoeliu): Following assert may be removed once confirmed.
+ assert(CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
+ CHECK_GOLDEN_LAST3_LAST4(vrfl));
+ pred_context = 1;
+ }
+ } else if (l_sg || a_sg) { // single/comp
+ const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+ const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+
+ if (CHECK_GOLDEN_LAST3_LAST4(vrfc) && !CHECK_GOLDEN_LAST3_LAST4(rfs))
+ pred_context = 1;
+ else if (CHECK_GOLDEN_LAST3_LAST4(rfs) &&
+ !CHECK_GOLDEN_LAST3_LAST4(vrfc))
+ pred_context = 2;
+ else
+ pred_context = 4;
+ } else { // comp/comp
+ if ((CHECK_LAST_OR_LAST2(vrfa) && CHECK_LAST_OR_LAST2(vrfl))) {
+ pred_context = 4;
+ } else {
+ // NOTE(zoeliu): Following assert may be removed once confirmed.
+ assert(CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
+ CHECK_GOLDEN_LAST3_LAST4(vrfl));
+ pred_context = 2;
+ }
+ }
+ }
+ } 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)) {
+ pred_context = 2;
+ } else {
+ if (has_second_ref(edge_mbmi))
+ pred_context =
+ 4 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[var_ref_idx]));
+ else
+ pred_context = 3 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]));
+ }
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+
+ return pred_context;
+}
+
+// Returns a context number for the given MB prediction signal
+// Signal the first reference frame for a compound mode is LAST,
+// conditioning on that it is known either LAST/LAST2.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is LAST_FRAME,
+// conditioning on it is either LAST_FRAME or LAST2_FRAME.
+int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
+ 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;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+ const int var_ref_idx = !fix_ref_idx;
+
+ 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 (2)
+ pred_context = 2;
+ } else if (above_intra || left_intra) { // intra/inter
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+
+ if (!has_second_ref(edge_mbmi)) // single pred (1/3)
+ pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != LAST_FRAME);
+ else // comp pred (1/3)
+ pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
+ != LAST_FRAME);
+ } else { // inter/inter
+ const int l_sg = !has_second_ref(left_mbmi);
+ const int a_sg = !has_second_ref(above_mbmi);
+ const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
+ : above_mbmi->ref_frame[var_ref_idx];
+ const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
+ : left_mbmi->ref_frame[var_ref_idx];
+
+ if (vrfa == vrfl && vrfa == LAST_FRAME)
+ pred_context = 0;
+ else if (l_sg && a_sg) { // single/single
+ if (vrfa == LAST_FRAME || vrfl == LAST_FRAME)
+ pred_context = 1;
+ else if (CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
+ CHECK_GOLDEN_LAST3_LAST4(vrfl))
+ pred_context = 2 + (vrfa != vrfl);
+ else if (vrfa == vrfl)
+ pred_context = 3;
+ else
+ pred_context = 4;
+ } else if (l_sg || a_sg) { // single/comp
+ const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+ const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+
+ if (vrfc == LAST_FRAME && rfs != LAST_FRAME)
+ pred_context = 1;
+ else if (rfs == LAST_FRAME && vrfc != LAST_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 +
+ (vrfc == LAST2_FRAME || CHECK_GOLDEN_LAST3_LAST4(rfs));
+ } else { // comp/comp
+ if (vrfa == LAST_FRAME || vrfl == LAST_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 + (CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
+ CHECK_GOLDEN_LAST3_LAST4(vrfl));
+ }
+ }
+ } 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)) {
+ pred_context = 2;
+ } else {
+ if (has_second_ref(edge_mbmi)) {
+ pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != LAST_FRAME);
+ } else {
+ if (edge_mbmi->ref_frame[0] == LAST_FRAME)
+ pred_context = 0;
+ else
+ pred_context = 2 + CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]);
+ }
+ }
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+
+ return pred_context;
+}
+
+#define CHECK_LAST3_OR_LAST4(ref_frame) \
+ ((ref_frame == LAST3_FRAME) || (ref_frame == LAST4_FRAME))
+
+// Returns a context number for the given MB prediction signal
+// Signal the first reference frame for a compound mode is GOLDEN,
+// conditioning on that it is known either GOLDEN/LAST3/LAST4.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is GOLDEN_FRAME,
+// conditioning on it is either GOLDEN / LAST3 / LAST4.
+int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
+ 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;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+ const int var_ref_idx = !fix_ref_idx;
+
+ 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 (2)
+ pred_context = 2;
+ } else if (above_intra || left_intra) { // intra/inter
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+
+ if (!has_second_ref(edge_mbmi)) // single pred (1/3)
+ pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != GOLDEN_FRAME);
+ else // comp pred (1/3)
+ pred_context = 1 +
+ 2 * (edge_mbmi->ref_frame[var_ref_idx] != GOLDEN_FRAME);
+ } else { // inter/inter
+ const int l_sg = !has_second_ref(left_mbmi);
+ const int a_sg = !has_second_ref(above_mbmi);
+ const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
+ : above_mbmi->ref_frame[var_ref_idx];
+ const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
+ : left_mbmi->ref_frame[var_ref_idx];
+
+ if (vrfa == vrfl && vrfa == GOLDEN_FRAME)
+ pred_context = 0;
+ else if (l_sg && a_sg) { // single/single
+ if (vrfa == GOLDEN_FRAME || vrfl == GOLDEN_FRAME)
+ pred_context = 1;
+ else if (CHECK_LAST_OR_LAST2(vrfa) || CHECK_LAST_OR_LAST2(vrfl))
+ pred_context = 2 + (vrfa != vrfl);
+ else if (vrfa == vrfl)
+ pred_context = 3;
+ else
+ pred_context = 4;
+ } else if (l_sg || a_sg) { // single/comp
+ const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+ const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+
+ if (vrfc == GOLDEN_FRAME && rfs != GOLDEN_FRAME)
+ pred_context = 1;
+ else if (rfs == GOLDEN_FRAME && vrfc != GOLDEN_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 +
+ (CHECK_LAST3_OR_LAST4(vrfc) || CHECK_LAST_OR_LAST2(rfs));
+ } else { // comp/comp
+ if (vrfa == GOLDEN_FRAME || vrfl == GOLDEN_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 +
+ (CHECK_LAST_OR_LAST2(vrfa) || CHECK_LAST_OR_LAST2(vrfl));
+ }
+ }
+ } 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)) {
+ pred_context = 2;
+ } else {
+ if (has_second_ref(edge_mbmi)) {
+ pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != GOLDEN_FRAME);
+ } else {
+ if (edge_mbmi->ref_frame[0] == GOLDEN_FRAME)
+ pred_context = 0;
+ else
+ pred_context = 2 + CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]);
+ }
+ }
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+
+ return pred_context;
+}
+
+#define CHECK_LAST_LAST2_GOLDEN(ref_frame) \
+ ((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME) || \
+ (ref_frame == GOLDEN_FRAME))
+
+// Returns a context number for the given MB prediction signal
+// Signal the first reference frame for a compound mode is LAST3,
+// conditioning on that it is known either LAST3/LAST4.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is LAST3_FRAME,
+// conditioning on it is either LAST3 / LAST4.
+int vp10_get_pred_context_comp_ref_p3(const VP10_COMMON *cm,
+ 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;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+ const int var_ref_idx = !fix_ref_idx;
+
+ 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 (2)
+ pred_context = 2;
+ } else if (above_intra || left_intra) { // intra/inter
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+
+ if (!has_second_ref(edge_mbmi)) // single pred (1/3)
+ pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != LAST3_FRAME);
+ else // comp pred (1/3)
+ pred_context = 1 +
+ 2 * (edge_mbmi->ref_frame[var_ref_idx] != LAST3_FRAME);
+ } else { // inter/inter
+ const int l_sg = !has_second_ref(left_mbmi);
+ const int a_sg = !has_second_ref(above_mbmi);
+ const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
+ : above_mbmi->ref_frame[var_ref_idx];
+ const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
+ : left_mbmi->ref_frame[var_ref_idx];
+
+ if (vrfa == vrfl && vrfa == LAST3_FRAME)
+ pred_context = 0;
+ else if (l_sg && a_sg) { // single/single
+ if (vrfa == LAST3_FRAME || vrfl == LAST3_FRAME)
+ pred_context = 1;
+ else if (CHECK_LAST_LAST2_GOLDEN(vrfa) || CHECK_LAST_LAST2_GOLDEN(vrfl))
+ pred_context = 2 + (vrfa != vrfl);
+ else if (vrfa == vrfl)
+ pred_context = 3;
+ else
+ pred_context = 4;
+ } else if (l_sg || a_sg) { // single/comp
+ const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+ const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+
+ if (vrfc == LAST3_FRAME && rfs != LAST3_FRAME)
+ pred_context = 1;
+ else if (rfs == LAST3_FRAME && vrfc != LAST3_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 +
+ (vrfc == LAST4_FRAME || CHECK_LAST_LAST2_GOLDEN(rfs));
+ } else { // comp/comp
+ if (vrfa == LAST3_FRAME || vrfl == LAST3_FRAME)
+ pred_context = 2;
+ else
+ pred_context = 3 +
+ (CHECK_LAST_LAST2_GOLDEN(vrfa) || CHECK_LAST_LAST2_GOLDEN(vrfl));
+ }
+ }
+ } 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)) {
+ pred_context = 2;
+ } else {
+ if (has_second_ref(edge_mbmi)) {
+ pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != LAST3_FRAME);
+ } else {
+ if (edge_mbmi->ref_frame[0] == LAST3_FRAME)
+ pred_context = 0;
+ else
+ pred_context = 2 + CHECK_LAST_LAST2_GOLDEN(edge_mbmi->ref_frame[0]);
+ }
+ }
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+
+ return pred_context;
+}
+
+#else // CONFIG_EXT_REFS
+
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
- const MACROBLOCKD *xd) {
+ 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;
@@ -186,6 +601,472 @@
return pred_context;
}
+#endif // CONFIG_EXT_REFS
+
+#if CONFIG_EXT_REFS
+
+#define CHECK_GOLDEN_OR_ALTREF(ref_frame) \
+ ((ref_frame == GOLDEN_FRAME) || (ref_frame == ALTREF_FRAME))
+
+// For the bit to signal whether the single reference is a ALTREF_FRAME
+// or a GOLDEN_FRAME.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is ALTREF/GOLDEN.
+int vp10_get_pred_context_single_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 has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ if (has_above && has_left) { // 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 or inter/intra
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+
+ if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]));
+ else
+ pred_context = 1 + (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]) ||
+ !CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[1]));
+ } else { // inter/inter
+ const int above_has_second = has_second_ref(above_mbmi);
+ const int left_has_second = has_second_ref(left_mbmi);
+
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
+
+ if (above_has_second && left_has_second) {
+ pred_context = 1 + (!CHECK_GOLDEN_OR_ALTREF(above0) ||
+ !CHECK_GOLDEN_OR_ALTREF(above1) ||
+ !CHECK_GOLDEN_OR_ALTREF(left0) ||
+ !CHECK_GOLDEN_OR_ALTREF(left1));
+ } else if (above_has_second || left_has_second) {
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
+
+ if (!CHECK_GOLDEN_OR_ALTREF(rfs))
+ pred_context = 3 + (!CHECK_GOLDEN_OR_ALTREF(crf1) ||
+ !CHECK_GOLDEN_OR_ALTREF(crf2));
+ else
+ pred_context = !CHECK_GOLDEN_OR_ALTREF(crf1) ||
+ !CHECK_GOLDEN_OR_ALTREF(crf2);
+ } else {
+ pred_context = 2 * (!CHECK_GOLDEN_OR_ALTREF(above0)) +
+ 2 * (!CHECK_GOLDEN_OR_ALTREF(left0));
+ }
+ }
+ } else if (has_above || has_left) { // one edge available
+ const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
+ if (!is_inter_block(edge_mbmi)) { // intra
+ pred_context = 2;
+ } else { // inter
+ if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]));
+ else
+ pred_context = 1 + (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]) ||
+ !CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[1]));
+ }
+ } else { // no edges available
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+ return pred_context;
+}
+
+// For the bit to signal whether the single reference is ALTREF_FRAME or
+// GOLDEN_FRAME, knowing that it shall be either of these 2 choices.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is ALTREF_FRAME, conditioning
+// on it is either ALTREF_FRAME/GOLDEN_FRAME.
+int vp10_get_pred_context_single_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 has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ if (has_above && has_left) { // 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 or inter/intra
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+ if (!has_second_ref(edge_mbmi)) {
+ if (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]))
+ pred_context = 3;
+ else
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
+ } else {
+ pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
+ edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
+ }
+ } else { // inter/inter
+ const int above_has_second = has_second_ref(above_mbmi);
+ const int left_has_second = has_second_ref(left_mbmi);
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
+
+ if (above_has_second && left_has_second) {
+ if (above0 == left0 && above1 == left1)
+ pred_context = 3 * (above0 == GOLDEN_FRAME ||
+ above1 == GOLDEN_FRAME ||
+ left0 == GOLDEN_FRAME ||
+ left1 == GOLDEN_FRAME);
+ else
+ pred_context = 2;
+ } else if (above_has_second || left_has_second) {
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
+
+ if (rfs == GOLDEN_FRAME)
+ pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+ else if (rfs == ALTREF_FRAME)
+ pred_context = (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+ else
+ pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+ } else {
+ if (!CHECK_GOLDEN_OR_ALTREF(above0) && !CHECK_GOLDEN_OR_ALTREF(left0)) {
+ pred_context = 2 + (above0 == left0);
+ } else if (!CHECK_GOLDEN_OR_ALTREF(above0) ||
+ !CHECK_GOLDEN_OR_ALTREF(left0)) {
+ const MV_REFERENCE_FRAME edge0 =
+ !CHECK_GOLDEN_OR_ALTREF(above0) ? left0 : above0;
+ pred_context = 4 * (edge0 == GOLDEN_FRAME);
+ } else {
+ pred_context = 2 * (above0 == GOLDEN_FRAME) +
+ 2 * (left0 == GOLDEN_FRAME);
+ }
+ }
+ }
+ } else if (has_above || has_left) { // one edge available
+ const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
+
+ if (!is_inter_block(edge_mbmi) ||
+ (!CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]) &&
+ !has_second_ref(edge_mbmi)))
+ pred_context = 2;
+ else if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
+ else
+ pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
+ edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+ return pred_context;
+}
+
+// For the bit to signal whether the single reference is LAST3/LAST4 or
+// LAST2/LAST, knowing that it shall be either of these 2 choices.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is LAST3/LAST4, conditioning
+// on it is either LAST3/LAST4/LAST2/LAST.
+int vp10_get_pred_context_single_ref_p3(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 has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ if (has_above && has_left) { // 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 or inter/intra
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+ if (!has_second_ref(edge_mbmi)) {
+ if (CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]))
+ pred_context = 3;
+ else
+ pred_context = 4 * CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]);
+ } else {
+ pred_context = 1 +
+ 2 * (CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]) ||
+ CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[1]));
+ }
+ } else { // inter/inter
+ const int above_has_second = has_second_ref(above_mbmi);
+ const int left_has_second = has_second_ref(left_mbmi);
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
+
+ if (above_has_second && left_has_second) {
+ if (above0 == left0 && above1 == left1)
+ pred_context = 3 * (CHECK_LAST_OR_LAST2(above0) ||
+ CHECK_LAST_OR_LAST2(above1) ||
+ CHECK_LAST_OR_LAST2(left0) ||
+ CHECK_LAST_OR_LAST2(left1));
+ else
+ pred_context = 2;
+ } else if (above_has_second || left_has_second) {
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
+
+ if (CHECK_LAST_OR_LAST2(rfs))
+ pred_context = 3 + (CHECK_LAST_OR_LAST2(crf1) ||
+ CHECK_LAST_OR_LAST2(crf2));
+ else if (rfs == LAST3_FRAME || rfs == LAST4_FRAME)
+ pred_context = (CHECK_LAST_OR_LAST2(crf1) ||
+ CHECK_LAST_OR_LAST2(crf2));
+ else
+ pred_context = 1 + 2 * (CHECK_LAST_OR_LAST2(crf1) ||
+ CHECK_LAST_OR_LAST2(crf2));
+ } else {
+ if (CHECK_GOLDEN_OR_ALTREF(above0) && CHECK_GOLDEN_OR_ALTREF(left0)) {
+ pred_context = 2 + (above0 == left0);
+ } else if (CHECK_GOLDEN_OR_ALTREF(above0) ||
+ CHECK_GOLDEN_OR_ALTREF(left0)) {
+ const MV_REFERENCE_FRAME edge0 =
+ CHECK_GOLDEN_OR_ALTREF(above0) ? left0 : above0;
+ pred_context = 4 * CHECK_LAST_OR_LAST2(edge0);
+ } else {
+ pred_context = 2 * CHECK_LAST_OR_LAST2(above0) +
+ 2 * CHECK_LAST_OR_LAST2(left0);
+ }
+ }
+ }
+ } else if (has_above || has_left) { // one edge available
+ const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
+
+ if (!is_inter_block(edge_mbmi) ||
+ (CHECK_GOLDEN_OR_ALTREF(edge_mbmi->ref_frame[0]) &&
+ !has_second_ref(edge_mbmi)))
+ pred_context = 2;
+ else if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]));
+ else
+ pred_context = 3 * (CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]) ||
+ CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[1]));
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+ return pred_context;
+}
+
+// For the bit to signal whether the single reference is LAST2_FRAME or
+// LAST_FRAME, knowing that it shall be either of these 2 choices.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is LAST2_FRAME, conditioning
+// on it is either LAST2_FRAME/LAST_FRAME.
+int vp10_get_pred_context_single_ref_p4(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 has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ if (has_above && has_left) { // 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 or inter/intra
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+ if (!has_second_ref(edge_mbmi)) {
+ if (!CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]))
+ pred_context = 3;
+ else
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
+ } else {
+ pred_context = 1 +
+ 2 * (edge_mbmi->ref_frame[0] == LAST_FRAME ||
+ edge_mbmi->ref_frame[1] == LAST_FRAME);
+ }
+ } else { // inter/inter
+ const int above_has_second = has_second_ref(above_mbmi);
+ const int left_has_second = has_second_ref(left_mbmi);
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
+
+ if (above_has_second && left_has_second) {
+ if (above0 == left0 && above1 == left1)
+ pred_context = 3 * (above0 == LAST_FRAME || above1 == LAST_FRAME ||
+ left0 == LAST_FRAME || left1 == LAST_FRAME);
+ else
+ pred_context = 2;
+ } else if (above_has_second || left_has_second) {
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
+
+ if (rfs == LAST_FRAME)
+ pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
+ else if (rfs == LAST2_FRAME)
+ pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
+ else
+ pred_context = 1 + 2 * (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
+ } else {
+ if (!CHECK_LAST_OR_LAST2(above0) &&
+ !CHECK_LAST_OR_LAST2(left0)) {
+ pred_context = 2 + (above0 == left0);
+ } else if (!CHECK_LAST_OR_LAST2(above0) ||
+ !CHECK_LAST_OR_LAST2(left0)) {
+ const MV_REFERENCE_FRAME edge0 =
+ !CHECK_LAST_OR_LAST2(above0) ? left0 : above0;
+ pred_context = 4 * (edge0 == LAST_FRAME);
+ } else {
+ pred_context = 2 * (above0 == LAST_FRAME) + 2 * (left0 == LAST_FRAME);
+ }
+ }
+ }
+ } else if (has_above || has_left) { // one edge available
+ const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
+
+ if (!is_inter_block(edge_mbmi) ||
+ (!CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]) &&
+ !has_second_ref(edge_mbmi)))
+ pred_context = 2;
+ else if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
+ else
+ pred_context = 3 * (edge_mbmi->ref_frame[0] == LAST_FRAME ||
+ edge_mbmi->ref_frame[1] == LAST_FRAME);
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+ return pred_context;
+}
+
+// For the bit to signal whether the single reference is LAST4_FRAME or
+// LAST3_FRAME, knowing that it shall be either of these 2 choices.
+//
+// NOTE(zoeliu): The probability of ref_frame[0] is LAST4_FRAME, conditioning
+// on it is either LAST4_FRAME/LAST3_FRAME.
+int vp10_get_pred_context_single_ref_p5(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 has_above = xd->up_available;
+ const int has_left = xd->left_available;
+
+ // Note:
+ // The mode info data structure has a one element border above and to the
+ // left of the entries correpsonding to real macroblocks.
+ // The prediction flags in these dummy entries are initialised to 0.
+ if (has_above && has_left) { // 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 or inter/intra
+ const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
+ if (!has_second_ref(edge_mbmi)) {
+ if (!CHECK_LAST3_OR_LAST4(edge_mbmi->ref_frame[0]))
+ pred_context = 3;
+ else
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST3_FRAME);
+ } else {
+ pred_context = 1 +
+ 2 * (edge_mbmi->ref_frame[0] == LAST3_FRAME ||
+ edge_mbmi->ref_frame[1] == LAST3_FRAME);
+ }
+ } else { // inter/inter
+ const int above_has_second = has_second_ref(above_mbmi);
+ const int left_has_second = has_second_ref(left_mbmi);
+ const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
+ const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
+ const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
+
+ if (above_has_second && left_has_second) {
+ if (above0 == left0 && above1 == left1)
+ pred_context = 3 * (above0 == LAST3_FRAME || above1 == LAST3_FRAME ||
+ left0 == LAST3_FRAME || left1 == LAST3_FRAME);
+ else
+ pred_context = 2;
+ } else if (above_has_second || left_has_second) {
+ const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
+ const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
+
+ if (rfs == LAST3_FRAME)
+ pred_context = 3 + (crf1 == LAST3_FRAME || crf2 == LAST3_FRAME);
+ else if (rfs == LAST4_FRAME)
+ pred_context = (crf1 == LAST3_FRAME || crf2 == LAST3_FRAME);
+ else
+ pred_context = 1 + 2 * (crf1 == LAST3_FRAME || crf2 == LAST3_FRAME);
+ } else {
+ if (!CHECK_LAST3_OR_LAST4(above0) &&
+ !CHECK_LAST3_OR_LAST4(left0)) {
+ pred_context = 2 + (above0 == left0);
+ } else if (!CHECK_LAST3_OR_LAST4(above0) ||
+ !CHECK_LAST3_OR_LAST4(left0)) {
+ const MV_REFERENCE_FRAME edge0 =
+ !CHECK_LAST3_OR_LAST4(above0) ? left0 : above0;
+ pred_context = 4 * (edge0 == LAST3_FRAME);
+ } else {
+ pred_context = 2 * (above0 == LAST3_FRAME) +
+ 2 * (left0 == LAST3_FRAME);
+ }
+ }
+ }
+ } else if (has_above || has_left) { // one edge available
+ const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
+
+ if (!is_inter_block(edge_mbmi) ||
+ (!CHECK_LAST3_OR_LAST4(edge_mbmi->ref_frame[0]) &&
+ !has_second_ref(edge_mbmi)))
+ pred_context = 2;
+ else if (!has_second_ref(edge_mbmi))
+ pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST3_FRAME);
+ else
+ pred_context = 3 * (edge_mbmi->ref_frame[0] == LAST3_FRAME ||
+ edge_mbmi->ref_frame[1] == LAST3_FRAME);
+ } else { // no edges available (2)
+ pred_context = 2;
+ }
+
+ assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+ return pred_context;
+}
+
+#else // CONFIG_EXT_REFS
+
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
@@ -337,3 +1218,5 @@
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}
+
+#endif // CONFIG_EXT_REFS
diff --git a/vp10/common/pred_common.h b/vp10/common/pred_common.h
index ebba225..4ebfcdb 100644
--- a/vp10/common/pred_common.h
+++ b/vp10/common/pred_common.h
@@ -87,25 +87,77 @@
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p(const VP10_COMMON *cm,
- const MACROBLOCKD *xd) {
+ const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p(cm, xd);
- return cm->fc->comp_ref_prob[pred_context];
+ return cm->fc->comp_ref_prob[pred_context][0];
}
+#if CONFIG_EXT_REFS
+int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p1(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ const int pred_context = vp10_get_pred_context_comp_ref_p1(cm, xd);
+ return cm->fc->comp_ref_prob[pred_context][1];
+}
+
+int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p2(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ const int pred_context = vp10_get_pred_context_comp_ref_p2(cm, xd);
+ return cm->fc->comp_ref_prob[pred_context][2];
+}
+
+int vp10_get_pred_context_comp_ref_p3(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p3(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ const int pred_context = vp10_get_pred_context_comp_ref_p3(cm, xd);
+ return cm->fc->comp_ref_prob[pred_context][3];
+}
+#endif // CONFIG_EXT_REFS
+
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p1(const VP10_COMMON *cm,
- const MACROBLOCKD *xd) {
+ const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p1(xd)][0];
}
int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p2(const VP10_COMMON *cm,
- const MACROBLOCKD *xd) {
+ const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p2(xd)][1];
}
+#if CONFIG_EXT_REFS
+int vp10_get_pred_context_single_ref_p3(const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_single_ref_p3(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p3(xd)][2];
+}
+
+int vp10_get_pred_context_single_ref_p4(const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_single_ref_p4(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p4(xd)][3];
+}
+
+int vp10_get_pred_context_single_ref_p5(const MACROBLOCKD *xd);
+
+static INLINE vpx_prob vp10_get_pred_prob_single_ref_p5(const VP10_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p5(xd)][4];
+}
+#endif // CONFIG_EXT_REFS
+
// 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.
diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c
index 55b3537..80d8d14 100644
--- a/vp10/common/thread_common.c
+++ b/vp10/common/thread_common.c
@@ -379,13 +379,14 @@
cm->counts.comp_inter[i][j] += counts->comp_inter[i][j];
for (i = 0; i < REF_CONTEXTS; i++)
- for (j = 0; j < 2; j++)
+ for (j = 0; j < (SINGLE_REFS - 1); j++)
for (k = 0; k < 2; k++)
- cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k];
+ cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k];
for (i = 0; i < REF_CONTEXTS; i++)
- for (j = 0; j < 2; j++)
- cm->counts.comp_ref[i][j] += counts->comp_ref[i][j];
+ for (j = 0; j < (COMP_REFS - 1); j++)
+ for (k = 0; k < 2; k++)
+ cm->counts.comp_ref[i][j][k] += counts->comp_ref[i][j][k];
for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
for (j = 0; j < TX_SIZES; j++)
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index 531be1f..438d6df 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -61,13 +61,26 @@
cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
cm->comp_fixed_ref = ALTREF_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
+#if CONFIG_EXT_REFS
+ cm->comp_var_ref[1] = LAST2_FRAME;
+ cm->comp_var_ref[2] = LAST3_FRAME;
+ cm->comp_var_ref[3] = LAST4_FRAME;
+ cm->comp_var_ref[4] = GOLDEN_FRAME;
+#else
cm->comp_var_ref[1] = GOLDEN_FRAME;
+#endif // CONFIG_EXT_REFS
} else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
cm->ref_frame_sign_bias[ALTREF_FRAME]) {
+#if CONFIG_EXT_REFS
+ assert(0);
+#endif // CONFIG_EXT_REFS
cm->comp_fixed_ref = GOLDEN_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
cm->comp_var_ref[1] = ALTREF_FRAME;
} else {
+#if CONFIG_EXT_REFS
+ assert(0);
+#endif // CONFIG_EXT_REFS
cm->comp_fixed_ref = LAST_FRAME;
cm->comp_var_ref[0] = GOLDEN_FRAME;
cm->comp_var_ref[1] = ALTREF_FRAME;
@@ -130,21 +143,27 @@
static void read_frame_reference_mode_probs(VP10_COMMON *cm, vpx_reader *r) {
FRAME_CONTEXT *const fc = cm->fc;
- int i;
+ int i, j;
if (cm->reference_mode == REFERENCE_MODE_SELECT)
for (i = 0; i < COMP_INTER_CONTEXTS; ++i)
vp10_diff_update_prob(r, &fc->comp_inter_prob[i]);
- if (cm->reference_mode != COMPOUND_REFERENCE)
+ if (cm->reference_mode != COMPOUND_REFERENCE) {
for (i = 0; i < REF_CONTEXTS; ++i) {
- vp10_diff_update_prob(r, &fc->single_ref_prob[i][0]);
- vp10_diff_update_prob(r, &fc->single_ref_prob[i][1]);
+ for (j = 0; j < (SINGLE_REFS - 1); ++j) {
+ vp10_diff_update_prob(r, &fc->single_ref_prob[i][j]);
+ }
}
+ }
- if (cm->reference_mode != SINGLE_REFERENCE)
- for (i = 0; i < REF_CONTEXTS; ++i)
- vp10_diff_update_prob(r, &fc->comp_ref_prob[i]);
+ if (cm->reference_mode != SINGLE_REFERENCE) {
+ for (i = 0; i < REF_CONTEXTS; ++i) {
+ for (j = 0; j < (COMP_REFS - 1); ++j) {
+ vp10_diff_update_prob(r, &fc->comp_ref_prob[i][j]);
+ }
+ }
+ }
}
static void update_mv_probs(vpx_prob *p, int n, vpx_reader *r) {
@@ -1938,6 +1957,10 @@
int i, mask, ref_index = 0;
size_t sz;
+#if CONFIG_EXT_REFS
+ cm->last3_frame_type = cm->last2_frame_type;
+ cm->last2_frame_type = cm->last_frame_type;
+#endif // CONFIG_EXT_REFS
cm->last_frame_type = cm->frame_type;
cm->last_intra_only = cm->intra_only;
@@ -2106,20 +2129,70 @@
// Generate next_ref_frame_map.
lock_buffer_pool(pool);
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
+#if CONFIG_EXT_REFS
+// TODO(zoeliu): To move the following #define's to a header file
+#define PBI_LST_FB_IDX 0
+#define PBI_LST2_FB_IDX 1
+#define PBI_LST3_FB_IDX 2
+#define PBI_LST4_FB_IDX 3
+#define PBI_GLD_FB_IDX 4
+#define PBI_ALT_FB_IDX 5
+ // NOTE(zoeliu):
+ // (1) When ref_index == PBI_LST2_FB_IDX and the corresponding mask bit is
+ // set, it indicates that LAST2_FRAME shall be refreshed, but keep in
+ // mind that this has already been handled when LAST_FRAME is being
+ // refreshed, i.e., when ref_index == PBI_LST_FB_IDX and the mask bit
+ // is being set correspondingly;
+ // (2) The only exception is that when current frame is a KEY_FRAME, where
+ // all the frames in the frame buffer shall get refreshed;
+ // (3) Similar handling for when ref_index == PBI_LST3_FB_IDX or when
+ // ref_indx == PBI_LST4_FB_IDX.
+ if ((mask & 1) &&
+ (cm->frame_type == KEY_FRAME || (ref_index != PBI_LST2_FB_IDX &&
+ ref_index != PBI_LST3_FB_IDX &&
+ ref_index != PBI_LST4_FB_IDX))) {
+ // The reference frame map for the decoding of the next frame is updated
+ // and held by either current thread or possibly another decoder thread.
+ if (cm->frame_type != KEY_FRAME && ref_index == PBI_LST_FB_IDX &&
+ (mask & (1 << PBI_LST2_FB_IDX))) {
+ if (mask & (1 << PBI_LST3_FB_IDX)) {
+ if (mask & (1 << PBI_LST4_FB_IDX)) {
+ cm->next_ref_frame_map[PBI_LST4_FB_IDX] =
+ cm->next_ref_frame_map[PBI_LST3_FB_IDX];
+ ++frame_bufs[cm->next_ref_frame_map[PBI_LST3_FB_IDX]].ref_count;
+ }
+ cm->next_ref_frame_map[PBI_LST3_FB_IDX] =
+ cm->next_ref_frame_map[PBI_LST2_FB_IDX];
+ ++frame_bufs[cm->next_ref_frame_map[PBI_LST2_FB_IDX]].ref_count;
+ }
+ cm->next_ref_frame_map[PBI_LST2_FB_IDX] =
+ cm->next_ref_frame_map[PBI_LST_FB_IDX];
+ ++frame_bufs[cm->next_ref_frame_map[PBI_LST_FB_IDX]].ref_count;
+ }
+ cm->next_ref_frame_map[ref_index] = cm->new_fb_idx;
+ ++frame_bufs[cm->new_fb_idx].ref_count;
+ } else if (!(mask & 1)) {
+ cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
+ }
+#else
if (mask & 1) {
cm->next_ref_frame_map[ref_index] = cm->new_fb_idx;
++frame_bufs[cm->new_fb_idx].ref_count;
} else {
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
}
+#endif // CONFIG_EXT_REFS
+
// Current thread holds the reference frame.
if (cm->ref_frame_map[ref_index] >= 0)
++frame_bufs[cm->ref_frame_map[ref_index]].ref_count;
+
++ref_index;
}
for (; ref_index < REF_FRAMES; ++ref_index) {
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
+
// Current thread holds the reference frame.
if (cm->ref_frame_map[ref_index] >= 0)
++frame_bufs[cm->ref_frame_map[ref_index]].ref_count;
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index d66ddd9..ea21c8b 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -534,12 +534,68 @@
if (mode == COMPOUND_REFERENCE) {
const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int ctx = vp10_get_pred_context_comp_ref_p(cm, xd);
- const int bit = vpx_read(r, fc->comp_ref_prob[ctx]);
+ const int bit = vpx_read(r, fc->comp_ref_prob[ctx][0]);
if (counts)
- ++counts->comp_ref[ctx][bit];
+ ++counts->comp_ref[ctx][0][bit];
ref_frame[idx] = cm->comp_fixed_ref;
+
+#if CONFIG_EXT_REFS
+ if (!bit) {
+ const int ctx1 = vp10_get_pred_context_comp_ref_p1(cm, xd);
+ const int bit1 = vpx_read(r, fc->comp_ref_prob[ctx1][1]);
+ if (counts)
+ ++counts->comp_ref[ctx1][1][bit1];
+ ref_frame[!idx] = cm->comp_var_ref[bit1 ? 0 : 1];
+ } else {
+ const int ctx2 = vp10_get_pred_context_comp_ref_p2(cm, xd);
+ const int bit2 = vpx_read(r, fc->comp_ref_prob[ctx2][2]);
+ if (counts)
+ ++counts->comp_ref[ctx2][2][bit2];
+ if (!bit2) {
+ const int ctx3 = vp10_get_pred_context_comp_ref_p3(cm, xd);
+ const int bit3 = vpx_read(r, fc->comp_ref_prob[ctx3][3]);
+ if (counts)
+ ++counts->comp_ref[ctx3][3][bit3];
+ ref_frame[!idx] = cm->comp_var_ref[bit3 ? 2 : 3];
+ } else {
+ ref_frame[!idx] = cm->comp_var_ref[4];
+ }
+ }
+#else
ref_frame[!idx] = cm->comp_var_ref[bit];
+#endif // CONFIG_EXT_REFS
} else if (mode == SINGLE_REFERENCE) {
+#if CONFIG_EXT_REFS
+ const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
+ const int bit0 = vpx_read(r, fc->single_ref_prob[ctx0][0]);
+ if (counts)
+ ++counts->single_ref[ctx0][0][bit0];
+ if (bit0) {
+ const int ctx1 = vp10_get_pred_context_single_ref_p2(xd);
+ const int bit1 = vpx_read(r, fc->single_ref_prob[ctx1][1]);
+ if (counts)
+ ++counts->single_ref[ctx1][1][bit1];
+ ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
+ } else {
+ const int ctx2 = vp10_get_pred_context_single_ref_p3(xd);
+ const int bit2 = vpx_read(r, fc->single_ref_prob[ctx2][2]);
+ if (counts)
+ ++counts->single_ref[ctx2][2][bit2];
+ if (bit2) {
+ const int ctx4 = vp10_get_pred_context_single_ref_p5(xd);
+ const int bit4 = vpx_read(r, fc->single_ref_prob[ctx4][4]);
+ if (counts)
+ ++counts->single_ref[ctx4][4][bit4];
+ ref_frame[0] = bit4 ? LAST4_FRAME : LAST3_FRAME;
+ } else {
+ const int ctx3 = vp10_get_pred_context_single_ref_p4(xd);
+ const int bit3 = vpx_read(r, fc->single_ref_prob[ctx3][3]);
+ if (counts)
+ ++counts->single_ref[ctx3][3][bit3];
+ ref_frame[0] = bit3 ? LAST2_FRAME : LAST_FRAME;
+ }
+ }
+#else
const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
const int bit0 = vpx_read(r, fc->single_ref_prob[ctx0][0]);
if (counts)
@@ -553,6 +609,7 @@
} else {
ref_frame[0] = LAST_FRAME;
}
+#endif // CONFIG_EXT_REFS
ref_frame[1] = NONE;
} else {
diff --git a/vp10/decoder/decoder.c b/vp10/decoder/decoder.c
index 7499230..2dbadb3 100644
--- a/vp10/decoder/decoder.c
+++ b/vp10/decoder/decoder.c
@@ -196,10 +196,23 @@
// later commit that adds VP9-specific controls for this functionality.
if (ref_frame_flag == VP9_LAST_FLAG) {
ref_buf = &cm->frame_refs[0];
+#if CONFIG_EXT_REFS
+ } else if (ref_frame_flag == VP9_LAST2_FLAG) {
+ ref_buf = &cm->frame_refs[1];
+ } else if (ref_frame_flag == VP9_LAST3_FLAG) {
+ ref_buf = &cm->frame_refs[2];
+ } else if (ref_frame_flag == VP9_LAST4_FLAG) {
+ ref_buf = &cm->frame_refs[3];
+ } else if (ref_frame_flag == VP9_GOLD_FLAG) {
+ ref_buf = &cm->frame_refs[4];
+ } else if (ref_frame_flag == VP9_ALT_FLAG) {
+ ref_buf = &cm->frame_refs[5];
+#else
} else if (ref_frame_flag == VP9_GOLD_FLAG) {
ref_buf = &cm->frame_refs[1];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
ref_buf = &cm->frame_refs[2];
+#endif // CONFIG_EXT_REFS
} else {
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Invalid reference frame");
@@ -243,10 +256,10 @@
// Current thread releases the holding of reference frame.
decrease_ref_count(old_idx, frame_bufs, pool);
- // Release the reference frame in reference map.
- if ((mask & 1) && old_idx >= 0) {
+ // Release the reference frame holding in the reference map for the decoding
+ // of the next frame.
+ if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
- }
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
++ref_index;
}
@@ -268,7 +281,7 @@
}
// Invalidate these references until the next frame starts.
- for (ref_index = 0; ref_index < 3; ref_index++)
+ for (ref_index = 0; ref_index < REFS_PER_FRAME; ref_index++)
cm->frame_refs[ref_index].idx = -1;
}
@@ -326,7 +339,6 @@
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
}
-
if (setjmp(cm->error.jmp)) {
const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
int i;
@@ -350,10 +362,10 @@
// Current thread releases the holding of reference frame.
decrease_ref_count(old_idx, frame_bufs, pool);
- // Release the reference frame in reference map.
- if ((mask & 1) && old_idx >= 0) {
+ // Release the reference frame holding in the reference map for the
+ // decoding of the next frame.
+ if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
- }
++ref_index;
}
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index a80e5bd..3fdad0c 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -484,15 +484,58 @@
}
if (is_compound) {
- vpx_write(w, mbmi->ref_frame[0] == GOLDEN_FRAME,
- vp10_get_pred_prob_comp_ref_p(cm, xd));
+#if CONFIG_EXT_REFS
+ const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
+ mbmi->ref_frame[0] == LAST3_FRAME ||
+ mbmi->ref_frame[0] == LAST4_FRAME);
+#else
+ const int bit = mbmi->ref_frame[0] == GOLDEN_FRAME;
+#endif // CONFIG_EXT_REFS
+ vpx_write(w, bit, vp10_get_pred_prob_comp_ref_p(cm, xd));
+
+#if CONFIG_EXT_REFS
+ if (!bit) {
+ const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
+ vpx_write(w, bit1, vp10_get_pred_prob_comp_ref_p1(cm, xd));
+ } else {
+ const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
+ vpx_write(w, bit2, vp10_get_pred_prob_comp_ref_p2(cm, xd));
+ if (!bit2) {
+ const int bit3 = mbmi->ref_frame[0] == LAST3_FRAME;
+ vpx_write(w, bit3, vp10_get_pred_prob_comp_ref_p3(cm, xd));
+ }
+ }
+#endif // CONFIG_EXT_REFS
} else {
+#if CONFIG_EXT_REFS
+ const int bit0 = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
+ mbmi->ref_frame[0] == ALTREF_FRAME);
+ vpx_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
+
+ if (bit0) {
+ const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
+ vpx_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
+ } else {
+ const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
+ mbmi->ref_frame[0] == LAST4_FRAME);
+ vpx_write(w, bit2, vp10_get_pred_prob_single_ref_p3(cm, xd));
+
+ if (!bit2) {
+ const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
+ vpx_write(w, bit3, vp10_get_pred_prob_single_ref_p4(cm, xd));
+ } else {
+ const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
+ vpx_write(w, bit4, vp10_get_pred_prob_single_ref_p5(cm, xd));
+ }
+ }
+#else
const int bit0 = mbmi->ref_frame[0] != LAST_FRAME;
vpx_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
if (bit0) {
const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
vpx_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
}
+#endif // CONFIG_EXT_REFS
}
}
}
@@ -1406,6 +1449,11 @@
// and this needs to be generalized as other uses are implemented
// (like RTC/temporal scalability).
return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+#if CONFIG_EXT_REFS
+ (cpi->refresh_last2_frame << cpi->lst2_fb_idx) |
+ (cpi->refresh_last3_frame << cpi->lst3_fb_idx) |
+ (cpi->refresh_last4_frame << cpi->lst4_fb_idx) |
+#endif // CONFIG_EXT_REFS
(cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
@@ -1414,6 +1462,11 @@
arf_idx = gf_group->arf_update_idx[gf_group->index];
}
return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+#if CONFIG_EXT_REFS
+ (cpi->refresh_last2_frame << cpi->lst2_fb_idx) |
+ (cpi->refresh_last3_frame << cpi->lst3_fb_idx) |
+ (cpi->refresh_last4_frame << cpi->lst4_fb_idx) |
+#endif // CONFIG_EXT_REFS
(cpi->refresh_golden_frame << cpi->gld_fb_idx) |
(cpi->refresh_alt_ref_frame << arf_idx);
}
@@ -1584,6 +1637,13 @@
vpx_wb_write_bit(wb, cm->show_frame);
vpx_wb_write_bit(wb, cm->error_resilient_mode);
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame =
+ (cm->frame_type == KEY_FRAME || cpi->refresh_last_frame) ? 1 : 0;
+ cpi->refresh_last3_frame = cpi->refresh_last2_frame ? 1 : 0;
+ cpi->refresh_last4_frame = cpi->refresh_last3_frame ? 1 : 0;
+#endif // CONFIG_EXT_REFS
+
if (cm->frame_type == KEY_FRAME) {
write_sync_code(wb);
write_bitdepth_colorspace_sampling(cm, wb);
@@ -1715,17 +1775,21 @@
if (cm->reference_mode != COMPOUND_REFERENCE) {
for (i = 0; i < REF_CONTEXTS; i++) {
- vp10_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][0],
- counts->single_ref[i][0]);
- vp10_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][1],
- counts->single_ref[i][1]);
+ for (j = 0; j < (SINGLE_REFS - 1); j ++) {
+ vp10_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][j],
+ counts->single_ref[i][j]);
+ }
}
}
- if (cm->reference_mode != SINGLE_REFERENCE)
- for (i = 0; i < REF_CONTEXTS; i++)
- vp10_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i],
- counts->comp_ref[i]);
+ if (cm->reference_mode != SINGLE_REFERENCE) {
+ for (i = 0; i < REF_CONTEXTS; i++) {
+ for (j = 0; j < (COMP_REFS - 1); j ++) {
+ vp10_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i][j],
+ counts->comp_ref[i][j]);
+ }
+ }
+ }
for (i = 0; i < BLOCK_SIZE_GROUPS; ++i)
prob_diff_update(vp10_intra_mode_tree, cm->fc->y_mode_prob[i],
diff --git a/vp10/encoder/denoiser.c b/vp10/encoder/denoiser.c
index e5d8157..c4955fe 100644
--- a/vp10/encoder/denoiser.c
+++ b/vp10/encoder/denoiser.c
@@ -398,6 +398,14 @@
&denoiser->running_avg_y[INTRA_FRAME]);
}
if (refresh_last_frame) {
+#if CONFIG_EXT_REFS
+ swap_frame_buffer(&denoiser->running_avg_y[LAST4_FRAME],
+ &denoiser->running_avg_y[LAST3_FRAME]);
+ swap_frame_buffer(&denoiser->running_avg_y[LAST3_FRAME],
+ &denoiser->running_avg_y[LAST2_FRAME]);
+ swap_frame_buffer(&denoiser->running_avg_y[LAST2_FRAME],
+ &denoiser->running_avg_y[LAST_FRAME]);
+#endif // CONFIG_EXT_REFS
swap_frame_buffer(&denoiser->running_avg_y[LAST_FRAME],
&denoiser->running_avg_y[INTRA_FRAME]);
}
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 127cd04..c57b224 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -1282,14 +1282,51 @@
[has_second_ref(mbmi)]++;
if (has_second_ref(mbmi)) {
- counts->comp_ref[vp10_get_pred_context_comp_ref_p(cm, xd)]
+#if CONFIG_EXT_REFS
+ const int bit = (ref0 == GOLDEN_FRAME || ref0 == LAST3_FRAME ||
+ ref0 == LAST4_FRAME);
+ counts->comp_ref[vp10_get_pred_context_comp_ref_p(cm, xd)][0][bit]++;
+ if (!bit) {
+ counts->comp_ref[vp10_get_pred_context_comp_ref_p1(cm, xd)][1]
+ [ref0 == LAST_FRAME]++;
+ } else {
+ counts->comp_ref[vp10_get_pred_context_comp_ref_p2(cm, xd)][2]
+ [ref0 == GOLDEN_FRAME]++;
+ if (ref0 != GOLDEN_FRAME) {
+ counts->comp_ref[vp10_get_pred_context_comp_ref_p3(cm, xd)][3]
+ [ref0 == LAST3_FRAME]++;
+ }
+ }
+#else
+ counts->comp_ref[vp10_get_pred_context_comp_ref_p(cm, xd)][0]
[ref0 == GOLDEN_FRAME]++;
+#endif // CONFIG_EXT_REFS
} else {
+#if CONFIG_EXT_REFS
+ const int bit = (ref0 == ALTREF_FRAME || ref0 == GOLDEN_FRAME);
+ counts->single_ref[vp10_get_pred_context_single_ref_p1(xd)][0][bit]++;
+ if (bit) {
+ counts->single_ref[vp10_get_pred_context_single_ref_p2(xd)][1]
+ [ref0 != GOLDEN_FRAME]++;
+ } else {
+ const int bit1 = !(ref0 == LAST2_FRAME || ref0 == LAST_FRAME);
+ counts->single_ref[vp10_get_pred_context_single_ref_p3(xd)][2]
+ [bit1]++;
+ if (!bit1) {
+ counts->single_ref[vp10_get_pred_context_single_ref_p4(xd)][3]
+ [ref0 != LAST_FRAME]++;
+ } else {
+ counts->single_ref[vp10_get_pred_context_single_ref_p5(xd)][4]
+ [ref0 != LAST3_FRAME]++;
+ }
+ }
+#else
counts->single_ref[vp10_get_pred_context_single_ref_p1(xd)][0]
[ref0 != LAST_FRAME]++;
if (ref0 != LAST_FRAME)
counts->single_ref[vp10_get_pred_context_single_ref_p2(xd)][1]
[ref0 != GOLDEN_FRAME]++;
+#endif // CONFIG_EXT_REFS
}
}
}
@@ -2670,8 +2707,14 @@
if (segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) {
return 0;
} else {
- return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG)
- + !!(ref_flags & VP9_ALT_FLAG)) >= 2;
+ return (!!(ref_flags & VP9_GOLD_FLAG) +
+ !!(ref_flags & VP9_LAST_FLAG) +
+#if CONFIG_EXT_REFS
+ !!(ref_flags & VP9_LAST2_FLAG) +
+ !!(ref_flags & VP9_LAST3_FLAG) +
+ !!(ref_flags & VP9_LAST4_FLAG) +
+#endif // CONFIG_EXT_REFS
+ !!(ref_flags & VP9_ALT_FLAG)) >= 2;
}
}
@@ -2696,6 +2739,8 @@
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
return GOLDEN_FRAME;
else
+ // TODO(zoeliu): TO investigate whether a frame_type other than
+ // INTRA/ALTREF/GOLDEN/LAST needs to be specified seperately.
return LAST_FRAME;
}
@@ -2914,7 +2959,14 @@
cpi->allow_comp_inter_inter = 1;
cm->comp_fixed_ref = ALTREF_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
+#if CONFIG_EXT_REFS
+ cm->comp_var_ref[1] = LAST2_FRAME;
+ cm->comp_var_ref[2] = LAST3_FRAME;
+ cm->comp_var_ref[3] = LAST4_FRAME;
+ cm->comp_var_ref[4] = GOLDEN_FRAME;
+#else
cm->comp_var_ref[1] = GOLDEN_FRAME;
+#endif // CONFIG_EXT_REFS
}
} else {
cpi->allow_comp_inter_inter = 0;
@@ -2930,9 +2982,12 @@
// either compound, single or hybrid prediction as per whatever has
// worked best for that type of frame in the past.
// It also predicts whether another coding mode would have worked
- // better that this coding mode. If that is the case, it remembers
+ // better than this coding mode. If that is the case, it remembers
// that for subsequent frames.
// It does the same analysis for transform size selection also.
+ //
+ // TODO(zoeliu): TO investigate whether a frame_type other than
+ // INTRA/ALTREF/GOLDEN/LAST needs to be specified seperately.
const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
int64_t *const mode_thrs = rd_opt->prediction_type_threshes[frame_type];
int64_t *const filter_thrs = rd_opt->filter_threshes[frame_type];
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index c9911f8..7746839 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -718,8 +718,16 @@
static void init_buffer_indices(VP10_COMP *cpi) {
cpi->lst_fb_idx = 0;
+#if CONFIG_EXT_REFS
+ cpi->lst2_fb_idx = 1;
+ cpi->lst3_fb_idx = 2;
+ cpi->lst4_fb_idx = 3;
+ cpi->gld_fb_idx = 4;
+ cpi->alt_fb_idx = 5;
+#else
cpi->gld_fb_idx = 1;
cpi->alt_fb_idx = 2;
+#endif // CONFIG_EXT_REFS
}
static void init_config(struct VP10_COMP *cpi, VP10EncoderConfig *oxcf) {
@@ -1422,6 +1430,12 @@
cpi->refresh_golden_frame = 0;
cpi->refresh_last_frame = 1;
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame = 0;
+ cpi->refresh_last3_frame = 0;
+ cpi->refresh_last4_frame = 0;
+#endif // CONFIG_EXT_REFS
+
cm->refresh_frame_context =
oxcf->error_resilient_mode ? REFRESH_FRAME_CONTEXT_OFF :
oxcf->frame_parallel_decoding_mode ? REFRESH_FRAME_CONTEXT_FORWARD
@@ -2279,7 +2293,7 @@
}
int vp10_use_as_reference(VP10_COMP *cpi, int ref_frame_flags) {
- if (ref_frame_flags > 7)
+ if (ref_frame_flags > ((1 << REFS_PER_FRAME) - 1))
return -1;
cpi->ref_frame_flags = ref_frame_flags;
@@ -2290,6 +2304,11 @@
cpi->ext_refresh_golden_frame = (ref_frame_flags & VP9_GOLD_FLAG) != 0;
cpi->ext_refresh_alt_ref_frame = (ref_frame_flags & VP9_ALT_FLAG) != 0;
cpi->ext_refresh_last_frame = (ref_frame_flags & VP9_LAST_FLAG) != 0;
+#if CONFIG_EXT_REFS
+ cpi->ext_refresh_last2_frame = (ref_frame_flags & VP9_LAST2_FLAG) != 0;
+ cpi->ext_refresh_last3_frame = (ref_frame_flags & VP9_LAST3_FLAG) != 0;
+ cpi->ext_refresh_last4_frame = (ref_frame_flags & VP9_LAST4_FLAG) != 0;
+#endif // CONFIG_EXT_REFS
cpi->ext_refresh_frame_flags_pending = 1;
}
@@ -2298,6 +2317,14 @@
MV_REFERENCE_FRAME ref_frame = NONE;
if (ref_frame_flag == VP9_LAST_FLAG)
ref_frame = LAST_FRAME;
+#if CONFIG_EXT_REFS
+ else if (ref_frame_flag == VP9_LAST2_FLAG)
+ ref_frame = LAST2_FRAME;
+ else if (ref_frame_flag == VP9_LAST3_FLAG)
+ ref_frame = LAST3_FRAME;
+ else if (ref_frame_flag == VP9_LAST4_FLAG)
+ ref_frame = LAST4_FRAME;
+#endif // CONFIG_EXT_REFS
else if (ref_frame_flag == VP9_GOLD_FLAG)
ref_frame = GOLDEN_FRAME;
else if (ref_frame_flag == VP9_ALT_FLAG)
@@ -2634,12 +2661,82 @@
}
if (cpi->refresh_last_frame) {
+#if CONFIG_EXT_REFS
+ if (cpi->refresh_last2_frame) {
+ if (cpi->refresh_last3_frame) {
+ if (cpi->refresh_last4_frame) {
+ if (cm->frame_type == KEY_FRAME)
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst4_fb_idx],
+ cm->new_fb_idx);
+ else
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst4_fb_idx],
+ cm->ref_frame_map[cpi->lst3_fb_idx]);
+ }
+
+ if (cm->frame_type == KEY_FRAME)
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst3_fb_idx],
+ cm->new_fb_idx);
+ else
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst3_fb_idx],
+ cm->ref_frame_map[cpi->lst2_fb_idx]);
+ }
+
+ if (cm->frame_type == KEY_FRAME)
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst2_fb_idx],
+ cm->new_fb_idx);
+ else
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst2_fb_idx],
+ cm->ref_frame_map[cpi->lst_fb_idx]);
+ }
+#endif // CONFIG_EXT_REFS
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
- if (!cpi->rc.is_src_frame_alt_ref)
+
+ if (!cpi->rc.is_src_frame_alt_ref) {
+#if CONFIG_EXT_REFS
+ if (cpi->refresh_last2_frame) {
+ if (cpi->refresh_last3_frame) {
+ if (cpi->refresh_last4_frame) {
+ if (cm->frame_type == KEY_FRAME)
+ memcpy(cpi->interp_filter_selected[LAST4_FRAME],
+ cpi->interp_filter_selected[0],
+ sizeof(cpi->interp_filter_selected[0]));
+ else
+ memcpy(cpi->interp_filter_selected[LAST4_FRAME],
+ cpi->interp_filter_selected[LAST3_FRAME],
+ sizeof(cpi->interp_filter_selected[LAST3_FRAME]));
+ }
+
+ if (cm->frame_type == KEY_FRAME)
+ memcpy(cpi->interp_filter_selected[LAST3_FRAME],
+ cpi->interp_filter_selected[0],
+ sizeof(cpi->interp_filter_selected[0]));
+ else
+ memcpy(cpi->interp_filter_selected[LAST3_FRAME],
+ cpi->interp_filter_selected[LAST2_FRAME],
+ sizeof(cpi->interp_filter_selected[LAST2_FRAME]));
+ }
+
+ if (cm->frame_type == KEY_FRAME)
+ memcpy(cpi->interp_filter_selected[LAST2_FRAME],
+ cpi->interp_filter_selected[0],
+ sizeof(cpi->interp_filter_selected[0]));
+ else
+ memcpy(cpi->interp_filter_selected[LAST2_FRAME],
+ cpi->interp_filter_selected[LAST_FRAME],
+ sizeof(cpi->interp_filter_selected[LAST_FRAME]));
+ }
+#endif // CONFIG_EXT_REFS
memcpy(cpi->interp_filter_selected[LAST_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
+ }
}
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0) {
@@ -2706,7 +2803,16 @@
void vp10_scale_references(VP10_COMP *cpi) {
VP10_COMMON *cm = &cpi->common;
MV_REFERENCE_FRAME ref_frame;
- const VP9_REFFRAME ref_mask[3] = {VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG};
+ const VP9_REFFRAME ref_mask[REFS_PER_FRAME] = {
+ VP9_LAST_FLAG,
+#if CONFIG_EXT_REFS
+ VP9_LAST2_FLAG,
+ VP9_LAST3_FLAG,
+ VP9_LAST4_FLAG,
+#endif // CONFIG_EXT_REFS
+ VP9_GOLD_FLAG,
+ VP9_ALT_FLAG
+ };
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
// Need to convert from VP9_REFFRAME to index into ref_mask (subtract 1).
@@ -2791,10 +2897,18 @@
if (cpi->oxcf.pass == 0) {
// Only release scaled references under certain conditions:
// if reference will be updated, or if scaled reference has same resolution.
- int refresh[3];
+ int refresh[REFS_PER_FRAME];
refresh[0] = (cpi->refresh_last_frame) ? 1 : 0;
+#if CONFIG_EXT_REFS
+ refresh[1] = (cpi->refresh_last2_frame) ? 1 : 0;
+ refresh[2] = (cpi->refresh_last3_frame) ? 1 : 0;
+ refresh[3] = (cpi->refresh_last4_frame) ? 1 : 0;
+ refresh[4] = (cpi->refresh_golden_frame) ? 1 : 0;
+ refresh[5] = (cpi->refresh_alt_ref_frame) ? 1 : 0;
+#else
refresh[1] = (cpi->refresh_golden_frame) ? 1 : 0;
refresh[2] = (cpi->refresh_alt_ref_frame) ? 1 : 0;
+#endif // CONFIG_EXT_REFS
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
const int idx = cpi->scaled_ref_idx[i - 1];
RefCntBuffer *const buf = idx != INVALID_IDX ?
@@ -3428,7 +3542,30 @@
const int gold_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx];
const int gold_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
+
+#if CONFIG_EXT_REFS
+ const int last2_is_last = map[cpi->lst2_fb_idx] == map[cpi->lst_fb_idx];
+ const int gld_is_last2 = map[cpi->gld_fb_idx] == map[cpi->lst2_fb_idx];
+ const int alt_is_last2 = map[cpi->alt_fb_idx] == map[cpi->lst2_fb_idx];
+
+ const int last3_is_last = map[cpi->lst3_fb_idx] == map[cpi->lst_fb_idx];
+ const int last3_is_last2 = map[cpi->lst3_fb_idx] == map[cpi->lst2_fb_idx];
+ const int gld_is_last3 = map[cpi->gld_fb_idx] == map[cpi->lst3_fb_idx];
+ const int alt_is_last3 = map[cpi->alt_fb_idx] == map[cpi->lst3_fb_idx];
+
+ const int last4_is_last = map[cpi->lst4_fb_idx] == map[cpi->lst_fb_idx];
+ const int last4_is_last2 = map[cpi->lst4_fb_idx] == map[cpi->lst2_fb_idx];
+ const int last4_is_last3 = map[cpi->lst4_fb_idx] == map[cpi->lst3_fb_idx];
+ const int gld_is_last4 = map[cpi->gld_fb_idx] == map[cpi->lst4_fb_idx];
+ const int alt_is_last4 = map[cpi->alt_fb_idx] == map[cpi->lst4_fb_idx];
+#endif // CONFIG_EXT_REFS
+
int flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
+#if CONFIG_EXT_REFS
+ flags |= VP9_LAST2_FLAG;
+ flags |= VP9_LAST3_FLAG;
+ flags |= VP9_LAST4_FLAG;
+#endif // CONFIG_EXT_REFS
if (gold_is_last)
flags &= ~VP9_GOLD_FLAG;
@@ -3442,6 +3579,35 @@
if (gold_is_alt)
flags &= ~VP9_ALT_FLAG;
+#if CONFIG_EXT_REFS
+ if (last4_is_last || last4_is_last2 || last4_is_last3)
+ flags &= ~VP9_LAST4_FLAG;
+
+ if (gld_is_last4)
+ flags &= ~VP9_GOLD_FLAG;
+
+ if (alt_is_last4)
+ flags &= ~VP9_ALT_FLAG;
+
+ if (last3_is_last || last3_is_last2)
+ flags &= ~VP9_LAST3_FLAG;
+
+ if (gld_is_last3)
+ flags &= ~VP9_GOLD_FLAG;
+
+ if (alt_is_last3)
+ flags &= ~VP9_ALT_FLAG;
+
+ if (last2_is_last)
+ flags &= ~VP9_LAST2_FLAG;
+
+ if (gld_is_last2)
+ flags &= ~VP9_GOLD_FLAG;
+
+ if (alt_is_last2)
+ flags &= ~VP9_ALT_FLAG;
+#endif // CONFIG_EXT_REFS
+
return flags;
}
@@ -3456,6 +3622,11 @@
}
if (cpi->ext_refresh_frame_flags_pending) {
cpi->refresh_last_frame = cpi->ext_refresh_last_frame;
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame = cpi->ext_refresh_last2_frame;
+ cpi->refresh_last3_frame = cpi->ext_refresh_last3_frame;
+ cpi->refresh_last4_frame = cpi->ext_refresh_last4_frame;
+#endif // CONFIG_EXT_REFS
cpi->refresh_golden_frame = cpi->ext_refresh_golden_frame;
cpi->refresh_alt_ref_frame = cpi->ext_refresh_alt_ref_frame;
cpi->ext_refresh_frame_flags_pending = 0;
@@ -3524,6 +3695,17 @@
for (ifilter = EIGHTTAP; ifilter <= EIGHTTAP_SHARP; ++ifilter) {
if ((ref_total[LAST_FRAME] &&
cpi->interp_filter_selected[LAST_FRAME][ifilter] == 0) &&
+#if CONFIG_EXT_REFS
+ (ref_total[LAST2_FRAME] == 0 ||
+ cpi->interp_filter_selected[LAST2_FRAME][ifilter] * 50
+ < ref_total[LAST2_FRAME]) &&
+ (ref_total[LAST3_FRAME] == 0 ||
+ cpi->interp_filter_selected[LAST3_FRAME][ifilter] * 50
+ < ref_total[LAST3_FRAME]) &&
+ (ref_total[LAST4_FRAME] == 0 ||
+ cpi->interp_filter_selected[LAST4_FRAME][ifilter] * 50
+ < ref_total[LAST4_FRAME]) &&
+#endif // CONFIG_EXT_REFS
(ref_total[GOLDEN_FRAME] == 0 ||
cpi->interp_filter_selected[GOLDEN_FRAME][ifilter] * 50
< ref_total[GOLDEN_FRAME]) &&
@@ -3691,6 +3873,10 @@
cpi->ref_frame_flags = get_ref_frame_flags(cpi);
+#if CONFIG_EXT_REFS
+ cm->last3_frame_type = cm->last2_frame_type;
+ cm->last2_frame_type = cm->last_frame_type;
+#endif // CONFIG_EXT_REFS
cm->last_frame_type = cm->frame_type;
vp10_rc_postencode_update(cpi, *size);
@@ -3854,6 +4040,11 @@
return cm->frame_type == KEY_FRAME ||
cpi->refresh_last_frame ||
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame ||
+ cpi->refresh_last3_frame ||
+ cpi->refresh_last4_frame ||
+#endif // CONFIG_EXT_REFS
cpi->refresh_golden_frame ||
cpi->refresh_alt_ref_frame ||
cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF ||
@@ -3990,6 +4181,11 @@
: REFRESH_FRAME_CONTEXT_BACKWARD;
cpi->refresh_last_frame = 1;
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame = 0;
+ cpi->refresh_last3_frame = 0;
+ cpi->refresh_last4_frame = 0;
+#endif // CONFIG_EXT_REFS
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 0;
@@ -4014,6 +4210,11 @@
cpi->refresh_alt_ref_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_last_frame = 0;
+#if CONFIG_EXT_REFS
+ cpi->refresh_last2_frame = 0;
+ cpi->refresh_last3_frame = 0;
+ cpi->refresh_last4_frame = 0;
+#endif // CONFIG_EXT_REFS
rc->is_src_frame_alt_ref = 0;
rc->source_alt_ref_pending = 0;
} else {
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index e20b569..7b38000 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -304,15 +304,30 @@
int scaled_ref_idx[MAX_REF_FRAMES];
int lst_fb_idx;
+#if CONFIG_EXT_REFS
+ int lst2_fb_idx;
+ int lst3_fb_idx;
+ int lst4_fb_idx;
+#endif // CONFIG_EXT_REFS
int gld_fb_idx;
int alt_fb_idx;
int refresh_last_frame;
+#if CONFIG_EXT_REFS
+ int refresh_last2_frame;
+ int refresh_last3_frame;
+ int refresh_last4_frame;
+#endif // CONFIG_EXT_REFS
int refresh_golden_frame;
int refresh_alt_ref_frame;
int ext_refresh_frame_flags_pending;
int ext_refresh_last_frame;
+#if CONFIG_EXT_REFS
+ int ext_refresh_last2_frame;
+ int ext_refresh_last3_frame;
+ int ext_refresh_last4_frame;
+#endif // CONFIG_EXT_REFS
int ext_refresh_golden_frame;
int ext_refresh_alt_ref_frame;
@@ -554,6 +569,14 @@
MV_REFERENCE_FRAME ref_frame) {
if (ref_frame == LAST_FRAME) {
return cpi->lst_fb_idx;
+#if CONFIG_EXT_REFS
+ } else if (ref_frame == LAST2_FRAME) {
+ return cpi->lst2_fb_idx;
+ } else if (ref_frame == LAST3_FRAME) {
+ return cpi->lst3_fb_idx;
+ } else if (ref_frame == LAST4_FRAME) {
+ return cpi->lst4_fb_idx;
+#endif // CONFIG_EXT_REFS
} else if (ref_frame == GOLDEN_FRAME) {
return cpi->gld_fb_idx;
} else {
diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c
index cb32252..823e6b8 100644
--- a/vp10/encoder/rd.c
+++ b/vp10/encoder/rd.c
@@ -608,10 +608,20 @@
if (sf->adaptive_rd_thresh) {
rd->thresh_mult[THR_NEARESTMV] = 300;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_NEARESTL2] = 300;
+ rd->thresh_mult[THR_NEARESTL3] = 300;
+ rd->thresh_mult[THR_NEARESTL4] = 300;
+#endif // CONFIG_EXT_REFS
rd->thresh_mult[THR_NEARESTG] = 300;
rd->thresh_mult[THR_NEARESTA] = 300;
} else {
rd->thresh_mult[THR_NEARESTMV] = 0;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_NEARESTL2] = 0;
+ rd->thresh_mult[THR_NEARESTL3] = 0;
+ rd->thresh_mult[THR_NEARESTL4] = 0;
+#endif // CONFIG_EXT_REFS
rd->thresh_mult[THR_NEARESTG] = 0;
rd->thresh_mult[THR_NEARESTA] = 0;
}
@@ -619,26 +629,61 @@
rd->thresh_mult[THR_DC] += 1000;
rd->thresh_mult[THR_NEWMV] += 1000;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_NEWL2] += 1000;
+ rd->thresh_mult[THR_NEWL3] += 1000;
+ rd->thresh_mult[THR_NEWL4] += 1000;
+#endif // CONFIG_EXT_REFS
rd->thresh_mult[THR_NEWA] += 1000;
rd->thresh_mult[THR_NEWG] += 1000;
rd->thresh_mult[THR_NEARMV] += 1000;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_NEARL2] += 1000;
+ rd->thresh_mult[THR_NEARL3] += 1000;
+ rd->thresh_mult[THR_NEARL4] += 1000;
+#endif // CONFIG_EXT_REFS
rd->thresh_mult[THR_NEARA] += 1000;
- rd->thresh_mult[THR_COMP_NEARESTLA] += 1000;
- rd->thresh_mult[THR_COMP_NEARESTGA] += 1000;
+ rd->thresh_mult[THR_NEARG] += 1000;
+
+ rd->thresh_mult[THR_ZEROMV] += 2000;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_ZEROL2] += 2000;
+ rd->thresh_mult[THR_ZEROL3] += 2000;
+ rd->thresh_mult[THR_ZEROL4] += 2000;
+#endif // CONFIG_EXT_REFS
+ rd->thresh_mult[THR_ZEROG] += 2000;
+ rd->thresh_mult[THR_ZEROA] += 2000;
rd->thresh_mult[THR_TM] += 1000;
+ rd->thresh_mult[THR_COMP_NEARESTLA] += 1000;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_COMP_NEARESTL2A] += 1000;
+ rd->thresh_mult[THR_COMP_NEARESTL3A] += 1000;
+ rd->thresh_mult[THR_COMP_NEARESTL4A] += 1000;
+#endif // CONFIG_EXT_REFS
+ rd->thresh_mult[THR_COMP_NEARESTGA] += 1000;
+
rd->thresh_mult[THR_COMP_NEARLA] += 1500;
rd->thresh_mult[THR_COMP_NEWLA] += 2000;
- rd->thresh_mult[THR_NEARG] += 1000;
rd->thresh_mult[THR_COMP_NEARGA] += 1500;
rd->thresh_mult[THR_COMP_NEWGA] += 2000;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_COMP_NEARL2A] += 1500;
+ rd->thresh_mult[THR_COMP_NEWL2A] += 2000;
+ rd->thresh_mult[THR_COMP_NEARL3A] += 1500;
+ rd->thresh_mult[THR_COMP_NEWL3A] += 2000;
+ rd->thresh_mult[THR_COMP_NEARL4A] += 1500;
+ rd->thresh_mult[THR_COMP_NEWL4A] += 2000;
+#endif // CONFIG_EXT_REFS
- rd->thresh_mult[THR_ZEROMV] += 2000;
- rd->thresh_mult[THR_ZEROG] += 2000;
- rd->thresh_mult[THR_ZEROA] += 2000;
rd->thresh_mult[THR_COMP_ZEROLA] += 2500;
+#if CONFIG_EXT_REFS
+ rd->thresh_mult[THR_COMP_ZEROL2A] += 2500;
+ rd->thresh_mult[THR_COMP_ZEROL3A] += 2500;
+ rd->thresh_mult[THR_COMP_ZEROL4A] += 2500;
+#endif // CONFIG_EXT_REFS
rd->thresh_mult[THR_COMP_ZEROGA] += 2500;
rd->thresh_mult[THR_H_PRED] += 2000;
@@ -652,9 +697,15 @@
}
void vp10_set_rd_speed_thresholds_sub8x8(VP10_COMP *cpi) {
- static const int thresh_mult[2][MAX_REFS] =
- {{2500, 2500, 2500, 4500, 4500, 2500},
- {2000, 2000, 2000, 4000, 4000, 2000}};
+ static const int thresh_mult[2][MAX_REFS] = {
+#if CONFIG_EXT_REFS
+ {2500, 2500, 2500, 2500, 2500, 2500, 4500, 4500, 4500, 4500, 4500, 2500},
+ {2000, 2000, 2000, 2000, 2000, 2000, 4000, 4000, 4000, 4000, 4000, 2000}
+#else
+ {2500, 2500, 2500, 4500, 4500, 2500},
+ {2000, 2000, 2000, 4000, 4000, 2000}
+#endif // CONFIG_EXT_REFS
+ };
RD_OPT *const rd = &cpi->rd;
const int idx = cpi->oxcf.mode == BEST;
memcpy(rd->thresh_mult_sub8x8, thresh_mult[idx], sizeof(thresh_mult[idx]));
diff --git a/vp10/encoder/rd.h b/vp10/encoder/rd.h
index cd58bf8..42261ac 100644
--- a/vp10/encoder/rd.h
+++ b/vp10/encoder/rd.h
@@ -33,8 +33,17 @@
#define INVALID_MV 0x80008000
+#if CONFIG_EXT_REFS
+#define MAX_MODES 54
+#else
#define MAX_MODES 30
+#endif // CONFIG_EXT_REFS
+
+#if CONFIG_EXT_REFS
+#define MAX_REFS 12
+#else
#define MAX_REFS 6
+#endif // CONFIG_EXT_REFS
#define RD_THRESH_MAX_FACT 64
#define RD_THRESH_INC 1
@@ -43,34 +52,72 @@
// const MODE_DEFINITION vp10_mode_order[MAX_MODES] used in the rd code.
typedef enum {
THR_NEARESTMV,
+#if CONFIG_EXT_REFS
+ THR_NEARESTL2,
+ THR_NEARESTL3,
+ THR_NEARESTL4,
+#endif // CONFIG_EXT_REFS
THR_NEARESTA,
THR_NEARESTG,
THR_DC,
THR_NEWMV,
+#if CONFIG_EXT_REFS
+ THR_NEWL2,
+ THR_NEWL3,
+ THR_NEWL4,
+#endif // CONFIG_EXT_REFS
THR_NEWA,
THR_NEWG,
THR_NEARMV,
+#if CONFIG_EXT_REFS
+ THR_NEARL2,
+ THR_NEARL3,
+ THR_NEARL4,
+#endif // CONFIG_EXT_REFS
THR_NEARA,
THR_NEARG,
THR_ZEROMV,
+#if CONFIG_EXT_REFS
+ THR_ZEROL2,
+ THR_ZEROL3,
+ THR_ZEROL4,
+#endif // CONFIG_EXT_REFS
THR_ZEROG,
THR_ZEROA,
THR_COMP_NEARESTLA,
+#if CONFIG_EXT_REFS
+ THR_COMP_NEARESTL2A,
+ THR_COMP_NEARESTL3A,
+ THR_COMP_NEARESTL4A,
+#endif // CONFIG_EXT_REFS
THR_COMP_NEARESTGA,
THR_TM,
THR_COMP_NEARLA,
THR_COMP_NEWLA,
+#if CONFIG_EXT_REFS
+ THR_COMP_NEARL2A,
+ THR_COMP_NEWL2A,
+ THR_COMP_NEARL3A,
+ THR_COMP_NEWL3A,
+ THR_COMP_NEARL4A,
+ THR_COMP_NEWL4A,
+#endif // CONFIG_EXT_REFS
THR_COMP_NEARGA,
THR_COMP_NEWGA,
THR_COMP_ZEROLA,
+#if CONFIG_EXT_REFS
+ THR_COMP_ZEROL2A,
+ THR_COMP_ZEROL3A,
+ THR_COMP_ZEROL4A,
+#endif // CONFIG_EXT_REFS
THR_COMP_ZEROGA,
THR_H_PRED,
@@ -85,9 +132,19 @@
typedef enum {
THR_LAST,
+#if CONFIG_EXT_REFS
+ THR_LAST2,
+ THR_LAST3,
+ THR_LAST4,
+#endif // CONFIG_EXT_REFS
THR_GOLD,
THR_ALTR,
THR_COMP_LA,
+#if CONFIG_EXT_REFS
+ THR_COMP_L2A,
+ THR_COMP_L3A,
+ THR_COMP_L4A,
+#endif // CONFIG_EXT_REFS
THR_COMP_GA,
THR_INTRA,
} THR_MODES_SUB8X8;
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index 7562b60..ba7468e 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -43,6 +43,29 @@
#include "vp10/encoder/rdopt.h"
#include "vp10/encoder/aq_variance.h"
+#if CONFIG_EXT_REFS
+
+#define LAST_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << LAST2_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST3_FRAME) | (1 << LAST4_FRAME))
+#define LAST2_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << LAST_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST3_FRAME) | (1 << LAST4_FRAME))
+#define LAST3_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << LAST_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST2_FRAME) | (1 << LAST4_FRAME))
+#define LAST4_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << LAST_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST2_FRAME) | (1 << LAST3_FRAME))
+#define GOLDEN_FRAME_MODE_MASK ((1 << LAST_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << LAST2_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST3_FRAME) | (1 << LAST4_FRAME))
+#define ALT_REF_MODE_MASK ((1 << LAST_FRAME) | (1 << GOLDEN_FRAME) | \
+ (1 << LAST2_FRAME) | (1 << INTRA_FRAME) | \
+ (1 << LAST3_FRAME) | (1 << LAST4_FRAME))
+
+#else
+
#define LAST_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
(1 << INTRA_FRAME))
#define GOLDEN_FRAME_MODE_MASK ((1 << LAST_FRAME) | (1 << ALTREF_FRAME) | \
@@ -50,6 +73,8 @@
#define ALT_REF_MODE_MASK ((1 << LAST_FRAME) | (1 << GOLDEN_FRAME) | \
(1 << INTRA_FRAME))
+#endif // CONFIG_EXT_REFS
+
#define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | 0x01)
#define MIN_EARLY_TERM_INDEX 3
@@ -89,34 +114,72 @@
#define LAST_NEW_MV_INDEX 6
static const MODE_DEFINITION vp10_mode_order[MAX_MODES] = {
{NEARESTMV, {LAST_FRAME, NONE}},
+#if CONFIG_EXT_REFS
+ {NEARESTMV, {LAST2_FRAME, NONE}},
+ {NEARESTMV, {LAST3_FRAME, NONE}},
+ {NEARESTMV, {LAST4_FRAME, NONE}},
+#endif // CONFIG_EXT_REFS
{NEARESTMV, {ALTREF_FRAME, NONE}},
{NEARESTMV, {GOLDEN_FRAME, NONE}},
{DC_PRED, {INTRA_FRAME, NONE}},
{NEWMV, {LAST_FRAME, NONE}},
+#if CONFIG_EXT_REFS
+ {NEWMV, {LAST2_FRAME, NONE}},
+ {NEWMV, {LAST3_FRAME, NONE}},
+ {NEWMV, {LAST4_FRAME, NONE}},
+#endif // CONFIG_EXT_REFS
{NEWMV, {ALTREF_FRAME, NONE}},
{NEWMV, {GOLDEN_FRAME, NONE}},
{NEARMV, {LAST_FRAME, NONE}},
+#if CONFIG_EXT_REFS
+ {NEARMV, {LAST2_FRAME, NONE}},
+ {NEARMV, {LAST3_FRAME, NONE}},
+ {NEARMV, {LAST4_FRAME, NONE}},
+#endif // CONFIG_EXT_REFS
{NEARMV, {ALTREF_FRAME, NONE}},
{NEARMV, {GOLDEN_FRAME, NONE}},
{ZEROMV, {LAST_FRAME, NONE}},
+#if CONFIG_EXT_REFS
+ {ZEROMV, {LAST2_FRAME, NONE}},
+ {ZEROMV, {LAST3_FRAME, NONE}},
+ {ZEROMV, {LAST4_FRAME, NONE}},
+#endif // CONFIG_EXT_REFS
{ZEROMV, {GOLDEN_FRAME, NONE}},
{ZEROMV, {ALTREF_FRAME, NONE}},
{NEARESTMV, {LAST_FRAME, ALTREF_FRAME}},
+#if CONFIG_EXT_REFS
+ {NEARESTMV, {LAST2_FRAME, ALTREF_FRAME}},
+ {NEARESTMV, {LAST3_FRAME, ALTREF_FRAME}},
+ {NEARESTMV, {LAST4_FRAME, ALTREF_FRAME}},
+#endif // CONFIG_EXT_REFS
{NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}},
{TM_PRED, {INTRA_FRAME, NONE}},
{NEARMV, {LAST_FRAME, ALTREF_FRAME}},
{NEWMV, {LAST_FRAME, ALTREF_FRAME}},
+#if CONFIG_EXT_REFS
+ {NEARMV, {LAST2_FRAME, ALTREF_FRAME}},
+ {NEWMV, {LAST2_FRAME, ALTREF_FRAME}},
+ {NEARMV, {LAST3_FRAME, ALTREF_FRAME}},
+ {NEWMV, {LAST3_FRAME, ALTREF_FRAME}},
+ {NEARMV, {LAST4_FRAME, ALTREF_FRAME}},
+ {NEWMV, {LAST4_FRAME, ALTREF_FRAME}},
+#endif // CONFIG_EXT_REFS
{NEARMV, {GOLDEN_FRAME, ALTREF_FRAME}},
{NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}},
{ZEROMV, {LAST_FRAME, ALTREF_FRAME}},
+#if CONFIG_EXT_REFS
+ {ZEROMV, {LAST3_FRAME, ALTREF_FRAME}},
+ {ZEROMV, {LAST2_FRAME, ALTREF_FRAME}},
+ {ZEROMV, {LAST4_FRAME, ALTREF_FRAME}},
+#endif // CONFIG_EXT_REFS
{ZEROMV, {GOLDEN_FRAME, ALTREF_FRAME}},
{H_PRED, {INTRA_FRAME, NONE}},
@@ -131,9 +194,19 @@
static const REF_DEFINITION vp10_ref_order[MAX_REFS] = {
{{LAST_FRAME, NONE}},
+#if CONFIG_EXT_REFS
+ {{LAST2_FRAME, NONE}},
+ {{LAST3_FRAME, NONE}},
+ {{LAST4_FRAME, NONE}},
+#endif // CONFIG_EXT_REFS
{{GOLDEN_FRAME, NONE}},
{{ALTREF_FRAME, NONE}},
{{LAST_FRAME, ALTREF_FRAME}},
+#if CONFIG_EXT_REFS
+ {{LAST2_FRAME, ALTREF_FRAME}},
+ {{LAST3_FRAME, ALTREF_FRAME}},
+ {{LAST4_FRAME, ALTREF_FRAME}},
+#endif // CONFIG_EXT_REFS
{{GOLDEN_FRAME, ALTREF_FRAME}},
{{INTRA_FRAME, NONE}},
};
@@ -3677,34 +3750,108 @@
if (cm->reference_mode != COMPOUND_REFERENCE) {
vpx_prob ref_single_p1 = vp10_get_pred_prob_single_ref_p1(cm, xd);
vpx_prob ref_single_p2 = vp10_get_pred_prob_single_ref_p2(cm, xd);
+#if CONFIG_EXT_REFS
+ vpx_prob ref_single_p3 = vp10_get_pred_prob_single_ref_p3(cm, xd);
+ vpx_prob ref_single_p4 = vp10_get_pred_prob_single_ref_p4(cm, xd);
+ vpx_prob ref_single_p5 = vp10_get_pred_prob_single_ref_p5(cm, xd);
+#endif // CONFIG_EXT_REFS
unsigned int base_cost = vp10_cost_bit(intra_inter_p, 1);
if (cm->reference_mode == REFERENCE_MODE_SELECT)
base_cost += vp10_cost_bit(comp_inter_p, 0);
- ref_costs_single[LAST_FRAME] = ref_costs_single[GOLDEN_FRAME] =
+ ref_costs_single[LAST_FRAME] =
+#if CONFIG_EXT_REFS
+ ref_costs_single[LAST2_FRAME] =
+ ref_costs_single[LAST3_FRAME] =
+ ref_costs_single[LAST4_FRAME] =
+#endif // CONFIG_EXT_REFS
+ ref_costs_single[GOLDEN_FRAME] =
ref_costs_single[ALTREF_FRAME] = base_cost;
+
+#if CONFIG_EXT_REFS
+ ref_costs_single[LAST_FRAME] += vp10_cost_bit(ref_single_p1, 0);
+ ref_costs_single[LAST2_FRAME] += vp10_cost_bit(ref_single_p1, 0);
+ ref_costs_single[LAST3_FRAME] += vp10_cost_bit(ref_single_p1, 0);
+ ref_costs_single[LAST4_FRAME] += vp10_cost_bit(ref_single_p1, 0);
+ ref_costs_single[GOLDEN_FRAME] += vp10_cost_bit(ref_single_p1, 1);
+ ref_costs_single[ALTREF_FRAME] += vp10_cost_bit(ref_single_p1, 1);
+
+ ref_costs_single[LAST_FRAME] += vp10_cost_bit(ref_single_p3, 0);
+ ref_costs_single[LAST2_FRAME] += vp10_cost_bit(ref_single_p3, 0);
+ ref_costs_single[LAST3_FRAME] += vp10_cost_bit(ref_single_p3, 1);
+ ref_costs_single[LAST4_FRAME] += vp10_cost_bit(ref_single_p3, 1);
+ ref_costs_single[GOLDEN_FRAME] += vp10_cost_bit(ref_single_p2, 0);
+ ref_costs_single[ALTREF_FRAME] += vp10_cost_bit(ref_single_p2, 1);
+
+ ref_costs_single[LAST_FRAME] += vp10_cost_bit(ref_single_p4, 0);
+ ref_costs_single[LAST2_FRAME] += vp10_cost_bit(ref_single_p4, 1);
+ ref_costs_single[LAST3_FRAME] += vp10_cost_bit(ref_single_p5, 0);
+ ref_costs_single[LAST4_FRAME] += vp10_cost_bit(ref_single_p5, 1);
+#else
ref_costs_single[LAST_FRAME] += vp10_cost_bit(ref_single_p1, 0);
ref_costs_single[GOLDEN_FRAME] += vp10_cost_bit(ref_single_p1, 1);
ref_costs_single[ALTREF_FRAME] += vp10_cost_bit(ref_single_p1, 1);
ref_costs_single[GOLDEN_FRAME] += vp10_cost_bit(ref_single_p2, 0);
ref_costs_single[ALTREF_FRAME] += vp10_cost_bit(ref_single_p2, 1);
+#endif // CONFIG_EXT_REFS
} else {
ref_costs_single[LAST_FRAME] = 512;
+#if CONFIG_EXT_REFS
+ ref_costs_single[LAST2_FRAME] = 512;
+ ref_costs_single[LAST3_FRAME] = 512;
+ ref_costs_single[LAST4_FRAME] = 512;
+#endif // CONFIG_EXT_REFS
ref_costs_single[GOLDEN_FRAME] = 512;
ref_costs_single[ALTREF_FRAME] = 512;
}
+
if (cm->reference_mode != SINGLE_REFERENCE) {
vpx_prob ref_comp_p = vp10_get_pred_prob_comp_ref_p(cm, xd);
+#if CONFIG_EXT_REFS
+ vpx_prob ref_comp_p1 = vp10_get_pred_prob_comp_ref_p1(cm, xd);
+ vpx_prob ref_comp_p2 = vp10_get_pred_prob_comp_ref_p2(cm, xd);
+ vpx_prob ref_comp_p3 = vp10_get_pred_prob_comp_ref_p3(cm, xd);
+#endif // CONFIG_EXT_REFS
unsigned int base_cost = vp10_cost_bit(intra_inter_p, 1);
if (cm->reference_mode == REFERENCE_MODE_SELECT)
base_cost += vp10_cost_bit(comp_inter_p, 1);
- ref_costs_comp[LAST_FRAME] = base_cost + vp10_cost_bit(ref_comp_p, 0);
- ref_costs_comp[GOLDEN_FRAME] = base_cost + vp10_cost_bit(ref_comp_p, 1);
+ ref_costs_comp[LAST_FRAME] =
+#if CONFIG_EXT_REFS
+ ref_costs_comp[LAST2_FRAME] =
+ ref_costs_comp[LAST3_FRAME] =
+ ref_costs_comp[LAST4_FRAME] =
+#endif // CONFIG_EXT_REFS
+ ref_costs_comp[GOLDEN_FRAME] = base_cost;
+
+#if CONFIG_EXT_REFS
+ ref_costs_comp[LAST_FRAME] += vp10_cost_bit(ref_comp_p, 0);
+ ref_costs_comp[LAST2_FRAME] += vp10_cost_bit(ref_comp_p, 0);
+ ref_costs_comp[LAST3_FRAME] += vp10_cost_bit(ref_comp_p, 1);
+ ref_costs_comp[LAST4_FRAME] += vp10_cost_bit(ref_comp_p, 1);
+ ref_costs_comp[GOLDEN_FRAME] += vp10_cost_bit(ref_comp_p, 1);
+
+ ref_costs_comp[LAST_FRAME] += vp10_cost_bit(ref_comp_p1, 1);
+ ref_costs_comp[LAST2_FRAME] += vp10_cost_bit(ref_comp_p1, 0);
+ ref_costs_comp[LAST3_FRAME] += vp10_cost_bit(ref_comp_p2, 0);
+ ref_costs_comp[LAST4_FRAME] += vp10_cost_bit(ref_comp_p2, 0);
+ ref_costs_comp[GOLDEN_FRAME] += vp10_cost_bit(ref_comp_p2, 1);
+
+ ref_costs_comp[LAST3_FRAME] += vp10_cost_bit(ref_comp_p3, 1);
+ ref_costs_comp[LAST4_FRAME] += vp10_cost_bit(ref_comp_p3, 0);
+#else
+ ref_costs_comp[LAST_FRAME] += vp10_cost_bit(ref_comp_p, 0);
+ ref_costs_comp[GOLDEN_FRAME] += vp10_cost_bit(ref_comp_p, 1);
+#endif // CONFIG_EXT_REFS
} else {
ref_costs_comp[LAST_FRAME] = 512;
+#if CONFIG_EXT_REFS
+ ref_costs_comp[LAST2_FRAME] = 512;
+ ref_costs_comp[LAST3_FRAME] = 512;
+ ref_costs_comp[LAST4_FRAME] = 512;
+#endif // CONFIG_EXT_REFS
ref_costs_comp[GOLDEN_FRAME] = 512;
}
}
@@ -3732,13 +3879,14 @@
sizeof(*best_filter_diff) * SWITCHABLE_FILTER_CONTEXTS);
}
-static void setup_buffer_inter(VP10_COMP *cpi, MACROBLOCK *x,
- MV_REFERENCE_FRAME ref_frame,
- BLOCK_SIZE block_size,
- int mi_row, int mi_col,
- int_mv frame_nearest_mv[MAX_REF_FRAMES],
- int_mv frame_near_mv[MAX_REF_FRAMES],
- struct buf_2d yv12_mb[4][MAX_MB_PLANE]) {
+static void setup_buffer_inter(
+ VP10_COMP *cpi, MACROBLOCK *x,
+ MV_REFERENCE_FRAME ref_frame,
+ BLOCK_SIZE block_size,
+ int mi_row, int mi_col,
+ int_mv frame_nearest_mv[MAX_REF_FRAMES],
+ int_mv frame_near_mv[MAX_REF_FRAMES],
+ struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE]) {
const VP10_COMMON *cm = &cpi->common;
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
MACROBLOCKD *const xd = &x->e_mbd;
@@ -4551,12 +4699,21 @@
unsigned char segment_id = mbmi->segment_id;
int comp_pred, i, k;
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
- struct buf_2d yv12_mb[4][MAX_MB_PLANE];
+ struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE];
int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
INTERP_FILTER single_inter_filter[MB_MODE_COUNT][MAX_REF_FRAMES];
int single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
- static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
- VP9_ALT_FLAG };
+ static const int flag_list[REFS_PER_FRAME + 1] = {
+ 0,
+ VP9_LAST_FLAG,
+#if CONFIG_EXT_REFS
+ VP9_LAST2_FLAG,
+ VP9_LAST3_FLAG,
+ VP9_LAST4_FLAG,
+#endif // CONFIG_EXT_REFS
+ VP9_GOLD_FLAG,
+ VP9_ALT_FLAG
+ };
int64_t best_rd = best_rd_so_far;
int64_t best_pred_diff[REFERENCE_MODES];
int64_t best_pred_rd[REFERENCE_MODES];
@@ -4664,7 +4821,14 @@
// an unfiltered alternative. We allow near/nearest as well
// because they may result in zero-zero MVs but be cheaper.
if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
- ref_frame_skip_mask[0] = (1 << LAST_FRAME) | (1 << GOLDEN_FRAME);
+ ref_frame_skip_mask[0] =
+ (1 << LAST_FRAME) |
+#if CONFIG_EXT_REFS
+ (1 << LAST2_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << LAST4_FRAME) |
+#endif // CONFIG_EXT_REFS
+ (1 << GOLDEN_FRAME);
ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
mode_skip_mask[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
if (frame_mv[NEARMV][ALTREF_FRAME].as_int != 0)
@@ -4750,6 +4914,20 @@
ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK;
ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
break;
+#if CONFIG_EXT_REFS
+ case LAST2_FRAME:
+ ref_frame_skip_mask[0] |= LAST2_FRAME_MODE_MASK;
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+ case LAST3_FRAME:
+ ref_frame_skip_mask[0] |= LAST3_FRAME_MODE_MASK;
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+ case LAST4_FRAME:
+ ref_frame_skip_mask[0] |= LAST4_FRAME_MODE_MASK;
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+#endif // CONFIG_EXT_REFS
case GOLDEN_FRAME:
ref_frame_skip_mask[0] |= GOLDEN_FRAME_MODE_MASK;
ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
@@ -4771,6 +4949,20 @@
if (mode_skip_mask[ref_frame] & (1 << this_mode))
continue;
+#if CONFIG_EXT_REFS
+ if (cm->last_frame_type == KEY_FRAME && ref_frame == LAST2_FRAME)
+ continue;
+
+ if ((cm->last2_frame_type == KEY_FRAME ||
+ cm->last_frame_type == KEY_FRAME) && ref_frame == LAST3_FRAME)
+ continue;
+
+ if ((cm->last3_frame_type == KEY_FRAME ||
+ cm->last2_frame_type == KEY_FRAME ||
+ cm->last_frame_type == KEY_FRAME) && ref_frame == LAST4_FRAME)
+ continue;
+#endif // CONFIG_EXT_REFS
+
// Test best rd so far against threshold for trying this mode.
if (best_mode_skippable && sf->schedule_mode_search)
mode_threshold[mode_index] <<= 1;
@@ -5373,9 +5565,18 @@
unsigned char segment_id = mbmi->segment_id;
int comp_pred, i;
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
- struct buf_2d yv12_mb[4][MAX_MB_PLANE];
- static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
- VP9_ALT_FLAG };
+ struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE];
+ static const int flag_list[REFS_PER_FRAME + 1] = {
+ 0,
+ VP9_LAST_FLAG,
+#if CONFIG_EXT_REFS
+ VP9_LAST2_FLAG,
+ VP9_LAST3_FLAG,
+ VP9_LAST4_FLAG,
+#endif // CONFIG_EXT_REFS
+ VP9_GOLD_FLAG,
+ VP9_ALT_FLAG
+ };
int64_t best_rd = best_rd_so_far;
int64_t best_yrd = best_rd_so_far; // FIXME(rbultje) more precise
int64_t best_pred_diff[REFERENCE_MODES];
@@ -5462,6 +5663,20 @@
ref_frame = vp10_ref_order[ref_index].ref_frame[0];
second_ref_frame = vp10_ref_order[ref_index].ref_frame[1];
+#if CONFIG_EXT_REFS
+ if (cm->last_frame_type == KEY_FRAME && ref_frame == LAST2_FRAME)
+ continue;
+
+ if ((cm->last2_frame_type == KEY_FRAME ||
+ cm->last_frame_type == KEY_FRAME) && ref_frame == LAST3_FRAME)
+ continue;
+
+ if ((cm->last3_frame_type == KEY_FRAME ||
+ cm->last2_frame_type == KEY_FRAME ||
+ cm->last_frame_type == KEY_FRAME) && ref_frame == LAST4_FRAME)
+ continue;
+#endif // CONFIG_EXT_REFS
+
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (ref_index > 2 && sf->mode_skip_start < MAX_MODES) {
@@ -5470,15 +5685,59 @@
case INTRA_FRAME:
break;
case LAST_FRAME:
- ref_frame_skip_mask[0] |= (1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME);
+ ref_frame_skip_mask[0] |= (1 << GOLDEN_FRAME) |
+#if CONFIG_EXT_REFS
+ (1 << LAST2_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << LAST4_FRAME) |
+#endif // CONFIG_EXT_REFS
+ (1 << ALTREF_FRAME);
ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
break;
+#if CONFIG_EXT_REFS
+ case LAST2_FRAME:
+ ref_frame_skip_mask[0] |= (1 << LAST_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << LAST4_FRAME) |
+ (1 << GOLDEN_FRAME) |
+ (1 << ALTREF_FRAME);
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+ case LAST3_FRAME:
+ ref_frame_skip_mask[0] |= (1 << LAST_FRAME) |
+ (1 << LAST2_FRAME) |
+ (1 << LAST4_FRAME) |
+ (1 << GOLDEN_FRAME) |
+ (1 << ALTREF_FRAME);
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+ case LAST4_FRAME:
+ ref_frame_skip_mask[0] |= (1 << LAST_FRAME) |
+ (1 << LAST2_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << GOLDEN_FRAME) |
+ (1 << ALTREF_FRAME);
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+ break;
+#endif // CONFIG_EXT_REFS
case GOLDEN_FRAME:
- ref_frame_skip_mask[0] |= (1 << LAST_FRAME) | (1 << ALTREF_FRAME);
+ ref_frame_skip_mask[0] |= (1 << LAST_FRAME) |
+#if CONFIG_EXT_REFS
+ (1 << LAST2_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << LAST4_FRAME) |
+#endif // CONFIG_EXT_REFS
+ (1 << ALTREF_FRAME);
ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
break;
case ALTREF_FRAME:
- ref_frame_skip_mask[0] |= (1 << GOLDEN_FRAME) | (1 << LAST_FRAME);
+ ref_frame_skip_mask[0] |= (1 << GOLDEN_FRAME) |
+#if CONFIG_EXT_REFS
+ (1 << LAST2_FRAME) |
+ (1 << LAST3_FRAME) |
+ (1 << LAST4_FRAME) |
+#endif // CONFIG_EXT_REFS
+ (1 << LAST_FRAME);
break;
case NONE:
case MAX_REF_FRAMES:
@@ -5610,8 +5869,16 @@
this_rd_thresh = (ref_frame == LAST_FRAME) ?
rd_opt->threshes[segment_id][bsize][THR_LAST] :
rd_opt->threshes[segment_id][bsize][THR_ALTR];
+#if CONFIG_EXT_REFS
+ this_rd_thresh = (ref_frame == LAST2_FRAME) ?
+ rd_opt->threshes[segment_id][bsize][THR_LAST2] : this_rd_thresh;
+ this_rd_thresh = (ref_frame == LAST3_FRAME) ?
+ rd_opt->threshes[segment_id][bsize][THR_LAST3] : this_rd_thresh;
+ this_rd_thresh = (ref_frame == LAST4_FRAME) ?
+ rd_opt->threshes[segment_id][bsize][THR_LAST4] : this_rd_thresh;
+#endif // CONFIG_EXT_REFS
this_rd_thresh = (ref_frame == GOLDEN_FRAME) ?
- rd_opt->threshes[segment_id][bsize][THR_GOLD] : this_rd_thresh;
+ rd_opt->threshes[segment_id][bsize][THR_GOLD] : this_rd_thresh;
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
filter_cache[i] = INT64_MAX;
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 1f16325..e4c349c 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -192,6 +192,7 @@
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
+
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
diff --git a/vp9/common/vp9_thread_common.c b/vp9/common/vp9_thread_common.c
index db78d6b..033326d 100644
--- a/vp9/common/vp9_thread_common.c
+++ b/vp9/common/vp9_thread_common.c
@@ -379,11 +379,11 @@
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
- accum->single_ref[i][j][k] += counts->single_ref[i][j][k];
+ accum->single_ref[i][j][k] += counts->single_ref[i][j][k];
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
- accum->comp_ref[i][j] += counts->comp_ref[i][j];
+ accum->comp_ref[i][j] += counts->comp_ref[i][j];
for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
for (j = 0; j < TX_SIZES; j++)
diff --git a/vp9/decoder/vp9_decoder.c b/vp9/decoder/vp9_decoder.c
index f5da07e..ed49a69 100644
--- a/vp9/decoder/vp9_decoder.c
+++ b/vp9/decoder/vp9_decoder.c
@@ -237,15 +237,16 @@
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
lock_buffer_pool(pool);
+
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
const int old_idx = cm->ref_frame_map[ref_index];
// Current thread releases the holding of reference frame.
decrease_ref_count(old_idx, frame_bufs, pool);
// Release the reference frame in reference map.
- if (mask & 1) {
+ if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
- }
+
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
++ref_index;
}
@@ -267,7 +268,7 @@
}
// Invalidate these references until the next frame starts.
- for (ref_index = 0; ref_index < 3; ref_index++)
+ for (ref_index = 0; ref_index < REFS_PER_FRAME; ref_index++)
cm->frame_refs[ref_index].idx = -1;
}
@@ -325,7 +326,6 @@
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
}
-
if (setjmp(cm->error.jmp)) {
const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
int i;
@@ -350,9 +350,8 @@
decrease_ref_count(old_idx, frame_bufs, pool);
// Release the reference frame in reference map.
- if (mask & 1) {
+ if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
- }
++ref_index;
}
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index f9c28f6..2dd948d 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -4047,7 +4047,7 @@
// either compound, single or hybrid prediction as per whatever has
// worked best for that type of frame in the past.
// It also predicts whether another coding mode would have worked
- // better that this coding mode. If that is the case, it remembers
+ // better than this coding mode. If that is the case, it remembers
// that for subsequent frames.
// It does the same analysis for transform size selection also.
const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
diff --git a/vp9/encoder/vp9_rd.c b/vp9/encoder/vp9_rd.c
index eda7743..21e57c4 100644
--- a/vp9/encoder/vp9_rd.c
+++ b/vp9/encoder/vp9_rd.c
@@ -590,6 +590,12 @@
rd->thresh_mult[THR_NEARMV] += 1000;
rd->thresh_mult[THR_NEARA] += 1000;
+ rd->thresh_mult[THR_NEARG] += 1000;
+
+ rd->thresh_mult[THR_ZEROMV] += 2000;
+ rd->thresh_mult[THR_ZEROG] += 2000;
+ rd->thresh_mult[THR_ZEROA] += 2000;
+
rd->thresh_mult[THR_COMP_NEARESTLA] += 1000;
rd->thresh_mult[THR_COMP_NEARESTGA] += 1000;
@@ -597,13 +603,9 @@
rd->thresh_mult[THR_COMP_NEARLA] += 1500;
rd->thresh_mult[THR_COMP_NEWLA] += 2000;
- rd->thresh_mult[THR_NEARG] += 1000;
rd->thresh_mult[THR_COMP_NEARGA] += 1500;
rd->thresh_mult[THR_COMP_NEWGA] += 2000;
- rd->thresh_mult[THR_ZEROMV] += 2000;
- rd->thresh_mult[THR_ZEROG] += 2000;
- rd->thresh_mult[THR_ZEROA] += 2000;
rd->thresh_mult[THR_COMP_ZEROLA] += 2500;
rd->thresh_mult[THR_COMP_ZEROGA] += 2500;
@@ -618,9 +620,10 @@
}
void vp9_set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi) {
- static const int thresh_mult[2][MAX_REFS] =
- {{2500, 2500, 2500, 4500, 4500, 2500},
- {2000, 2000, 2000, 4000, 4000, 2000}};
+ static const int thresh_mult[2][MAX_REFS] = {
+ {2500, 2500, 2500, 4500, 4500, 2500},
+ {2000, 2000, 2000, 4000, 4000, 2000}
+ };
RD_OPT *const rd = &cpi->rd;
const int idx = cpi->oxcf.mode == BEST;
memcpy(rd->thresh_mult_sub8x8, thresh_mult[idx], sizeof(thresh_mult[idx]));
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index e32130e..31c5b2e 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3966,7 +3966,7 @@
rd_opt->threshes[segment_id][bsize][THR_LAST] :
rd_opt->threshes[segment_id][bsize][THR_ALTR];
this_rd_thresh = (ref_frame == GOLDEN_FRAME) ?
- rd_opt->threshes[segment_id][bsize][THR_GOLD] : this_rd_thresh;
+ rd_opt->threshes[segment_id][bsize][THR_GOLD] : this_rd_thresh;
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
filter_cache[i] = INT64_MAX;
@@ -3988,6 +3988,7 @@
int64_t rs_rd;
MB_MODE_INFO_EXT *mbmi_ext = x->mbmi_ext;
mbmi->interp_filter = switchable_filter_index;
+
tmp_rd = rd_pick_best_sub8x8_mode(cpi, x,
&mbmi_ext->ref_mvs[ref_frame][0],
second_ref, best_yrd, &rate,