Changed mv ref to nearestmv always for sub8x8

For all sub8x8 partition, the mv ref has changed to its own nearest_mv
instead of the nearest_mv of the super 8x8 block:

--enable-newmvref-sub8x8: ~0.1% gain for derflr

Besides the above new experiment, code has been cleaned largely for the
sub8x8 motion search, such that the mv ref can be fairly easily changed to
use other options, e.g., the next step's global motion effort.

Change-Id: I8e3f4aaa8553ba8c445369692e079db5ce282593
This commit is contained in:
Zoe Liu 2015-02-09 15:54:56 -08:00
parent 4c1049d7a8
commit b359952c2c
8 changed files with 431 additions and 168 deletions

1
configure vendored
View File

@ -293,6 +293,7 @@ EXPERIMENT_LIST="
compound_modes
global_motion
palette
newmvref_sub8x8
"
CONFIG_LIST="
external_build

View File

@ -155,6 +155,9 @@ static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) {
typedef struct {
PREDICTION_MODE as_mode;
int_mv as_mv[2]; // first, second inter predictor motion vectors
#if CONFIG_NEWMVREF_SUB8X8
int_mv ref_mv[2];
#endif // CONFIG_NEWMVREF_SUB8X8
} b_mode_info;
// Note that the rate-distortion optimization loop, bit-stream writer, and

View File

@ -26,7 +26,9 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
int different_ref_found = 0;
#if !CONFIG_NEWMVREF_SUB8X8
int context_counter = 0;
#endif // CONFIG_NEWMVREF_SUB8X8
// Blank the reference vector list
vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
@ -41,13 +43,16 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
xd->mi_stride].src_mi;
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
// Keep counts for entropy encoding.
#if !CONFIG_NEWMVREF_SUB8X8
context_counter += mode_2_counter[candidate->mode];
#endif // CONFIG_NEWMVREF_SUB8X8
different_ref_found = 1;
if (candidate->ref_frame[0] == ref_frame)
if (candidate->ref_frame[0] == ref_frame) {
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block));
else if (candidate->ref_frame[1] == ref_frame)
} else if (candidate->ref_frame[1] == ref_frame) {
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
}
}
}
@ -98,39 +103,77 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
Done:
#if !CONFIG_NEWMVREF_SUB8X8
mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
#endif // CONFIG_NEWMVREF_SUB8X8
// Clamp vectors
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
}
#if CONFIG_NEWMVREF_SUB8X8
// This function keeps a mode count for a given MB/SB
void vp9_update_mv_context(const VP9_COMMON *cm, const MACROBLOCKD *xd,
const TileInfo *const tile,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col) {
int i, refmv_count = 0;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
int context_counter = 0;
// Blank the reference vector list
vpx_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].src_mi;
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));
} else if (candidate->ref_frame[1] == ref_frame) {
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
}
}
}
Done:
mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
}
#endif // CONFIG_NEWMVREF_SUB8X8
void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
const TileInfo *const tile,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int mi_row, int mi_col) {
#if CONFIG_NEWMVREF_SUB8X8
vp9_update_mv_context(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col);
#endif // CONFIG_NEWMVREF_SUB8X8
find_mv_refs_idx(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col);
}
static void lower_mv_precision(MV *mv, int allow_hp) {
const int use_hp = allow_hp && vp9_use_mv_hp(mv);
if (!use_hp) {
if (mv->row & 1)
mv->row += (mv->row > 0 ? -1 : 1);
if (mv->col & 1)
mv->col += (mv->col > 0 ? -1 : 1);
}
}
void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
int_mv *mvlist, int_mv *nearest, int_mv *near) {
int i;
// Make sure all the candidates are properly clamped etc
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
lower_mv_precision(&mvlist[i].as_mv, allow_hp);
clamp_mv2(&mvlist[i].as_mv, xd);
MV *mv = &mvlist[i].as_mv;
const int usehp = allow_hp && vp9_use_mv_hp(mv);
vp9_lower_mv_precision(mv, usehp);
clamp_mv2(mv, xd);
}
*nearest = mvlist[0];
*near = mvlist[1];
@ -139,8 +182,13 @@ void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
const TileInfo *const tile,
int block, int ref, int mi_row, int mi_col,
#if CONFIG_NEWMVREF_SUB8X8
int_mv *mv_list,
#endif // CONFIG_NEWMVREF_SUB8X8
int_mv *nearest, int_mv *near) {
#if !CONFIG_NEWMVREF_SUB8X8
int_mv mv_list[MAX_MV_REF_CANDIDATES];
#endif // CONFIG_NEWMVREF_SUB8X8
MODE_INFO *const mi = xd->mi[0].src_mi;
b_mode_info *bmi = mi->bmi;
int n;

View File

@ -215,11 +215,29 @@ static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
}
#if CONFIG_NEWMVREF_SUB8X8
// This function keeps a mode count for a given MB/SB
void vp9_update_mv_context(const VP9_COMMON *cm, const MACROBLOCKD *xd,
const TileInfo *const tile,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col);
#endif // CONFIG_NEWMVREF_SUB8X8
void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
const TileInfo *const tile,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list, int mi_row, int mi_col);
static INLINE void vp9_lower_mv_precision(MV *mv, const int usehp) {
if (!usehp) {
if (mv->row & 1)
mv->row += (mv->row > 0 ? -1 : 1);
if (mv->col & 1)
mv->col += (mv->col > 0 ? -1 : 1);
}
}
// check a list of motion vectors by sad score using a number rows of pixels
// above and a number cols of pixels in the left to select the one with best
// score to use as ref motion vector
@ -229,6 +247,9 @@ void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
const TileInfo *const tile,
int block, int ref, int mi_row, int mi_col,
#if CONFIG_NEWMVREF_SUB8X8
int_mv *mv_list,
#endif // CONFIG_NEWMVREF_SUB8X8
int_mv *nearest, int_mv *near);
#if CONFIG_COPY_MODE

