• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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