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