1 /*
2 * Copyright (c) 2020 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 "vp9/ratectrl_rtc.h"
11
12 #include <climits>
13 #include <fstream> // NOLINT
14 #include <string>
15
16 #include "./vpx_config.h"
17 #include "gtest/gtest.h"
18 #include "test/codec_factory.h"
19 #include "test/encode_test_driver.h"
20 #include "test/i420_video_source.h"
21 #include "test/util.h"
22 #include "test/video_source.h"
23 #include "vp9/encoder/vp9_encoder.h"
24 #include "vp9/encoder/vp9_svc_layercontext.h"
25 #include "vpx/vpx_codec.h"
26 #include "vpx_ports/bitops.h"
27
28 namespace {
29
30 const size_t kNumFrames = 300;
31
32 const int kTemporalId3Layer[4] = { 0, 2, 1, 2 };
33 const int kTemporalId2Layer[2] = { 0, 1 };
34 const int kTemporalRateAllocation3Layer[3] = { 50, 70, 100 };
35 const int kTemporalRateAllocation2Layer[2] = { 60, 100 };
36 const int kSpatialLayerBitrate[3] = { 200, 400, 1000 };
37 const int kSpatialLayerBitrateLow[3] = { 50, 100, 400 };
38
39 class RcInterfaceTest
40 : public ::libvpx_test::EncoderTest,
41 public ::libvpx_test::CodecTestWith2Params<int, vpx_rc_mode> {
42 public:
RcInterfaceTest()43 RcInterfaceTest()
44 : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
45 encoder_exit_(false), frame_drop_thresh_(0), num_drops_(0) {}
46
47 ~RcInterfaceTest() override = default;
48
49 protected:
SetUp()50 void SetUp() override {
51 InitializeConfig();
52 SetMode(::libvpx_test::kRealTime);
53 }
54
PreEncodeFrameHook(libvpx_test::VideoSource * video,libvpx_test::Encoder * encoder)55 void PreEncodeFrameHook(libvpx_test::VideoSource *video,
56 libvpx_test::Encoder *encoder) override {
57 if (video->frame() == 0) {
58 encoder->Control(VP8E_SET_CPUUSED, 7);
59 encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
60 if (rc_cfg_.is_screen) {
61 encoder->Control(VP9E_SET_TUNE_CONTENT, VP9E_CONTENT_SCREEN);
62 } else {
63 encoder->Control(VP9E_SET_TUNE_CONTENT, VP9E_CONTENT_DEFAULT);
64 }
65 encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 1000);
66 encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
67 }
68 frame_params_.frame_type = video->frame() % key_interval_ == 0
69 ? libvpx::RcFrameType::kKeyFrame
70 : libvpx::RcFrameType::kInterFrame;
71 if (rc_cfg_.rc_mode == VPX_CBR &&
72 frame_params_.frame_type == libvpx::RcFrameType::kInterFrame) {
73 // Disable golden frame update.
74 frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
75 frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
76 }
77 encoder_exit_ = video->frame() == kNumFrames;
78 }
79
PostEncodeFrameHook(::libvpx_test::Encoder * encoder)80 void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) override {
81 if (encoder_exit_) {
82 return;
83 }
84 int loopfilter_level, qp;
85 encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
86 encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
87 if (rc_api_->ComputeQP(frame_params_) == libvpx::FrameDropDecision::kOk) {
88 ASSERT_EQ(rc_api_->GetQP(), qp);
89 ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
90 } else {
91 num_drops_++;
92 }
93 }
94
FramePktHook(const vpx_codec_cx_pkt_t * pkt)95 void FramePktHook(const vpx_codec_cx_pkt_t *pkt) override {
96 rc_api_->PostEncodeUpdate(pkt->data.frame.sz, frame_params_);
97 }
98
RunOneLayer()99 void RunOneLayer() {
100 SetConfig(GET_PARAM(2));
101 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
102 frame_params_.spatial_layer_id = 0;
103 frame_params_.temporal_layer_id = 0;
104
105 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
106 1280, 720, 30, 1, 0, kNumFrames);
107
108 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
109 }
110
RunOneLayerScreen()111 void RunOneLayerScreen() {
112 SetConfig(GET_PARAM(2));
113 rc_cfg_.is_screen = true;
114 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
115 frame_params_.spatial_layer_id = 0;
116 frame_params_.temporal_layer_id = 0;
117
118 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
119 1280, 720, 30, 1, 0, kNumFrames);
120
121 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
122 }
123
RunOneLayerDropFramesCBR()124 void RunOneLayerDropFramesCBR() {
125 if (GET_PARAM(2) != VPX_CBR) {
126 GTEST_SKIP() << "Frame dropping is only for CBR mode.";
127 }
128 frame_drop_thresh_ = 30;
129 SetConfig(GET_PARAM(2));
130 // Use lower bitrate, lower max-q, and enable frame dropper.
131 rc_cfg_.target_bandwidth = 200;
132 cfg_.rc_target_bitrate = 200;
133 rc_cfg_.max_quantizer = 50;
134 cfg_.rc_max_quantizer = 50;
135 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
136 frame_params_.spatial_layer_id = 0;
137 frame_params_.temporal_layer_id = 0;
138
139 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
140 1280, 720, 30, 1, 0, kNumFrames);
141
142 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
143 // Check that some frames were dropped, otherwise test has no value.
144 ASSERT_GE(num_drops_, 1);
145 }
146
RunOneLayerVBRPeriodicKey()147 void RunOneLayerVBRPeriodicKey() {
148 if (GET_PARAM(2) != VPX_VBR) return;
149 key_interval_ = 100;
150 SetConfig(VPX_VBR);
151 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
152 frame_params_.spatial_layer_id = 0;
153 frame_params_.temporal_layer_id = 0;
154
155 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
156 1280, 720, 30, 1, 0, kNumFrames);
157
158 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
159 }
160
161 private:
SetConfig(vpx_rc_mode rc_mode)162 void SetConfig(vpx_rc_mode rc_mode) {
163 rc_cfg_.width = 1280;
164 rc_cfg_.height = 720;
165 rc_cfg_.max_quantizer = 52;
166 rc_cfg_.min_quantizer = 2;
167 rc_cfg_.target_bandwidth = 1000;
168 rc_cfg_.buf_initial_sz = 600;
169 rc_cfg_.buf_optimal_sz = 600;
170 rc_cfg_.buf_sz = 1000;
171 rc_cfg_.undershoot_pct = 50;
172 rc_cfg_.overshoot_pct = 50;
173 rc_cfg_.max_intra_bitrate_pct = 1000;
174 rc_cfg_.framerate = 30.0;
175 rc_cfg_.ss_number_layers = 1;
176 rc_cfg_.ts_number_layers = 1;
177 rc_cfg_.scaling_factor_num[0] = 1;
178 rc_cfg_.scaling_factor_den[0] = 1;
179 rc_cfg_.layer_target_bitrate[0] = 1000;
180 rc_cfg_.max_quantizers[0] = 52;
181 rc_cfg_.min_quantizers[0] = 2;
182 rc_cfg_.rc_mode = rc_mode;
183 rc_cfg_.aq_mode = aq_mode_;
184 rc_cfg_.frame_drop_thresh = frame_drop_thresh_;
185
186 // Encoder settings for ground truth.
187 cfg_.g_w = 1280;
188 cfg_.g_h = 720;
189 cfg_.rc_undershoot_pct = 50;
190 cfg_.rc_overshoot_pct = 50;
191 cfg_.rc_buf_initial_sz = 600;
192 cfg_.rc_buf_optimal_sz = 600;
193 cfg_.rc_buf_sz = 1000;
194 cfg_.rc_dropframe_thresh = 0;
195 cfg_.rc_min_quantizer = 2;
196 cfg_.rc_max_quantizer = 52;
197 cfg_.rc_end_usage = rc_mode;
198 cfg_.g_lag_in_frames = 0;
199 cfg_.g_error_resilient = 0;
200 cfg_.rc_target_bitrate = 1000;
201 cfg_.kf_min_dist = key_interval_;
202 cfg_.kf_max_dist = key_interval_;
203 cfg_.rc_dropframe_thresh = frame_drop_thresh_;
204 }
205
206 std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
207 libvpx::VP9RateControlRtcConfig rc_cfg_;
208 int aq_mode_;
209 int key_interval_;
210 libvpx::VP9FrameParamsQpRTC frame_params_;
211 bool encoder_exit_;
212 int frame_drop_thresh_;
213 int num_drops_;
214 };
215
216 class RcInterfaceSvcTest
217 : public ::libvpx_test::EncoderTest,
218 public ::libvpx_test::CodecTestWith2Params<int, bool> {
219 public:
RcInterfaceSvcTest()220 RcInterfaceSvcTest()
221 : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
222 dynamic_spatial_layers_(0), inter_layer_pred_off_(GET_PARAM(2)),
223 parallel_spatial_layers_(false), frame_drop_thresh_(0),
224 max_consec_drop_(INT_MAX), num_drops_(0) {}
225 ~RcInterfaceSvcTest() override = default;
226
227 protected:
SetUp()228 void SetUp() override {
229 InitializeConfig();
230 SetMode(::libvpx_test::kRealTime);
231 }
232
PreEncodeFrameHook(libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)233 void PreEncodeFrameHook(libvpx_test::VideoSource *video,
234 ::libvpx_test::Encoder *encoder) override {
235 if (video->frame() == 0) {
236 current_superframe_ = 0;
237 encoder->Control(VP8E_SET_CPUUSED, 7);
238 encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
239 encoder->Control(VP9E_SET_TUNE_CONTENT, 0);
240 encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
241 encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
242 encoder->Control(VP9E_SET_SVC, 1);
243 encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
244 if (inter_layer_pred_off_) {
245 encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED,
246 INTER_LAYER_PRED_OFF_NONKEY);
247 }
248 if (frame_drop_thresh_ > 0) {
249 vpx_svc_frame_drop_t svc_drop_frame;
250 svc_drop_frame.framedrop_mode = FULL_SUPERFRAME_DROP;
251 for (int sl = 0; sl < rc_cfg_.ss_number_layers; ++sl)
252 svc_drop_frame.framedrop_thresh[sl] = frame_drop_thresh_;
253 svc_drop_frame.max_consec_drop = max_consec_drop_;
254 encoder->Control(VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame);
255 }
256 }
257 frame_params_.frame_type = video->frame() % key_interval_ == 0
258 ? libvpx::RcFrameType::kKeyFrame
259 : libvpx::RcFrameType::kInterFrame;
260 encoder_exit_ = video->frame() == kNumFrames;
261 if (dynamic_spatial_layers_ == 1) {
262 if (video->frame() == 100) {
263 // Go down to 2 spatial layers: set top SL to 0 bitrate.
264 // Update the encoder config.
265 cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[8];
266 cfg_.layer_target_bitrate[6] = 0;
267 cfg_.layer_target_bitrate[7] = 0;
268 cfg_.layer_target_bitrate[8] = 0;
269 encoder->Config(&cfg_);
270 // Update the RC config.
271 rc_cfg_.target_bandwidth -= rc_cfg_.layer_target_bitrate[8];
272 rc_cfg_.layer_target_bitrate[6] = 0;
273 rc_cfg_.layer_target_bitrate[7] = 0;
274 rc_cfg_.layer_target_bitrate[8] = 0;
275 ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
276 } else if (video->frame() == 200) {
277 // Go down to 1 spatial layer.
278 // Update the encoder config.
279 cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[5];
280 cfg_.layer_target_bitrate[3] = 0;
281 cfg_.layer_target_bitrate[4] = 0;
282 cfg_.layer_target_bitrate[5] = 0;
283 encoder->Config(&cfg_);
284 // Update the RC config.
285 rc_cfg_.target_bandwidth -= rc_cfg_.layer_target_bitrate[5];
286 rc_cfg_.layer_target_bitrate[3] = 0;
287 rc_cfg_.layer_target_bitrate[4] = 0;
288 rc_cfg_.layer_target_bitrate[5] = 0;
289 ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
290 } else if (/*DISABLES CODE*/ (false) && video->frame() == 280) {
291 // TODO(marpan): Re-enable this going back up when issue is fixed.
292 // Go back up to 3 spatial layers.
293 // Update the encoder config: use the original bitrates.
294 SetEncoderConfigSvc(3, 3);
295 encoder->Config(&cfg_);
296 // Update the RC config.
297 SetRCConfigSvc(3, 3);
298 ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
299 }
300 }
301 }
302
SetFrameParamsSvc(int sl)303 virtual void SetFrameParamsSvc(int sl) {
304 frame_params_.spatial_layer_id = sl;
305 if (rc_cfg_.ts_number_layers == 3)
306 frame_params_.temporal_layer_id =
307 kTemporalId3Layer[current_superframe_ % 4];
308 else if (rc_cfg_.ts_number_layers == 2)
309 frame_params_.temporal_layer_id =
310 kTemporalId2Layer[current_superframe_ % 2];
311 else
312 frame_params_.temporal_layer_id = 0;
313 frame_params_.frame_type =
314 current_superframe_ % key_interval_ == 0 && sl == 0
315 ? libvpx::RcFrameType::kKeyFrame
316 : libvpx::RcFrameType::kInterFrame;
317 }
318
PostEncodeFrameHook(::libvpx_test::Encoder * encoder)319 void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) override {
320 if (encoder_exit_) {
321 return;
322 }
323 int superframe_is_dropped = false;
324 ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
325 for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) sizes_[sl] = 0;
326 std::vector<int> rc_qp;
327 // For FULL_SUPERFRAME_DROP: the full superframe drop decision is
328 // determined on the base spatial layer.
329 SetFrameParamsSvc(0);
330 if (rc_api_->ComputeQP(frame_params_) == libvpx::FrameDropDecision::kDrop) {
331 superframe_is_dropped = true;
332 num_drops_++;
333 }
334 while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
335 ASSERT_EQ(superframe_is_dropped, false);
336 ParseSuperframeSizes(static_cast<const uint8_t *>(pkt->data.frame.buf),
337 pkt->data.frame.sz);
338 if (!parallel_spatial_layers_ || current_superframe_ == 0) {
339 for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
340 if (sizes_[sl] > 0) {
341 SetFrameParamsSvc(sl);
342 // For sl=0 ComputeQP() is already called above (line 310).
343 if (sl > 0) rc_api_->ComputeQP(frame_params_);
344 rc_api_->PostEncodeUpdate(sizes_[sl], frame_params_);
345 rc_qp.push_back(rc_api_->GetQP());
346 }
347 }
348 } else {
349 for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
350 // For sl=0 ComputeQP() is already called above (line 310).
351 if (sizes_[sl] > 0 && sl > 0) {
352 SetFrameParamsSvc(sl);
353 rc_api_->ComputeQP(frame_params_);
354 }
355 }
356 for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
357 if (sizes_[sl] > 0) {
358 SetFrameParamsSvc(sl);
359 rc_api_->PostEncodeUpdate(sizes_[sl], frame_params_);
360 rc_qp.push_back(rc_api_->GetQP());
361 }
362 }
363 }
364 }
365 if (!superframe_is_dropped) {
366 int loopfilter_level;
367 std::vector<int> encoder_qp(VPX_SS_MAX_LAYERS, 0);
368 encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
369 encoder->Control(VP9E_GET_LAST_QUANTIZER_SVC_LAYERS, encoder_qp.data());
370 encoder_qp.resize(rc_qp.size());
371 ASSERT_EQ(rc_qp, encoder_qp);
372 ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
373 current_superframe_++;
374 }
375 }
376 // This method needs to be overridden because non-reference frames are
377 // expected to be mismatched frames as the encoder will avoid loopfilter on
378 // these frames.
MismatchHook(const vpx_image_t *,const vpx_image_t *)379 void MismatchHook(const vpx_image_t * /*img1*/,
380 const vpx_image_t * /*img2*/) override {}
381
RunSvc()382 void RunSvc() {
383 SetRCConfigSvc(3, 3);
384 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
385 SetEncoderConfigSvc(3, 3);
386
387 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
388 1280, 720, 30, 1, 0, kNumFrames);
389
390 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
391 }
392
RunSvcDropFramesCBR()393 void RunSvcDropFramesCBR() {
394 max_consec_drop_ = 10;
395 frame_drop_thresh_ = 30;
396 SetRCConfigSvc(3, 3);
397 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
398 SetEncoderConfigSvc(3, 3);
399
400 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
401 1280, 720, 30, 1, 0, kNumFrames);
402
403 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
404 // Check that some frames were dropped, otherwise test has no value.
405 ASSERT_GE(num_drops_, 1);
406 }
407
RunSvcPeriodicKey()408 void RunSvcPeriodicKey() {
409 SetRCConfigSvc(3, 3);
410 key_interval_ = 100;
411 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
412 SetEncoderConfigSvc(3, 3);
413
414 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
415 1280, 720, 30, 1, 0, kNumFrames);
416
417 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
418 }
419
RunSvcDynamicSpatial()420 void RunSvcDynamicSpatial() {
421 dynamic_spatial_layers_ = 1;
422 SetRCConfigSvc(3, 3);
423 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
424 SetEncoderConfigSvc(3, 3);
425
426 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
427 1280, 720, 30, 1, 0, kNumFrames);
428
429 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
430 }
431
RunSvcParallelSpatialLayers()432 void RunSvcParallelSpatialLayers() {
433 if (!inter_layer_pred_off_) return;
434 parallel_spatial_layers_ = true;
435 SetRCConfigSvc(3, 3);
436 rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
437 SetEncoderConfigSvc(3, 3);
438
439 ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
440 1280, 720, 30, 1, 0, kNumFrames);
441
442 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
443 }
444
445 private:
ParseSuperframeSizes(const uint8_t * data,size_t data_sz)446 vpx_codec_err_t ParseSuperframeSizes(const uint8_t *data, size_t data_sz) {
447 uint8_t marker = *(data + data_sz - 1);
448 if ((marker & 0xe0) == 0xc0) {
449 const uint32_t frames = (marker & 0x7) + 1;
450 const uint32_t mag = ((marker >> 3) & 0x3) + 1;
451 const size_t index_sz = 2 + mag * frames;
452 // This chunk is marked as having a superframe index but doesn't have
453 // enough data for it, thus it's an invalid superframe index.
454 if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
455 {
456 const uint8_t marker2 = *(data + data_sz - index_sz);
457 // This chunk is marked as having a superframe index but doesn't have
458 // the matching marker byte at the front of the index therefore it's an
459 // invalid chunk.
460 if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
461 }
462 const uint8_t *x = &data[data_sz - index_sz + 1];
463 for (uint32_t i = 0; i < frames; ++i) {
464 uint32_t this_sz = 0;
465
466 for (uint32_t j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
467 sizes_[i] = this_sz;
468 }
469 }
470 return VPX_CODEC_OK;
471 }
472
SetEncoderConfigSvc(int number_spatial_layers,int number_temporal_layers)473 void SetEncoderConfigSvc(int number_spatial_layers,
474 int number_temporal_layers) {
475 cfg_.g_w = 1280;
476 cfg_.g_h = 720;
477 cfg_.ss_number_layers = number_spatial_layers;
478 cfg_.ts_number_layers = number_temporal_layers;
479 cfg_.g_timebase.num = 1;
480 cfg_.g_timebase.den = 30;
481 if (number_spatial_layers == 3) {
482 svc_params_.scaling_factor_num[0] = 1;
483 svc_params_.scaling_factor_den[0] = 4;
484 svc_params_.scaling_factor_num[1] = 2;
485 svc_params_.scaling_factor_den[1] = 4;
486 svc_params_.scaling_factor_num[2] = 4;
487 svc_params_.scaling_factor_den[2] = 4;
488 } else if (number_spatial_layers == 2) {
489 svc_params_.scaling_factor_num[0] = 1;
490 svc_params_.scaling_factor_den[0] = 2;
491 svc_params_.scaling_factor_num[1] = 2;
492 svc_params_.scaling_factor_den[1] = 2;
493 } else if (number_spatial_layers == 1) {
494 svc_params_.scaling_factor_num[0] = 1;
495 svc_params_.scaling_factor_den[0] = 1;
496 }
497
498 for (int i = 0; i < VPX_MAX_LAYERS; ++i) {
499 svc_params_.max_quantizers[i] = 56;
500 svc_params_.min_quantizers[i] = 2;
501 svc_params_.speed_per_layer[i] = 7;
502 svc_params_.loopfilter_ctrl[i] = LOOPFILTER_ALL;
503 }
504 cfg_.rc_end_usage = VPX_CBR;
505 cfg_.g_lag_in_frames = 0;
506 cfg_.g_error_resilient = 0;
507
508 if (number_temporal_layers == 3) {
509 cfg_.ts_rate_decimator[0] = 4;
510 cfg_.ts_rate_decimator[1] = 2;
511 cfg_.ts_rate_decimator[2] = 1;
512 cfg_.temporal_layering_mode = 3;
513 } else if (number_temporal_layers == 2) {
514 cfg_.ts_rate_decimator[0] = 2;
515 cfg_.ts_rate_decimator[1] = 1;
516 cfg_.temporal_layering_mode = 2;
517 } else if (number_temporal_layers == 1) {
518 cfg_.ts_rate_decimator[0] = 1;
519 cfg_.temporal_layering_mode = 0;
520 }
521
522 cfg_.rc_buf_initial_sz = 500;
523 cfg_.rc_buf_optimal_sz = 600;
524 cfg_.rc_buf_sz = 1000;
525 cfg_.rc_min_quantizer = 2;
526 cfg_.rc_max_quantizer = 56;
527 cfg_.g_threads = 1;
528 cfg_.kf_max_dist = 9999;
529 cfg_.rc_overshoot_pct = 50;
530 cfg_.rc_undershoot_pct = 50;
531 cfg_.rc_dropframe_thresh = frame_drop_thresh_;
532
533 cfg_.rc_target_bitrate = 0;
534 for (int sl = 0; sl < number_spatial_layers; sl++) {
535 int spatial_bitrate = 0;
536 if (number_spatial_layers <= 3)
537 spatial_bitrate = frame_drop_thresh_ > 0 ? kSpatialLayerBitrateLow[sl]
538 : kSpatialLayerBitrate[sl];
539 for (int tl = 0; tl < number_temporal_layers; tl++) {
540 int layer = sl * number_temporal_layers + tl;
541 if (number_temporal_layers == 3)
542 cfg_.layer_target_bitrate[layer] =
543 kTemporalRateAllocation3Layer[tl] * spatial_bitrate / 100;
544 else if (number_temporal_layers == 2)
545 cfg_.layer_target_bitrate[layer] =
546 kTemporalRateAllocation2Layer[tl] * spatial_bitrate / 100;
547 else if (number_temporal_layers == 1)
548 cfg_.layer_target_bitrate[layer] = spatial_bitrate;
549 }
550 cfg_.rc_target_bitrate += spatial_bitrate;
551 }
552
553 cfg_.kf_min_dist = key_interval_;
554 cfg_.kf_max_dist = key_interval_;
555 }
556
SetRCConfigSvc(int number_spatial_layers,int number_temporal_layers)557 void SetRCConfigSvc(int number_spatial_layers, int number_temporal_layers) {
558 rc_cfg_.width = 1280;
559 rc_cfg_.height = 720;
560 rc_cfg_.ss_number_layers = number_spatial_layers;
561 rc_cfg_.ts_number_layers = number_temporal_layers;
562 rc_cfg_.max_quantizer = 56;
563 rc_cfg_.min_quantizer = 2;
564 rc_cfg_.buf_initial_sz = 500;
565 rc_cfg_.buf_optimal_sz = 600;
566 rc_cfg_.buf_sz = 1000;
567 rc_cfg_.undershoot_pct = 50;
568 rc_cfg_.overshoot_pct = 50;
569 rc_cfg_.max_intra_bitrate_pct = 900;
570 rc_cfg_.framerate = 30.0;
571 rc_cfg_.rc_mode = VPX_CBR;
572 rc_cfg_.aq_mode = aq_mode_;
573 rc_cfg_.frame_drop_thresh = frame_drop_thresh_;
574 rc_cfg_.max_consec_drop = max_consec_drop_;
575
576 if (number_spatial_layers == 3) {
577 rc_cfg_.scaling_factor_num[0] = 1;
578 rc_cfg_.scaling_factor_den[0] = 4;
579 rc_cfg_.scaling_factor_num[1] = 2;
580 rc_cfg_.scaling_factor_den[1] = 4;
581 rc_cfg_.scaling_factor_num[2] = 4;
582 rc_cfg_.scaling_factor_den[2] = 4;
583 } else if (number_spatial_layers == 2) {
584 rc_cfg_.scaling_factor_num[0] = 1;
585 rc_cfg_.scaling_factor_den[0] = 2;
586 rc_cfg_.scaling_factor_num[1] = 2;
587 rc_cfg_.scaling_factor_den[1] = 2;
588 } else if (number_spatial_layers == 1) {
589 rc_cfg_.scaling_factor_num[0] = 1;
590 rc_cfg_.scaling_factor_den[0] = 1;
591 }
592
593 if (number_temporal_layers == 3) {
594 rc_cfg_.ts_rate_decimator[0] = 4;
595 rc_cfg_.ts_rate_decimator[1] = 2;
596 rc_cfg_.ts_rate_decimator[2] = 1;
597 } else if (number_temporal_layers == 2) {
598 rc_cfg_.ts_rate_decimator[0] = 2;
599 rc_cfg_.ts_rate_decimator[1] = 1;
600 } else if (number_temporal_layers == 1) {
601 rc_cfg_.ts_rate_decimator[0] = 1;
602 }
603
604 rc_cfg_.target_bandwidth = 0;
605 for (int sl = 0; sl < number_spatial_layers; sl++) {
606 int spatial_bitrate = 0;
607 if (number_spatial_layers <= 3)
608 spatial_bitrate = frame_drop_thresh_ > 0 ? kSpatialLayerBitrateLow[sl]
609 : kSpatialLayerBitrate[sl];
610 for (int tl = 0; tl < number_temporal_layers; tl++) {
611 int layer = sl * number_temporal_layers + tl;
612 if (number_temporal_layers == 3)
613 rc_cfg_.layer_target_bitrate[layer] =
614 kTemporalRateAllocation3Layer[tl] * spatial_bitrate / 100;
615 else if (number_temporal_layers == 2)
616 rc_cfg_.layer_target_bitrate[layer] =
617 kTemporalRateAllocation2Layer[tl] * spatial_bitrate / 100;
618 else if (number_temporal_layers == 1)
619 rc_cfg_.layer_target_bitrate[layer] = spatial_bitrate;
620 }
621 rc_cfg_.target_bandwidth += spatial_bitrate;
622 }
623
624 for (int sl = 0; sl < rc_cfg_.ss_number_layers; ++sl) {
625 for (int tl = 0; tl < rc_cfg_.ts_number_layers; ++tl) {
626 const int i = sl * rc_cfg_.ts_number_layers + tl;
627 rc_cfg_.max_quantizers[i] = 56;
628 rc_cfg_.min_quantizers[i] = 2;
629 }
630 }
631 }
632
633 int aq_mode_;
634 std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
635 libvpx::VP9RateControlRtcConfig rc_cfg_;
636 vpx_svc_extra_cfg_t svc_params_;
637 libvpx::VP9FrameParamsQpRTC frame_params_;
638 bool encoder_exit_;
639 int current_superframe_;
640 uint32_t sizes_[8];
641 int key_interval_;
642 int dynamic_spatial_layers_;
643 bool inter_layer_pred_off_;
644 // ComputeQP() and PostEncodeUpdate() don't need to be sequential for KSVC.
645 bool parallel_spatial_layers_;
646 int frame_drop_thresh_;
647 int max_consec_drop_;
648 int num_drops_;
649 };
650
TEST_P(RcInterfaceTest,OneLayer)651 TEST_P(RcInterfaceTest, OneLayer) { RunOneLayer(); }
652
TEST_P(RcInterfaceTest,OneLayerDropFramesCBR)653 TEST_P(RcInterfaceTest, OneLayerDropFramesCBR) { RunOneLayerDropFramesCBR(); }
654
TEST_P(RcInterfaceTest,OneLayerScreen)655 TEST_P(RcInterfaceTest, OneLayerScreen) { RunOneLayerScreen(); }
656
TEST_P(RcInterfaceTest,OneLayerVBRPeriodicKey)657 TEST_P(RcInterfaceTest, OneLayerVBRPeriodicKey) { RunOneLayerVBRPeriodicKey(); }
658
TEST_P(RcInterfaceSvcTest,Svc)659 TEST_P(RcInterfaceSvcTest, Svc) { RunSvc(); }
660
TEST_P(RcInterfaceSvcTest,SvcDropFramesCBR)661 TEST_P(RcInterfaceSvcTest, SvcDropFramesCBR) { RunSvcDropFramesCBR(); }
662
TEST_P(RcInterfaceSvcTest,SvcParallelSpatialLayers)663 TEST_P(RcInterfaceSvcTest, SvcParallelSpatialLayers) {
664 RunSvcParallelSpatialLayers();
665 }
666
TEST_P(RcInterfaceSvcTest,SvcPeriodicKey)667 TEST_P(RcInterfaceSvcTest, SvcPeriodicKey) { RunSvcPeriodicKey(); }
668
TEST_P(RcInterfaceSvcTest,SvcDynamicSpatial)669 TEST_P(RcInterfaceSvcTest, SvcDynamicSpatial) { RunSvcDynamicSpatial(); }
670
671 VP9_INSTANTIATE_TEST_SUITE(RcInterfaceTest, ::testing::Values(0, 3),
672 ::testing::Values(VPX_CBR, VPX_VBR));
673 VP9_INSTANTIATE_TEST_SUITE(RcInterfaceSvcTest, ::testing::Values(0, 3),
674 ::testing::Values(true, false));
675 } // namespace
676