datarate_test.cc 35.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
10
#include "./vpx_config.h"
11
12
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
13
14
#include "test/encode_test_driver.h"
#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
20
namespace {

21
class DatarateTestLarge : public ::libvpx_test::EncoderTest,
22
23
    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
 public:
24
25
26
  DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}

  virtual ~DatarateTestLarge() {}
27

28
29
30
 protected:
  virtual void SetUp() {
    InitializeConfig();
31
    SetMode(GET_PARAM(1));
32
33
34
35
36
37
38
39
40
41
    ResetModel();
  }

  virtual void ResetModel() {
    last_pts_ = 0;
    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
    frame_number_ = 0;
    first_drop_ = 0;
    bits_total_ = 0;
    duration_ = 0.0;
42
43
    denoiser_offon_test_ = 0;
    denoiser_offon_period_ = -1;
44
45
46
  }

  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
47
                                  ::libvpx_test::Encoder *encoder) {
Marco's avatar
Marco committed
48
    if (video->frame() == 0)
49
      encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
50
51
52
53
54
55
56
57
58
59
60

    if (denoiser_offon_test_) {
      ASSERT_GT(denoiser_offon_period_, 0)
          << "denoiser_offon_period_ is not positive.";
      if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
        // Flip denoiser_on_ periodically
        denoiser_on_ ^= 1;
      }
      encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
    }

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    const vpx_rational_t tb = video->timebase();
    timebase_ = static_cast<double>(tb.num) / tb.den;
    duration_ = 0;
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    // Time since last timestamp = duration.
    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;

    // TODO(jimbankoski): Remove these lines when the issue:
    // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
    // For now the codec assumes buffer starts at starting buffer rate
    // plus one frame's time.
    if (last_pts_ == 0)
      duration = 1;

    // Add to the buffer the bits we'd expect from a constant bitrate server.
78
79
    bits_in_buffer_model_ += static_cast<int64_t>(
        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
80
81
82
83

    /* Test the buffer model here before subtracting the frame. Do so because
     * the way the leaky bucket model works in libvpx is to allow the buffer to
     * empty - and then stop showing frames until we've got enough bits to
Marco Paniconi's avatar
Marco Paniconi committed
84
85
     * show one. As noted in comment below (issue 495), this does not currently
     * apply to key frames. For now exclude key frames in condition below. */
86
87
    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
                         ? true: false;
Marco Paniconi's avatar
Marco Paniconi committed
88
89
90
91
    if (!key_frame) {
      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
          << pkt->data.frame.pts;
    }
92

93
    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
94
95
96
97
98

    // Subtract from the buffer the bits associated with a played back frame.
    bits_in_buffer_model_ -= frame_size_in_bits;

    // Update the running total of bits for end of test datarate checks.
Yaowu Xu's avatar
Yaowu Xu committed
99
    bits_total_ += frame_size_in_bits;
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

    // If first drop not set and we have a drop set it to this time.
    if (!first_drop_ && duration > 1)
      first_drop_ = last_pts_ + 1;

    // Update the most recent pts.
    last_pts_ = pkt->data.frame.pts;

    // We update this so that we can calculate the datarate minus the last
    // frame encoded in the file.
    bits_in_last_frame_ = frame_size_in_bits;

    ++frame_number_;
  }

  virtual void EndPassHook(void) {
    if (bits_total_) {
117
      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
118
119
120
121
122
123
124
125
126
127
128
129

      duration_ = (last_pts_ + 1) * timebase_;

      // Effective file datarate includes the time spent prebuffering.
      effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
          / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);

      file_datarate_ = file_size_in_kb / duration_;
    }
  }

  vpx_codec_pts_t last_pts_;
130
  int64_t bits_in_buffer_model_;
131
132
133
134
135
136
137
  double timebase_;
  int frame_number_;
  vpx_codec_pts_t first_drop_;
  int64_t bits_total_;
  double duration_;
  double file_datarate_;
  double effective_datarate_;
