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