Commit 1ac85879 authored by Yue Chen's avatar Yue Chen

EXT_INTER experiment

NEW2MV is enabled, representing a new motion vector predicted from
NEARMV. It is mostly ported from nextgen, where it was named
NEW_INTER.
A few fixes are done for sub8x8 RDO to correct some misused
mv references in the original patch.
A 'bug-fix' for encoding complexity is done, reducing the additional
encoding time from 50% to 20%. In sub8x8 case, the old patch
did motion search for every interpolation filter (vp9 only
searches once). This fix also slightly improves the coding gain.
This experiment has been made compatible with REF_MV and EXT_REFS.

Coding gain (derflr/hevcmr/hevchd): 0.267%/0.542%/0.257%

Change-Id: I9a94c5f292e7454492a877f65072e8aedba087d4
parent eee6afe0
......@@ -48,8 +48,18 @@ typedef enum {
#define MAXTXLEN 32
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
#if CONFIG_EXT_INTER
return mode >= NEARESTMV && mode <= NEWFROMNEARMV;
#else
return mode >= NEARESTMV && mode <= NEWMV;
#endif // CONFIG_EXT_INTER
}
#if CONFIG_EXT_INTER
static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEWMV || mode == NEWFROMNEARMV);
}
#endif // CONFIG_EXT_INTER
/* For keyframes, intra block modes are predicted by the (already decoded)
modes for the Y blocks to the left and above us; for interframes, there
......@@ -58,6 +68,9 @@ static INLINE int is_inter_mode(PREDICTION_MODE mode) {
typedef struct {
PREDICTION_MODE as_mode;
int_mv as_mv[2]; // first, second inter predictor motion vectors
#if CONFIG_EXT_INTER
int_mv ref_mv[2];
#endif // CONFIG_EXT_INTER
} b_mode_info;
// Note that the rate-distortion optimization loop, bit-stream writer, and
......
......@@ -183,10 +183,24 @@ static const vpx_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = {
static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = {
220, 220, 200, 200, 180, 128, 30, 220, 30,
};
#if CONFIG_EXT_INTER
static const vpx_prob default_new2mv_prob = 180;
#endif
#endif
static const vpx_prob default_inter_mode_probs[INTER_MODE_CONTEXTS]
[INTER_MODES - 1] = {
#if CONFIG_EXT_INTER
// TODO(zoeliu): To adjust the initial default probs
{2, 173, 34, 173}, // 0 = both zero mv
{7, 145, 85, 145}, // 1 = one zero mv + one a predicted mv
{7, 166, 63, 166}, // 2 = two predicted mvs
{7, 94, 66, 128}, // 3 = one predicted/zero and one new mv
{8, 64, 46, 128}, // 4 = two new mvs
{17, 81, 31, 128}, // 5 = one intra neighbour + x
{25, 29, 30, 96}, // 6 = two intra neighbours
#else
{2, 173, 34}, // 0 = both zero mv
{7, 145, 85}, // 1 = one zero mv + one a predicted mv
{7, 166, 63}, // 2 = two predicted mvs
......@@ -194,6 +208,7 @@ static const vpx_prob default_inter_mode_probs[INTER_MODE_CONTEXTS]
{8, 64, 46}, // 4 = two new mvs
{17, 81, 31}, // 5 = one intra neighbour + x
{25, 29, 30}, // 6 = two intra neighbours
#endif // CONFIG_EXT_INTER
};
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
......@@ -212,7 +227,12 @@ const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)] = {
const vpx_tree_index vp10_inter_mode_tree[TREE_SIZE(INTER_MODES)] = {
-INTER_OFFSET(ZEROMV), 2,
-INTER_OFFSET(NEARESTMV), 4,
#if CONFIG_EXT_INTER
-INTER_OFFSET(NEARMV), 6,
-INTER_OFFSET(NEWMV), -INTER_OFFSET(NEWFROMNEARMV)
#else
-INTER_OFFSET(NEARMV), -INTER_OFFSET(NEWMV)
#endif // CONFIG_EXT_INTER
};
const vpx_tree_index vp10_partition_tree[TREE_SIZE(PARTITION_TYPES)] = {
......@@ -1232,7 +1252,10 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->newmv_prob, default_newmv_prob);
vp10_copy(fc->zeromv_prob, default_zeromv_prob);
vp10_copy(fc->refmv_prob, default_refmv_prob);
#endif
#if CONFIG_EXT_INTER
fc->new2mv_prob = default_new2mv_prob;
#endif // CONFIG_EXT_INTER
#endif // CONFIG_REF_MV
vp10_copy(fc->inter_mode_probs, default_inter_mode_probs);
#if CONFIG_SUPERTX
vp10_copy(fc->supertx_prob, default_supertx_prob);
......@@ -1292,6 +1315,11 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
fc->refmv_prob[i] = mode_mv_merge_probs(pre_fc->refmv_prob[i],
counts->refmv_mode[i]);
#if CONFIG_EXT_INTER
fc->new2mv_prob = mode_mv_merge_probs(pre_fc->new2mv_prob,
counts->new2mv_mode);
#endif // CONFIG_EXT_INTER
#else
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
vpx_tree_merge_probs(vp10_inter_mode_tree, pre_fc->inter_mode_probs[i],
......
......@@ -65,6 +65,9 @@ typedef struct frame_contexts {
vpx_prob newmv_prob[NEWMV_MODE_CONTEXTS];
vpx_prob zeromv_prob[ZEROMV_MODE_CONTEXTS];
vpx_prob refmv_prob[REFMV_MODE_CONTEXTS];
#if CONFIG_EXT_INTER
vpx_prob new2mv_prob;
#endif // CONFIG_EXT_INTER
#endif
vpx_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1];
......@@ -110,6 +113,9 @@ typedef struct FRAME_COUNTS {
unsigned int newmv_mode[NEWMV_MODE_CONTEXTS][2];
unsigned int zeromv_mode[ZEROMV_MODE_CONTEXTS][2];
unsigned int refmv_mode[REFMV_MODE_CONTEXTS][2];
#if CONFIG_EXT_INTER
unsigned int new2mv_mode[2];
#endif // CONFIG_EXT_INTER
#endif
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
......
......@@ -177,7 +177,12 @@ typedef enum {
#define NEARMV 11
#define ZEROMV 12
#define NEWMV 13
#if CONFIG_EXT_INTER
#define NEWFROMNEARMV 14
#define MB_MODE_COUNT 15
#else
#define MB_MODE_COUNT 14
#endif // CONFIG_EXT_INTER
typedef uint8_t PREDICTION_MODE;
#define INTRA_MODES (TM_PRED + 1)
......@@ -201,7 +206,11 @@ typedef enum {
#define DIRECTIONAL_MODES (INTRA_MODES - 2)
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTER
#define INTER_MODES (1 + NEWFROMNEARMV - NEARESTMV)
#else
#define INTER_MODES (1 + NEWMV - NEARESTMV)
#endif // CONFIG_EXT_INTER
#define SKIP_CONTEXTS 3
......
......@@ -207,6 +207,9 @@ static const uint16_t above_border_uv = 0x000f;
static const int mode_lf_lut[MB_MODE_COUNT] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0)
#if CONFIG_EXT_INTER
, 1 // NEWFROMNEARMV mode
#endif // CONFIG_EXT_INTER
};
static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
......
......@@ -613,6 +613,52 @@ Done:
mv_ref_list[i].as_int = 0;
}
#if CONFIG_EXT_INTER
// This function keeps a mode count for a given MB/SB
void vp10_update_mv_context(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col,
int16_t *mode_context) {
int i, refmv_count = 0;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
int context_counter = 0;
const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type] << 3;
const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type] << 3;
const TileInfo *const tile = &xd->tile;
// Blank the reference vector list
memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
// The nearest 2 blocks are examined only.
// If the size < 8x8, we get the mv from the bmi substructure;
for (i = 0; i < 2; ++i) {
const POSITION *const mv_ref = &mv_ref_search[i];
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
const MODE_INFO *const candidate_mi =
xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
// Keep counts for entropy encoding.
context_counter += mode_2_counter[candidate->mode];
if (candidate->ref_frame[0] == ref_frame) {
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
refmv_count, mv_ref_list, bw, bh, xd, Done);
} else if (candidate->ref_frame[1] == ref_frame) {
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
refmv_count, mv_ref_list, bw, bh, xd, Done);
}
}
}
Done:
if (mode_context)
mode_context[ref_frame] = counter_to_context[context_counter];
}
#endif // CONFIG_EXT_INTER
void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
#if CONFIG_REF_MV
......@@ -626,8 +672,15 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
#if CONFIG_REF_MV
int idx, all_zero = 1;
#endif
#if CONFIG_EXT_INTER
vp10_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, mode_context);
find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, sync, data, NULL);
#else
find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, sync, data, mode_context);
#endif // CONFIG_EXT_INTER
#if CONFIG_REF_MV
setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack,
......@@ -656,8 +709,13 @@ void vp10_find_best_ref_mvs(int allow_hp,
void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
int block, int ref, int mi_row, int mi_col,
#if CONFIG_EXT_INTER
int_mv *mv_list,
#endif // CONFIG_EXT_INTER
int_mv *nearest_mv, int_mv *near_mv) {
#if !CONFIG_EXT_INTER
int_mv mv_list[MAX_MV_REF_CANDIDATES];
#endif // !CONFIG_EXT_INTER
MODE_INFO *const mi = xd->mi[0];
b_mode_info *bmi = mi->bmi;
int n;
......
......@@ -55,6 +55,9 @@ static const int mode_2_counter[MB_MODE_COUNT] = {
0, // NEARMV
3, // ZEROMV
1, // NEWMV
#if CONFIG_EXT_INTER
1, // NEWFROMNEARMV
#endif // CONFIG_EXT_INTER
};
// There are 3^3 different combinations of 3 counts that can be either 0,1 or
......@@ -265,8 +268,20 @@ void vp10_find_best_ref_mvs(int allow_hp,
void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
int block, int ref, int mi_row, int mi_col,
#if CONFIG_EXT_INTER
int_mv *mv_list,
#endif // CONFIG_EXT_INTER
int_mv *nearest_mv, int_mv *near_mv);
#if CONFIG_EXT_INTER
// This function keeps a mode count for a given MB/SB
void vp10_update_mv_context(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col,
int16_t *mode_context);
#endif // CONFIG_EXT_INTER
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -378,6 +378,11 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
for (j = 0; j < 2; ++j)
cm->counts.refmv_mode[i][j] += counts->refmv_mode[i][j];
#if CONFIG_EXT_INTER
for (j = 0; j < 2; ++j)
cm->counts.new2mv_mode[j] += counts->new2mv_mode[j];
#endif // CONFIG_EXT_INTER
#endif
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
......
......@@ -132,6 +132,9 @@ static void read_inter_mode_probs(FRAME_CONTEXT *fc, vpx_reader *r) {
vp10_diff_update_prob(r, &fc->zeromv_prob[i]);
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
vp10_diff_update_prob(r, &fc->refmv_prob[i]);
#if CONFIG_EXT_INTER
vp10_diff_update_prob(r, &fc->new2mv_prob);
#endif // CONFIG_EXT_INTER
#else
int j;
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
......
......@@ -63,6 +63,9 @@ static PREDICTION_MODE read_intra_mode_uv(VP10_COMMON *cm, MACROBLOCKD *xd,
}
static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
MB_MODE_INFO *mbmi,
#endif
vpx_reader *r, int16_t ctx) {
#if CONFIG_REF_MV
FRAME_COUNTS *counts = xd->counts;
......@@ -72,7 +75,25 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
if (vpx_read(r, mode_prob) == 0) {
if (counts)
++counts->newmv_mode[mode_ctx][0];
#if CONFIG_EXT_INTER
if (has_second_ref(mbmi)) {
#endif // CONFIG_EXT_INTER
return NEWMV;
#if CONFIG_EXT_INTER
} else {
mode_prob = cm->fc->new2mv_prob;
if (vpx_read(r, mode_prob) == 0) {
if (counts)
++counts->new2mv_mode[0];
return NEWMV;
} else {
if (counts)
++counts->new2mv_mode[1];
return NEWFROMNEARMV;
}
}
#endif // CONFIG_EXT_INTER
}
if (counts)
++counts->newmv_mode[mode_ctx][1];
......@@ -774,6 +795,9 @@ static INLINE int assign_mv(VP10_COMMON *cm, MACROBLOCKD *xd,
int ret = 1;
switch (mode) {
#if CONFIG_EXT_INTER
case NEWFROMNEARMV:
#endif // CONFIG_EXT_INTER
case NEWMV: {
FRAME_COUNTS *counts = xd->counts;
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
......@@ -839,6 +863,9 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
const int allow_hp = cm->allow_high_precision_mv;
int_mv nearestmv[2], nearmv[2];
int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
#if CONFIG_EXT_INTER
int mv_idx;
#endif // CONFIG_EXT_INTER
int ref, is_compound;
int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
int16_t mode_ctx = 0;
......@@ -885,7 +912,11 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
}
} else {
if (bsize >= BLOCK_8X8)
mbmi->mode = read_inter_mode(cm, xd, r, mode_ctx);
mbmi->mode = read_inter_mode(cm, xd,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
mbmi,
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
r, mode_ctx);
}
if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
......@@ -936,6 +967,9 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
int idx, idy;
PREDICTION_MODE b_mode;
int_mv nearest_sub8x8[2], near_sub8x8[2];
#if CONFIG_EXT_INTER
int_mv ref_mv[2][2];
#endif // CONFIG_EXT_INTER
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
int_mv block[2];
......@@ -944,16 +978,49 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame,
bsize, j);
#endif
b_mode = read_inter_mode(cm, xd, r, mode_ctx);
b_mode = read_inter_mode(cm, xd,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
mbmi,
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
r, mode_ctx);
#if CONFIG_EXT_INTER
mv_idx = (b_mode == NEWFROMNEARMV) ? 1 : 0;
if (b_mode != ZEROMV) {
#else
if (b_mode == NEARESTMV || b_mode == NEARMV) {
#endif // CONFIG_EXT_INTER
for (ref = 0; ref < 1 + is_compound; ++ref)
#if CONFIG_EXT_INTER
{
int_mv mv_ref_list[MAX_MV_REF_CANDIDATES];
vp10_update_mv_context(cm, xd, mi, mbmi->ref_frame[ref],
mv_ref_list, j, mi_row, mi_col, NULL);
#endif // CONFIG_EXT_INTER
vp10_append_sub8x8_mvs_for_idx(cm, xd, j, ref, mi_row, mi_col,
#if CONFIG_EXT_INTER
mv_ref_list,
#endif // CONFIG_EXT_INTER
&nearest_sub8x8[ref],
&near_sub8x8[ref]);
#if CONFIG_EXT_INTER
if (have_newmv_in_inter_mode(b_mode)) {
mv_ref_list[0].as_int = nearest_sub8x8[ref].as_int;
mv_ref_list[1].as_int = near_sub8x8[ref].as_int;
vp10_find_best_ref_mvs(allow_hp, mv_ref_list,
&ref_mv[0][ref], &ref_mv[1][ref]);
}
}
#endif // CONFIG_EXT_INTER
}
if (!assign_mv(cm, xd, b_mode, block, nearestmv,
if (!assign_mv(cm, xd, b_mode, block,
#if CONFIG_EXT_INTER
ref_mv[mv_idx],
#else
nearestmv,
#endif // CONFIG_EXT_INTER
nearest_sub8x8, near_sub8x8,
is_compound, allow_hp, r)) {
xd->corrupted |= 1;
......@@ -976,7 +1043,13 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
} else {
xd->corrupted |= !assign_mv(cm, xd, mbmi->mode, mbmi->mv, nearestmv,
xd->corrupted |= !assign_mv(cm, xd, mbmi->mode, mbmi->mv,
#if CONFIG_EXT_INTER
mbmi->mode == NEWFROMNEARMV ?
nearmv : nearestmv,
#else
nearestmv,
#endif // CONFIG_EXT_INTER
nearestmv, nearmv, is_compound, allow_hp, r);
}
#if CONFIG_EXT_INTERP
......
......@@ -49,7 +49,11 @@ static const struct vp10_token partition_encodings[PARTITION_TYPES] =
{{0, 1}, {2, 2}, {6, 3}, {7, 3}};
#if !CONFIG_REF_MV
static const struct vp10_token inter_mode_encodings[INTER_MODES] =
#if CONFIG_EXT_INTER
{{2, 2}, {6, 3}, {0, 1}, {14, 4}, {15, 4}};
#else
{{2, 2}, {6, 3}, {0, 1}, {7, 3}};
#endif // CONFIG_EXT_INTER
#endif
static const struct vp10_token palette_size_encodings[] = {
{0, 1}, {2, 2}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {63, 6},
......@@ -117,13 +121,25 @@ static void write_intra_mode(vpx_writer *w, PREDICTION_MODE mode,
static void write_inter_mode(VP10_COMMON *cm,
vpx_writer *w, PREDICTION_MODE mode,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
int is_compound,
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
const int16_t mode_ctx) {
#if CONFIG_REF_MV
const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
const vpx_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx];
#if CONFIG_EXT_INTER
vpx_write(w, mode != NEWMV && mode != NEWFROMNEARMV, newmv_prob);
if (!is_compound && (mode == NEWMV || mode == NEWFROMNEARMV))
vpx_write(w, mode == NEWFROMNEARMV, cm->fc->new2mv_prob);
if (mode != NEWMV && mode != NEWFROMNEARMV) {
#else
vpx_write(w, mode != NEWMV, newmv_prob);
if (mode != NEWMV) {
#endif // CONFIG_EXT_INTER
const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
const vpx_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx];
......@@ -279,6 +295,10 @@ static void update_inter_mode_probs(VP10_COMMON *cm, vpx_writer *w,
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
vp10_cond_prob_diff_update(w, &cm->fc->refmv_prob[i],
counts->refmv_mode[i]);
#if CONFIG_EXT_INTER
vp10_cond_prob_diff_update(w, &cm->fc->new2mv_prob, counts->new2mv_mode);
#endif // CONFIG_EXT_INTER
}
#endif
......@@ -906,7 +926,11 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
// If segment skip is not enabled code the mode.
if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
if (bsize >= BLOCK_8X8) {
write_inter_mode(cm, w, mode, mode_ctx);
write_inter_mode(cm, w, mode,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
has_second_ref(mbmi),
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
mode_ctx);
}
}
......@@ -926,23 +950,52 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, j);
#endif
write_inter_mode(cm, w, b_mode, mode_ctx);
write_inter_mode(cm, w, b_mode,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
has_second_ref(mbmi),
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
mode_ctx);
#if CONFIG_EXT_INTER
if (b_mode == NEWMV || b_mode == NEWFROMNEARMV) {
#else
if (b_mode == NEWMV) {
#endif // CONFIG_EXT_INTER
for (ref = 0; ref < 1 + is_compound; ++ref)
vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
#if CONFIG_EXT_INTER
&mi->bmi[j].ref_mv[ref].as_mv,
#else
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
#endif // CONFIG_EXT_INTER
nmvc, allow_hp);
}
}
}
} else {
#if CONFIG_EXT_INTER
if (mode == NEWMV || mode == NEWFROMNEARMV) {
#else
if (mode == NEWMV) {
#endif // CONFIG_EXT_INTER
for (ref = 0; ref < 1 + is_compound; ++ref)
#if CONFIG_EXT_INTER
{
if (mode == NEWFROMNEARMV)
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][1].as_mv,
nmvc, allow_hp);
else
#endif // CONFIG_EXT_INTER
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv, nmvc,
allow_hp);
#if CONFIG_EXT_INTER
}
#endif // CONFIG_EXT_INTER
}
}
#if CONFIG_EXT_INTERP
write_switchable_interp_filter(cpi, xd, w);
#endif // CONFIG_EXT_INTERP
......
......@@ -1668,9 +1668,18 @@ static void rd_pick_sb_modes(VP10_COMP *cpi,
#if CONFIG_REF_MV
static void update_inter_mode_stats(FRAME_COUNTS *counts,
PREDICTION_MODE mode,
#if CONFIG_EXT_INTER
int is_compound,
#endif // CONFIG_EXT_INTER
int16_t mode_context) {
int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
#if CONFIG_EXT_INTER
if (mode == NEWMV || mode == NEWFROMNEARMV) {
if (!is_compound)
++counts->new2mv_mode[mode == NEWFROMNEARMV];
#else
if (mode == NEWMV) {
#endif // CONFIG_EXT_INTER
++counts->newmv_mode[mode_ctx][0];
return;
} else {
......@@ -1789,7 +1798,12 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td
#if CONFIG_REF_MV
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
update_inter_mode_stats(counts, mode, mode_ctx);
update_inter_mode_stats(counts, mode,
#if CONFIG_EXT_INTER
has_second_ref(mbmi),
#endif // CONFIG_EXT_INTER
mode_ctx);
#else
++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
#endif
......@@ -1804,7 +1818,11 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td
#if CONFIG_REF_MV
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, j);
update_inter_mode_stats(counts, b_mode, mode_ctx);
update_inter_mode_stats(counts, b_mode,
#if CONFIG_EXT_INTER
has_second_ref(mbmi),
#endif // CONFIG_EXT_INTER
mode_ctx);
#else
++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
#endif
......
......@@ -224,6 +224,41 @@ void vp10_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
build_nmv_component_cost_table(mvcost[1], &ctx->comps[1], usehp);
}
#if CONFIG_EXT_INTER
static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
const int_mv mvs[2],
nmv_context_counts *counts) {
int i;
PREDICTION_MODE mode = mbmi->mode;
int mv_idx = (mode == NEWFROMNEARMV);
if (mode == NEWMV || mode == NEWFROMNEARMV) {
for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][mv_idx].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
}
}
static void inc_mvs_sub8x8(const MODE_INFO *mi,
int block,
const int_mv mvs[2],
nmv_context_counts *counts) {
int i;
PREDICTION_MODE mode = mi->bmi[block].as_mode;
if (mode == NEWMV || mode == NEWFROMNEARMV) {
for (i = 0; i < 1 + has_second_ref(&mi->mbmi); ++i) {
const MV *ref = &mi->bmi[block].ref_mv[i].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
}
}
#else
static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
const int_mv mvs[2],
nmv_context_counts *counts) {
......@@ -236,6 +271,7 @@ static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
}
#endif // CONFIG_EXT_INTER
void vp10_update_mv_count(ThreadData *td) {
const MACROBLOCKD *xd = &td->mb.e_mbd;
......@@ -251,12 +287,22 @@ void vp10_update_mv_count(ThreadData *td) {
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
const int i = idy * 2 + idx;
#if CONFIG_EXT_INTER
if (have_newmv_in_inter_mode(mi->bmi[i].as_mode))
inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, &td->counts->mv);
#else
if (mi->bmi[i].as_mode == NEWMV)
inc_mvs(mbmi, mbmi_ext, mi->bmi[i].as_mv, &td->counts->mv);
#endif // CONFIG_EXT_INTER
}
}
} else {
#if CONFIG_EXT_INTER
if (have_newmv_in_inter_mode(mbmi->mode))
#else
if (mbmi->mode == NEWMV)
#endif // CONFIG_EXT_INTER
inc_mvs(mbmi, mbmi_ext, mbmi->mv, &td->counts->mv);
}
}
......
......@@ -473,6 +473,9 @@ typedef struct VP10_COMP {
int newmv_mode_cost[NEWMV_MODE_CONTEXTS][2];
int zeromv_mode_cost[ZEROMV_MODE_CONTEXTS][2];
int refmv_mode_cost[REFMV_MODE_CONTEXTS][2];
#if CONFIG_EXT_INTER
int new2mv_mode_cost[2];
#endif // CONFIG_EXT_INTER
#endif
unsigned int inter_mode_cost[INTER_MODE_CONTEXTS][INTER_MODES];
......
......@@ -377,6 +377,10 @@ void vp10_initialize_rd_consts(VP10_COMP *cpi) {
cpi->refmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->refmv_prob[i], 0);
cpi->refmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->refmv_prob[i], 1);
}
#if CONFIG_EXT_INTER
cpi->new2mv_mode_cost[0] = vp10_cost_bit(cm->fc->new2mv_prob, 0);
cpi->new2mv_mode_cost[1] = vp10_cost_bit(cm->fc->new2mv_prob, 1);
#endif // CONFIG_EXT_INTER
#else
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
vp10_cost_tokens((int *)cpi->inter_mode_cost[i],
......@@ -686,6 +690,17 @@ void vp10_set_rd_speed_thresholds(VP10_COMP *cpi) {
rd->thresh_mult[THR_NEARA] += 1000;
rd->thresh_mult[THR_NEARG] += 1000;
#if CONFIG_EXT_INTER
rd->thresh_mult[THR_NEWFROMNEARMV] += 1000;
#if CONFIG_EXT_REF
rd->thresh_mult[THR_NEWFROMNEARL2] += 1000;
rd->thresh_mult[THR_NEWFROMNEARL3] += 1000;
rd->thresh_mult[THR_NEWFROMNEARL4] += 1000;
#endif // CONFIG_EXT_REF
rd->thresh_mult[THR_NEWFROMNEARG] += 1000;
rd->thresh_mult[THR_NEWFROMNEARA] += 1000;
#endif // CONFIG_EXT_INTER
rd->thresh_mult[THR_ZEROMV] += 2000;
#if CONFIG_EXT_REFS