• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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