aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYunqing Wang <yunqingwang@google.com>2023-12-06 14:24:07 -0800
committerWan-Teh Chang <wtc@google.com>2023-12-08 19:29:46 +0000
commit75d7727f58ddf751b4333a4df94cab1fd920a35c (patch)
treef45a63865172e154109cc6ee824ee05772bd75bb
parent36b2dec5eebaffde48e9eee3bd39cee4f6bb6c4b (diff)
downloadlibvpx-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.cc31
-rw-r--r--vp9/encoder/vp9_encodeframe.c15
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;