xref: /aosp_15_r20/external/libvpx/test/vp9_ratectrl_rtc_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
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