138
  size_t bits_in_last_frame_;
139
  int denoiser_on_;
140
141
  int denoiser_offon_test_;
  int denoiser_offon_period_;
142
143
};

144
#if CONFIG_TEMPORAL_DENOISING
145
146
147
// Check basic datarate targeting, for a single bitrate, but loop over the
// various denoiser settings.
TEST_P(DatarateTestLarge, DenoiserLevels) {
148
149
150
151
152
153
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_max_quantizer = 56;
  cfg_.rc_end_usage = VPX_CBR;
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);
154
155
156
157
158
159
160
161
162
163
  for (int j = 1; j < 5; ++j) {
    // Run over the denoiser levels.
    // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
    // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
    // denoiserOnAggressive, and denoiserOnAdaptive.
    // For the spatial denoiser (if !CONFIG_TEMPORAL_DENOISING), the level j
    // refers to the blur thresholds: 20, 40, 60 80.
    // The j = 0 case (denoiser off) is covered in the tests below.
    denoiser_on_ = j;
    cfg_.rc_target_bitrate = 300;
164
165
166
167
168
169
170
171
172
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
        << " The datarate for the file exceeds the target!";

    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
        << " The datarate for the file missed the target!";
  }
}
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
TEST_P(DatarateTestLarge, DenoiserOffOn) {
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_max_quantizer = 56;
  cfg_.rc_end_usage = VPX_CBR;
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 299);
  cfg_.rc_target_bitrate = 300;
  ResetModel();
  // The denoiser is off by default.
  denoiser_on_ = 0;
  // Set the offon test flag.
  denoiser_offon_test_ = 1;
  denoiser_offon_period_ = 100;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
      << " The datarate for the file exceeds the target!";
  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
      << " The datarate for the file missed the target!";
}
196
#endif  // CONFIG_TEMPORAL_DENOISING
197

198
TEST_P(DatarateTestLarge, BasicBufferModel) {
199
  denoiser_on_ = 0;
200
201
202
203
204
205
206
207
208
209
210
211
212
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_max_quantizer = 56;
  cfg_.rc_end_usage = VPX_CBR;
  // 2 pass cbr datarate control has a bug hidden by the small # of
  // frames selected in this encode. The problem is that even if the buffer is
  // negative we produce a keyframe on a cutscene. Ignoring datarate
  // constraints
  // TODO(jimbankoski): ( Fix when issue
  // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);

Marco Paniconi's avatar
Marco Paniconi committed
213
214
215
216
217
218
  // There is an issue for low bitrates in real-time mode, where the
  // effective_datarate slightly overshoots the target bitrate.
  // This is same the issue as noted about (#495).
  // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
  // when the issue is resolved.
  for (int i = 100; i < 800; i += 200) {
219
220
221
    cfg_.rc_target_bitrate = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
222
    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
223
224
225
226
227
228
229
        << " The datarate for the file exceeds the target!";

    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
        << " The datarate for the file missed the target!";
  }
}

230
TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
231
  denoiser_on_ = 0;
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_max_quantizer = 36;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.rc_target_bitrate = 200;
  cfg_.kf_mode = VPX_KF_DISABLED;

  const int frame_count = 40;
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, frame_count);

  // Here we check that the first dropped frame gets earlier and earlier
  // as the drop frame threshold is increased.

  const int kDropFrameThreshTestStep = 30;
  vpx_codec_pts_t last_drop = frame_count;
  for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
    cfg_.rc_dropframe_thresh = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_LE(first_drop_, last_drop)
        << " The first dropped frame for drop_thresh " << i
        << " > first dropped frame for drop_thresh "
        << i - kDropFrameThreshTestStep;
    last_drop = first_drop_;
  }
}

259
class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
Marco Paniconi's avatar
Marco Paniconi committed
260
261
    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
 public:
262
  DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
Marco Paniconi's avatar
Marco Paniconi committed
263

