]> granicus.if.org Git - libvpx/blob - test/datarate_test.cc
vp9 svc: Allow denoising next to highest resolution.
[libvpx] / test / datarate_test.cc
1 /*
2  *  Copyright (c) 2012 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  */
10 #include "./vpx_config.h"
11 #include "third_party/googletest/src/include/gtest/gtest.h"
12 #include "test/codec_factory.h"
13 #include "test/encode_test_driver.h"
14 #include "test/i420_video_source.h"
15 #include "test/util.h"
16 #include "test/y4m_video_source.h"
17 #include "vpx/vpx_codec.h"
18
19 namespace {
20
21 class DatarateTestLarge
22     : public ::libvpx_test::EncoderTest,
23       public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
24  public:
25   DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
26
27   virtual ~DatarateTestLarge() {}
28
29  protected:
30   virtual void SetUp() {
31     InitializeConfig();
32     SetMode(GET_PARAM(1));
33     set_cpu_used_ = GET_PARAM(2);
34     ResetModel();
35   }
36
37   virtual void ResetModel() {
38     last_pts_ = 0;
39     bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
40     frame_number_ = 0;
41     first_drop_ = 0;
42     bits_total_ = 0;
43     duration_ = 0.0;
44     denoiser_offon_test_ = 0;
45     denoiser_offon_period_ = -1;
46     gf_boost_ = 0;
47     use_roi_ = 0;
48   }
49
50   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
51                                   ::libvpx_test::Encoder *encoder) {
52     if (video->frame() == 0) {
53       encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
54       encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
55       encoder->Control(VP8E_SET_GF_CBR_BOOST_PCT, gf_boost_);
56     }
57
58 #if CONFIG_VP8_ENCODER
59     if (use_roi_ == 1) {
60       encoder->Control(VP8E_SET_ROI_MAP, &roi_);
61     }
62 #endif
63
64     if (denoiser_offon_test_) {
65       ASSERT_GT(denoiser_offon_period_, 0)
66           << "denoiser_offon_period_ is not positive.";
67       if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
68         // Flip denoiser_on_ periodically
69         denoiser_on_ ^= 1;
70       }
71       encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
72     }
73
74     const vpx_rational_t tb = video->timebase();
75     timebase_ = static_cast<double>(tb.num) / tb.den;
76     duration_ = 0;
77   }
78
79   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
80     // Time since last timestamp = duration.
81     vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
82
83     // TODO(jimbankoski): Remove these lines when the issue:
84     // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
85     // For now the codec assumes buffer starts at starting buffer rate
86     // plus one frame's time.
87     if (last_pts_ == 0) duration = 1;
88
89     // Add to the buffer the bits we'd expect from a constant bitrate server.
90     bits_in_buffer_model_ += static_cast<int64_t>(
91         duration * timebase_ * cfg_.rc_target_bitrate * 1000);
92
93     /* Test the buffer model here before subtracting the frame. Do so because
94      * the way the leaky bucket model works in libvpx is to allow the buffer to
95      * empty - and then stop showing frames until we've got enough bits to
96      * show one. As noted in comment below (issue 495), this does not currently
97      * apply to key frames. For now exclude key frames in condition below. */
98     const bool key_frame =
99         (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
100     if (!key_frame) {
101       ASSERT_GE(bits_in_buffer_model_, 0)
102           << "Buffer Underrun at frame " << pkt->data.frame.pts;
103     }
104
105     const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
106
107     // Subtract from the buffer the bits associated with a played back frame.
108     bits_in_buffer_model_ -= frame_size_in_bits;
109
110     // Update the running total of bits for end of test datarate checks.
111     bits_total_ += frame_size_in_bits;
112
113     // If first drop not set and we have a drop set it to this time.
114     if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1;
115
116     // Update the most recent pts.
117     last_pts_ = pkt->data.frame.pts;
118
119     // We update this so that we can calculate the datarate minus the last
120     // frame encoded in the file.
121     bits_in_last_frame_ = frame_size_in_bits;
122
123     ++frame_number_;
124   }
125
126   virtual void EndPassHook(void) {
127     if (bits_total_) {
128       const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
129
130       duration_ = (last_pts_ + 1) * timebase_;
131
132       // Effective file datarate includes the time spent prebuffering.
133       effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 /
134                             (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
135
136       file_datarate_ = file_size_in_kb / duration_;
137     }
138   }
139
140   vpx_codec_pts_t last_pts_;
141   int64_t bits_in_buffer_model_;
142   double timebase_;
143   int frame_number_;
144   vpx_codec_pts_t first_drop_;
145   int64_t bits_total_;
146   double duration_;
147   double file_datarate_;
148   double effective_datarate_;
149   int64_t bits_in_last_frame_;
150   int denoiser_on_;
151   int denoiser_offon_test_;
152   int denoiser_offon_period_;
153   int set_cpu_used_;
154   int gf_boost_;
155   int use_roi_;
156   vpx_roi_map_t roi_;
157 };
158
159 #if CONFIG_TEMPORAL_DENOISING
160 // Check basic datarate targeting, for a single bitrate, but loop over the
161 // various denoiser settings.
162 TEST_P(DatarateTestLarge, DenoiserLevels) {
163   cfg_.rc_buf_initial_sz = 500;
164   cfg_.rc_dropframe_thresh = 1;
165   cfg_.rc_max_quantizer = 56;
166   cfg_.rc_end_usage = VPX_CBR;
167   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
168                                        30, 1, 0, 140);
169   for (int j = 1; j < 5; ++j) {
170     // Run over the denoiser levels.
171     // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
172     // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
173     // denoiserOnAggressive, and denoiserOnAdaptive.
174     denoiser_on_ = j;
175     cfg_.rc_target_bitrate = 300;
176     ResetModel();
177     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
178     ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
179         << " The datarate for the file exceeds the target!";
180
181     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
182         << " The datarate for the file missed the target!";
183   }
184 }
185
186 // Check basic datarate targeting, for a single bitrate, when denoiser is off
187 // and on.
188 TEST_P(DatarateTestLarge, DenoiserOffOn) {
189   cfg_.rc_buf_initial_sz = 500;
190   cfg_.rc_dropframe_thresh = 1;
191   cfg_.rc_max_quantizer = 56;
192   cfg_.rc_end_usage = VPX_CBR;
193   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
194                                        30, 1, 0, 299);
195   cfg_.rc_target_bitrate = 300;
196   ResetModel();
197   // The denoiser is off by default.
198   denoiser_on_ = 0;
199   // Set the offon test flag.
200   denoiser_offon_test_ = 1;
201   denoiser_offon_period_ = 100;
202   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
203   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
204       << " The datarate for the file exceeds the target!";
205   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
206       << " The datarate for the file missed the target!";
207 }
208 #endif  // CONFIG_TEMPORAL_DENOISING
209
210 TEST_P(DatarateTestLarge, BasicBufferModel) {
211   denoiser_on_ = 0;
212   cfg_.rc_buf_initial_sz = 500;
213   cfg_.rc_dropframe_thresh = 1;
214   cfg_.rc_max_quantizer = 56;
215   cfg_.rc_end_usage = VPX_CBR;
216   // 2 pass cbr datarate control has a bug hidden by the small # of
217   // frames selected in this encode. The problem is that even if the buffer is
218   // negative we produce a keyframe on a cutscene. Ignoring datarate
219   // constraints
220   // TODO(jimbankoski): ( Fix when issue
221   // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
222   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
223                                        30, 1, 0, 140);
224
225   // There is an issue for low bitrates in real-time mode, where the
226   // effective_datarate slightly overshoots the target bitrate.
227   // This is same the issue as noted about (#495).
228   // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
229   // when the issue is resolved.
230   for (int i = 100; i < 800; i += 200) {
231     cfg_.rc_target_bitrate = i;
232     ResetModel();
233     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
234     ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
235         << " The datarate for the file exceeds the target!";
236     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
237         << " The datarate for the file missed the target!";
238   }
239 }
240
241 TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
242   denoiser_on_ = 0;
243   cfg_.rc_buf_initial_sz = 500;
244   cfg_.rc_max_quantizer = 36;
245   cfg_.rc_end_usage = VPX_CBR;
246   cfg_.rc_target_bitrate = 200;
247   cfg_.kf_mode = VPX_KF_DISABLED;
248
249   const int frame_count = 40;
250   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
251                                        30, 1, 0, frame_count);
252
253   // Here we check that the first dropped frame gets earlier and earlier
254   // as the drop frame threshold is increased.
255
256   const int kDropFrameThreshTestStep = 30;
257   vpx_codec_pts_t last_drop = frame_count;
258   for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
259     cfg_.rc_dropframe_thresh = i;
260     ResetModel();
261     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
262     ASSERT_LE(first_drop_, last_drop)
263         << " The first dropped frame for drop_thresh " << i
264         << " > first dropped frame for drop_thresh "
265         << i - kDropFrameThreshTestStep;
266     last_drop = first_drop_;
267   }
268 }
269
270 TEST_P(DatarateTestLarge, DropFramesMultiThreads) {
271   denoiser_on_ = 0;
272   cfg_.rc_buf_initial_sz = 500;
273   cfg_.rc_dropframe_thresh = 30;
274   cfg_.rc_max_quantizer = 56;
275   cfg_.rc_end_usage = VPX_CBR;
276   cfg_.g_threads = 2;
277
278   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
279                                        30, 1, 0, 140);
280   cfg_.rc_target_bitrate = 200;
281   ResetModel();
282   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
283   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
284       << " The datarate for the file exceeds the target!";
285
286   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
287       << " The datarate for the file missed the target!";
288 }
289
290 class DatarateTestRealTime : public DatarateTestLarge {
291  public:
292   virtual ~DatarateTestRealTime() {}
293 };
294
295 #if CONFIG_TEMPORAL_DENOISING
296 // Check basic datarate targeting, for a single bitrate, but loop over the
297 // various denoiser settings.
298 TEST_P(DatarateTestRealTime, DenoiserLevels) {
299   cfg_.rc_buf_initial_sz = 500;
300   cfg_.rc_dropframe_thresh = 1;
301   cfg_.rc_max_quantizer = 56;
302   cfg_.rc_end_usage = VPX_CBR;
303   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
304                                        30, 1, 0, 140);
305   for (int j = 1; j < 5; ++j) {
306     // Run over the denoiser levels.
307     // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
308     // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
309     // denoiserOnAggressive, and denoiserOnAdaptive.
310     denoiser_on_ = j;
311     cfg_.rc_target_bitrate = 300;
312     ResetModel();
313     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
314     ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
315         << " The datarate for the file exceeds the target!";
316     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
317         << " The datarate for the file missed the target!";
318   }
319 }
320
321 // Check basic datarate targeting, for a single bitrate, when denoiser is off
322 // and on.
323 TEST_P(DatarateTestRealTime, DenoiserOffOn) {
324   cfg_.rc_buf_initial_sz = 500;
325   cfg_.rc_dropframe_thresh = 1;
326   cfg_.rc_max_quantizer = 56;
327   cfg_.rc_end_usage = VPX_CBR;
328   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
329                                        30, 1, 0, 299);
330   cfg_.rc_target_bitrate = 300;
331   ResetModel();
332   // The denoiser is off by default.
333   denoiser_on_ = 0;
334   // Set the offon test flag.
335   denoiser_offon_test_ = 1;
336   denoiser_offon_period_ = 100;
337   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
338   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
339       << " The datarate for the file exceeds the target!";
340   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
341       << " The datarate for the file missed the target!";
342 }
343 #endif  // CONFIG_TEMPORAL_DENOISING
344
345 TEST_P(DatarateTestRealTime, BasicBufferModel) {
346   denoiser_on_ = 0;
347   cfg_.rc_buf_initial_sz = 500;
348   cfg_.rc_dropframe_thresh = 1;
349   cfg_.rc_max_quantizer = 56;
350   cfg_.rc_end_usage = VPX_CBR;
351   // 2 pass cbr datarate control has a bug hidden by the small # of
352   // frames selected in this encode. The problem is that even if the buffer is
353   // negative we produce a keyframe on a cutscene, ignoring datarate
354   // constraints
355   // TODO(jimbankoski): Fix when issue
356   // http://bugs.chromium.org/p/webm/issues/detail?id=495 is addressed.
357   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
358                                        30, 1, 0, 140);
359
360   // There is an issue for low bitrates in real-time mode, where the
361   // effective_datarate slightly overshoots the target bitrate.
362   // This is same the issue as noted above (#495).
363   // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
364   // when the issue is resolved.
365   for (int i = 100; i <= 700; i += 200) {
366     cfg_.rc_target_bitrate = i;
367     ResetModel();
368     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
369     ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
370         << " The datarate for the file exceeds the target!";
371     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
372         << " The datarate for the file missed the target!";
373   }
374 }
375
376 TEST_P(DatarateTestRealTime, ChangingDropFrameThresh) {
377   denoiser_on_ = 0;
378   cfg_.rc_buf_initial_sz = 500;
379   cfg_.rc_max_quantizer = 36;
380   cfg_.rc_end_usage = VPX_CBR;
381   cfg_.rc_target_bitrate = 200;
382   cfg_.kf_mode = VPX_KF_DISABLED;
383
384   const int frame_count = 40;
385   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
386                                        30, 1, 0, frame_count);
387
388   // Check that the first dropped frame gets earlier and earlier
389   // as the drop frame threshold is increased.
390
391   const int kDropFrameThreshTestStep = 30;
392   vpx_codec_pts_t last_drop = frame_count;
393   for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
394     cfg_.rc_dropframe_thresh = i;
395     ResetModel();
396     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
397     ASSERT_LE(first_drop_, last_drop)
398         << " The first dropped frame for drop_thresh " << i
399         << " > first dropped frame for drop_thresh "
400         << i - kDropFrameThreshTestStep;
401     last_drop = first_drop_;
402   }
403 }
404
405 TEST_P(DatarateTestRealTime, DropFramesMultiThreads) {
406   denoiser_on_ = 0;
407   cfg_.rc_buf_initial_sz = 500;
408   cfg_.rc_dropframe_thresh = 30;
409   cfg_.rc_max_quantizer = 56;
410   cfg_.rc_end_usage = VPX_CBR;
411   // Encode using multiple threads.
412   cfg_.g_threads = 2;
413
414   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
415                                        30, 1, 0, 140);
416   cfg_.rc_target_bitrate = 200;
417   ResetModel();
418   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
419   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
420       << " The datarate for the file exceeds the target!";
421
422   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
423       << " The datarate for the file missed the target!";
424 }
425
426 TEST_P(DatarateTestRealTime, RegionOfInterest) {
427   denoiser_on_ = 0;
428   cfg_.rc_buf_initial_sz = 500;
429   cfg_.rc_dropframe_thresh = 0;
430   cfg_.rc_max_quantizer = 56;
431   cfg_.rc_end_usage = VPX_CBR;
432   // Encode using multiple threads.
433   cfg_.g_threads = 2;
434
435   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
436                                        30, 1, 0, 300);
437   cfg_.rc_target_bitrate = 450;
438   cfg_.g_w = 352;
439   cfg_.g_h = 288;
440
441   ResetModel();
442
443   // Set ROI parameters
444   use_roi_ = 1;
445   memset(&roi_, 0, sizeof(roi_));
446
447   roi_.rows = (cfg_.g_h + 15) / 16;
448   roi_.cols = (cfg_.g_w + 15) / 16;
449
450   roi_.delta_q[0] = 0;
451   roi_.delta_q[1] = -20;
452   roi_.delta_q[2] = 0;
453   roi_.delta_q[3] = 0;
454
455   roi_.delta_lf[0] = 0;
456   roi_.delta_lf[1] = -20;
457   roi_.delta_lf[2] = 0;
458   roi_.delta_lf[3] = 0;
459
460   roi_.static_threshold[0] = 0;
461   roi_.static_threshold[1] = 1000;
462   roi_.static_threshold[2] = 0;
463   roi_.static_threshold[3] = 0;
464
465   // Use 2 states: 1 is center square, 0 is the rest.
466   roi_.roi_map =
467       (uint8_t *)calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map));
468   for (unsigned int i = 0; i < roi_.rows; ++i) {
469     for (unsigned int j = 0; j < roi_.cols; ++j) {
470       if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) &&
471           j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) {
472         roi_.roi_map[i * roi_.cols + j] = 1;
473       }
474     }
475   }
476
477   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
478   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
479       << " The datarate for the file exceeds the target!";
480
481   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
482       << " The datarate for the file missed the target!";
483
484   free(roi_.roi_map);
485 }
486
487 TEST_P(DatarateTestRealTime, GFBoost) {
488   denoiser_on_ = 0;
489   cfg_.rc_buf_initial_sz = 500;
490   cfg_.rc_dropframe_thresh = 0;
491   cfg_.rc_max_quantizer = 56;
492   cfg_.rc_end_usage = VPX_CBR;
493   cfg_.g_error_resilient = 0;
494
495   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
496                                        30, 1, 0, 300);
497   cfg_.rc_target_bitrate = 300;
498   ResetModel();
499   // Apply a gf boost.
500   gf_boost_ = 50;
501
502   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
503   ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
504       << " The datarate for the file exceeds the target!";
505
506   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
507       << " The datarate for the file missed the target!";
508 }
509
510 class DatarateTestVP9Large
511     : public ::libvpx_test::EncoderTest,
512       public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
513  public:
514   DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
515
516  protected:
517   virtual ~DatarateTestVP9Large() {}
518
519   virtual void SetUp() {
520     InitializeConfig();
521     SetMode(GET_PARAM(1));
522     set_cpu_used_ = GET_PARAM(2);
523     ResetModel();
524   }
525
526   virtual void ResetModel() {
527     last_pts_ = 0;
528     bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
529     frame_number_ = 0;
530     tot_frame_number_ = 0;
531     first_drop_ = 0;
532     num_drops_ = 0;
533     // Denoiser is off by default.
534     denoiser_on_ = 0;
535     // For testing up to 3 layers.
536     for (int i = 0; i < 3; ++i) {
537       bits_total_[i] = 0;
538     }
539     denoiser_offon_test_ = 0;
540     denoiser_offon_period_ = -1;
541     frame_parallel_decoding_mode_ = 1;
542   }
543
544   //
545   // Frame flags and layer id for temporal layers.
546   //
547
548   // For two layers, test pattern is:
549   //   1     3
550   // 0    2     .....
551   // For three layers, test pattern is:
552   //   1      3    5      7
553   //      2           6
554   // 0          4            ....
555   // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
556   // For this 3 layer example, the 2nd enhancement layer (layer 2) updates
557   // the altref frame.
558   int SetFrameFlags(int frame_num, int num_temp_layers) {
559     int frame_flags = 0;
560     if (num_temp_layers == 2) {
561       if (frame_num % 2 == 0) {
562         // Layer 0: predict from L and ARF, update L.
563         frame_flags =
564             VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
565       } else {
566         // Layer 1: predict from L, G and ARF, and update G.
567         frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
568                       VP8_EFLAG_NO_UPD_ENTROPY;
569       }
570     } else if (num_temp_layers == 3) {
571       if (frame_num % 4 == 0) {
572         // Layer 0: predict from L and ARF; update L.
573         frame_flags =
574             VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
575       } else if ((frame_num - 2) % 4 == 0) {
576         // Layer 1: predict from L, G, ARF; update G.
577         frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
578       } else if ((frame_num - 1) % 2 == 0) {
579         // Layer 2: predict from L, G, ARF; update ARF.
580         frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
581       }
582     }
583     return frame_flags;
584   }
585
586   int SetLayerId(int frame_num, int num_temp_layers) {
587     int layer_id = 0;
588     if (num_temp_layers == 2) {
589       if (frame_num % 2 == 0) {
590         layer_id = 0;
591       } else {
592         layer_id = 1;
593       }
594     } else if (num_temp_layers == 3) {
595       if (frame_num % 4 == 0) {
596         layer_id = 0;
597       } else if ((frame_num - 2) % 4 == 0) {
598         layer_id = 1;
599       } else if ((frame_num - 1) % 2 == 0) {
600         layer_id = 2;
601       }
602     }
603     return layer_id;
604   }
605
606   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
607                                   ::libvpx_test::Encoder *encoder) {
608     if (video->frame() == 0) encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
609
610     if (denoiser_offon_test_) {
611       ASSERT_GT(denoiser_offon_period_, 0)
612           << "denoiser_offon_period_ is not positive.";
613       if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
614         // Flip denoiser_on_ periodically
615         denoiser_on_ ^= 1;
616       }
617     }
618
619     encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
620     encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
621     encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
622                      frame_parallel_decoding_mode_);
623
624     if (cfg_.ts_number_layers > 1) {
625       if (video->frame() == 0) {
626         encoder->Control(VP9E_SET_SVC, 1);
627       }
628       vpx_svc_layer_id_t layer_id;
629       layer_id.spatial_layer_id = 0;
630       frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
631       layer_id.temporal_layer_id =
632           SetLayerId(video->frame(), cfg_.ts_number_layers);
633       encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
634     }
635     const vpx_rational_t tb = video->timebase();
636     timebase_ = static_cast<double>(tb.num) / tb.den;
637     duration_ = 0;
638   }
639
640   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
641     // Time since last timestamp = duration.
642     vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
643
644     if (duration > 1) {
645       // If first drop not set and we have a drop set it to this time.
646       if (!first_drop_) first_drop_ = last_pts_ + 1;
647       // Update the number of frame drops.
648       num_drops_ += static_cast<int>(duration - 1);
649       // Update counter for total number of frames (#frames input to encoder).
650       // Needed for setting the proper layer_id below.
651       tot_frame_number_ += static_cast<int>(duration - 1);
652     }
653
654     int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
655
656     // Add to the buffer the bits we'd expect from a constant bitrate server.
657     bits_in_buffer_model_ += static_cast<int64_t>(
658         duration * timebase_ * cfg_.rc_target_bitrate * 1000);
659
660     // Buffer should not go negative.
661     ASSERT_GE(bits_in_buffer_model_, 0)
662         << "Buffer Underrun at frame " << pkt->data.frame.pts;
663
664     const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
665
666     // Update the total encoded bits. For temporal layers, update the cumulative
667     // encoded bits per layer.
668     for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
669       bits_total_[i] += frame_size_in_bits;
670     }
671
672     // Update the most recent pts.
673     last_pts_ = pkt->data.frame.pts;
674     ++frame_number_;
675     ++tot_frame_number_;
676   }
677
678   virtual void EndPassHook(void) {
679     for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
680          ++layer) {
681       duration_ = (last_pts_ + 1) * timebase_;
682       if (bits_total_[layer]) {
683         // Effective file datarate:
684         effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
685       }
686     }
687   }
688
689   vpx_codec_pts_t last_pts_;
690   double timebase_;
691   int frame_number_;      // Counter for number of non-dropped/encoded frames.
692   int tot_frame_number_;  // Counter for total number of input frames.
693   int64_t bits_total_[3];
694   double duration_;
695   double effective_datarate_[3];
696   int set_cpu_used_;
697   int64_t bits_in_buffer_model_;
698   vpx_codec_pts_t first_drop_;
699   int num_drops_;
700   int denoiser_on_;
701   int denoiser_offon_test_;
702   int denoiser_offon_period_;
703   int frame_parallel_decoding_mode_;
704 };
705
706 // Check basic rate targeting for VBR mode with 0 lag.
707 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagZero) {
708   cfg_.rc_min_quantizer = 0;
709   cfg_.rc_max_quantizer = 63;
710   cfg_.g_error_resilient = 0;
711   cfg_.rc_end_usage = VPX_VBR;
712   cfg_.g_lag_in_frames = 0;
713
714   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
715                                        30, 1, 0, 300);
716   for (int i = 400; i <= 800; i += 400) {
717     cfg_.rc_target_bitrate = i;
718     ResetModel();
719     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
720     ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
721         << " The datarate for the file is lower than target by too much!";
722     ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30)
723         << " The datarate for the file is greater than target by too much!";
724   }
725 }
726
727 // Check basic rate targeting for VBR mode with non-zero lag.
728 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZero) {
729   cfg_.rc_min_quantizer = 0;
730   cfg_.rc_max_quantizer = 63;
731   cfg_.g_error_resilient = 0;
732   cfg_.rc_end_usage = VPX_VBR;
733   // For non-zero lag, rate control will work (be within bounds) for
734   // real-time mode.
735   if (deadline_ == VPX_DL_REALTIME) {
736     cfg_.g_lag_in_frames = 15;
737   } else {
738     cfg_.g_lag_in_frames = 0;
739   }
740
741   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
742                                        30, 1, 0, 300);
743   for (int i = 400; i <= 800; i += 400) {
744     cfg_.rc_target_bitrate = i;
745     ResetModel();
746     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
747     ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
748         << " The datarate for the file is lower than target by too much!";
749     ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30)
750         << " The datarate for the file is greater than target by too much!";
751   }
752 }
753
754 // Check basic rate targeting for VBR mode with non-zero lag, with
755 // frame_parallel_decoding_mode off. This enables the adapt_coeff/mode/mv probs
756 // since error_resilience is off.
757 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZeroFrameParDecOff) {
758   cfg_.rc_min_quantizer = 0;
759   cfg_.rc_max_quantizer = 63;
760   cfg_.g_error_resilient = 0;
761   cfg_.rc_end_usage = VPX_VBR;
762   // For non-zero lag, rate control will work (be within bounds) for
763   // real-time mode.
764   if (deadline_ == VPX_DL_REALTIME) {
765     cfg_.g_lag_in_frames = 15;
766   } else {
767     cfg_.g_lag_in_frames = 0;
768   }
769
770   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
771                                        30, 1, 0, 300);
772   for (int i = 400; i <= 800; i += 400) {
773     cfg_.rc_target_bitrate = i;
774     ResetModel();
775     frame_parallel_decoding_mode_ = 0;
776     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
777     ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
778         << " The datarate for the file is lower than target by too much!";
779     ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30)
780         << " The datarate for the file is greater than target by too much!";
781   }
782 }
783
784 // Check basic rate targeting for CBR mode.
785 TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
786   cfg_.rc_buf_initial_sz = 500;
787   cfg_.rc_buf_optimal_sz = 500;
788   cfg_.rc_buf_sz = 1000;
789   cfg_.rc_dropframe_thresh = 1;
790   cfg_.rc_min_quantizer = 0;
791   cfg_.rc_max_quantizer = 63;
792   cfg_.rc_end_usage = VPX_CBR;
793   cfg_.g_lag_in_frames = 0;
794
795   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
796                                        30, 1, 0, 140);
797   for (int i = 150; i < 800; i += 200) {
798     cfg_.rc_target_bitrate = i;
799     ResetModel();
800     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
801     ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
802         << " The datarate for the file is lower than target by too much!";
803     ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
804         << " The datarate for the file is greater than target by too much!";
805   }
806 }
807
808 // Check basic rate targeting for CBR mode, with frame_parallel_decoding_mode
809 // off( and error_resilience off).
810 TEST_P(DatarateTestVP9Large, BasicRateTargetingFrameParDecOff) {
811   cfg_.rc_buf_initial_sz = 500;
812   cfg_.rc_buf_optimal_sz = 500;
813   cfg_.rc_buf_sz = 1000;
814   cfg_.rc_dropframe_thresh = 1;
815   cfg_.rc_min_quantizer = 0;
816   cfg_.rc_max_quantizer = 63;
817   cfg_.rc_end_usage = VPX_CBR;
818   cfg_.g_lag_in_frames = 0;
819   cfg_.g_error_resilient = 0;
820
821   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
822                                        30, 1, 0, 140);
823   for (int i = 150; i < 800; i += 200) {
824     cfg_.rc_target_bitrate = i;
825     ResetModel();
826     frame_parallel_decoding_mode_ = 0;
827     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
828     ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
829         << " The datarate for the file is lower than target by too much!";
830     ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
831         << " The datarate for the file is greater than target by too much!";
832   }
833 }
834
835 // Check basic rate targeting for CBR mode, with 2 threads and dropped frames.
836 TEST_P(DatarateTestVP9Large, BasicRateTargetingDropFramesMultiThreads) {
837   cfg_.rc_buf_initial_sz = 500;
838   cfg_.rc_buf_optimal_sz = 500;
839   cfg_.rc_buf_sz = 1000;
840   cfg_.rc_dropframe_thresh = 30;
841   cfg_.rc_min_quantizer = 0;
842   cfg_.rc_max_quantizer = 63;
843   cfg_.rc_end_usage = VPX_CBR;
844   cfg_.g_lag_in_frames = 0;
845   // Encode using multiple threads.
846   cfg_.g_threads = 2;
847
848   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
849                                        30, 1, 0, 140);
850   cfg_.rc_target_bitrate = 200;
851   ResetModel();
852   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
853   ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
854       << " The datarate for the file is lower than target by too much!";
855   ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
856       << " The datarate for the file is greater than target by too much!";
857 }
858
859 // Check basic rate targeting for CBR.
860 TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
861   ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
862
863   cfg_.g_profile = 1;
864   cfg_.g_timebase = video.timebase();
865
866   cfg_.rc_buf_initial_sz = 500;
867   cfg_.rc_buf_optimal_sz = 500;
868   cfg_.rc_buf_sz = 1000;
869   cfg_.rc_dropframe_thresh = 1;
870   cfg_.rc_min_quantizer = 0;
871   cfg_.rc_max_quantizer = 63;
872   cfg_.rc_end_usage = VPX_CBR;
873
874   for (int i = 250; i < 900; i += 200) {
875     cfg_.rc_target_bitrate = i;
876     ResetModel();
877     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
878     ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
879               effective_datarate_[0] * 0.80)
880         << " The datarate for the file exceeds the target by too much!";
881     ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
882               effective_datarate_[0] * 1.15)
883         << " The datarate for the file missed the target!"
884         << cfg_.rc_target_bitrate << " " << effective_datarate_;
885   }
886 }
887
888 // Check that (1) the first dropped frame gets earlier and earlier
889 // as the drop frame threshold is increased, and (2) that the total number of
890 // frame drops does not decrease as we increase frame drop threshold.
891 // Use a lower qp-max to force some frame drops.
892 TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
893   cfg_.rc_buf_initial_sz = 500;
894   cfg_.rc_buf_optimal_sz = 500;
895   cfg_.rc_buf_sz = 1000;
896   cfg_.rc_undershoot_pct = 20;
897   cfg_.rc_undershoot_pct = 20;
898   cfg_.rc_dropframe_thresh = 10;
899   cfg_.rc_min_quantizer = 0;
900   cfg_.rc_max_quantizer = 50;
901   cfg_.rc_end_usage = VPX_CBR;
902   cfg_.rc_target_bitrate = 200;
903   cfg_.g_lag_in_frames = 0;
904   // TODO(marpan): Investigate datarate target failures with a smaller keyframe
905   // interval (128).
906   cfg_.kf_max_dist = 9999;
907
908   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
909                                        30, 1, 0, 140);
910
911   const int kDropFrameThreshTestStep = 30;
912   for (int j = 50; j <= 150; j += 100) {
913     cfg_.rc_target_bitrate = j;
914     vpx_codec_pts_t last_drop = 140;
915     int last_num_drops = 0;
916     for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
917       cfg_.rc_dropframe_thresh = i;
918       ResetModel();
919       ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
920       ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
921           << " The datarate for the file is lower than target by too much!";
922       ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
923           << " The datarate for the file is greater than target by too much!";
924       ASSERT_LE(first_drop_, last_drop)
925           << " The first dropped frame for drop_thresh " << i
926           << " > first dropped frame for drop_thresh "
927           << i - kDropFrameThreshTestStep;
928       ASSERT_GE(num_drops_, last_num_drops * 0.85)
929           << " The number of dropped frames for drop_thresh " << i
930           << " < number of dropped frames for drop_thresh "
931           << i - kDropFrameThreshTestStep;
932       last_drop = first_drop_;
933       last_num_drops = num_drops_;
934     }
935   }
936 }
937
938 // Check basic rate targeting for 2 temporal layers.
939 TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
940   cfg_.rc_buf_initial_sz = 500;
941   cfg_.rc_buf_optimal_sz = 500;
942   cfg_.rc_buf_sz = 1000;
943   cfg_.rc_dropframe_thresh = 1;
944   cfg_.rc_min_quantizer = 0;
945   cfg_.rc_max_quantizer = 63;
946   cfg_.rc_end_usage = VPX_CBR;
947   cfg_.g_lag_in_frames = 0;
948
949   // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
950   cfg_.ss_number_layers = 1;
951   cfg_.ts_number_layers = 2;
952   cfg_.ts_rate_decimator[0] = 2;
953   cfg_.ts_rate_decimator[1] = 1;
954
955   cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
956
957   if (deadline_ == VPX_DL_REALTIME) cfg_.g_error_resilient = 1;
958
959   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
960                                        30, 1, 0, 200);
961   for (int i = 200; i <= 800; i += 200) {
962     cfg_.rc_target_bitrate = i;
963     ResetModel();
964     // 60-40 bitrate allocation for 2 temporal layers.
965     cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
966     cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
967     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
968     for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
969       ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
970           << " The datarate for the file is lower than target by too much, "
971              "for layer: "
972           << j;
973       ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
974           << " The datarate for the file is greater than target by too much, "
975              "for layer: "
976           << j;
977     }
978   }
979 }
980
981 // Check basic rate targeting for 3 temporal layers.
982 TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
983   cfg_.rc_buf_initial_sz = 500;
984   cfg_.rc_buf_optimal_sz = 500;
985   cfg_.rc_buf_sz = 1000;
986   cfg_.rc_dropframe_thresh = 1;
987   cfg_.rc_min_quantizer = 0;
988   cfg_.rc_max_quantizer = 63;
989   cfg_.rc_end_usage = VPX_CBR;
990   cfg_.g_lag_in_frames = 0;
991
992   // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
993   cfg_.ss_number_layers = 1;
994   cfg_.ts_number_layers = 3;
995   cfg_.ts_rate_decimator[0] = 4;
996   cfg_.ts_rate_decimator[1] = 2;
997   cfg_.ts_rate_decimator[2] = 1;
998
999   cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
1000
1001   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1002                                        30, 1, 0, 200);
1003   for (int i = 200; i <= 800; i += 200) {
1004     cfg_.rc_target_bitrate = i;
1005     ResetModel();
1006     // 40-20-40 bitrate allocation for 3 temporal layers.
1007     cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
1008     cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
1009     cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
1010     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1011     for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
1012       // TODO(yaowu): Work out more stable rc control strategy and
1013       //              Adjust the thresholds to be tighter than .75.
1014       ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
1015           << " The datarate for the file is lower than target by too much, "
1016              "for layer: "
1017           << j;
1018       // TODO(yaowu): Work out more stable rc control strategy and
1019       //              Adjust the thresholds to be tighter than 1.25.
1020       ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
1021           << " The datarate for the file is greater than target by too much, "
1022              "for layer: "
1023           << j;
1024     }
1025   }
1026 }
1027
1028 // Check basic rate targeting for 3 temporal layers, with frame dropping.
1029 // Only for one (low) bitrate with lower max_quantizer, and somewhat higher
1030 // frame drop threshold, to force frame dropping.
1031 TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
1032   cfg_.rc_buf_initial_sz = 500;
1033   cfg_.rc_buf_optimal_sz = 500;
1034   cfg_.rc_buf_sz = 1000;
1035   // Set frame drop threshold and rc_max_quantizer to force some frame drops.
1036   cfg_.rc_dropframe_thresh = 20;
1037   cfg_.rc_max_quantizer = 45;
1038   cfg_.rc_min_quantizer = 0;
1039   cfg_.rc_end_usage = VPX_CBR;
1040   cfg_.g_lag_in_frames = 0;
1041
1042   // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
1043   cfg_.ss_number_layers = 1;
1044   cfg_.ts_number_layers = 3;
1045   cfg_.ts_rate_decimator[0] = 4;
1046   cfg_.ts_rate_decimator[1] = 2;
1047   cfg_.ts_rate_decimator[2] = 1;
1048
1049   cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
1050
1051   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1052                                        30, 1, 0, 200);
1053   cfg_.rc_target_bitrate = 200;
1054   ResetModel();
1055   // 40-20-40 bitrate allocation for 3 temporal layers.
1056   cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
1057   cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
1058   cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
1059   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1060   for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
1061     ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
1062         << " The datarate for the file is lower than target by too much, "
1063            "for layer: "
1064         << j;
1065     ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
1066         << " The datarate for the file is greater than target by too much, "
1067            "for layer: "
1068         << j;
1069     // Expect some frame drops in this test: for this 200 frames test,
1070     // expect at least 10% and not more than 60% drops.
1071     ASSERT_GE(num_drops_, 20);
1072     ASSERT_LE(num_drops_, 130);
1073   }
1074 }
1075
1076 #if CONFIG_VP9_TEMPORAL_DENOISING
1077 class DatarateTestVP9LargeDenoiser : public DatarateTestVP9Large {
1078  public:
1079   virtual ~DatarateTestVP9LargeDenoiser() {}
1080 };
1081
1082 // Check basic datarate targeting, for a single bitrate, when denoiser is on.
1083 TEST_P(DatarateTestVP9LargeDenoiser, LowNoise) {
1084   cfg_.rc_buf_initial_sz = 500;
1085   cfg_.rc_buf_optimal_sz = 500;
1086   cfg_.rc_buf_sz = 1000;
1087   cfg_.rc_dropframe_thresh = 1;
1088   cfg_.rc_min_quantizer = 2;
1089   cfg_.rc_max_quantizer = 56;
1090   cfg_.rc_end_usage = VPX_CBR;
1091   cfg_.g_lag_in_frames = 0;
1092
1093   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1094                                        30, 1, 0, 140);
1095
1096   // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
1097   // there is only one denoiser mode: denoiserYonly(which is 1),
1098   // but may add more modes in the future.
1099   cfg_.rc_target_bitrate = 300;
1100   ResetModel();
1101   // Turn on the denoiser.
1102   denoiser_on_ = 1;
1103   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1104   ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
1105       << " The datarate for the file is lower than target by too much!";
1106   ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
1107       << " The datarate for the file is greater than target by too much!";
1108 }
1109
1110 // Check basic datarate targeting, for a single bitrate, when denoiser is on,
1111 // for clip with high noise level. Use 2 threads.
1112 TEST_P(DatarateTestVP9LargeDenoiser, HighNoise) {
1113   cfg_.rc_buf_initial_sz = 500;
1114   cfg_.rc_buf_optimal_sz = 500;
1115   cfg_.rc_buf_sz = 1000;
1116   cfg_.rc_dropframe_thresh = 1;
1117   cfg_.rc_min_quantizer = 2;
1118   cfg_.rc_max_quantizer = 56;
1119   cfg_.rc_end_usage = VPX_CBR;
1120   cfg_.g_lag_in_frames = 0;
1121   cfg_.g_threads = 2;
1122
1123   ::libvpx_test::Y4mVideoSource video("noisy_clip_640_360.y4m", 0, 200);
1124
1125   // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
1126   // there is only one denoiser mode: kDenoiserOnYOnly(which is 1),
1127   // but may add more modes in the future.
1128   cfg_.rc_target_bitrate = 1000;
1129   ResetModel();
1130   // Turn on the denoiser.
1131   denoiser_on_ = 1;
1132   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1133   ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
1134       << " The datarate for the file is lower than target by too much!";
1135   ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
1136       << " The datarate for the file is greater than target by too much!";
1137 }
1138
1139 // Check basic datarate targeting, for a single bitrate, when denoiser is on,
1140 // for 1280x720 clip with 4 threads.
1141 TEST_P(DatarateTestVP9LargeDenoiser, 4threads) {
1142   cfg_.rc_buf_initial_sz = 500;
1143   cfg_.rc_buf_optimal_sz = 500;
1144   cfg_.rc_buf_sz = 1000;
1145   cfg_.rc_dropframe_thresh = 1;
1146   cfg_.rc_min_quantizer = 2;
1147   cfg_.rc_max_quantizer = 56;
1148   cfg_.rc_end_usage = VPX_CBR;
1149   cfg_.g_lag_in_frames = 0;
1150   cfg_.g_threads = 4;
1151
1152   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1153
1154   // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
1155   // there is only one denoiser mode: denoiserYonly(which is 1),
1156   // but may add more modes in the future.
1157   cfg_.rc_target_bitrate = 1000;
1158   ResetModel();
1159   // Turn on the denoiser.
1160   denoiser_on_ = 1;
1161   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1162   ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
1163       << " The datarate for the file is lower than target by too much!";
1164   ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.29)
1165       << " The datarate for the file is greater than target by too much!";
1166 }
1167
1168 // Check basic datarate targeting, for a single bitrate, when denoiser is off
1169 // and on.
1170 TEST_P(DatarateTestVP9LargeDenoiser, DenoiserOffOn) {
1171   cfg_.rc_buf_initial_sz = 500;
1172   cfg_.rc_buf_optimal_sz = 500;
1173   cfg_.rc_buf_sz = 1000;
1174   cfg_.rc_dropframe_thresh = 1;
1175   cfg_.rc_min_quantizer = 2;
1176   cfg_.rc_max_quantizer = 56;
1177   cfg_.rc_end_usage = VPX_CBR;
1178   cfg_.g_lag_in_frames = 0;
1179
1180   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1181                                        30, 1, 0, 299);
1182
1183   // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
1184   // there is only one denoiser mode: denoiserYonly(which is 1),
1185   // but may add more modes in the future.
1186   cfg_.rc_target_bitrate = 300;
1187   ResetModel();
1188   // The denoiser is off by default.
1189   denoiser_on_ = 0;
1190   // Set the offon test flag.
1191   denoiser_offon_test_ = 1;
1192   denoiser_offon_period_ = 100;
1193   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1194   ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
1195       << " The datarate for the file is lower than target by too much!";
1196   ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
1197       << " The datarate for the file is greater than target by too much!";
1198 }
1199 #endif  // CONFIG_VP9_TEMPORAL_DENOISING
1200
1201 class DatarateOnePassCbrSvc
1202     : public ::libvpx_test::EncoderTest,
1203       public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
1204  public:
1205   DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {
1206     memset(&svc_params_, 0, sizeof(svc_params_));
1207   }
1208   virtual ~DatarateOnePassCbrSvc() {}
1209
1210  protected:
1211   virtual void SetUp() {
1212     InitializeConfig();
1213     SetMode(GET_PARAM(1));
1214     speed_setting_ = GET_PARAM(2);
1215     ResetModel();
1216   }
1217   virtual void ResetModel() {
1218     last_pts_ = 0;
1219     bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
1220     frame_number_ = 0;
1221     first_drop_ = 0;
1222     bits_total_ = 0;
1223     duration_ = 0.0;
1224     mismatch_psnr_ = 0.0;
1225     mismatch_nframes_ = 0;
1226     denoiser_on_ = 0;
1227     tune_content_ = 0;
1228     base_speed_setting_ = 5;
1229   }
1230   virtual void BeginPassHook(unsigned int /*pass*/) {}
1231   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
1232                                   ::libvpx_test::Encoder *encoder) {
1233     if (video->frame() == 0) {
1234       int i;
1235       for (i = 0; i < VPX_MAX_LAYERS; ++i) {
1236         svc_params_.max_quantizers[i] = 63;
1237         svc_params_.min_quantizers[i] = 0;
1238       }
1239       svc_params_.speed_per_layer[0] = base_speed_setting_;
1240       for (i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
1241         svc_params_.speed_per_layer[i] = speed_setting_;
1242       }
1243
1244       encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
1245       encoder->Control(VP9E_SET_SVC, 1);
1246       encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
1247       encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
1248       encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
1249       encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
1250       encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
1251       encoder->Control(VP9E_SET_ROW_MT, 1);
1252       encoder->Control(VP8E_SET_STATIC_THRESHOLD, 1);
1253       encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_);
1254     }
1255     const vpx_rational_t tb = video->timebase();
1256     timebase_ = static_cast<double>(tb.num) / tb.den;
1257     duration_ = 0;
1258   }
1259   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
1260     vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
1261     if (last_pts_ == 0) duration = 1;
1262     bits_in_buffer_model_ += static_cast<int64_t>(
1263         duration * timebase_ * cfg_.rc_target_bitrate * 1000);
1264     const bool key_frame =
1265         (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
1266     if (!key_frame) {
1267       // TODO(marpan): This check currently fails for some of the SVC tests,
1268       // re-enable when issue (webm:1350) is resolved.
1269       //  ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
1270       //                                      << pkt->data.frame.pts;
1271     }
1272     const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
1273     bits_in_buffer_model_ -= static_cast<int64_t>(frame_size_in_bits);
1274     bits_total_ += frame_size_in_bits;
1275     if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1;
1276     last_pts_ = pkt->data.frame.pts;
1277     bits_in_last_frame_ = frame_size_in_bits;
1278     ++frame_number_;
1279   }
1280   virtual void EndPassHook(void) {
1281     if (bits_total_) {
1282       const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
1283       duration_ = (last_pts_ + 1) * timebase_;
1284       file_datarate_ = file_size_in_kb / duration_;
1285     }
1286   }
1287
1288   virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
1289     double mismatch_psnr = compute_psnr(img1, img2);
1290     mismatch_psnr_ += mismatch_psnr;
1291     ++mismatch_nframes_;
1292   }
1293
1294   unsigned int GetMismatchFrames() { return mismatch_nframes_; }
1295
1296   vpx_codec_pts_t last_pts_;
1297   int64_t bits_in_buffer_model_;
1298   double timebase_;
1299   int frame_number_;
1300   vpx_codec_pts_t first_drop_;
1301   int64_t bits_total_;
1302   double duration_;
1303   double file_datarate_;
1304   size_t bits_in_last_frame_;
1305   vpx_svc_extra_cfg_t svc_params_;
1306   int speed_setting_;
1307   double mismatch_psnr_;
1308   int mismatch_nframes_;
1309   int denoiser_on_;
1310   int tune_content_;
1311   int base_speed_setting_;
1312 };
1313 static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg,
1314                                   const vpx_svc_extra_cfg_t *svc_params,
1315                                   int spatial_layers, int temporal_layers,
1316                                   int temporal_layering_mode) {
1317   int sl, spatial_layer_target;
1318   float total = 0;
1319   float alloc_ratio[VPX_MAX_LAYERS] = { 0 };
1320   for (sl = 0; sl < spatial_layers; ++sl) {
1321     if (svc_params->scaling_factor_den[sl] > 0) {
1322       alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] * 1.0 /
1323                                 svc_params->scaling_factor_den[sl]);
1324       total += alloc_ratio[sl];
1325     }
1326   }
1327   for (sl = 0; sl < spatial_layers; ++sl) {
1328     enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
1329         (unsigned int)(enc_cfg->rc_target_bitrate * alloc_ratio[sl] / total);
1330     const int index = sl * temporal_layers;
1331     if (temporal_layering_mode == 3) {
1332       enc_cfg->layer_target_bitrate[index] = spatial_layer_target >> 1;
1333       enc_cfg->layer_target_bitrate[index + 1] =
1334           (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
1335       enc_cfg->layer_target_bitrate[index + 2] = spatial_layer_target;
1336     } else if (temporal_layering_mode == 2) {
1337       enc_cfg->layer_target_bitrate[index] = spatial_layer_target * 2 / 3;
1338       enc_cfg->layer_target_bitrate[index + 1] = spatial_layer_target;
1339     }
1340   }
1341 }
1342
1343 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1
1344 // temporal layer, with screen content mode on and same speed setting for all
1345 // layers.
1346 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TLScreenContent1) {
1347   cfg_.rc_buf_initial_sz = 500;
1348   cfg_.rc_buf_optimal_sz = 500;
1349   cfg_.rc_buf_sz = 1000;
1350   cfg_.rc_min_quantizer = 0;
1351   cfg_.rc_max_quantizer = 63;
1352   cfg_.rc_end_usage = VPX_CBR;
1353   cfg_.g_lag_in_frames = 0;
1354   cfg_.ss_number_layers = 2;
1355   cfg_.ts_number_layers = 1;
1356   cfg_.ts_rate_decimator[0] = 1;
1357   cfg_.g_error_resilient = 1;
1358   cfg_.g_threads = 1;
1359   cfg_.temporal_layering_mode = 0;
1360   svc_params_.scaling_factor_num[0] = 144;
1361   svc_params_.scaling_factor_den[0] = 288;
1362   svc_params_.scaling_factor_num[1] = 288;
1363   svc_params_.scaling_factor_den[1] = 288;
1364   cfg_.rc_dropframe_thresh = 10;
1365   cfg_.kf_max_dist = 9999;
1366   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1367   cfg_.rc_target_bitrate = 500;
1368   ResetModel();
1369   tune_content_ = 1;
1370   base_speed_setting_ = speed_setting_;
1371   assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1372                         cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1373   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1374   EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
1375 }
1376
1377 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
1378 // 3 temporal layers. Run CIF clip with 1 thread.
1379 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) {
1380   cfg_.rc_buf_initial_sz = 500;
1381   cfg_.rc_buf_optimal_sz = 500;
1382   cfg_.rc_buf_sz = 1000;
1383   cfg_.rc_min_quantizer = 0;
1384   cfg_.rc_max_quantizer = 63;
1385   cfg_.rc_end_usage = VPX_CBR;
1386   cfg_.g_lag_in_frames = 0;
1387   cfg_.ss_number_layers = 2;
1388   cfg_.ts_number_layers = 3;
1389   cfg_.ts_rate_decimator[0] = 4;
1390   cfg_.ts_rate_decimator[1] = 2;
1391   cfg_.ts_rate_decimator[2] = 1;
1392   cfg_.g_error_resilient = 1;
1393   cfg_.g_threads = 1;
1394   cfg_.temporal_layering_mode = 3;
1395   svc_params_.scaling_factor_num[0] = 144;
1396   svc_params_.scaling_factor_den[0] = 288;
1397   svc_params_.scaling_factor_num[1] = 288;
1398   svc_params_.scaling_factor_den[1] = 288;
1399   cfg_.rc_dropframe_thresh = 0;
1400   cfg_.kf_max_dist = 9999;
1401   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1402                                        30, 1, 0, 200);
1403   // TODO(marpan): Check that effective_datarate for each layer hits the
1404   // layer target_bitrate.
1405   for (int i = 200; i <= 800; i += 200) {
1406     cfg_.rc_target_bitrate = i;
1407     ResetModel();
1408     assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1409                           cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1410     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1411     ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78)
1412         << " The datarate for the file exceeds the target by too much!";
1413     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
1414         << " The datarate for the file is lower than the target by too much!";
1415 #if CONFIG_VP9_DECODER
1416     // Number of temporal layers > 1, so half of the frames in this SVC pattern
1417     // will be non-reference frame and hence encoder will avoid loopfilter.
1418     // Since frame dropper is off, we can expcet 100 (half of the sequence)
1419     // mismatched frames.
1420     EXPECT_EQ(static_cast<unsigned int>(100), GetMismatchFrames());
1421 #endif
1422   }
1423 }
1424
1425 // Check basic rate targeting for 1 pass CBR SVC with denoising.
1426 // 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads.
1427 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) {
1428   cfg_.rc_buf_initial_sz = 500;
1429   cfg_.rc_buf_optimal_sz = 500;
1430   cfg_.rc_buf_sz = 1000;
1431   cfg_.rc_min_quantizer = 0;
1432   cfg_.rc_max_quantizer = 63;
1433   cfg_.rc_end_usage = VPX_CBR;
1434   cfg_.g_lag_in_frames = 0;
1435   cfg_.ss_number_layers = 2;
1436   cfg_.ts_number_layers = 3;
1437   cfg_.ts_rate_decimator[0] = 4;
1438   cfg_.ts_rate_decimator[1] = 2;
1439   cfg_.ts_rate_decimator[2] = 1;
1440   cfg_.g_error_resilient = 1;
1441   cfg_.g_threads = 2;
1442   cfg_.temporal_layering_mode = 3;
1443   svc_params_.scaling_factor_num[0] = 144;
1444   svc_params_.scaling_factor_den[0] = 288;
1445   svc_params_.scaling_factor_num[1] = 288;
1446   svc_params_.scaling_factor_den[1] = 288;
1447   cfg_.rc_dropframe_thresh = 0;
1448   cfg_.kf_max_dist = 9999;
1449   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1450   // TODO(marpan): Check that effective_datarate for each layer hits the
1451   // layer target_bitrate.
1452   // For SVC, noise_sen = 1 means denoising only the top spatial layer
1453   // noise_sen = 2 means denoising the two top spatial layers.
1454   for (int noise_sen = 1; noise_sen <= 2; noise_sen++) {
1455     for (int i = 600; i <= 1000; i += 200) {
1456       cfg_.rc_target_bitrate = i;
1457       ResetModel();
1458       denoiser_on_ = noise_sen;
1459       assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1460                             cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1461       ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1462       ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78)
1463           << " The datarate for the file exceeds the target by too much!";
1464       ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
1465           << " The datarate for the file is lower than the target by too much!";
1466 #if CONFIG_VP9_DECODER
1467       // Number of temporal layers > 1, so half of the frames in this SVC
1468       // pattern
1469       // will be non-reference frame and hence encoder will avoid loopfilter.
1470       // Since frame dropper is off, we can expcet 150 (half of the sequence)
1471       // mismatched frames.
1472       EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
1473 #endif
1474     }
1475   }
1476 }
1477
1478 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
1479 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
1480 TEST_P(DatarateOnePassCbrSvc, DISABLED_OnePassCbrSvc2SL3TLSmallKf) {
1481   cfg_.rc_buf_initial_sz = 500;
1482   cfg_.rc_buf_optimal_sz = 500;
1483   cfg_.rc_buf_sz = 1000;
1484   cfg_.rc_min_quantizer = 0;
1485   cfg_.rc_max_quantizer = 63;
1486   cfg_.rc_end_usage = VPX_CBR;
1487   cfg_.g_lag_in_frames = 0;
1488   cfg_.ss_number_layers = 2;
1489   cfg_.ts_number_layers = 3;
1490   cfg_.ts_rate_decimator[0] = 4;
1491   cfg_.ts_rate_decimator[1] = 2;
1492   cfg_.ts_rate_decimator[2] = 1;
1493   cfg_.g_error_resilient = 1;
1494   cfg_.g_threads = 1;
1495   cfg_.temporal_layering_mode = 3;
1496   svc_params_.scaling_factor_num[0] = 144;
1497   svc_params_.scaling_factor_den[0] = 288;
1498   svc_params_.scaling_factor_num[1] = 288;
1499   svc_params_.scaling_factor_den[1] = 288;
1500   cfg_.rc_dropframe_thresh = 10;
1501   ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1502                                        30, 1, 0, 200);
1503   cfg_.rc_target_bitrate = 400;
1504   // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
1505   // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
1506   for (int j = 64; j <= 67; j++) {
1507     cfg_.kf_max_dist = j;
1508     ResetModel();
1509     assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1510                           cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1511     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1512     ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.80)
1513         << " The datarate for the file exceeds the target by too much!";
1514     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
1515         << " The datarate for the file is lower than the target by too much!";
1516   }
1517 }
1518
1519 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
1520 // 3 temporal layers. Run HD clip with 4 threads.
1521 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL4Threads) {
1522   cfg_.rc_buf_initial_sz = 500;
1523   cfg_.rc_buf_optimal_sz = 500;
1524   cfg_.rc_buf_sz = 1000;
1525   cfg_.rc_min_quantizer = 0;
1526   cfg_.rc_max_quantizer = 63;
1527   cfg_.rc_end_usage = VPX_CBR;
1528   cfg_.g_lag_in_frames = 0;
1529   cfg_.ss_number_layers = 2;
1530   cfg_.ts_number_layers = 3;
1531   cfg_.ts_rate_decimator[0] = 4;
1532   cfg_.ts_rate_decimator[1] = 2;
1533   cfg_.ts_rate_decimator[2] = 1;
1534   cfg_.g_error_resilient = 1;
1535   cfg_.g_threads = 4;
1536   cfg_.temporal_layering_mode = 3;
1537   svc_params_.scaling_factor_num[0] = 144;
1538   svc_params_.scaling_factor_den[0] = 288;
1539   svc_params_.scaling_factor_num[1] = 288;
1540   svc_params_.scaling_factor_den[1] = 288;
1541   cfg_.rc_dropframe_thresh = 0;
1542   cfg_.kf_max_dist = 9999;
1543   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1544   cfg_.rc_target_bitrate = 800;
1545   ResetModel();
1546   assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1547                         cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1548   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1549   ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78)
1550       << " The datarate for the file exceeds the target by too much!";
1551   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
1552       << " The datarate for the file is lower than the target by too much!";
1553 #if CONFIG_VP9_DECODER
1554   // Number of temporal layers > 1, so half of the frames in this SVC pattern
1555   // will be non-reference frame and hence encoder will avoid loopfilter.
1556   // Since frame dropper is off, we can expcet 150 (half of the sequence)
1557   // mismatched frames.
1558   EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
1559 #endif
1560 }
1561
1562 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
1563 // 3 temporal layers. Run CIF clip with 1 thread.
1564 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL) {
1565   cfg_.rc_buf_initial_sz = 500;
1566   cfg_.rc_buf_optimal_sz = 500;
1567   cfg_.rc_buf_sz = 1000;
1568   cfg_.rc_min_quantizer = 0;
1569   cfg_.rc_max_quantizer = 63;
1570   cfg_.rc_end_usage = VPX_CBR;
1571   cfg_.g_lag_in_frames = 0;
1572   cfg_.ss_number_layers = 3;
1573   cfg_.ts_number_layers = 3;
1574   cfg_.ts_rate_decimator[0] = 4;
1575   cfg_.ts_rate_decimator[1] = 2;
1576   cfg_.ts_rate_decimator[2] = 1;
1577   cfg_.g_error_resilient = 1;
1578   cfg_.g_threads = 1;
1579   cfg_.temporal_layering_mode = 3;
1580   svc_params_.scaling_factor_num[0] = 72;
1581   svc_params_.scaling_factor_den[0] = 288;
1582   svc_params_.scaling_factor_num[1] = 144;
1583   svc_params_.scaling_factor_den[1] = 288;
1584   svc_params_.scaling_factor_num[2] = 288;
1585   svc_params_.scaling_factor_den[2] = 288;
1586   cfg_.rc_dropframe_thresh = 0;
1587   cfg_.kf_max_dist = 9999;
1588   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1589   cfg_.rc_target_bitrate = 800;
1590   ResetModel();
1591   assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1592                         cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1593   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1594   ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78)
1595       << " The datarate for the file exceeds the target by too much!";
1596   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
1597       << " The datarate for the file is lower than the target by too much!";
1598 #if CONFIG_VP9_DECODER
1599   // Number of temporal layers > 1, so half of the frames in this SVC pattern
1600   // will be non-reference frame and hence encoder will avoid loopfilter.
1601   // Since frame dropper is off, we can expcet 150 (half of the sequence)
1602   // mismatched frames.
1603   EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
1604 #endif
1605 }
1606
1607 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
1608 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
1609 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) {
1610   cfg_.rc_buf_initial_sz = 500;
1611   cfg_.rc_buf_optimal_sz = 500;
1612   cfg_.rc_buf_sz = 1000;
1613   cfg_.rc_min_quantizer = 0;
1614   cfg_.rc_max_quantizer = 63;
1615   cfg_.rc_end_usage = VPX_CBR;
1616   cfg_.g_lag_in_frames = 0;
1617   cfg_.ss_number_layers = 3;
1618   cfg_.ts_number_layers = 3;
1619   cfg_.ts_rate_decimator[0] = 4;
1620   cfg_.ts_rate_decimator[1] = 2;
1621   cfg_.ts_rate_decimator[2] = 1;
1622   cfg_.g_error_resilient = 1;
1623   cfg_.g_threads = 1;
1624   cfg_.temporal_layering_mode = 3;
1625   svc_params_.scaling_factor_num[0] = 72;
1626   svc_params_.scaling_factor_den[0] = 288;
1627   svc_params_.scaling_factor_num[1] = 144;
1628   svc_params_.scaling_factor_den[1] = 288;
1629   svc_params_.scaling_factor_num[2] = 288;
1630   svc_params_.scaling_factor_den[2] = 288;
1631   cfg_.rc_dropframe_thresh = 10;
1632   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1633   cfg_.rc_target_bitrate = 800;
1634   // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
1635   // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
1636   for (int j = 32; j <= 35; j++) {
1637     cfg_.kf_max_dist = j;
1638     ResetModel();
1639     assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1640                           cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1641     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1642     ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.80)
1643         << " The datarate for the file exceeds the target by too much!";
1644     ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30)
1645         << " The datarate for the file is lower than the target by too much!";
1646   }
1647 }
1648
1649 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
1650 // 3 temporal layers. Run HD clip with 4 threads.
1651 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL4threads) {
1652   cfg_.rc_buf_initial_sz = 500;
1653   cfg_.rc_buf_optimal_sz = 500;
1654   cfg_.rc_buf_sz = 1000;
1655   cfg_.rc_min_quantizer = 0;
1656   cfg_.rc_max_quantizer = 63;
1657   cfg_.rc_end_usage = VPX_CBR;
1658   cfg_.g_lag_in_frames = 0;
1659   cfg_.ss_number_layers = 3;
1660   cfg_.ts_number_layers = 3;
1661   cfg_.ts_rate_decimator[0] = 4;
1662   cfg_.ts_rate_decimator[1] = 2;
1663   cfg_.ts_rate_decimator[2] = 1;
1664   cfg_.g_error_resilient = 1;
1665   cfg_.g_threads = 4;
1666   cfg_.temporal_layering_mode = 3;
1667   svc_params_.scaling_factor_num[0] = 72;
1668   svc_params_.scaling_factor_den[0] = 288;
1669   svc_params_.scaling_factor_num[1] = 144;
1670   svc_params_.scaling_factor_den[1] = 288;
1671   svc_params_.scaling_factor_num[2] = 288;
1672   svc_params_.scaling_factor_den[2] = 288;
1673   cfg_.rc_dropframe_thresh = 0;
1674   cfg_.kf_max_dist = 9999;
1675   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1676   cfg_.rc_target_bitrate = 800;
1677   ResetModel();
1678   assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
1679                         cfg_.ts_number_layers, cfg_.temporal_layering_mode);
1680   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1681   ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78)
1682       << " The datarate for the file exceeds the target by too much!";
1683   ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
1684       << " The datarate for the file is lower than the target by too much!";
1685 #if CONFIG_VP9_DECODER
1686   // Number of temporal layers > 1, so half of the frames in this SVC pattern
1687   // will be non-reference frame and hence encoder will avoid loopfilter.
1688   // Since frame dropper is off, we can expcet 150 (half of the sequence)
1689   // mismatched frames.
1690   EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
1691 #endif
1692 }
1693
1694 // Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial
1695 // downscale 5x5.
1696 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TL5x5MultipleRuns) {
1697   cfg_.rc_buf_initial_sz = 500;
1698   cfg_.rc_buf_optimal_sz = 500;
1699   cfg_.rc_buf_sz = 1000;
1700   cfg_.rc_min_quantizer = 0;
1701   cfg_.rc_max_quantizer = 63;
1702   cfg_.rc_end_usage = VPX_CBR;
1703   cfg_.g_lag_in_frames = 0;
1704   cfg_.ss_number_layers = 2;
1705   cfg_.ts_number_layers = 1;
1706   cfg_.ts_rate_decimator[0] = 1;
1707   cfg_.g_error_resilient = 1;
1708   cfg_.g_threads = 3;
1709   cfg_.temporal_layering_mode = 0;
1710   svc_params_.scaling_factor_num[0] = 256;
1711   svc_params_.scaling_factor_den[0] = 1280;
1712   svc_params_.scaling_factor_num[1] = 1280;
1713   svc_params_.scaling_factor_den[1] = 1280;
1714   cfg_.rc_dropframe_thresh = 10;
1715   cfg_.kf_max_dist = 999999;
1716   cfg_.kf_min_dist = 0;
1717   cfg_.ss_target_bitrate[0] = 300;
1718   cfg_.ss_target_bitrate[1] = 1400;
1719   cfg_.layer_target_bitrate[0] = 300;
1720   cfg_.layer_target_bitrate[1] = 1400;
1721   cfg_.rc_target_bitrate = 1700;
1722   ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
1723   ResetModel();
1724   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1725   EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
1726 }
1727
1728 VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES,
1729                           ::testing::Values(0));
1730 VP8_INSTANTIATE_TEST_CASE(DatarateTestRealTime,
1731                           ::testing::Values(::libvpx_test::kRealTime),
1732                           ::testing::Values(-6, -12));
1733 VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
1734                           ::testing::Values(::libvpx_test::kOnePassGood,
1735                                             ::libvpx_test::kRealTime),
1736                           ::testing::Range(2, 9));
1737 #if CONFIG_VP9_TEMPORAL_DENOISING
1738 VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9LargeDenoiser,
1739                           ::testing::Values(::libvpx_test::kRealTime),
1740                           ::testing::Range(5, 9));
1741 #endif
1742 VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
1743                           ::testing::Values(::libvpx_test::kRealTime),
1744                           ::testing::Range(5, 9));
1745 }  // namespace