xref: /aosp_15_r20/external/libvpx/test/vp9_end_to_end_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1 /*
2  *  Copyright (c) 2014 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 "memory"
12 
13 #include "gtest/gtest.h"
14 
15 #include "test/codec_factory.h"
16 #include "test/encode_test_driver.h"
17 #include "test/i420_video_source.h"
18 #include "test/util.h"
19 #include "test/y4m_video_source.h"
20 #include "test/yuv_video_source.h"
21 #include "vpx_config.h"
22 
23 namespace {
24 
25 const unsigned int kWidth = 160;
26 const unsigned int kHeight = 90;
27 const unsigned int kFramerate = 50;
28 const unsigned int kFrames = 20;
29 const int kBitrate = 500;
30 // List of psnr thresholds for speed settings 0-7 and 5 encoding modes
31 const double kPsnrThreshold[][5] = {
32   { 36.0, 37.0, 37.0, 37.0, 37.0 }, { 35.0, 36.0, 36.0, 36.0, 36.0 },
33   { 34.0, 35.0, 35.0, 35.0, 35.0 }, { 33.0, 34.0, 34.0, 34.0, 34.0 },
34   { 32.0, 33.0, 33.0, 33.0, 33.0 }, { 28.0, 32.0, 32.0, 32.0, 32.0 },
35   { 28.4, 31.0, 31.0, 31.0, 31.0 }, { 27.5, 30.0, 30.0, 30.0, 30.0 },
36 };
37 
38 typedef struct {
39   const char *filename;
40   unsigned int input_bit_depth;
41   vpx_img_fmt fmt;
42   vpx_bit_depth_t bit_depth;
43   unsigned int profile;
44 } TestVideoParam;
45 
46 const TestVideoParam kTestVectors[] = {
47   { "park_joy_90p_8_420.y4m", 8, VPX_IMG_FMT_I420, VPX_BITS_8, 0 },
48   { "park_joy_90p_8_422.y4m", 8, VPX_IMG_FMT_I422, VPX_BITS_8, 1 },
49   { "park_joy_90p_8_444.y4m", 8, VPX_IMG_FMT_I444, VPX_BITS_8, 1 },
50   { "park_joy_90p_8_440.yuv", 8, VPX_IMG_FMT_I440, VPX_BITS_8, 1 },
51 #if CONFIG_VP9_HIGHBITDEPTH
52   { "park_joy_90p_10_420_20f.y4m", 10, VPX_IMG_FMT_I42016, VPX_BITS_10, 2 },
53   { "park_joy_90p_10_422_20f.y4m", 10, VPX_IMG_FMT_I42216, VPX_BITS_10, 3 },
54   { "park_joy_90p_10_444_20f.y4m", 10, VPX_IMG_FMT_I44416, VPX_BITS_10, 3 },
55   { "park_joy_90p_10_440.yuv", 10, VPX_IMG_FMT_I44016, VPX_BITS_10, 3 },
56   { "park_joy_90p_12_420_20f.y4m", 12, VPX_IMG_FMT_I42016, VPX_BITS_12, 2 },
57   { "park_joy_90p_12_422_20f.y4m", 12, VPX_IMG_FMT_I42216, VPX_BITS_12, 3 },
58   { "park_joy_90p_12_444_20f.y4m", 12, VPX_IMG_FMT_I44416, VPX_BITS_12, 3 },
59   { "park_joy_90p_12_440.yuv", 12, VPX_IMG_FMT_I44016, VPX_BITS_12, 3 },
60 #endif  // CONFIG_VP9_HIGHBITDEPTH
61 };
62 
63 const TestVideoParam kTestVectorsNv12[] = {
64   { "hantro_collage_w352h288_nv12.yuv", 8, VPX_IMG_FMT_NV12, VPX_BITS_8, 0 },
65 };
66 
67 // Encoding modes tested
68 const libvpx_test::TestMode kEncodingModeVectors[] = {
69 #if !CONFIG_REALTIME_ONLY
70   ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
71 #endif
72   ::libvpx_test::kRealTime
73 };
74 
75 // Speed settings tested
76 const int kCpuUsedVectors[] = { 1, 2, 3, 5, 6, 7 };
77 
is_extension_y4m(const char * filename)78 int is_extension_y4m(const char *filename) {
79   const char *dot = strrchr(filename, '.');
80   if (!dot || dot == filename) {
81     return 0;
82   } else {
83     return !strcmp(dot, ".y4m");
84   }
85 }
86 
87 class EndToEndTestAdaptiveRDThresh
88     : public ::libvpx_test::EncoderTest,
89       public ::libvpx_test::CodecTestWith2Params<int, int> {
90  protected:
EndToEndTestAdaptiveRDThresh()91   EndToEndTestAdaptiveRDThresh()
92       : EncoderTest(GET_PARAM(0)), cpu_used_start_(GET_PARAM(1)),
93         cpu_used_end_(GET_PARAM(2)) {}
94 
95   ~EndToEndTestAdaptiveRDThresh() override = default;
96 
SetUp()97   void SetUp() override {
98     InitializeConfig();
99     SetMode(::libvpx_test::kRealTime);
100     cfg_.g_lag_in_frames = 0;
101     cfg_.rc_end_usage = VPX_CBR;
102     cfg_.rc_buf_sz = 1000;
103     cfg_.rc_buf_initial_sz = 500;
104     cfg_.rc_buf_optimal_sz = 600;
105     dec_cfg_.threads = 4;
106   }
107 
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)108   void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
109                           ::libvpx_test::Encoder *encoder) override {
110     if (video->frame() == 0) {
111       encoder->Control(VP8E_SET_CPUUSED, cpu_used_start_);
112       encoder->Control(VP9E_SET_ROW_MT, 1);
113       encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
114     }
115     if (video->frame() == 100)
116       encoder->Control(VP8E_SET_CPUUSED, cpu_used_end_);
117   }
118 
119  private:
120   int cpu_used_start_;
121   int cpu_used_end_;
122 };
123 
124 class EndToEndTestLarge
125     : public ::libvpx_test::EncoderTest,
126       public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode,
127                                                  TestVideoParam, int> {
128  protected:
EndToEndTestLarge()129   EndToEndTestLarge()
130       : EncoderTest(GET_PARAM(0)), test_video_param_(GET_PARAM(2)),
131         cpu_used_(GET_PARAM(3)), psnr_(0.0), nframes_(0),
132         encoding_mode_(GET_PARAM(1)) {
133     cyclic_refresh_ = 0;
134     denoiser_on_ = 0;
135   }
136 
137   ~EndToEndTestLarge() override = default;
138 
SetUp()139   void SetUp() override {
140     InitializeConfig();
141     SetMode(encoding_mode_);
142     if (encoding_mode_ != ::libvpx_test::kRealTime) {
143       cfg_.g_lag_in_frames = 5;
144       cfg_.rc_end_usage = VPX_VBR;
145     } else {
146       cfg_.g_lag_in_frames = 0;
147       cfg_.rc_end_usage = VPX_CBR;
148       cfg_.rc_buf_sz = 1000;
149       cfg_.rc_buf_initial_sz = 500;
150       cfg_.rc_buf_optimal_sz = 600;
151     }
152     dec_cfg_.threads = 4;
153   }
154 
BeginPassHook(unsigned int)155   void BeginPassHook(unsigned int) override {
156     psnr_ = 0.0;
157     nframes_ = 0;
158   }
159 
PSNRPktHook(const vpx_codec_cx_pkt_t * pkt)160   void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) override {
161     psnr_ += pkt->data.psnr.psnr[0];
162     nframes_++;
163   }
164 
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)165   void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
166                           ::libvpx_test::Encoder *encoder) override {
167     if (video->frame() == 0) {
168       encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
169       encoder->Control(VP9E_SET_TILE_COLUMNS, 4);
170       encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
171       if (encoding_mode_ != ::libvpx_test::kRealTime) {
172         encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
173         encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
174         encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
175         encoder->Control(VP8E_SET_ARNR_TYPE, 3);
176       } else {
177         encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
178         encoder->Control(VP9E_SET_AQ_MODE, cyclic_refresh_);
179       }
180     }
181   }
182 
GetAveragePsnr() const183   double GetAveragePsnr() const {
184     if (nframes_) return psnr_ / nframes_;
185     return 0.0;
186   }
187 
GetPsnrThreshold()188   double GetPsnrThreshold() {
189     return kPsnrThreshold[cpu_used_][encoding_mode_];
190   }
191 
192   TestVideoParam test_video_param_;
193   int cpu_used_;
194   int cyclic_refresh_;
195   int denoiser_on_;
196 
197  private:
198   double psnr_;
199   unsigned int nframes_;
200   libvpx_test::TestMode encoding_mode_;
201 };
202 
203 #if CONFIG_VP9_DECODER
204 // The test parameters control VP9D_SET_LOOP_FILTER_OPT and the number of
205 // decoder threads.
206 class EndToEndTestLoopFilterThreading
207     : public ::libvpx_test::EncoderTest,
208       public ::libvpx_test::CodecTestWith2Params<bool, int> {
209  protected:
EndToEndTestLoopFilterThreading()210   EndToEndTestLoopFilterThreading()
211       : EncoderTest(GET_PARAM(0)), use_loop_filter_opt_(GET_PARAM(1)) {}
212 
213   ~EndToEndTestLoopFilterThreading() override = default;
214 
SetUp()215   void SetUp() override {
216     InitializeConfig();
217     SetMode(::libvpx_test::kRealTime);
218     cfg_.g_threads = 2;
219     cfg_.g_lag_in_frames = 0;
220     cfg_.rc_target_bitrate = 500;
221     cfg_.rc_end_usage = VPX_CBR;
222     cfg_.kf_min_dist = 1;
223     cfg_.kf_max_dist = 1;
224     dec_cfg_.threads = GET_PARAM(2);
225   }
226 
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)227   void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
228                           ::libvpx_test::Encoder *encoder) override {
229     if (video->frame() == 0) {
230       encoder->Control(VP8E_SET_CPUUSED, 8);
231     }
232     encoder->Control(VP9E_SET_TILE_COLUMNS, 4 - video->frame() % 5);
233   }
234 
PreDecodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Decoder * decoder)235   void PreDecodeFrameHook(::libvpx_test::VideoSource *video,
236                           ::libvpx_test::Decoder *decoder) override {
237     if (video->frame() == 0) {
238       decoder->Control(VP9D_SET_LOOP_FILTER_OPT, use_loop_filter_opt_ ? 1 : 0);
239     }
240   }
241 
242  private:
243   const bool use_loop_filter_opt_;
244 };
245 #endif  // CONFIG_VP9_DECODER
246 
247 class EndToEndNV12 : public EndToEndTestLarge {};
248 
TEST_P(EndToEndNV12,EndtoEndNV12Test)249 TEST_P(EndToEndNV12, EndtoEndNV12Test) {
250   cfg_.rc_target_bitrate = kBitrate;
251   cfg_.g_error_resilient = 0;
252   cfg_.g_profile = test_video_param_.profile;
253   cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
254   cfg_.g_bit_depth = test_video_param_.bit_depth;
255   init_flags_ = VPX_CODEC_USE_PSNR;
256   if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
257 
258   std::unique_ptr<libvpx_test::VideoSource> video;
259 
260   video.reset(new libvpx_test::YUVVideoSource(test_video_param_.filename,
261                                               test_video_param_.fmt, 352, 288,
262                                               30, 1, 0, 100));
263   ASSERT_NE(video.get(), nullptr);
264 
265   ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
266 }
267 
TEST_P(EndToEndTestLarge,EndtoEndPSNRTest)268 TEST_P(EndToEndTestLarge, EndtoEndPSNRTest) {
269   cfg_.rc_target_bitrate = kBitrate;
270   cfg_.g_error_resilient = 0;
271   cfg_.g_profile = test_video_param_.profile;
272   cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
273   cfg_.g_bit_depth = test_video_param_.bit_depth;
274   init_flags_ = VPX_CODEC_USE_PSNR;
275   if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
276 
277   std::unique_ptr<libvpx_test::VideoSource> video;
278   if (is_extension_y4m(test_video_param_.filename)) {
279     video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
280                                                 kFrames));
281   } else {
282     video.reset(new libvpx_test::YUVVideoSource(
283         test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
284         kFramerate, 1, 0, kFrames));
285   }
286   ASSERT_NE(video.get(), nullptr);
287 
288   ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
289   const double psnr = GetAveragePsnr();
290   EXPECT_GT(psnr, GetPsnrThreshold());
291 }
292 
TEST_P(EndToEndTestLarge,EndtoEndPSNRDenoiserAQTest)293 TEST_P(EndToEndTestLarge, EndtoEndPSNRDenoiserAQTest) {
294   cfg_.rc_target_bitrate = kBitrate;
295   cfg_.g_error_resilient = 0;
296   cfg_.g_profile = test_video_param_.profile;
297   cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
298   cfg_.g_bit_depth = test_video_param_.bit_depth;
299   init_flags_ = VPX_CODEC_USE_PSNR;
300   cyclic_refresh_ = 3;
301   denoiser_on_ = 1;
302   if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
303 
304   std::unique_ptr<libvpx_test::VideoSource> video;
305   if (is_extension_y4m(test_video_param_.filename)) {
306     video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
307                                                 kFrames));
308   } else {
309     video.reset(new libvpx_test::YUVVideoSource(
310         test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
311         kFramerate, 1, 0, kFrames));
312   }
313   ASSERT_NE(video.get(), nullptr);
314 
315   ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
316   const double psnr = GetAveragePsnr();
317   EXPECT_GT(psnr, GetPsnrThreshold());
318 }
319 
TEST_P(EndToEndTestAdaptiveRDThresh,EndtoEndAdaptiveRDThreshRowMT)320 TEST_P(EndToEndTestAdaptiveRDThresh, EndtoEndAdaptiveRDThreshRowMT) {
321   cfg_.rc_target_bitrate = kBitrate;
322   cfg_.g_error_resilient = 0;
323   cfg_.g_threads = 2;
324   ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
325                                        0, 400);
326 
327   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
328 }
329 
330 #if CONFIG_VP9_DECODER
TEST_P(EndToEndTestLoopFilterThreading,TileCountChange)331 TEST_P(EndToEndTestLoopFilterThreading, TileCountChange) {
332   ::libvpx_test::RandomVideoSource video;
333   video.SetSize(4096, 2160);
334   video.set_limit(10);
335 
336   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
337 }
338 #endif  // CONFIG_VP9_DECODER
339 
340 VP9_INSTANTIATE_TEST_SUITE(EndToEndTestLarge,
341                            ::testing::ValuesIn(kEncodingModeVectors),
342                            ::testing::ValuesIn(kTestVectors),
343                            ::testing::ValuesIn(kCpuUsedVectors));
344 
345 VP9_INSTANTIATE_TEST_SUITE(EndToEndNV12,
346                            ::testing::Values(::libvpx_test::kRealTime),
347                            ::testing::ValuesIn(kTestVectorsNv12),
348                            ::testing::Values(6, 7, 8));
349 
350 VP9_INSTANTIATE_TEST_SUITE(EndToEndTestAdaptiveRDThresh,
351                            ::testing::Values(5, 6, 7), ::testing::Values(8, 9));
352 
353 #if CONFIG_VP9_DECODER
354 VP9_INSTANTIATE_TEST_SUITE(EndToEndTestLoopFilterThreading, ::testing::Bool(),
355                            ::testing::Range(2, 6));
356 #endif  // CONFIG_VP9_DECODER
357 }  // namespace
358