From 99284cb118c96048337ee32235fba4276d269d17 Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Thu, 9 Jan 2020 10:50:43 -0800 Subject: [PATCH] Fix test failure with --size-limit The test didn't verify expected error code with invalid sizes. It assumed VPX_CODEC_OK. Added new Encoder class which doesn't run decoding at all. It accepts expected error code to verify with encoder output. The encoder behavior was changed in 94a65e8. BUG=webm:1670 Change-Id: I6324d8f744e6c4aa82aa66913923dc140b07bfc9 --- test/frame_size_tests.cc | 133 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 6 deletions(-) diff --git a/test/frame_size_tests.cc b/test/frame_size_tests.cc index f66972b..9397af2 100644 --- a/test/frame_size_tests.cc +++ b/test/frame_size_tests.cc @@ -7,12 +7,73 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ +#include + #include "third_party/googletest/src/include/gtest/gtest.h" #include "test/codec_factory.h" +#include "test/register_state_check.h" #include "test/video_source.h" namespace { +class EncoderWithExpectedError : public ::libvpx_test::Encoder { + public: + EncoderWithExpectedError(vpx_codec_enc_cfg_t cfg, + unsigned long deadline, // NOLINT + const unsigned long init_flags, // NOLINT + ::libvpx_test::TwopassStatsStore *stats) + : ::libvpx_test::Encoder(cfg, deadline, init_flags, stats) {} + // This overrides with expected error code. + void EncodeFrame(::libvpx_test::VideoSource *video, + const unsigned long frame_flags, // NOLINT + const vpx_codec_err_t expected_err) { + if (video->img()) { + EncodeFrameInternal(*video, frame_flags, expected_err); + } else { + Flush(); + } + + // Handle twopass stats + ::libvpx_test::CxDataIterator iter = GetCxData(); + + while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { + if (pkt->kind != VPX_CODEC_STATS_PKT) continue; + + stats_->Append(*pkt); + } + } + + protected: + void EncodeFrameInternal(const ::libvpx_test::VideoSource &video, + const unsigned long frame_flags, // NOLINT + const vpx_codec_err_t expected_err) { + vpx_codec_err_t res; + const vpx_image_t *img = video.img(); + + // Handle frame resizing + if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) { + cfg_.g_w = img->d_w; + cfg_.g_h = img->d_h; + res = vpx_codec_enc_config_set(&encoder_, &cfg_); + ASSERT_EQ(res, VPX_CODEC_OK) << EncoderError(); + } + + // Encode the frame + API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(), + video.duration(), + frame_flags, deadline_)); + ASSERT_EQ(expected_err, res) << EncoderError(); + } + + virtual vpx_codec_iface_t *CodecInterface() const { +#if CONFIG_VP9_ENCODER + return &vpx_codec_vp9_cx_algo; +#else + return NULL; +#endif + } +}; + class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest, public ::testing::Test { protected: @@ -43,7 +104,67 @@ class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest, } } - int expected_res_; + using ::libvpx_test::EncoderTest::RunLoop; + virtual void RunLoop(::libvpx_test::VideoSource *video, + const vpx_codec_err_t expected_err) { + stats_.Reset(); + + ASSERT_TRUE(passes_ == 1 || passes_ == 2); + for (unsigned int pass = 0; pass < passes_; pass++) { + last_pts_ = 0; + + if (passes_ == 1) { + cfg_.g_pass = VPX_RC_ONE_PASS; + } else if (pass == 0) { + cfg_.g_pass = VPX_RC_FIRST_PASS; + } else { + cfg_.g_pass = VPX_RC_LAST_PASS; + } + + BeginPassHook(pass); + std::unique_ptr encoder( + new EncoderWithExpectedError(cfg_, deadline_, init_flags_, &stats_)); + ASSERT_NE(encoder.get(), nullptr); + + ASSERT_NO_FATAL_FAILURE(video->Begin()); + encoder->InitEncoder(video); + ASSERT_FALSE(::testing::Test::HasFatalFailure()); + for (bool again = true; again; video->Next()) { + again = (video->img() != NULL); + + PreEncodeFrameHook(video, encoder.get()); + encoder->EncodeFrame(video, frame_flags_, expected_err); + + PostEncodeFrameHook(encoder.get()); + + ::libvpx_test::CxDataIterator iter = encoder->GetCxData(); + + while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { + pkt = MutateEncoderOutputHook(pkt); + again = true; + switch (pkt->kind) { + case VPX_CODEC_CX_FRAME_PKT: + ASSERT_GE(pkt->data.frame.pts, last_pts_); + last_pts_ = pkt->data.frame.pts; + FramePktHook(pkt); + break; + + case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break; + case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break; + default: break; + } + } + + if (!Continue()) break; + } + + EndPassHook(); + + if (!Continue()) break; + } + } + + vpx_codec_err_t expected_res_; }; TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) { @@ -52,8 +173,8 @@ TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) { #if CONFIG_SIZE_LIMIT video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16); video.set_limit(2); - expected_res_ = VPX_CODEC_CORRUPT_FRAME; - ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + expected_res_ = VPX_CODEC_MEM_ERROR; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video, expected_res_)); #endif } @@ -64,7 +185,7 @@ TEST_F(VP9FrameSizeTestsLarge, ValidSizes) { video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT); video.set_limit(2); expected_res_ = VPX_CODEC_OK; - ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video)); #else // This test produces a pretty large single frame allocation, (roughly // 25 megabits). The encoder allocates a good number of these frames @@ -80,7 +201,7 @@ TEST_F(VP9FrameSizeTestsLarge, ValidSizes) { #endif video.set_limit(2); expected_res_ = VPX_CODEC_OK; - ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video)); #endif } @@ -90,6 +211,6 @@ TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) { video.SetSize(1, 1); video.set_limit(2); expected_res_ = VPX_CODEC_OK; - ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video)); } } // namespace -- 2.7.4