blob: e9abdde6daa1345ce3ac8f1514b82bc0187feb02 [file] [log] [blame]
Adrian Grangecc017ca2012-10-02 12:16:27 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Frank Galligan38536f62013-12-12 08:36:34 -08003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*/
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080011
Tom Finegan7a07ece2017-02-07 17:14:05 -080012#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
John Koleszar706cafe2013-01-18 11:51:12 -080013#include "test/codec_factory.h"
Adrian Grangecc017ca2012-10-02 12:16:27 -070014#include "test/encode_test_driver.h"
15#include "test/i420_video_source.h"
John Koleszar706cafe2013-01-18 11:51:12 -080016#include "test/util.h"
Adrian Grangecc017ca2012-10-02 12:16:27 -070017
18namespace {
19
Marco Paniconif61b9622014-02-24 18:14:50 -080020const int kMaxErrorFrames = 12;
21const int kMaxDroppableFrames = 12;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080022
clang-format3a826f12016-08-11 17:46:05 -070023class ErrorResilienceTestLarge
Sebastien Alaiwan4322bc12017-06-05 10:18:28 +020024 : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
25 public ::libaom_test::EncoderTest {
Adrian Grangecc017ca2012-10-02 12:16:27 -070026 protected:
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070027 ErrorResilienceTestLarge()
clang-format3a826f12016-08-11 17:46:05 -070028 : EncoderTest(GET_PARAM(0)), psnr_(0.0), nframes_(0), mismatch_psnr_(0.0),
29 mismatch_nframes_(0), encoding_mode_(GET_PARAM(1)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080030 Reset();
31 }
John Koleszar706cafe2013-01-18 11:51:12 -080032
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070033 virtual ~ErrorResilienceTestLarge() {}
Adrian Grangecc017ca2012-10-02 12:16:27 -070034
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080035 void Reset() {
36 error_nframes_ = 0;
37 droppable_nframes_ = 0;
Marco2c6d9c52015-01-11 15:26:44 -080038 pattern_switch_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080039 }
40
Adrian Grangecc017ca2012-10-02 12:16:27 -070041 virtual void SetUp() {
42 InitializeConfig();
43 SetMode(encoding_mode_);
44 }
45
46 virtual void BeginPassHook(unsigned int /*pass*/) {
47 psnr_ = 0.0;
48 nframes_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080049 mismatch_psnr_ = 0.0;
50 mismatch_nframes_ = 0;
Adrian Grangecc017ca2012-10-02 12:16:27 -070051 }
52
Yaowu Xuf883b422016-08-30 14:01:10 -070053 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
Adrian Grangecc017ca2012-10-02 12:16:27 -070054 psnr_ += pkt->data.psnr.psnr[0];
55 nframes_++;
56 }
57
Urvang Joshid71a2312016-07-14 12:33:48 -070058 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video) {
clang-format3a826f12016-08-11 17:46:05 -070059 frame_flags_ &=
Yaowu Xuf883b422016-08-30 14:01:10 -070060 ~(AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF);
James Zerncc73e1f2016-08-08 15:09:30 -070061 if (droppable_nframes_ > 0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -070062 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080063 for (unsigned int i = 0; i < droppable_nframes_; ++i) {
Deb Mukherjee0d8723f2013-08-19 14:16:26 -070064 if (droppable_frames_[i] == video->frame()) {
clang-format3a826f12016-08-11 17:46:05 -070065 std::cout << "Encoding droppable frame: " << droppable_frames_[i]
66 << "\n";
Yaowu Xuf883b422016-08-30 14:01:10 -070067 frame_flags_ |= (AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
68 AOM_EFLAG_NO_UPD_ARF);
James Zerncc73e1f2016-08-08 15:09:30 -070069 return;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080070 }
71 }
72 }
73 }
74
Adrian Grangecc017ca2012-10-02 12:16:27 -070075 double GetAveragePsnr() const {
clang-format3a826f12016-08-11 17:46:05 -070076 if (nframes_) return psnr_ / nframes_;
Adrian Grangecc017ca2012-10-02 12:16:27 -070077 return 0.0;
78 }
79
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080080 double GetAverageMismatchPsnr() const {
clang-format3a826f12016-08-11 17:46:05 -070081 if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080082 return 0.0;
83 }
84
85 virtual bool DoDecode() const {
86 if (error_nframes_ > 0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -070087 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080088 for (unsigned int i = 0; i < error_nframes_; ++i) {
89 if (error_frames_[i] == nframes_ - 1) {
90 std::cout << " Skipping decoding frame: "
91 << error_frames_[i] << "\n";
92 return 0;
93 }
94 }
95 }
96 return 1;
97 }
98
Yaowu Xuf883b422016-08-30 14:01:10 -070099 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800100 double mismatch_psnr = compute_psnr(img1, img2);
101 mismatch_psnr_ += mismatch_psnr;
102 ++mismatch_nframes_;
103 // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
Yaowu Xuc27fc142016-08-22 16:08:15 -0700104 ::libaom_test::EncoderTest::MismatchHook(img1, img2);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800105 }
106
107 void SetErrorFrames(int num, unsigned int *list) {
108 if (num > kMaxErrorFrames)
109 num = kMaxErrorFrames;
110 else if (num < 0)
111 num = 0;
112 error_nframes_ = num;
113 for (unsigned int i = 0; i < error_nframes_; ++i)
114 error_frames_[i] = list[i];
115 }
116
117 void SetDroppableFrames(int num, unsigned int *list) {
118 if (num > kMaxDroppableFrames)
119 num = kMaxDroppableFrames;
120 else if (num < 0)
121 num = 0;
122 droppable_nframes_ = num;
123 for (unsigned int i = 0; i < droppable_nframes_; ++i)
124 droppable_frames_[i] = list[i];
125 }
126
clang-format3a826f12016-08-11 17:46:05 -0700127 unsigned int GetMismatchFrames() { return mismatch_nframes_; }
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800128
clang-format3a826f12016-08-11 17:46:05 -0700129 void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
Marco2c6d9c52015-01-11 15:26:44 -0800130
Adrian Grangecc017ca2012-10-02 12:16:27 -0700131 private:
132 double psnr_;
133 unsigned int nframes_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800134 unsigned int error_nframes_;
135 unsigned int droppable_nframes_;
Marco2c6d9c52015-01-11 15:26:44 -0800136 unsigned int pattern_switch_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800137 double mismatch_psnr_;
138 unsigned int mismatch_nframes_;
139 unsigned int error_frames_[kMaxErrorFrames];
140 unsigned int droppable_frames_[kMaxDroppableFrames];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700141 libaom_test::TestMode encoding_mode_;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700142};
143
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700144TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700145 const aom_rational timebase = { 33333333, 1000000000 };
Adrian Grangecc017ca2012-10-02 12:16:27 -0700146 cfg_.g_timebase = timebase;
147 cfg_.rc_target_bitrate = 2000;
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700148 cfg_.g_lag_in_frames = 10;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700149
Yaowu Xuf883b422016-08-30 14:01:10 -0700150 init_flags_ = AOM_CODEC_USE_PSNR;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700151
Yaowu Xuc27fc142016-08-22 16:08:15 -0700152 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
Yaowu Xu2e7da0a2017-05-08 15:30:08 -0700153 timebase.den, timebase.num, 0, 12);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700154
155 // Error resilient mode OFF.
156 cfg_.g_error_resilient = 0;
157 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
158 const double psnr_resilience_off = GetAveragePsnr();
159 EXPECT_GT(psnr_resilience_off, 25.0);
160
161 // Error resilient mode ON.
162 cfg_.g_error_resilient = 1;
163 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
164 const double psnr_resilience_on = GetAveragePsnr();
165 EXPECT_GT(psnr_resilience_on, 25.0);
166
167 // Test that turning on error resilient mode hurts by 10% at most.
168 if (psnr_resilience_off > 0.0) {
169 const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
170 EXPECT_GE(psnr_ratio, 0.9);
171 EXPECT_LE(psnr_ratio, 1.1);
172 }
173}
174
Marco Paniconif61b9622014-02-24 18:14:50 -0800175// Check for successful decoding and no encoder/decoder mismatch
176// if we lose (i.e., drop before decoding) a set of droppable
177// frames (i.e., frames that don't update any reference buffers).
178// Check both isolated and consecutive loss.
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700179TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700180 const aom_rational timebase = { 33333333, 1000000000 };
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800181 cfg_.g_timebase = timebase;
John Koleszarc0490a52013-05-07 12:58:32 -0700182 cfg_.rc_target_bitrate = 500;
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700183 // FIXME(debargha): Fix this to work for any lag.
184 // Currently this test only works for lag = 0
185 cfg_.g_lag_in_frames = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800186
Yaowu Xuf883b422016-08-30 14:01:10 -0700187 init_flags_ = AOM_CODEC_USE_PSNR;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800188
Yaowu Xuc27fc142016-08-22 16:08:15 -0700189 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
Yaowu Xu2e7da0a2017-05-08 15:30:08 -0700190 timebase.den, timebase.num, 0, 20);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800191
192 // Error resilient mode ON.
193 cfg_.g_error_resilient = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700194 cfg_.kf_mode = AOM_KF_DISABLED;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800195
Marco Paniconif61b9622014-02-24 18:14:50 -0800196 // Set an arbitrary set of error frames same as droppable frames.
197 // In addition to isolated loss/drop, add a long consecutive series
198 // (of size 9) of dropped frames.
Yaowu Xu2e7da0a2017-05-08 15:30:08 -0700199 unsigned int num_droppable_frames = 5;
200 unsigned int droppable_frame_list[] = { 5, 10, 13, 16, 19 };
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800201 SetDroppableFrames(num_droppable_frames, droppable_frame_list);
202 SetErrorFrames(num_droppable_frames, droppable_frame_list);
203 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
204 // Test that no mismatches have been found
clang-format3a826f12016-08-11 17:46:05 -0700205 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
206 EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800207
Marco Paniconif61b9622014-02-24 18:14:50 -0800208 // Reset previously set of error/droppable frames.
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800209 Reset();
210
John Koleszar9fba0342013-05-07 13:02:45 -0700211#if 0
212 // TODO(jkoleszar): This test is disabled for the time being as too
213 // sensitive. It's not clear how to set a reasonable threshold for
214 // this behavior.
215
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800216 // Now set an arbitrary set of error frames that are non-droppable
217 unsigned int num_error_frames = 3;
218 unsigned int error_frame_list[] = {3, 10, 20};
219 SetErrorFrames(num_error_frames, error_frame_list);
220 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
John Koleszar9fba0342013-05-07 13:02:45 -0700221
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800222 // Test that dropping an arbitrary set of inter frames does not hurt too much
223 // Note the Average Mismatch PSNR is the average of the PSNR between
224 // decoded frame and encoder's version of the same frame for all frames
225 // with mismatch.
226 const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
227 std::cout << " Mismatch PSNR: "
228 << psnr_resilience_mismatch << "\n";
229 EXPECT_GT(psnr_resilience_mismatch, 20.0);
John Koleszar9fba0342013-05-07 13:02:45 -0700230#endif
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800231}
232
Yaowu Xuf883b422016-08-30 14:01:10 -0700233AV1_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700234} // namespace