xref: /aosp_15_r20/external/libvpx/test/error_resilience_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "test/codec_factory.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "test/encode_test_driver.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "test/i420_video_source.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "test/util.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_config.h"
17*fb1b10abSAndroid Build Coastguard Worker 
18*fb1b10abSAndroid Build Coastguard Worker namespace {
19*fb1b10abSAndroid Build Coastguard Worker 
20*fb1b10abSAndroid Build Coastguard Worker const int kMaxErrorFrames = 12;
21*fb1b10abSAndroid Build Coastguard Worker const int kMaxDroppableFrames = 12;
22*fb1b10abSAndroid Build Coastguard Worker 
23*fb1b10abSAndroid Build Coastguard Worker class ErrorResilienceTestLarge
24*fb1b10abSAndroid Build Coastguard Worker     : public ::libvpx_test::EncoderTest,
25*fb1b10abSAndroid Build Coastguard Worker       public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
26*fb1b10abSAndroid Build Coastguard Worker  protected:
ErrorResilienceTestLarge()27*fb1b10abSAndroid Build Coastguard Worker   ErrorResilienceTestLarge()
28*fb1b10abSAndroid Build Coastguard Worker       : EncoderTest(GET_PARAM(0)), svc_support_(GET_PARAM(2)), psnr_(0.0),
29*fb1b10abSAndroid Build Coastguard Worker         nframes_(0), mismatch_psnr_(0.0), mismatch_nframes_(0),
30*fb1b10abSAndroid Build Coastguard Worker         encoding_mode_(GET_PARAM(1)) {
31*fb1b10abSAndroid Build Coastguard Worker     Reset();
32*fb1b10abSAndroid Build Coastguard Worker   }
33*fb1b10abSAndroid Build Coastguard Worker 
34*fb1b10abSAndroid Build Coastguard Worker   ~ErrorResilienceTestLarge() override = default;
35*fb1b10abSAndroid Build Coastguard Worker 
Reset()36*fb1b10abSAndroid Build Coastguard Worker   void Reset() {
37*fb1b10abSAndroid Build Coastguard Worker     error_nframes_ = 0;
38*fb1b10abSAndroid Build Coastguard Worker     droppable_nframes_ = 0;
39*fb1b10abSAndroid Build Coastguard Worker     pattern_switch_ = 0;
40*fb1b10abSAndroid Build Coastguard Worker   }
41*fb1b10abSAndroid Build Coastguard Worker 
SetUp()42*fb1b10abSAndroid Build Coastguard Worker   void SetUp() override {
43*fb1b10abSAndroid Build Coastguard Worker     InitializeConfig();
44*fb1b10abSAndroid Build Coastguard Worker     SetMode(encoding_mode_);
45*fb1b10abSAndroid Build Coastguard Worker   }
46*fb1b10abSAndroid Build Coastguard Worker 
BeginPassHook(unsigned int)47*fb1b10abSAndroid Build Coastguard Worker   void BeginPassHook(unsigned int /*pass*/) override {
48*fb1b10abSAndroid Build Coastguard Worker     psnr_ = 0.0;
49*fb1b10abSAndroid Build Coastguard Worker     nframes_ = 0;
50*fb1b10abSAndroid Build Coastguard Worker     mismatch_psnr_ = 0.0;
51*fb1b10abSAndroid Build Coastguard Worker     mismatch_nframes_ = 0;
52*fb1b10abSAndroid Build Coastguard Worker   }
53*fb1b10abSAndroid Build Coastguard Worker 
PSNRPktHook(const vpx_codec_cx_pkt_t * pkt)54*fb1b10abSAndroid Build Coastguard Worker   void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) override {
55*fb1b10abSAndroid Build Coastguard Worker     psnr_ += pkt->data.psnr.psnr[0];
56*fb1b10abSAndroid Build Coastguard Worker     nframes_++;
57*fb1b10abSAndroid Build Coastguard Worker   }
58*fb1b10abSAndroid Build Coastguard Worker 
59*fb1b10abSAndroid Build Coastguard Worker   //
60*fb1b10abSAndroid Build Coastguard Worker   // Frame flags and layer id for temporal layers.
61*fb1b10abSAndroid Build Coastguard Worker   // For two layers, test pattern is:
62*fb1b10abSAndroid Build Coastguard Worker   //   1     3
63*fb1b10abSAndroid Build Coastguard Worker   // 0    2     .....
64*fb1b10abSAndroid Build Coastguard Worker   // LAST is updated on base/layer 0, GOLDEN  updated on layer 1.
65*fb1b10abSAndroid Build Coastguard Worker   // Non-zero pattern_switch parameter means pattern will switch to
66*fb1b10abSAndroid Build Coastguard Worker   // not using LAST for frame_num >= pattern_switch.
SetFrameFlags(int frame_num,int num_temp_layers,int pattern_switch)67*fb1b10abSAndroid Build Coastguard Worker   int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) {
68*fb1b10abSAndroid Build Coastguard Worker     int frame_flags = 0;
69*fb1b10abSAndroid Build Coastguard Worker     if (num_temp_layers == 2) {
70*fb1b10abSAndroid Build Coastguard Worker       if (frame_num % 2 == 0) {
71*fb1b10abSAndroid Build Coastguard Worker         if (frame_num < pattern_switch || pattern_switch == 0) {
72*fb1b10abSAndroid Build Coastguard Worker           // Layer 0: predict from LAST and ARF, update LAST.
73*fb1b10abSAndroid Build Coastguard Worker           frame_flags =
74*fb1b10abSAndroid Build Coastguard Worker               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
75*fb1b10abSAndroid Build Coastguard Worker         } else {
76*fb1b10abSAndroid Build Coastguard Worker           // Layer 0: predict from GF and ARF, update GF.
77*fb1b10abSAndroid Build Coastguard Worker           frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
78*fb1b10abSAndroid Build Coastguard Worker                         VP8_EFLAG_NO_UPD_ARF;
79*fb1b10abSAndroid Build Coastguard Worker         }
80*fb1b10abSAndroid Build Coastguard Worker       } else {
81*fb1b10abSAndroid Build Coastguard Worker         if (frame_num < pattern_switch || pattern_switch == 0) {
82*fb1b10abSAndroid Build Coastguard Worker           // Layer 1: predict from L, GF, and ARF, update GF.
83*fb1b10abSAndroid Build Coastguard Worker           frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
84*fb1b10abSAndroid Build Coastguard Worker         } else {
85*fb1b10abSAndroid Build Coastguard Worker           // Layer 1: predict from GF and ARF, update GF.
86*fb1b10abSAndroid Build Coastguard Worker           frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
87*fb1b10abSAndroid Build Coastguard Worker                         VP8_EFLAG_NO_UPD_ARF;
88*fb1b10abSAndroid Build Coastguard Worker         }
89*fb1b10abSAndroid Build Coastguard Worker       }
90*fb1b10abSAndroid Build Coastguard Worker     }
91*fb1b10abSAndroid Build Coastguard Worker     return frame_flags;
92*fb1b10abSAndroid Build Coastguard Worker   }
93*fb1b10abSAndroid Build Coastguard Worker 
PreEncodeFrameHook(libvpx_test::VideoSource * video)94*fb1b10abSAndroid Build Coastguard Worker   void PreEncodeFrameHook(libvpx_test::VideoSource *video) override {
95*fb1b10abSAndroid Build Coastguard Worker     frame_flags_ &=
96*fb1b10abSAndroid Build Coastguard Worker         ~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF);
97*fb1b10abSAndroid Build Coastguard Worker     // For temporal layer case.
98*fb1b10abSAndroid Build Coastguard Worker     if (cfg_.ts_number_layers > 1) {
99*fb1b10abSAndroid Build Coastguard Worker       frame_flags_ =
100*fb1b10abSAndroid Build Coastguard Worker           SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_);
101*fb1b10abSAndroid Build Coastguard Worker       for (unsigned int i = 0; i < droppable_nframes_; ++i) {
102*fb1b10abSAndroid Build Coastguard Worker         if (droppable_frames_[i] == video->frame()) {
103*fb1b10abSAndroid Build Coastguard Worker           std::cout << "Encoding droppable frame: " << droppable_frames_[i]
104*fb1b10abSAndroid Build Coastguard Worker                     << "\n";
105*fb1b10abSAndroid Build Coastguard Worker         }
106*fb1b10abSAndroid Build Coastguard Worker       }
107*fb1b10abSAndroid Build Coastguard Worker     } else {
108*fb1b10abSAndroid Build Coastguard Worker       if (droppable_nframes_ > 0 &&
109*fb1b10abSAndroid Build Coastguard Worker           (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
110*fb1b10abSAndroid Build Coastguard Worker         for (unsigned int i = 0; i < droppable_nframes_; ++i) {
111*fb1b10abSAndroid Build Coastguard Worker           if (droppable_frames_[i] == video->frame()) {
112*fb1b10abSAndroid Build Coastguard Worker             std::cout << "Encoding droppable frame: " << droppable_frames_[i]
113*fb1b10abSAndroid Build Coastguard Worker                       << "\n";
114*fb1b10abSAndroid Build Coastguard Worker             frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
115*fb1b10abSAndroid Build Coastguard Worker                              VP8_EFLAG_NO_UPD_ARF);
116*fb1b10abSAndroid Build Coastguard Worker             return;
117*fb1b10abSAndroid Build Coastguard Worker           }
118*fb1b10abSAndroid Build Coastguard Worker         }
119*fb1b10abSAndroid Build Coastguard Worker       }
120*fb1b10abSAndroid Build Coastguard Worker     }
121*fb1b10abSAndroid Build Coastguard Worker   }
122*fb1b10abSAndroid Build Coastguard Worker 
GetAveragePsnr() const123*fb1b10abSAndroid Build Coastguard Worker   double GetAveragePsnr() const {
124*fb1b10abSAndroid Build Coastguard Worker     if (nframes_) return psnr_ / nframes_;
125*fb1b10abSAndroid Build Coastguard Worker     return 0.0;
126*fb1b10abSAndroid Build Coastguard Worker   }
127*fb1b10abSAndroid Build Coastguard Worker 
GetAverageMismatchPsnr() const128*fb1b10abSAndroid Build Coastguard Worker   double GetAverageMismatchPsnr() const {
129*fb1b10abSAndroid Build Coastguard Worker     if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
130*fb1b10abSAndroid Build Coastguard Worker     return 0.0;
131*fb1b10abSAndroid Build Coastguard Worker   }
132*fb1b10abSAndroid Build Coastguard Worker 
DoDecode() const133*fb1b10abSAndroid Build Coastguard Worker   bool DoDecode() const override {
134*fb1b10abSAndroid Build Coastguard Worker     if (error_nframes_ > 0 &&
135*fb1b10abSAndroid Build Coastguard Worker         (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
136*fb1b10abSAndroid Build Coastguard Worker       for (unsigned int i = 0; i < error_nframes_; ++i) {
137*fb1b10abSAndroid Build Coastguard Worker         if (error_frames_[i] == nframes_ - 1) {
138*fb1b10abSAndroid Build Coastguard Worker           std::cout << "             Skipping decoding frame: "
139*fb1b10abSAndroid Build Coastguard Worker                     << error_frames_[i] << "\n";
140*fb1b10abSAndroid Build Coastguard Worker           return false;
141*fb1b10abSAndroid Build Coastguard Worker         }
142*fb1b10abSAndroid Build Coastguard Worker       }
143*fb1b10abSAndroid Build Coastguard Worker     }
144*fb1b10abSAndroid Build Coastguard Worker     return true;
145*fb1b10abSAndroid Build Coastguard Worker   }
146*fb1b10abSAndroid Build Coastguard Worker 
MismatchHook(const vpx_image_t * img1,const vpx_image_t * img2)147*fb1b10abSAndroid Build Coastguard Worker   void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) override {
148*fb1b10abSAndroid Build Coastguard Worker     double mismatch_psnr = compute_psnr(img1, img2);
149*fb1b10abSAndroid Build Coastguard Worker     mismatch_psnr_ += mismatch_psnr;
150*fb1b10abSAndroid Build Coastguard Worker     ++mismatch_nframes_;
151*fb1b10abSAndroid Build Coastguard Worker     // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
152*fb1b10abSAndroid Build Coastguard Worker   }
153*fb1b10abSAndroid Build Coastguard Worker 
SetErrorFrames(int num,unsigned int * list)154*fb1b10abSAndroid Build Coastguard Worker   void SetErrorFrames(int num, unsigned int *list) {
155*fb1b10abSAndroid Build Coastguard Worker     if (num > kMaxErrorFrames) {
156*fb1b10abSAndroid Build Coastguard Worker       num = kMaxErrorFrames;
157*fb1b10abSAndroid Build Coastguard Worker     } else if (num < 0) {
158*fb1b10abSAndroid Build Coastguard Worker       num = 0;
159*fb1b10abSAndroid Build Coastguard Worker     }
160*fb1b10abSAndroid Build Coastguard Worker     error_nframes_ = num;
161*fb1b10abSAndroid Build Coastguard Worker     for (unsigned int i = 0; i < error_nframes_; ++i) {
162*fb1b10abSAndroid Build Coastguard Worker       error_frames_[i] = list[i];
163*fb1b10abSAndroid Build Coastguard Worker     }
164*fb1b10abSAndroid Build Coastguard Worker   }
165*fb1b10abSAndroid Build Coastguard Worker 
SetDroppableFrames(int num,unsigned int * list)166*fb1b10abSAndroid Build Coastguard Worker   void SetDroppableFrames(int num, unsigned int *list) {
167*fb1b10abSAndroid Build Coastguard Worker     if (num > kMaxDroppableFrames) {
168*fb1b10abSAndroid Build Coastguard Worker       num = kMaxDroppableFrames;
169*fb1b10abSAndroid Build Coastguard Worker     } else if (num < 0) {
170*fb1b10abSAndroid Build Coastguard Worker       num = 0;
171*fb1b10abSAndroid Build Coastguard Worker     }
172*fb1b10abSAndroid Build Coastguard Worker     droppable_nframes_ = num;
173*fb1b10abSAndroid Build Coastguard Worker     for (unsigned int i = 0; i < droppable_nframes_; ++i) {
174*fb1b10abSAndroid Build Coastguard Worker       droppable_frames_[i] = list[i];
175*fb1b10abSAndroid Build Coastguard Worker     }
176*fb1b10abSAndroid Build Coastguard Worker   }
177*fb1b10abSAndroid Build Coastguard Worker 
GetMismatchFrames()178*fb1b10abSAndroid Build Coastguard Worker   unsigned int GetMismatchFrames() { return mismatch_nframes_; }
179*fb1b10abSAndroid Build Coastguard Worker 
SetPatternSwitch(int frame_switch)180*fb1b10abSAndroid Build Coastguard Worker   void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
181*fb1b10abSAndroid Build Coastguard Worker 
182*fb1b10abSAndroid Build Coastguard Worker   bool svc_support_;
183*fb1b10abSAndroid Build Coastguard Worker 
184*fb1b10abSAndroid Build Coastguard Worker  private:
185*fb1b10abSAndroid Build Coastguard Worker   double psnr_;
186*fb1b10abSAndroid Build Coastguard Worker   unsigned int nframes_;
187*fb1b10abSAndroid Build Coastguard Worker   unsigned int error_nframes_;
188*fb1b10abSAndroid Build Coastguard Worker   unsigned int droppable_nframes_;
189*fb1b10abSAndroid Build Coastguard Worker   unsigned int pattern_switch_;
190*fb1b10abSAndroid Build Coastguard Worker   double mismatch_psnr_;
191*fb1b10abSAndroid Build Coastguard Worker   unsigned int mismatch_nframes_;
192*fb1b10abSAndroid Build Coastguard Worker   unsigned int error_frames_[kMaxErrorFrames];
193*fb1b10abSAndroid Build Coastguard Worker   unsigned int droppable_frames_[kMaxDroppableFrames];
194*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::TestMode encoding_mode_;
195*fb1b10abSAndroid Build Coastguard Worker };
196*fb1b10abSAndroid Build Coastguard Worker 
TEST_P(ErrorResilienceTestLarge,OnVersusOff)197*fb1b10abSAndroid Build Coastguard Worker TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
198*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_REALTIME_ONLY
199*fb1b10abSAndroid Build Coastguard Worker   GTEST_SKIP()
200*fb1b10abSAndroid Build Coastguard Worker       << "Non-zero g_lag_in_frames is unsupported with CONFIG_REALTIME_ONLY";
201*fb1b10abSAndroid Build Coastguard Worker #else
202*fb1b10abSAndroid Build Coastguard Worker   const vpx_rational timebase = { 33333333, 1000000000 };
203*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_timebase = timebase;
204*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_target_bitrate = 2000;
205*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_lag_in_frames = 10;
206*fb1b10abSAndroid Build Coastguard Worker 
207*fb1b10abSAndroid Build Coastguard Worker   init_flags_ = VPX_CODEC_USE_PSNR;
208*fb1b10abSAndroid Build Coastguard Worker 
209*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
210*fb1b10abSAndroid Build Coastguard Worker                                      timebase.den, timebase.num, 0, 30);
211*fb1b10abSAndroid Build Coastguard Worker 
212*fb1b10abSAndroid Build Coastguard Worker   // Error resilient mode OFF.
213*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 0;
214*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
215*fb1b10abSAndroid Build Coastguard Worker   const double psnr_resilience_off = GetAveragePsnr();
216*fb1b10abSAndroid Build Coastguard Worker   EXPECT_GT(psnr_resilience_off, 25.0);
217*fb1b10abSAndroid Build Coastguard Worker 
218*fb1b10abSAndroid Build Coastguard Worker   // Error resilient mode ON.
219*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 1;
220*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
221*fb1b10abSAndroid Build Coastguard Worker   const double psnr_resilience_on = GetAveragePsnr();
222*fb1b10abSAndroid Build Coastguard Worker   EXPECT_GT(psnr_resilience_on, 25.0);
223*fb1b10abSAndroid Build Coastguard Worker 
224*fb1b10abSAndroid Build Coastguard Worker   // Test that turning on error resilient mode hurts by 10% at most.
225*fb1b10abSAndroid Build Coastguard Worker   if (psnr_resilience_off > 0.0) {
226*fb1b10abSAndroid Build Coastguard Worker     const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
227*fb1b10abSAndroid Build Coastguard Worker     EXPECT_GE(psnr_ratio, 0.9);
228*fb1b10abSAndroid Build Coastguard Worker     EXPECT_LE(psnr_ratio, 1.1);
229*fb1b10abSAndroid Build Coastguard Worker   }
230*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_REALTIME_ONLY
231*fb1b10abSAndroid Build Coastguard Worker }
232*fb1b10abSAndroid Build Coastguard Worker 
233*fb1b10abSAndroid Build Coastguard Worker // Check for successful decoding and no encoder/decoder mismatch
234*fb1b10abSAndroid Build Coastguard Worker // if we lose (i.e., drop before decoding) a set of droppable
235*fb1b10abSAndroid Build Coastguard Worker // frames (i.e., frames that don't update any reference buffers).
236*fb1b10abSAndroid Build Coastguard Worker // Check both isolated and consecutive loss.
TEST_P(ErrorResilienceTestLarge,DropFramesWithoutRecovery)237*fb1b10abSAndroid Build Coastguard Worker TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
238*fb1b10abSAndroid Build Coastguard Worker   const vpx_rational timebase = { 33333333, 1000000000 };
239*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_timebase = timebase;
240*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_target_bitrate = 500;
241*fb1b10abSAndroid Build Coastguard Worker   // FIXME(debargha): Fix this to work for any lag.
242*fb1b10abSAndroid Build Coastguard Worker   // Currently this test only works for lag = 0
243*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_lag_in_frames = 0;
244*fb1b10abSAndroid Build Coastguard Worker 
245*fb1b10abSAndroid Build Coastguard Worker   init_flags_ = VPX_CODEC_USE_PSNR;
246*fb1b10abSAndroid Build Coastguard Worker 
247*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
248*fb1b10abSAndroid Build Coastguard Worker                                      timebase.den, timebase.num, 0, 40);
249*fb1b10abSAndroid Build Coastguard Worker 
250*fb1b10abSAndroid Build Coastguard Worker   // Error resilient mode ON.
251*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 1;
252*fb1b10abSAndroid Build Coastguard Worker   cfg_.kf_mode = VPX_KF_DISABLED;
253*fb1b10abSAndroid Build Coastguard Worker 
254*fb1b10abSAndroid Build Coastguard Worker   // Set an arbitrary set of error frames same as droppable frames.
255*fb1b10abSAndroid Build Coastguard Worker   // In addition to isolated loss/drop, add a long consecutive series
256*fb1b10abSAndroid Build Coastguard Worker   // (of size 9) of dropped frames.
257*fb1b10abSAndroid Build Coastguard Worker   unsigned int num_droppable_frames = 11;
258*fb1b10abSAndroid Build Coastguard Worker   unsigned int droppable_frame_list[] = { 5,  16, 22, 23, 24, 25,
259*fb1b10abSAndroid Build Coastguard Worker                                           26, 27, 28, 29, 30 };
260*fb1b10abSAndroid Build Coastguard Worker   SetDroppableFrames(num_droppable_frames, droppable_frame_list);
261*fb1b10abSAndroid Build Coastguard Worker   SetErrorFrames(num_droppable_frames, droppable_frame_list);
262*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
263*fb1b10abSAndroid Build Coastguard Worker   // Test that no mismatches have been found
264*fb1b10abSAndroid Build Coastguard Worker   std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
265*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
266*fb1b10abSAndroid Build Coastguard Worker 
267*fb1b10abSAndroid Build Coastguard Worker   // Reset previously set of error/droppable frames.
268*fb1b10abSAndroid Build Coastguard Worker   Reset();
269*fb1b10abSAndroid Build Coastguard Worker 
270*fb1b10abSAndroid Build Coastguard Worker #if 0
271*fb1b10abSAndroid Build Coastguard Worker   // TODO(jkoleszar): This test is disabled for the time being as too
272*fb1b10abSAndroid Build Coastguard Worker   // sensitive. It's not clear how to set a reasonable threshold for
273*fb1b10abSAndroid Build Coastguard Worker   // this behavior.
274*fb1b10abSAndroid Build Coastguard Worker 
275*fb1b10abSAndroid Build Coastguard Worker   // Now set an arbitrary set of error frames that are non-droppable
276*fb1b10abSAndroid Build Coastguard Worker   unsigned int num_error_frames = 3;
277*fb1b10abSAndroid Build Coastguard Worker   unsigned int error_frame_list[] = {3, 10, 20};
278*fb1b10abSAndroid Build Coastguard Worker   SetErrorFrames(num_error_frames, error_frame_list);
279*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
280*fb1b10abSAndroid Build Coastguard Worker 
281*fb1b10abSAndroid Build Coastguard Worker   // Test that dropping an arbitrary set of inter frames does not hurt too much
282*fb1b10abSAndroid Build Coastguard Worker   // Note the Average Mismatch PSNR is the average of the PSNR between
283*fb1b10abSAndroid Build Coastguard Worker   // decoded frame and encoder's version of the same frame for all frames
284*fb1b10abSAndroid Build Coastguard Worker   // with mismatch.
285*fb1b10abSAndroid Build Coastguard Worker   const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
286*fb1b10abSAndroid Build Coastguard Worker   std::cout << "             Mismatch PSNR: "
287*fb1b10abSAndroid Build Coastguard Worker             << psnr_resilience_mismatch << "\n";
288*fb1b10abSAndroid Build Coastguard Worker   EXPECT_GT(psnr_resilience_mismatch, 20.0);
289*fb1b10abSAndroid Build Coastguard Worker #endif
290*fb1b10abSAndroid Build Coastguard Worker }
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker // Check for successful decoding and no encoder/decoder mismatch
293*fb1b10abSAndroid Build Coastguard Worker // if we lose (i.e., drop before decoding) the enhancement layer frames for a
294*fb1b10abSAndroid Build Coastguard Worker // two layer temporal pattern. The base layer does not predict from the top
295*fb1b10abSAndroid Build Coastguard Worker // layer, so successful decoding is expected.
296*fb1b10abSAndroid Build Coastguard Worker TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
297*fb1b10abSAndroid Build Coastguard Worker   // This test doesn't run if SVC is not supported.
298*fb1b10abSAndroid Build Coastguard Worker   if (!svc_support_) return;
299*fb1b10abSAndroid Build Coastguard Worker 
300*fb1b10abSAndroid Build Coastguard Worker   const vpx_rational timebase = { 33333333, 1000000000 };
301*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_timebase = timebase;
302*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_target_bitrate = 500;
303*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_lag_in_frames = 0;
304*fb1b10abSAndroid Build Coastguard Worker 
305*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_end_usage = VPX_CBR;
306*fb1b10abSAndroid Build Coastguard Worker   // 2 Temporal layers, no spatial layers, CBR mode.
307*fb1b10abSAndroid Build Coastguard Worker   cfg_.ss_number_layers = 1;
308*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_number_layers = 2;
309*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[0] = 2;
310*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[1] = 1;
311*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_periodicity = 2;
312*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
313*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
314*fb1b10abSAndroid Build Coastguard Worker 
315*fb1b10abSAndroid Build Coastguard Worker   init_flags_ = VPX_CODEC_USE_PSNR;
316*fb1b10abSAndroid Build Coastguard Worker 
317*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
318*fb1b10abSAndroid Build Coastguard Worker                                      timebase.den, timebase.num, 0, 40);
319*fb1b10abSAndroid Build Coastguard Worker 
320*fb1b10abSAndroid Build Coastguard Worker   // Error resilient mode ON.
321*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 1;
322*fb1b10abSAndroid Build Coastguard Worker   cfg_.kf_mode = VPX_KF_DISABLED;
323*fb1b10abSAndroid Build Coastguard Worker   SetPatternSwitch(0);
324*fb1b10abSAndroid Build Coastguard Worker 
325*fb1b10abSAndroid Build Coastguard Worker   // The odd frames are the enhancement layer for 2 layer pattern, so set
326*fb1b10abSAndroid Build Coastguard Worker   // those frames as droppable. Drop the last 7 frames.
327*fb1b10abSAndroid Build Coastguard Worker   unsigned int num_droppable_frames = 7;
328*fb1b10abSAndroid Build Coastguard Worker   unsigned int droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 };
329*fb1b10abSAndroid Build Coastguard Worker   SetDroppableFrames(num_droppable_frames, droppable_frame_list);
330*fb1b10abSAndroid Build Coastguard Worker   SetErrorFrames(num_droppable_frames, droppable_frame_list);
331*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
332*fb1b10abSAndroid Build Coastguard Worker   // Test that no mismatches have been found
333*fb1b10abSAndroid Build Coastguard Worker   std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
334*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
335*fb1b10abSAndroid Build Coastguard Worker 
336*fb1b10abSAndroid Build Coastguard Worker   // Reset previously set of error/droppable frames.
337*fb1b10abSAndroid Build Coastguard Worker   Reset();
338*fb1b10abSAndroid Build Coastguard Worker }
339*fb1b10abSAndroid Build Coastguard Worker 
340*fb1b10abSAndroid Build Coastguard Worker // Check for successful decoding and no encoder/decoder mismatch
341*fb1b10abSAndroid Build Coastguard Worker // for a two layer temporal pattern, where at some point in the
342*fb1b10abSAndroid Build Coastguard Worker // sequence, the LAST ref is not used anymore.
343*fb1b10abSAndroid Build Coastguard Worker TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
344*fb1b10abSAndroid Build Coastguard Worker   // This test doesn't run if SVC is not supported.
345*fb1b10abSAndroid Build Coastguard Worker   if (!svc_support_) return;
346*fb1b10abSAndroid Build Coastguard Worker 
347*fb1b10abSAndroid Build Coastguard Worker   const vpx_rational timebase = { 33333333, 1000000000 };
348*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_timebase = timebase;
349*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_target_bitrate = 500;
350*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_lag_in_frames = 0;
351*fb1b10abSAndroid Build Coastguard Worker 
352*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_end_usage = VPX_CBR;
353*fb1b10abSAndroid Build Coastguard Worker   // 2 Temporal layers, no spatial layers, CBR mode.
354*fb1b10abSAndroid Build Coastguard Worker   cfg_.ss_number_layers = 1;
355*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_number_layers = 2;
356*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[0] = 2;
357*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[1] = 1;
358*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_periodicity = 2;
359*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
360*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
361*fb1b10abSAndroid Build Coastguard Worker 
362*fb1b10abSAndroid Build Coastguard Worker   init_flags_ = VPX_CODEC_USE_PSNR;
363*fb1b10abSAndroid Build Coastguard Worker 
364*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
365*fb1b10abSAndroid Build Coastguard Worker                                      timebase.den, timebase.num, 0, 100);
366*fb1b10abSAndroid Build Coastguard Worker 
367*fb1b10abSAndroid Build Coastguard Worker   // Error resilient mode ON.
368*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 1;
369*fb1b10abSAndroid Build Coastguard Worker   cfg_.kf_mode = VPX_KF_DISABLED;
370*fb1b10abSAndroid Build Coastguard Worker   SetPatternSwitch(60);
371*fb1b10abSAndroid Build Coastguard Worker 
372*fb1b10abSAndroid Build Coastguard Worker   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
373*fb1b10abSAndroid Build Coastguard Worker   // Test that no mismatches have been found
374*fb1b10abSAndroid Build Coastguard Worker   std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
375*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
376*fb1b10abSAndroid Build Coastguard Worker 
377*fb1b10abSAndroid Build Coastguard Worker   // Reset previously set of error/droppable frames.
378*fb1b10abSAndroid Build Coastguard Worker   Reset();
379*fb1b10abSAndroid Build Coastguard Worker }
380*fb1b10abSAndroid Build Coastguard Worker 
381*fb1b10abSAndroid Build Coastguard Worker class ErrorResilienceTestLargeCodecControls
382*fb1b10abSAndroid Build Coastguard Worker     : public ::libvpx_test::EncoderTest,
383*fb1b10abSAndroid Build Coastguard Worker       public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
384*fb1b10abSAndroid Build Coastguard Worker  protected:
ErrorResilienceTestLargeCodecControls()385*fb1b10abSAndroid Build Coastguard Worker   ErrorResilienceTestLargeCodecControls()
386*fb1b10abSAndroid Build Coastguard Worker       : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) {
387*fb1b10abSAndroid Build Coastguard Worker     Reset();
388*fb1b10abSAndroid Build Coastguard Worker   }
389*fb1b10abSAndroid Build Coastguard Worker 
390*fb1b10abSAndroid Build Coastguard Worker   ~ErrorResilienceTestLargeCodecControls() override = default;
391*fb1b10abSAndroid Build Coastguard Worker 
Reset()392*fb1b10abSAndroid Build Coastguard Worker   void Reset() {
393*fb1b10abSAndroid Build Coastguard Worker     last_pts_ = 0;
394*fb1b10abSAndroid Build Coastguard Worker     tot_frame_number_ = 0;
395*fb1b10abSAndroid Build Coastguard Worker     // For testing up to 3 layers.
396*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < 3; ++i) {
397*fb1b10abSAndroid Build Coastguard Worker       bits_total_[i] = 0;
398*fb1b10abSAndroid Build Coastguard Worker     }
399*fb1b10abSAndroid Build Coastguard Worker     duration_ = 0.0;
400*fb1b10abSAndroid Build Coastguard Worker   }
401*fb1b10abSAndroid Build Coastguard Worker 
SetUp()402*fb1b10abSAndroid Build Coastguard Worker   void SetUp() override {
403*fb1b10abSAndroid Build Coastguard Worker     InitializeConfig();
404*fb1b10abSAndroid Build Coastguard Worker     SetMode(encoding_mode_);
405*fb1b10abSAndroid Build Coastguard Worker   }
406*fb1b10abSAndroid Build Coastguard Worker 
407*fb1b10abSAndroid Build Coastguard Worker   //
408*fb1b10abSAndroid Build Coastguard Worker   // Frame flags and layer id for temporal layers.
409*fb1b10abSAndroid Build Coastguard Worker   //
410*fb1b10abSAndroid Build Coastguard Worker 
411*fb1b10abSAndroid Build Coastguard Worker   // For two layers, test pattern is:
412*fb1b10abSAndroid Build Coastguard Worker   //   1     3
413*fb1b10abSAndroid Build Coastguard Worker   // 0    2     .....
414*fb1b10abSAndroid Build Coastguard Worker   // For three layers, test pattern is:
415*fb1b10abSAndroid Build Coastguard Worker   //   1      3    5      7
416*fb1b10abSAndroid Build Coastguard Worker   //      2           6
417*fb1b10abSAndroid Build Coastguard Worker   // 0          4            ....
418*fb1b10abSAndroid Build Coastguard Worker   // LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
419*fb1b10abSAndroid Build Coastguard Worker   // and ALTREF is updated on top layer for 3 layer pattern.
SetFrameFlags(int frame_num,int num_temp_layers)420*fb1b10abSAndroid Build Coastguard Worker   int SetFrameFlags(int frame_num, int num_temp_layers) {
421*fb1b10abSAndroid Build Coastguard Worker     int frame_flags = 0;
422*fb1b10abSAndroid Build Coastguard Worker     if (num_temp_layers == 2) {
423*fb1b10abSAndroid Build Coastguard Worker       if (frame_num % 2 == 0) {
424*fb1b10abSAndroid Build Coastguard Worker         // Layer 0: predict from L and ARF, update L.
425*fb1b10abSAndroid Build Coastguard Worker         frame_flags =
426*fb1b10abSAndroid Build Coastguard Worker             VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
427*fb1b10abSAndroid Build Coastguard Worker       } else {
428*fb1b10abSAndroid Build Coastguard Worker         // Layer 1: predict from L, G and ARF, and update G.
429*fb1b10abSAndroid Build Coastguard Worker         frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
430*fb1b10abSAndroid Build Coastguard Worker                       VP8_EFLAG_NO_UPD_ENTROPY;
431*fb1b10abSAndroid Build Coastguard Worker       }
432*fb1b10abSAndroid Build Coastguard Worker     } else if (num_temp_layers == 3) {
433*fb1b10abSAndroid Build Coastguard Worker       if (frame_num % 4 == 0) {
434*fb1b10abSAndroid Build Coastguard Worker         // Layer 0: predict from L, update L.
435*fb1b10abSAndroid Build Coastguard Worker         frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
436*fb1b10abSAndroid Build Coastguard Worker                       VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
437*fb1b10abSAndroid Build Coastguard Worker       } else if ((frame_num - 2) % 4 == 0) {
438*fb1b10abSAndroid Build Coastguard Worker         // Layer 1: predict from L, G,  update G.
439*fb1b10abSAndroid Build Coastguard Worker         frame_flags =
440*fb1b10abSAndroid Build Coastguard Worker             VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
441*fb1b10abSAndroid Build Coastguard Worker       } else if ((frame_num - 1) % 2 == 0) {
442*fb1b10abSAndroid Build Coastguard Worker         // Layer 2: predict from L, G, ARF; update ARG.
443*fb1b10abSAndroid Build Coastguard Worker         frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
444*fb1b10abSAndroid Build Coastguard Worker       }
445*fb1b10abSAndroid Build Coastguard Worker     }
446*fb1b10abSAndroid Build Coastguard Worker     return frame_flags;
447*fb1b10abSAndroid Build Coastguard Worker   }
448*fb1b10abSAndroid Build Coastguard Worker 
SetLayerId(int frame_num,int num_temp_layers)449*fb1b10abSAndroid Build Coastguard Worker   int SetLayerId(int frame_num, int num_temp_layers) {
450*fb1b10abSAndroid Build Coastguard Worker     int layer_id = 0;
451*fb1b10abSAndroid Build Coastguard Worker     if (num_temp_layers == 2) {
452*fb1b10abSAndroid Build Coastguard Worker       if (frame_num % 2 == 0) {
453*fb1b10abSAndroid Build Coastguard Worker         layer_id = 0;
454*fb1b10abSAndroid Build Coastguard Worker       } else {
455*fb1b10abSAndroid Build Coastguard Worker         layer_id = 1;
456*fb1b10abSAndroid Build Coastguard Worker       }
457*fb1b10abSAndroid Build Coastguard Worker     } else if (num_temp_layers == 3) {
458*fb1b10abSAndroid Build Coastguard Worker       if (frame_num % 4 == 0) {
459*fb1b10abSAndroid Build Coastguard Worker         layer_id = 0;
460*fb1b10abSAndroid Build Coastguard Worker       } else if ((frame_num - 2) % 4 == 0) {
461*fb1b10abSAndroid Build Coastguard Worker         layer_id = 1;
462*fb1b10abSAndroid Build Coastguard Worker       } else if ((frame_num - 1) % 2 == 0) {
463*fb1b10abSAndroid Build Coastguard Worker         layer_id = 2;
464*fb1b10abSAndroid Build Coastguard Worker       }
465*fb1b10abSAndroid Build Coastguard Worker     }
466*fb1b10abSAndroid Build Coastguard Worker     return layer_id;
467*fb1b10abSAndroid Build Coastguard Worker   }
468*fb1b10abSAndroid Build Coastguard Worker 
PreEncodeFrameHook(libvpx_test::VideoSource * video,libvpx_test::Encoder * encoder)469*fb1b10abSAndroid Build Coastguard Worker   void PreEncodeFrameHook(libvpx_test::VideoSource *video,
470*fb1b10abSAndroid Build Coastguard Worker                           libvpx_test::Encoder *encoder) override {
471*fb1b10abSAndroid Build Coastguard Worker     if (cfg_.ts_number_layers > 1) {
472*fb1b10abSAndroid Build Coastguard Worker       int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
473*fb1b10abSAndroid Build Coastguard Worker       int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
474*fb1b10abSAndroid Build Coastguard Worker       if (video->frame() > 0) {
475*fb1b10abSAndroid Build Coastguard Worker         encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
476*fb1b10abSAndroid Build Coastguard Worker         encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
477*fb1b10abSAndroid Build Coastguard Worker       }
478*fb1b10abSAndroid Build Coastguard Worker       const vpx_rational_t tb = video->timebase();
479*fb1b10abSAndroid Build Coastguard Worker       timebase_ = static_cast<double>(tb.num) / tb.den;
480*fb1b10abSAndroid Build Coastguard Worker       duration_ = 0;
481*fb1b10abSAndroid Build Coastguard Worker       return;
482*fb1b10abSAndroid Build Coastguard Worker     }
483*fb1b10abSAndroid Build Coastguard Worker   }
484*fb1b10abSAndroid Build Coastguard Worker 
FramePktHook(const vpx_codec_cx_pkt_t * pkt)485*fb1b10abSAndroid Build Coastguard Worker   void FramePktHook(const vpx_codec_cx_pkt_t *pkt) override {
486*fb1b10abSAndroid Build Coastguard Worker     // Time since last timestamp = duration.
487*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
488*fb1b10abSAndroid Build Coastguard Worker     if (duration > 1) {
489*fb1b10abSAndroid Build Coastguard Worker       // Update counter for total number of frames (#frames input to encoder).
490*fb1b10abSAndroid Build Coastguard Worker       // Needed for setting the proper layer_id below.
491*fb1b10abSAndroid Build Coastguard Worker       tot_frame_number_ += static_cast<int>(duration - 1);
492*fb1b10abSAndroid Build Coastguard Worker     }
493*fb1b10abSAndroid Build Coastguard Worker     int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
494*fb1b10abSAndroid Build Coastguard Worker     const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
495*fb1b10abSAndroid Build Coastguard Worker     // Update the total encoded bits. For temporal layers, update the cumulative
496*fb1b10abSAndroid Build Coastguard Worker     // encoded bits per layer.
497*fb1b10abSAndroid Build Coastguard Worker     for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
498*fb1b10abSAndroid Build Coastguard Worker       bits_total_[i] += frame_size_in_bits;
499*fb1b10abSAndroid Build Coastguard Worker     }
500*fb1b10abSAndroid Build Coastguard Worker     // Update the most recent pts.
501*fb1b10abSAndroid Build Coastguard Worker     last_pts_ = pkt->data.frame.pts;
502*fb1b10abSAndroid Build Coastguard Worker     ++tot_frame_number_;
503*fb1b10abSAndroid Build Coastguard Worker   }
504*fb1b10abSAndroid Build Coastguard Worker 
EndPassHook()505*fb1b10abSAndroid Build Coastguard Worker   void EndPassHook() override {
506*fb1b10abSAndroid Build Coastguard Worker     duration_ = (last_pts_ + 1) * timebase_;
507*fb1b10abSAndroid Build Coastguard Worker     if (cfg_.ts_number_layers > 1) {
508*fb1b10abSAndroid Build Coastguard Worker       for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
509*fb1b10abSAndroid Build Coastguard Worker            ++layer) {
510*fb1b10abSAndroid Build Coastguard Worker         if (bits_total_[layer]) {
511*fb1b10abSAndroid Build Coastguard Worker           // Effective file datarate:
512*fb1b10abSAndroid Build Coastguard Worker           effective_datarate_[layer] =
513*fb1b10abSAndroid Build Coastguard Worker               (bits_total_[layer] / 1000.0) / duration_;
514*fb1b10abSAndroid Build Coastguard Worker         }
515*fb1b10abSAndroid Build Coastguard Worker       }
516*fb1b10abSAndroid Build Coastguard Worker     }
517*fb1b10abSAndroid Build Coastguard Worker   }
518*fb1b10abSAndroid Build Coastguard Worker 
519*fb1b10abSAndroid Build Coastguard Worker   double effective_datarate_[3];
520*fb1b10abSAndroid Build Coastguard Worker 
521*fb1b10abSAndroid Build Coastguard Worker  private:
522*fb1b10abSAndroid Build Coastguard Worker   libvpx_test::TestMode encoding_mode_;
523*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_pts_t last_pts_;
524*fb1b10abSAndroid Build Coastguard Worker   double timebase_;
525*fb1b10abSAndroid Build Coastguard Worker   int64_t bits_total_[3];
526*fb1b10abSAndroid Build Coastguard Worker   double duration_;
527*fb1b10abSAndroid Build Coastguard Worker   int tot_frame_number_;
528*fb1b10abSAndroid Build Coastguard Worker };
529*fb1b10abSAndroid Build Coastguard Worker 
530*fb1b10abSAndroid Build Coastguard Worker // Check two codec controls used for:
531*fb1b10abSAndroid Build Coastguard Worker // (1) for setting temporal layer id, and (2) for settings encoder flags.
532*fb1b10abSAndroid Build Coastguard Worker // This test invokes those controls for each frame, and verifies encoder/decoder
533*fb1b10abSAndroid Build Coastguard Worker // mismatch and basic rate control response.
534*fb1b10abSAndroid Build Coastguard Worker // TODO(marpan): Maybe move this test to datarate_test.cc.
TEST_P(ErrorResilienceTestLargeCodecControls,CodecControl3TemporalLayers)535*fb1b10abSAndroid Build Coastguard Worker TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
536*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_buf_initial_sz = 500;
537*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_buf_optimal_sz = 500;
538*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_buf_sz = 1000;
539*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_dropframe_thresh = 1;
540*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_min_quantizer = 2;
541*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_max_quantizer = 56;
542*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_end_usage = VPX_CBR;
543*fb1b10abSAndroid Build Coastguard Worker   cfg_.rc_dropframe_thresh = 1;
544*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_lag_in_frames = 0;
545*fb1b10abSAndroid Build Coastguard Worker   cfg_.kf_mode = VPX_KF_DISABLED;
546*fb1b10abSAndroid Build Coastguard Worker   cfg_.g_error_resilient = 1;
547*fb1b10abSAndroid Build Coastguard Worker 
548*fb1b10abSAndroid Build Coastguard Worker   // 3 Temporal layers. Framerate decimation (4, 2, 1).
549*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_number_layers = 3;
550*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[0] = 4;
551*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[1] = 2;
552*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_rate_decimator[2] = 1;
553*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_periodicity = 4;
554*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_layer_id[0] = 0;
555*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_layer_id[1] = 2;
556*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_layer_id[2] = 1;
557*fb1b10abSAndroid Build Coastguard Worker   cfg_.ts_layer_id[3] = 2;
558*fb1b10abSAndroid Build Coastguard Worker 
559*fb1b10abSAndroid Build Coastguard Worker   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
560*fb1b10abSAndroid Build Coastguard Worker                                        30, 1, 0, 200);
561*fb1b10abSAndroid Build Coastguard Worker   for (int i = 200; i <= 800; i += 200) {
562*fb1b10abSAndroid Build Coastguard Worker     cfg_.rc_target_bitrate = i;
563*fb1b10abSAndroid Build Coastguard Worker     Reset();
564*fb1b10abSAndroid Build Coastguard Worker     // 40-20-40 bitrate allocation for 3 temporal layers.
565*fb1b10abSAndroid Build Coastguard Worker     cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
566*fb1b10abSAndroid Build Coastguard Worker     cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
567*fb1b10abSAndroid Build Coastguard Worker     cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
568*fb1b10abSAndroid Build Coastguard Worker     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
569*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
570*fb1b10abSAndroid Build Coastguard Worker       ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
571*fb1b10abSAndroid Build Coastguard Worker           << " The datarate for the file is lower than target by too much, "
572*fb1b10abSAndroid Build Coastguard Worker              "for layer: "
573*fb1b10abSAndroid Build Coastguard Worker           << j;
574*fb1b10abSAndroid Build Coastguard Worker       ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
575*fb1b10abSAndroid Build Coastguard Worker           << " The datarate for the file is greater than target by too much, "
576*fb1b10abSAndroid Build Coastguard Worker              "for layer: "
577*fb1b10abSAndroid Build Coastguard Worker           << j;
578*fb1b10abSAndroid Build Coastguard Worker     }
579*fb1b10abSAndroid Build Coastguard Worker   }
580*fb1b10abSAndroid Build Coastguard Worker }
581*fb1b10abSAndroid Build Coastguard Worker 
582*fb1b10abSAndroid Build Coastguard Worker VP8_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
583*fb1b10abSAndroid Build Coastguard Worker                            ::testing::Values(true));
584*fb1b10abSAndroid Build Coastguard Worker VP8_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLargeCodecControls,
585*fb1b10abSAndroid Build Coastguard Worker                            ONE_PASS_TEST_MODES);
586*fb1b10abSAndroid Build Coastguard Worker VP9_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
587*fb1b10abSAndroid Build Coastguard Worker                            ::testing::Values(true));
588*fb1b10abSAndroid Build Coastguard Worker }  // namespace
589