xref: /aosp_15_r20/external/libaom/test/tile_config_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2020, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include "aom/aom_codec.h"
13 #include "aom_dsp/aom_dsp_common.h"
14 #include "gtest/gtest.h"
15 #include "test/codec_factory.h"
16 #include "test/encode_test_driver.h"
17 #include "test/y4m_video_source.h"
18 #include "test/i420_video_source.h"
19 #include "test/util.h"
20 
21 namespace {
22 typedef struct {
23   // Superblock size
24   const unsigned int sb_size;
25   // log2(number of tile rows)
26   const unsigned int tile_rows;
27   // log2(number of tile columns)
28   const unsigned int tile_cols;
29 } uniformTileConfigParam;
30 
31 const libaom_test::TestMode kTestModeParams[] =
32 #if CONFIG_REALTIME_ONLY
33     { ::libaom_test::kRealTime };
34 #else
35     { ::libaom_test::kRealTime, ::libaom_test::kOnePassGood,
36       ::libaom_test::kTwoPassGood };
37 #endif
38 
39 static const uniformTileConfigParam uniformTileConfigParams[] = {
40   { 128, 0, 0 }, { 128, 0, 2 }, { 128, 2, 0 }, { 128, 1, 2 }, { 128, 2, 2 },
41   { 128, 3, 2 }, { 64, 0, 0 },  { 64, 0, 2 },  { 64, 2, 0 },  { 64, 1, 2 },
42   { 64, 2, 2 },  { 64, 3, 3 },  { 64, 4, 4 }
43 };
44 
45 typedef struct {
46   // Superblock size
47   const unsigned int sb_size;
48   // number of tile widths
49   const unsigned int tile_width_count;
50   // list of tile widths
51   int tile_widths[AOM_MAX_TILE_COLS];
52   // number of tile heights
53   const unsigned int tile_height_count;
54   // list of tile heights
55   int tile_heights[AOM_MAX_TILE_ROWS];
56 } nonUniformTileConfigParam;
57 
58 const nonUniformTileConfigParam nonUniformTileConfigParams[] = {
59   { 64, 1, { 3 }, 1, { 3 } },          { 64, 2, { 1, 2 }, 2, { 1, 2 } },
60   { 64, 3, { 2, 3, 4 }, 2, { 2, 3 } }, { 128, 1, { 3 }, 1, { 3 } },
61   { 128, 2, { 1, 2 }, 2, { 1, 2 } },   { 128, 3, { 2, 3, 4 }, 2, { 2, 3 } },
62 };
63 
64 // Find smallest k>=0 such that (blk_size << k) >= target
tile_log2(int blk_size,int target)65 static inline int tile_log2(int blk_size, int target) {
66   int k;
67   for (k = 0; (blk_size << k) < target; k++) {
68   }
69   return k;
70 }
71 
72 // This class is used to validate tile configuration for uniform spacing.
73 class UniformTileConfigTestLarge
74     : public ::libaom_test::CodecTestWith3Params<
75           libaom_test::TestMode, uniformTileConfigParam, aom_rc_mode>,
76       public ::libaom_test::EncoderTest {
77  protected:
UniformTileConfigTestLarge()78   UniformTileConfigTestLarge()
79       : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
80         tile_config_param_(GET_PARAM(2)), end_usage_check_(GET_PARAM(3)) {
81     tile_config_violated_ = false;
82     max_tile_cols_log2_ = tile_log2(1, AOM_MAX_TILE_COLS);
83     max_tile_rows_log2_ = tile_log2(1, AOM_MAX_TILE_ROWS);
84   }
85   ~UniformTileConfigTestLarge() override = default;
86 
SetUp()87   void SetUp() override {
88     InitializeConfig(encoding_mode_);
89     const aom_rational timebase = { 1, 30 };
90     cfg_.g_timebase = timebase;
91     cfg_.rc_end_usage = end_usage_check_;
92     cfg_.g_threads = 1;
93     cfg_.g_lag_in_frames = 19;
94   }
95 
DoDecode() const96   bool DoDecode() const override { return true; }
97 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)98   void PreEncodeFrameHook(::libaom_test::VideoSource *video,
99                           ::libaom_test::Encoder *encoder) override {
100     if (video->frame() == 0) {
101       encoder->Control(AV1E_SET_TILE_COLUMNS, tile_config_param_.tile_cols);
102       encoder->Control(AV1E_SET_TILE_ROWS, tile_config_param_.tile_rows);
103       encoder->Control(AOME_SET_CPUUSED, 5);
104       encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
105       encoder->Control(AV1E_SET_SUPERBLOCK_SIZE,
106                        tile_config_param_.sb_size == 64
107                            ? AOM_SUPERBLOCK_SIZE_64X64
108                            : AOM_SUPERBLOCK_SIZE_128X128);
109     }
110   }
111 
HandleDecodeResult(const aom_codec_err_t res_dec,libaom_test::Decoder * decoder)112   bool HandleDecodeResult(const aom_codec_err_t res_dec,
113                           libaom_test::Decoder *decoder) override {
114     EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
115     if (AOM_CODEC_OK == res_dec) {
116       aom_codec_ctx_t *ctx_dec = decoder->GetDecoder();
117       aom_tile_info tile_info;
118       int config_tile_columns = AOMMIN(1 << (int)tile_config_param_.tile_cols,
119                                        1 << max_tile_cols_log2_);
120       int config_tile_rows = AOMMIN(1 << (int)tile_config_param_.tile_rows,
121                                     1 << max_tile_rows_log2_);
122 
123       AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_TILE_INFO, &tile_info);
124       if (tile_info.tile_columns != config_tile_columns ||
125           tile_info.tile_rows != config_tile_rows) {
126         tile_config_violated_ = true;
127       }
128     }
129     return AOM_CODEC_OK == res_dec;
130   }
131 
132   ::libaom_test::TestMode encoding_mode_;
133   const uniformTileConfigParam tile_config_param_;
134   int max_tile_cols_log2_;
135   int max_tile_rows_log2_;
136   bool tile_config_violated_;
137   aom_rc_mode end_usage_check_;
138 };
139 
140 // This class is used to validate tile configuration for non uniform spacing.
141 class NonUniformTileConfigTestLarge
142     : public ::libaom_test::CodecTestWith3Params<
143           libaom_test::TestMode, nonUniformTileConfigParam, aom_rc_mode>,
144       public ::libaom_test::EncoderTest {
145  protected:
NonUniformTileConfigTestLarge()146   NonUniformTileConfigTestLarge()
147       : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
148         tile_config_param_(GET_PARAM(2)), rc_end_usage_(GET_PARAM(3)) {
149     tile_config_violated_ = false;
150   }
151   ~NonUniformTileConfigTestLarge() override = default;
152 
SetUp()153   void SetUp() override {
154     InitializeConfig(encoding_mode_);
155     const aom_rational timebase = { 1, 30 };
156     cfg_.g_timebase = timebase;
157     cfg_.rc_end_usage = rc_end_usage_;
158     cfg_.g_threads = 1;
159     cfg_.g_lag_in_frames = 35;
160     cfg_.rc_target_bitrate = 1000;
161     cfg_.tile_width_count = tile_config_param_.tile_width_count;
162     memcpy(cfg_.tile_widths, tile_config_param_.tile_widths,
163            sizeof(tile_config_param_.tile_widths[0]) *
164                tile_config_param_.tile_width_count);
165     cfg_.tile_height_count = tile_config_param_.tile_height_count;
166     memcpy(cfg_.tile_heights, tile_config_param_.tile_heights,
167            sizeof(tile_config_param_.tile_heights[0]) *
168                tile_config_param_.tile_height_count);
169   }
170 
DoDecode() const171   bool DoDecode() const override { return true; }
172 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)173   void PreEncodeFrameHook(::libaom_test::VideoSource *video,
174                           ::libaom_test::Encoder *encoder) override {
175     if (video->frame() == 0) {
176       encoder->Control(AOME_SET_CPUUSED, 5);
177       encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
178       encoder->Control(AV1E_SET_SUPERBLOCK_SIZE,
179                        tile_config_param_.sb_size == 64
180                            ? AOM_SUPERBLOCK_SIZE_64X64
181                            : AOM_SUPERBLOCK_SIZE_128X128);
182     }
183   }
184 
HandleDecodeResult(const aom_codec_err_t res_dec,libaom_test::Decoder * decoder)185   bool HandleDecodeResult(const aom_codec_err_t res_dec,
186                           libaom_test::Decoder *decoder) override {
187     EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
188     if (AOM_CODEC_OK == res_dec) {
189       aom_codec_ctx_t *ctx_dec = decoder->GetDecoder();
190       aom_tile_info tile_info;
191       AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_TILE_INFO, &tile_info);
192 
193       // check validity of tile cols
194       int tile_col_idx, tile_col = 0;
195       for (tile_col_idx = 0; tile_col_idx < tile_info.tile_columns - 1;
196            tile_col_idx++) {
197         if (tile_config_param_.tile_widths[tile_col] !=
198             tile_info.tile_widths[tile_col_idx])
199           tile_config_violated_ = true;
200         tile_col = (tile_col + 1) % (int)tile_config_param_.tile_width_count;
201       }
202       // last column may not be able to accommodate config, but if it is
203       // greater than what is configured, there is a violation.
204       if (tile_config_param_.tile_widths[tile_col] <
205           tile_info.tile_widths[tile_col_idx])
206         tile_config_violated_ = true;
207 
208       // check validity of tile rows
209       int tile_row_idx, tile_row = 0;
210       for (tile_row_idx = 0; tile_row_idx < tile_info.tile_rows - 1;
211            tile_row_idx++) {
212         if (tile_config_param_.tile_heights[tile_row] !=
213             tile_info.tile_heights[tile_row_idx])
214           tile_config_violated_ = true;
215         tile_row = (tile_row + 1) % (int)tile_config_param_.tile_height_count;
216       }
217       // last row may not be able to accommodate config, but if it is
218       // greater than what is configured, there is a violation.
219       if (tile_config_param_.tile_heights[tile_row] <
220           tile_info.tile_heights[tile_row_idx])
221         tile_config_violated_ = true;
222     }
223     return AOM_CODEC_OK == res_dec;
224   }
225 
226   ::libaom_test::TestMode encoding_mode_;
227   const nonUniformTileConfigParam tile_config_param_;
228   bool tile_config_violated_;
229   aom_rc_mode rc_end_usage_;
230 };
231 
TEST_P(UniformTileConfigTestLarge,UniformTileConfigTest)232 TEST_P(UniformTileConfigTestLarge, UniformTileConfigTest) {
233   ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 1);
234   ASSERT_NO_FATAL_FAILURE(video.Begin());
235 
236   int max_tiles_cols = video.img()->w / (int)tile_config_param_.sb_size;
237   int max_tiles_rows = video.img()->h / (int)tile_config_param_.sb_size;
238   max_tile_cols_log2_ = tile_log2(1, AOMMIN(max_tiles_cols, AOM_MAX_TILE_COLS));
239   max_tile_rows_log2_ = tile_log2(1, AOMMIN(max_tiles_rows, AOM_MAX_TILE_ROWS));
240 
241   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
242   ASSERT_EQ(tile_config_violated_, false);
243 }
244 
TEST_P(UniformTileConfigTestLarge,UniformTileConfigTestLowRes)245 TEST_P(UniformTileConfigTestLarge, UniformTileConfigTestLowRes) {
246   ::libaom_test::Y4mVideoSource video("screendata.y4m", 0, 1);
247   ASSERT_NO_FATAL_FAILURE(video.Begin());
248 
249   int max_tiles_cols = video.img()->w / (int)tile_config_param_.sb_size;
250   int max_tiles_rows = video.img()->h / (int)tile_config_param_.sb_size;
251   max_tile_cols_log2_ = tile_log2(1, AOMMIN(max_tiles_cols, AOM_MAX_TILE_COLS));
252   max_tile_rows_log2_ = tile_log2(1, AOMMIN(max_tiles_rows, AOM_MAX_TILE_ROWS));
253 
254   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
255   ASSERT_EQ(tile_config_violated_, false);
256 }
257 
TEST_P(NonUniformTileConfigTestLarge,NonUniformTileConfigTest)258 TEST_P(NonUniformTileConfigTestLarge, NonUniformTileConfigTest) {
259   ::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 1);
260   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
261   ASSERT_EQ(tile_config_violated_, false);
262 }
263 
264 AV1_INSTANTIATE_TEST_SUITE(UniformTileConfigTestLarge,
265                            ::testing::ValuesIn(kTestModeParams),
266                            ::testing::ValuesIn(uniformTileConfigParams),
267                            ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ));
268 
269 AV1_INSTANTIATE_TEST_SUITE(NonUniformTileConfigTestLarge,
270                            ::testing::ValuesIn(kTestModeParams),
271                            ::testing::ValuesIn(nonUniformTileConfigParams),
272                            ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ));
273 
274 typedef struct {
275   // Number of tile groups to set.
276   const int num_tg;
277   // Number of tile rows to set
278   const int num_tile_rows;
279   // Number of tile columns to set
280   const int num_tile_cols;
281 } TileGroupConfigParams;
282 
283 static const TileGroupConfigParams tileGroupTestParams[] = {
284   { 5, 4, 4 }, { 3, 3, 3 }, { 5, 3, 3 }, { 7, 5, 5 }, { 7, 3, 3 }, { 7, 4, 4 }
285 };
286 
operator <<(std::ostream & os,const TileGroupConfigParams & test_arg)287 std::ostream &operator<<(std::ostream &os,
288                          const TileGroupConfigParams &test_arg) {
289   return os << "TileGroupConfigParams { num_tg:" << test_arg.num_tg
290             << " num_tile_rows:" << test_arg.num_tile_rows
291             << " num_tile_cols:" << test_arg.num_tile_cols << " }";
292 }
293 
294 // This class is used to test number of tile groups present in header.
295 class TileGroupTestLarge
296     : public ::libaom_test::CodecTestWith2Params<libaom_test::TestMode,
297                                                  TileGroupConfigParams>,
298       public ::libaom_test::EncoderTest {
299  protected:
TileGroupTestLarge()300   TileGroupTestLarge()
301       : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
302         tile_group_config_params_(GET_PARAM(2)) {
303     tile_group_config_violated_ = false;
304   }
305   ~TileGroupTestLarge() override = default;
306 
SetUp()307   void SetUp() override {
308     InitializeConfig(encoding_mode_);
309     const aom_rational timebase = { 1, 30 };
310     cfg_.g_timebase = timebase;
311     cfg_.rc_end_usage = AOM_Q;
312     cfg_.g_threads = 1;
313   }
314 
DoDecode() const315   bool DoDecode() const override { return true; }
316 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)317   void PreEncodeFrameHook(::libaom_test::VideoSource *video,
318                           ::libaom_test::Encoder *encoder) override {
319     if (video->frame() == 0) {
320       encoder->Control(AOME_SET_CPUUSED, 5);
321       encoder->Control(AV1E_SET_NUM_TG, tile_group_config_params_.num_tg);
322       encoder->Control(AV1E_SET_TILE_COLUMNS,
323                        tile_group_config_params_.num_tile_cols);
324       encoder->Control(AV1E_SET_TILE_ROWS,
325                        tile_group_config_params_.num_tile_rows);
326     }
327   }
328 
HandleDecodeResult(const aom_codec_err_t res_dec,libaom_test::Decoder * decoder)329   bool HandleDecodeResult(const aom_codec_err_t res_dec,
330                           libaom_test::Decoder *decoder) override {
331     EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
332     if (AOM_CODEC_OK == res_dec) {
333       aom_tile_info tile_info;
334       aom_codec_ctx_t *ctx_dec = decoder->GetDecoder();
335       AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_TILE_INFO, &tile_info);
336       AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_SHOW_EXISTING_FRAME_FLAG,
337                                     &show_existing_frame_);
338       if (tile_info.num_tile_groups != tile_group_config_params_.num_tg &&
339           !show_existing_frame_)
340         tile_group_config_violated_ = true;
341       EXPECT_EQ(tile_group_config_violated_, false);
342     }
343     return AOM_CODEC_OK == res_dec;
344   }
345 
346   int show_existing_frame_;
347   bool tile_group_config_violated_;
348   aom_rc_mode end_usage_check_;
349   ::libaom_test::TestMode encoding_mode_;
350   const TileGroupConfigParams tile_group_config_params_;
351 };
352 
TEST_P(TileGroupTestLarge,TileGroupCountTest)353 TEST_P(TileGroupTestLarge, TileGroupCountTest) {
354   libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480,
355                                      cfg_.g_timebase.den, cfg_.g_timebase.num,
356                                      0, 5);
357   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
358 }
359 
360 AV1_INSTANTIATE_TEST_SUITE(TileGroupTestLarge,
361                            ::testing::ValuesIn(kTestModeParams),
362                            ::testing::ValuesIn(tileGroupTestParams));
363 }  // namespace
364