Bug 1797755 - Part 5: Use a single initial mark stack size regardless of whether...
[gecko.git] / third_party / aom / test / quantize_func_test.cc
blob554d0c72146a44ff91d072b9a457be97611f94d3
1 /*
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.
12 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
14 #include "config/aom_config.h"
15 #include "config/aom_dsp_rtcd.h"
16 #include "config/av1_rtcd.h"
18 #include "aom/aom_codec.h"
19 #include "aom_ports/aom_timer.h"
20 #include "av1/encoder/encoder.h"
21 #include "av1/common/scan.h"
22 #include "test/acm_random.h"
23 #include "test/clear_system_state.h"
24 #include "test/register_state_check.h"
25 #include "test/util.h"
27 namespace {
28 using libaom_test::ACMRandom;
30 #define QUAN_PARAM_LIST \
31 const tran_low_t *coeff_ptr, intptr_t n_coeffs, const int16_t *zbin_ptr, \
32 const int16_t *round_ptr, const int16_t *quant_ptr, \
33 const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, \
34 tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, \
35 const int16_t *scan, const int16_t *iscan
37 typedef void (*QuantizeFunc)(QUAN_PARAM_LIST);
38 typedef void (*QuantizeFuncHbd)(QUAN_PARAM_LIST, int log_scale);
40 #define HBD_QUAN_FUNC \
41 fn(coeff_ptr, n_coeffs, zbin_ptr, round_ptr, quant_ptr, quant_shift_ptr, \
42 qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, log_scale)
44 #define LBD_QUAN_FUNC \
45 fn(coeff_ptr, n_coeffs, zbin_ptr, round_ptr, quant_ptr, quant_shift_ptr, \
46 qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan)
48 template <QuantizeFuncHbd fn>
49 void highbd_quan16x16_wrapper(QUAN_PARAM_LIST) {
50 const int log_scale = 0;
51 HBD_QUAN_FUNC;
54 template <QuantizeFuncHbd fn>
55 void highbd_quan32x32_wrapper(QUAN_PARAM_LIST) {
56 const int log_scale = 1;
57 HBD_QUAN_FUNC;
60 template <QuantizeFuncHbd fn>
61 void highbd_quan64x64_wrapper(QUAN_PARAM_LIST) {
62 const int log_scale = 2;
63 HBD_QUAN_FUNC;
66 typedef enum { TYPE_B, TYPE_DC, TYPE_FP } QuantType;
68 using ::testing::tuple;
69 typedef tuple<QuantizeFunc, QuantizeFunc, TX_SIZE, QuantType, aom_bit_depth_t>
70 QuantizeParam;
72 typedef struct {
73 QUANTS quant;
74 Dequants dequant;
75 } QuanTable;
77 const int kTestNum = 1000;
79 class QuantizeTest : public ::testing::TestWithParam<QuantizeParam> {
80 protected:
81 QuantizeTest()
82 : quant_ref_(GET_PARAM(0)), quant_(GET_PARAM(1)), tx_size_(GET_PARAM(2)),
83 type_(GET_PARAM(3)), bd_(GET_PARAM(4)) {}
85 virtual ~QuantizeTest() {}
87 virtual void SetUp() {
88 qtab_ = reinterpret_cast<QuanTable *>(aom_memalign(32, sizeof(*qtab_)));
89 const int n_coeffs = coeff_num();
90 coeff_ = reinterpret_cast<tran_low_t *>(
91 aom_memalign(32, 6 * n_coeffs * sizeof(tran_low_t)));
92 InitQuantizer();
95 virtual void TearDown() {
96 aom_free(qtab_);
97 qtab_ = NULL;
98 aom_free(coeff_);
99 coeff_ = NULL;
100 libaom_test::ClearSystemState();
103 void InitQuantizer() {
104 av1_build_quantizer(bd_, 0, 0, 0, 0, 0, &qtab_->quant, &qtab_->dequant);
107 void QuantizeRun(bool is_loop, int q = 0, int test_num = 1) {
108 tran_low_t *coeff_ptr = coeff_;
109 const intptr_t n_coeffs = coeff_num();
111 tran_low_t *qcoeff_ref = coeff_ptr + n_coeffs;
112 tran_low_t *dqcoeff_ref = qcoeff_ref + n_coeffs;
114 tran_low_t *qcoeff = dqcoeff_ref + n_coeffs;
115 tran_low_t *dqcoeff = qcoeff + n_coeffs;
116 uint16_t *eob = (uint16_t *)(dqcoeff + n_coeffs);
118 // Testing uses 2-D DCT scan order table
119 const SCAN_ORDER *const sc = get_default_scan(tx_size_, DCT_DCT);
121 // Testing uses luminance quantization table
122 const int16_t *zbin = qtab_->quant.y_zbin[q];
124 const int16_t *round = 0;
125 const int16_t *quant = 0;
126 if (type_ == TYPE_B) {
127 round = qtab_->quant.y_round[q];
128 quant = qtab_->quant.y_quant[q];
129 } else if (type_ == TYPE_FP) {
130 round = qtab_->quant.y_round_fp[q];
131 quant = qtab_->quant.y_quant_fp[q];
134 const int16_t *quant_shift = qtab_->quant.y_quant_shift[q];
135 const int16_t *dequant = qtab_->dequant.y_dequant_QTX[q];
137 for (int i = 0; i < test_num; ++i) {
138 if (is_loop) FillCoeffRandom();
140 memset(qcoeff_ref, 0, 5 * n_coeffs * sizeof(*qcoeff_ref));
142 quant_ref_(coeff_ptr, n_coeffs, zbin, round, quant, quant_shift,
143 qcoeff_ref, dqcoeff_ref, dequant, &eob[0], sc->scan,
144 sc->iscan);
146 ASM_REGISTER_STATE_CHECK(quant_(coeff_ptr, n_coeffs, zbin, round, quant,
147 quant_shift, qcoeff, dqcoeff, dequant,
148 &eob[1], sc->scan, sc->iscan));
150 for (int j = 0; j < n_coeffs; ++j) {
151 ASSERT_EQ(qcoeff_ref[j], qcoeff[j])
152 << "Q mismatch on test: " << i << " at position: " << j
153 << " Q: " << q << " coeff: " << coeff_ptr[j];
156 for (int j = 0; j < n_coeffs; ++j) {
157 ASSERT_EQ(dqcoeff_ref[j], dqcoeff[j])
158 << "Dq mismatch on test: " << i << " at position: " << j
159 << " Q: " << q << " coeff: " << coeff_ptr[j];
162 ASSERT_EQ(eob[0], eob[1])
163 << "eobs mismatch on test: " << i << " Q: " << q;
167 void CompareResults(const tran_low_t *buf_ref, const tran_low_t *buf,
168 int size, const char *text, int q, int number) {
169 int i;
170 for (i = 0; i < size; ++i) {
171 ASSERT_EQ(buf_ref[i], buf[i]) << text << " mismatch on test: " << number
172 << " at position: " << i << " Q: " << q;
176 int coeff_num() const { return av1_get_max_eob(tx_size_); }
178 void FillCoeff(tran_low_t c) {
179 const int n_coeffs = coeff_num();
180 for (int i = 0; i < n_coeffs; ++i) {
181 coeff_[i] = c;
185 void FillCoeffRandom() {
186 const int n_coeffs = coeff_num();
187 FillCoeffZero();
188 int num = rnd_.Rand16() % n_coeffs;
189 for (int i = 0; i < num; ++i) {
190 coeff_[i] = GetRandomCoeff();
194 void FillCoeffZero() { FillCoeff(0); }
196 void FillCoeffConstant() {
197 tran_low_t c = GetRandomCoeff();
198 FillCoeff(c);
201 void FillDcOnly() {
202 FillCoeffZero();
203 coeff_[0] = GetRandomCoeff();
206 void FillDcLargeNegative() {
207 FillCoeffZero();
208 // Generate a qcoeff which contains 512/-512 (0x0100/0xFE00) to catch issues
209 // like BUG=883 where the constant being compared was incorrectly
210 // initialized.
211 coeff_[0] = -8191;
214 tran_low_t GetRandomCoeff() {
215 tran_low_t coeff;
216 if (bd_ == AOM_BITS_8) {
217 coeff =
218 clamp(static_cast<int16_t>(rnd_.Rand16()), INT16_MIN + 1, INT16_MAX);
219 } else {
220 tran_low_t min = -(1 << (7 + bd_));
221 tran_low_t max = -min - 1;
222 coeff = clamp(static_cast<tran_low_t>(rnd_.Rand31()), min, max);
224 return coeff;
227 ACMRandom rnd_;
228 QuanTable *qtab_;
229 tran_low_t *coeff_;
230 QuantizeFunc quant_ref_;
231 QuantizeFunc quant_;
232 TX_SIZE tx_size_;
233 QuantType type_;
234 aom_bit_depth_t bd_;
237 TEST_P(QuantizeTest, ZeroInput) {
238 FillCoeffZero();
239 QuantizeRun(false);
242 TEST_P(QuantizeTest, LargeNegativeInput) {
243 FillDcLargeNegative();
244 QuantizeRun(false, 0, 1);
247 TEST_P(QuantizeTest, DcOnlyInput) {
248 FillDcOnly();
249 QuantizeRun(false, 0, 1);
252 TEST_P(QuantizeTest, RandomInput) { QuantizeRun(true, 0, kTestNum); }
254 TEST_P(QuantizeTest, MultipleQ) {
255 for (int q = 0; q < QINDEX_RANGE; ++q) {
256 QuantizeRun(true, q, kTestNum);
260 // Force the coeff to be half the value of the dequant. This exposes a
261 // mismatch found in av1_quantize_fp_sse2().
262 TEST_P(QuantizeTest, CoeffHalfDequant) {
263 FillCoeff(16);
264 QuantizeRun(false, 25, 1);
267 TEST_P(QuantizeTest, DISABLED_Speed) {
268 tran_low_t *coeff_ptr = coeff_;
269 const intptr_t n_coeffs = coeff_num();
271 tran_low_t *qcoeff_ref = coeff_ptr + n_coeffs;
272 tran_low_t *dqcoeff_ref = qcoeff_ref + n_coeffs;
274 tran_low_t *qcoeff = dqcoeff_ref + n_coeffs;
275 tran_low_t *dqcoeff = qcoeff + n_coeffs;
276 uint16_t *eob = (uint16_t *)(dqcoeff + n_coeffs);
278 // Testing uses 2-D DCT scan order table
279 const SCAN_ORDER *const sc = get_default_scan(tx_size_, DCT_DCT);
281 // Testing uses luminance quantization table
282 const int q = 22;
283 const int16_t *zbin = qtab_->quant.y_zbin[q];
284 const int16_t *round_fp = qtab_->quant.y_round_fp[q];
285 const int16_t *quant_fp = qtab_->quant.y_quant_fp[q];
286 const int16_t *quant_shift = qtab_->quant.y_quant_shift[q];
287 const int16_t *dequant = qtab_->dequant.y_dequant_QTX[q];
288 const int kNumTests = 5000000;
289 aom_usec_timer timer;
291 FillCoeffRandom();
293 aom_usec_timer_start(&timer);
294 for (int n = 0; n < kNumTests; ++n) {
295 quant_(coeff_ptr, n_coeffs, zbin, round_fp, quant_fp, quant_shift, qcoeff,
296 dqcoeff, dequant, eob, sc->scan, sc->iscan);
298 aom_usec_timer_mark(&timer);
300 const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
301 printf("Elapsed time: %d us\n", elapsed_time);
304 using ::testing::make_tuple;
306 #if HAVE_AVX2
307 const QuantizeParam kQParamArrayAvx2[] = {
308 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_avx2, TX_16X16, TYPE_FP,
309 AOM_BITS_8),
310 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_avx2, TX_4X16, TYPE_FP,
311 AOM_BITS_8),
312 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_avx2, TX_16X4, TYPE_FP,
313 AOM_BITS_8),
314 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_avx2, TX_32X8, TYPE_FP,
315 AOM_BITS_8),
316 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_avx2, TX_8X32, TYPE_FP,
317 AOM_BITS_8),
318 make_tuple(&av1_quantize_fp_32x32_c, &av1_quantize_fp_32x32_avx2, TX_32X32,
319 TYPE_FP, AOM_BITS_8),
320 make_tuple(&av1_quantize_fp_32x32_c, &av1_quantize_fp_32x32_avx2, TX_16X64,
321 TYPE_FP, AOM_BITS_8),
322 make_tuple(&av1_quantize_fp_32x32_c, &av1_quantize_fp_32x32_avx2, TX_64X16,
323 TYPE_FP, AOM_BITS_8),
324 make_tuple(&av1_quantize_fp_64x64_c, &av1_quantize_fp_64x64_avx2, TX_64X64,
325 TYPE_FP, AOM_BITS_8),
326 make_tuple(&highbd_quan16x16_wrapper<av1_highbd_quantize_fp_c>,
327 &highbd_quan16x16_wrapper<av1_highbd_quantize_fp_avx2>, TX_16X16,
328 TYPE_FP, AOM_BITS_8),
329 make_tuple(&highbd_quan16x16_wrapper<av1_highbd_quantize_fp_c>,
330 &highbd_quan16x16_wrapper<av1_highbd_quantize_fp_avx2>, TX_16X16,
331 TYPE_FP, AOM_BITS_10),
332 make_tuple(&highbd_quan16x16_wrapper<av1_highbd_quantize_fp_c>,
333 &highbd_quan16x16_wrapper<av1_highbd_quantize_fp_avx2>, TX_16X16,
334 TYPE_FP, AOM_BITS_12),
335 make_tuple(&highbd_quan32x32_wrapper<av1_highbd_quantize_fp_c>,
336 &highbd_quan32x32_wrapper<av1_highbd_quantize_fp_avx2>, TX_32X32,
337 TYPE_FP, AOM_BITS_8),
338 make_tuple(&highbd_quan32x32_wrapper<av1_highbd_quantize_fp_c>,
339 &highbd_quan32x32_wrapper<av1_highbd_quantize_fp_avx2>, TX_32X32,
340 TYPE_FP, AOM_BITS_10),
341 make_tuple(&highbd_quan32x32_wrapper<av1_highbd_quantize_fp_c>,
342 &highbd_quan32x32_wrapper<av1_highbd_quantize_fp_avx2>, TX_32X32,
343 TYPE_FP, AOM_BITS_12),
344 make_tuple(&highbd_quan64x64_wrapper<av1_highbd_quantize_fp_c>,
345 &highbd_quan64x64_wrapper<av1_highbd_quantize_fp_avx2>, TX_64X64,
346 TYPE_FP, AOM_BITS_8),
347 make_tuple(&highbd_quan64x64_wrapper<av1_highbd_quantize_fp_c>,
348 &highbd_quan64x64_wrapper<av1_highbd_quantize_fp_avx2>, TX_64X64,
349 TYPE_FP, AOM_BITS_10),
350 make_tuple(&highbd_quan64x64_wrapper<av1_highbd_quantize_fp_c>,
351 &highbd_quan64x64_wrapper<av1_highbd_quantize_fp_avx2>, TX_64X64,
352 TYPE_FP, AOM_BITS_12),
353 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_avx2, TX_16X16,
354 TYPE_B, AOM_BITS_8),
355 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_avx2, TX_16X16,
356 TYPE_B, AOM_BITS_10),
357 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_avx2, TX_16X16,
358 TYPE_B, AOM_BITS_12),
361 INSTANTIATE_TEST_CASE_P(AVX2, QuantizeTest,
362 ::testing::ValuesIn(kQParamArrayAvx2));
363 #endif // HAVE_AVX2
365 #if HAVE_SSE2
366 const QuantizeParam kQParamArraySSE2[] = {
367 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_sse2, TX_16X16, TYPE_FP,
368 AOM_BITS_8),
369 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_sse2, TX_4X16, TYPE_FP,
370 AOM_BITS_8),
371 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_sse2, TX_16X4, TYPE_FP,
372 AOM_BITS_8),
373 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_sse2, TX_8X32, TYPE_FP,
374 AOM_BITS_8),
375 make_tuple(&av1_quantize_fp_c, &av1_quantize_fp_sse2, TX_32X8, TYPE_FP,
376 AOM_BITS_8),
377 make_tuple(&aom_quantize_b_c, &aom_quantize_b_sse2, TX_16X16, TYPE_B,
378 AOM_BITS_8),
379 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_sse2, TX_16X16,
380 TYPE_B, AOM_BITS_8),
381 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_sse2, TX_16X16,
382 TYPE_B, AOM_BITS_10),
383 make_tuple(&aom_highbd_quantize_b_c, &aom_highbd_quantize_b_sse2, TX_16X16,
384 TYPE_B, AOM_BITS_12),
385 make_tuple(&aom_highbd_quantize_b_32x32_c, &aom_highbd_quantize_b_32x32_sse2,
386 TX_32X32, TYPE_B, AOM_BITS_8),
387 make_tuple(&aom_highbd_quantize_b_32x32_c, &aom_highbd_quantize_b_32x32_sse2,
388 TX_32X32, TYPE_B, AOM_BITS_10),
389 make_tuple(&aom_highbd_quantize_b_32x32_c, &aom_highbd_quantize_b_32x32_sse2,
390 TX_32X32, TYPE_B, AOM_BITS_12),
393 INSTANTIATE_TEST_CASE_P(SSE2, QuantizeTest,
394 ::testing::ValuesIn(kQParamArraySSE2));
395 #endif
397 #if HAVE_SSSE3 && ARCH_X86_64
398 INSTANTIATE_TEST_CASE_P(
399 SSSE3, QuantizeTest,
400 ::testing::Values(make_tuple(&aom_quantize_b_c, &aom_quantize_b_ssse3,
401 TX_16X16, TYPE_B, AOM_BITS_8)));
403 // Like libvpx, the ssse3 and avx quantize tests do not pass.
404 // https://bugs.chromium.org/p/webm/issues/detail?id=1448
405 INSTANTIATE_TEST_CASE_P(
406 DISABLED_SSSE3_32x32, QuantizeTest,
407 ::testing::Values(make_tuple(&aom_quantize_b_32x32_c,
408 &aom_quantize_b_32x32_ssse3, TX_16X16, TYPE_B,
409 AOM_BITS_8)));
411 #endif // HAVE_SSSE3 && ARCH_X86_64
413 #if HAVE_AVX && ARCH_X86_64
414 INSTANTIATE_TEST_CASE_P(
415 AVX, QuantizeTest,
416 ::testing::Values(
417 make_tuple(&aom_quantize_b_c, &aom_quantize_b_avx, TX_16X16, TYPE_B,
418 AOM_BITS_8),
419 // Although these tests will not pass against _c, test them against each
420 // other so there is some minor checking.
421 make_tuple(&aom_quantize_b_32x32_ssse3, &aom_quantize_b_32x32_avx,
422 TX_32X32, TYPE_B, AOM_BITS_8)));
424 #endif // HAVE_AVX && ARCH_X86_64
425 } // namespace