Marco Paniconi's avatar
Marco Paniconi committed
264
 protected:
265
  virtual ~DatarateTestVP9Large() {}
Marco Paniconi's avatar
Marco Paniconi committed
266

Marco Paniconi's avatar
Marco Paniconi committed
267
268
269
270
271
272
273
274
275
  virtual void SetUp() {
    InitializeConfig();
    SetMode(GET_PARAM(1));
    set_cpu_used_ = GET_PARAM(2);
    ResetModel();
  }

  virtual void ResetModel() {
    last_pts_ = 0;
276
    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
Marco Paniconi's avatar
Marco Paniconi committed
277
    frame_number_ = 0;
278
    tot_frame_number_ = 0;
279
280
    first_drop_ = 0;
    num_drops_ = 0;
JackyChen's avatar
JackyChen committed
281
282
    // Denoiser is off by default.
    denoiser_on_ = 0;
283
284
285
286
    // For testing up to 3 layers.
    for (int i = 0; i < 3; ++i) {
      bits_total_[i] = 0;
    }
287
288
    denoiser_offon_test_ = 0;
    denoiser_offon_period_ = -1;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  }

  //
  // Frame flags and layer id for temporal layers.
  //

  // For two layers, test pattern is:
  //   1     3
  // 0    2     .....
  // For three layers, test pattern is:
  //   1      3    5      7
  //      2           6
  // 0          4            ....
  // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
  // For this 3 layer example, the 2nd enhancement layer (layer 2) does not
  // update any reference frames.
  int SetFrameFlags(int frame_num, int num_temp_layers) {
    int frame_flags = 0;
    if (num_temp_layers == 2) {
      if (frame_num % 2 == 0) {
        // Layer 0: predict from L and ARF, update L.
        frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
                      VP8_EFLAG_NO_UPD_ARF;
      } else {
        // Layer 1: predict from L, G and ARF, and update G.
        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
                      VP8_EFLAG_NO_UPD_ENTROPY;
      }
    } else if (num_temp_layers == 3) {
      if (frame_num % 4 == 0) {
        // Layer 0: predict from L and ARF; update L.
        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
                      VP8_EFLAG_NO_REF_GF;
      } else if ((frame_num - 2) % 4 == 0) {
        // Layer 1: predict from L, G, ARF; update G.
        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
      }  else if ((frame_num - 1) % 2 == 0) {
        // Layer 2: predict from L, G, ARF; update none.
        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
                      VP8_EFLAG_NO_UPD_LAST;
      }
    }
    return frame_flags;
  }

  int SetLayerId(int frame_num, int num_temp_layers) {
    int layer_id = 0;
    if (num_temp_layers == 2) {
      if (frame_num % 2 == 0) {
        layer_id = 0;
      } else {
        layer_id = 1;
      }
    } else if (num_temp_layers == 3) {
      if (frame_num % 4 == 0) {
        layer_id = 0;
      } else if ((frame_num - 2) % 4 == 0) {
        layer_id = 1;
      } else if ((frame_num - 1) % 2 == 0) {
        layer_id = 2;
      }
    }
    return layer_id;
Marco Paniconi's avatar
Marco Paniconi committed
352
353
  }

Marco Paniconi's avatar
Marco Paniconi committed
354
  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
355
                                  ::libvpx_test::Encoder *encoder) {
Marco's avatar
Marco committed
356
    if (video->frame() == 0)
Marco Paniconi's avatar
Marco Paniconi committed
357
      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
358

359
360
361
362
363
364
365
366
367
    if (denoiser_offon_test_) {
      ASSERT_GT(denoiser_offon_period_, 0)
          << "denoiser_offon_period_ is not positive.";
      if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
        // Flip denoiser_on_ periodically
        denoiser_on_ ^= 1;
      }
    }

368
369
    encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);

