blob: 353947c3d70872bdf356fa71f1d180ec26b9b45a [file] [log] [blame]
Peter de Rivaza7b2d092014-10-16 13:38:46 +01001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Peter de Rivaza7b2d092014-10-16 13:38:46 +01003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * 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.
Johann123e8a62017-12-28 14:40:49 -080010 */
Peter de Rivaza7b2d092014-10-16 13:38:46 +010011
12#include <cmath>
13#include <cstdlib>
14#include <string>
15
Tom Finegan7a07ece2017-02-07 17:14:05 -080016#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
Peter de Rivaza7b2d092014-10-16 13:38:46 +010017
Tom Finegan60e653d2018-05-22 11:34:58 -070018#include "config/aom_config.h"
Tom Finegan44702c82018-05-22 13:00:39 -070019#include "config/av1_rtcd.h"
Tom Finegan60e653d2018-05-22 11:34:58 -070020
Peter de Rivaza7b2d092014-10-16 13:38:46 +010021#include "test/acm_random.h"
22#include "test/clear_system_state.h"
23#include "test/register_state_check.h"
24#include "test/util.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070025#include "av1/common/entropy.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070026#include "aom/aom_codec.h"
27#include "aom/aom_integer.h"
Peter de Rivaza7b2d092014-10-16 13:38:46 +010028
Yaowu Xuc27fc142016-08-22 16:08:15 -070029using libaom_test::ACMRandom;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010030
31namespace {
Peter de Rivaza7b2d092014-10-16 13:38:46 +010032const int kNumIterations = 1000;
33
34typedef int64_t (*ErrorBlockFunc)(const tran_low_t *coeff,
35 const tran_low_t *dqcoeff,
clang-format3a826f12016-08-11 17:46:05 -070036 intptr_t block_size, int64_t *ssz, int bps);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010037
James Zern95612802018-03-30 11:37:54 -070038typedef ::testing::tuple<ErrorBlockFunc, ErrorBlockFunc, aom_bit_depth_t>
clang-format3a826f12016-08-11 17:46:05 -070039 ErrorBlockParam;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010040
clang-format3a826f12016-08-11 17:46:05 -070041class ErrorBlockTest : public ::testing::TestWithParam<ErrorBlockParam> {
Peter de Rivaza7b2d092014-10-16 13:38:46 +010042 public:
43 virtual ~ErrorBlockTest() {}
44 virtual void SetUp() {
clang-format3a826f12016-08-11 17:46:05 -070045 error_block_op_ = GET_PARAM(0);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010046 ref_error_block_op_ = GET_PARAM(1);
clang-format3a826f12016-08-11 17:46:05 -070047 bit_depth_ = GET_PARAM(2);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010048 }
49
Yaowu Xuc27fc142016-08-22 16:08:15 -070050 virtual void TearDown() { libaom_test::ClearSystemState(); }
Peter de Rivaza7b2d092014-10-16 13:38:46 +010051
52 protected:
Yaowu Xuf883b422016-08-30 14:01:10 -070053 aom_bit_depth_t bit_depth_;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010054 ErrorBlockFunc error_block_op_;
55 ErrorBlockFunc ref_error_block_op_;
56};
57
58TEST_P(ErrorBlockTest, OperationCheck) {
59 ACMRandom rnd(ACMRandom::DeterministicSeed());
James Zernfd3658b2015-05-02 13:24:16 -070060 DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
61 DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010062 int err_count_total = 0;
63 int first_failure = -1;
64 intptr_t block_size;
65 int64_t ssz;
66 int64_t ret;
67 int64_t ref_ssz;
68 int64_t ref_ret;
Geza Loreaa8f8522015-10-15 18:28:31 +010069 const int msb = bit_depth_ + 8 - 1;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010070 for (int i = 0; i < kNumIterations; ++i) {
71 int err_count = 0;
72 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
73 for (int j = 0; j < block_size; j++) {
Geza Loreaa8f8522015-10-15 18:28:31 +010074 // coeff and dqcoeff will always have at least the same sign, and this
75 // can be used for optimization, so generate test input precisely.
76 if (rnd(2)) {
77 // Positive number
clang-format3a826f12016-08-11 17:46:05 -070078 coeff[j] = rnd(1 << msb);
Geza Loreaa8f8522015-10-15 18:28:31 +010079 dqcoeff[j] = rnd(1 << msb);
80 } else {
81 // Negative number
clang-format3a826f12016-08-11 17:46:05 -070082 coeff[j] = -rnd(1 << msb);
Geza Loreaa8f8522015-10-15 18:28:31 +010083 dqcoeff[j] = -rnd(1 << msb);
84 }
Peter de Rivaza7b2d092014-10-16 13:38:46 +010085 }
clang-format3a826f12016-08-11 17:46:05 -070086 ref_ret =
87 ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
88 ASM_REGISTER_STATE_CHECK(
89 ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
Peter de Rivaza7b2d092014-10-16 13:38:46 +010090 err_count += (ref_ret != ret) | (ref_ssz != ssz);
91 if (err_count && !err_count_total) {
92 first_failure = i;
93 }
94 err_count_total += err_count;
95 }
96 EXPECT_EQ(0, err_count_total)
Geza Loreaa8f8522015-10-15 18:28:31 +010097 << "Error: Error Block Test, C output doesn't match optimized output. "
Peter de Rivaza7b2d092014-10-16 13:38:46 +010098 << "First failed at test case " << first_failure;
99}
100
101TEST_P(ErrorBlockTest, ExtremeValues) {
102 ACMRandom rnd(ACMRandom::DeterministicSeed());
James Zernfd3658b2015-05-02 13:24:16 -0700103 DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
104 DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100105 int err_count_total = 0;
106 int first_failure = -1;
107 intptr_t block_size;
108 int64_t ssz;
109 int64_t ret;
110 int64_t ref_ssz;
111 int64_t ref_ret;
Geza Loreaa8f8522015-10-15 18:28:31 +0100112 const int msb = bit_depth_ + 8 - 1;
113 int max_val = ((1 << msb) - 1);
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100114 for (int i = 0; i < kNumIterations; ++i) {
115 int err_count = 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100116 int k = (i / 9) % 9;
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100117
118 // Change the maximum coeff value, to test different bit boundaries
clang-format3a826f12016-08-11 17:46:05 -0700119 if (k == 8 && (i % 9) == 0) {
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100120 max_val >>= 1;
121 }
122 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
123 for (int j = 0; j < block_size; j++) {
Geza Loreaa8f8522015-10-15 18:28:31 +0100124 if (k < 4) {
125 // Test at positive maximum values
clang-format3a826f12016-08-11 17:46:05 -0700126 coeff[j] = k % 2 ? max_val : 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100127 dqcoeff[j] = (k >> 1) % 2 ? max_val : 0;
128 } else if (k < 8) {
129 // Test at negative maximum values
clang-format3a826f12016-08-11 17:46:05 -0700130 coeff[j] = k % 2 ? -max_val : 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100131 dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0;
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100132 } else {
Geza Loreaa8f8522015-10-15 18:28:31 +0100133 if (rnd(2)) {
134 // Positive number
clang-format3a826f12016-08-11 17:46:05 -0700135 coeff[j] = rnd(1 << 14);
Geza Loreaa8f8522015-10-15 18:28:31 +0100136 dqcoeff[j] = rnd(1 << 14);
137 } else {
138 // Negative number
clang-format3a826f12016-08-11 17:46:05 -0700139 coeff[j] = -rnd(1 << 14);
Geza Loreaa8f8522015-10-15 18:28:31 +0100140 dqcoeff[j] = -rnd(1 << 14);
141 }
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100142 }
143 }
clang-format3a826f12016-08-11 17:46:05 -0700144 ref_ret =
145 ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
146 ASM_REGISTER_STATE_CHECK(
147 ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100148 err_count += (ref_ret != ret) | (ref_ssz != ssz);
149 if (err_count && !err_count_total) {
150 first_failure = i;
151 }
152 err_count_total += err_count;
153 }
154 EXPECT_EQ(0, err_count_total)
Geza Loreaa8f8522015-10-15 18:28:31 +0100155 << "Error: Error Block Test, C output doesn't match optimized output. "
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100156 << "First failed at test case " << first_failure;
157}
158
Sebastien Alaiwan58596362018-01-26 10:11:35 +0100159#if (HAVE_SSE2 || HAVE_AVX)
James Zern95612802018-03-30 11:37:54 -0700160using ::testing::make_tuple;
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100161
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100162INSTANTIATE_TEST_CASE_P(
163 SSE2, ErrorBlockTest,
Yaowu Xuf883b422016-08-30 14:01:10 -0700164 ::testing::Values(make_tuple(&av1_highbd_block_error_sse2,
165 &av1_highbd_block_error_c, AOM_BITS_10),
166 make_tuple(&av1_highbd_block_error_sse2,
167 &av1_highbd_block_error_c, AOM_BITS_12),
168 make_tuple(&av1_highbd_block_error_sse2,
169 &av1_highbd_block_error_c, AOM_BITS_8)));
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100170#endif // HAVE_SSE2
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100171} // namespace