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 27using libvpx_test::ACMRandom; 28 29namespace { 30#if CONFIG_VP9_HIGHBITDEPTH 31const int kNumIterations = 1000; 32 33typedef 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 38typedef std::tr1::tuple<ErrorBlockFunc, ErrorBlockFunc, vpx_bit_depth_t> 39 ErrorBlockParam; 40 41class 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 59TEST_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 const int msb = bit_depth_ + 8 - 1; 71 for (int i = 0; i < kNumIterations; ++i) { 72 int err_count = 0; 73 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64 74 for (int j = 0; j < block_size; j++) { 75 // coeff and dqcoeff will always have at least the same sign, and this 76 // can be used for optimization, so generate test input precisely. 77 if (rnd(2)) { 78 // Positive number 79 coeff[j] = rnd(1 << msb); 80 dqcoeff[j] = rnd(1 << msb); 81 } else { 82 // Negative number 83 coeff[j] = -rnd(1 << msb); 84 dqcoeff[j] = -rnd(1 << msb); 85 } 86 } 87 ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, 88 bit_depth_); 89 ASM_REGISTER_STATE_CHECK(ret = error_block_op_(coeff, dqcoeff, block_size, 90 &ssz, bit_depth_)); 91 err_count += (ref_ret != ret) | (ref_ssz != ssz); 92 if (err_count && !err_count_total) { 93 first_failure = i; 94 } 95 err_count_total += err_count; 96 } 97 EXPECT_EQ(0, err_count_total) 98 << "Error: Error Block Test, C output doesn't match optimized output. " 99 << "First failed at test case " << first_failure; 100} 101 102TEST_P(ErrorBlockTest, ExtremeValues) { 103 ACMRandom rnd(ACMRandom::DeterministicSeed()); 104 DECLARE_ALIGNED(16, tran_low_t, coeff[4096]); 105 DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]); 106 int err_count_total = 0; 107 int first_failure = -1; 108 intptr_t block_size; 109 int64_t ssz; 110 int64_t ret; 111 int64_t ref_ssz; 112 int64_t ref_ret; 113 const int msb = bit_depth_ + 8 - 1; 114 int max_val = ((1 << msb) - 1); 115 for (int i = 0; i < kNumIterations; ++i) { 116 int err_count = 0; 117 int k = (i / 9) % 9; 118 119 // Change the maximum coeff value, to test different bit boundaries 120 if ( k == 8 && (i % 9) == 0 ) { 121 max_val >>= 1; 122 } 123 block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64 124 for (int j = 0; j < block_size; j++) { 125 if (k < 4) { 126 // Test at positive maximum values 127 coeff[j] = k % 2 ? max_val : 0; 128 dqcoeff[j] = (k >> 1) % 2 ? max_val : 0; 129 } else if (k < 8) { 130 // Test at negative maximum values 131 coeff[j] = k % 2 ? -max_val : 0; 132 dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0; 133 } else { 134 if (rnd(2)) { 135 // Positive number 136 coeff[j] = rnd(1 << 14); 137 dqcoeff[j] = rnd(1 << 14); 138 } else { 139 // Negative number 140 coeff[j] = -rnd(1 << 14); 141 dqcoeff[j] = -rnd(1 << 14); 142 } 143 } 144 } 145 ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, 146 bit_depth_); 147 ASM_REGISTER_STATE_CHECK(ret = error_block_op_(coeff, dqcoeff, block_size, 148 &ssz, bit_depth_)); 149 err_count += (ref_ret != ret) | (ref_ssz != ssz); 150 if (err_count && !err_count_total) { 151 first_failure = i; 152 } 153 err_count_total += err_count; 154 } 155 EXPECT_EQ(0, err_count_total) 156 << "Error: Error Block Test, C output doesn't match optimized output. " 157 << "First failed at test case " << first_failure; 158} 159 160using std::tr1::make_tuple; 161 162#if CONFIG_USE_X86INC 163int64_t wrap_vp9_highbd_block_error_8bit_c(const tran_low_t *coeff, 164 const tran_low_t *dqcoeff, 165 intptr_t block_size, 166 int64_t *ssz, int bps) { 167 assert(bps == 8); 168 return vp9_highbd_block_error_8bit_c(coeff, dqcoeff, block_size, ssz); 169} 170 171#if HAVE_SSE2 172int64_t wrap_vp9_highbd_block_error_8bit_sse2(const tran_low_t *coeff, 173 const tran_low_t *dqcoeff, 174 intptr_t block_size, 175 int64_t *ssz, int bps) { 176 assert(bps == 8); 177 return vp9_highbd_block_error_8bit_sse2(coeff, dqcoeff, block_size, ssz); 178} 179 180INSTANTIATE_TEST_CASE_P( 181 SSE2, ErrorBlockTest, 182 ::testing::Values( 183 make_tuple(&vp9_highbd_block_error_sse2, 184 &vp9_highbd_block_error_c, VPX_BITS_10), 185 make_tuple(&vp9_highbd_block_error_sse2, 186 &vp9_highbd_block_error_c, VPX_BITS_12), 187 make_tuple(&vp9_highbd_block_error_sse2, 188 &vp9_highbd_block_error_c, VPX_BITS_8), 189 make_tuple(&wrap_vp9_highbd_block_error_8bit_sse2, 190 &wrap_vp9_highbd_block_error_8bit_c, VPX_BITS_8))); 191#endif // HAVE_SSE2 192 193#if HAVE_AVX 194int64_t wrap_vp9_highbd_block_error_8bit_avx(const tran_low_t *coeff, 195 const tran_low_t *dqcoeff, 196 intptr_t block_size, 197 int64_t *ssz, int bps) { 198 assert(bps == 8); 199 return vp9_highbd_block_error_8bit_avx(coeff, dqcoeff, block_size, ssz); 200} 201 202INSTANTIATE_TEST_CASE_P( 203 AVX, ErrorBlockTest, 204 ::testing::Values( 205 make_tuple(&wrap_vp9_highbd_block_error_8bit_avx, 206 &wrap_vp9_highbd_block_error_8bit_c, VPX_BITS_8))); 207#endif // HAVE_AVX 208 209#endif // CONFIG_USE_X86INC 210#endif // CONFIG_VP9_HIGHBITDEPTH 211} // namespace 212