datarate_test.cc 42.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 int64_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
  int64_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
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
// Check basic rate targeting for VBR mode.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBR) {
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.g_error_resilient = 0;
  cfg_.rc_end_usage = VPX_VBR;
  cfg_.g_lag_in_frames = 0;

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 300);
  for (int i = 400; i <= 800; i += 400) {
    cfg_.rc_target_bitrate = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
        << " The datarate for the file is lower than target by too much!";
    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
        << " The datarate for the file is greater than target by too much!";
  }
}

// Check basic rate targeting for CBR,
475
TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
476
477
478
479
  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
480
481
482
  cfg_.rc_min_quantizer = 0;
  cfg_.rc_max_quantizer = 63;
  cfg_.rc_end_usage = VPX_CBR;
483
  cfg_.g_lag_in_frames = 0;
Marco Paniconi's avatar
Marco Paniconi committed
484
485
486

  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 140);
Marco Paniconi's avatar
Marco Paniconi committed
487
  for (int i = 150; i < 800; i += 200) {
Marco Paniconi's avatar
Marco Paniconi committed
488
489
490
    cfg_.rc_target_bitrate = i;
    ResetModel();
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
491
492
493
494
    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
495
496
  }
}
497

498
// Check basic rate targeting for CBR.
499
TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  ::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),
518
              effective_datarate_[0] * 0.85)
519
520
        << " The datarate for the file exceeds the target by too much!";
    ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
521
              effective_datarate_[0] * 1.15)
522
523
524
525
526
        << " The datarate for the file missed the target!"
        << cfg_.rc_target_bitrate << " "<< effective_datarate_;
  }
}

527
528
529
530
// 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.
531
TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
532
533
534
535
536
537
538
539
540
541
  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;
542
  cfg_.g_lag_in_frames = 0;
543
544
545
  // TODO(marpan): Investigate datarate target failures with a smaller keyframe
  // interval (128).
  cfg_.kf_max_dist = 9999;
546
547
548
549
550

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

  const int kDropFrameThreshTestStep = 30;
551
  vpx_codec_pts_t last_drop = 140;
552
553
554
555
556
  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));
557
558
559
560
    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!";
561
562
563
564
    ASSERT_LE(first_drop_, last_drop)
        << " The first dropped frame for drop_thresh " << i
        << " > first dropped frame for drop_thresh "
        << i - kDropFrameThreshTestStep;
565
    ASSERT_GE(num_drops_, last_num_drops * 0.85)
566
567
568
569
570
571
572
573
        << " 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_;
  }
}

574
// Check basic rate targeting for 2 temporal layers.
575
TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  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;

591
592
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

593
594
595
  if (deadline_ == VPX_DL_REALTIME)
    cfg_.g_error_resilient = 1;

596
597
598
599
600
601
  ::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.
602
603
    cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
    cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
604
605
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
606
      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
607
608
          << " The datarate for the file is lower than target by too much, "
              "for layer: " << j;
609
      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
610
611
612
613
614
615
616
          << " The datarate for the file is greater than target by too much, "
              "for layer: " << j;
    }
  }
}

// Check basic rate targeting for 3 temporal layers.
617
TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
618
619
620
  cfg_.rc_buf_initial_sz = 500;
  cfg_.rc_buf_optimal_sz = 500;
  cfg_.rc_buf_sz = 1000;
621
  cfg_.rc_dropframe_thresh = 1;
622
623
624
625
626
627
628
629
630
631
632
633
  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;

634
635
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

636
637
638
639
640
641
  ::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.
642
643
644
    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;
645
646
    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
647
648
      // TODO(yaowu): Work out more stable rc control strategy and
      //              Adjust the thresholds to be tighter than .75.
649
      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
650
651
          << " The datarate for the file is lower than target by too much, "
              "for layer: " << j;
Yaowu Xu's avatar
Yaowu Xu committed
652
653
      // TODO(yaowu): Work out more stable rc control strategy and
      //              Adjust the thresholds to be tighter than 1.25.
654
      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
655
656
657
658
659
          << " The datarate for the file is greater than target by too much, "
              "for layer: " << j;
    }
  }
}
660
661
662
663

// 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.
664
TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  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;

682
683
  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

684
685
686
687
688
  ::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.
689
690
691
  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;
692
693
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
694
    ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
695
696
        << " The datarate for the file is lower than target by too much, "
            "for layer: " << j;
697
    ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
698
699
700
        << " 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,
701
    // expect at least 10% and not more than 60% drops.
702
    ASSERT_GE(num_drops_, 20);
703
    ASSERT_LE(num_drops_, 130);
704
705
706
  }
}

JackyChen's avatar
JackyChen committed
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
#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!";
}
735
736
737

// Check basic datarate targeting, for a single bitrate, when denoiser is off
// and on.
738
TEST_P(DatarateTestVP9Large, DenoiserOffOn) {
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
  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!";
}
767
#endif  // CONFIG_VP9_TEMPORAL_DENOISING
JackyChen's avatar
JackyChen committed
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
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;
788
789
    mismatch_psnr_ = 0.0;
    mismatch_nframes_ = 0;
790
791
792
793
794
795
796
  }
  virtual void BeginPassHook(unsigned int /*pass*/) {
  }
  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
                                  ::libvpx_test::Encoder *encoder) {
    if (video->frame() == 0) {
      int i;
797
      for (i = 0; i < VPX_MAX_LAYERS; ++i) {
798
799
800
801
802
803
804
805
        svc_params_.max_quantizers[i] = 63;
        svc_params_.min_quantizers[i] = 0;
      }
      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);
806
      encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
    }
    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_;
      file_datarate_ = file_size_in_kb / duration_;
    }
  }
