blob: 49b0fba94a1091eb7e9ea3062eef1180d0889b39 [file] [log] [blame]
Linfeng Zhang0ba23e82017-12-20 16:27:28 -08001/*
2 * Copyright (c) 2017, 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 <stdint.h>
13#include <stdio.h>
14#include <string.h>
sarahparkera543df52018-11-02 16:02:05 -070015#include <tuple>
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080016
17#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
18
Tom Finegan60e653d2018-05-22 11:34:58 -070019#include "config/aom_config.h"
Tom Finegan44702c82018-05-22 13:00:39 -070020#include "config/av1_rtcd.h"
Tom Finegan60e653d2018-05-22 11:34:58 -070021
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080022#include "aom_ports/aom_timer.h"
23#include "aom_ports/mem.h"
Wan-Teh Changf2d15ee2020-03-10 09:24:43 -070024#include "av1/common/av1_common_int.h"
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080025#include "av1/common/idct.h"
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080026#include "av1/common/scan.h"
27#include "av1/common/txb_common.h"
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080028#include "test/acm_random.h"
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080029#include "test/register_state_check.h"
30#include "test/util.h"
31
32namespace {
33using libaom_test::ACMRandom;
34
35typedef void (*GetNzMapContextsFunc)(const uint8_t *const levels,
36 const int16_t *const scan,
37 const uint16_t eob, const TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +090038 const TX_CLASS tx_class,
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080039 int8_t *const coeff_contexts);
40
41class EncodeTxbTest : public ::testing::TestWithParam<GetNzMapContextsFunc> {
42 public:
43 EncodeTxbTest() : get_nz_map_contexts_func_(GetParam()) {}
44
James Zernf1fa1eb2023-07-25 15:34:13 -070045 ~EncodeTxbTest() override = default;
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080046
James Zernfaa2dcf2023-07-24 18:29:51 -070047 void SetUp() override {
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080048 coeff_contexts_ref_ = reinterpret_cast<int8_t *>(
49 aom_memalign(16, sizeof(*coeff_contexts_ref_) * MAX_TX_SQUARE));
James Zern9dea04e2022-04-28 13:18:36 -070050 ASSERT_NE(coeff_contexts_ref_, nullptr);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080051 coeff_contexts_ = reinterpret_cast<int8_t *>(
52 aom_memalign(16, sizeof(*coeff_contexts_) * MAX_TX_SQUARE));
James Zern9dea04e2022-04-28 13:18:36 -070053 ASSERT_NE(coeff_contexts_, nullptr);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080054 }
55
James Zernfaa2dcf2023-07-24 18:29:51 -070056 void TearDown() override {
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080057 aom_free(coeff_contexts_ref_);
58 aom_free(coeff_contexts_);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080059 }
60
61 void GetNzMapContextsRun() {
62 const int kNumTests = 10;
63 int result = 0;
64
65 for (int is_inter = 0; is_inter < 2; ++is_inter) {
66 for (int tx_type = DCT_DCT; tx_type < TX_TYPES; ++tx_type) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +090067 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080068 for (int tx_size = TX_4X4; tx_size < TX_SIZES_ALL; ++tx_size) {
Kyle Siefring7bb4c542022-12-09 10:27:41 -050069 const int bhl = get_txb_bhl((TX_SIZE)tx_size);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080070 const int width = get_txb_wide((TX_SIZE)tx_size);
71 const int height = get_txb_high((TX_SIZE)tx_size);
72 const int real_width = tx_size_wide[tx_size];
73 const int real_height = tx_size_high[tx_size];
Yaowu Xu5251fd42018-02-24 10:52:18 -080074 const int16_t *const scan = av1_scan_orders[tx_size][tx_type].scan;
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080075
Kyle Siefring7bb4c542022-12-09 10:27:41 -050076 levels_ = set_levels(levels_buf_, height);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080077 for (int i = 0; i < kNumTests && !result; ++i) {
78 for (int eob = 1; eob <= width * height && !result; ++eob) {
Kyle Siefring7bb4c542022-12-09 10:27:41 -050079 InitDataWithEob(scan, bhl, eob);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080080
81 av1_get_nz_map_contexts_c(levels_, scan, eob, (TX_SIZE)tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +090082 tx_class, coeff_contexts_ref_);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080083 get_nz_map_contexts_func_(levels_, scan, eob, (TX_SIZE)tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +090084 tx_class, coeff_contexts_);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080085
86 result = Compare(scan, eob);
87
88 EXPECT_EQ(result, 0)
Kyle Siefring7bb4c542022-12-09 10:27:41 -050089 << " tx_class " << (int)tx_class << " width " << real_width
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +090090 << " height " << real_height << " eob " << eob;
Linfeng Zhang0ba23e82017-12-20 16:27:28 -080091 }
92 }
93 }
94 }
95 }
96 }
97
98 void SpeedTestGetNzMapContextsRun() {
99 const int kNumTests = 2000000000;
100 aom_usec_timer timer;
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300101 aom_usec_timer timer_ref;
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800102
103 printf("Note: Only test the largest possible eob case!\n");
104 for (int tx_size = TX_4X4; tx_size < TX_SIZES_ALL; ++tx_size) {
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500105 const int bhl = get_txb_bhl((TX_SIZE)tx_size);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800106 const int width = get_txb_wide((TX_SIZE)tx_size);
107 const int height = get_txb_high((TX_SIZE)tx_size);
108 const int real_width = tx_size_wide[tx_size];
109 const int real_height = tx_size_high[tx_size];
110 const TX_TYPE tx_type = DCT_DCT;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900111 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Yaowu Xu5251fd42018-02-24 10:52:18 -0800112 const int16_t *const scan = av1_scan_orders[tx_size][tx_type].scan;
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800113 const int eob = width * height;
114 const int numTests = kNumTests / (width * height);
115
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500116 levels_ = set_levels(levels_buf_, height);
117 InitDataWithEob(scan, bhl, eob);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800118
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300119 aom_usec_timer_start(&timer_ref);
120 for (int i = 0; i < numTests; ++i) {
121 av1_get_nz_map_contexts_c(levels_, scan, eob, (TX_SIZE)tx_size,
122 tx_class, coeff_contexts_ref_);
123 }
124 aom_usec_timer_mark(&timer_ref);
125
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500126 levels_ = set_levels(levels_buf_, height);
127 InitDataWithEob(scan, bhl, eob);
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300128
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800129 aom_usec_timer_start(&timer);
130 for (int i = 0; i < numTests; ++i) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900131 get_nz_map_contexts_func_(levels_, scan, eob, (TX_SIZE)tx_size,
132 tx_class, coeff_contexts_);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800133 }
134 aom_usec_timer_mark(&timer);
135
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300136 const int elapsed_time_ref =
137 static_cast<int>(aom_usec_timer_elapsed(&timer_ref));
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800138 const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300139
140 printf("get_nz_map_contexts_%2dx%2d: %7.1f ms ref %7.1f ms gain %4.2f\n",
141 real_width, real_height, elapsed_time / 1000.0,
142 elapsed_time_ref / 1000.0,
143 (elapsed_time_ref * 1.0) / (elapsed_time * 1.0));
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800144 }
145 }
146
147 private:
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500148 void InitDataWithEob(const int16_t *const scan, const int bhl,
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800149 const int eob) {
150 memset(levels_buf_, 0, sizeof(levels_buf_));
151 memset(coeff_contexts_, 0, sizeof(*coeff_contexts_) * MAX_TX_SQUARE);
152
153 for (int c = 0; c < eob; ++c) {
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500154 levels_[get_padded_idx(scan[c], bhl)] =
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800155 static_cast<uint8_t>(clamp(rnd_.Rand8(), 0, INT8_MAX));
Hien Hoefd650a2019-08-27 15:36:23 -0700156 coeff_contexts_[scan[c]] = static_cast<int8_t>(rnd_.Rand16() >> 1);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800157 }
158
159 memcpy(coeff_contexts_ref_, coeff_contexts_,
160 sizeof(*coeff_contexts_) * MAX_TX_SQUARE);
161 }
162
163 bool Compare(const int16_t *const scan, const int eob) const {
164 bool result = false;
165 if (memcmp(coeff_contexts_, coeff_contexts_ref_,
166 sizeof(*coeff_contexts_ref_) * MAX_TX_SQUARE)) {
167 for (int i = 0; i < eob; i++) {
168 const int pos = scan[i];
169 if (coeff_contexts_ref_[pos] != coeff_contexts_[pos]) {
170 printf("coeff_contexts_[%d] diff:%6d (ref),%6d (opt)\n", pos,
171 coeff_contexts_ref_[pos], coeff_contexts_[pos]);
172 result = true;
173 break;
174 }
175 }
176 }
177 return result;
178 }
179
180 GetNzMapContextsFunc get_nz_map_contexts_func_;
181 ACMRandom rnd_;
182 uint8_t levels_buf_[TX_PAD_2D];
183 uint8_t *levels_;
184 int8_t *coeff_contexts_ref_;
185 int8_t *coeff_contexts_;
186};
chiyotsai9dfac722020-07-07 17:43:02 -0700187GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EncodeTxbTest);
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800188
189TEST_P(EncodeTxbTest, GetNzMapContexts) { GetNzMapContextsRun(); }
190
191TEST_P(EncodeTxbTest, DISABLED_SpeedTestGetNzMapContexts) {
192 SpeedTestGetNzMapContextsRun();
193}
194
195#if HAVE_SSE2
Cheng Chen96786fe2020-02-14 17:28:25 -0800196INSTANTIATE_TEST_SUITE_P(SSE2, EncodeTxbTest,
197 ::testing::Values(av1_get_nz_map_contexts_sse2));
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800198#endif
Peng Bin27d7ca92018-03-22 22:25:56 +0800199
Vitalii Dziumenko903ca2f2020-07-08 16:47:57 +0300200#if HAVE_NEON
201INSTANTIATE_TEST_SUITE_P(NEON, EncodeTxbTest,
202 ::testing::Values(av1_get_nz_map_contexts_neon));
203#endif
204
Xing Jina7106c32018-08-14 16:27:56 +0800205typedef void (*av1_txb_init_levels_func)(const tran_low_t *const coeff,
206 const int width, const int height,
207 uint8_t *const levels);
208
sarahparkera543df52018-11-02 16:02:05 -0700209typedef std::tuple<av1_txb_init_levels_func, int> TxbInitLevelParam;
Xing Jina7106c32018-08-14 16:27:56 +0800210
211class EncodeTxbInitLevelTest
212 : public ::testing::TestWithParam<TxbInitLevelParam> {
Peng Bin27d7ca92018-03-22 22:25:56 +0800213 public:
James Zernf1fa1eb2023-07-25 15:34:13 -0700214 ~EncodeTxbInitLevelTest() override = default;
Xing Jina7106c32018-08-14 16:27:56 +0800215 void RunTest(av1_txb_init_levels_func test_func, int tx_size, int is_speed);
Peng Bin27d7ca92018-03-22 22:25:56 +0800216};
chiyotsai9dfac722020-07-07 17:43:02 -0700217GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EncodeTxbInitLevelTest);
Peng Bin27d7ca92018-03-22 22:25:56 +0800218
Xing Jina7106c32018-08-14 16:27:56 +0800219void EncodeTxbInitLevelTest::RunTest(av1_txb_init_levels_func test_func,
220 int tx_size, int is_speed) {
Peng Bin27d7ca92018-03-22 22:25:56 +0800221 const int width = get_txb_wide((TX_SIZE)tx_size);
222 const int height = get_txb_high((TX_SIZE)tx_size);
223 tran_low_t coeff[MAX_TX_SQUARE];
224
225 uint8_t levels_buf[2][TX_PAD_2D];
Kyle Siefring7bb4c542022-12-09 10:27:41 -0500226 uint8_t *const levels0 = set_levels(levels_buf[0], height);
227 uint8_t *const levels1 = set_levels(levels_buf[1], height);
Peng Bin27d7ca92018-03-22 22:25:56 +0800228
229 ACMRandom rnd(ACMRandom::DeterministicSeed());
230 for (int i = 0; i < width * height; i++) {
James Zern6e661502022-08-31 16:21:18 -0700231 coeff[i] = rnd.Rand16Signed();
Peng Bin27d7ca92018-03-22 22:25:56 +0800232 }
233 for (int i = 0; i < TX_PAD_2D; i++) {
234 levels_buf[0][i] = rnd.Rand8();
235 levels_buf[1][i] = rnd.Rand8();
236 }
237 const int run_times = is_speed ? (width * height) * 10000 : 1;
238 aom_usec_timer timer;
239 aom_usec_timer_start(&timer);
240 for (int i = 0; i < run_times; ++i) {
241 av1_txb_init_levels_c(coeff, width, height, levels0);
242 }
243 const double t1 = get_time_mark(&timer);
244 aom_usec_timer_start(&timer);
245 for (int i = 0; i < run_times; ++i) {
Xing Jina7106c32018-08-14 16:27:56 +0800246 test_func(coeff, width, height, levels1);
Peng Bin27d7ca92018-03-22 22:25:56 +0800247 }
248 const double t2 = get_time_mark(&timer);
249 if (is_speed) {
250 printf("init %3dx%-3d:%7.2f/%7.2fns", width, height, t1, t2);
251 printf("(%3.2f)\n", t1 / t2);
252 }
253 const int stride = width + TX_PAD_HOR;
254 for (int r = 0; r < height + TX_PAD_VER; ++r) {
255 for (int c = 0; c < stride; ++c) {
256 ASSERT_EQ(levels_buf[0][c + r * stride], levels_buf[1][c + r * stride])
257 << "[" << r << "," << c << "] " << run_times << width << "x"
258 << height;
259 }
260 }
261}
262
Xing Jina7106c32018-08-14 16:27:56 +0800263TEST_P(EncodeTxbInitLevelTest, match) {
264 RunTest(GET_PARAM(0), GET_PARAM(1), 0);
265}
Peng Bin27d7ca92018-03-22 22:25:56 +0800266
Xing Jina7106c32018-08-14 16:27:56 +0800267TEST_P(EncodeTxbInitLevelTest, DISABLED_Speed) {
268 RunTest(GET_PARAM(0), GET_PARAM(1), 1);
269}
270
271#if HAVE_SSE4_1
Cheng Chen96786fe2020-02-14 17:28:25 -0800272INSTANTIATE_TEST_SUITE_P(
Xing Jina7106c32018-08-14 16:27:56 +0800273 SSE4_1, EncodeTxbInitLevelTest,
274 ::testing::Combine(::testing::Values(&av1_txb_init_levels_sse4_1),
275 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL), 1)));
Peng Bin27d7ca92018-03-22 22:25:56 +0800276#endif
Xing Jina7106c32018-08-14 16:27:56 +0800277#if HAVE_AVX2
Cheng Chen96786fe2020-02-14 17:28:25 -0800278INSTANTIATE_TEST_SUITE_P(
Xing Jina7106c32018-08-14 16:27:56 +0800279 AVX2, EncodeTxbInitLevelTest,
280 ::testing::Combine(::testing::Values(&av1_txb_init_levels_avx2),
281 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL), 1)));
282#endif
Vitalii Dziumenkoe4037542020-04-17 15:36:36 +0300283#if HAVE_NEON
284INSTANTIATE_TEST_SUITE_P(
285 NEON, EncodeTxbInitLevelTest,
286 ::testing::Combine(::testing::Values(&av1_txb_init_levels_neon),
287 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL), 1)));
288#endif
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800289} // namespace