blob: aa083d5324ea532a51878e21a8f06ef1bf2bc4cc [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
Yaowu Xuf883b422016-08-30 14:01:10 -070018#include "./aom_config.h"
19#include "./av1_rtcd.h"
Peter de Rivaza7b2d092014-10-16 13:38:46 +010020#include "test/acm_random.h"
21#include "test/clear_system_state.h"
22#include "test/register_state_check.h"
23#include "test/util.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070024#include "av1/common/entropy.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070025#include "aom/aom_codec.h"
26#include "aom/aom_integer.h"
Peter de Rivaza7b2d092014-10-16 13:38:46 +010027
Yaowu Xuc27fc142016-08-22 16:08:15 -070028using libaom_test::ACMRandom;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010029
30namespace {
Peter de Rivaza7b2d092014-10-16 13:38:46 +010031const int kNumIterations = 1000;
32
33typedef int64_t (*ErrorBlockFunc)(const tran_low_t *coeff,
34 const tran_low_t *dqcoeff,
clang-format3a826f12016-08-11 17:46:05 -070035 intptr_t block_size, int64_t *ssz, int bps);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010036
Yaowu Xuf883b422016-08-30 14:01:10 -070037typedef std::tr1::tuple<ErrorBlockFunc, ErrorBlockFunc, aom_bit_depth_t>
clang-format3a826f12016-08-11 17:46:05 -070038 ErrorBlockParam;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010039
clang-format3a826f12016-08-11 17:46:05 -070040class ErrorBlockTest : public ::testing::TestWithParam<ErrorBlockParam> {
Peter de Rivaza7b2d092014-10-16 13:38:46 +010041 public:
42 virtual ~ErrorBlockTest() {}
43 virtual void SetUp() {
clang-format3a826f12016-08-11 17:46:05 -070044 error_block_op_ = GET_PARAM(0);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010045 ref_error_block_op_ = GET_PARAM(1);
clang-format3a826f12016-08-11 17:46:05 -070046 bit_depth_ = GET_PARAM(2);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010047 }
48
Yaowu Xuc27fc142016-08-22 16:08:15 -070049 virtual void TearDown() { libaom_test::ClearSystemState(); }
Peter de Rivaza7b2d092014-10-16 13:38:46 +010050
51 protected:
Yaowu Xuf883b422016-08-30 14:01:10 -070052 aom_bit_depth_t bit_depth_;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010053 ErrorBlockFunc error_block_op_;
54 ErrorBlockFunc ref_error_block_op_;
55};
56
57TEST_P(ErrorBlockTest, OperationCheck) {
58 ACMRandom rnd(ACMRandom::DeterministicSeed());
James Zernfd3658b2015-05-02 13:24:16 -070059 DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
60 DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
Peter de Rivaza7b2d092014-10-16 13:38:46 +010061 int err_count_total = 0;
62 int first_failure = -1;
63 intptr_t block_size;
64 int64_t ssz;
65 int64_t ret;
66 int64_t ref_ssz;
67 int64_t ref_ret;
Geza Loreaa8f8522015-10-15 18:28:31 +010068 const int msb = bit_depth_ + 8 - 1;
Peter de Rivaza7b2d092014-10-16 13:38:46 +010069 for (int i = 0; i < kNumIterations; ++i) {
70 int err_count = 0;
71 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
72 for (int j = 0; j < block_size; j++) {
Geza Loreaa8f8522015-10-15 18:28:31 +010073 // coeff and dqcoeff will always have at least the same sign, and this
74 // can be used for optimization, so generate test input precisely.
75 if (rnd(2)) {
76 // Positive number
clang-format3a826f12016-08-11 17:46:05 -070077 coeff[j] = rnd(1 << msb);
Geza Loreaa8f8522015-10-15 18:28:31 +010078 dqcoeff[j] = rnd(1 << msb);
79 } else {
80 // Negative number
clang-format3a826f12016-08-11 17:46:05 -070081 coeff[j] = -rnd(1 << msb);
Geza Loreaa8f8522015-10-15 18:28:31 +010082 dqcoeff[j] = -rnd(1 << msb);
83 }
Peter de Rivaza7b2d092014-10-16 13:38:46 +010084 }
clang-format3a826f12016-08-11 17:46:05 -070085 ref_ret =
86 ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
87 ASM_REGISTER_STATE_CHECK(
88 ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
Peter de Rivaza7b2d092014-10-16 13:38:46 +010089 err_count += (ref_ret != ret) | (ref_ssz != ssz);
90 if (err_count && !err_count_total) {
91 first_failure = i;
92 }
93 err_count_total += err_count;
94 }
95 EXPECT_EQ(0, err_count_total)
Geza Loreaa8f8522015-10-15 18:28:31 +010096 << "Error: Error Block Test, C output doesn't match optimized output. "
Peter de Rivaza7b2d092014-10-16 13:38:46 +010097 << "First failed at test case " << first_failure;
98}
99
100TEST_P(ErrorBlockTest, ExtremeValues) {
101 ACMRandom rnd(ACMRandom::DeterministicSeed());
James Zernfd3658b2015-05-02 13:24:16 -0700102 DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
103 DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100104 int err_count_total = 0;
105 int first_failure = -1;
106 intptr_t block_size;
107 int64_t ssz;
108 int64_t ret;
109 int64_t ref_ssz;
110 int64_t ref_ret;
Geza Loreaa8f8522015-10-15 18:28:31 +0100111 const int msb = bit_depth_ + 8 - 1;
112 int max_val = ((1 << msb) - 1);
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100113 for (int i = 0; i < kNumIterations; ++i) {
114 int err_count = 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100115 int k = (i / 9) % 9;
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100116
117 // Change the maximum coeff value, to test different bit boundaries
clang-format3a826f12016-08-11 17:46:05 -0700118 if (k == 8 && (i % 9) == 0) {
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100119 max_val >>= 1;
120 }
121 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
122 for (int j = 0; j < block_size; j++) {
Geza Loreaa8f8522015-10-15 18:28:31 +0100123 if (k < 4) {
124 // Test at positive maximum values
clang-format3a826f12016-08-11 17:46:05 -0700125 coeff[j] = k % 2 ? max_val : 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100126 dqcoeff[j] = (k >> 1) % 2 ? max_val : 0;
127 } else if (k < 8) {
128 // Test at negative maximum values
clang-format3a826f12016-08-11 17:46:05 -0700129 coeff[j] = k % 2 ? -max_val : 0;
Geza Loreaa8f8522015-10-15 18:28:31 +0100130 dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0;
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100131 } else {
Geza Loreaa8f8522015-10-15 18:28:31 +0100132 if (rnd(2)) {
133 // Positive number
clang-format3a826f12016-08-11 17:46:05 -0700134 coeff[j] = rnd(1 << 14);
Geza Loreaa8f8522015-10-15 18:28:31 +0100135 dqcoeff[j] = rnd(1 << 14);
136 } else {
137 // Negative number
clang-format3a826f12016-08-11 17:46:05 -0700138 coeff[j] = -rnd(1 << 14);
Geza Loreaa8f8522015-10-15 18:28:31 +0100139 dqcoeff[j] = -rnd(1 << 14);
140 }
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100141 }
142 }
clang-format3a826f12016-08-11 17:46:05 -0700143 ref_ret =
144 ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
145 ASM_REGISTER_STATE_CHECK(
146 ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100147 err_count += (ref_ret != ret) | (ref_ssz != ssz);
148 if (err_count && !err_count_total) {
149 first_failure = i;
150 }
151 err_count_total += err_count;
152 }
153 EXPECT_EQ(0, err_count_total)
Geza Loreaa8f8522015-10-15 18:28:31 +0100154 << "Error: Error Block Test, C output doesn't match optimized output. "
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100155 << "First failed at test case " << first_failure;
156}
157
Sebastien Alaiwan58596362018-01-26 10:11:35 +0100158#if (HAVE_SSE2 || HAVE_AVX)
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100159using std::tr1::make_tuple;
160
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100161INSTANTIATE_TEST_CASE_P(
162 SSE2, ErrorBlockTest,
Yaowu Xuf883b422016-08-30 14:01:10 -0700163 ::testing::Values(make_tuple(&av1_highbd_block_error_sse2,
164 &av1_highbd_block_error_c, AOM_BITS_10),
165 make_tuple(&av1_highbd_block_error_sse2,
166 &av1_highbd_block_error_c, AOM_BITS_12),
167 make_tuple(&av1_highbd_block_error_sse2,
168 &av1_highbd_block_error_c, AOM_BITS_8)));
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100169#endif // HAVE_SSE2
Peter de Rivaza7b2d092014-10-16 13:38:46 +0100170} // namespace