]> granicus.if.org Git - libvpx/blob - test/vp9_error_block_test.cc
Merge "build/make/configure.sh: Fix armv7 builds in Xcode7."
[libvpx] / test / vp9_error_block_test.cc
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 <cmath>
12 #include <cstdlib>
13 #include <string>
14
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16
17 #include "./vpx_config.h"
18 #include "./vp9_rtcd.h"
19 #include "test/acm_random.h"
20 #include "test/clear_system_state.h"
21 #include "test/register_state_check.h"
22 #include "test/util.h"
23 #include "vp9/common/vp9_entropy.h"
24 #include "vpx/vpx_codec.h"
25 #include "vpx/vpx_integer.h"
26
27 using libvpx_test::ACMRandom;
28
29 namespace {
30 #if CONFIG_VP9_HIGHBITDEPTH
31 const int kNumIterations = 1000;
32
33 typedef int64_t (*ErrorBlockFunc)(const tran_low_t *coeff,
34                                   const tran_low_t *dqcoeff,
35                                   intptr_t block_size,
36                                   int64_t *ssz, int bps);
37
38 typedef std::tr1::tuple<ErrorBlockFunc, ErrorBlockFunc, vpx_bit_depth_t>
39                         ErrorBlockParam;
40
41 class ErrorBlockTest
42   : public ::testing::TestWithParam<ErrorBlockParam> {
43  public:
44   virtual ~ErrorBlockTest() {}
45   virtual void SetUp() {
46     error_block_op_     = GET_PARAM(0);
47     ref_error_block_op_ = GET_PARAM(1);
48     bit_depth_  = GET_PARAM(2);
49   }
50
51   virtual void TearDown() { libvpx_test::ClearSystemState(); }
52
53  protected:
54   vpx_bit_depth_t bit_depth_;
55   ErrorBlockFunc error_block_op_;
56   ErrorBlockFunc ref_error_block_op_;
57 };
58
59 TEST_P(ErrorBlockTest, OperationCheck) {
60   ACMRandom rnd(ACMRandom::DeterministicSeed());
61   DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
62   DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
63   int err_count_total = 0;
64   int first_failure = -1;
65   intptr_t block_size;
66   int64_t ssz;
67   int64_t ret;
68   int64_t ref_ssz;
69   int64_t ref_ret;
70   for (int i = 0; i < kNumIterations; ++i) {
71     int err_count = 0;
72     block_size = 16 << (i % 9);  // All block sizes from 4x4, 8x4 ..64x64
73     for (int j = 0; j < block_size; j++) {
74       coeff[j]   = rnd(2 << 20) - (1 << 20);
75       dqcoeff[j] = rnd(2 << 20) - (1 << 20);
76     }
77     ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz,
78                                   bit_depth_);
79     ASM_REGISTER_STATE_CHECK(ret = error_block_op_(coeff, dqcoeff, block_size,
80                                                    &ssz, bit_depth_));
81     err_count += (ref_ret != ret) | (ref_ssz != ssz);
82     if (err_count && !err_count_total) {
83       first_failure = i;
84     }
85     err_count_total += err_count;
86   }
87   EXPECT_EQ(0, err_count_total)
88       << "Error: Error Block Test, C output doesn't match SSE2 output. "
89       << "First failed at test case " << first_failure;
90 }
91
92 TEST_P(ErrorBlockTest, ExtremeValues) {
93   ACMRandom rnd(ACMRandom::DeterministicSeed());
94   DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
95   DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
96   int err_count_total = 0;
97   int first_failure = -1;
98   intptr_t block_size;
99   int64_t ssz;
100   int64_t ret;
101   int64_t ref_ssz;
102   int64_t ref_ret;
103   int max_val = ((1 << 20) - 1);
104   for (int i = 0; i < kNumIterations; ++i) {
105     int err_count = 0;
106     int k = (i / 9) % 5;
107
108     // Change the maximum coeff value, to test different bit boundaries
109     if ( k == 4 && (i % 9) == 0 ) {
110       max_val >>= 1;
111     }
112     block_size = 16 << (i % 9);  // All block sizes from 4x4, 8x4 ..64x64
113     for (int j = 0; j < block_size; j++) {
114       if (k < 4) {  // Test at maximum values
115         coeff[j]   = k % 2 ? max_val : -max_val;
116         dqcoeff[j] = (k >> 1) % 2 ? max_val : -max_val;
117       } else {
118         coeff[j]   = rnd(2 << 14) - (1 << 14);
119         dqcoeff[j] = rnd(2 << 14) - (1 << 14);
120       }
121     }
122     ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz,
123                                   bit_depth_);
124     ASM_REGISTER_STATE_CHECK(ret = error_block_op_(coeff, dqcoeff, block_size,
125                                                    &ssz, bit_depth_));
126     err_count += (ref_ret != ret) | (ref_ssz != ssz);
127     if (err_count && !err_count_total) {
128       first_failure = i;
129     }
130     err_count_total += err_count;
131   }
132   EXPECT_EQ(0, err_count_total)
133       << "Error: Error Block Test, C output doesn't match SSE2 output. "
134       << "First failed at test case " << first_failure;
135 }
136
137 using std::tr1::make_tuple;
138
139 #if HAVE_SSE2
140 INSTANTIATE_TEST_CASE_P(
141     SSE2, ErrorBlockTest,
142     ::testing::Values(
143         make_tuple(&vp9_highbd_block_error_sse2,
144                    &vp9_highbd_block_error_c, VPX_BITS_10),
145         make_tuple(&vp9_highbd_block_error_sse2,
146                    &vp9_highbd_block_error_c, VPX_BITS_12),
147         make_tuple(&vp9_highbd_block_error_sse2,
148                    &vp9_highbd_block_error_c, VPX_BITS_8)));
149 #endif  // HAVE_SSE2
150 #endif  // CONFIG_VP9_HIGHBITDEPTH
151 }  // namespace