View File

@ -838,7 +838,7 @@ static INLINE int assign_mv(VP9_COMMON *cm, PREDICTION_MODE mode,
mv[1].as_int = 0;
break;
}
#endif
#endif // CONFIG_COMPOUND_MODES
default: {
return 0;
}
@ -982,6 +982,9 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
int idx, idy;
PREDICTION_MODE b_mode;
int_mv nearest_sub8x8[2], near_sub8x8[2];
#if CONFIG_NEWMVREF_SUB8X8
int_mv ref_mv[2];
#endif // CONFIG_NEWMVREF_SUB8X8
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
int_mv block[2];
@ -997,19 +1000,59 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
#endif
#if CONFIG_COMPOUND_MODES
if (b_mode == NEARESTMV || b_mode == NEARMV ||
#if CONFIG_NEWMVREF_SUB8X8
b_mode == NEWMV || b_mode == NEW_NEWMV ||
#endif // CONFIG_NEWMVREF_SUB8X8
b_mode == NEAREST_NEARESTMV || b_mode == NEAREST_NEARMV ||
b_mode == NEAR_NEARESTMV || b_mode == NEAREST_NEWMV ||
b_mode == NEW_NEARESTMV || b_mode == NEAR_NEWMV ||
b_mode == NEW_NEARMV)
#else
if (b_mode == NEARESTMV || b_mode == NEARMV)
#endif
for (ref = 0; ref < 1 + is_compound; ++ref)
if (b_mode == NEARESTMV || b_mode == NEARMV
#if CONFIG_NEWMVREF_SUB8X8
|| b_mode == NEWMV
#endif // CONFIG_NEWMVREF_SUB8X8
)
#endif // CONFIG_COMPOUND_MODES
{
for (ref = 0; ref < 1 + is_compound; ++ref) {
#if CONFIG_NEWMVREF_SUB8X8
int_mv mv_ref_list[MAX_MV_REF_CANDIDATES];
int_mv second_ref_mv;
vp9_update_mv_context(cm, xd, tile, mi, mbmi->ref_frame[ref],
mv_ref_list, j, mi_row, mi_col);
#endif // CONFIG_NEWMVREF_SUB8X8
vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
#if CONFIG_NEWMVREF_SUB8X8
mv_ref_list,
#endif // CONFIG_NEWMVREF_SUB8X8
&nearest_sub8x8[ref],
&near_sub8x8[ref]);
#if CONFIG_NEWMVREF_SUB8X8
if (b_mode == NEWMV
#if CONFIG_COMPOUND_MODES
|| b_mode == NEW_NEWMV ||
b_mode == NEAREST_NEWMV ||
b_mode == NEW_NEARESTMV ||
b_mode == NEAR_NEWMV ||
b_mode == NEW_NEARMV
#endif // CONFIG_COMPOUND_MODES
) {
mv_ref_list[0].as_int = nearest_sub8x8[ref].as_int;
mv_ref_list[1].as_int = near_sub8x8[ref].as_int;
vp9_find_best_ref_mvs(xd, allow_hp, mv_ref_list,
&ref_mv[ref], &second_ref_mv);
}
#endif // CONFIG_NEWMVREF_SUB8X8
}
}
if (!assign_mv(cm, b_mode, block, nearestmv,
if (!assign_mv(cm, b_mode, block,
#if CONFIG_NEWMVREF_SUB8X8
ref_mv,
#else
nearestmv,
#endif // CONFIG_NEWMVREF_SUB8X8
nearest_sub8x8, near_sub8x8,
is_compound, allow_hp, r)) {
xd->corrupted |= 1;

View File

@ -646,22 +646,35 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
#else
if (b_mode == NEWMV) {
#endif
for (ref = 0; ref < 1 + is_compound; ++ref)
for (ref = 0; ref < 1 + is_compound; ++ref) {
vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
&mi->bmi[j].ref_mv[ref].as_mv,
#else
&mbmi->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
nmvc, allow_hp);
}
}
#if CONFIG_COMPOUND_MODES
else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) {
vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[1].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
&mi->bmi[j].ref_mv[1].as_mv,
#else
&mbmi->ref_mvs[mbmi->ref_frame[1]][0].as_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
nmvc, allow_hp);
} else if (b_mode == NEW_NEARESTMV || b_mode == NEW_NEARMV) {
vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[0].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
&mi->bmi[j].ref_mv[0].as_mv,
#else
&mbmi->ref_mvs[mbmi->ref_frame[0]][0].as_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
nmvc, allow_hp);
}
#endif
#endif // CONFIG_COMPOUND_MODES
}
}
} else {

View File

@ -229,26 +229,24 @@ void vp9_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
build_nmv_component_cost_table(mvcost[1], &ctx->comps[1], usehp);
}
static void inc_mvs(const MB_MODE_INFO *mbmi, const int_mv mvs[2],
nmv_context_counts *counts) {
static void inc_mvs(const MB_MODE_INFO *mbmi, const int_mv mv[2],
const int_mv ref_mv[2], nmv_context_counts *counts) {
int i;
for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
const MV *ref = &mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
const MV diff = {mv[i].as_mv.row - ref_mv[i].as_mv.row,
mv[i].as_mv.col - ref_mv[i].as_mv.col};
vp9_inc_mv(&diff, counts);
}
}
#if CONFIG_COMPOUND_MODES
static void inc_compound_single_mv(const MB_MODE_INFO *mbmi,
int ref_idx,
const int_mv mvs[2],
static void inc_compound_single_mv(int ref_idx,
const int_mv mv[2],
const int_mv ref_mv[2],
nmv_context_counts *counts) {
const MV *ref = &mbmi->ref_mvs[mbmi->ref_frame[ref_idx]][0].as_mv;
const MV diff = {mvs[ref_idx].as_mv.row - ref->row,
mvs[ref_idx].as_mv.col - ref->col};
const MV diff = {mv[ref_idx].as_mv.row - ref_mv[ref_idx].as_mv.row,
mv[ref_idx].as_mv.col - ref_mv[ref_idx].as_mv.col};
vp9_inc_mv(&diff, counts);
}
#endif
@ -256,6 +254,11 @@ static void inc_compound_single_mv(const MB_MODE_INFO *mbmi,
void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
const MODE_INFO *mi = xd->mi[0].src_mi;
const MB_MODE_INFO *const mbmi = &mi->mbmi;
int i;
int_mv ref_mv[2];
for (i = 0; i < 1 + has_second_ref(mbmi); ++i)
ref_mv[i].as_int = mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_int;
if (mbmi->sb_type < BLOCK_8X8) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
@ -270,14 +273,32 @@ void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
#else
if (mi->bmi[i].as_mode == NEWMV)
#endif
inc_mvs(mbmi, mi->bmi[i].as_mv, &cm->counts.mv);
inc_mvs(mbmi, mi->bmi[i].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
mi->bmi[i].ref_mv,
#else
ref_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
&cm->counts.mv);
#if CONFIG_COMPOUND_MODES
else if (mi->bmi[i].as_mode == NEAREST_NEWMV ||
mi->bmi[i].as_mode == NEAR_NEWMV)
inc_compound_single_mv(mbmi, 1, mi->bmi[i].as_mv, &cm->counts.mv);
inc_compound_single_mv(1, mi->bmi[i].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
mi->bmi[i].ref_mv,
#else
ref_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
&cm->counts.mv);
else if (mi->bmi[i].as_mode == NEW_NEARESTMV ||
mi->bmi[i].as_mode == NEW_NEARMV)
inc_compound_single_mv(mbmi, 0, mi->bmi[i].as_mv, &cm->counts.mv);
inc_compound_single_mv(0, mi->bmi[i].as_mv,
#if CONFIG_NEWMVREF_SUB8X8
mi->bmi[i].ref_mv,
#else
ref_mv,
#endif // CONFIG_NEWMVREF_SUB8X8
&cm->counts.mv);
#endif
}
}
@ -287,12 +308,12 @@ void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
#else
if (mbmi->mode == NEWMV)
#endif
inc_mvs(mbmi, mbmi->mv, &cm->counts.mv);
inc_mvs(mbmi, mbmi->mv, ref_mv, &cm->counts.mv);
#if CONFIG_COMPOUND_MODES
else if (mbmi->mode == NEAREST_NEWMV || mbmi->mode == NEAR_NEWMV)
inc_compound_single_mv(mbmi, 1, mbmi->mv, &cm->counts.mv);
inc_compound_single_mv(1, mbmi->mv, ref_mv, &cm->counts.mv);
else if (mbmi->mode == NEW_NEARESTMV || mbmi->mode == NEW_NEARMV)
inc_compound_single_mv(mbmi, 0, mbmi->mv, &cm->counts.mv);
inc_compound_single_mv(0, mbmi->mv, ref_mv, &cm->counts.mv);
#endif
}
}

