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