370
    if (cfg_.ts_number_layers > 1) {
Marco's avatar
Marco committed
371
      if (video->frame() == 0) {
372
373
        encoder->Control(VP9E_SET_SVC, 1);
      }
374
      vpx_svc_layer_id_t layer_id;
375
376
377
378
      layer_id.spatial_layer_id = 0;
      frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
      layer_id.temporal_layer_id = SetLayerId(video->frame(),
                                              cfg_.ts_number_layers);
Marco's avatar
Marco committed
379
      encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
380
    }
Marco Paniconi's avatar
Marco Paniconi committed
381
382
383
384
385
    const vpx_rational_t tb = video->timebase();
    timebase_ = static_cast<double>(tb.num) / tb.den;
    duration_ = 0;
  }

386

Marco Paniconi's avatar
Marco Paniconi committed
387
  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
388
389
390
    // Time since last timestamp = duration.
    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;

391
392
393
394
395
396
397
398
399
400
401
402
403
    if (duration > 1) {
      // If first drop not set and we have a drop set it to this time.
      if (!first_drop_)
        first_drop_ = last_pts_ + 1;
      // Update the number of frame drops.
      num_drops_ += static_cast<int>(duration - 1);
      // Update counter for total number of frames (#frames input to encoder).
      // Needed for setting the proper layer_id below.
      tot_frame_number_ += static_cast<int>(duration - 1);
    }

    int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);

404
    // Add to the buffer the bits we'd expect from a constant bitrate server.
405
406
    bits_in_buffer_model_ += static_cast<int64_t>(
        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
407
408
409
410
411

    // Buffer should not go negative.
    ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
        << pkt->data.frame.pts;

412
    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
413
414
415
416
417
418

    // Update the total encoded bits. For temporal layers, update the cumulative
    // encoded bits per layer.
    for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
      bits_total_[i] += frame_size_in_bits;
    }
419

Marco Paniconi's avatar
Marco Paniconi committed
420
421
422
    // Update the most recent pts.
    last_pts_ = pkt->data.frame.pts;
    ++frame_number_;
423
    ++tot_frame_number_;
Marco Paniconi's avatar
Marco Paniconi committed
424
425
426
  }

  virtual void EndPassHook(void) {
427
428
    for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
        ++layer) {
Marco Paniconi's avatar
Marco Paniconi committed
429
      duration_ = (last_pts_ + 1) * timebase_;
430
431
432
433
      if (bits_total_[layer]) {
        // Effective file datarate:
        effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
      }
Marco Paniconi's avatar
Marco Paniconi committed
434
435
    }
  }
Marco Paniconi's avatar
Marco Paniconi committed
436
437
438

  vpx_codec_pts_t last_pts_;
  double timebase_;
439
440
  int frame_number_;      // Counter for number of non-dropped/encoded frames.
  int tot_frame_number_;  // Counter for total number of input frames.
441
  int64_t bits_total_[3];
Marco Paniconi's avatar
Marco Paniconi committed
442
  double duration_;
443
  double effective_datarate_[3];
Marco Paniconi's avatar
Marco Paniconi committed
444
  int set_cpu_used_;
445
446
  int64_t bits_in_buffer_model_;
  vpx_codec_pts_t first_drop_;
447
  int num_drops_;
JackyChen's avatar
JackyChen committed
448
  int denoiser_on_;
449
450
  int denoiser_offon_test_;
  int denoiser_offon_period_;
Marco Paniconi's avatar
Marco Paniconi committed
451
452
};

453
// Check basic rate targeting,
454
TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
455
456
457
458
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_dropframe_thresh = 1;
Marco Paniconi's avatar
Marco Paniconi committed
459
460
461
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
462
  cfg_.g_lag_in_frames = 0;
