Commit 8986ad6a7f for aom
commit 8986ad6a7f776c6451f60558b1fae65e1c6b3019
Author: Marco Paniconi <marpan@google.com>
Date: Tue Apr 14 20:21:00 2026 -0700
rtc: Allow for scroll sb detection for non-screen
For resoln > 720p non-screen mode, allow for
superblock motion estimation that can capture scroll.
Reduces encode size spikes for scroll video content in
the issue below.
Bug: 500972837
Change-Id: I65f9f5f5907e0c064b1808dd438dff25780c4ddf
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 85df081bb1..9ccb2da051 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -2141,7 +2141,8 @@ int av1_vector_match(const int16_t *ref, const int16_t *src, int bwl,
unsigned int av1_int_pro_motion_estimation(
const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
int mi_col, const MV *ref_mv, unsigned int *y_sad_zero,
- int me_search_size_col, int me_search_size_row, int is_var_part) {
+ int me_search_size_col, int me_search_size_row, int is_var_part,
+ int use_larger_search) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mi = xd->mi[0];
@@ -2151,8 +2152,8 @@ unsigned int av1_int_pro_motion_estimation(
const int bh = block_size_high[bsize];
const int is_screen = cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN;
const int full_search = is_screen;
- const bool screen_scroll_superblock =
- is_screen && bsize == cm->seq_params->sb_size;
+ const bool scroll_superblock =
+ use_larger_search && bsize == cm->seq_params->sb_size;
// Keep border a multiple of 16.
const int border = (cpi->oxcf.border_in_pixels >> 4) << 4;
int search_size_width_left = me_search_size_col;
@@ -2160,7 +2161,7 @@ unsigned int av1_int_pro_motion_estimation(
int search_size_height_top = me_search_size_row;
int search_size_height_bottom = me_search_size_row;
// Allow for larger search size for column/horizontal screen motion.
- if (screen_scroll_superblock && is_var_part) {
+ if (scroll_superblock && is_var_part) {
if (((mi_col << 2) - search_size_width_left) < -border)
search_size_width_left = (mi_col << 2) + border;
if (((mi_col << 2) + search_size_width_right + bw) > cm->width + border)
@@ -2174,7 +2175,7 @@ unsigned int av1_int_pro_motion_estimation(
}
}
// Allow for larger search size for row/vertical screen motion.
- if (screen_scroll_superblock && is_var_part) {
+ if (scroll_superblock && is_var_part) {
if (((mi_row << 2) - search_size_height_top) < -border)
search_size_height_top = (mi_row << 2) + border;
if (((mi_row << 2) + search_size_height_bottom + bh) > cm->height + border)
@@ -2285,6 +2286,16 @@ unsigned int av1_int_pro_motion_estimation(
best_sad =
cpi->ppi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);
+ if (!is_screen && scroll_superblock) {
+ if (best_sad_col < best_sad_row && best_sad_col < (int)best_sad) {
+ best_int_mv->as_fullmv.row = 0;
+ best_sad = best_sad_col;
+ } else if (best_sad_row < best_sad_col && best_sad_row < (int)best_sad) {
+ best_int_mv->as_fullmv.col = 0;
+ best_sad = best_sad_row;
+ }
+ }
+
// Evaluate zero MV if found MV is non-zero.
if (best_int_mv->as_int != 0) {
tmp_sad = cpi->ppi->fn_ptr[bsize].sdf(x->plane[0].src.buf, src_stride,
@@ -2300,7 +2311,7 @@ unsigned int av1_int_pro_motion_estimation(
*y_sad_zero = best_sad;
}
- if (!screen_scroll_superblock) {
+ if (!scroll_superblock) {
const uint8_t *const pos[4] = {
ref_buf - ref_stride,
ref_buf - 1,
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index d268481167..eb70c29d0e 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -246,7 +246,8 @@ int av1_vector_match(const int16_t *ref, const int16_t *src, int bwl,
unsigned int av1_int_pro_motion_estimation(
const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
int mi_col, const MV *ref_mv, unsigned int *y_sad_zero,
- int me_search_size_col, int me_search_size_row, int is_var_part);
+ int me_search_size_col, int me_search_size_row, int is_var_part,
+ int use_larger_search);
int av1_refining_search_8p_c(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
const FULLPEL_MV start_mv, FULLPEL_MV *best_mv);
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 49953d0c3e..6f6dc889c4 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -331,7 +331,7 @@ static int search_new_mv(AV1_COMP *cpi, MACROBLOCK *x,
MV ref_mv = av1_get_ref_mv(x, 0).as_mv;
tmp_sad = av1_int_pro_motion_estimation(
cpi, x, bsize, mi_row, mi_col, &ref_mv, &y_sad_zero, me_search_size_col,
- me_search_size_row, 0);
+ me_search_size_row, 0, 0);
if (tmp_sad > x->pred_mv_sad[LAST_FRAME]) return -1;
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index b0c1a5bd89..ea2053fa43 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -1339,16 +1339,21 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x,
AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mi = xd->mi[0];
- const int is_screen = cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN;
+ const int large_search =
+ cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN ||
+ (source_sad_nonrd > kMedSad && cm->width * cm->height > 1280 * 720 &&
+ !cpi->rc.high_motion_content_screen_rtc);
+ const int max_sw =
+ (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) ? 512 : 256;
const int increase_col_sw =
source_sad_nonrd > kMedSad && !cpi->rc.high_motion_content_screen_rtc;
- int me_search_size_col = is_screen
- ? increase_col_sw ? 512 : 96
+ int me_search_size_col = large_search
+ ? increase_col_sw ? max_sw : 96
: block_size_wide[cm->seq_params->sb_size] >> 1;
- // For screen use larger search size row motion to capture
+ // Use larger search size row motion to capture
// vertical scroll, which can be larger motion.
- int me_search_size_row = is_screen
- ? source_sad_nonrd > kMedSad ? 512 : 192
+ int me_search_size_row = large_search
+ ? source_sad_nonrd > kMedSad ? max_sw : 192
: block_size_high[cm->seq_params->sb_size] >> 1;
if (cm->width * cm->height >= 3840 * 2160) {
me_search_size_row = me_search_size_row << 1;
@@ -1357,11 +1362,10 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x,
unsigned int y_sad_zero;
*y_sad = av1_int_pro_motion_estimation(
cpi, x, cm->seq_params->sb_size, mi_row, mi_col, &kZeroMv, &y_sad_zero,
- me_search_size_col, me_search_size_row, 1);
+ me_search_size_col, me_search_size_row, 1, large_search);
// The logic below selects whether the motion estimated in the
- // int_pro_motion() will be used in nonrd_pickmode. Only do this
- // for screen for now.
- if (is_screen) {
+ // int_pro_motion() will be used in nonrd_pickmode.
+ if (large_search) {
unsigned int thresh_sad =
(cm->seq_params->sb_size == BLOCK_128X128) ? 50000 : 20000;
if (*y_sad < (y_sad_zero >> 1) && *y_sad < thresh_sad) {