1 /*
2  *  Copyright (c) 2014 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 <string>
12 
13 #include "third_party/googletest/src/include/gtest/gtest.h"
14 
15 #include "./vpx_config.h"
16 #include "./vpx_dsp_rtcd.h"
17 #include "test/acm_random.h"
18 #include "test/clear_system_state.h"
19 #include "test/register_state_check.h"
20 #include "test/util.h"
21 #include "vp9/common/vp9_blockd.h"
22 #include "vp9/common/vp9_pred_common.h"
23 #include "vpx_mem/vpx_mem.h"
24 
25 namespace {
26 
27 using libvpx_test::ACMRandom;
28 
29 const int count_test_block = 100000;
30 
31 // Base class for VP9 intra prediction tests.
32 class VP9IntraPredBase {
33  public:
~VP9IntraPredBase()34   virtual ~VP9IntraPredBase() { libvpx_test::ClearSystemState(); }
35 
36  protected:
37   virtual void Predict(PREDICTION_MODE mode) = 0;
38 
CheckPrediction(int test_case_number,int * error_count) const39   void CheckPrediction(int test_case_number, int *error_count) const {
40     // For each pixel ensure that the calculated value is the same as reference.
41     for (int y = 0; y < block_size_; y++) {
42       for (int x = 0; x < block_size_; x++) {
43         *error_count += ref_dst_[x + y * stride_] != dst_[x + y * stride_];
44         if (*error_count == 1) {
45           ASSERT_EQ(ref_dst_[x + y * stride_], dst_[x + y * stride_])
46               << " Failed on Test Case Number "<< test_case_number;
47         }
48       }
49     }
50   }
51 
RunTest(uint16_t * left_col,uint16_t * above_data,uint16_t * dst,uint16_t * ref_dst)52   void RunTest(uint16_t* left_col, uint16_t* above_data,
53                uint16_t* dst, uint16_t* ref_dst) {
54     ACMRandom rnd(ACMRandom::DeterministicSeed());
55     left_col_ = left_col;
56     dst_ = dst;
57     ref_dst_ = ref_dst;
58     above_row_ = above_data + 16;
59     int error_count = 0;
60     for (int i = 0; i < count_test_block; ++i) {
61       // Fill edges with random data, try first with saturated values.
62       for (int x = -1; x <= block_size_*2; x++) {
63         if (i == 0) {
64           above_row_[x] = mask_;
65         } else {
66           above_row_[x] = rnd.Rand16() & mask_;
67         }
68       }
69       for (int y = 0; y < block_size_; y++) {
70         if (i == 0) {
71           left_col_[y] = mask_;
72         } else {
73           left_col_[y] = rnd.Rand16() & mask_;
74         }
75       }
76       Predict(DC_PRED);
77       CheckPrediction(i, &error_count);
78     }
79     ASSERT_EQ(0, error_count);
80   }
81 
82   int block_size_;
83   uint16_t *above_row_;
84   uint16_t *left_col_;
85   uint16_t *dst_;
86   uint16_t *ref_dst_;
87   ptrdiff_t stride_;
88   int mask_;
89 };
90 
91 typedef void (*intra_pred_fn_t)(
92       uint16_t *dst, ptrdiff_t stride, const uint16_t *above,
93       const uint16_t *left, int bps);
94 typedef std::tr1::tuple<intra_pred_fn_t,
95                         intra_pred_fn_t, int, int> intra_pred_params_t;
96 class VP9IntraPredTest
97     : public VP9IntraPredBase,
98       public ::testing::TestWithParam<intra_pred_params_t> {
99 
SetUp()100   virtual void SetUp() {
101     pred_fn_    = GET_PARAM(0);
102     ref_fn_     = GET_PARAM(1);
103     block_size_ = GET_PARAM(2);
104     bit_depth_  = GET_PARAM(3);
105     stride_     = block_size_ * 3;
106     mask_       = (1 << bit_depth_) - 1;
107   }
108 
Predict(PREDICTION_MODE mode)109   virtual void Predict(PREDICTION_MODE mode) {
110     const uint16_t *const_above_row = above_row_;
111     const uint16_t *const_left_col = left_col_;
112     ref_fn_(ref_dst_, stride_, const_above_row, const_left_col, bit_depth_);
113     ASM_REGISTER_STATE_CHECK(pred_fn_(dst_, stride_, const_above_row,
114                                       const_left_col, bit_depth_));
115   }
116   intra_pred_fn_t pred_fn_;
117   intra_pred_fn_t ref_fn_;
118   int bit_depth_;
119 };
120 
TEST_P(VP9IntraPredTest,IntraPredTests)121 TEST_P(VP9IntraPredTest, IntraPredTests) {
122   // max block size is 32
123   DECLARE_ALIGNED(16, uint16_t, left_col[2*32]);
124   DECLARE_ALIGNED(16, uint16_t, above_data[2*32+32]);
125   DECLARE_ALIGNED(16, uint16_t, dst[3 * 32 * 32]);
126   DECLARE_ALIGNED(16, uint16_t, ref_dst[3 * 32 * 32]);
127   RunTest(left_col, above_data, dst, ref_dst);
128 }
129 
130 using std::tr1::make_tuple;
131 
132 #if HAVE_SSE2
133 #if CONFIG_VP9_HIGHBITDEPTH
134 #if CONFIG_USE_X86INC
135 #if ARCH_X86_64
136 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_8, VP9IntraPredTest,
137                         ::testing::Values(
138                             make_tuple(&vpx_highbd_dc_predictor_32x32_sse2,
139                                        &vpx_highbd_dc_predictor_32x32_c, 32, 8),
140                             make_tuple(&vpx_highbd_tm_predictor_16x16_sse2,
141                                        &vpx_highbd_tm_predictor_16x16_c, 16, 8),
142                             make_tuple(&vpx_highbd_tm_predictor_32x32_sse2,
143                                        &vpx_highbd_tm_predictor_32x32_c, 32, 8),
144                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
145                                        &vpx_highbd_dc_predictor_4x4_c, 4, 8),
146                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
147                                        &vpx_highbd_dc_predictor_8x8_c, 8, 8),
148                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
149                                        &vpx_highbd_dc_predictor_16x16_c, 16, 8),
150                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
151                                        &vpx_highbd_v_predictor_4x4_c, 4, 8),
152                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
153                                        &vpx_highbd_v_predictor_8x8_c, 8, 8),
154                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
155                                        &vpx_highbd_v_predictor_16x16_c, 16, 8),
156                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
157                                        &vpx_highbd_v_predictor_32x32_c, 32, 8),
158                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
159                                        &vpx_highbd_tm_predictor_4x4_c, 4, 8),
160                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
161                                        &vpx_highbd_tm_predictor_8x8_c, 8, 8)));
162 #else
163 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_8, VP9IntraPredTest,
164                         ::testing::Values(
165                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
166                                        &vpx_highbd_dc_predictor_4x4_c, 4, 8),
167                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
168                                        &vpx_highbd_dc_predictor_8x8_c, 8, 8),
169                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
170                                        &vpx_highbd_dc_predictor_16x16_c, 16, 8),
171                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
172                                        &vpx_highbd_v_predictor_4x4_c, 4, 8),
173                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
174                                        &vpx_highbd_v_predictor_8x8_c, 8, 8),
175                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
176                                        &vpx_highbd_v_predictor_16x16_c, 16, 8),
177                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
178                                        &vpx_highbd_v_predictor_32x32_c, 32, 8),
179                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
180                                        &vpx_highbd_tm_predictor_4x4_c, 4, 8),
181                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
182                                        &vpx_highbd_tm_predictor_8x8_c, 8, 8)));
183 #endif  // !ARCH_X86_64
184 
185 #if ARCH_X86_64
186 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_10, VP9IntraPredTest,
187                         ::testing::Values(
188                             make_tuple(&vpx_highbd_dc_predictor_32x32_sse2,
189                                        &vpx_highbd_dc_predictor_32x32_c, 32,
190                                        10),
191                             make_tuple(&vpx_highbd_tm_predictor_16x16_sse2,
192                                        &vpx_highbd_tm_predictor_16x16_c, 16,
193                                        10),
194                             make_tuple(&vpx_highbd_tm_predictor_32x32_sse2,
195                                        &vpx_highbd_tm_predictor_32x32_c, 32,
196                                        10),
197                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
198                                        &vpx_highbd_dc_predictor_4x4_c, 4, 10),
199                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
200                                        &vpx_highbd_dc_predictor_8x8_c, 8, 10),
201                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
202                                        &vpx_highbd_dc_predictor_16x16_c, 16,
203                                        10),
204                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
205                                        &vpx_highbd_v_predictor_4x4_c, 4, 10),
206                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
207                                        &vpx_highbd_v_predictor_8x8_c, 8, 10),
208                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
209                                        &vpx_highbd_v_predictor_16x16_c, 16,
210                                        10),
211                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
212                                        &vpx_highbd_v_predictor_32x32_c, 32,
213                                        10),
214                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
215                                        &vpx_highbd_tm_predictor_4x4_c, 4, 10),
216                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
217                                        &vpx_highbd_tm_predictor_8x8_c, 8, 10)));
218 #else
219 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_10, VP9IntraPredTest,
220                         ::testing::Values(
221                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
222                                        &vpx_highbd_dc_predictor_4x4_c, 4, 10),
223                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
224                                        &vpx_highbd_dc_predictor_8x8_c, 8, 10),
225                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
226                                        &vpx_highbd_dc_predictor_16x16_c, 16,
227                                        10),
228                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
229                                        &vpx_highbd_v_predictor_4x4_c, 4, 10),
230                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
231                                        &vpx_highbd_v_predictor_8x8_c, 8, 10),
232                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
233                                        &vpx_highbd_v_predictor_16x16_c, 16, 10),
234                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
235                                        &vpx_highbd_v_predictor_32x32_c, 32, 10),
236                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
237                                        &vpx_highbd_tm_predictor_4x4_c, 4, 10),
238                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
239                                        &vpx_highbd_tm_predictor_8x8_c, 8, 10)));
240 #endif  // !ARCH_X86_64
241 
242 #if ARCH_X86_64
243 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_12, VP9IntraPredTest,
244                         ::testing::Values(
245                             make_tuple(&vpx_highbd_dc_predictor_32x32_sse2,
246                                        &vpx_highbd_dc_predictor_32x32_c, 32,
247                                        12),
248                             make_tuple(&vpx_highbd_tm_predictor_16x16_sse2,
249                                        &vpx_highbd_tm_predictor_16x16_c, 16,
250                                        12),
251                             make_tuple(&vpx_highbd_tm_predictor_32x32_sse2,
252                                        &vpx_highbd_tm_predictor_32x32_c, 32,
253                                        12),
254                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
255                                        &vpx_highbd_dc_predictor_4x4_c, 4, 12),
256                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
257                                        &vpx_highbd_dc_predictor_8x8_c, 8, 12),
258                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
259                                        &vpx_highbd_dc_predictor_16x16_c, 16,
260                                        12),
261                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
262                                        &vpx_highbd_v_predictor_4x4_c, 4, 12),
263                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
264                                        &vpx_highbd_v_predictor_8x8_c, 8, 12),
265                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
266                                        &vpx_highbd_v_predictor_16x16_c, 16,
267                                        12),
268                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
269                                        &vpx_highbd_v_predictor_32x32_c, 32,
270                                        12),
271                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
272                                        &vpx_highbd_tm_predictor_4x4_c, 4, 12),
273                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
274                                        &vpx_highbd_tm_predictor_8x8_c, 8, 12)));
275 #else
276 INSTANTIATE_TEST_CASE_P(SSE2_TO_C_12, VP9IntraPredTest,
277                         ::testing::Values(
278                             make_tuple(&vpx_highbd_dc_predictor_4x4_sse,
279                                        &vpx_highbd_dc_predictor_4x4_c, 4, 12),
280                             make_tuple(&vpx_highbd_dc_predictor_8x8_sse2,
281                                        &vpx_highbd_dc_predictor_8x8_c, 8, 12),
282                             make_tuple(&vpx_highbd_dc_predictor_16x16_sse2,
283                                        &vpx_highbd_dc_predictor_16x16_c, 16,
284                                        12),
285                             make_tuple(&vpx_highbd_v_predictor_4x4_sse,
286                                        &vpx_highbd_v_predictor_4x4_c, 4, 12),
287                             make_tuple(&vpx_highbd_v_predictor_8x8_sse2,
288                                        &vpx_highbd_v_predictor_8x8_c, 8, 12),
289                             make_tuple(&vpx_highbd_v_predictor_16x16_sse2,
290                                        &vpx_highbd_v_predictor_16x16_c, 16, 12),
291                             make_tuple(&vpx_highbd_v_predictor_32x32_sse2,
292                                        &vpx_highbd_v_predictor_32x32_c, 32, 12),
293                             make_tuple(&vpx_highbd_tm_predictor_4x4_sse,
294                                        &vpx_highbd_tm_predictor_4x4_c, 4, 12),
295                             make_tuple(&vpx_highbd_tm_predictor_8x8_sse2,
296                                        &vpx_highbd_tm_predictor_8x8_c, 8, 12)));
297 #endif  // !ARCH_X86_64
298 #endif  // CONFIG_USE_X86INC
299 #endif  // CONFIG_VP9_HIGHBITDEPTH
300 #endif  // HAVE_SSE2
301 }  // namespace
302