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"
25 using libvpx_test::ACMRandom;
29 virtual ~IntraPredBase() {}
31 virtual void TearDown() {
32 libvpx_test::ClearSystemState();
36 void SetupMacroblock(MACROBLOCKD *mbptr,
44 mbptr_->up_available = 1;
45 mbptr_->left_available = 1;
46 mbptr_->mode_info_context = miptr_;
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 +
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();
66 virtual void Predict(MB_PREDICTION_MODE mode) = 0;
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;
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);
81 void SetTopLeftUnavailable() {
86 int BlockSizeLog2Min1() const {
87 switch (block_size_) {
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
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;
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_],
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]);
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_));
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_]);
146 static int ClipByte(int value) {
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]);
169 SCOPED_TRACE("DC_PRED");
175 SCOPED_TRACE("DC_PRED LEFT");
177 SetLeftUnavailable();
182 SCOPED_TRACE("DC_PRED TOP");
189 SCOPED_TRACE("DC_PRED TOP_LEFT");
191 SetTopLeftUnavailable();
196 SCOPED_TRACE("H_PRED");
202 SCOPED_TRACE("V_PRED");
208 SCOPED_TRACE("TM_PRED");
217 uint8_t *data_ptr_[2]; // in the case of Y, only [0] is used
223 typedef void (*intra_pred_y_fn_t)(MACROBLOCKD *x,
230 class IntraPredYTest : public ::testing::TestWithParam<intra_pred_y_fn_t>,
231 protected IntraPredBase {
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));
242 static void TearDownTestCase() {
243 vpx_free(data_array_);
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
257 // We use 17 lines so we have one line above us for top-prediction.
258 static const int kDataBufferSize = kStride * (kBlockSize + 1);
260 virtual void SetUp() {
261 pred_fn_ = GetParam();
262 SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 1);
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));
273 intra_pred_y_fn_t pred_fn_;
274 static uint8_t* data_array_;
275 static MACROBLOCKD * mb_;
276 static MODE_INFO *mi_;
279 MACROBLOCKD* IntraPredYTest::mb_ = NULL;
280 MODE_INFO* IntraPredYTest::mi_ = NULL;
281 uint8_t* IntraPredYTest::data_array_ = NULL;
283 TEST_P(IntraPredYTest, IntraPredTests) {
287 INSTANTIATE_TEST_CASE_P(C, IntraPredYTest,
289 vp8_build_intra_predictors_mby_s_c));
291 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredYTest,
293 vp8_build_intra_predictors_mby_s_sse2));
296 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredYTest,
298 vp8_build_intra_predictors_mby_s_ssse3));
301 typedef void (*intra_pred_uv_fn_t)(MACROBLOCKD *x,
311 class IntraPredUVTest : public ::testing::TestWithParam<intra_pred_uv_fn_t>,
312 protected IntraPredBase {
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));
323 static void TearDownTestCase() {
324 vpx_free(data_array_);
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
338 // We use 9 lines so we have one line above us for top-prediction.
340 static const int kDataBufferSize = 2 * kStride * (kBlockSize + 1);
342 virtual void SetUp() {
343 pred_fn_ = GetParam();
344 SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 2);
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);
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
359 // We use 9 lines so we have one line above us for top-prediction.
361 static uint8_t* data_array_;
362 static MACROBLOCKD* mb_;
363 static MODE_INFO* mi_;
366 MACROBLOCKD* IntraPredUVTest::mb_ = NULL;
367 MODE_INFO* IntraPredUVTest::mi_ = NULL;
368 uint8_t* IntraPredUVTest::data_array_ = NULL;
370 TEST_P(IntraPredUVTest, IntraPredTests) {
374 INSTANTIATE_TEST_CASE_P(C, IntraPredUVTest,
376 vp8_build_intra_predictors_mbuv_s_c));
378 INSTANTIATE_TEST_CASE_P(SSE2, IntraPredUVTest,
380 vp8_build_intra_predictors_mbuv_s_sse2));
383 INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredUVTest,
385 vp8_build_intra_predictors_mbuv_s_ssse3));