vp9[loongarch]: Optimize fdct4x4/8x8_lsx
[platform/upstream/libvpx.git] / test / vp9_ratectrl_rtc_test.cc
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 kTemporalId[4] = { 0, 2, 1, 2 };
30
31 class RcInterfaceTest
32     : public ::libvpx_test::EncoderTest,
33       public ::libvpx_test::CodecTestWith2Params<int, vpx_rc_mode> {
34  public:
35   RcInterfaceTest()
36       : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
37         encoder_exit_(false) {}
38
39   virtual ~RcInterfaceTest() {}
40
41  protected:
42   virtual void SetUp() {
43     InitializeConfig();
44     SetMode(::libvpx_test::kRealTime);
45   }
46
47   virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
48                                   libvpx_test::Encoder *encoder) {
49     if (video->frame() == 0) {
50       encoder->Control(VP8E_SET_CPUUSED, 7);
51       encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
52       encoder->Control(VP9E_SET_TUNE_CONTENT, 0);
53       encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 1000);
54       encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
55     }
56     frame_params_.frame_type =
57         video->frame() % key_interval_ == 0 ? KEY_FRAME : INTER_FRAME;
58     if (rc_cfg_.rc_mode == VPX_CBR && frame_params_.frame_type == INTER_FRAME) {
59       // Disable golden frame update.
60       frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
61       frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
62     }
63     encoder_exit_ = video->frame() == kNumFrames;
64   }
65
66   virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
67     if (encoder_exit_) {
68       return;
69     }
70     int loopfilter_level, qp;
71     encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
72     encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
73     rc_api_->ComputeQP(frame_params_);
74     ASSERT_EQ(rc_api_->GetQP(), qp);
75     ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
76   }
77
78   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
79     rc_api_->PostEncodeUpdate(pkt->data.frame.sz);
80   }
81
82   void RunOneLayer() {
83     SetConfig(GET_PARAM(2));
84     rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
85     frame_params_.spatial_layer_id = 0;
86     frame_params_.temporal_layer_id = 0;
87
88     ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
89                                          1280, 720, 30, 1, 0, kNumFrames);
90
91     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
92   }
93
94   void RunOneLayerVBRPeriodicKey() {
95     if (GET_PARAM(2) != VPX_VBR) return;
96     key_interval_ = 100;
97     SetConfig(VPX_VBR);
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
108  private:
109   void SetConfig(vpx_rc_mode rc_mode) {
110     rc_cfg_.width = 1280;
111     rc_cfg_.height = 720;
112     rc_cfg_.max_quantizer = 52;
113     rc_cfg_.min_quantizer = 2;
114     rc_cfg_.target_bandwidth = 1000;
115     rc_cfg_.buf_initial_sz = 600;
116     rc_cfg_.buf_optimal_sz = 600;
117     rc_cfg_.buf_sz = 1000;
118     rc_cfg_.undershoot_pct = 50;
119     rc_cfg_.overshoot_pct = 50;
120     rc_cfg_.max_intra_bitrate_pct = 1000;
121     rc_cfg_.framerate = 30.0;
122     rc_cfg_.ss_number_layers = 1;
123     rc_cfg_.ts_number_layers = 1;
124     rc_cfg_.scaling_factor_num[0] = 1;
125     rc_cfg_.scaling_factor_den[0] = 1;
126     rc_cfg_.layer_target_bitrate[0] = 1000;
127     rc_cfg_.max_quantizers[0] = 52;
128     rc_cfg_.min_quantizers[0] = 2;
129     rc_cfg_.rc_mode = rc_mode;
130     rc_cfg_.aq_mode = aq_mode_;
131
132     // Encoder settings for ground truth.
133     cfg_.g_w = 1280;
134     cfg_.g_h = 720;
135     cfg_.rc_undershoot_pct = 50;
136     cfg_.rc_overshoot_pct = 50;
137     cfg_.rc_buf_initial_sz = 600;
138     cfg_.rc_buf_optimal_sz = 600;
139     cfg_.rc_buf_sz = 1000;
140     cfg_.rc_dropframe_thresh = 0;
141     cfg_.rc_min_quantizer = 2;
142     cfg_.rc_max_quantizer = 52;
143     cfg_.rc_end_usage = rc_mode;
144     cfg_.g_lag_in_frames = 0;
145     cfg_.g_error_resilient = 0;
146     cfg_.rc_target_bitrate = 1000;
147     cfg_.kf_min_dist = key_interval_;
148     cfg_.kf_max_dist = key_interval_;
149   }
150
151   std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
152   libvpx::VP9RateControlRtcConfig rc_cfg_;
153   int aq_mode_;
154   int key_interval_;
155   libvpx::VP9FrameParamsQpRTC frame_params_;
156   bool encoder_exit_;
157 };
158
159 class RcInterfaceSvcTest : public ::libvpx_test::EncoderTest,
160                            public ::libvpx_test::CodecTestWithParam<int> {
161  public:
162   RcInterfaceSvcTest() : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)) {}
163   virtual ~RcInterfaceSvcTest() {}
164
165  protected:
166   virtual void SetUp() {
167     InitializeConfig();
168     SetMode(::libvpx_test::kRealTime);
169   }
170
171   virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
172                                   ::libvpx_test::Encoder *encoder) {
173     if (video->frame() == 0) {
174       encoder->Control(VP8E_SET_CPUUSED, 7);
175       encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
176       encoder->Control(VP9E_SET_TUNE_CONTENT, 0);
177       encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
178       encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
179       encoder->Control(VP9E_SET_SVC, 1);
180       encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
181     }
182
183     frame_params_.frame_type = video->frame() == 0 ? KEY_FRAME : INTER_FRAME;
184     if (rc_cfg_.rc_mode == VPX_CBR && frame_params_.frame_type == INTER_FRAME) {
185       // Disable golden frame update.
186       frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
187       frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
188     }
189     encoder_exit_ = video->frame() == kNumFrames;
190     current_superframe_ = video->frame();
191   }
192
193   virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
194     ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
195     while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
196       ParseSuperframeSizes(static_cast<const uint8_t *>(pkt->data.frame.buf),
197                            pkt->data.frame.sz);
198       for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
199         frame_params_.spatial_layer_id = sl;
200         frame_params_.temporal_layer_id = kTemporalId[current_superframe_ % 4];
201         rc_api_->ComputeQP(frame_params_);
202         frame_params_.frame_type = INTER_FRAME;
203         rc_api_->PostEncodeUpdate(sizes_[sl]);
204       }
205     }
206     if (!encoder_exit_) {
207       int loopfilter_level, qp;
208       encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
209       encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
210       ASSERT_EQ(rc_api_->GetQP(), qp);
211       ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
212     }
213   }
214   // This method needs to be overridden because non-reference frames are
215   // expected to be mismatched frames as the encoder will avoid loopfilter on
216   // these frames.
217   virtual void MismatchHook(const vpx_image_t * /*img1*/,
218                             const vpx_image_t * /*img2*/) {}
219
220   void RunSvc() {
221     SetConfigSvc();
222     rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
223     SetEncoderSvc();
224
225     ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
226                                          1280, 720, 30, 1, 0, kNumFrames);
227
228     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
229   }
230
231  private:
232   vpx_codec_err_t ParseSuperframeSizes(const uint8_t *data, size_t data_sz) {
233     uint8_t marker = *(data + data_sz - 1);
234     if ((marker & 0xe0) == 0xc0) {
235       const uint32_t frames = (marker & 0x7) + 1;
236       const uint32_t mag = ((marker >> 3) & 0x3) + 1;
237       const size_t index_sz = 2 + mag * frames;
238       // This chunk is marked as having a superframe index but doesn't have
239       // enough data for it, thus it's an invalid superframe index.
240       if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
241       {
242         const uint8_t marker2 = *(data + data_sz - index_sz);
243         // This chunk is marked as having a superframe index but doesn't have
244         // the matching marker byte at the front of the index therefore it's an
245         // invalid chunk.
246         if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
247       }
248       const uint8_t *x = &data[data_sz - index_sz + 1];
249       for (uint32_t i = 0; i < frames; ++i) {
250         uint32_t this_sz = 0;
251
252         for (uint32_t j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
253         sizes_[i] = this_sz;
254       }
255     }
256     return VPX_CODEC_OK;
257   }
258
259   void SetEncoderSvc() {
260     cfg_.ss_number_layers = 3;
261     cfg_.ts_number_layers = 3;
262     cfg_.g_timebase.num = 1;
263     cfg_.g_timebase.den = 30;
264     svc_params_.scaling_factor_num[0] = 72;
265     svc_params_.scaling_factor_den[0] = 288;
266     svc_params_.scaling_factor_num[1] = 144;
267     svc_params_.scaling_factor_den[1] = 288;
268     svc_params_.scaling_factor_num[2] = 288;
269     svc_params_.scaling_factor_den[2] = 288;
270     for (int i = 0; i < VPX_MAX_LAYERS; ++i) {
271       svc_params_.max_quantizers[i] = 56;
272       svc_params_.min_quantizers[i] = 2;
273       svc_params_.speed_per_layer[i] = 7;
274     }
275     cfg_.rc_end_usage = VPX_CBR;
276     cfg_.g_lag_in_frames = 0;
277     cfg_.g_error_resilient = 0;
278     // 3 temporal layers
279     cfg_.ts_rate_decimator[0] = 4;
280     cfg_.ts_rate_decimator[1] = 2;
281     cfg_.ts_rate_decimator[2] = 1;
282     cfg_.temporal_layering_mode = 3;
283
284     cfg_.rc_buf_initial_sz = 500;
285     cfg_.rc_buf_optimal_sz = 600;
286     cfg_.rc_buf_sz = 1000;
287     cfg_.rc_min_quantizer = 2;
288     cfg_.rc_max_quantizer = 56;
289     cfg_.g_threads = 1;
290     cfg_.kf_max_dist = 9999;
291     cfg_.rc_target_bitrate = 1600;
292     cfg_.rc_overshoot_pct = 50;
293     cfg_.rc_undershoot_pct = 50;
294
295     cfg_.layer_target_bitrate[0] = 100;
296     cfg_.layer_target_bitrate[1] = 140;
297     cfg_.layer_target_bitrate[2] = 200;
298     cfg_.layer_target_bitrate[3] = 250;
299     cfg_.layer_target_bitrate[4] = 350;
300     cfg_.layer_target_bitrate[5] = 500;
301     cfg_.layer_target_bitrate[6] = 450;
302     cfg_.layer_target_bitrate[7] = 630;
303     cfg_.layer_target_bitrate[8] = 900;
304   }
305
306   void SetConfigSvc() {
307     rc_cfg_.width = 1280;
308     rc_cfg_.height = 720;
309     rc_cfg_.max_quantizer = 56;
310     rc_cfg_.min_quantizer = 2;
311     rc_cfg_.target_bandwidth = 1600;
312     rc_cfg_.buf_initial_sz = 500;
313     rc_cfg_.buf_optimal_sz = 600;
314     rc_cfg_.buf_sz = 1000;
315     rc_cfg_.undershoot_pct = 50;
316     rc_cfg_.overshoot_pct = 50;
317     rc_cfg_.max_intra_bitrate_pct = 900;
318     rc_cfg_.framerate = 30.0;
319     rc_cfg_.ss_number_layers = 3;
320     rc_cfg_.ts_number_layers = 3;
321     rc_cfg_.rc_mode = VPX_CBR;
322     rc_cfg_.aq_mode = aq_mode_;
323
324     rc_cfg_.scaling_factor_num[0] = 1;
325     rc_cfg_.scaling_factor_den[0] = 4;
326     rc_cfg_.scaling_factor_num[1] = 2;
327     rc_cfg_.scaling_factor_den[1] = 4;
328     rc_cfg_.scaling_factor_num[2] = 4;
329     rc_cfg_.scaling_factor_den[2] = 4;
330
331     rc_cfg_.ts_rate_decimator[0] = 4;
332     rc_cfg_.ts_rate_decimator[1] = 2;
333     rc_cfg_.ts_rate_decimator[2] = 1;
334
335     rc_cfg_.layer_target_bitrate[0] = 100;
336     rc_cfg_.layer_target_bitrate[1] = 140;
337     rc_cfg_.layer_target_bitrate[2] = 200;
338     rc_cfg_.layer_target_bitrate[3] = 250;
339     rc_cfg_.layer_target_bitrate[4] = 350;
340     rc_cfg_.layer_target_bitrate[5] = 500;
341     rc_cfg_.layer_target_bitrate[6] = 450;
342     rc_cfg_.layer_target_bitrate[7] = 630;
343     rc_cfg_.layer_target_bitrate[8] = 900;
344
345     for (int sl = 0; sl < rc_cfg_.ss_number_layers; ++sl) {
346       for (int tl = 0; tl < rc_cfg_.ts_number_layers; ++tl) {
347         const int i = sl * rc_cfg_.ts_number_layers + tl;
348         rc_cfg_.max_quantizers[i] = 56;
349         rc_cfg_.min_quantizers[i] = 2;
350       }
351     }
352   }
353
354   int aq_mode_;
355   std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
356   libvpx::VP9RateControlRtcConfig rc_cfg_;
357   vpx_svc_extra_cfg_t svc_params_;
358   libvpx::VP9FrameParamsQpRTC frame_params_;
359   bool encoder_exit_;
360   int current_superframe_;
361   uint32_t sizes_[8];
362 };
363
364 TEST_P(RcInterfaceTest, OneLayer) { RunOneLayer(); }
365
366 TEST_P(RcInterfaceTest, OneLayerVBRPeriodicKey) { RunOneLayerVBRPeriodicKey(); }
367
368 TEST_P(RcInterfaceSvcTest, Svc) { RunSvc(); }
369
370 VP9_INSTANTIATE_TEST_SUITE(RcInterfaceTest, ::testing::Values(0, 3),
371                            ::testing::Values(VPX_CBR, VPX_VBR));
372 VP9_INSTANTIATE_TEST_SUITE(RcInterfaceSvcTest, ::testing::Values(0, 3));
373 }  // namespace