blob: 76322fc5f18b069362b21a11c4bc20bed7b6f219 [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.
Johann123e8a62017-12-28 14:40:49 -080010 */
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;
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -070022const int kMaxErrorResilientFrames = 12;
Debargha Mukherjee93b047e2018-03-29 11:27:42 -070023const int kMaxNoMFMVFrames = 12;
Debargha Mukherjee776b6412018-03-23 17:25:06 -070024const int kCpuUsed = 1;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080025
clang-format3a826f12016-08-11 17:46:05 -070026class ErrorResilienceTestLarge
Sebastien Alaiwan4322bc12017-06-05 10:18:28 +020027 : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
28 public ::libaom_test::EncoderTest {
Adrian Grangecc017ca2012-10-02 12:16:27 -070029 protected:
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070030 ErrorResilienceTestLarge()
clang-format3a826f12016-08-11 17:46:05 -070031 : EncoderTest(GET_PARAM(0)), psnr_(0.0), nframes_(0), mismatch_psnr_(0.0),
Debargha Mukherjee5729d172018-03-29 12:31:21 -070032 mismatch_nframes_(0), encoding_mode_(GET_PARAM(1)), allow_mismatch_(0) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080033 Reset();
34 }
John Koleszar706cafe2013-01-18 11:51:12 -080035
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070036 virtual ~ErrorResilienceTestLarge() {}
Adrian Grangecc017ca2012-10-02 12:16:27 -070037
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080038 void Reset() {
39 error_nframes_ = 0;
40 droppable_nframes_ = 0;
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -070041 error_resilient_nframes_ = 0;
Debargha Mukherjee93b047e2018-03-29 11:27:42 -070042 nomfmv_nframes_ = 0;
Marco2c6d9c52015-01-11 15:26:44 -080043 pattern_switch_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080044 }
45
Adrian Grangecc017ca2012-10-02 12:16:27 -070046 virtual void SetUp() {
47 InitializeConfig();
48 SetMode(encoding_mode_);
49 }
50
51 virtual void BeginPassHook(unsigned int /*pass*/) {
52 psnr_ = 0.0;
53 nframes_ = 0;
Debargha Mukherjee776b6412018-03-23 17:25:06 -070054 decoded_nframes_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080055 mismatch_psnr_ = 0.0;
56 mismatch_nframes_ = 0;
Adrian Grangecc017ca2012-10-02 12:16:27 -070057 }
58
Yaowu Xuf883b422016-08-30 14:01:10 -070059 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
Adrian Grangecc017ca2012-10-02 12:16:27 -070060 psnr_ += pkt->data.psnr.psnr[0];
61 nframes_++;
62 }
63
Debargha Mukherjee776b6412018-03-23 17:25:06 -070064 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
65 libaom_test::Encoder *encoder) {
66 if (video->frame() == 0) encoder->Control(AOME_SET_CPUUSED, kCpuUsed);
James Zerncc73e1f2016-08-08 15:09:30 -070067 if (droppable_nframes_ > 0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -070068 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080069 for (unsigned int i = 0; i < droppable_nframes_; ++i) {
Deb Mukherjee0d8723f2013-08-19 14:16:26 -070070 if (droppable_frames_[i] == video->frame()) {
Debargha Mukherjee776b6412018-03-23 17:25:06 -070071 std::cout << " Encoding droppable frame: "
72 << droppable_frames_[i] << "\n";
Yaowu Xuf883b422016-08-30 14:01:10 -070073 frame_flags_ |= (AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
74 AOM_EFLAG_NO_UPD_ARF);
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -070075 break;
76 }
77 }
78 }
79 encoder->Control(AV1E_SET_ERROR_RESILIENT_MODE, 0);
80 if (error_resilient_nframes_ > 0 &&
81 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
82 for (unsigned int i = 0; i < error_resilient_nframes_; ++i) {
83 if (error_resilient_frames_[i] == video->frame()) {
84 std::cout << " Encoding error_resilient frame: "
85 << error_resilient_frames_[i] << "\n";
86 encoder->Control(AV1E_SET_ERROR_RESILIENT_MODE, 1);
87 break;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080088 }
89 }
90 }
Debargha Mukherjee93b047e2018-03-29 11:27:42 -070091 encoder->Control(AV1E_SET_ALLOW_REF_FRAME_MVS, 1);
92 if (nomfmv_nframes_ > 0 &&
93 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
94 for (unsigned int i = 0; i < nomfmv_nframes_; ++i) {
95 if (nomfmv_frames_[i] == video->frame()) {
96 std::cout << " Encoding no mfmv frame: "
97 << nomfmv_frames_[i] << "\n";
98 encoder->Control(AV1E_SET_ALLOW_REF_FRAME_MVS, 0);
99 break;
100 }
101 }
102 }
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800103 }
104
Adrian Grangecc017ca2012-10-02 12:16:27 -0700105 double GetAveragePsnr() const {
clang-format3a826f12016-08-11 17:46:05 -0700106 if (nframes_) return psnr_ / nframes_;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700107 return 0.0;
108 }
109
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800110 double GetAverageMismatchPsnr() const {
clang-format3a826f12016-08-11 17:46:05 -0700111 if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800112 return 0.0;
113 }
114
115 virtual bool DoDecode() const {
116 if (error_nframes_ > 0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -0700117 (cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800118 for (unsigned int i = 0; i < error_nframes_; ++i) {
119 if (error_frames_[i] == nframes_ - 1) {
120 std::cout << " Skipping decoding frame: "
121 << error_frames_[i] << "\n";
122 return 0;
123 }
124 }
125 }
126 return 1;
127 }
128
Yaowu Xuf883b422016-08-30 14:01:10 -0700129 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) {
Debargha Mukherjee5729d172018-03-29 12:31:21 -0700130 if (allow_mismatch_) {
131 double mismatch_psnr = compute_psnr(img1, img2);
132 mismatch_psnr_ += mismatch_psnr;
133 ++mismatch_nframes_;
134 // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
135 } else {
136 ::libaom_test::EncoderTest::MismatchHook(img1, img2);
137 }
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800138 }
139
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700140 virtual void DecompressedFrameHook(const aom_image_t &img,
141 aom_codec_pts_t pts) {
142 (void)img;
143 (void)pts;
144 ++decoded_nframes_;
145 }
146
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800147 void SetErrorFrames(int num, unsigned int *list) {
148 if (num > kMaxErrorFrames)
149 num = kMaxErrorFrames;
150 else if (num < 0)
151 num = 0;
152 error_nframes_ = num;
153 for (unsigned int i = 0; i < error_nframes_; ++i)
154 error_frames_[i] = list[i];
155 }
156
157 void SetDroppableFrames(int num, unsigned int *list) {
158 if (num > kMaxDroppableFrames)
159 num = kMaxDroppableFrames;
160 else if (num < 0)
161 num = 0;
162 droppable_nframes_ = num;
163 for (unsigned int i = 0; i < droppable_nframes_; ++i)
164 droppable_frames_[i] = list[i];
165 }
166
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -0700167 void SetErrorResilientFrames(int num, unsigned int *list) {
168 if (num > kMaxErrorResilientFrames)
169 num = kMaxErrorResilientFrames;
170 else if (num < 0)
171 num = 0;
172 error_resilient_nframes_ = num;
173 for (unsigned int i = 0; i < error_resilient_nframes_; ++i)
174 error_resilient_frames_[i] = list[i];
175 }
176
Debargha Mukherjee93b047e2018-03-29 11:27:42 -0700177 void SetNoMFMVFrames(int num, unsigned int *list) {
178 if (num > kMaxNoMFMVFrames)
179 num = kMaxNoMFMVFrames;
180 else if (num < 0)
181 num = 0;
182 nomfmv_nframes_ = num;
183 for (unsigned int i = 0; i < nomfmv_nframes_; ++i)
184 nomfmv_frames_[i] = list[i];
185 }
186
clang-format3a826f12016-08-11 17:46:05 -0700187 unsigned int GetMismatchFrames() { return mismatch_nframes_; }
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700188 unsigned int GetEncodedFrames() { return nframes_; }
189 unsigned int GetDecodedFrames() { return decoded_nframes_; }
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800190
Debargha Mukherjee5729d172018-03-29 12:31:21 -0700191 void SetAllowMismatch(int allow) { allow_mismatch_ = allow; }
clang-format3a826f12016-08-11 17:46:05 -0700192 void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
Marco2c6d9c52015-01-11 15:26:44 -0800193
Adrian Grangecc017ca2012-10-02 12:16:27 -0700194 private:
195 double psnr_;
196 unsigned int nframes_;
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700197 unsigned int decoded_nframes_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800198 unsigned int error_nframes_;
199 unsigned int droppable_nframes_;
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -0700200 unsigned int error_resilient_nframes_;
Debargha Mukherjee93b047e2018-03-29 11:27:42 -0700201 unsigned int nomfmv_nframes_;
Marco2c6d9c52015-01-11 15:26:44 -0800202 unsigned int pattern_switch_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800203 double mismatch_psnr_;
204 unsigned int mismatch_nframes_;
205 unsigned int error_frames_[kMaxErrorFrames];
206 unsigned int droppable_frames_[kMaxDroppableFrames];
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -0700207 unsigned int error_resilient_frames_[kMaxErrorResilientFrames];
Debargha Mukherjee93b047e2018-03-29 11:27:42 -0700208 unsigned int nomfmv_frames_[kMaxNoMFMVFrames];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700209 libaom_test::TestMode encoding_mode_;
Debargha Mukherjee5729d172018-03-29 12:31:21 -0700210 int allow_mismatch_;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700211};
212
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700213TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700214 const aom_rational timebase = { 33333333, 1000000000 };
Adrian Grangecc017ca2012-10-02 12:16:27 -0700215 cfg_.g_timebase = timebase;
216 cfg_.rc_target_bitrate = 2000;
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700217 cfg_.g_lag_in_frames = 10;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700218
Yaowu Xuf883b422016-08-30 14:01:10 -0700219 init_flags_ = AOM_CODEC_USE_PSNR;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700220
Yaowu Xuc27fc142016-08-22 16:08:15 -0700221 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
Yaowu Xu2e7da0a2017-05-08 15:30:08 -0700222 timebase.den, timebase.num, 0, 12);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700223
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -0700224 // Global error resilient mode OFF.
Adrian Grangecc017ca2012-10-02 12:16:27 -0700225 cfg_.g_error_resilient = 0;
226 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
227 const double psnr_resilience_off = GetAveragePsnr();
228 EXPECT_GT(psnr_resilience_off, 25.0);
229
Debargha Mukherjee9dec0c52018-03-25 09:09:36 -0700230 Reset();
231 // Error resilient mode ON for certain frames
232 unsigned int num_error_resilient_frames = 5;
233 unsigned int error_resilient_frame_list[] = { 3, 5, 6, 9, 11 };
234 SetErrorResilientFrames(num_error_resilient_frames,
235 error_resilient_frame_list);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700236 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
237 const double psnr_resilience_on = GetAveragePsnr();
238 EXPECT_GT(psnr_resilience_on, 25.0);
239
240 // Test that turning on error resilient mode hurts by 10% at most.
241 if (psnr_resilience_off > 0.0) {
242 const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
243 EXPECT_GE(psnr_ratio, 0.9);
244 EXPECT_LE(psnr_ratio, 1.1);
245 }
246}
247
Marco Paniconif61b9622014-02-24 18:14:50 -0800248// Check for successful decoding and no encoder/decoder mismatch
249// if we lose (i.e., drop before decoding) a set of droppable
250// frames (i.e., frames that don't update any reference buffers).
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700251TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700252 const aom_rational timebase = { 33333333, 1000000000 };
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800253 cfg_.g_timebase = timebase;
John Koleszarc0490a52013-05-07 12:58:32 -0700254 cfg_.rc_target_bitrate = 500;
Sarah Parker73556772018-03-28 18:28:05 -0700255 cfg_.g_lag_in_frames = 10;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800256
Yaowu Xuf883b422016-08-30 14:01:10 -0700257 init_flags_ = AOM_CODEC_USE_PSNR;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800258
Yaowu Xuc27fc142016-08-22 16:08:15 -0700259 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
Yaowu Xu2e7da0a2017-05-08 15:30:08 -0700260 timebase.den, timebase.num, 0, 20);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800261
Yaowu Xuf883b422016-08-30 14:01:10 -0700262 cfg_.kf_mode = AOM_KF_DISABLED;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800263
Marco Paniconif61b9622014-02-24 18:14:50 -0800264 // Set an arbitrary set of error frames same as droppable frames.
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700265 unsigned int num_droppable_frames = 3;
266 unsigned int droppable_frame_list[] = { 5, 10, 13 };
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800267 SetDroppableFrames(num_droppable_frames, droppable_frame_list);
268 SetErrorFrames(num_droppable_frames, droppable_frame_list);
269 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
270 // Test that no mismatches have been found
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700271 std::cout << " Encoded frames: " << GetEncodedFrames() << "\n";
272 std::cout << " Decoded frames: " << GetDecodedFrames() << "\n";
clang-format3a826f12016-08-11 17:46:05 -0700273 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700274 EXPECT_EQ(GetEncodedFrames() - GetDecodedFrames(), num_droppable_frames);
Debargha Mukherjee5729d172018-03-29 12:31:21 -0700275}
276
277// Check for ParseAbility property of an error-resilient frame.
278// Encode a frame in error-resilient mode (E-frame), and disallow all
279// subsequent frames from using MFMV. If frames are dropped before the
280// E frame, all frames starting from the E frame should be parse-able.
281TEST_P(ErrorResilienceTestLarge, ParseAbilityTest) {
282 const aom_rational timebase = { 33333333, 1000000000 };
283 cfg_.g_timebase = timebase;
284 cfg_.rc_target_bitrate = 500;
285 // TODO(sarahparker, debargha): Make control setting work correctly for
286 // lag_in_frames > 0
287 cfg_.g_lag_in_frames = 0;
288
289 init_flags_ = AOM_CODEC_USE_PSNR;
290
291 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
292 timebase.den, timebase.num, 0, 15);
293
294 cfg_.kf_mode = AOM_KF_DISABLED;
295
296 SetAllowMismatch(1);
297
298 // Set an arbitrary error resilient (E) frame
299 unsigned int num_error_resilient_frames = 1;
300 unsigned int error_resilient_frame_list[] = { 6 };
301 SetErrorResilientFrames(num_error_resilient_frames,
302 error_resilient_frame_list);
303 // Set all frames after the error resilient frame to not allow MFMV
304 unsigned int num_nomfmv_frames = 8;
305 unsigned int nomfmv_frame_list[] = { 7, 8, 9, 10, 11, 12, 13, 14 };
306 SetNoMFMVFrames(num_nomfmv_frames, nomfmv_frame_list);
307
308 // Set a few frames before the E frame that are lost (not decoded)
309 unsigned int num_error_frames = 3;
310 unsigned int error_frame_list[] = { 3, 4, 5 };
311 SetErrorFrames(num_error_frames, error_frame_list);
312
313 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
314 std::cout << " Encoded frames: " << GetEncodedFrames() << "\n";
315 std::cout << " Decoded frames: " << GetDecodedFrames() << "\n";
316 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
317 EXPECT_EQ(GetEncodedFrames() - GetDecodedFrames(), num_error_frames);
318 // All frames following the E-frame and the E-frame are expected to have
319 // mismatches, but still be parse-able.
320 EXPECT_EQ(GetMismatchFrames(), num_nomfmv_frames + 1);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800321}
322
Debargha Mukherjee776b6412018-03-23 17:25:06 -0700323AV1_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, NONREALTIME_TEST_MODES);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700324} // namespace