2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
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.
17 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
19 #include "config/aom_config.h"
20 #include "config/av1_rtcd.h"
22 #include "aom_ports/aom_timer.h"
23 #include "aom_ports/mem.h"
24 #include "av1/common/av1_common_int.h"
25 #include "av1/common/idct.h"
26 #include "av1/common/scan.h"
27 #include "av1/common/txb_common.h"
28 #include "test/acm_random.h"
29 #include "test/register_state_check.h"
30 #include "test/util.h"
33 using libaom_test::ACMRandom
;
35 typedef void (*GetNzMapContextsFunc
)(const uint8_t *const levels
,
36 const int16_t *const scan
,
37 const uint16_t eob
, const TX_SIZE tx_size
,
38 const TX_CLASS tx_class
,
39 int8_t *const coeff_contexts
);
41 class EncodeTxbTest
: public ::testing::TestWithParam
<GetNzMapContextsFunc
> {
43 EncodeTxbTest() : get_nz_map_contexts_func_(GetParam()) {}
45 virtual ~EncodeTxbTest() {}
47 virtual void SetUp() {
48 coeff_contexts_ref_
= reinterpret_cast<int8_t *>(
49 aom_memalign(16, sizeof(*coeff_contexts_ref_
) * MAX_TX_SQUARE
));
50 ASSERT_TRUE(coeff_contexts_ref_
!= NULL
);
51 coeff_contexts_
= reinterpret_cast<int8_t *>(
52 aom_memalign(16, sizeof(*coeff_contexts_
) * MAX_TX_SQUARE
));
53 ASSERT_TRUE(coeff_contexts_
!= NULL
);
56 virtual void TearDown() {
57 aom_free(coeff_contexts_ref_
);
58 aom_free(coeff_contexts_
);
61 void GetNzMapContextsRun() {
62 const int kNumTests
= 10;
65 for (int is_inter
= 0; is_inter
< 2; ++is_inter
) {
66 for (int tx_type
= DCT_DCT
; tx_type
< TX_TYPES
; ++tx_type
) {
67 const TX_CLASS tx_class
= tx_type_to_class
[tx_type
];
68 for (int tx_size
= TX_4X4
; tx_size
< TX_SIZES_ALL
; ++tx_size
) {
69 const int bwl
= get_txb_bwl((TX_SIZE
)tx_size
);
70 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
];
74 const int16_t *const scan
= av1_scan_orders
[tx_size
][tx_type
].scan
;
76 levels_
= set_levels(levels_buf_
, width
);
77 for (int i
= 0; i
< kNumTests
&& !result
; ++i
) {
78 for (int eob
= 1; eob
<= width
* height
&& !result
; ++eob
) {
79 InitDataWithEob(scan
, bwl
, eob
);
81 av1_get_nz_map_contexts_c(levels_
, scan
, eob
, (TX_SIZE
)tx_size
,
82 tx_class
, coeff_contexts_ref_
);
83 get_nz_map_contexts_func_(levels_
, scan
, eob
, (TX_SIZE
)tx_size
,
84 tx_class
, coeff_contexts_
);
86 result
= Compare(scan
, eob
);
89 << " tx_class " << tx_class
<< " width " << real_width
90 << " height " << real_height
<< " eob " << eob
;
98 void SpeedTestGetNzMapContextsRun() {
99 const int kNumTests
= 2000000000;
100 aom_usec_timer timer
;
101 aom_usec_timer timer_ref
;
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
) {
105 const int bwl
= get_txb_bwl((TX_SIZE
)tx_size
);
106 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
;
111 const TX_CLASS tx_class
= tx_type_to_class
[tx_type
];
112 const int16_t *const scan
= av1_scan_orders
[tx_size
][tx_type
].scan
;
113 const int eob
= width
* height
;
114 const int numTests
= kNumTests
/ (width
* height
);
116 levels_
= set_levels(levels_buf_
, width
);
117 InitDataWithEob(scan
, bwl
, eob
);
119 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_
);
124 aom_usec_timer_mark(&timer_ref
);
126 levels_
= set_levels(levels_buf_
, width
);
127 InitDataWithEob(scan
, bwl
, eob
);
129 aom_usec_timer_start(&timer
);
130 for (int i
= 0; i
< numTests
; ++i
) {
131 get_nz_map_contexts_func_(levels_
, scan
, eob
, (TX_SIZE
)tx_size
,
132 tx_class
, coeff_contexts_
);
134 aom_usec_timer_mark(&timer
);
136 const int elapsed_time_ref
=
137 static_cast<int>(aom_usec_timer_elapsed(&timer_ref
));
138 const int elapsed_time
= static_cast<int>(aom_usec_timer_elapsed(&timer
));
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));
148 void InitDataWithEob(const int16_t *const scan
, const int bwl
,
150 memset(levels_buf_
, 0, sizeof(levels_buf_
));
151 memset(coeff_contexts_
, 0, sizeof(*coeff_contexts_
) * MAX_TX_SQUARE
);
153 for (int c
= 0; c
< eob
; ++c
) {
154 levels_
[get_padded_idx(scan
[c
], bwl
)] =
155 static_cast<uint8_t>(clamp(rnd_
.Rand8(), 0, INT8_MAX
));
156 coeff_contexts_
[scan
[c
]] = static_cast<int8_t>(rnd_
.Rand16() >> 1);
159 memcpy(coeff_contexts_ref_
, coeff_contexts_
,
160 sizeof(*coeff_contexts_
) * MAX_TX_SQUARE
);
163 bool Compare(const int16_t *const scan
, const int eob
) const {
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
]);
180 GetNzMapContextsFunc get_nz_map_contexts_func_
;
182 uint8_t levels_buf_
[TX_PAD_2D
];
184 int8_t *coeff_contexts_ref_
;
185 int8_t *coeff_contexts_
;
187 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EncodeTxbTest
);
189 TEST_P(EncodeTxbTest
, GetNzMapContexts
) { GetNzMapContextsRun(); }
191 TEST_P(EncodeTxbTest
, DISABLED_SpeedTestGetNzMapContexts
) {
192 SpeedTestGetNzMapContextsRun();
196 INSTANTIATE_TEST_SUITE_P(SSE2
, EncodeTxbTest
,
197 ::testing::Values(av1_get_nz_map_contexts_sse2
));
201 INSTANTIATE_TEST_SUITE_P(NEON
, EncodeTxbTest
,
202 ::testing::Values(av1_get_nz_map_contexts_neon
));
205 typedef void (*av1_txb_init_levels_func
)(const tran_low_t
*const coeff
,
206 const int width
, const int height
,
207 uint8_t *const levels
);
209 typedef std::tuple
<av1_txb_init_levels_func
, int> TxbInitLevelParam
;
211 class EncodeTxbInitLevelTest
212 : public ::testing::TestWithParam
<TxbInitLevelParam
> {
214 virtual ~EncodeTxbInitLevelTest() {}
215 virtual void TearDown() {}
216 void RunTest(av1_txb_init_levels_func test_func
, int tx_size
, int is_speed
);
218 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EncodeTxbInitLevelTest
);
220 void EncodeTxbInitLevelTest::RunTest(av1_txb_init_levels_func test_func
,
221 int tx_size
, int is_speed
) {
222 const int width
= get_txb_wide((TX_SIZE
)tx_size
);
223 const int height
= get_txb_high((TX_SIZE
)tx_size
);
224 tran_low_t coeff
[MAX_TX_SQUARE
];
226 uint8_t levels_buf
[2][TX_PAD_2D
];
227 uint8_t *const levels0
= set_levels(levels_buf
[0], width
);
228 uint8_t *const levels1
= set_levels(levels_buf
[1], width
);
230 ACMRandom
rnd(ACMRandom::DeterministicSeed());
231 for (int i
= 0; i
< width
* height
; i
++) {
232 coeff
[i
] = rnd
.Rand15Signed() + rnd
.Rand15Signed();
234 for (int i
= 0; i
< TX_PAD_2D
; i
++) {
235 levels_buf
[0][i
] = rnd
.Rand8();
236 levels_buf
[1][i
] = rnd
.Rand8();
238 const int run_times
= is_speed
? (width
* height
) * 10000 : 1;
239 aom_usec_timer timer
;
240 aom_usec_timer_start(&timer
);
241 for (int i
= 0; i
< run_times
; ++i
) {
242 av1_txb_init_levels_c(coeff
, width
, height
, levels0
);
244 const double t1
= get_time_mark(&timer
);
245 aom_usec_timer_start(&timer
);
246 for (int i
= 0; i
< run_times
; ++i
) {
247 test_func(coeff
, width
, height
, levels1
);
249 const double t2
= get_time_mark(&timer
);
251 printf("init %3dx%-3d:%7.2f/%7.2fns", width
, height
, t1
, t2
);
252 printf("(%3.2f)\n", t1
/ t2
);
254 const int stride
= width
+ TX_PAD_HOR
;
255 for (int r
= 0; r
< height
+ TX_PAD_VER
; ++r
) {
256 for (int c
= 0; c
< stride
; ++c
) {
257 ASSERT_EQ(levels_buf
[0][c
+ r
* stride
], levels_buf
[1][c
+ r
* stride
])
258 << "[" << r
<< "," << c
<< "] " << run_times
<< width
<< "x"
264 TEST_P(EncodeTxbInitLevelTest
, match
) {
265 RunTest(GET_PARAM(0), GET_PARAM(1), 0);
268 TEST_P(EncodeTxbInitLevelTest
, DISABLED_Speed
) {
269 RunTest(GET_PARAM(0), GET_PARAM(1), 1);
273 INSTANTIATE_TEST_SUITE_P(
274 SSE4_1
, EncodeTxbInitLevelTest
,
275 ::testing::Combine(::testing::Values(&av1_txb_init_levels_sse4_1
),
276 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL
), 1)));
279 INSTANTIATE_TEST_SUITE_P(
280 AVX2
, EncodeTxbInitLevelTest
,
281 ::testing::Combine(::testing::Values(&av1_txb_init_levels_avx2
),
282 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL
), 1)));
285 INSTANTIATE_TEST_SUITE_P(
286 NEON
, EncodeTxbInitLevelTest
,
287 ::testing::Combine(::testing::Values(&av1_txb_init_levels_neon
),
288 ::testing::Range(0, static_cast<int>(TX_SIZES_ALL
), 1)));