blob: 99419ad6d898cfff485639a3fdeead3b139a16d8 [file] [log] [blame]
Adrian Grangecc017ca2012-10-02 12:16:27 -07001/*
Frank Galligan38536f62013-12-12 08:36:34 -08002 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080010
Adrian Grangecc017ca2012-10-02 12:16:27 -070011#include "third_party/googletest/src/include/gtest/gtest.h"
John Koleszar706cafe2013-01-18 11:51:12 -080012#include "test/codec_factory.h"
Adrian Grangecc017ca2012-10-02 12:16:27 -070013#include "test/encode_test_driver.h"
14#include "test/i420_video_source.h"
John Koleszar706cafe2013-01-18 11:51:12 -080015#include "test/util.h"
Adrian Grangecc017ca2012-10-02 12:16:27 -070016
17namespace {
18
Marco Paniconif61b9622014-02-24 18:14:50 -080019const int kMaxErrorFrames = 12;
20const int kMaxDroppableFrames = 12;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080021
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070022class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
James Zerncc73e1f2016-08-08 15:09:30 -070023 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
Adrian Grangecc017ca2012-10-02 12:16:27 -070024 protected:
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070025 ErrorResilienceTestLarge()
26 : EncoderTest(GET_PARAM(0)),
27 psnr_(0.0),
28 nframes_(0),
29 mismatch_psnr_(0.0),
30 mismatch_nframes_(0),
31 encoding_mode_(GET_PARAM(1)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080032 Reset();
33 }
John Koleszar706cafe2013-01-18 11:51:12 -080034
Jim Bankoskia0b5ed62014-03-12 08:13:16 -070035 virtual ~ErrorResilienceTestLarge() {}
Adrian Grangecc017ca2012-10-02 12:16:27 -070036
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080037 void Reset() {
38 error_nframes_ = 0;
39 droppable_nframes_ = 0;
Marco2c6d9c52015-01-11 15:26:44 -080040 pattern_switch_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080041 }
42
Adrian Grangecc017ca2012-10-02 12:16:27 -070043 virtual void SetUp() {
44 InitializeConfig();
45 SetMode(encoding_mode_);
46 }
47
48 virtual void BeginPassHook(unsigned int /*pass*/) {
49 psnr_ = 0.0;
50 nframes_ = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080051 mismatch_psnr_ = 0.0;
52 mismatch_nframes_ = 0;
Adrian Grangecc017ca2012-10-02 12:16:27 -070053 }
54
Adrian Grangecc017ca2012-10-02 12:16:27 -070055 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
56 psnr_ += pkt->data.psnr.psnr[0];
57 nframes_++;
58 }
59
Marco8fd55252014-10-29 15:34:18 -070060 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
James Zerncffef112016-02-11 18:27:00 -080061 ::libvpx_test::Encoder * /*encoder*/) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080062 frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST |
63 VP8_EFLAG_NO_UPD_GF |
64 VP8_EFLAG_NO_UPD_ARF);
James Zerncc73e1f2016-08-08 15:09:30 -070065 if (droppable_nframes_ > 0 &&
66 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080067 for (unsigned int i = 0; i < droppable_nframes_; ++i) {
Deb Mukherjee0d8723f2013-08-19 14:16:26 -070068 if (droppable_frames_[i] == video->frame()) {
Marco8fd55252014-10-29 15:34:18 -070069 std::cout << "Encoding droppable frame: "
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080070 << droppable_frames_[i] << "\n";
James Zerncc73e1f2016-08-08 15:09:30 -070071 frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
72 VP8_EFLAG_NO_UPD_GF |
73 VP8_EFLAG_NO_UPD_ARF);
74 return;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080075 }
76 }
77 }
78 }
79
Adrian Grangecc017ca2012-10-02 12:16:27 -070080 double GetAveragePsnr() const {
81 if (nframes_)
82 return psnr_ / nframes_;
83 return 0.0;
84 }
85
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080086 double GetAverageMismatchPsnr() const {
87 if (mismatch_nframes_)
88 return mismatch_psnr_ / mismatch_nframes_;
89 return 0.0;
90 }
91
92 virtual bool DoDecode() const {
93 if (error_nframes_ > 0 &&
94 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
95 for (unsigned int i = 0; i < error_nframes_; ++i) {
96 if (error_frames_[i] == nframes_ - 1) {
97 std::cout << " Skipping decoding frame: "
98 << error_frames_[i] << "\n";
99 return 0;
100 }
101 }
102 }
103 return 1;
104 }
105
106 virtual void MismatchHook(const vpx_image_t *img1,
107 const vpx_image_t *img2) {
108 double mismatch_psnr = compute_psnr(img1, img2);
109 mismatch_psnr_ += mismatch_psnr;
110 ++mismatch_nframes_;
111 // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
Geza Loree0dcab92016-05-09 13:19:34 +0100112 ::libvpx_test::EncoderTest::MismatchHook(img1, img2);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800113 }
114
115 void SetErrorFrames(int num, unsigned int *list) {
116 if (num > kMaxErrorFrames)
117 num = kMaxErrorFrames;
118 else if (num < 0)
119 num = 0;
120 error_nframes_ = num;
121 for (unsigned int i = 0; i < error_nframes_; ++i)
122 error_frames_[i] = list[i];
123 }
124
125 void SetDroppableFrames(int num, unsigned int *list) {
126 if (num > kMaxDroppableFrames)
127 num = kMaxDroppableFrames;
128 else if (num < 0)
129 num = 0;
130 droppable_nframes_ = num;
131 for (unsigned int i = 0; i < droppable_nframes_; ++i)
132 droppable_frames_[i] = list[i];
133 }
134
135 unsigned int GetMismatchFrames() {
136 return mismatch_nframes_;
137 }
138
Marco2c6d9c52015-01-11 15:26:44 -0800139 void SetPatternSwitch(int frame_switch) {
140 pattern_switch_ = frame_switch;
141 }
142
Adrian Grangecc017ca2012-10-02 12:16:27 -0700143 private:
144 double psnr_;
145 unsigned int nframes_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800146 unsigned int error_nframes_;
147 unsigned int droppable_nframes_;
Marco2c6d9c52015-01-11 15:26:44 -0800148 unsigned int pattern_switch_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800149 double mismatch_psnr_;
150 unsigned int mismatch_nframes_;
151 unsigned int error_frames_[kMaxErrorFrames];
152 unsigned int droppable_frames_[kMaxDroppableFrames];
Adrian Grangecc017ca2012-10-02 12:16:27 -0700153 libvpx_test::TestMode encoding_mode_;
154};
155
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700156TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
Adrian Grangecc017ca2012-10-02 12:16:27 -0700157 const vpx_rational timebase = { 33333333, 1000000000 };
158 cfg_.g_timebase = timebase;
159 cfg_.rc_target_bitrate = 2000;
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700160 cfg_.g_lag_in_frames = 10;
Adrian Grangecc017ca2012-10-02 12:16:27 -0700161
162 init_flags_ = VPX_CODEC_USE_PSNR;
163
164 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
165 timebase.den, timebase.num, 0, 30);
166
167 // Error resilient mode OFF.
168 cfg_.g_error_resilient = 0;
169 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
170 const double psnr_resilience_off = GetAveragePsnr();
171 EXPECT_GT(psnr_resilience_off, 25.0);
172
173 // Error resilient mode ON.
174 cfg_.g_error_resilient = 1;
175 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
176 const double psnr_resilience_on = GetAveragePsnr();
177 EXPECT_GT(psnr_resilience_on, 25.0);
178
179 // Test that turning on error resilient mode hurts by 10% at most.
180 if (psnr_resilience_off > 0.0) {
181 const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
182 EXPECT_GE(psnr_ratio, 0.9);
183 EXPECT_LE(psnr_ratio, 1.1);
184 }
185}
186
Marco Paniconif61b9622014-02-24 18:14:50 -0800187// Check for successful decoding and no encoder/decoder mismatch
188// if we lose (i.e., drop before decoding) a set of droppable
189// frames (i.e., frames that don't update any reference buffers).
190// Check both isolated and consecutive loss.
Jim Bankoskia0b5ed62014-03-12 08:13:16 -0700191TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800192 const vpx_rational timebase = { 33333333, 1000000000 };
193 cfg_.g_timebase = timebase;
John Koleszarc0490a52013-05-07 12:58:32 -0700194 cfg_.rc_target_bitrate = 500;
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700195 // FIXME(debargha): Fix this to work for any lag.
196 // Currently this test only works for lag = 0
197 cfg_.g_lag_in_frames = 0;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800198
199 init_flags_ = VPX_CODEC_USE_PSNR;
200
201 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
Marco Paniconif61b9622014-02-24 18:14:50 -0800202 timebase.den, timebase.num, 0, 40);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800203
204 // Error resilient mode ON.
205 cfg_.g_error_resilient = 1;
Marco Paniconif61b9622014-02-24 18:14:50 -0800206 cfg_.kf_mode = VPX_KF_DISABLED;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800207
Marco Paniconif61b9622014-02-24 18:14:50 -0800208 // Set an arbitrary set of error frames same as droppable frames.
209 // In addition to isolated loss/drop, add a long consecutive series
210 // (of size 9) of dropped frames.
211 unsigned int num_droppable_frames = 11;
212 unsigned int droppable_frame_list[] = {5, 16, 22, 23, 24, 25, 26, 27, 28,
213 29, 30};
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800214 SetDroppableFrames(num_droppable_frames, droppable_frame_list);
215 SetErrorFrames(num_droppable_frames, droppable_frame_list);
216 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
217 // Test that no mismatches have been found
218 std::cout << " Mismatch frames: "
219 << GetMismatchFrames() << "\n";
220 EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
221
Marco Paniconif61b9622014-02-24 18:14:50 -0800222 // Reset previously set of error/droppable frames.
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800223 Reset();
224
John Koleszar9fba0342013-05-07 13:02:45 -0700225#if 0
226 // TODO(jkoleszar): This test is disabled for the time being as too
227 // sensitive. It's not clear how to set a reasonable threshold for
228 // this behavior.
229
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800230 // Now set an arbitrary set of error frames that are non-droppable
231 unsigned int num_error_frames = 3;
232 unsigned int error_frame_list[] = {3, 10, 20};
233 SetErrorFrames(num_error_frames, error_frame_list);
234 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
John Koleszar9fba0342013-05-07 13:02:45 -0700235
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800236 // Test that dropping an arbitrary set of inter frames does not hurt too much
237 // Note the Average Mismatch PSNR is the average of the PSNR between
238 // decoded frame and encoder's version of the same frame for all frames
239 // with mismatch.
240 const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
241 std::cout << " Mismatch PSNR: "
242 << psnr_resilience_mismatch << "\n";
243 EXPECT_GT(psnr_resilience_mismatch, 20.0);
John Koleszar9fba0342013-05-07 13:02:45 -0700244#endif
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800245}
246
James Zerncc73e1f2016-08-08 15:09:30 -0700247VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES);
Adrian Grangecc017ca2012-10-02 12:16:27 -0700248} // namespace