From 75d7727f58ddf751b4333a4df94cab1fd920a35c Mon Sep 17 00:00:00 2001 From: Yunqing Wang Date: Wed, 6 Dec 2023 14:24:07 -0800 Subject: [PATCH] Fix a bug in simple motion search This change fixed a bug revealed by b/311294795. In simple motion search, the reference buffer pointer needs to be restored after the search. Otherwise, it causes problems while the reference frame scaling happens. This CL fixes the bug. Bug: b/311294795 Change-Id: I093722d5888de3cc6a6542de82a6ec9d601f897d (cherry picked from commit 50ed636e49db2b8fa2436413480f11ab1f2a2d1a) --- test/encode_api_test.cc | 31 +++++++++++++++++++++++++++++++ vp9/encoder/vp9_encodeframe.c | 15 +++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc index 6b1012f..e2374ab 100644 --- a/test/encode_api_test.cc +++ b/test/encode_api_test.cc @@ -863,6 +863,37 @@ TEST(EncodeAPI, Buganizer312875957PredBufferStride) { encoder.Encode(false); } +// This is a test case from clusterfuzz: based on b/311294795 +// Encode a few frames with multiple change config calls +// with different frame sizes. +TEST(EncodeAPI, Buganizer311294795) { + VP9Encoder encoder(1); + + // Set initial config. + encoder.Configure(12, 1678, 620, VPX_VBR, VPX_DL_REALTIME); + + // Encode first frame. + encoder.Encode(false); + + // Change config. + encoder.Configure(16, 632, 620, VPX_VBR, VPX_DL_GOOD_QUALITY); + + // Encode 2nd frame with new config + encoder.Encode(true); + + // Change config. + encoder.Configure(16, 1678, 342, VPX_VBR, VPX_DL_GOOD_QUALITY); + + // Encode 3rd frame with new config. + encoder.Encode(false); + + // Change config. + encoder.Configure(0, 1574, 618, VPX_VBR, VPX_DL_REALTIME); + // Encode more frames with new config. + encoder.Encode(false); + encoder.Encode(false); +} + class EncodeApiGetTplStatsTest : public ::libvpx_test::EncoderTest, public ::testing::TestWithParam { diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index d6ac044..7ff5f00 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -3443,11 +3443,17 @@ static void simple_motion_search(const VP9_COMP *const cpi, MACROBLOCK *const x, MV ref_mv_full = { ref_mv.row >> 3, ref_mv.col >> 3 }; MV best_mv = { 0, 0 }; int cost_list[5]; + struct buf_2d backup_pre[MAX_MB_PLANE] = { { 0, 0 } }; - if (scaled_ref_frame) + if (scaled_ref_frame) { yv12 = scaled_ref_frame; - else + // As reported in b/311294795, the reference buffer pointer needs to be + // saved and restored after the search. Otherwise, it causes problems while + // the reference frame scaling happens. + for (int i = 0; i < MAX_MB_PLANE; i++) backup_pre[i] = xd->plane[i].pre[0]; + } else { yv12 = get_ref_frame_buffer(cpi, ref); + } assert(yv12 != NULL); if (!yv12) return; @@ -3464,6 +3470,11 @@ static void simple_motion_search(const VP9_COMP *const cpi, MACROBLOCK *const x, x->mv_limits = tmp_mv_limits; mi->mv[0].as_mv = best_mv; + // Restore reference buffer pointer. + if (scaled_ref_frame) { + for (int i = 0; i < MAX_MB_PLANE; i++) xd->plane[i].pre[0] = backup_pre[i]; + } + set_ref_ptrs(cm, xd, mi->ref_frame[0], mi->ref_frame[1]); xd->plane[0].dst.buf = pred_buf; xd->plane[0].dst.stride = 64; -- 2.7.4