Marco Paniconi's avatar
Marco Paniconi committed
463
464
465

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);
Marco Paniconi's avatar
Marco Paniconi committed
466
  for (int i = 150; i < 800; i += 200) {
Marco Paniconi's avatar
Marco Paniconi committed
467
468
469
    cfg_.rc_target_bitrate = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
470
471
472
473
    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
        << " The datarate for the file is lower than target by too much!";
    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
        << " The datarate for the file is greater than target by too much!";
Marco Paniconi's avatar
Marco Paniconi committed
474
475
  }
}
476

477
// Check basic rate targeting,
478
TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);

  cfg_.g_profile = 1;
  cfg_.g_timebase = video.timebase();

  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;

  for (int i = 250; i < 900; i += 200) {
    cfg_.rc_target_bitrate = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
497
              effective_datarate_[0] * 0.85)
498
499
        << " The datarate for the file exceeds the target by too much!";
    ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
500
              effective_datarate_[0] * 1.15)
501
502
503
504
505
        << " The datarate for the file missed the target!"
        << cfg_.rc_target_bitrate << " "<< effective_datarate_;
  }
}

506
507
508
509
// Check that (1) the first dropped frame gets earlier and earlier
// as the drop frame threshold is increased, and (2) that the total number of
// frame drops does not decrease as we increase frame drop threshold.
// Use a lower qp-max to force some frame drops.
510
TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
511
512
513
514
515
516
517
518
519
520
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_undershoot_pct = 20;
  cfg_.rc_undershoot_pct = 20;
  cfg_.rc_dropframe_thresh = 10;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 50;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.rc_target_bitrate = 200;
521
  cfg_.g_lag_in_frames = 0;
522
523
524
525
526

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);

  const int kDropFrameThreshTestStep = 30;
527
  vpx_codec_pts_t last_drop = 140;
528
529
530
531
532
  int last_num_drops = 0;
  for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
    cfg_.rc_dropframe_thresh = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
533
534
535
536
    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
        << " The datarate for the file is lower than target by too much!";
    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
        << " The datarate for the file is greater than target by too much!";
537
538
539
540
    ASSERT_LE(first_drop_, last_drop)
        << " The first dropped frame for drop_thresh " << i
        << " > first dropped frame for drop_thresh "
        << i - kDropFrameThreshTestStep;
541
    ASSERT_GE(num_drops_, last_num_drops * 0.85)
542
543
544
545
546
547
548
549
        << " The number of dropped frames for drop_thresh " << i
        << " < number of dropped frames for drop_thresh "
        << i - kDropFrameThreshTestStep;
    last_drop = first_drop_;
    last_num_drops = num_drops_;
  }
}

550
// Check basic rate targeting for 2 temporal layers.
551
TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;

  // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
  cfg_.ss_number_layers = 1;
  cfg_.ts_number_layers = 2;
  cfg_.ts_rate_decimator[0] = 2;
  cfg_.ts_rate_decimator[1] = 1;

567
568
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

569
570
571
  if (deadline_ == VPX_DL_REALTIME)
    cfg_.g_error_resilient = 1;

572
573
574
575
576
577
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 200);
  for (int i = 200; i <= 800; i += 200) {
    cfg_.rc_target_bitrate = i;
    ResetModel();
    // 60-40 bitrate allocation for 2 temporal layers.
578
579
    cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
    cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
580
581
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
582
      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
583
584
          << " The datarate for the file is lower than target by too much, "
              "for layer: " << j;
585
      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
586
587
588
589
590
591
592
          << " The datarate for the file is greater than target by too much, "
              "for layer: " << j;
    }
  }
}

// Check basic rate targeting for 3 temporal layers.
593
TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
594
595
596
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
597
  cfg_.rc_dropframe_thresh = 1;
598
599
600
601
602
603
604
605
606
607
608
609
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;

  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
  cfg_.ss_number_layers = 1;
  cfg_.ts_number_layers = 3;
  cfg_.ts_rate_decimator[0] = 4;
  cfg_.ts_rate_decimator[1] = 2;
  cfg_.ts_rate_decimator[2] = 1;

610
611
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

