| /* | |
| * Copyright (c) 2026, Alliance for Open Media. All rights reserved. | |
| * | |
| * This source code is subject to the terms of the BSD 2 Clause License and | |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | |
| * was not distributed with this source code in the LICENSE file, you can | |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open | |
| * Media Patent License 1.0 was not distributed with this source code in the | |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | |
| */ | |
| #include <csetjmp> | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <memory> | |
| #include "gtest/gtest.h" | |
| #include "config/aom_config.h" | |
| #include "aom_mem/aom_mem.h" | |
| #include "av1/common/blockd.h" | |
| #include "av1/common/reconintra.h" | |
| #include "av1/encoder/allintra_vis.h" | |
| namespace { | |
| TEST(EncodeInternal, Buganizer558446054) { | |
| av1_init_intra_predictors(); | |
| MACROBLOCKD xd = {}; | |
| YV12_BUFFER_CONFIG cur_buf = {}; | |
| xd.cur_buf = &cur_buf; | |
| MB_MODE_INFO mbmi = {}; | |
| mbmi.bsize = BLOCK_8X8; | |
| mbmi.partition = PARTITION_NONE; | |
| mbmi.mode = D45_PRED; | |
| MB_MODE_INFO *mbmi_ptr = &mbmi; | |
| xd.mi = &mbmi_ptr; | |
| xd.bd = 8; | |
| xd.left_available = 1; | |
| xd.up_available = 1; | |
| xd.tile.mi_row_end = 100; | |
| xd.tile.mi_col_end = 100; | |
| // Set mb_to_bottom_edge and mb_to_right_edge such that | |
| // yd + txhpx < 0 and xr < 0: | |
| // yd + txhpx = (mb_to_bottom_edge >> 3) + hpx - y = -16 + 8 - 0 = -8 < 0 | |
| // xr = (mb_to_right_edge >> 3) + wpx - x - txwpx = -5 + 8 - 0 - 4 = -1 < 0 | |
| // xr + txwpx = 3 > 0 (so n_top_px = 3). | |
| xd.mb_to_bottom_edge = -16 * 8; | |
| xd.mb_to_right_edge = -5 * 8; | |
| uint8_t ref_buf[64 * 64]; | |
| memset(ref_buf, 200, sizeof(ref_buf)); | |
| uint8_t dst_buf[64 * 64] = { 0 }; | |
| av1_predict_intra_block(&xd, BLOCK_64X64, /*enable_intra_edge_filter=*/0, | |
| /*wpx=*/8, /*hpx=*/8, TX_4X4, D45_PRED, | |
| /*angle_delta=*/0, /*use_palette=*/0, | |
| FILTER_INTRA_MODES, ref_buf + 64 * 8 + 8, 64, dst_buf, | |
| 64, /*col_off=*/0, /*row_off=*/0, /*plane=*/0); | |
| // In Debug builds (-UNDEBUG), reverting clamp() triggers: | |
| // Assertion `n_left_px >= 0' failed. | |
| // In Release builds (-DNDEBUG), reverting clamp() causes n_topright_px < 0 | |
| // (-4 < 0), skipping top-right extension of above_row[3]=200 into | |
| // above_row[4..7] and leaving dst_buf[3] == 127 instead of 200. | |
| ASSERT_EQ(dst_buf[3], 200); | |
| } | |
| TEST(EncodeInternal, Buganizer558463892_558589747) { | |
| std::unique_ptr<AV1_COMP> cpi_test(new AV1_COMP()); | |
| struct aom_internal_error_info error = {}; | |
| if (setjmp(error.jmp)) FAIL(); | |
| error.setjmp = 1; | |
| cpi_test->common.error = &error; | |
| cpi_test->frame_info.mi_rows = 16; | |
| cpi_test->frame_info.mi_cols = 16; | |
| av1_init_mb_wiener_var_buffer(cpi_test.get()); | |
| ASSERT_NE(cpi_test->mb_weber_stats, nullptr); | |
| cpi_test->mb_weber_stats[0].satd = 12345; | |
| // Increase dimensions to 64x64 MI units: mb_weber_stats must be reallocated. | |
| cpi_test->frame_info.mi_rows = 64; | |
| cpi_test->frame_info.mi_cols = 64; | |
| av1_init_mb_wiener_var_buffer(cpi_test.get()); | |
| EXPECT_EQ(cpi_test->mb_weber_stats[0].satd, 0); | |
| aom_free(cpi_test->mb_weber_stats); | |
| } | |
| TEST(EncodeInternal, Buganizer558417547) { | |
| std::unique_ptr<AV1_COMP> cpi_test(new AV1_COMP()); | |
| SequenceHeader seq_params = {}; | |
| seq_params.bit_depth = AOM_BITS_8; | |
| seq_params.sb_size = BLOCK_64X64; | |
| cpi_test->common.seq_params = &seq_params; | |
| cpi_test->common.mi_params.mi_rows = 16; | |
| cpi_test->common.mi_params.mi_cols = 16; | |
| cpi_test->common.quant_params.base_qindex = 128; | |
| cpi_test->common.delta_q_info.delta_q_res = 4; | |
| cpi_test->frame_info.mi_rows = 16; | |
| cpi_test->frame_info.mi_cols = 16; | |
| cpi_test->norm_wiener_variance = 100; | |
| struct aom_internal_error_info error = {}; | |
| if (setjmp(error.jmp)) FAIL(); | |
| error.setjmp = 1; | |
| cpi_test->common.error = &error; | |
| av1_init_mb_wiener_var_buffer(cpi_test.get()); | |
| ASSERT_NE(cpi_test->mb_weber_stats, nullptr); | |
| // Set large SATD and distortion values exceeding INT32_MAX. | |
| for (int i = 0; i < 16 * 16; ++i) { | |
| cpi_test->mb_weber_stats[i].satd = 3000000000LL; | |
| cpi_test->mb_weber_stats[i].distortion = 3000000000LL; | |
| cpi_test->mb_weber_stats[i].rec_pix_max = 255; | |
| } | |
| // Test out-of-bounds / negative mi_row and mi_col without crashing or SIGFPE. | |
| int q_neg = av1_get_sbq_perceptual_ai(cpi_test.get(), BLOCK_64X64, -16, -16); | |
| EXPECT_GE(q_neg, 0); | |
| int q_oob = av1_get_sbq_perceptual_ai(cpi_test.get(), BLOCK_64X64, 100, 100); | |
| EXPECT_GE(q_oob, 0); | |
| aom_free(cpi_test->mb_weber_stats); | |
| } | |
| } // namespace |