tile_config_test.cc (14169B)
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 struct uniformTileConfigParam { 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 }; 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 struct nonUniformTileConfigParam { 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 }; 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 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: 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 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 96 bool DoDecode() const override { return true; } 97 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 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: 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 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 171 bool DoDecode() const override { return true; } 172 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 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 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 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 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 struct TileGroupConfigParams { 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 }; 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 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: 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 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 315 bool DoDecode() const override { return true; } 316 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 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 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