612
613
614
615
616
617
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 200);
  for (int i = 200; i <= 800; i += 200) {
    cfg_.rc_target_bitrate = i;
    ResetModel();
    // 40-20-40 bitrate allocation for 3 temporal layers.
618
619
620
    cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
    cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
    cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
621
622
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
623
624
      // TODO(yaowu): Work out more stable rc control strategy and
      //              Adjust the thresholds to be tighter than .75.
625
      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
626
627
          << " The datarate for the file is lower than target by too much, "
              "for layer: " << j;
Yaowu Xu's avatar
Yaowu Xu committed
628
629
      // TODO(yaowu): Work out more stable rc control strategy and
      //              Adjust the thresholds to be tighter than 1.25.
630
      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
631
632
633
634
635
          << " The datarate for the file is greater than target by too much, "
              "for layer: " << j;
    }
  }
}
636
637
638
639

// Check basic rate targeting for 3 temporal layers, with frame dropping.
// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
// frame drop threshold, to force frame dropping.
640
TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  // Set frame drop threshold and rc_max_quantizer to force some frame drops.
  cfg_.rc_dropframe_thresh = 20;
  cfg_.rc_max_quantizer = 45;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;

  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
  cfg_.ss_number_layers = 1;
  cfg_.ts_number_layers = 3;
  cfg_.ts_rate_decimator[0] = 4;
  cfg_.ts_rate_decimator[1] = 2;
  cfg_.ts_rate_decimator[2] = 1;

658
659
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

660
661
662
663
664
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 200);
  cfg_.rc_target_bitrate = 200;
  ResetModel();
  // 40-20-40 bitrate allocation for 3 temporal layers.
665
666
667
  cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
  cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
  cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
668
669
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
670
    ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
671
672
        << " The datarate for the file is lower than target by too much, "
            "for layer: " << j;
673
    ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
674
675
676
        << " The datarate for the file is greater than target by too much, "
            "for layer: " << j;
    // Expect some frame drops in this test: for this 200 frames test,
677
    // expect at least 10% and not more than 60% drops.
678
    ASSERT_GE(num_drops_, 20);
679
    ASSERT_LE(num_drops_, 130);
680
681
682
  }
}

JackyChen's avatar
JackyChen committed
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
#if CONFIG_VP9_TEMPORAL_DENOISING
// Check basic datarate targeting, for a single bitrate, when denoiser is on.
TEST_P(DatarateTestVP9Large, DenoiserLevels) {
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_min_quantizer = 2;
  cfg_.rc_max_quantizer = 56;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);

  // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
  // there is only one denoiser mode: denoiserYonly(which is 1),
  // but may add more modes in the future.
  cfg_.rc_target_bitrate = 300;
  ResetModel();
  // Turn on the denoiser.
  denoiser_on_ = 1;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
      << " The datarate for the file is lower than target by too much!";
  ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
      << " The datarate for the file is greater than target by too much!";
}
711
712
713

// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
714
TEST_P(DatarateTestVP9Large, DenoiserOffOn) {
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_dropframe_thresh = 1;
  cfg_.rc_min_quantizer = 2;
  cfg_.rc_max_quantizer = 56;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 299);

  // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
  // there is only one denoiser mode: denoiserYonly(which is 1),
  // but may add more modes in the future.
  cfg_.rc_target_bitrate = 300;
  ResetModel();
  // The denoiser is off by default.
  denoiser_on_ = 0;
  // Set the offon test flag.
  denoiser_offon_test_ = 1;
  denoiser_offon_period_ = 100;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
      << " The datarate for the file is lower than target by too much!";
  ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
      << " The datarate for the file is greater than target by too much!";
}
743
#endif  // CONFIG_VP9_TEMPORAL_DENOISING
JackyChen's avatar
JackyChen committed
744

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
 public:
  DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {}
  virtual ~DatarateOnePassCbrSvc() {}
 protected:
  virtual void SetUp() {
    InitializeConfig();
    SetMode(GET_PARAM(1));
    speed_setting_ = GET_PARAM(2);
    ResetModel();
  }
  virtual void ResetModel() {
    last_pts_ = 0;
    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
    frame_number_ = 0;
    first_drop_ = 0;
    bits_total_ = 0;
    duration_ = 0.0;
764
765
    mismatch_psnr_ = 0.0;
    mismatch_nframes_ = 0;
766
767
768
769
770
771
772
  }
  virtual void BeginPassHook(unsigned int /*pass*/) {
  }
  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
                                  ::libvpx_test::Encoder *encoder) {
    if (video->frame() == 0) {
      int i;
773
      for (i = 0; i < VPX_MAX_LAYERS; ++i) {
774
775
776
777
778
779
780
781
782
783
784
785
        svc_params_.max_quantizers[i] = 63;
        svc_params_.min_quantizers[i] = 0;
      }
      svc_params_.scaling_factor_num[0] = 144;
      svc_params_.scaling_factor_den[0] = 288;
      svc_params_.scaling_factor_num[1] = 288;
      svc_params_.scaling_factor_den[1] = 288;
      encoder->Control(VP9E_SET_SVC, 1);
      encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
      encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
      encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
      encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
786
      encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
    }
    const vpx_rational_t tb = video->timebase();
    timebase_ = static_cast<double>(tb.num) / tb.den;
    duration_ = 0;
  }
  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
    if (last_pts_ == 0)
      duration = 1;
    bits_in_buffer_model_ += static_cast<int64_t>(
        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
                         ? true: false;
    if (!key_frame) {
      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
          << pkt->data.frame.pts;
    }
    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
    bits_in_buffer_model_ -= frame_size_in_bits;
    bits_total_ += frame_size_in_bits;
    if (!first_drop_ && duration > 1)
      first_drop_ = last_pts_ + 1;
    last_pts_ = pkt->data.frame.pts;
    bits_in_last_frame_ = frame_size_in_bits;
    ++frame_number_;
  }
  virtual void EndPassHook(void) {
    if (bits_total_) {
      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
      duration_ = (last_pts_ + 1) * timebase_;
      effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
          / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
      file_datarate_ = file_size_in_kb / duration_;
    }
  }
822
823
824
825
826
827
828
829
830
831
832
833

  virtual void MismatchHook(const vpx_image_t *img1,
                            const vpx_image_t *img2) {
    double mismatch_psnr = compute_psnr(img1, img2);
    mismatch_psnr_ += mismatch_psnr;
    ++mismatch_nframes_;
  }

  unsigned int GetMismatchFrames() {
    return mismatch_nframes_;
  }

834
835
836
837
838
839
840
841
842
843
844
845
  vpx_codec_pts_t last_pts_;
  int64_t bits_in_buffer_model_;
  double timebase_;
  int frame_number_;
  vpx_codec_pts_t first_drop_;
  int64_t bits_total_;
  double duration_;
  double file_datarate_;
  double effective_datarate_;
  size_t bits_in_last_frame_;
  vpx_svc_extra_cfg_t svc_params_;
  int speed_setting_;
846
847
  double mismatch_psnr_;
  int mismatch_nframes_;
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
};
static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg,
    const vpx_svc_extra_cfg_t *svc_params,
    int spatial_layers,
    int temporal_layers,
    int temporal_layering_mode,
    unsigned int total_rate) {
  int sl, spatial_layer_target;
  float total = 0;
  float alloc_ratio[VPX_MAX_LAYERS] = {0};
  for (sl = 0; sl < spatial_layers; ++sl) {
    if (svc_params->scaling_factor_den[sl] > 0) {
      alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] *
          1.0 / svc_params->scaling_factor_den[sl]);
      total += alloc_ratio[sl];
    }
  }
  for (sl = 0; sl < spatial_layers; ++sl) {
    enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
        (unsigned int)(enc_cfg->rc_target_bitrate *
            alloc_ratio[sl] / total);
    const int index = sl * temporal_layers;
    if (temporal_layering_mode == 3) {
      enc_cfg->layer_target_bitrate[index] =
          spatial_layer_target >> 1;
      enc_cfg->layer_target_bitrate[index + 1] =
          (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
      enc_cfg->layer_target_bitrate[index + 2] =
          spatial_layer_target;
    } else if (temporal_layering_mode == 2) {
      enc_cfg->layer_target_bitrate[index] =
          spatial_layer_target * 2 / 3;
      enc_cfg->layer_target_bitrate[index + 1] =
          spatial_layer_target;
    }
  }
}
Marco's avatar
Marco committed
885

