vp9_cx_iface: set default cpu_used=5 w/CONFIG_REALTIME_ONLY
[platform/upstream/libvpx.git] / test / vp8_ratectrl_rtc_test.cc
1 /*
2  *  Copyright (c) 2021 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
11 #include <fstream>  // NOLINT
12 #include <string>
13
14 #include "./vpx_config.h"
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16 #include "test/codec_factory.h"
17 #include "test/encode_test_driver.h"
18 #include "test/i420_video_source.h"
19 #include "test/util.h"
20 #include "test/video_source.h"
21 #include "vp8/vp8_ratectrl_rtc.h"
22 #include "vpx/vpx_codec.h"
23 #include "vpx_ports/bitops.h"
24
25 namespace {
26
27 struct Vp8RCTestVideo {
28   Vp8RCTestVideo() {}
29   Vp8RCTestVideo(const char *name_, int width_, int height_,
30                  unsigned int frames_)
31       : name(name_), width(width_), height(height_), frames(frames_) {}
32
33   friend std::ostream &operator<<(std::ostream &os,
34                                   const Vp8RCTestVideo &video) {
35     os << video.name << " " << video.width << " " << video.height << " "
36        << video.frames;
37     return os;
38   }
39   const char *name;
40   int width;
41   int height;
42   unsigned int frames;
43 };
44
45 const Vp8RCTestVideo kVp8RCTestVectors[] = {
46   Vp8RCTestVideo("niklas_640_480_30.yuv", 640, 480, 470),
47   Vp8RCTestVideo("desktop_office1.1280_720-020.yuv", 1280, 720, 300),
48 };
49
50 class Vp8RcInterfaceTest
51     : public ::libvpx_test::EncoderTest,
52       public ::libvpx_test::CodecTestWith2Params<int, Vp8RCTestVideo> {
53  public:
54   Vp8RcInterfaceTest()
55       : EncoderTest(GET_PARAM(0)), key_interval_(3000), encoder_exit_(false) {}
56   virtual ~Vp8RcInterfaceTest() {}
57
58  protected:
59   virtual void SetUp() {
60     InitializeConfig();
61     SetMode(::libvpx_test::kRealTime);
62   }
63
64   // From error_resilience_test.cc
65   int SetFrameFlags(int frame_num, int num_temp_layers) {
66     int frame_flags = 0;
67     if (num_temp_layers == 2) {
68       if (frame_num % 2 == 0) {
69         // Layer 0: predict from L and ARF, update L.
70         frame_flags =
71             VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
72       } else {
73         // Layer 1: predict from L, G and ARF, and update G.
74         frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
75                       VP8_EFLAG_NO_UPD_ENTROPY;
76       }
77     } else if (num_temp_layers == 3) {
78       if (frame_num % 4 == 0) {
79         // Layer 0: predict from L, update L.
80         frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
81                       VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
82       } else if ((frame_num - 2) % 4 == 0) {
83         // Layer 1: predict from L, G,  update G.
84         frame_flags =
85             VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
86       } else if ((frame_num - 1) % 2 == 0) {
87         // Layer 2: predict from L, G, ARF; update ARG.
88         frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
89       }
90     }
91     return frame_flags;
92   }
93
94   int SetLayerId(int frame_num, int num_temp_layers) {
95     int layer_id = 0;
96     if (num_temp_layers == 2) {
97       if (frame_num % 2 == 0) {
98         layer_id = 0;
99       } else {
100         layer_id = 1;
101       }
102     } else if (num_temp_layers == 3) {
103       if (frame_num % 4 == 0) {
104         layer_id = 0;
105       } else if ((frame_num - 2) % 4 == 0) {
106         layer_id = 1;
107       } else if ((frame_num - 1) % 2 == 0) {
108         layer_id = 2;
109       }
110     }
111     return layer_id;
112   }
113
114   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
115                                   ::libvpx_test::Encoder *encoder) {
116     if (rc_cfg_.ts_number_layers > 1) {
117       const int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
118       const int frame_flags =
119           SetFrameFlags(video->frame(), cfg_.ts_number_layers);
120       frame_params_.temporal_layer_id = layer_id;
121       if (video->frame() > 0) {
122         encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
123         encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
124       }
125     } else {
126       if (video->frame() == 0) {
127         encoder->Control(VP8E_SET_CPUUSED, -6);
128         encoder->Control(VP8E_SET_RTC_EXTERNAL_RATECTRL, 1);
129         encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 1000);
130       }
131       if (frame_params_.frame_type == INTER_FRAME) {
132         // Disable golden frame update.
133         frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
134         frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
135       }
136     }
137     frame_params_.frame_type =
138         video->frame() % key_interval_ == 0 ? KEY_FRAME : INTER_FRAME;
139     encoder_exit_ = video->frame() == test_video_.frames;
140   }
141
142   virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
143     if (encoder_exit_) {
144       return;
145     }
146     int qp;
147     encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
148     rc_api_->ComputeQP(frame_params_);
149     ASSERT_EQ(rc_api_->GetQP(), qp);
150   }
151
152   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
153     rc_api_->PostEncodeUpdate(pkt->data.frame.sz);
154   }
155
156   void RunOneLayer() {
157     test_video_ = GET_PARAM(2);
158     target_bitrate_ = GET_PARAM(1);
159     if (test_video_.width == 1280 && target_bitrate_ == 200) return;
160     if (test_video_.width == 640 && target_bitrate_ == 1000) return;
161     SetConfig();
162     rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
163     rc_api_->UpdateRateControl(rc_cfg_);
164
165     ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
166                                          test_video_.height, 30, 1, 0,
167                                          test_video_.frames);
168
169     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
170   }
171
172   void RunPeriodicKey() {
173     test_video_ = GET_PARAM(2);
174     target_bitrate_ = GET_PARAM(1);
175     if (test_video_.width == 1280 && target_bitrate_ == 200) return;
176     if (test_video_.width == 640 && target_bitrate_ == 1000) return;
177     key_interval_ = 100;
178     SetConfig();
179     rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
180     rc_api_->UpdateRateControl(rc_cfg_);
181
182     ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
183                                          test_video_.height, 30, 1, 0,
184                                          test_video_.frames);
185
186     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
187   }
188
189   void RunTemporalLayers2TL() {
190     test_video_ = GET_PARAM(2);
191     target_bitrate_ = GET_PARAM(1);
192     if (test_video_.width == 1280 && target_bitrate_ == 200) return;
193     if (test_video_.width == 640 && target_bitrate_ == 1000) return;
194     SetConfigTemporalLayers(2);
195     rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
196     rc_api_->UpdateRateControl(rc_cfg_);
197
198     ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
199                                          test_video_.height, 30, 1, 0,
200                                          test_video_.frames);
201
202     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
203   }
204
205   void RunTemporalLayers3TL() {
206     test_video_ = GET_PARAM(2);
207     target_bitrate_ = GET_PARAM(1);
208     if (test_video_.width == 1280 && target_bitrate_ == 200) return;
209     if (test_video_.width == 640 && target_bitrate_ == 1000) return;
210     SetConfigTemporalLayers(3);
211     rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
212     rc_api_->UpdateRateControl(rc_cfg_);
213
214     ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
215                                          test_video_.height, 30, 1, 0,
216                                          test_video_.frames);
217
218     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
219   }
220
221  private:
222   void SetConfig() {
223     rc_cfg_.width = test_video_.width;
224     rc_cfg_.height = test_video_.height;
225     rc_cfg_.max_quantizer = 60;
226     rc_cfg_.min_quantizer = 2;
227     rc_cfg_.target_bandwidth = target_bitrate_;
228     rc_cfg_.buf_initial_sz = 600;
229     rc_cfg_.buf_optimal_sz = 600;
230     rc_cfg_.buf_sz = target_bitrate_;
231     rc_cfg_.undershoot_pct = 50;
232     rc_cfg_.overshoot_pct = 50;
233     rc_cfg_.max_intra_bitrate_pct = 1000;
234     rc_cfg_.framerate = 30.0;
235     rc_cfg_.layer_target_bitrate[0] = target_bitrate_;
236
237     // Encoder settings for ground truth.
238     cfg_.g_w = test_video_.width;
239     cfg_.g_h = test_video_.height;
240     cfg_.rc_undershoot_pct = 50;
241     cfg_.rc_overshoot_pct = 50;
242     cfg_.rc_buf_initial_sz = 600;
243     cfg_.rc_buf_optimal_sz = 600;
244     cfg_.rc_buf_sz = target_bitrate_;
245     cfg_.rc_dropframe_thresh = 0;
246     cfg_.rc_min_quantizer = 2;
247     cfg_.rc_max_quantizer = 60;
248     cfg_.rc_end_usage = VPX_CBR;
249     cfg_.g_lag_in_frames = 0;
250     cfg_.g_error_resilient = 1;
251     cfg_.rc_target_bitrate = target_bitrate_;
252     cfg_.kf_min_dist = key_interval_;
253     cfg_.kf_max_dist = key_interval_;
254   }
255
256   void SetConfigTemporalLayers(int temporal_layers) {
257     rc_cfg_.width = test_video_.width;
258     rc_cfg_.height = test_video_.height;
259     rc_cfg_.max_quantizer = 60;
260     rc_cfg_.min_quantizer = 2;
261     rc_cfg_.target_bandwidth = target_bitrate_;
262     rc_cfg_.buf_initial_sz = 600;
263     rc_cfg_.buf_optimal_sz = 600;
264     rc_cfg_.buf_sz = target_bitrate_;
265     rc_cfg_.undershoot_pct = 50;
266     rc_cfg_.overshoot_pct = 50;
267     rc_cfg_.max_intra_bitrate_pct = 1000;
268     rc_cfg_.framerate = 30.0;
269     if (temporal_layers == 2) {
270       rc_cfg_.layer_target_bitrate[0] = 60 * target_bitrate_ / 100;
271       rc_cfg_.layer_target_bitrate[1] = target_bitrate_;
272       rc_cfg_.ts_rate_decimator[0] = 2;
273       rc_cfg_.ts_rate_decimator[1] = 1;
274     } else if (temporal_layers == 3) {
275       rc_cfg_.layer_target_bitrate[0] = 40 * target_bitrate_ / 100;
276       rc_cfg_.layer_target_bitrate[1] = 60 * target_bitrate_ / 100;
277       rc_cfg_.layer_target_bitrate[2] = target_bitrate_;
278       rc_cfg_.ts_rate_decimator[0] = 4;
279       rc_cfg_.ts_rate_decimator[1] = 2;
280       rc_cfg_.ts_rate_decimator[2] = 1;
281     }
282
283     rc_cfg_.ts_number_layers = temporal_layers;
284
285     // Encoder settings for ground truth.
286     cfg_.g_w = test_video_.width;
287     cfg_.g_h = test_video_.height;
288     cfg_.rc_undershoot_pct = 50;
289     cfg_.rc_overshoot_pct = 50;
290     cfg_.rc_buf_initial_sz = 600;
291     cfg_.rc_buf_optimal_sz = 600;
292     cfg_.rc_buf_sz = target_bitrate_;
293     cfg_.rc_dropframe_thresh = 0;
294     cfg_.rc_min_quantizer = 2;
295     cfg_.rc_max_quantizer = 60;
296     cfg_.rc_end_usage = VPX_CBR;
297     cfg_.g_lag_in_frames = 0;
298     cfg_.g_error_resilient = 1;
299     cfg_.rc_target_bitrate = target_bitrate_;
300     cfg_.kf_min_dist = key_interval_;
301     cfg_.kf_max_dist = key_interval_;
302     // 2 Temporal layers, no spatial layers, CBR mode.
303     cfg_.ss_number_layers = 1;
304     cfg_.ts_number_layers = temporal_layers;
305     if (temporal_layers == 2) {
306       cfg_.ts_rate_decimator[0] = 2;
307       cfg_.ts_rate_decimator[1] = 1;
308       cfg_.ts_periodicity = 2;
309       cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
310       cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
311     } else if (temporal_layers == 3) {
312       cfg_.ts_rate_decimator[0] = 4;
313       cfg_.ts_rate_decimator[1] = 2;
314       cfg_.ts_rate_decimator[2] = 1;
315       cfg_.ts_periodicity = 4;
316       cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
317       cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
318       cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
319     }
320   }
321
322   std::unique_ptr<libvpx::VP8RateControlRTC> rc_api_;
323   libvpx::VP8RateControlRtcConfig rc_cfg_;
324   int key_interval_;
325   int target_bitrate_;
326   Vp8RCTestVideo test_video_;
327   libvpx::VP8FrameParamsQpRTC frame_params_;
328   bool encoder_exit_;
329 };
330
331 TEST_P(Vp8RcInterfaceTest, OneLayer) { RunOneLayer(); }
332
333 TEST_P(Vp8RcInterfaceTest, OneLayerPeriodicKey) { RunPeriodicKey(); }
334
335 TEST_P(Vp8RcInterfaceTest, TemporalLayers2TL) { RunTemporalLayers2TL(); }
336
337 TEST_P(Vp8RcInterfaceTest, TemporalLayers3TL) { RunTemporalLayers3TL(); }
338
339 VP8_INSTANTIATE_TEST_SUITE(Vp8RcInterfaceTest,
340                            ::testing::Values(200, 400, 1000),
341                            ::testing::ValuesIn(kVp8RCTestVectors));
342
343 }  // namespace