1 /*
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16
17 #include "./vpx_config.h"
18 #include "./vp8_rtcd.h"
19 #include "test/acm_random.h"
20 #include "test/clear_system_state.h"
21 #include "test/register_state_check.h"
22 #include "test/util.h"
23 #include "vpx/vpx_integer.h"
24 #include "vpx_mem/vpx_mem.h"
25
26 namespace {
27
28 typedef void (*SixtapPredictFunc)(uint8_t *src_ptr,
29 int src_pixels_per_line,
30 int xoffset,
31 int yoffset,
32 uint8_t *dst_ptr,
33 int dst_pitch);
34
35 typedef std::tr1::tuple<int, int, SixtapPredictFunc> SixtapPredictParam;
36
37 class SixtapPredictTest
38 : public ::testing::TestWithParam<SixtapPredictParam> {
39 public:
SetUpTestCase()40 static void SetUpTestCase() {
41 src_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kSrcSize));
42 dst_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize));
43 dst_c_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize));
44 }
45
TearDownTestCase()46 static void TearDownTestCase() {
47 vpx_free(src_);
48 src_ = NULL;
49 vpx_free(dst_);
50 dst_ = NULL;
51 vpx_free(dst_c_);
52 dst_c_ = NULL;
53 }
54
TearDown()55 virtual void TearDown() {
56 libvpx_test::ClearSystemState();
57 }
58
59 protected:
60 // Make test arrays big enough for 16x16 functions. Six-tap filters
61 // need 5 extra pixels outside of the macroblock.
62 static const int kSrcStride = 21;
63 static const int kDstStride = 16;
64 static const int kDataAlignment = 16;
65 static const int kSrcSize = kSrcStride * kSrcStride + 1;
66 static const int kDstSize = kDstStride * kDstStride;
67
SetUp()68 virtual void SetUp() {
69 width_ = GET_PARAM(0);
70 height_ = GET_PARAM(1);
71 sixtap_predict_ = GET_PARAM(2);
72 memset(src_, 0, kSrcSize);
73 memset(dst_, 0, kDstSize);
74 memset(dst_c_, 0, kDstSize);
75 }
76
77 int width_;
78 int height_;
79 SixtapPredictFunc sixtap_predict_;
80 // The src stores the macroblock we will filter on, and makes it 1 byte larger
81 // in order to test unaligned access. The result is stored in dst and dst_c(c
82 // reference code result).
83 static uint8_t* src_;
84 static uint8_t* dst_;
85 static uint8_t* dst_c_;
86 };
87
88 uint8_t* SixtapPredictTest::src_ = NULL;
89 uint8_t* SixtapPredictTest::dst_ = NULL;
90 uint8_t* SixtapPredictTest::dst_c_ = NULL;
91
TEST_P(SixtapPredictTest,TestWithPresetData)92 TEST_P(SixtapPredictTest, TestWithPresetData) {
93 // Test input
94 static const uint8_t test_data[kSrcSize] = {
95 216, 184, 4, 191, 82, 92, 41, 0, 1, 226, 236, 172, 20, 182, 42, 226, 177,
96 79, 94, 77, 179, 203, 206, 198, 22, 192, 19, 75, 17, 192, 44, 233, 120,
97 48, 168, 203, 141, 210, 203, 143, 180, 184, 59, 201, 110, 102, 171, 32,
98 182, 10, 109, 105, 213, 60, 47, 236, 253, 67, 55, 14, 3, 99, 247, 124,
99 148, 159, 71, 34, 114, 19, 177, 38, 203, 237, 239, 58, 83, 155, 91, 10,
100 166, 201, 115, 124, 5, 163, 104, 2, 231, 160, 16, 234, 4, 8, 103, 153,
101 167, 174, 187, 26, 193, 109, 64, 141, 90, 48, 200, 174, 204, 36, 184,
102 114, 237, 43, 238, 242, 207, 86, 245, 182, 247, 6, 161, 251, 14, 8, 148,
103 182, 182, 79, 208, 120, 188, 17, 6, 23, 65, 206, 197, 13, 242, 126, 128,
104 224, 170, 110, 211, 121, 197, 200, 47, 188, 207, 208, 184, 221, 216, 76,
105 148, 143, 156, 100, 8, 89, 117, 14, 112, 183, 221, 54, 197, 208, 180, 69,
106 176, 94, 180, 131, 215, 121, 76, 7, 54, 28, 216, 238, 249, 176, 58, 142,
107 64, 215, 242, 72, 49, 104, 87, 161, 32, 52, 216, 230, 4, 141, 44, 181,
108 235, 224, 57, 195, 89, 134, 203, 144, 162, 163, 126, 156, 84, 185, 42,
109 148, 145, 29, 221, 194, 134, 52, 100, 166, 105, 60, 140, 110, 201, 184,
110 35, 181, 153, 93, 121, 243, 227, 68, 131, 134, 232, 2, 35, 60, 187, 77,
111 209, 76, 106, 174, 15, 241, 227, 115, 151, 77, 175, 36, 187, 121, 221,
112 223, 47, 118, 61, 168, 105, 32, 237, 236, 167, 213, 238, 202, 17, 170,
113 24, 226, 247, 131, 145, 6, 116, 117, 121, 11, 194, 41, 48, 126, 162, 13,
114 93, 209, 131, 154, 122, 237, 187, 103, 217, 99, 60, 200, 45, 78, 115, 69,
115 49, 106, 200, 194, 112, 60, 56, 234, 72, 251, 19, 120, 121, 182, 134, 215,
116 135, 10, 114, 2, 247, 46, 105, 209, 145, 165, 153, 191, 243, 12, 5, 36,
117 119, 206, 231, 231, 11, 32, 209, 83, 27, 229, 204, 149, 155, 83, 109, 35,
118 93, 223, 37, 84, 14, 142, 37, 160, 52, 191, 96, 40, 204, 101, 77, 67, 52,
119 53, 43, 63, 85, 253, 147, 113, 226, 96, 6, 125, 179, 115, 161, 17, 83,
120 198, 101, 98, 85, 139, 3, 137, 75, 99, 178, 23, 201, 255, 91, 253, 52,
121 134, 60, 138, 131, 208, 251, 101, 48, 2, 227, 228, 118, 132, 245, 202,
122 75, 91, 44, 160, 231, 47, 41, 50, 147, 220, 74, 92, 219, 165, 89, 16
123 };
124
125 // Expected result
126 static const uint8_t expected_dst[kDstSize] = {
127 117, 102, 74, 135, 42, 98, 175, 206, 70, 73, 222, 197, 50, 24, 39, 49, 38,
128 105, 90, 47, 169, 40, 171, 215, 200, 73, 109, 141, 53, 85, 177, 164, 79,
129 208, 124, 89, 212, 18, 81, 145, 151, 164, 217, 153, 91, 154, 102, 102,
130 159, 75, 164, 152, 136, 51, 213, 219, 186, 116, 193, 224, 186, 36, 231,
131 208, 84, 211, 155, 167, 35, 59, 42, 76, 216, 149, 73, 201, 78, 149, 184,
132 100, 96, 196, 189, 198, 188, 235, 195, 117, 129, 120, 129, 49, 25, 133,
133 113, 69, 221, 114, 70, 143, 99, 157, 108, 189, 140, 78, 6, 55, 65, 240,
134 255, 245, 184, 72, 90, 100, 116, 131, 39, 60, 234, 167, 33, 160, 88, 185,
135 200, 157, 159, 176, 127, 151, 138, 102, 168, 106, 170, 86, 82, 219, 189,
136 76, 33, 115, 197, 106, 96, 198, 136, 97, 141, 237, 151, 98, 137, 191,
137 185, 2, 57, 95, 142, 91, 255, 185, 97, 137, 76, 162, 94, 173, 131, 193,
138 161, 81, 106, 72, 135, 222, 234, 137, 66, 137, 106, 243, 210, 147, 95,
139 15, 137, 110, 85, 66, 16, 96, 167, 147, 150, 173, 203, 140, 118, 196,
140 84, 147, 160, 19, 95, 101, 123, 74, 132, 202, 82, 166, 12, 131, 166,
141 189, 170, 159, 85, 79, 66, 57, 152, 132, 203, 194, 0, 1, 56, 146, 180,
142 224, 156, 28, 83, 181, 79, 76, 80, 46, 160, 175, 59, 106, 43, 87, 75,
143 136, 85, 189, 46, 71, 200, 90
144 };
145
146 uint8_t *src = const_cast<uint8_t*>(test_data);
147
148 ASM_REGISTER_STATE_CHECK(
149 sixtap_predict_(&src[kSrcStride * 2 + 2 + 1], kSrcStride,
150 2, 2, dst_, kDstStride));
151
152 for (int i = 0; i < height_; ++i)
153 for (int j = 0; j < width_; ++j)
154 ASSERT_EQ(expected_dst[i * kDstStride + j], dst_[i * kDstStride + j])
155 << "i==" << (i * width_ + j);
156 }
157
158 using libvpx_test::ACMRandom;
159
TEST_P(SixtapPredictTest,TestWithRandomData)160 TEST_P(SixtapPredictTest, TestWithRandomData) {
161 ACMRandom rnd(ACMRandom::DeterministicSeed());
162 for (int i = 0; i < kSrcSize; ++i)
163 src_[i] = rnd.Rand8();
164
165 // Run tests for all possible offsets.
166 for (int xoffset = 0; xoffset < 8; ++xoffset) {
167 for (int yoffset = 0; yoffset < 8; ++yoffset) {
168 // Call c reference function.
169 // Move start point to next pixel to test if the function reads
170 // unaligned data correctly.
171 vp8_sixtap_predict16x16_c(&src_[kSrcStride * 2 + 2 + 1], kSrcStride,
172 xoffset, yoffset, dst_c_, kDstStride);
173
174 // Run test.
175 ASM_REGISTER_STATE_CHECK(
176 sixtap_predict_(&src_[kSrcStride * 2 + 2 + 1], kSrcStride,
177 xoffset, yoffset, dst_, kDstStride));
178
179 for (int i = 0; i < height_; ++i)
180 for (int j = 0; j < width_; ++j)
181 ASSERT_EQ(dst_c_[i * kDstStride + j], dst_[i * kDstStride + j])
182 << "i==" << (i * width_ + j);
183 }
184 }
185 }
186
187 using std::tr1::make_tuple;
188
189 const SixtapPredictFunc sixtap_16x16_c = vp8_sixtap_predict16x16_c;
190 const SixtapPredictFunc sixtap_8x8_c = vp8_sixtap_predict8x8_c;
191 const SixtapPredictFunc sixtap_8x4_c = vp8_sixtap_predict8x4_c;
192 const SixtapPredictFunc sixtap_4x4_c = vp8_sixtap_predict4x4_c;
193 INSTANTIATE_TEST_CASE_P(
194 C, SixtapPredictTest, ::testing::Values(
195 make_tuple(16, 16, sixtap_16x16_c),
196 make_tuple(8, 8, sixtap_8x8_c),
197 make_tuple(8, 4, sixtap_8x4_c),
198 make_tuple(4, 4, sixtap_4x4_c)));
199 #if HAVE_NEON
200 const SixtapPredictFunc sixtap_16x16_neon = vp8_sixtap_predict16x16_neon;
201 const SixtapPredictFunc sixtap_8x8_neon = vp8_sixtap_predict8x8_neon;
202 const SixtapPredictFunc sixtap_8x4_neon = vp8_sixtap_predict8x4_neon;
203 INSTANTIATE_TEST_CASE_P(
204 NEON, SixtapPredictTest, ::testing::Values(
205 make_tuple(16, 16, sixtap_16x16_neon),
206 make_tuple(8, 8, sixtap_8x8_neon),
207 make_tuple(8, 4, sixtap_8x4_neon)));
208 #endif
209 #if HAVE_MMX
210 const SixtapPredictFunc sixtap_16x16_mmx = vp8_sixtap_predict16x16_mmx;
211 const SixtapPredictFunc sixtap_8x8_mmx = vp8_sixtap_predict8x8_mmx;
212 const SixtapPredictFunc sixtap_8x4_mmx = vp8_sixtap_predict8x4_mmx;
213 const SixtapPredictFunc sixtap_4x4_mmx = vp8_sixtap_predict4x4_mmx;
214 INSTANTIATE_TEST_CASE_P(
215 MMX, SixtapPredictTest, ::testing::Values(
216 make_tuple(16, 16, sixtap_16x16_mmx),
217 make_tuple(8, 8, sixtap_8x8_mmx),
218 make_tuple(8, 4, sixtap_8x4_mmx),
219 make_tuple(4, 4, sixtap_4x4_mmx)));
220 #endif
221 #if HAVE_SSE2
222 const SixtapPredictFunc sixtap_16x16_sse2 = vp8_sixtap_predict16x16_sse2;
223 const SixtapPredictFunc sixtap_8x8_sse2 = vp8_sixtap_predict8x8_sse2;
224 const SixtapPredictFunc sixtap_8x4_sse2 = vp8_sixtap_predict8x4_sse2;
225 INSTANTIATE_TEST_CASE_P(
226 SSE2, SixtapPredictTest, ::testing::Values(
227 make_tuple(16, 16, sixtap_16x16_sse2),
228 make_tuple(8, 8, sixtap_8x8_sse2),
229 make_tuple(8, 4, sixtap_8x4_sse2)));
230 #endif
231 #if HAVE_SSSE3
232 const SixtapPredictFunc sixtap_16x16_ssse3 = vp8_sixtap_predict16x16_ssse3;
233 const SixtapPredictFunc sixtap_8x8_ssse3 = vp8_sixtap_predict8x8_ssse3;
234 const SixtapPredictFunc sixtap_8x4_ssse3 = vp8_sixtap_predict8x4_ssse3;
235 const SixtapPredictFunc sixtap_4x4_ssse3 = vp8_sixtap_predict4x4_ssse3;
236 INSTANTIATE_TEST_CASE_P(
237 SSSE3, SixtapPredictTest, ::testing::Values(
238 make_tuple(16, 16, sixtap_16x16_ssse3),
239 make_tuple(8, 8, sixtap_8x8_ssse3),
240 make_tuple(8, 4, sixtap_8x4_ssse3),
241 make_tuple(4, 4, sixtap_4x4_ssse3)));
242 #endif
243 #if HAVE_MSA
244 const SixtapPredictFunc sixtap_16x16_msa = vp8_sixtap_predict16x16_msa;
245 const SixtapPredictFunc sixtap_8x8_msa = vp8_sixtap_predict8x8_msa;
246 const SixtapPredictFunc sixtap_8x4_msa = vp8_sixtap_predict8x4_msa;
247 const SixtapPredictFunc sixtap_4x4_msa = vp8_sixtap_predict4x4_msa;
248 INSTANTIATE_TEST_CASE_P(
249 MSA, SixtapPredictTest, ::testing::Values(
250 make_tuple(16, 16, sixtap_16x16_msa),
251 make_tuple(8, 8, sixtap_8x8_msa),
252 make_tuple(8, 4, sixtap_8x4_msa),
253 make_tuple(4, 4, sixtap_4x4_msa)));
254 #endif
255 } // namespace
256