886
// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
887
// 3 temporal layers. Run CIF clip with 1 thread.
888
889
890
891
892
893
894
895
896
897
898
899
900
901
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc) {
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;
  cfg_.ss_number_layers = 2;
  cfg_.ts_number_layers = 3;
  cfg_.ts_rate_decimator[0] = 4;
  cfg_.ts_rate_decimator[1] = 2;
  cfg_.ts_rate_decimator[2] = 1;
  cfg_.g_error_resilient = 1;
902
  cfg_.g_threads = 1;
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
  cfg_.temporal_layering_mode = 3;
  svc_params_.scaling_factor_num[0] = 144;
  svc_params_.scaling_factor_den[0] = 288;
  svc_params_.scaling_factor_num[1] = 288;
  svc_params_.scaling_factor_den[1] = 288;
  // TODO(wonkap/marpan): No frame drop for now, we need to implement correct
  // frame dropping for SVC.
  cfg_.rc_dropframe_thresh = 0;
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 200);
  // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the
  // layer target_bitrate. Also check if test can pass at lower bitrate (~200k).
  for (int i = 400; i <= 800; i += 200) {
    cfg_.rc_target_bitrate = i;
    ResetModel();
    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
        cfg_.ts_number_layers, cfg_.temporal_layering_mode,
        cfg_.rc_target_bitrate);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.85)
            << " The datarate for the file exceeds the target by too much!";
    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
        << " The datarate for the file is lower than the target by too much!";
926
    EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
927
928
  }
}
Marco's avatar
Marco committed
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
// 3 temporal layers. Run HD clip with 4 threads.
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc4threads) {
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
  cfg_.g_lag_in_frames = 0;
  cfg_.ss_number_layers = 2;
  cfg_.ts_number_layers = 3;
  cfg_.ts_rate_decimator[0] = 4;
  cfg_.ts_rate_decimator[1] = 2;
  cfg_.ts_rate_decimator[2] = 1;
  cfg_.g_error_resilient = 1;
  cfg_.g_threads = 4;
  cfg_.temporal_layering_mode = 3;
  svc_params_.scaling_factor_num[0] = 144;
  svc_params_.scaling_factor_den[0] = 288;
  svc_params_.scaling_factor_num[1] = 288;
  svc_params_.scaling_factor_den[1] = 288;
  // TODO(wonkap/marpan): No frame drop for now, we need to implement correct
  // frame dropping for SVC.
  cfg_.rc_dropframe_thresh = 0;
  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
                                       30, 1, 0, 300);
  cfg_.rc_target_bitrate = 800;
  ResetModel();
  assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
      cfg_.ts_number_layers, cfg_.temporal_layering_mode,
      cfg_.rc_target_bitrate);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.85)
          << " The datarate for the file exceeds the target by too much!";
  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
      << " The datarate for the file is lower than the target by too much!";
  EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
}

970
971
VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
972
973
                          ::testing::Values(::libvpx_test::kOnePassGood,
                                            ::libvpx_test::kRealTime),
974
                          ::testing::Range(2, 7));
975
976
977
VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
                          ::testing::Values(::libvpx_test::kRealTime),
                          ::testing::Range(5, 8));
978
}  // namespace