View File

@ -1998,6 +1998,7 @@ static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode,
static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize,
int_mv *frame_mv,
int_mv *ref_mv,
int mi_row, int mi_col,
int_mv single_newmv[MAX_REF_FRAMES],
int *rate_mv);
@ -2010,6 +2011,9 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
int *mvcost[2]) {
MODE_INFO *const mic = xd->mi[0].src_mi;
const MB_MODE_INFO *const mbmi = &mic->mbmi;
#if CONFIG_NEWMVREF_SUB8X8
int usehp = cpi->common.allow_high_precision_mv;
#endif // CONFIG_NEWMVREF_SUB8X8
int thismvcost = 0;
int idx, idy;
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type];
@ -2062,6 +2066,11 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
case NEW_NEARMV:
case NEW_NEARESTMV:
this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int;
#if CONFIG_NEWMVREF_SUB8X8
usehp = usehp && vp9_use_mv_hp(&best_ref_mv[0]->as_mv);
if (!usehp)
vp9_lower_mv_precision(&this_mv[0].as_mv, usehp);
#endif // CONFIG_NEWMVREF_SUB8X8
thismvcost += vp9_mv_bit_cost(&this_mv[0].as_mv, &best_ref_mv[0]->as_mv,
mvjcost, mvcost, MV_COST_WEIGHT_SUB);
this_mv[1].as_int = frame_mv[mbmi->ref_frame[1]].as_int;
@ -2070,6 +2079,11 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
case NEAREST_NEWMV:
this_mv[0].as_int = frame_mv[mbmi->ref_frame[0]].as_int;
this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int;
#if CONFIG_NEWMVREF_SUB8X8
usehp = usehp && vp9_use_mv_hp(&best_ref_mv[1]->as_mv);
if (!usehp)
vp9_lower_mv_precision(&this_mv[1].as_mv, usehp);
#endif // CONFIG_NEWMVREF_SUB8X8
thismvcost += vp9_mv_bit_cost(&this_mv[1].as_mv, &best_ref_mv[1]->as_mv,
mvjcost, mvcost, MV_COST_WEIGHT_SUB);
break;
@ -2231,6 +2245,9 @@ typedef struct {
int64_t bsse;
int64_t brdcost;
int_mv mvs[2];
#if CONFIG_NEWMVREF_SUB8X8
int_mv ref_mv[2];
#endif // CONFIG_NEWMVREF_SUB8X8
ENTROPY_CONTEXT ta[2];
ENTROPY_CONTEXT tl[2];
} SEG_RDSTAT;
@ -2372,6 +2389,106 @@ static int check_best_zero_mv(
return 1;
}
static void single_motion_search_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
int i, const BLOCK_SIZE bsize,
MV *new_mv,
int_mv *ref_mv, int_mv *mvp) {
VP9_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MODE_INFO *mi = xd->mi[0].src_mi;
MB_MODE_INFO *mbmi = &mi->mbmi;
int step_param = 0;
int thissme, bestsme = INT_MAX;
int sadpb = x->sadperbit4;
MV mvp_full;
int max_mv;
int cost_list[5];
if (cpi->oxcf.mode != BEST) {
#if CONFIG_NEWMVREF_SUB8X8
mvp->as_int = ref_mv->as_int;
#else
// use previous block's result as next block's MV predictor.
if (i > 0) {
mvp->as_int = mi->bmi[i - 1].as_mv[0].as_int;
if (i == 2)
mvp->as_int = mi->bmi[i - 2].as_mv[0].as_int;
}
#endif // CONFIG_NEWMVREF_SUB8X8
}
if (i == 0)
max_mv = x->max_mv_context[mbmi->ref_frame[0]];
else
max_mv = MAX(abs(mvp->as_mv.row), abs(mvp->as_mv.col)) >> 3;
if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
// Take wtd average of the step_params based on the last frame's
// max mv magnitude and the best ref mvs of the current block for
// the given reference.
step_param = (vp9_init_search_range(max_mv) +
cpi->mv_step_param) / 2;
} else {
step_param = cpi->mv_step_param;
}
mvp_full.row = mvp->as_mv.row >> 3;
mvp_full.col = mvp->as_mv.col >> 3;
if (cpi->sf.adaptive_motion_search) {
mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].col >> 3;
step_param = MAX(step_param, 8);
}
vp9_set_mv_search_range(x, &ref_mv->as_mv);
bestsme = vp9_full_pixel_search(
cpi, x, bsize, &mvp_full, step_param, sadpb,
cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
&ref_mv->as_mv, new_mv, INT_MAX, 1);
// Should we do a full search (best quality only)
if (cpi->oxcf.mode == BEST) {
int_mv *const best_mv = &mi->bmi[i].as_mv[0];
/* Check if mvp_full is within the range. */
clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
x->mv_row_min, x->mv_row_max);
thissme = cpi->full_search_sad(x, &mvp_full,
sadpb, 16, &cpi->fn_ptr[bsize],
&ref_mv->as_mv, &best_mv->as_mv);
cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
if (thissme < bestsme) {
bestsme = thissme;
*new_mv = best_mv->as_mv;
} else {
// The full search result is actually worse so re-instate the
// previous best vector
best_mv->as_mv = *new_mv;
}
}
if (bestsme < INT_MAX) {
int distortion;
cpi->find_fractional_mv_step(
x,
new_mv,
&ref_mv->as_mv,
cm->allow_high_precision_mv,
x->errorperbit, &cpi->fn_ptr[bsize],
cpi->sf.mv.subpel_force_stop,
cpi->sf.mv.subpel_iters_per_step,
cond_cost_list(cpi, cost_list),
x->nmvjointcost, x->mvcost,
&distortion,
&x->pred_sse[mbmi->ref_frame[0]],
NULL, 0, 0);
}
if (cpi->sf.adaptive_motion_search)
x->pred_mv[mbmi->ref_frame[0]] = *new_mv;
}
static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
const TileInfo * const tile,
int_mv *best_ref_mv,
@ -2410,16 +2527,20 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_COMPOUND_MODES
int_mv newnew_seg_mvs[4][MAX_REF_FRAMES];
#endif
int_mv ref_mv_sub8x8[2];
vp9_zero(*bsi);
bsi->segment_rd = best_rd;
bsi->ref_mv[0] = best_ref_mv;
bsi->ref_mv[1] = second_best_ref_mv;
bsi->mvp.as_int = best_ref_mv->as_int;
bsi->mvthresh = mvthresh;
ref_mv_sub8x8[0].as_int = best_ref_mv->as_int;
ref_mv_sub8x8[1].as_int =
second_best_ref_mv ? second_best_ref_mv->as_int : 0;
bsi->ref_mv[0] = &ref_mv_sub8x8[0];
bsi->ref_mv[1] = &ref_mv_sub8x8[1];
for (i = 0; i < 4; i++)
bsi->modes[i] = ZEROMV;
@ -2446,10 +2567,25 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
for (ref = 0; ref < 1 + has_second_rf; ++ref) {
const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
#if CONFIG_NEWMVREF_SUB8X8
int_mv mv_ref_list[MAX_MV_REF_CANDIDATES];
int_mv second_ref_mv;
vp9_update_mv_context(cm, xd, tile, mi, frame, mv_ref_list,
i, mi_row, mi_col);
#endif // CONFIG_NEWMVREF_SUB8X8
frame_mv[ZEROMV][frame].as_int = 0;
vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, i, ref, mi_row, mi_col,
#if CONFIG_NEWMVREF_SUB8X8
mv_ref_list,
#endif // CONFIG_NEWMVREF_SUB8X8
&frame_mv[NEARESTMV][frame],
&frame_mv[NEARMV][frame]);
#if CONFIG_NEWMVREF_SUB8X8
mv_ref_list[0].as_int = frame_mv[NEARESTMV][frame].as_int;
mv_ref_list[1].as_int = frame_mv[NEARMV][frame].as_int;
vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, mv_ref_list,
&ref_mv_sub8x8[ref], &second_ref_mv);
#endif // CONFIG_NEWMVREF_SUB8X8
#if CONFIG_COMPOUND_MODES
frame_mv[ZERO_ZEROMV][frame].as_int = 0;
frame_mv[NEAREST_NEARESTMV][frame].as_int =
@ -2502,10 +2638,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
if (is_inter_compound_mode(this_mode)) {
mode_idx = INTER_COMPOUND_OFFSET(this_mode) + INTER_OFFSET(NEWMV) + 1;
} else {
mode_idx = INTER_OFFSET(this_mode);
}
#else
#endif
mode_idx = INTER_OFFSET(this_mode);
#if CONFIG_COMPOUND_MODES
}
#endif
bsi->rdstat[i][mode_idx].brdcost = INT64_MAX;
@ -2523,108 +2659,29 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
sizeof(bsi->rdstat[i][mode_idx].tl));
// motion search for newmv (single predictor case only)
if (!has_second_rf && this_mode == NEWMV &&
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
MV *const new_mv = &mode_mv[NEWMV][0].as_mv;
int step_param = 0;
int thissme, bestsme = INT_MAX;
int sadpb = x->sadperbit4;
MV mvp_full;
int max_mv;
int cost_list[5];
// Note: Need to check new mvs for every iteration as the mv ref has
// changed in the NEWMVREF_SUB8X8 experiment.
if (!has_second_rf && this_mode == NEWMV
#if !CONFIG_NEWMVREF_SUB8X8
&& seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV
#endif // CONFIG_NEWMVREF_SUB8X8
) {
/* Is the best so far sufficiently good that we cant justify doing
* and new motion search. */
if (best_rd < label_mv_thresh)
break;
if (cpi->oxcf.mode != BEST) {
// use previous block's result as next block's MV predictor.
if (i > 0) {
bsi->mvp.as_int = mi->bmi[i - 1].as_mv[0].as_int;
if (i == 2)
bsi->mvp.as_int = mi->bmi[i - 2].as_mv[0].as_int;
}
}
if (i == 0)
max_mv = x->max_mv_context[mbmi->ref_frame[0]];
else
max_mv = MAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
// Take wtd average of the step_params based on the last frame's
// max mv magnitude and the best ref mvs of the current block for
// the given reference.
step_param = (vp9_init_search_range(max_mv) +
cpi->mv_step_param) / 2;
} else {
step_param = cpi->mv_step_param;
}
mvp_full.row = bsi->mvp.as_mv.row >> 3;
mvp_full.col = bsi->mvp.as_mv.col >> 3;
if (cpi->sf.adaptive_motion_search) {
mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].col >> 3;
step_param = MAX(step_param, 8);
}
// adjust src pointer for this block
mi_buf_shift(x, i);
vp9_set_mv_search_range(x, &bsi->ref_mv[0]->as_mv);
bestsme = vp9_full_pixel_search(
cpi, x, bsize, &mvp_full, step_param, sadpb,
cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
&bsi->ref_mv[0]->as_mv, new_mv,
INT_MAX, 1);
// Should we do a full search (best quality only)
if (cpi->oxcf.mode == BEST) {
int_mv *const best_mv = &mi->bmi[i].as_mv[0];
/* Check if mvp_full is within the range. */
clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
x->mv_row_min, x->mv_row_max);
thissme = cpi->full_search_sad(x, &mvp_full,
sadpb, 16, &cpi->fn_ptr[bsize],
&bsi->ref_mv[0]->as_mv,
&best_mv->as_mv);
cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
if (thissme < bestsme) {
bestsme = thissme;
*new_mv = best_mv->as_mv;
} else {
// The full search result is actually worse so re-instate the
// previous best vector
best_mv->as_mv = *new_mv;
}
}
if (bestsme < INT_MAX) {
int distortion;
cpi->find_fractional_mv_step(
x,
new_mv,
&bsi->ref_mv[0]->as_mv,
cm->allow_high_precision_mv,
x->errorperbit, &cpi->fn_ptr[bsize],
cpi->sf.mv.subpel_force_stop,
cpi->sf.mv.subpel_iters_per_step,
cond_cost_list(cpi, cost_list),
x->nmvjointcost, x->mvcost,
&distortion,
&x->pred_sse[mbmi->ref_frame[0]],
NULL, 0, 0);
// save motion search result for use in compound prediction
seg_mvs[i][mbmi->ref_frame[0]].as_mv = *new_mv;
}
if (cpi->sf.adaptive_motion_search)
x->pred_mv[mbmi->ref_frame[0]] = *new_mv;
frame_mv[this_mode][mbmi->ref_frame[0]].as_int = INVALID_MV;
single_motion_search_sub8x8(
cpi, x, i, bsize,
&frame_mv[this_mode][mbmi->ref_frame[0]].as_mv,
&ref_mv_sub8x8[0],
&bsi->mvp);
// save motion search result for use in compound prediction
seg_mvs[i][mbmi->ref_frame[0]].as_int =
frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
// restore src pointers
mi_buf_restore(x, orig_src, orig_pre);
}
@ -2634,18 +2691,27 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV)
continue;
}
// Note: Need to check new mvs for every iteration as the mv ref has
// changed in the NEWMVREF_SUB8X8 experiment.
// TODO(zoeliu): Further optimization work may be done for:
// NEW_NEARESTMV, NEW_NEARMV, NEAREST_NEWMV, and NEAR_NEWMV, as the mv
// ref may have changed in the compound mode as opposed to single ref.
if (has_second_rf
#if CONFIG_COMPOUND_MODES
if (has_second_rf &&
this_mode == NEW_NEWMV &&
mbmi->interp_filter == EIGHTTAP) {
&& this_mode == NEW_NEWMV
#else
if (has_second_rf && this_mode == NEWMV &&
mbmi->interp_filter == EIGHTTAP) {
#endif
&& this_mode == NEWMV
#endif // CONFIG_COMPOUND_MODES
#if !CONFIG_NEWMVREF_SUB8X8
&& mbmi->interp_filter == EIGHTTAP
#endif // CONFIG_NEWMVREF_SUB8X8
) {
mi_buf_shift(x, i);
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
int rate_mv;
joint_motion_search(cpi, x, bsize, frame_mv[this_mode],
joint_motion_search(cpi, x, bsize,
frame_mv[this_mode],
ref_mv_sub8x8,
mi_row, mi_col, seg_mvs[i],
&rate_mv);
#if CONFIG_COMPOUND_MODES
@ -2655,9 +2721,9 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
#else
seg_mvs[i][mbmi->ref_frame[0]].as_int =
frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
seg_mvs[i][mbmi->ref_frame[1]].as_int =
frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
#endif
}
// restore src pointers
@ -2689,6 +2755,17 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
if (num_4x4_blocks_high > 1)
bsi->rdstat[i + 2][mode_idx].mvs[ref].as_int =
mode_mv[this_mode][ref].as_int;
#if CONFIG_NEWMVREF_SUB8X8
// Save the mv refs for the best mvs.
bsi->rdstat[i][mode_idx].ref_mv[ref].as_int =
bsi->ref_mv[ref]->as_int;
if (num_4x4_blocks_wide > 1)
bsi->rdstat[i + 1][mode_idx].ref_mv[ref].as_int =
bsi->ref_mv[ref]->as_int;
if (num_4x4_blocks_high > 1)
bsi->rdstat[i + 2][mode_idx].ref_mv[ref].as_int =
bsi->ref_mv[ref]->as_int;
#endif // CONFIG_NEWMVREF_SUB8X8
}
// Trap vectors that reach beyond the UMV borders
@ -2704,6 +2781,23 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
for (ref = 0; ref < 1 + has_second_rf; ++ref) {
subpelmv |= mv_has_subpel(&mode_mv[this_mode][ref].as_mv);
#if CONFIG_NEWMVREF_SUB8X8
if (this_mode == NEWMV
#if CONFIG_COMPOUND_MODES
|| this_mode == NEW_NEWMV ||
this_mode == NEAREST_NEWMV ||
this_mode == NEW_NEARESTMV ||
this_mode == NEAR_NEWMV ||
this_mode == NEW_NEARMV
#endif // CONFIG_COMPOUND_MODES
)
have_ref &= (
(mode_mv[this_mode][ref].as_int ==
ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int) &&
(bsi->ref_mv[ref]->as_int ==
ref_bsi->rdstat[i][mode_idx].ref_mv[ref].as_int) );
else
#endif // CONFIG_NEWMVREF_SUB8X8
have_ref &= mode_mv[this_mode][ref].as_int ==
ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int;
}
@ -2712,6 +2806,23 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
ref_bsi = bsi_buf + 1;
have_ref = 1;
for (ref = 0; ref < 1 + has_second_rf; ++ref)
#if CONFIG_NEWMVREF_SUB8X8
if (this_mode == NEWMV
#if CONFIG_COMPOUND_MODES
|| this_mode == NEW_NEWMV ||
this_mode == NEAREST_NEWMV ||
this_mode == NEW_NEARESTMV ||
this_mode == NEAR_NEWMV ||
this_mode == NEW_NEARMV
#endif // CONFIG_COMPOUND_MODES
)
have_ref &= (
(mode_mv[this_mode][ref].as_int ==
ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int) &&
(bsi->ref_mv[ref]->as_int ==
ref_bsi->rdstat[i][mode_idx].ref_mv[ref].as_int) );
else
#endif // CONFIG_NEWMVREF_SUB8X8
have_ref &= mode_mv[this_mode][ref].as_int ==
ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int;
}
@ -2759,7 +2870,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
mode_selected = this_mode;
best_rd = bsi->rdstat[i][mode_idx].brdcost;
}
} /*for each 4x4 mode*/
} /*for each sub 8x8 mode*/
if (best_rd == INT64_MAX) {
int iy, midx;
@ -2778,10 +2889,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
mode_idx = INTER_COMPOUND_OFFSET(mode_selected)
+ INTER_OFFSET(NEWMV) + 1;
} else {
mode_idx = INTER_OFFSET(mode_selected);
}
#else
#endif
mode_idx = INTER_OFFSET(mode_selected);
#if CONFIG_COMPOUND_MODES
}
#endif
vpx_memcpy(t_above, bsi->rdstat[i][mode_idx].ta, sizeof(t_above));
vpx_memcpy(t_left, bsi->rdstat[i][mode_idx].tl, sizeof(t_left));
@ -2789,19 +2900,17 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_COMPOUND_MODES
if (mode_selected == NEW_NEWMV) {
set_and_cost_bmi_mvs(cpi, xd, i, mode_selected, mode_mv[mode_selected],
frame_mv[mode_selected], newnew_seg_mvs[i],
bsi->ref_mv,
x->nmvjointcost, x->mvcost);
frame_mv[mode_selected], newnew_seg_mvs[i],
bsi->ref_mv, x->nmvjointcost, x->mvcost);
} else {
#endif
set_and_cost_bmi_mvs(cpi, xd, i, mode_selected, mode_mv[mode_selected],
frame_mv[mode_selected], seg_mvs[i],
bsi->ref_mv, x->nmvjointcost, x->mvcost);
frame_mv[mode_selected], seg_mvs[i],
bsi->ref_mv, x->nmvjointcost, x->mvcost);
#if CONFIG_COMPOUND_MODES
}
#endif
br += bsi->rdstat[i][mode_idx].brate;
bd += bsi->rdstat[i][mode_idx].bdist;
block_sse += bsi->rdstat[i][mode_idx].bsse;
@ -2842,14 +2951,19 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
if (is_inter_compound_mode(bsi->modes[i])) {
mode_idx = INTER_COMPOUND_OFFSET(bsi->modes[i]) + INTER_OFFSET(NEWMV) + 1;
} else {
mode_idx = INTER_OFFSET(bsi->modes[i]);
}
#else
#endif
mode_idx = INTER_OFFSET(bsi->modes[i]);
#if CONFIG_COMPOUND_MODES
}
#endif
mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int;
if (has_second_ref(mbmi))
mi->bmi[i].as_mv[1].as_int = bsi->rdstat[i][mode_idx].mvs[1].as_int;
#if CONFIG_NEWMVREF_SUB8X8
mi->bmi[i].ref_mv[0].as_int = bsi->rdstat[i][mode_idx].ref_mv[0].as_int;
if (has_second_ref(mbmi))
mi->bmi[i].ref_mv[1].as_int = bsi->rdstat[i][mode_idx].ref_mv[1].as_int;
#endif // CONFIG_NEWMVREF_SUB8X8
x->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs;
mi->bmi[i].as_mode = bsi->modes[i];
}
@ -3121,6 +3235,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize,
int_mv *frame_mv,
int_mv *ref_mv,
int mi_row, int mi_col,
int_mv single_newmv[MAX_REF_FRAMES],
int *rate_mv) {
@ -3130,7 +3245,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
const int refs[2] = { mbmi->ref_frame[0],
mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
int_mv ref_mv[2];
int ite, ref;
// Prediction buffer from second frame.
#if CONFIG_VP9_HIGHBITDEPTH
@ -3160,8 +3274,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
#endif // CONFIG_VP9_HIGHBITDEPTH
for (ref = 0; ref < 2; ++ref) {
ref_mv[ref] = mbmi->ref_mvs[refs[ref]][0];
if (scaled_ref_frame[ref]) {
int i;
// Swap out the reference frame for a version that's been scaled to
@ -3172,7 +3284,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
vp9_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col,
NULL);
}
frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int;
}
@ -3291,7 +3402,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
}
*rate_mv += vp9_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
&mbmi->ref_mvs[refs[ref]][0].as_mv,
&ref_mv[ref].as_mv,
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
}
@ -3507,6 +3618,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
int i;
int refs[2] = { mbmi->ref_frame[0],
(mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
int_mv ref_mv[2] =
{ mbmi->ref_mvs[refs[0]][0], mbmi->ref_mvs[refs[1]][0] };
int_mv cur_mv[2];
#if CONFIG_VP9_HIGHBITDEPTH
DECLARE_ALIGNED_ARRAY(16, uint16_t, tmp_buf16, MAX_MB_PLANE * 64 * 64);
@ -3654,7 +3767,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_COMPOUND_MODES
if (this_mode == NEW_NEWMV) {
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
joint_motion_search(cpi, x, bsize, frame_mv,
joint_motion_search(cpi, x, bsize, frame_mv, ref_mv,
mi_row, mi_col, single_newmv, &rate_mv);
} else {
// Initialize mv using single prediction mode result.
@ -3679,7 +3792,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
#else
// Initialize mv using single prediction mode result.
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
joint_motion_search(cpi, x, bsize, frame_mv,
joint_motion_search(cpi, x, bsize, frame_mv, ref_mv,
mi_row, mi_col, single_newmv, &rate_mv);
} else {
rate_mv = vp9_mv_bit_cost(&frame_mv[refs[0]].as_mv,