2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
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.
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"
18 #include "./vpx_config.h"
19 #include "./vp8_rtcd.h"
20 #include "vp8/common/blockd.h"
21 #include "vpx_mem/vpx_mem.h"
26 using libvpx_test::ACMRandom;
30 virtual ~IntraPredBase() {}
32 virtual void TearDown() {
33 libvpx_test::ClearSystemState();
37 void SetupMacroblock(MACROBLOCKD *mbptr,
45 mbptr_->up_available = 1;
46 mbptr_->left_available = 1;
47 mbptr_->mode_info_context = miptr_;
49 block_size_ = block_size;
50 num_planes_ = num_planes;
51 for (int p = 0; p < num_planes; p++)
52 data_ptr_[p] = data + stride * (block_size + 1) * p +
57 // Fill edges with random data
58 ACMRandom rnd(ACMRandom::DeterministicSeed());
59 for (int p = 0; p < num_planes_; p++) {
60 for (int x = -1 ; x <= block_size_; x++)
61 data_ptr_[p][x - stride_] = rnd.Rand8();
62 for (int y = 0; y < block_size_; y++)
63 data_ptr_[p][y * stride_ - 1] = rnd.Rand8();
67 virtual void Predict(MB_PREDICTION_MODE mode) = 0;
69 void SetLeftUnavailable() {
70 mbptr_->left_available = 0;
71 for (int p = 0; p < num_planes_; p++)
72 for (int i = -1; i < block_size_; ++i)
73 data_ptr_[p][stride_ * i - 1] = 129;
76 void SetTopUnavailable() {
77 mbptr_->up_available = 0;
78 for (int p = 0; p < num_planes_; p++)
79 memset(&data_ptr_[p][-1 - stride_], 127, block_size_ + 2);
82 void SetTopLeftUnavailable() {
87 int BlockSizeLog2Min1() const {
88 switch (block_size_) {
98 // check DC prediction output against a reference
99 void CheckDCPrediction() const {
100 for (int p = 0; p < num_planes_; p++) {
101 // calculate expected DC
103 if (mbptr_->up_available || mbptr_->left_available) {
104 int sum = 0, shift = BlockSizeLog2Min1() + mbptr_->up_available +
105 mbptr_->left_available;
106 if (mbptr_->up_available)
107 for (int x = 0; x < block_size_; x++)
108 sum += data_ptr_[p][x - stride_];
109 if (mbptr_->left_available)
110 for (int y = 0; y < block_size_; y++)
111 sum += data_ptr_[p][y * stride_ - 1];
112 expected = (sum + (1 << (shift - 1))) >> shift;
116 // check that all subsequent lines are equal to the first
117 for (int y = 1; y < block_size_; ++y)
118 ASSERT_EQ(0, memcmp(data_ptr_[p], &data_ptr_[p][y * stride_],
120 // within the first line, ensure that each pixel has the same value
121 for (int x = 1; x < block_size_; ++x)
122 ASSERT_EQ(data_ptr_[p][0], data_ptr_[p][x]);
123 // now ensure that that pixel has the expected (DC) value
124 ASSERT_EQ(expected, data_ptr_[p][0]);
128 // check V prediction output against a reference
129 void CheckVPrediction() const {
130 // check that all lines equal the top border
131 for (int p = 0; p < num_planes_; p++)
132 for (int y = 0; y < block_size_; y++)
133 ASSERT_EQ(0, memcmp(&data_ptr_[p][-stride_],
134 &data_ptr_[p][y * stride_], block_size_));
137 // check H prediction output against a reference
138 void CheckHPrediction() const {
139 // for each line, ensure that each pixel is equal to the left border
140 for (int p = 0; p < num_planes_; p++)
141 for (int y = 0; y < block_size_; y++)
142 for (int x = 0; x < block_size_; x++)
143 ASSERT_EQ(data_ptr_[p][-1 + y * stride_],
144 data_ptr_[p][x + y * stride_]);
147 static int ClipByte(int value) {
155 // check TM prediction output against a reference
156 void CheckTMPrediction() const {
157 for (int p = 0; p < num_planes_; p++)
158 for (int y = 0; y < block_size_; y++)
159 for (int x = 0; x < block_size_; x++) {
160 const int expected = ClipByte(data_ptr_[p][x - stride_]
161 + data_ptr_[p][stride_ * y - 1]
162 - data_ptr_[p][-1 - stride_]);
163 ASSERT_EQ(expected, data_ptr_[p][y * stride_ + x]);
170 SCOPED_TRACE("DC_PRED");
176 SCOPED_TRACE("DC_PRED LEFT");
178 SetLeftUnavailable();
183 SCOPED_TRACE("DC_PRED TOP");
190 SCOPED_TRACE("DC_PRED TOP_LEFT");
192 SetTopLeftUnavailable();
197 SCOPED_TRACE("H_PRED");
203 SCOPED_TRACE("V_PRED");
209 SCOPED_TRACE("TM_PRED");
218 uint8_t *data_ptr_[2]; // in the case of Y, only [0] is used
224 typedef void (*intra_pred_y_fn_t)(MACROBLOCKD *x,
231 class IntraPredYTest : public ::testing::TestWithParam<intra_pred_y_fn_t>,
232 protected IntraPredBase {
234 static void SetUpTestCase() {
235 mb_ = reinterpret_cast<MACROBLOCKD*>(
236 vpx_memalign(32, sizeof(MACROBLOCKD)));
237 mi_ = reinterpret_cast<MODE_INFO*>(
238 vpx_memalign(32, sizeof(MODE_INFO)));
239 data_array_ = reinterpret_cast<uint8_t*>(
240 vpx_memalign(kDataAlignment, kDataBufferSize));
243 static void TearDownTestCase() {
244 vpx_free(data_array_);
251 static const int kBlockSize = 16;
252 static const int kDataAlignment = 16;
253 static const int kStride = kBlockSize * 3;
254 // We use 48 so that the data pointer of the first pixel in each row of
255 // each macroblock is 16-byte aligned, and this gives us access to the
256 // top-left and top-right corner pixels belonging to the top-left/right
258 // We use 17 lines so we have one line above us for top-prediction.
259 static const int kDataBufferSize = kStride * (kBlockSize + 1);
261 virtual void SetUp() {
262 pred_fn_ = GetParam();
263 SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 1);
266 virtual void Predict(MB_PREDICTION_MODE mode) {
267 mbptr_->mode_info_context->mbmi.mode = mode;
268 REGISTER_STATE_CHECK(pred_fn_(mbptr_,
269 data_ptr_[0] - kStride,
270 data_ptr_[0] - 1, kStride,
271 data_ptr_[0], kStride));
274 intra_pred_y_fn_t pred_fn_;
275 static uint8_t* data_array_;
276 static MACROBLOCKD * mb_;
277 static MODE_INFO *mi_;
280 MACROBLOCKD* IntraPredYTest::mb_ = NULL;
281 MODE_INFO* IntraPredYTest::mi_ = NULL;
282 uint8_t* IntraPredYTest::data_array_ = NULL;
284 TEST_P(IntraPredYTest, IntraPredTests) {
288 INSTANTIATE_TEST_CASE_P(C, IntraPredYTest,
290 vp8_build_intra_predictors_mby_s_c));
292 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredYTest,
294 vp8_build_intra_predictors_mby_s_sse2));
297 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredYTest,
299 vp8_build_intra_predictors_mby_s_ssse3));
302 typedef void (*intra_pred_uv_fn_t)(MACROBLOCKD *x,
312 class IntraPredUVTest : public ::testing::TestWithParam<intra_pred_uv_fn_t>,
313 protected IntraPredBase {
315 static void SetUpTestCase() {
316 mb_ = reinterpret_cast<MACROBLOCKD*>(
317 vpx_memalign(32, sizeof(MACROBLOCKD)));
318 mi_ = reinterpret_cast<MODE_INFO*>(
319 vpx_memalign(32, sizeof(MODE_INFO)));
320 data_array_ = reinterpret_cast<uint8_t*>(
321 vpx_memalign(kDataAlignment, kDataBufferSize));
324 static void TearDownTestCase() {
325 vpx_free(data_array_);
332 static const int kBlockSize = 8;
333 static const int kDataAlignment = 8;
334 static const int kStride = kBlockSize * 3;
335 // We use 24 so that the data pointer of the first pixel in each row of
336 // each macroblock is 8-byte aligned, and this gives us access to the
337 // top-left and top-right corner pixels belonging to the top-left/right
339 // We use 9 lines so we have one line above us for top-prediction.
341 static const int kDataBufferSize = 2 * kStride * (kBlockSize + 1);
343 virtual void SetUp() {
344 pred_fn_ = GetParam();
345 SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 2);
348 virtual void Predict(MB_PREDICTION_MODE mode) {
349 mbptr_->mode_info_context->mbmi.uv_mode = mode;
350 pred_fn_(mbptr_, data_ptr_[0] - kStride, data_ptr_[1] - kStride,
351 data_ptr_[0] - 1, data_ptr_[1] - 1, kStride,
352 data_ptr_[0], data_ptr_[1], kStride);
355 intra_pred_uv_fn_t pred_fn_;
356 // We use 24 so that the data pointer of the first pixel in each row of
357 // each macroblock is 8-byte aligned, and this gives us access to the
358 // top-left and top-right corner pixels belonging to the top-left/right
360 // We use 9 lines so we have one line above us for top-prediction.
362 static uint8_t* data_array_;
363 static MACROBLOCKD* mb_;
364 static MODE_INFO* mi_;
367 MACROBLOCKD* IntraPredUVTest::mb_ = NULL;
368 MODE_INFO* IntraPredUVTest::mi_ = NULL;
369 uint8_t* IntraPredUVTest::data_array_ = NULL;
371 TEST_P(IntraPredUVTest, IntraPredTests) {
375 INSTANTIATE_TEST_CASE_P(C, IntraPredUVTest,
377 vp8_build_intra_predictors_mbuv_s_c));
379 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredUVTest,
381 vp8_build_intra_predictors_mbuv_s_sse2));
384 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredUVTest,
386 vp8_build_intra_predictors_mbuv_s_ssse3));