840
841
842
843
844
845
846
847
848
849
850
851

  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_;
  }

852
853
854
855
856
857
858
859
860
861
862
  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_;
  size_t bits_in_last_frame_;
  vpx_svc_extra_cfg_t svc_params_;
  int speed_setting_;
863
864
  double mismatch_psnr_;
  int mismatch_nframes_;
865
866
867
868
869
};
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,
870
    int temporal_layering_mode) {
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  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
901

902
// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
903
// 3 temporal layers. Run CIF clip with 1 thread.
904
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) {
905
906
907
908
909
910
911
912
913
914
915
916
917
  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;
918
  cfg_.g_threads = 1;
919
920
921
922
923
  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;
924
  cfg_.rc_dropframe_thresh = 10;
925
  cfg_.kf_max_dist = 9999;
926
927
928
  ::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
929
930
  // layer target_bitrate.
  for (int i = 200; i <= 800; i += 200) {
931
932
933
    cfg_.rc_target_bitrate = i;
    ResetModel();
    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
934
        cfg_.ts_number_layers, cfg_.temporal_layering_mode);
935
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
936
    ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
937
938
939
            << " 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!";
940
    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
941
942
  }
}
Marco's avatar
Marco committed
943

944
945
946
// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) {
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  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 = 1;
  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;
  cfg_.rc_dropframe_thresh = 10;
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 200);
969
970
971
972
973
  cfg_.rc_target_bitrate = 400;
  // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
  // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
  for (int j = 64; j <= 67; j++) {
    cfg_.kf_max_dist = j;
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
    ResetModel();
    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
        cfg_.ts_number_layers, cfg_.temporal_layering_mode);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(cfg_.rc_target_bitrate, file_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(static_cast<unsigned int>(0), GetMismatchFrames());
  }
}

// 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, OnePassCbrSvc2SpatialLayers4threads) {
  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;
  cfg_.rc_dropframe_thresh = 10;
  cfg_.kf_max_dist = 9999;
  ::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);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  ASSERT_GE(cfg_.rc_target_bitrate, file_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(static_cast<unsigned int>(0), GetMismatchFrames());
}

1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
// 3 temporal layers. Run CIF clip with 1 thread.
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) {
  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 = 3;
  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 = 1;
  cfg_.temporal_layering_mode = 3;
  svc_params_.scaling_factor_num[0] = 72;
  svc_params_.scaling_factor_den[0] = 288;
  svc_params_.scaling_factor_num[1] = 144;
  svc_params_.scaling_factor_den[1] = 288;
  svc_params_.scaling_factor_num[2] = 288;
  svc_params_.scaling_factor_den[2] = 288;
  cfg_.rc_dropframe_thresh = 10;
1049
  cfg_.kf_max_dist = 9999;
1050
1051
1052
1053
1054
1055
1056
  ::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);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1057
  ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
1058
          << " The datarate for the file exceeds the target by too much!";
1059
  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
1060
      << " The datarate for the file is lower than the target by too much!";
1061
  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
1062
1063
}

1064
1065
// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
1066
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) {
1067
1068
1069
1070
1071
1072
1073
  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;
1074
  cfg_.ss_number_layers = 3;
1075
1076
1077
1078
1079
  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;
1080
  cfg_.g_threads = 1;
1081
  cfg_.temporal_layering_mode = 3;
1082
  svc_params_.scaling_factor_num[0] = 72;
1083
  svc_params_.scaling_factor_den[0] = 288;
1084
  svc_params_.scaling_factor_num[1] = 144;
1085
  svc_params_.scaling_factor_den[1] = 288;
1086
1087
  svc_params_.scaling_factor_num[2] = 288;
  svc_params_.scaling_factor_den[2] = 288;
1088
  cfg_.rc_dropframe_thresh = 10;
1089
1090
1091
  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
                                       30, 1, 0, 300);
  cfg_.rc_target_bitrate = 800;
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
  // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
  for (int j = 32; j <= 35; j++) {
    cfg_.kf_max_dist = j;
    ResetModel();
    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
       cfg_.ts_number_layers, cfg_.temporal_layering_mode);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
    ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
            << " The datarate for the file exceeds the target by too much!";
    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30)
        << " The datarate for the file is lower than the target by too much!";
    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
  }
1106
1107
}

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
// 3 temporal layers. Run HD clip with 4 threads.
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) {
  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 = 3;
  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] = 72;
  svc_params_.scaling_factor_den[0] = 288;
  svc_params_.scaling_factor_num[1] = 144;
  svc_params_.scaling_factor_den[1] = 288;
  svc_params_.scaling_factor_num[2] = 288;
  svc_params_.scaling_factor_den[2] = 288;
  cfg_.rc_dropframe_thresh = 10;
1133
  cfg_.kf_max_dist = 9999;
1134
1135
1136
1137
1138
1139
1140
  ::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);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1141
  ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
1142
          << " The datarate for the file exceeds the target by too much!";
1143
  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
1144
      << " The datarate for the file is lower than the target by too much!";
1145
  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
1146
1147
}

Yaowu Xu's avatar
Yaowu Xu committed
1148
1149
1150
1151
1152
/* VP10 does not support multiple layers yet.
VP10_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
                           ::testing::Values(::libvpx_test::kRealTime),
                           ::testing::Range(5, 8));
                           */
1153
}  // namespace