Pass (second_)best_mv explicitly to av1_full_pixel_search
This CL passes the best_mvs explicitly to full_pixel_search functions to
expose a bug where the second_best_mv is incorrectly overwritten.
As a result of this change, macroblock x can be changed to const. To
facilitate this, we also refactor intrabc hash search to a
separate function.
Change-Id: I3c184fd3219bcea8c1581ffa8e8ff552893f8c43
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 89fd4d3..da7b50a 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -394,8 +394,6 @@
// Store the best motion vector during motion search
int_mv best_mv;
- // Store the second best motion vector during full-pixel motion search
- int_mv second_best_mv;
// Store the fractional best motion vector during sub/Qpel-pixel motion search
int_mv fractional_best_mv[3];
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index fd7dcd2..4c793be 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -234,8 +234,8 @@
tmp_err = av1_full_pixel_search(
cpi, x, bsize, start_mv, step_param, NSTEP, 0, x->sadperbit16,
- cond_cost_list(cpi, cost_list), ref_mv, (MI_SIZE * xd->mi_col),
- (MI_SIZE * xd->mi_row), 0, &cpi->ss_cfg[SS_CFG_FPF], 0);
+ cond_cost_list(cpi, cost_list), ref_mv, 0, &cpi->ss_cfg[SS_CFG_FPF],
+ &x->best_mv.as_fullmv, NULL);
if (tmp_err < INT_MAX) {
tmp_err = av1_get_mvpred_sse(x, &x->best_mv.as_fullmv, ref_mv, &v_fn_ptr) +
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 521d8b7..59552c8 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -480,10 +480,11 @@
// candidates as indicated in the num_candidates and candidates arrays
// passed into this function
static int pattern_search(
- MACROBLOCK *x, FULLPEL_MV start_mv, int search_param, int sad_per_bit,
+ const MACROBLOCK *x, FULLPEL_MV start_mv, int search_param, int sad_per_bit,
int do_init_search, int *cost_list, const aom_variance_fn_ptr_t *vfp,
const MV *ref_mv, const int num_candidates[MAX_PATTERN_SCALES],
- const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES]) {
+ const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES],
+ FULLPEL_MV *best_mv) {
const MACROBLOCKD *const xd = &x->e_mbd;
static const int search_param_to_steps[MAX_MVSEARCH_STEPS] = {
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
@@ -716,6 +717,9 @@
}
}
+ best_mv->row = br;
+ best_mv->col = bc;
+
// Returns the one-away integer pel cost/sad around the best as follows:
// cost_list[0]: cost/sad at the best integer pel
// cost_list[1]: cost/sad at delta {0, -1} (left) from the best integer pel
@@ -723,19 +727,15 @@
// cost_list[3]: cost/sad at delta { 0, 1} (right) from the best integer pel
// cost_list[4]: cost/sad at delta {-1, 0} (top) from the best integer pel
if (cost_list) {
- const FULLPEL_MV full_best_mv = { br, bc };
if (USE_SAD_COSTLIST) {
- calc_int_sad_list(x, ref_mv, sad_per_bit, vfp, &full_best_mv, cost_list,
+ calc_int_sad_list(x, ref_mv, sad_per_bit, vfp, best_mv, cost_list,
costlist_has_sad);
} else {
- calc_int_cost_list(x, ref_mv, vfp, &full_best_mv, cost_list);
+ calc_int_cost_list(x, ref_mv, vfp, best_mv, cost_list);
}
}
- x->best_mv.as_fullmv.row = br;
- x->best_mv.as_fullmv.col = bc;
- const int var_cost =
- av1_get_mvpred_var(x, &x->best_mv.as_fullmv, ref_mv, vfp);
+ const int var_cost = av1_get_mvpred_var(x, best_mv, ref_mv, vfp);
return var_cost;
}
#undef CHECK_BETTER
@@ -754,10 +754,10 @@
// vfp: a function pointer to the simd function so we can compute the cost
// efficiently
// ref_mv: the reference mv used to compute the mv cost
-static int hex_search(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int hex_search(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int search_param, int sad_per_bit, int do_init_search,
int *cost_list, const aom_variance_fn_ptr_t *vfp,
- const MV *ref_mv) {
+ const MV *ref_mv, FULLPEL_MV *best_mv) {
// First scale has 8-closest points, the rest have 6 points in hex shape
// at increasing scales
static const int hex_num_candidates[MAX_PATTERN_SCALES] = { 8, 6, 6, 6, 6, 6,
@@ -787,13 +787,13 @@
/* clang-format on */
return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
cost_list, vfp, ref_mv, hex_num_candidates,
- hex_candidates);
+ hex_candidates, best_mv);
}
-static int bigdia_search(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int bigdia_search(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int search_param, int sad_per_bit, int do_init_search,
int *cost_list, const aom_variance_fn_ptr_t *vfp,
- const MV *ref_mv) {
+ const MV *ref_mv, FULLPEL_MV *best_mv) {
// First scale has 4-closest points, the rest have 8 points in diamond
// shape at increasing scales
static const int bigdia_num_candidates[MAX_PATTERN_SCALES] = {
@@ -828,13 +828,13 @@
/* clang-format on */
return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
cost_list, vfp, ref_mv, bigdia_num_candidates,
- bigdia_candidates);
+ bigdia_candidates, best_mv);
}
-static int square_search(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int square_search(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int search_param, int sad_per_bit, int do_init_search,
int *cost_list, const aom_variance_fn_ptr_t *vfp,
- const MV *ref_mv) {
+ const MV *ref_mv, FULLPEL_MV *best_mv) {
// All scales have 8 closest points in square shape
static const int square_num_candidates[MAX_PATTERN_SCALES] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
@@ -869,32 +869,35 @@
/* clang-format on */
return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
cost_list, vfp, ref_mv, square_num_candidates,
- square_candidates);
+ square_candidates, best_mv);
}
-static int fast_hex_search(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int fast_hex_search(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int search_param, int sad_per_bit,
int do_init_search, // must be zero for fast_hex
int *cost_list, const aom_variance_fn_ptr_t *vfp,
- const MV *ref_mv) {
+ const MV *ref_mv, FULLPEL_MV *best_mv) {
return hex_search(x, start_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param),
- sad_per_bit, do_init_search, cost_list, vfp, ref_mv);
+ sad_per_bit, do_init_search, cost_list, vfp, ref_mv,
+ best_mv);
}
-static int fast_dia_search(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int fast_dia_search(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int search_param, int sad_per_bit,
int do_init_search, int *cost_list,
- const aom_variance_fn_ptr_t *vfp, const MV *ref_mv) {
- return bigdia_search(x, start_mv,
- AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param),
- sad_per_bit, do_init_search, cost_list, vfp, ref_mv);
+ const aom_variance_fn_ptr_t *vfp, const MV *ref_mv,
+ FULLPEL_MV *best_mv) {
+ return bigdia_search(
+ x, start_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param), sad_per_bit,
+ do_init_search, cost_list, vfp, ref_mv, best_mv);
}
// Exhaustive motion search around a given centre position with a given
// step size.
-static int exhuastive_mesh_search(MACROBLOCK *x, FULLPEL_MV *ref_mv,
- FULLPEL_MV *best_mv, int range, int step,
- int sad_per_bit,
+static int exhuastive_mesh_search(const MACROBLOCK *x, FULLPEL_MV *ref_mv,
+ FULLPEL_MV *best_mv,
+ FULLPEL_MV *second_best_mv, int range,
+ int step, int sad_per_bit,
const aom_variance_fn_ptr_t *fn_ptr,
FULLPEL_MV start_mv) {
const MACROBLOCKD *const xd = &x->e_mbd;
@@ -929,7 +932,9 @@
sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
if (sad < best_sad) {
best_sad = sad;
- x->second_best_mv.as_fullmv = *best_mv;
+ if (second_best_mv) {
+ *second_best_mv = *best_mv;
+ }
*best_mv = mv;
}
}
@@ -951,7 +956,9 @@
sads[i] + mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
if (sad < best_sad) {
best_sad = sad;
- x->second_best_mv.as_fullmv = *best_mv;
+ if (second_best_mv) {
+ *second_best_mv = *best_mv;
+ }
*best_mv = mv;
}
}
@@ -966,7 +973,9 @@
sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
if (sad < best_sad) {
best_sad = sad;
- x->second_best_mv.as_fullmv = *best_mv;
+ if (second_best_mv) {
+ *second_best_mv = *best_mv;
+ }
*best_mv = mv;
}
}
@@ -979,9 +988,11 @@
return best_sad;
}
-static int diamond_search_sad(MACROBLOCK *x, const search_site_config *cfg,
+static int diamond_search_sad(const MACROBLOCK *x,
+ const search_site_config *cfg,
FULLPEL_MV start_mv, FULLPEL_MV *best_mv,
- int search_param, int sad_per_bit, int *num00,
+ FULLPEL_MV *second_best_mv, int search_param,
+ int sad_per_bit, int *num00,
const aom_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, uint8_t *second_pred,
uint8_t *mask, int mask_stride, int inv_mask) {
@@ -1093,7 +1104,9 @@
}
if (best_site != 0) {
- x->second_best_mv.as_fullmv = *best_mv;
+ if (second_best_mv) {
+ *second_best_mv = *best_mv;
+ }
best_mv->row += ss[best_site].mv.row;
best_mv->col += ss[best_site].mv.col;
best_address += ss[best_site].offset;
@@ -1117,62 +1130,63 @@
/* do_refine: If last step (1-away) of n-step search doesn't pick the center
point as the best match, we will do a final 1-away diamond
refining search */
-static int full_pixel_diamond(MACROBLOCK *x, const FULLPEL_MV start_mv,
+static int full_pixel_diamond(const MACROBLOCK *x, const FULLPEL_MV start_mv,
int step_param, int sadpb, int *cost_list,
const aom_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, const search_site_config *cfg,
uint8_t *second_pred, uint8_t *mask,
- int mask_stride, int inv_mask) {
- FULLPEL_MV best_mv;
+ int mask_stride, int inv_mask,
+ FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv) {
int thissme, n, num00 = 0;
- int bestsme = diamond_search_sad(x, cfg, start_mv, &best_mv, step_param,
- sadpb, &n, fn_ptr, ref_mv, second_pred, mask,
- mask_stride, inv_mask);
+ int bestsme = diamond_search_sad(x, cfg, start_mv, best_mv, second_best_mv,
+ step_param, sadpb, &n, fn_ptr, ref_mv,
+ second_pred, mask, mask_stride, inv_mask);
if (bestsme < INT_MAX) {
if (mask)
bestsme = av1_get_mvpred_mask_var(
- x, &best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask, fn_ptr,
+ x, best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask, fn_ptr,
&x->plane[0].src, &x->e_mbd.plane[0].pre[0]);
else if (second_pred)
bestsme =
- av1_get_mvpred_av_var(x, &best_mv, ref_mv, second_pred, fn_ptr,
+ av1_get_mvpred_av_var(x, best_mv, ref_mv, second_pred, fn_ptr,
&x->plane[0].src, &x->e_mbd.plane[0].pre[0]);
else
- bestsme = av1_get_mvpred_var(x, &best_mv, ref_mv, fn_ptr);
+ bestsme = av1_get_mvpred_var(x, best_mv, ref_mv, fn_ptr);
}
- x->best_mv.as_fullmv = best_mv;
-
// If there won't be more n-step search, check to see if refining search is
// needed.
const int further_steps = cfg->ss_count - 1 - step_param;
while (n < further_steps) {
++n;
+ FULLPEL_MV tmp_best_mv;
if (num00) {
num00--;
} else {
- thissme = diamond_search_sad(x, cfg, start_mv, &best_mv, step_param + n,
- sadpb, &num00, fn_ptr, ref_mv, second_pred,
- mask, mask_stride, inv_mask);
+ // TODO(chiyotsai@google.com): There is another bug here where the second
+ // best mv gets incorrectly overwritten. Fix it later.
+ thissme = diamond_search_sad(
+ x, cfg, start_mv, &tmp_best_mv, second_best_mv, step_param + n, sadpb,
+ &num00, fn_ptr, ref_mv, second_pred, mask, mask_stride, inv_mask);
if (thissme < INT_MAX) {
if (mask)
thissme = av1_get_mvpred_mask_var(
- x, &best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask,
+ x, &tmp_best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask,
fn_ptr, &x->plane[0].src, &x->e_mbd.plane[0].pre[0]);
else if (second_pred)
- thissme = av1_get_mvpred_av_var(x, &best_mv, ref_mv, second_pred,
+ thissme = av1_get_mvpred_av_var(x, &tmp_best_mv, ref_mv, second_pred,
fn_ptr, &x->plane[0].src,
&x->e_mbd.plane[0].pre[0]);
else
- thissme = av1_get_mvpred_var(x, &best_mv, ref_mv, fn_ptr);
+ thissme = av1_get_mvpred_var(x, &tmp_best_mv, ref_mv, fn_ptr);
}
if (thissme < bestsme) {
bestsme = thissme;
- x->best_mv.as_fullmv = best_mv;
+ *best_mv = tmp_best_mv;
}
}
}
@@ -1196,8 +1210,9 @@
// Runs an limited range exhaustive mesh search using a pattern set
// according to the encode speed profile.
static int full_pixel_exhaustive(
- MACROBLOCK *x, const FULLPEL_MV start_mv, int sadpb, int *cost_list,
+ const MACROBLOCK *x, const FULLPEL_MV start_mv, int sadpb, int *cost_list,
const aom_variance_fn_ptr_t *fn_ptr, const MV *ref_mv, FULLPEL_MV *best_mv,
+ FULLPEL_MV *second_best_mv,
const struct MESH_PATTERN *const mesh_patterns) {
FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
int bestsme;
@@ -1222,8 +1237,8 @@
interval = AOMMAX(interval, range / baseline_interval_divisor);
// initial search
- bestsme = exhuastive_mesh_search(x, &full_ref_mv, best_mv, range, interval,
- sadpb, fn_ptr, *best_mv);
+ bestsme = exhuastive_mesh_search(x, &full_ref_mv, best_mv, second_best_mv,
+ range, interval, sadpb, fn_ptr, *best_mv);
if ((interval > MIN_INTERVAL) && (range > MIN_RANGE)) {
// Progressive searches with range and step size decreasing each time
@@ -1231,7 +1246,7 @@
for (i = 1; i < MAX_MESH_STEP; ++i) {
// First pass with coarser step and longer range
bestsme = exhuastive_mesh_search(
- x, &full_ref_mv, best_mv, mesh_patterns[i].range,
+ x, &full_ref_mv, best_mv, second_best_mv, mesh_patterns[i].range,
mesh_patterns[i].interval, sadpb, fn_ptr, *best_mv);
if (mesh_patterns[i].interval == 1) break;
@@ -1245,10 +1260,10 @@
if (cost_list) {
if (USE_SAD_COSTLIST) {
const int costlist_has_sad = 0;
- calc_int_sad_list(x, ref_mv, sadpb, fn_ptr, &x->best_mv.as_fullmv,
- cost_list, costlist_has_sad);
+ calc_int_sad_list(x, ref_mv, sadpb, fn_ptr, best_mv, cost_list,
+ costlist_has_sad);
} else {
- calc_int_cost_list(x, ref_mv, fn_ptr, &x->best_mv.as_fullmv, cost_list);
+ calc_int_cost_list(x, ref_mv, fn_ptr, best_mv, cost_list);
}
}
return bestsme;
@@ -1343,15 +1358,15 @@
return best_sad;
}
-int av1_full_pixel_search(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
- const FULLPEL_MV start_mv, int step_param, int method,
- int run_mesh_search, int error_per_bit,
- int *cost_list, const MV *ref_mv, int x_pos,
- int y_pos, int intra, const search_site_config *cfg,
- int use_intrabc_mesh_pattern) {
+int av1_full_pixel_search(const AV1_COMP *cpi, const MACROBLOCK *x,
+ BLOCK_SIZE bsize, const FULLPEL_MV start_mv,
+ int step_param, int method, int run_mesh_search,
+ int error_per_bit, int *cost_list, const MV *ref_mv,
+ int is_intra_mode, const search_site_config *cfg,
+ FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv) {
const SPEED_FEATURES *const sf = &cpi->sf;
const aom_variance_fn_ptr_t *fn_ptr = &cpi->fn_ptr[bsize];
- int var = 0;
+ int bestsme = 0;
if (cost_list) {
cost_list[0] = INT_MAX;
@@ -1363,30 +1378,30 @@
switch (method) {
case FAST_DIAMOND:
- var = fast_dia_search(x, start_mv, step_param, error_per_bit, 0,
- cost_list, fn_ptr, ref_mv);
+ bestsme = fast_dia_search(x, start_mv, step_param, error_per_bit, 0,
+ cost_list, fn_ptr, ref_mv, best_mv);
break;
case FAST_HEX:
- var = fast_hex_search(x, start_mv, step_param, error_per_bit, 0,
- cost_list, fn_ptr, ref_mv);
+ bestsme = fast_hex_search(x, start_mv, step_param, error_per_bit, 0,
+ cost_list, fn_ptr, ref_mv, best_mv);
break;
case HEX:
- var = hex_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
- fn_ptr, ref_mv);
+ bestsme = hex_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
+ fn_ptr, ref_mv, best_mv);
break;
case SQUARE:
- var = square_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
- fn_ptr, ref_mv);
+ bestsme = square_search(x, start_mv, step_param, error_per_bit, 1,
+ cost_list, fn_ptr, ref_mv, best_mv);
break;
case BIGDIA:
- var = bigdia_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
- fn_ptr, ref_mv);
+ bestsme = bigdia_search(x, start_mv, step_param, error_per_bit, 1,
+ cost_list, fn_ptr, ref_mv, best_mv);
break;
case NSTEP:
case DIAMOND:
- var =
- full_pixel_diamond(x, start_mv, step_param, error_per_bit, cost_list,
- fn_ptr, ref_mv, cfg, NULL, NULL, 0, 0);
+ bestsme = full_pixel_diamond(x, start_mv, step_param, error_per_bit,
+ cost_list, fn_ptr, ref_mv, cfg, NULL, NULL,
+ 0, 0, best_mv, second_best_mv);
break;
default: assert(0 && "Invalid search method.");
}
@@ -1397,15 +1412,14 @@
exhuastive_thr >>=
10 - (mi_size_wide_log2[bsize] + mi_size_high_log2[bsize]);
// Threshold variance for an exhaustive full search.
- if (var > exhuastive_thr) run_mesh_search = 1;
+ if (bestsme > exhuastive_thr) run_mesh_search = 1;
}
// TODO(yunqing): the following is used to reduce mesh search in temporal
// filtering. Can extend it to intrabc.
- if (!use_intrabc_mesh_pattern && sf->mv_sf.prune_mesh_search) {
- const int full_pel_mv_diff =
- AOMMAX(abs(start_mv.row - x->best_mv.as_fullmv.row),
- abs(start_mv.col - x->best_mv.as_fullmv.col));
+ if (!is_intra_mode && sf->mv_sf.prune_mesh_search) {
+ const int full_pel_mv_diff = AOMMAX(abs(start_mv.row - best_mv->row),
+ abs(start_mv.col - best_mv->col));
if (full_pel_mv_diff <= 4) {
run_mesh_search = 0;
}
@@ -1417,83 +1431,82 @@
// Pick the mesh pattern for exhaustive search based on the toolset (intraBC
// or non-intraBC)
const MESH_PATTERN *const mesh_patterns =
- use_intrabc_mesh_pattern ? sf->mv_sf.intrabc_mesh_patterns
- : sf->mv_sf.mesh_patterns;
- var_ex =
- full_pixel_exhaustive(x, x->best_mv.as_fullmv, error_per_bit, cost_list,
- fn_ptr, ref_mv, &tmp_mv_ex, mesh_patterns);
- if (var_ex < var) {
- var = var_ex;
- x->best_mv.as_fullmv = tmp_mv_ex;
+ is_intra_mode ? sf->mv_sf.intrabc_mesh_patterns
+ : sf->mv_sf.mesh_patterns;
+ // TODO(chiyotsai@google.com): There is a bug here where the second best mv
+ // gets overwritten without actually comparing the rdcost.
+ var_ex = full_pixel_exhaustive(x, *best_mv, error_per_bit, cost_list,
+ fn_ptr, ref_mv, &tmp_mv_ex, second_best_mv,
+ mesh_patterns);
+ if (var_ex < bestsme) {
+ bestsme = var_ex;
+ *best_mv = tmp_mv_ex;
}
}
- // Use hash-me for intrablock copy
- do {
- if (!intra || !av1_use_hash_me(cpi)) break;
+ return bestsme;
+}
- // already single ME
- // get block size and original buffer of current block
- const int block_height = block_size_high[bsize];
- const int block_width = block_size_wide[bsize];
- if (block_height == block_width && x_pos >= 0 && y_pos >= 0) {
- if (block_width == 4 || block_width == 8 || block_width == 16 ||
- block_width == 32 || block_width == 64 || block_width == 128) {
- uint8_t *what = x->plane[0].src.buf;
- const int what_stride = x->plane[0].src.stride;
- uint32_t hash_value1, hash_value2;
- FULLPEL_MV best_hash_mv;
- int best_hash_cost = INT_MAX;
+void av1_intrabc_hash_search(const AV1_COMP *cpi, MACROBLOCK *x,
+ BLOCK_SIZE bsize, const MV *ref_mv, int *bestsme,
+ FULLPEL_MV *best_mv) {
+ if (!av1_use_hash_me(cpi)) return;
- // for the hashMap
- hash_table *ref_frame_hash = &cpi->common.cur_frame->hash_table;
+ const aom_variance_fn_ptr_t *fn_ptr = &cpi->fn_ptr[bsize];
+ const int block_height = block_size_high[bsize];
+ const int block_width = block_size_wide[bsize];
+ const int mi_row = x->e_mbd.mi_row;
+ const int mi_col = x->e_mbd.mi_col;
+ const int x_pos = mi_col * MI_SIZE;
+ const int y_pos = mi_row * MI_SIZE;
- av1_get_block_hash_value(what, what_stride, block_width, &hash_value1,
- &hash_value2, is_cur_buf_hbd(&x->e_mbd), x);
+ if (block_height == block_width) {
+ uint8_t *what = x->plane[0].src.buf;
+ const int what_stride = x->plane[0].src.stride;
+ uint32_t hash_value1, hash_value2;
+ FULLPEL_MV best_hash_mv;
+ int best_hash_cost = INT_MAX;
- const int count = av1_hash_table_count(ref_frame_hash, hash_value1);
- // for intra, at lest one matching can be found, itself.
- if (count <= (intra ? 1 : 0)) {
- break;
- }
+ // for the hashMap
+ hash_table *ref_frame_hash = &cpi->common.cur_frame->hash_table;
- Iterator iterator =
- av1_hash_get_first_iterator(ref_frame_hash, hash_value1);
- for (int i = 0; i < count; i++, aom_iterator_increment(&iterator)) {
- block_hash ref_block_hash =
- *(block_hash *)(aom_iterator_get(&iterator));
- if (hash_value2 == ref_block_hash.hash_value2) {
- // For intra, make sure the prediction is from valid area.
- if (intra) {
- const int mi_col = x_pos / MI_SIZE;
- const int mi_row = y_pos / MI_SIZE;
- const MV dv = { 8 * (ref_block_hash.y - y_pos),
- 8 * (ref_block_hash.x - x_pos) };
- if (!av1_is_dv_valid(dv, &cpi->common, &x->e_mbd, mi_row, mi_col,
- bsize, cpi->common.seq_params.mib_size_log2))
- continue;
- }
- FULLPEL_MV hash_mv;
- hash_mv.col = ref_block_hash.x - x_pos;
- hash_mv.row = ref_block_hash.y - y_pos;
- if (!av1_is_fullmv_in_range(&x->mv_limits, hash_mv)) continue;
- const int refCost = av1_get_mvpred_var(x, &hash_mv, ref_mv, fn_ptr);
- if (refCost < best_hash_cost) {
- best_hash_cost = refCost;
- best_hash_mv = hash_mv;
- }
- }
- }
- if (best_hash_cost < var) {
- x->second_best_mv = x->best_mv;
- x->best_mv.as_fullmv = best_hash_mv;
- var = best_hash_cost;
+ av1_get_block_hash_value(what, what_stride, block_width, &hash_value1,
+ &hash_value2, is_cur_buf_hbd(&x->e_mbd), x);
+
+ const int count = av1_hash_table_count(ref_frame_hash, hash_value1);
+ // for intra, at lest one matching can be found, itself.
+ if (count <= 1) {
+ return;
+ }
+
+ Iterator iterator =
+ av1_hash_get_first_iterator(ref_frame_hash, hash_value1);
+ for (int i = 0; i < count; i++, aom_iterator_increment(&iterator)) {
+ block_hash ref_block_hash = *(block_hash *)(aom_iterator_get(&iterator));
+ if (hash_value2 == ref_block_hash.hash_value2) {
+ // Make sure the prediction is from valid area.
+ const MV dv = { GET_MV_SUBPEL(ref_block_hash.y - y_pos),
+ GET_MV_SUBPEL(ref_block_hash.x - x_pos) };
+ if (!av1_is_dv_valid(dv, &cpi->common, &x->e_mbd, mi_row, mi_col, bsize,
+ cpi->common.seq_params.mib_size_log2))
+ continue;
+
+ FULLPEL_MV hash_mv;
+ hash_mv.col = ref_block_hash.x - x_pos;
+ hash_mv.row = ref_block_hash.y - y_pos;
+ if (!av1_is_fullmv_in_range(&x->mv_limits, hash_mv)) continue;
+ const int refCost = av1_get_mvpred_var(x, &hash_mv, ref_mv, fn_ptr);
+ if (refCost < best_hash_cost) {
+ best_hash_cost = refCost;
+ best_hash_mv = hash_mv;
}
}
}
- } while (0);
-
- return var;
+ if (best_hash_cost < *bestsme) {
+ *best_mv = best_hash_mv;
+ *bestsme = best_hash_cost;
+ }
+ }
}
// =============================================================================
@@ -1619,7 +1632,7 @@
return best_sad;
}
-static int obmc_full_pixel_diamond(const AV1_COMP *cpi, MACROBLOCK *x,
+static int obmc_full_pixel_diamond(const AV1_COMP *cpi, const MACROBLOCK *x,
const FULLPEL_MV start_mv, int step_param,
int sadpb, int do_refine,
const aom_variance_fn_ptr_t *fn_ptr,
@@ -1679,7 +1692,7 @@
return bestsme;
}
-int av1_obmc_full_pixel_search(const AV1_COMP *cpi, MACROBLOCK *x,
+int av1_obmc_full_pixel_search(const AV1_COMP *cpi, const MACROBLOCK *x,
const FULLPEL_MV start_mv, int step_param,
int sadpb, const aom_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, FULLPEL_MV *best_mv,
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index 8a66cf1..a251d03 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -150,18 +150,21 @@
const struct buf_2d *src,
const struct buf_2d *pre);
-int av1_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
+int av1_full_pixel_search(const struct AV1_COMP *cpi, const MACROBLOCK *x,
BLOCK_SIZE bsize, const FULLPEL_MV start_mv,
int step_param, int method, int run_mesh_search,
int error_per_bit, int *cost_list, const MV *ref_mv,
- int x_pos, int y_pos, int intra,
- const search_site_config *cfg,
- int use_intrabc_mesh_pattern);
+ int is_intra_mode, const search_site_config *cfg,
+ FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv);
-int av1_obmc_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
+void av1_intrabc_hash_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
+ BLOCK_SIZE bsize, const MV *ref_mv, int *bestsme,
+ FULLPEL_MV *best_mv);
+
+int av1_obmc_full_pixel_search(const struct AV1_COMP *cpi, const MACROBLOCK *x,
const FULLPEL_MV start_mv, int step_param,
int sadpb, const aom_variance_fn_ptr_t *fn_ptr,
- const MV *ref_mv, FULLPEL_MV *dst_mv,
+ const MV *ref_mv, FULLPEL_MV *best_mv,
const search_site_config *cfg);
unsigned int av1_refine_warped_mv(const struct AV1_COMP *cpi,
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index 870a308..c8857e7 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -125,13 +125,15 @@
const int sadpb = x->sadperbit16;
int cost_list[5];
- x->best_mv.as_int = x->second_best_mv.as_int = INVALID_MV;
+ int_mv second_best_mv;
+ x->best_mv.as_int = second_best_mv.as_int = INVALID_MV;
switch (mbmi->motion_mode) {
case SIMPLE_TRANSLATION:
bestsme = av1_full_pixel_search(
cpi, x, bsize, start_mv, step_param, cpi->sf.mv_sf.search_method, 0,
- sadpb, cond_cost_list(cpi, cost_list), &ref_mv, (MI_SIZE * mi_col),
- (MI_SIZE * mi_row), 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
+ sadpb, cond_cost_list(cpi, cost_list), &ref_mv, 0,
+ &cpi->ss_cfg[SS_CFG_SRC], &x->best_mv.as_fullmv,
+ &second_best_mv.as_fullmv);
break;
case OBMC_CAUSAL:
bestsme = av1_obmc_full_pixel_search(
@@ -211,8 +213,8 @@
switch (mbmi->motion_mode) {
case SIMPLE_TRANSLATION:
if (cpi->sf.mv_sf.use_accurate_subpel_search) {
- const int try_second = x->second_best_mv.as_int != INVALID_MV &&
- x->second_best_mv.as_int != x->best_mv.as_int;
+ const int try_second = second_best_mv.as_int != INVALID_MV &&
+ second_best_mv.as_int != x->best_mv.as_int;
const int best_mv_var = cpi->find_fractional_mv_step(
x, cm, &ms_params, &dis, &x->pred_sse[ref]);
@@ -222,7 +224,7 @@
&ref_mv);
MV best_mv = x->best_mv.as_mv;
- x->best_mv = x->second_best_mv;
+ x->best_mv = second_best_mv;
if (av1_is_subpelmv_in_range(
&subpel_limits,
get_mv_from_fullmv(&x->best_mv.as_fullmv))) {
@@ -707,8 +709,8 @@
av1_set_mv_search_range(&x->mv_limits, &ref_mv);
var = av1_full_pixel_search(
cpi, x, bsize, start_mv, step_param, search_methods, do_mesh_search,
- sadpb, cond_cost_list(cpi, cost_list), &ref_mv, mi_col * MI_SIZE,
- mi_row * MI_SIZE, 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
+ sadpb, cond_cost_list(cpi, cost_list), &ref_mv, 0,
+ &cpi->ss_cfg[SS_CFG_SRC], &x->best_mv.as_fullmv, NULL);
// Restore
x->mv_limits = tmp_mv_limits;
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 7b4dcd5..70d4db3 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -152,10 +152,10 @@
else
center_mv = tmp_mv->as_mv;
- av1_full_pixel_search(
- cpi, x, bsize, start_mv, step_param, cpi->sf.mv_sf.search_method, 0,
- sadpb, cond_cost_list(cpi, cost_list), ¢er_mv, (MI_SIZE * mi_col),
- (MI_SIZE * mi_row), 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
+ av1_full_pixel_search(cpi, x, bsize, start_mv, step_param,
+ cpi->sf.mv_sf.search_method, 0, sadpb,
+ cond_cost_list(cpi, cost_list), ¢er_mv, 0,
+ &cpi->ss_cfg[SS_CFG_SRC], &x->best_mv.as_fullmv, NULL);
x->mv_limits = tmp_mv_limits;
*tmp_mv = x->best_mv;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index d188b7b..57710d8 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -2728,11 +2728,12 @@
FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
const int sadpb = x->sadperbit16;
int cost_list[5];
- const int bestsme = av1_full_pixel_search(
+ int bestsme = av1_full_pixel_search(
cpi, x, bsize, start_mv, step_param, cpi->sf.mv_sf.search_method, 0,
- sadpb, cond_cost_list(cpi, cost_list), &dv_ref.as_mv,
- (MI_SIZE * mi_col), (MI_SIZE * mi_row), 1,
- &cpi->ss_cfg[SS_CFG_LOOKAHEAD], 1);
+ sadpb, cond_cost_list(cpi, cost_list), &dv_ref.as_mv, 1,
+ &cpi->ss_cfg[SS_CFG_LOOKAHEAD], &x->best_mv.as_fullmv, NULL);
+ av1_intrabc_hash_search(cpi, x, bsize, &dv_ref.as_mv, &bestsme,
+ &x->best_mv.as_fullmv);
x->mv_limits = tmp_mv_limits;
if (bestsme == INT_MAX) continue;
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index e4e53ec..e600ab8 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -69,8 +69,6 @@
// Block information (ONLY Y-plane is used for motion search).
const int mb_height = block_size_high[block_size];
const int mb_width = block_size_wide[block_size];
- const int mb_y = mb_height * mb_row;
- const int mb_x = mb_width * mb_col;
const int y_stride = frame_to_filter->y_stride;
assert(y_stride == ref_frame->y_stride);
const int y_offset = mb_row * mb_height * y_stride + mb_col * mb_width;
@@ -126,8 +124,8 @@
mb->mv_cost_type = mv_cost_type;
av1_full_pixel_search(cpi, mb, block_size, start_mv, step_param,
full_search_method, 1, sadperbit16,
- cond_cost_list(cpi, cost_list), &baseline_mv, mb_x,
- mb_y, 0, &ss_cfg, 0);
+ cond_cost_list(cpi, cost_list), &baseline_mv, 0,
+ &ss_cfg, &mb->best_mv.as_fullmv, NULL);
// Since we are merely refining the result from full pixel search, we don't
// need regularization for subpel search
mb->mv_cost_type = MV_COST_NONE;
@@ -168,8 +166,8 @@
mb->mv_cost_type = mv_cost_type;
av1_full_pixel_search(cpi, mb, subblock_size, start_mv, step_param,
full_search_method, 1, sadperbit16,
- cond_cost_list(cpi, cost_list), &baseline_mv,
- mb_x, mb_y, 0, &ss_cfg, 0);
+ cond_cost_list(cpi, cost_list), &baseline_mv, 0,
+ &ss_cfg, &mb->best_mv.as_fullmv, NULL);
// Since we are merely refining the result from full pixel search, we
// don't need regularization for subpel search
mb->mv_cost_type = MV_COST_NONE;
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 2c50db9..893e258 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -121,8 +121,8 @@
static uint32_t motion_estimation(AV1_COMP *cpi, MACROBLOCK *x,
uint8_t *cur_frame_buf,
uint8_t *ref_frame_buf, int stride,
- int stride_ref, BLOCK_SIZE bsize, int mi_row,
- int mi_col, MV center_mv) {
+ int stride_ref, BLOCK_SIZE bsize,
+ MV center_mv) {
AV1_COMMON *cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv_sf;
@@ -154,8 +154,8 @@
assert(ss_cfg->stride == stride_ref);
av1_full_pixel_search(cpi, x, bsize, start_mv, step_param, search_method, 0,
- sadpb, cond_cost_list(cpi, cost_list), ¢er_mv,
- (MI_SIZE * mi_col), (MI_SIZE * mi_row), 0, ss_cfg, 0);
+ sadpb, cond_cost_list(cpi, cost_list), ¢er_mv, 0,
+ ss_cfg, &x->best_mv.as_fullmv, NULL);
/* restore UMV window */
x->mv_limits = tmp_mv_limits;
@@ -350,9 +350,9 @@
}
for (int idx = 0; idx < refmv_count; ++idx) {
- uint32_t thissme = motion_estimation(
- cpi, x, src_mb_buffer, ref_mb, src_stride, ref_stride, bsize, mi_row,
- mi_col, center_mvs[idx].as_mv);
+ uint32_t thissme =
+ motion_estimation(cpi, x, src_mb_buffer, ref_mb, src_stride,
+ ref_stride, bsize, center_mvs[idx].as_mv);
if (thissme < bestsme) {
bestsme = thissme;