Unify mv_limits setting in encoder
Unified mv_limits setting in temporal filter and TPL, making it
consistent with mv_limits in encoding stage.
Speed 1 borg test result:
avg_psnr: ovr_psnr: ssim: speed change:
lowres: -0.003 -0.004 0.030 0%
midres: -0.035 -0.022 -0.040 0.2%
hdres: -0.027 -0.028 -0.009 0%
Minor impact on quality and speed.
STATS_CHANGED
Change-Id: I1b0d6d2dde8e1054964805b6317f8272d8281997
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index 4a38a36..9d4f372 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -104,16 +104,36 @@
// Set up limit values for MV components.
// Mv beyond the range do not produce new/different prediction block.
+static INLINE void av1_set_mv_row_limits(const AV1_COMMON *const cm,
+ FullMvLimits *mv_limits, int mi_row,
+ int mi_height, int border) {
+ const int min1 = -(mi_row * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
+ const int min2 = -(((mi_row + mi_height) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
+ mv_limits->row_min = AOMMAX(min1, min2);
+ const int max1 = (cm->mi_rows - mi_row - mi_height) * MI_SIZE + border -
+ 2 * AOM_INTERP_EXTEND;
+ const int max2 = (cm->mi_rows - mi_row) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
+ mv_limits->row_max = AOMMIN(max1, max2);
+}
+
+static INLINE void av1_set_mv_col_limits(const AV1_COMMON *const cm,
+ FullMvLimits *mv_limits, int mi_col,
+ int mi_width, int border) {
+ const int min1 = -(mi_col * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
+ const int min2 = -(((mi_col + mi_width) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
+ mv_limits->col_min = AOMMAX(min1, min2);
+ const int max1 = (cm->mi_cols - mi_col - mi_width) * MI_SIZE + border -
+ 2 * AOM_INTERP_EXTEND;
+ const int max2 = (cm->mi_cols - mi_col) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
+ mv_limits->col_max = AOMMIN(max1, max2);
+}
+
static INLINE void av1_set_mv_limits(const AV1_COMMON *const cm,
FullMvLimits *mv_limits, int mi_row,
int mi_col, int mi_height, int mi_width,
int border) {
- mv_limits->row_min = -(mi_row * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
- mv_limits->col_min = -(mi_col * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
- mv_limits->row_max = (cm->mi_rows - mi_row - mi_height) * MI_SIZE + border -
- 2 * AOM_INTERP_EXTEND;
- mv_limits->col_max = (cm->mi_cols - mi_col - mi_width) * MI_SIZE + border -
- 2 * AOM_INTERP_EXTEND;
+ av1_set_mv_row_limits(cm, mv_limits, mi_row, mi_height, border);
+ av1_set_mv_col_limits(cm, mv_limits, mi_col, mi_width, border);
}
void av1_set_mv_search_range(FullMvLimits *mv_limits, const MV *mv);
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 3b9648e..e4e53ec 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -881,29 +881,6 @@
return (frame_length + mb_length - 1) / mb_length;
}
-// Helper function to get motion search range, or say limit of motion vector, on
-// either side of the frame.
-// TODO(chengchen): Figure out how this function works.
-// Previous comments: """
-// Source frames are extended to 16 pixels. This is different than
-// L/A/G reference frames that have a border of 32 (AV1ENCBORDERINPIXELS)
-// A 6/8 tap filter is used for motion search. This requires 2 pixels
-// before and 3 pixels after. So the largest Y mv on a border would
-// then be 16 - AOM_INTERP_EXTEND. The UV blocks are half the size of the
-// Y and therefore only extended by 8. The largest mv that a UV block
-// can support is 8 - AOM_INTERP_EXTEND. A UV mv is half of a Y mv.
-// (16 - AOM_INTERP_EXTEND) >> 1 which is greater than
-// 8 - AOM_INTERP_EXTEND.
-// To keep the mv in play for both Y and UV planes the max that it
-// can be on a border is therefore 16 - (2*AOM_INTERP_EXTEND+1).
-// """
-static INLINE int get_min_mv(const int block_idx, const int mb_length) {
- return -((block_idx * mb_length) + (17 - 2 * AOM_INTERP_EXTEND));
-}
-static INLINE int get_max_mv(const int block_reverse_idx, const int mb_length) {
- return (block_reverse_idx * mb_length) + (17 - 2 * AOM_INTERP_EXTEND);
-}
-
typedef struct {
int64_t sum;
int64_t sse;
@@ -940,6 +917,8 @@
const int mb_rows = get_num_blocks(frame_height, mb_height);
const int mb_cols = get_num_blocks(frame_width, mb_width);
const int num_planes = av1_num_planes(&cpi->common);
+ const int mi_h = mi_size_high_log2[block_size];
+ const int mi_w = mi_size_wide_log2[block_size];
assert(num_planes >= 1 && num_planes <= MAX_MB_PLANE);
const int is_high_bitdepth = is_frame_high_bitdepth(frame_to_filter);
@@ -975,11 +954,13 @@
TF_ENABLE_PLANEWISE_STRATEGY && AOMMIN(frame_height, frame_width) >= 480;
// Perform temporal filtering block by block.
for (int mb_row = 0; mb_row < mb_rows; mb_row++) {
- mb->mv_limits.row_min = get_min_mv(mb_row, mb_height);
- mb->mv_limits.row_max = get_max_mv(mb_rows - 1 - mb_row, mb_height);
+ av1_set_mv_row_limits(&cpi->common, &mb->mv_limits, (mb_row << mi_h),
+ (mb_height >> MI_SIZE_LOG2),
+ cpi->oxcf.border_in_pixels);
for (int mb_col = 0; mb_col < mb_cols; mb_col++) {
- mb->mv_limits.col_min = get_min_mv(mb_col, mb_width);
- mb->mv_limits.col_max = get_max_mv(mb_cols - 1 - mb_col, mb_width);
+ av1_set_mv_col_limits(&cpi->common, &mb->mv_limits, (mb_col << mi_w),
+ (mb_width >> MI_SIZE_LOG2),
+ cpi->oxcf.border_in_pixels);
memset(accum, 0, num_planes * mb_pels * sizeof(accum[0]));
memset(count, 0, num_planes * mb_pels * sizeof(count[0]));
MV ref_mv = kZeroMv; // Reference motion vector passed down along frames.
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index f306c9f..3c244f7 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -758,9 +758,8 @@
for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
// Motion estimation row boundary
- x->mv_limits.row_min = -((mi_row * MI_SIZE) + (17 - 2 * AOM_INTERP_EXTEND));
- x->mv_limits.row_max = (cm->mi_rows - mi_height - mi_row) * MI_SIZE +
- (17 - 2 * AOM_INTERP_EXTEND);
+ av1_set_mv_row_limits(cm, &x->mv_limits, mi_row, mi_height,
+ cpi->oxcf.border_in_pixels);
xd->mb_to_top_edge = -GET_MV_SUBPEL(mi_row * MI_SIZE);
xd->mb_to_bottom_edge =
GET_MV_SUBPEL((cm->mi_rows - mi_height - mi_row) * MI_SIZE);
@@ -768,10 +767,8 @@
TplDepStats tpl_stats;
// Motion estimation column boundary
- x->mv_limits.col_min =
- -((mi_col * MI_SIZE) + (17 - 2 * AOM_INTERP_EXTEND));
- x->mv_limits.col_max = ((cm->mi_cols - mi_width - mi_col) * MI_SIZE) +
- (17 - 2 * AOM_INTERP_EXTEND);
+ av1_set_mv_col_limits(cm, &x->mv_limits, mi_col, mi_width,
+ cpi->oxcf.border_in_pixels);
xd->mb_to_left_edge = -GET_MV_SUBPEL(mi_col * MI_SIZE);
xd->mb_to_right_edge = GET_MV_SUBPEL(cm->mi_cols - mi_width - mi_col);
mode_estimation(cpi, x, xd, &sf, frame_idx, mi_row, mi_col, bsize,