1 /*
2 * Copyright (c) 2016, 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 <tuple>
13
14 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
15
16 #include "config/av1_rtcd.h"
17
18 #include "test/acm_random.h"
19 #include "test/register_state_check.h"
20 #include "test/util.h"
21 #include "av1/common/enums.h"
22
23 namespace {
24
25 using libaom_test::ACMRandom;
26 using std::tuple;
27
28 typedef void (*Predictor)(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
29 const uint8_t *above, const uint8_t *left, int mode);
30
31 // Note:
32 // Test parameter list:
33 // Reference predictor, optimized predictor, prediction mode, tx size
34 //
35 typedef tuple<Predictor, Predictor, int> PredFuncMode;
36 typedef tuple<PredFuncMode, TX_SIZE> PredParams;
37
38 const int MaxTxSize = 32;
39
40 const int MaxTestNum = 100;
41
42 class AV1FilterIntraPredTest : public ::testing::TestWithParam<PredParams> {
43 public:
~AV1FilterIntraPredTest()44 virtual ~AV1FilterIntraPredTest() {}
SetUp()45 virtual void SetUp() {
46 PredFuncMode funcMode = GET_PARAM(0);
47 predFuncRef_ = std::get<0>(funcMode);
48 predFunc_ = std::get<1>(funcMode);
49 mode_ = std::get<2>(funcMode);
50 txSize_ = GET_PARAM(1);
51
52 alloc_ = new uint8_t[2 * MaxTxSize + 1];
53 predRef_ = new uint8_t[MaxTxSize * MaxTxSize];
54 pred_ = new uint8_t[MaxTxSize * MaxTxSize];
55 ASSERT_NE(alloc_, nullptr);
56 ASSERT_NE(predRef_, nullptr);
57 ASSERT_NE(pred_, nullptr);
58 }
59
TearDown()60 virtual void TearDown() {
61 delete[] alloc_;
62 delete[] predRef_;
63 delete[] pred_;
64 }
65
66 protected:
RunTest() const67 void RunTest() const {
68 int tstIndex = 0;
69 int stride = tx_size_wide[txSize_];
70 uint8_t *left = alloc_;
71 uint8_t *above = alloc_ + MaxTxSize;
72 while (tstIndex < MaxTestNum) {
73 PrepareBuffer();
74 predFuncRef_(predRef_, stride, txSize_, &above[1], left, mode_);
75 API_REGISTER_STATE_CHECK(
76 predFunc_(pred_, stride, txSize_, &above[1], left, mode_));
77 DiffPred(tstIndex);
78 tstIndex += 1;
79 }
80 }
RunSpeedTest() const81 void RunSpeedTest() const {
82 int stride = tx_size_wide[txSize_];
83 uint8_t *left = alloc_;
84 uint8_t *above = alloc_ + MaxTxSize;
85 const int numIter = 5000;
86
87 PrepareBuffer();
88 aom_usec_timer ref_timer;
89 aom_usec_timer_start(&ref_timer);
90 for (int i = 0; i < numIter; i++) {
91 predFuncRef_(predRef_, stride, txSize_, &above[1], left, mode_);
92 }
93 aom_usec_timer_mark(&ref_timer);
94
95 aom_usec_timer timer;
96 aom_usec_timer_start(&timer);
97 for (int i = 0; i < numIter; i++) {
98 predFunc_(pred_, stride, txSize_, &above[1], left, mode_);
99 }
100 aom_usec_timer_mark(&timer);
101
102 const int ref_sum_time =
103 static_cast<int>(aom_usec_timer_elapsed(&ref_timer));
104 const int sum_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
105
106 printf("c_time = %d \t simd_time = %d \t Gain = %4.2f \t mode = %d \n",
107 ref_sum_time, sum_time,
108 (static_cast<float>(ref_sum_time) / static_cast<float>(sum_time)),
109 static_cast<int>(mode_));
110
111 DiffPred(0);
112 }
113
114 private:
PrepareBuffer() const115 void PrepareBuffer() const {
116 ACMRandom rnd(ACMRandom::DeterministicSeed());
117 int i = 0;
118 while (i < (2 * MaxTxSize + 1)) {
119 alloc_[i] = rnd.Rand8();
120 i++;
121 }
122 }
123
DiffPred(int testNum) const124 void DiffPred(int testNum) const {
125 int i = 0;
126 while (i < tx_size_wide[txSize_] * tx_size_high[txSize_]) {
127 EXPECT_EQ(predRef_[i], pred_[i]) << "Error at position: " << i << " "
128 << "Tx size: " << tx_size_wide[txSize_]
129 << "x" << tx_size_high[txSize_] << " "
130 << "Test number: " << testNum;
131 i++;
132 }
133 }
134
135 Predictor predFunc_;
136 Predictor predFuncRef_;
137 int mode_;
138 TX_SIZE txSize_;
139 uint8_t *alloc_;
140 uint8_t *pred_;
141 uint8_t *predRef_;
142 };
143
TEST_P(AV1FilterIntraPredTest,BitExactCheck)144 TEST_P(AV1FilterIntraPredTest, BitExactCheck) { RunTest(); }
145
TEST_P(AV1FilterIntraPredTest,DISABLED_Speed)146 TEST_P(AV1FilterIntraPredTest, DISABLED_Speed) { RunSpeedTest(); }
147
148 using ::testing::make_tuple;
149 #if HAVE_SSE4_1
150 const PredFuncMode kPredFuncMdArray[] = {
151 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
152 FILTER_DC_PRED),
153 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
154 FILTER_V_PRED),
155 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
156 FILTER_H_PRED),
157 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
158 FILTER_D157_PRED),
159 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
160 FILTER_PAETH_PRED),
161 };
162
163 const TX_SIZE kTxSize[] = { TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_4X8,
164 TX_8X4, TX_8X16, TX_16X8, TX_16X32, TX_32X16,
165 TX_4X16, TX_16X4, TX_8X32, TX_32X8 };
166
167 INSTANTIATE_TEST_SUITE_P(
168 SSE4_1, AV1FilterIntraPredTest,
169 ::testing::Combine(::testing::ValuesIn(kPredFuncMdArray),
170 ::testing::ValuesIn(kTxSize)));
171 #endif // HAVE_SSE4_1
172
173 #if HAVE_NEON
174 const PredFuncMode kPredFuncMdArrayNEON[] = {
175 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_neon,
176 FILTER_DC_PRED),
177 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_neon,
178 FILTER_V_PRED),
179 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_neon,
180 FILTER_H_PRED),
181 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_neon,
182 FILTER_D157_PRED),
183 make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_neon,
184 FILTER_PAETH_PRED),
185 };
186
187 const TX_SIZE kTxSizeNEON[] = { TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_4X8,
188 TX_8X4, TX_8X16, TX_16X8, TX_16X32, TX_32X16,
189 TX_4X16, TX_16X4, TX_8X32, TX_32X8 };
190
191 INSTANTIATE_TEST_SUITE_P(
192 NEON, AV1FilterIntraPredTest,
193 ::testing::Combine(::testing::ValuesIn(kPredFuncMdArrayNEON),
194 ::testing::ValuesIn(kTxSizeNEON)));
195 #endif // HAVE_NEON
196
197 } // namespace
198