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