Merge "Changed mv ref to nearestmv always for sub8x8" into nextgen

This commit is contained in:
Zoe Liu 2015-03-05 11:57:21 -08:00 committed by Gerrit Code Review
commit e222d46658
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,