OLD | NEW |
(Empty) | |
| 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 #include <math.h> |
| 12 #include <stdlib.h> |
| 13 #include <string.h> |
| 14 |
| 15 #include "third_party/googletest/src/include/gtest/gtest.h" |
| 16 |
| 17 extern "C" { |
| 18 #include "vp9_rtcd.h" |
| 19 } |
| 20 |
| 21 #include "acm_random.h" |
| 22 #include "vpx/vpx_integer.h" |
| 23 |
| 24 using libvpx_test::ACMRandom; |
| 25 |
| 26 namespace { |
| 27 |
| 28 TEST(VP9Fdct8x8Test, SignBiasCheck) { |
| 29 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 30 int16_t test_input_block[64]; |
| 31 int16_t test_output_block[64]; |
| 32 const int pitch = 16; |
| 33 int count_sign_block[64][2]; |
| 34 const int count_test_block = 100000; |
| 35 |
| 36 memset(count_sign_block, 0, sizeof(count_sign_block)); |
| 37 |
| 38 for (int i = 0; i < count_test_block; ++i) { |
| 39 // Initialize a test block with input range [-255, 255]. |
| 40 for (int j = 0; j < 64; ++j) |
| 41 test_input_block[j] = rnd.Rand8() - rnd.Rand8(); |
| 42 |
| 43 vp9_short_fdct8x8_c(test_input_block, test_output_block, pitch); |
| 44 |
| 45 for (int j = 0; j < 64; ++j) { |
| 46 if (test_output_block[j] < 0) |
| 47 ++count_sign_block[j][0]; |
| 48 else if (test_output_block[j] > 0) |
| 49 ++count_sign_block[j][1]; |
| 50 } |
| 51 } |
| 52 |
| 53 for (int j = 0; j < 64; ++j) { |
| 54 const bool bias_acceptable = (abs(count_sign_block[j][0] - |
| 55 count_sign_block[j][1]) < 1000); |
| 56 EXPECT_TRUE(bias_acceptable) |
| 57 << "Error: 8x8 FDCT has a sign bias > 1%" |
| 58 << " for input range [-255, 255] at index " << j; |
| 59 } |
| 60 |
| 61 memset(count_sign_block, 0, sizeof(count_sign_block)); |
| 62 |
| 63 for (int i = 0; i < count_test_block; ++i) { |
| 64 // Initialize a test block with input range [-15, 15]. |
| 65 for (int j = 0; j < 64; ++j) |
| 66 test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4); |
| 67 |
| 68 vp9_short_fdct8x8_c(test_input_block, test_output_block, pitch); |
| 69 |
| 70 for (int j = 0; j < 64; ++j) { |
| 71 if (test_output_block[j] < 0) |
| 72 ++count_sign_block[j][0]; |
| 73 else if (test_output_block[j] > 0) |
| 74 ++count_sign_block[j][1]; |
| 75 } |
| 76 } |
| 77 |
| 78 for (int j = 0; j < 64; ++j) { |
| 79 const bool bias_acceptable = (abs(count_sign_block[j][0] - |
| 80 count_sign_block[j][1]) < 10000); |
| 81 EXPECT_TRUE(bias_acceptable) |
| 82 << "Error: 8x8 FDCT has a sign bias > 10%" |
| 83 << " for input range [-15, 15] at index " << j; |
| 84 } |
| 85 }; |
| 86 |
| 87 TEST(VP9Fdct8x8Test, RoundTripErrorCheck) { |
| 88 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 89 int max_error = 0; |
| 90 double total_error = 0; |
| 91 const int count_test_block = 100000; |
| 92 for (int i = 0; i < count_test_block; ++i) { |
| 93 int16_t test_input_block[64]; |
| 94 int16_t test_temp_block[64]; |
| 95 int16_t test_output_block[64]; |
| 96 |
| 97 // Initialize a test block with input range [-255, 255]. |
| 98 for (int j = 0; j < 64; ++j) |
| 99 test_input_block[j] = rnd.Rand8() - rnd.Rand8(); |
| 100 |
| 101 const int pitch = 16; |
| 102 vp9_short_fdct8x8_c(test_input_block, test_temp_block, pitch); |
| 103 for (int j = 0; j < 64; ++j){ |
| 104 if(test_temp_block[j] > 0) { |
| 105 test_temp_block[j] += 2; |
| 106 test_temp_block[j] /= 4; |
| 107 test_temp_block[j] *= 4; |
| 108 } else { |
| 109 test_temp_block[j] -= 2; |
| 110 test_temp_block[j] /= 4; |
| 111 test_temp_block[j] *= 4; |
| 112 } |
| 113 } |
| 114 vp9_short_idct8x8_c(test_temp_block, test_output_block, pitch); |
| 115 |
| 116 for (int j = 0; j < 64; ++j) { |
| 117 const int diff = test_input_block[j] - test_output_block[j]; |
| 118 const int error = diff * diff; |
| 119 if (max_error < error) |
| 120 max_error = error; |
| 121 total_error += error; |
| 122 } |
| 123 } |
| 124 |
| 125 EXPECT_GE(1, max_error) |
| 126 << "Error: 8x8 FDCT/IDCT has an individual roundtrip error > 1"; |
| 127 |
| 128 EXPECT_GE(count_test_block/5, total_error) |
| 129 << "Error: 8x8 FDCT/IDCT has average roundtrip error > 1/5 per block"; |
| 130 }; |
| 131 |
| 132 TEST(VP9Fdct8x8Test, ExtremalCheck) { |
| 133 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 134 int max_error = 0; |
| 135 double total_error = 0; |
| 136 const int count_test_block = 100000; |
| 137 for (int i = 0; i < count_test_block; ++i) { |
| 138 int16_t test_input_block[64]; |
| 139 int16_t test_temp_block[64]; |
| 140 int16_t test_output_block[64]; |
| 141 |
| 142 // Initialize a test block with input range {-255, 255}. |
| 143 for (int j = 0; j < 64; ++j) |
| 144 test_input_block[j] = rnd.Rand8() % 2 ? 255 : -255; |
| 145 |
| 146 const int pitch = 16; |
| 147 vp9_short_fdct8x8_c(test_input_block, test_temp_block, pitch); |
| 148 vp9_short_idct8x8_c(test_temp_block, test_output_block, pitch); |
| 149 |
| 150 for (int j = 0; j < 64; ++j) { |
| 151 const int diff = test_input_block[j] - test_output_block[j]; |
| 152 const int error = diff * diff; |
| 153 if (max_error < error) |
| 154 max_error = error; |
| 155 total_error += error; |
| 156 } |
| 157 |
| 158 EXPECT_GE(1, max_error) |
| 159 << "Error: Extremal 8x8 FDCT/IDCT has an" |
| 160 << " individual roundtrip error > 1"; |
| 161 |
| 162 EXPECT_GE(count_test_block/5, total_error) |
| 163 << "Error: Extremal 8x8 FDCT/IDCT has average" |
| 164 << " roundtrip error > 1/5 per block"; |
| 165 } |
| 166 }; |
| 167 |
| 168 } // namespace |
OLD | NEW |