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
18namespace {
19
20class DatarateTestLarge : public ::libvpx_test::EncoderTest,
21    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
22 public:
23  DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
24
25  virtual ~DatarateTestLarge() {}
26
27 protected:
28  virtual void SetUp() {
29    InitializeConfig();
30    SetMode(GET_PARAM(1));
31    ResetModel();
32  }
33
34  virtual void ResetModel() {
35    last_pts_ = 0;
36    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
37    frame_number_ = 0;
38    first_drop_ = 0;
39    bits_total_ = 0;
40    duration_ = 0.0;
41  }
42
43  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
44                                  ::libvpx_test::Encoder *encoder) {
45    if (video->frame() == 1) {
46      encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
47    }
48    const vpx_rational_t tb = video->timebase();
49    timebase_ = static_cast<double>(tb.num) / tb.den;
50    duration_ = 0;
51  }
52
53  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
54    // Time since last timestamp = duration.
55    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
56
57    // TODO(jimbankoski): Remove these lines when the issue:
58    // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
59    // For now the codec assumes buffer starts at starting buffer rate
60    // plus one frame's time.
61    if (last_pts_ == 0)
62      duration = 1;
63
64    // Add to the buffer the bits we'd expect from a constant bitrate server.
65    bits_in_buffer_model_ += static_cast<int64_t>(
66        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
67
68    /* Test the buffer model here before subtracting the frame. Do so because
69     * the way the leaky bucket model works in libvpx is to allow the buffer to
70     * empty - and then stop showing frames until we've got enough bits to
71     * show one. As noted in comment below (issue 495), this does not currently
72     * apply to key frames. For now exclude key frames in condition below. */
73    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
74                         ? true: false;
75    if (!key_frame) {
76      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
77          << pkt->data.frame.pts;
78    }
79
80    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
81
82    // Subtract from the buffer the bits associated with a played back frame.
83    bits_in_buffer_model_ -= frame_size_in_bits;
84
85    // Update the running total of bits for end of test datarate checks.
86    bits_total_ += frame_size_in_bits;
87
88    // If first drop not set and we have a drop set it to this time.
89    if (!first_drop_ && duration > 1)
90      first_drop_ = last_pts_ + 1;
91
92    // Update the most recent pts.
93    last_pts_ = pkt->data.frame.pts;
94
95    // We update this so that we can calculate the datarate minus the last
96    // frame encoded in the file.
97    bits_in_last_frame_ = frame_size_in_bits;
98
99    ++frame_number_;
100  }
101
102  virtual void EndPassHook(void) {
103    if (bits_total_) {
104      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
105
106      duration_ = (last_pts_ + 1) * timebase_;
107
108      // Effective file datarate includes the time spent prebuffering.
109      effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
110          / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
111
112      file_datarate_ = file_size_in_kb / duration_;
113    }
114  }
115
116  vpx_codec_pts_t last_pts_;
117  int64_t bits_in_buffer_model_;
118  double timebase_;
119  int frame_number_;
120  vpx_codec_pts_t first_drop_;
121  int64_t bits_total_;
122  double duration_;
123  double file_datarate_;
124  double effective_datarate_;
125  size_t bits_in_last_frame_;
126  int denoiser_on_;
127};
128
129#if CONFIG_TEMPORAL_DENOISING
130// Check basic datarate targeting, for a single bitrate, but loop over the
131// various denoiser settings.
132TEST_P(DatarateTestLarge, DenoiserLevels) {
133  cfg_.rc_buf_initial_sz = 500;
134  cfg_.rc_dropframe_thresh = 1;
135  cfg_.rc_max_quantizer = 56;
136  cfg_.rc_end_usage = VPX_CBR;
137  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
138                                       30, 1, 0, 140);
139  for (int j = 1; j < 5; ++j) {
140    // Run over the denoiser levels.
141    // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
142    // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
143    // denoiserOnAggressive, and denoiserOnAdaptive.
144    // For the spatial denoiser (if !CONFIG_TEMPORAL_DENOISING), the level j
145    // refers to the blur thresholds: 20, 40, 60 80.
146    // The j = 0 case (denoiser off) is covered in the tests below.
147    denoiser_on_ = j;
148    cfg_.rc_target_bitrate = 300;
149    ResetModel();
150    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
151    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
152        << " The datarate for the file exceeds the target!";
153
154    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
155        << " The datarate for the file missed the target!";
156  }
157}
158#endif  // CONFIG_TEMPORAL_DENOISING
159
160TEST_P(DatarateTestLarge, BasicBufferModel) {
161  denoiser_on_ = 0;
162  cfg_.rc_buf_initial_sz = 500;
163  cfg_.rc_dropframe_thresh = 1;
164  cfg_.rc_max_quantizer = 56;
165  cfg_.rc_end_usage = VPX_CBR;
166  // 2 pass cbr datarate control has a bug hidden by the small # of
167  // frames selected in this encode. The problem is that even if the buffer is
168  // negative we produce a keyframe on a cutscene. Ignoring datarate
169  // constraints
170  // TODO(jimbankoski): ( Fix when issue
171  // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
172  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
173                                       30, 1, 0, 140);
174
175  // There is an issue for low bitrates in real-time mode, where the
176  // effective_datarate slightly overshoots the target bitrate.
177  // This is same the issue as noted about (#495).
178  // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
179  // when the issue is resolved.
180  for (int i = 100; i < 800; i += 200) {
181    cfg_.rc_target_bitrate = i;
182    ResetModel();
183    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
184    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
185        << " The datarate for the file exceeds the target!";
186
187    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
188        << " The datarate for the file missed the target!";
189  }
190}
191
192TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
193  denoiser_on_ = 0;
194  cfg_.rc_buf_initial_sz = 500;
195  cfg_.rc_max_quantizer = 36;
196  cfg_.rc_end_usage = VPX_CBR;
197  cfg_.rc_target_bitrate = 200;
198  cfg_.kf_mode = VPX_KF_DISABLED;
199
200  const int frame_count = 40;
201  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
202                                       30, 1, 0, frame_count);
203
204  // Here we check that the first dropped frame gets earlier and earlier
205  // as the drop frame threshold is increased.
206
207  const int kDropFrameThreshTestStep = 30;
208  vpx_codec_pts_t last_drop = frame_count;
209  for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
210    cfg_.rc_dropframe_thresh = i;
211    ResetModel();
212    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
213    ASSERT_LE(first_drop_, last_drop)
214        << " The first dropped frame for drop_thresh " << i
215        << " > first dropped frame for drop_thresh "
216        << i - kDropFrameThreshTestStep;
217    last_drop = first_drop_;
218  }
219}
220
221class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
222    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
223 public:
224  DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
225
226 protected:
227  virtual ~DatarateTestVP9Large() {}
228
229  virtual void SetUp() {
230    InitializeConfig();
231    SetMode(GET_PARAM(1));
232    set_cpu_used_ = GET_PARAM(2);
233    ResetModel();
234  }
235
236  virtual void ResetModel() {
237    last_pts_ = 0;
238    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
239    frame_number_ = 0;
240    tot_frame_number_ = 0;
241    first_drop_ = 0;
242    num_drops_ = 0;
243    // Denoiser is off by default.
244    denoiser_on_ = 0;
245    // For testing up to 3 layers.
246    for (int i = 0; i < 3; ++i) {
247      bits_total_[i] = 0;
248    }
249  }
250
251  //
252  // Frame flags and layer id for temporal layers.
253  //
254
255  // For two layers, test pattern is:
256  //   1     3
257  // 0    2     .....
258  // For three layers, test pattern is:
259  //   1      3    5      7
260  //      2           6
261  // 0          4            ....
262  // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
263  // For this 3 layer example, the 2nd enhancement layer (layer 2) does not
264  // update any reference frames.
265  int SetFrameFlags(int frame_num, int num_temp_layers) {
266    int frame_flags = 0;
267    if (num_temp_layers == 2) {
268      if (frame_num % 2 == 0) {
269        // Layer 0: predict from L and ARF, update L.
270        frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
271                      VP8_EFLAG_NO_UPD_ARF;
272      } else {
273        // Layer 1: predict from L, G and ARF, and update G.
274        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
275                      VP8_EFLAG_NO_UPD_ENTROPY;
276      }
277    } else if (num_temp_layers == 3) {
278      if (frame_num % 4 == 0) {
279        // Layer 0: predict from L and ARF; update L.
280        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
281                      VP8_EFLAG_NO_REF_GF;
282      } else if ((frame_num - 2) % 4 == 0) {
283        // Layer 1: predict from L, G, ARF; update G.
284        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
285      }  else if ((frame_num - 1) % 2 == 0) {
286        // Layer 2: predict from L, G, ARF; update none.
287        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
288                      VP8_EFLAG_NO_UPD_LAST;
289      }
290    }
291    return frame_flags;
292  }
293
294  int SetLayerId(int frame_num, int num_temp_layers) {
295    int layer_id = 0;
296    if (num_temp_layers == 2) {
297      if (frame_num % 2 == 0) {
298        layer_id = 0;
299      } else {
300        layer_id = 1;
301      }
302    } else if (num_temp_layers == 3) {
303      if (frame_num % 4 == 0) {
304        layer_id = 0;
305      } else if ((frame_num - 2) % 4 == 0) {
306        layer_id = 1;
307      } else if ((frame_num - 1) % 2 == 0) {
308        layer_id = 2;
309      }
310    }
311    return layer_id;
312  }
313
314  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
315                                  ::libvpx_test::Encoder *encoder) {
316    if (video->frame() == 1) {
317      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
318      encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
319    }
320    if (cfg_.ts_number_layers > 1) {
321      if (video->frame() == 1) {
322        encoder->Control(VP9E_SET_SVC, 1);
323      }
324      vpx_svc_layer_id_t layer_id = {0, 0};
325      layer_id.spatial_layer_id = 0;
326      frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
327      layer_id.temporal_layer_id = SetLayerId(video->frame(),
328                                              cfg_.ts_number_layers);
329      if (video->frame() > 0) {
330       encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
331      }
332    }
333    const vpx_rational_t tb = video->timebase();
334    timebase_ = static_cast<double>(tb.num) / tb.den;
335    duration_ = 0;
336  }
337
338
339  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
340    // Time since last timestamp = duration.
341    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
342
343    if (duration > 1) {
344      // If first drop not set and we have a drop set it to this time.
345      if (!first_drop_)
346        first_drop_ = last_pts_ + 1;
347      // Update the number of frame drops.
348      num_drops_ += static_cast<int>(duration - 1);
349      // Update counter for total number of frames (#frames input to encoder).
350      // Needed for setting the proper layer_id below.
351      tot_frame_number_ += static_cast<int>(duration - 1);
352    }
353
354    int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
355
356    // Add to the buffer the bits we'd expect from a constant bitrate server.
357    bits_in_buffer_model_ += static_cast<int64_t>(
358        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
359
360    // Buffer should not go negative.
361    ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
362        << pkt->data.frame.pts;
363
364    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
365
366    // Update the total encoded bits. For temporal layers, update the cumulative
367    // encoded bits per layer.
368    for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
369      bits_total_[i] += frame_size_in_bits;
370    }
371
372    // Update the most recent pts.
373    last_pts_ = pkt->data.frame.pts;
374    ++frame_number_;
375    ++tot_frame_number_;
376  }
377
378  virtual void EndPassHook(void) {
379    for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
380        ++layer) {
381      duration_ = (last_pts_ + 1) * timebase_;
382      if (bits_total_[layer]) {
383        // Effective file datarate:
384        effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
385      }
386    }
387  }
388
389  vpx_codec_pts_t last_pts_;
390  double timebase_;
391  int frame_number_;      // Counter for number of non-dropped/encoded frames.
392  int tot_frame_number_;  // Counter for total number of input frames.
393  int64_t bits_total_[3];
394  double duration_;
395  double effective_datarate_[3];
396  int set_cpu_used_;
397  int64_t bits_in_buffer_model_;
398  vpx_codec_pts_t first_drop_;
399  int num_drops_;
400  int denoiser_on_;
401};
402
403// Check basic rate targeting,
404TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
405  cfg_.rc_buf_initial_sz = 500;
406  cfg_.rc_buf_optimal_sz = 500;
407  cfg_.rc_buf_sz = 1000;
408  cfg_.rc_dropframe_thresh = 1;
409  cfg_.rc_min_quantizer = 0;
410  cfg_.rc_max_quantizer = 63;
411  cfg_.rc_end_usage = VPX_CBR;
412  cfg_.g_lag_in_frames = 0;
413
414  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
415                                       30, 1, 0, 140);
416  for (int i = 150; i < 800; i += 200) {
417    cfg_.rc_target_bitrate = i;
418    ResetModel();
419    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
420    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
421        << " The datarate for the file is lower than target by too much!";
422    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
423        << " The datarate for the file is greater than target by too much!";
424  }
425}
426
427// Check basic rate targeting,
428TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
429  ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
430
431  cfg_.g_profile = 1;
432  cfg_.g_timebase = video.timebase();
433
434  cfg_.rc_buf_initial_sz = 500;
435  cfg_.rc_buf_optimal_sz = 500;
436  cfg_.rc_buf_sz = 1000;
437  cfg_.rc_dropframe_thresh = 1;
438  cfg_.rc_min_quantizer = 0;
439  cfg_.rc_max_quantizer = 63;
440  cfg_.rc_end_usage = VPX_CBR;
441
442  for (int i = 250; i < 900; i += 200) {
443    cfg_.rc_target_bitrate = i;
444    ResetModel();
445    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
446    ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
447              effective_datarate_[0] * 0.85)
448        << " The datarate for the file exceeds the target by too much!";
449    ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
450              effective_datarate_[0] * 1.15)
451        << " The datarate for the file missed the target!"
452        << cfg_.rc_target_bitrate << " "<< effective_datarate_;
453  }
454}
455
456// Check that (1) the first dropped frame gets earlier and earlier
457// as the drop frame threshold is increased, and (2) that the total number of
458// frame drops does not decrease as we increase frame drop threshold.
459// Use a lower qp-max to force some frame drops.
460TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
461  cfg_.rc_buf_initial_sz = 500;
462  cfg_.rc_buf_optimal_sz = 500;
463  cfg_.rc_buf_sz = 1000;
464  cfg_.rc_undershoot_pct = 20;
465  cfg_.rc_undershoot_pct = 20;
466  cfg_.rc_dropframe_thresh = 10;
467  cfg_.rc_min_quantizer = 0;
468  cfg_.rc_max_quantizer = 50;
469  cfg_.rc_end_usage = VPX_CBR;
470  cfg_.rc_target_bitrate = 200;
471  cfg_.g_lag_in_frames = 0;
472
473  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
474                                       30, 1, 0, 140);
475
476  const int kDropFrameThreshTestStep = 30;
477  vpx_codec_pts_t last_drop = 140;
478  int last_num_drops = 0;
479  for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
480    cfg_.rc_dropframe_thresh = i;
481    ResetModel();
482    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
483    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
484        << " The datarate for the file is lower than target by too much!";
485    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
486        << " The datarate for the file is greater than target by too much!";
487    ASSERT_LE(first_drop_, last_drop)
488        << " The first dropped frame for drop_thresh " << i
489        << " > first dropped frame for drop_thresh "
490        << i - kDropFrameThreshTestStep;
491    ASSERT_GE(num_drops_, last_num_drops)
492        << " The number of dropped frames for drop_thresh " << i
493        << " < number of dropped frames for drop_thresh "
494        << i - kDropFrameThreshTestStep;
495    last_drop = first_drop_;
496    last_num_drops = num_drops_;
497  }
498}
499
500// Check basic rate targeting for 2 temporal layers.
501TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
502  cfg_.rc_buf_initial_sz = 500;
503  cfg_.rc_buf_optimal_sz = 500;
504  cfg_.rc_buf_sz = 1000;
505  cfg_.rc_dropframe_thresh = 1;
506  cfg_.rc_min_quantizer = 0;
507  cfg_.rc_max_quantizer = 63;
508  cfg_.rc_end_usage = VPX_CBR;
509  cfg_.g_lag_in_frames = 0;
510
511  // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
512  cfg_.ss_number_layers = 1;
513  cfg_.ts_number_layers = 2;
514  cfg_.ts_rate_decimator[0] = 2;
515  cfg_.ts_rate_decimator[1] = 1;
516
517  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
518                                       30, 1, 0, 200);
519  for (int i = 200; i <= 800; i += 200) {
520    cfg_.rc_target_bitrate = i;
521    ResetModel();
522    // 60-40 bitrate allocation for 2 temporal layers.
523    cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
524    cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
525    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
526    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
527      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85)
528          << " The datarate for the file is lower than target by too much, "
529              "for layer: " << j;
530      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15)
531          << " The datarate for the file is greater than target by too much, "
532              "for layer: " << j;
533    }
534  }
535}
536
537// Check basic rate targeting for 3 temporal layers.
538TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
539  cfg_.rc_buf_initial_sz = 500;
540  cfg_.rc_buf_optimal_sz = 500;
541  cfg_.rc_buf_sz = 1000;
542  cfg_.rc_dropframe_thresh = 1;
543  cfg_.rc_min_quantizer = 0;
544  cfg_.rc_max_quantizer = 63;
545  cfg_.rc_end_usage = VPX_CBR;
546  cfg_.g_lag_in_frames = 0;
547
548  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
549  cfg_.ss_number_layers = 1;
550  cfg_.ts_number_layers = 3;
551  cfg_.ts_rate_decimator[0] = 4;
552  cfg_.ts_rate_decimator[1] = 2;
553  cfg_.ts_rate_decimator[2] = 1;
554
555  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
556                                       30, 1, 0, 200);
557  for (int i = 200; i <= 800; i += 200) {
558    cfg_.rc_target_bitrate = i;
559    ResetModel();
560    // 40-20-40 bitrate allocation for 3 temporal layers.
561    cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
562    cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
563    cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
564    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
565    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
566      // TODO(yaowu): Work out more stable rc control strategy and
567      //              Adjust the thresholds to be tighter than .75.
568      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
569          << " The datarate for the file is lower than target by too much, "
570              "for layer: " << j;
571      // TODO(yaowu): Work out more stable rc control strategy and
572      //              Adjust the thresholds to be tighter than 1.25.
573      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
574          << " The datarate for the file is greater than target by too much, "
575              "for layer: " << j;
576    }
577  }
578}
579
580// Check basic rate targeting for 3 temporal layers, with frame dropping.
581// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
582// frame drop threshold, to force frame dropping.
583TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
584  cfg_.rc_buf_initial_sz = 500;
585  cfg_.rc_buf_optimal_sz = 500;
586  cfg_.rc_buf_sz = 1000;
587  // Set frame drop threshold and rc_max_quantizer to force some frame drops.
588  cfg_.rc_dropframe_thresh = 20;
589  cfg_.rc_max_quantizer = 45;
590  cfg_.rc_min_quantizer = 0;
591  cfg_.rc_end_usage = VPX_CBR;
592  cfg_.g_lag_in_frames = 0;
593
594  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
595  cfg_.ss_number_layers = 1;
596  cfg_.ts_number_layers = 3;
597  cfg_.ts_rate_decimator[0] = 4;
598  cfg_.ts_rate_decimator[1] = 2;
599  cfg_.ts_rate_decimator[2] = 1;
600
601  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
602                                       30, 1, 0, 200);
603  cfg_.rc_target_bitrate = 200;
604  ResetModel();
605  // 40-20-40 bitrate allocation for 3 temporal layers.
606  cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
607  cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
608  cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
609  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
610  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
611    ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85)
612        << " The datarate for the file is lower than target by too much, "
613            "for layer: " << j;
614    ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15)
615        << " The datarate for the file is greater than target by too much, "
616            "for layer: " << j;
617    // Expect some frame drops in this test: for this 200 frames test,
618    // expect at least 10% and not more than 60% drops.
619    ASSERT_GE(num_drops_, 20);
620    ASSERT_LE(num_drops_, 130);
621  }
622}
623
624#if CONFIG_VP9_TEMPORAL_DENOISING
625// Check basic datarate targeting, for a single bitrate, when denoiser is on.
626TEST_P(DatarateTestVP9Large, DenoiserLevels) {
627  cfg_.rc_buf_initial_sz = 500;
628  cfg_.rc_buf_optimal_sz = 500;
629  cfg_.rc_buf_sz = 1000;
630  cfg_.rc_dropframe_thresh = 1;
631  cfg_.rc_min_quantizer = 2;
632  cfg_.rc_max_quantizer = 56;
633  cfg_.rc_end_usage = VPX_CBR;
634  cfg_.g_lag_in_frames = 0;
635
636  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
637                                       30, 1, 0, 140);
638
639  // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
640  // there is only one denoiser mode: denoiserYonly(which is 1),
641  // but may add more modes in the future.
642  cfg_.rc_target_bitrate = 300;
643  ResetModel();
644  // Turn on the denoiser.
645  denoiser_on_ = 1;
646  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
647  ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
648      << " The datarate for the file is lower than target by too much!";
649  ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
650      << " The datarate for the file is greater than target by too much!";
651}
652#endif  // CONFIG_VP9_TEMPORAL_DENOISING
653
654VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
655VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
656                          ::testing::Values(::libvpx_test::kOnePassGood,
657                          ::libvpx_test::kRealTime),
658                          ::testing::Range(2, 7));
659}  // namespace
660