diff options
author | Yunqing Wang <yunqingwang@google.com> | 2023-12-06 14:24:07 -0800 |
---|---|---|
committer | Wan-Teh Chang <wtc@google.com> | 2023-12-08 19:29:46 +0000 |
commit | 75d7727f58ddf751b4333a4df94cab1fd920a35c (patch) | |
tree | f45a63865172e154109cc6ee824ee05772bd75bb | |
parent | 36b2dec5eebaffde48e9eee3bd39cee4f6bb6c4b (diff) | |
download | libvpx-75d7727f58ddf751b4333a4df94cab1fd920a35c.tar.gz |
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)
-rw-r--r-- | test/encode_api_test.cc | 31 | ||||
-rw-r--r-- | 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 6b1012f3f..e2374abb4 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<const libvpx_test::CodecFactory *> { diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index d6ac04400..7ff5f00ed 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; |