Commit 8e173429 authored by Yunqing Wang's avatar Yunqing Wang
Browse files

Port an out of range motion vector bug fix in sub-pel motion estimation

Ported an out of range MV bug fix from VP9.
(https://chromium-review.googlesource.com/c/458180/)

Change-Id: Id2a7636f3c78547f8ae2081c4bcba709910b1650
parent 37f86a3d
......@@ -53,6 +53,21 @@ void av1_set_mv_search_range(MACROBLOCK *x, const MV *mv) {
if (x->mv_row_max > row_max) x->mv_row_max = row_max;
}
void av1_set_subpel_mv_search_range(const MACROBLOCK *x, int *col_min,
int *col_max, int *row_min, int *row_max,
const MV *ref_mv) {
const int max_mv = MAX_FULL_PEL_VAL * 8;
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - max_mv);
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + max_mv);
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - max_mv);
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + max_mv);
*col_min = AOMMAX(MV_LOW + 1, minc);
*col_max = AOMMIN(MV_UPP - 1, maxc);
*row_min = AOMMAX(MV_LOW + 1, minr);
*row_max = AOMMIN(MV_UPP - 1, maxr);
}
int av1_init_search_range(int size) {
int sr = 0;
// Minimum search size no matter what the passed in value.
......@@ -277,33 +292,32 @@ static INLINE const uint8_t *upre(const uint8_t *buf, int stride, int r,
} \
}
#define SETUP_SUBPEL_SEARCH \
const uint8_t *const src_address = x->plane[0].src.buf; \
const int src_stride = x->plane[0].src.stride; \
const MACROBLOCKD *xd = &x->e_mbd; \
unsigned int besterr = INT_MAX; \
unsigned int sse; \
unsigned int whichdir; \
int thismse; \
MV *bestmv = &x->best_mv.as_mv; \
const unsigned int halfiters = iters_per_step; \
const unsigned int quarteriters = iters_per_step; \
const unsigned int eighthiters = iters_per_step; \
const int y_stride = xd->plane[0].pre[0].stride; \
const int offset = bestmv->row * y_stride + bestmv->col; \
const uint8_t *const y = xd->plane[0].pre[0].buf; \
\
int br = bestmv->row * 8; \
int bc = bestmv->col * 8; \
int hstep = 4; \
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - MV_MAX); \
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + MV_MAX); \
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - MV_MAX); \
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + MV_MAX); \
int tr = br; \
int tc = bc; \
\
bestmv->row *= 8; \
#define SETUP_SUBPEL_SEARCH \
const uint8_t *const src_address = x->plane[0].src.buf; \
const int src_stride = x->plane[0].src.stride; \
const MACROBLOCKD *xd = &x->e_mbd; \
unsigned int besterr = INT_MAX; \
unsigned int sse; \
unsigned int whichdir; \
int thismse; \
MV *bestmv = &x->best_mv.as_mv; \
const unsigned int halfiters = iters_per_step; \
const unsigned int quarteriters = iters_per_step; \
const unsigned int eighthiters = iters_per_step; \
const int y_stride = xd->plane[0].pre[0].stride; \
const int offset = bestmv->row * y_stride + bestmv->col; \
const uint8_t *const y = xd->plane[0].pre[0].buf; \
\
int br = bestmv->row * 8; \
int bc = bestmv->col * 8; \
int hstep = 4; \
int minc, maxc, minr, maxr; \
int tr = br; \
int tc = bc; \
\
av1_set_subpel_mv_search_range(x, &minc, &maxc, &minr, &maxr, ref_mv); \
\
bestmv->row *= 8; \
bestmv->col *= 8;
static unsigned int setup_center_error(
......@@ -433,10 +447,6 @@ int av1_find_best_sub_pixel_tree_pruned_evenmore(
bestmv->row = br;
bestmv->col = bc;
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -499,10 +509,6 @@ int av1_find_best_sub_pixel_tree_pruned_more(
bestmv->row = br;
bestmv->col = bc;
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -587,10 +593,6 @@ int av1_find_best_sub_pixel_tree_pruned(
bestmv->row = br;
bestmv->col = bc;
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -674,16 +676,15 @@ int av1_find_best_sub_pixel_tree(MACROBLOCK *x, const MV *ref_mv, int allow_hp,
int bc = bestmv->col * 8;
int hstep = 4;
int iter, round = 3 - forced_stop;
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
int tr = br;
int tc = bc;
const MV *search_step = search_step_table;
int idx, best_idx = -1;
unsigned int cost_array[5];
int kr, kc;
int minc, maxc, minr, maxr;
av1_set_subpel_mv_search_range(x, &minc, &maxc, &minr, &maxr, ref_mv);
if (!allow_hp)
if (round == 3) round = 2;
......@@ -811,10 +812,6 @@ int av1_find_best_sub_pixel_tree(MACROBLOCK *x, const MV *ref_mv, int allow_hp,
bestmv->row = br;
bestmv->col = bc;
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -2409,13 +2406,11 @@ int av1_find_best_masked_sub_pixel_tree(
int br = bestmv->row * 8;
int bc = bestmv->col * 8;
int hstep = 4;
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
int tr = br;
int tc = bc;
int minc, maxc, minr, maxr;
av1_set_subpel_mv_search_range(x, &minc, &maxc, &minr, &maxr, ref_mv);
// central mv
bestmv->row *= 8;
......@@ -2463,10 +2458,6 @@ int av1_find_best_masked_sub_pixel_tree(
bestmv->row = br;
bestmv->col = bc;
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -2552,10 +2543,6 @@ int av1_find_best_masked_sub_pixel_tree_up(
int hstep = 4;
int iter;
int round = 3 - forced_stop;
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
int tr = br;
int tc = bc;
const MV *search_step = search_step_table;
......@@ -2569,6 +2556,10 @@ int av1_find_best_masked_sub_pixel_tree_up(
const uint8_t *y;
const struct buf_2d backup_pred = pd->pre[is_second];
int minc, maxc, minr, maxr;
av1_set_subpel_mv_search_range(x, &minc, &maxc, &minr, &maxr, ref_mv);
if (use_upsampled_ref) {
int ref = xd->mi[0]->mbmi.ref_frame[is_second];
const YV12_BUFFER_CONFIG *upsampled_ref = get_upsampled_ref(cpi, ref);
......@@ -2704,10 +2695,6 @@ int av1_find_best_masked_sub_pixel_tree_up(
pd->pre[is_second] = backup_pred;
}
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......@@ -3054,10 +3041,6 @@ int av1_find_best_obmc_sub_pixel_tree_up(
int hstep = 4;
int iter;
int round = 3 - forced_stop;
const int minc = AOMMAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
const int maxc = AOMMIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
const int minr = AOMMAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
const int maxr = AOMMIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
int tr = br;
int tc = bc;
const MV *search_step = search_step_table;
......@@ -3071,6 +3054,10 @@ int av1_find_best_obmc_sub_pixel_tree_up(
const uint8_t *y;
const struct buf_2d backup_pred = pd->pre[is_second];
int minc, maxc, minr, maxr;
av1_set_subpel_mv_search_range(x, &minc, &maxc, &minr, &maxr, ref_mv);
if (use_upsampled_ref) {
int ref = xd->mi[0]->mbmi.ref_frame[is_second];
const YV12_BUFFER_CONFIG *upsampled_ref = get_upsampled_ref(cpi, ref);
......@@ -3201,10 +3188,6 @@ int av1_find_best_obmc_sub_pixel_tree_up(
pd->pre[is_second] = backup_pred;
}
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
return INT_MAX;
return besterr;
}
......
......@@ -47,6 +47,10 @@ void av1_init_dsmotion_compensation(search_site_config *cfg, int stride);
void av1_init3smotion_compensation(search_site_config *cfg, int stride);
void av1_set_mv_search_range(MACROBLOCK *x, const MV *mv);
void av1_set_subpel_mv_search_range(const MACROBLOCK *x, int *col_min,
int *col_max, int *row_min, int *row_max,
const MV *ref_mv);
int av1_mv_bit_cost(const MV *mv, const MV *ref, const int *mvjcost,
int *mvcost[2], int weight);
......
......@@ -258,6 +258,10 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
int distortion;
unsigned int sse;
int cost_list[5];
int tmp_col_min = x->mv_col_min;
int tmp_col_max = x->mv_col_max;
int tmp_row_min = x->mv_row_min;
int tmp_row_max = x->mv_row_max;
MV best_ref_mv1 = { 0, 0 };
MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
......@@ -278,6 +282,8 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
step_param = mv_sf->reduce_first_step_size;
step_param = AOMMIN(step_param, MAX_MVSEARCH_STEPS - 2);
av1_set_mv_search_range(x, &best_ref_mv1);
#if CONFIG_REF_MV
x->mvcost = x->mv_cost_stack[0];
x->nmvjointcost = x->nmv_vec_cost[0];
......@@ -290,6 +296,11 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
cond_cost_list(cpi, cost_list), &cpi->fn_ptr[BLOCK_16X16], 0,
&best_ref_mv1);
x->mv_col_min = tmp_col_min;
x->mv_col_max = tmp_col_max;
x->mv_row_min = tmp_row_min;
x->mv_row_max = tmp_row_max;
// Ignore mv costing by sending NULL pointer instead of cost array
bestsme = cpi->find_fractional_mv_step(
x, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment