Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / test / intrapred_test.cc
1 /*
2  *  Copyright (c) 2012 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
12 #include <string.h>
13 #include "test/acm_random.h"
14 #include "test/clear_system_state.h"
15 #include "test/register_state_check.h"
16 #include "third_party/googletest/src/include/gtest/gtest.h"
17
18 #include "./vpx_config.h"
19 #include "./vp8_rtcd.h"
20 #include "vp8/common/blockd.h"
21 #include "vpx_mem/vpx_mem.h"
22
23 namespace {
24
25 using libvpx_test::ACMRandom;
26
27 class IntraPredBase {
28  public:
29   virtual ~IntraPredBase() { libvpx_test::ClearSystemState(); }
30
31  protected:
32   void SetupMacroblock(MACROBLOCKD *mbptr,
33                        MODE_INFO *miptr,
34                        uint8_t *data,
35                        int block_size,
36                        int stride,
37                        int num_planes) {
38     mbptr_ = mbptr;
39     miptr_ = miptr;
40     mbptr_->up_available = 1;
41     mbptr_->left_available = 1;
42     mbptr_->mode_info_context = miptr_;
43     stride_ = stride;
44     block_size_ = block_size;
45     num_planes_ = num_planes;
46     for (int p = 0; p < num_planes; p++)
47       data_ptr_[p] = data + stride * (block_size + 1) * p +
48                      stride + block_size;
49   }
50
51   void FillRandom() {
52     // Fill edges with random data
53     ACMRandom rnd(ACMRandom::DeterministicSeed());
54     for (int p = 0; p < num_planes_; p++) {
55       for (int x = -1 ; x <= block_size_; x++)
56         data_ptr_[p][x - stride_] = rnd.Rand8();
57       for (int y = 0; y < block_size_; y++)
58         data_ptr_[p][y * stride_ - 1] = rnd.Rand8();
59     }
60   }
61
62   virtual void Predict(MB_PREDICTION_MODE mode) = 0;
63
64   void SetLeftUnavailable() {
65     mbptr_->left_available = 0;
66     for (int p = 0; p < num_planes_; p++)
67       for (int i = -1; i < block_size_; ++i)
68         data_ptr_[p][stride_ * i - 1] = 129;
69   }
70
71   void SetTopUnavailable() {
72     mbptr_->up_available = 0;
73     for (int p = 0; p < num_planes_; p++)
74       memset(&data_ptr_[p][-1 - stride_], 127, block_size_ + 2);
75   }
76
77   void SetTopLeftUnavailable() {
78     SetLeftUnavailable();
79     SetTopUnavailable();
80   }
81
82   int BlockSizeLog2Min1() const {
83     switch (block_size_) {
84       case 16:
85         return 3;
86       case 8:
87         return 2;
88       default:
89         return 0;
90     }
91   }
92
93   // check DC prediction output against a reference
94   void CheckDCPrediction() const {
95     for (int p = 0; p < num_planes_; p++) {
96       // calculate expected DC
97       int expected;
98       if (mbptr_->up_available || mbptr_->left_available) {
99         int sum = 0, shift = BlockSizeLog2Min1() + mbptr_->up_available +
100                              mbptr_->left_available;
101         if (mbptr_->up_available)
102           for (int x = 0; x < block_size_; x++)
103             sum += data_ptr_[p][x - stride_];
104         if (mbptr_->left_available)
105           for (int y = 0; y < block_size_; y++)
106             sum += data_ptr_[p][y * stride_ - 1];
107         expected = (sum + (1 << (shift - 1))) >> shift;
108       } else {
109         expected = 0x80;
110       }
111       // check that all subsequent lines are equal to the first
112       for (int y = 1; y < block_size_; ++y)
113         ASSERT_EQ(0, memcmp(data_ptr_[p], &data_ptr_[p][y * stride_],
114                             block_size_));
115       // within the first line, ensure that each pixel has the same value
116       for (int x = 1; x < block_size_; ++x)
117         ASSERT_EQ(data_ptr_[p][0], data_ptr_[p][x]);
118       // now ensure that that pixel has the expected (DC) value
119       ASSERT_EQ(expected, data_ptr_[p][0]);
120     }
121   }
122
123   // check V prediction output against a reference
124   void CheckVPrediction() const {
125     // check that all lines equal the top border
126     for (int p = 0; p < num_planes_; p++)
127       for (int y = 0; y < block_size_; y++)
128         ASSERT_EQ(0, memcmp(&data_ptr_[p][-stride_],
129                             &data_ptr_[p][y * stride_], block_size_));
130   }
131
132   // check H prediction output against a reference
133   void CheckHPrediction() const {
134     // for each line, ensure that each pixel is equal to the left border
135     for (int p = 0; p < num_planes_; p++)
136       for (int y = 0; y < block_size_; y++)
137         for (int x = 0; x < block_size_; x++)
138           ASSERT_EQ(data_ptr_[p][-1 + y * stride_],
139                     data_ptr_[p][x + y * stride_]);
140   }
141
142   static int ClipByte(int value) {
143     if (value > 255)
144       return 255;
145     else if (value < 0)
146       return 0;
147     return value;
148   }
149
150   // check TM prediction output against a reference
151   void CheckTMPrediction() const {
152     for (int p = 0; p < num_planes_; p++)
153       for (int y = 0; y < block_size_; y++)
154         for (int x = 0; x < block_size_; x++) {
155           const int expected = ClipByte(data_ptr_[p][x - stride_]
156                                       + data_ptr_[p][stride_ * y - 1]
157                                       - data_ptr_[p][-1 - stride_]);
158           ASSERT_EQ(expected, data_ptr_[p][y * stride_ + x]);
159        }
160   }
161
162   // Actual test
163   void RunTest() {
164     {
165       SCOPED_TRACE("DC_PRED");
166       FillRandom();
167       Predict(DC_PRED);
168       CheckDCPrediction();
169     }
170     {
171       SCOPED_TRACE("DC_PRED LEFT");
172       FillRandom();
173       SetLeftUnavailable();
174       Predict(DC_PRED);
175       CheckDCPrediction();
176     }
177     {
178       SCOPED_TRACE("DC_PRED TOP");
179       FillRandom();
180       SetTopUnavailable();
181       Predict(DC_PRED);
182       CheckDCPrediction();
183     }
184     {
185       SCOPED_TRACE("DC_PRED TOP_LEFT");
186       FillRandom();
187       SetTopLeftUnavailable();
188       Predict(DC_PRED);
189       CheckDCPrediction();
190     }
191     {
192       SCOPED_TRACE("H_PRED");
193       FillRandom();
194       Predict(H_PRED);
195       CheckHPrediction();
196     }
197     {
198       SCOPED_TRACE("V_PRED");
199       FillRandom();
200       Predict(V_PRED);
201       CheckVPrediction();
202     }
203     {
204       SCOPED_TRACE("TM_PRED");
205       FillRandom();
206       Predict(TM_PRED);
207       CheckTMPrediction();
208     }
209   }
210
211   MACROBLOCKD *mbptr_;
212   MODE_INFO *miptr_;
213   uint8_t *data_ptr_[2];  // in the case of Y, only [0] is used
214   int stride_;
215   int block_size_;
216   int num_planes_;
217 };
218
219 typedef void (*IntraPredYFunc)(MACROBLOCKD *x,
220                                uint8_t *yabove_row,
221                                uint8_t *yleft,
222                                int left_stride,
223                                uint8_t *ypred_ptr,
224                                int y_stride);
225
226 class IntraPredYTest
227     : public IntraPredBase,
228       public ::testing::TestWithParam<IntraPredYFunc> {
229  public:
230   static void SetUpTestCase() {
231     mb_ = reinterpret_cast<MACROBLOCKD*>(
232         vpx_memalign(32, sizeof(MACROBLOCKD)));
233     mi_ = reinterpret_cast<MODE_INFO*>(
234         vpx_memalign(32, sizeof(MODE_INFO)));
235     data_array_ = reinterpret_cast<uint8_t*>(
236         vpx_memalign(kDataAlignment, kDataBufferSize));
237   }
238
239   static void TearDownTestCase() {
240     vpx_free(data_array_);
241     vpx_free(mi_);
242     vpx_free(mb_);
243     data_array_ = NULL;
244   }
245
246  protected:
247   static const int kBlockSize = 16;
248   static const int kDataAlignment = 16;
249   static const int kStride = kBlockSize * 3;
250   // We use 48 so that the data pointer of the first pixel in each row of
251   // each macroblock is 16-byte aligned, and this gives us access to the
252   // top-left and top-right corner pixels belonging to the top-left/right
253   // macroblocks.
254   // We use 17 lines so we have one line above us for top-prediction.
255   static const int kDataBufferSize = kStride * (kBlockSize + 1);
256
257   virtual void SetUp() {
258     pred_fn_ = GetParam();
259     SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 1);
260   }
261
262   virtual void Predict(MB_PREDICTION_MODE mode) {
263     mbptr_->mode_info_context->mbmi.mode = mode;
264     ASM_REGISTER_STATE_CHECK(pred_fn_(mbptr_,
265                                       data_ptr_[0] - kStride,
266                                       data_ptr_[0] - 1, kStride,
267                                       data_ptr_[0], kStride));
268   }
269
270   IntraPredYFunc pred_fn_;
271   static uint8_t* data_array_;
272   static MACROBLOCKD * mb_;
273   static MODE_INFO *mi_;
274 };
275
276 MACROBLOCKD* IntraPredYTest::mb_ = NULL;
277 MODE_INFO* IntraPredYTest::mi_ = NULL;
278 uint8_t* IntraPredYTest::data_array_ = NULL;
279
280 TEST_P(IntraPredYTest, IntraPredTests) {
281   RunTest();
282 }
283
284 INSTANTIATE_TEST_CASE_P(C, IntraPredYTest,
285                         ::testing::Values(
286                             vp8_build_intra_predictors_mby_s_c));
287 #if HAVE_SSE2
288 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredYTest,
289                         ::testing::Values(
290                             vp8_build_intra_predictors_mby_s_sse2));
291 #endif
292 #if HAVE_SSSE3
293 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredYTest,
294                         ::testing::Values(
295                             vp8_build_intra_predictors_mby_s_ssse3));
296 #endif
297 #if HAVE_NEON
298 INSTANTIATE_TEST_CASE_P(NEON, IntraPredYTest,
299                         ::testing::Values(
300                             vp8_build_intra_predictors_mby_s_neon));
301 #endif
302
303 typedef void (*IntraPredUvFunc)(MACROBLOCKD *x,
304                                 uint8_t *uabove_row,
305                                 uint8_t *vabove_row,
306                                 uint8_t *uleft,
307                                 uint8_t *vleft,
308                                 int left_stride,
309                                 uint8_t *upred_ptr,
310                                 uint8_t *vpred_ptr,
311                                 int pred_stride);
312
313 class IntraPredUVTest
314     : public IntraPredBase,
315       public ::testing::TestWithParam<IntraPredUvFunc> {
316  public:
317   static void SetUpTestCase() {
318     mb_ = reinterpret_cast<MACROBLOCKD*>(
319         vpx_memalign(32, sizeof(MACROBLOCKD)));
320     mi_ = reinterpret_cast<MODE_INFO*>(
321         vpx_memalign(32, sizeof(MODE_INFO)));
322     data_array_ = reinterpret_cast<uint8_t*>(
323         vpx_memalign(kDataAlignment, kDataBufferSize));
324   }
325
326   static void TearDownTestCase() {
327     vpx_free(data_array_);
328     vpx_free(mi_);
329     vpx_free(mb_);
330     data_array_ = NULL;
331   }
332
333  protected:
334   static const int kBlockSize = 8;
335   static const int kDataAlignment = 8;
336   static const int kStride = kBlockSize * 3;
337   // We use 24 so that the data pointer of the first pixel in each row of
338   // each macroblock is 8-byte aligned, and this gives us access to the
339   // top-left and top-right corner pixels belonging to the top-left/right
340   // macroblocks.
341   // We use 9 lines so we have one line above us for top-prediction.
342   // [0] = U, [1] = V
343   static const int kDataBufferSize = 2 * kStride * (kBlockSize + 1);
344
345   virtual void SetUp() {
346     pred_fn_ = GetParam();
347     SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 2);
348   }
349
350   virtual void Predict(MB_PREDICTION_MODE mode) {
351     mbptr_->mode_info_context->mbmi.uv_mode = mode;
352     pred_fn_(mbptr_, data_ptr_[0] - kStride, data_ptr_[1] - kStride,
353              data_ptr_[0] - 1, data_ptr_[1] - 1, kStride,
354              data_ptr_[0], data_ptr_[1], kStride);
355   }
356
357   IntraPredUvFunc pred_fn_;
358   // We use 24 so that the data pointer of the first pixel in each row of
359   // each macroblock is 8-byte aligned, and this gives us access to the
360   // top-left and top-right corner pixels belonging to the top-left/right
361   // macroblocks.
362   // We use 9 lines so we have one line above us for top-prediction.
363   // [0] = U, [1] = V
364   static uint8_t* data_array_;
365   static MACROBLOCKD* mb_;
366   static MODE_INFO* mi_;
367 };
368
369 MACROBLOCKD* IntraPredUVTest::mb_ = NULL;
370 MODE_INFO* IntraPredUVTest::mi_ = NULL;
371 uint8_t* IntraPredUVTest::data_array_ = NULL;
372
373 TEST_P(IntraPredUVTest, IntraPredTests) {
374   RunTest();
375 }
376
377 INSTANTIATE_TEST_CASE_P(C, IntraPredUVTest,
378                         ::testing::Values(
379                             vp8_build_intra_predictors_mbuv_s_c));
380 #if HAVE_SSE2
381 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredUVTest,
382                         ::testing::Values(
383                             vp8_build_intra_predictors_mbuv_s_sse2));
384 #endif
385 #if HAVE_SSSE3
386 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredUVTest,
387                         ::testing::Values(
388                             vp8_build_intra_predictors_mbuv_s_ssse3));
389 #endif
390 #if HAVE_NEON
391 INSTANTIATE_TEST_CASE_P(NEON, IntraPredUVTest,
392                         ::testing::Values(
393                             vp8_build_intra_predictors_mbuv_s_neon));
394 #endif
395
396 }  // namespace