2 * Copyright (c) 2014 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.
15 #include "third_party/googletest/src/include/gtest/gtest.h"
17 #include "test/acm_random.h"
18 #include "test/clear_system_state.h"
19 #include "test/register_state_check.h"
20 #include "test/util.h"
21 #include "./vpx_config.h"
22 #include "./vp9_rtcd.h"
23 #include "vp9/common/vp9_entropy.h"
24 #include "vpx/vpx_integer.h"
26 using libvpx_test::ACMRandom;
29 #if CONFIG_VP9_HIGHBITDEPTH
30 const int number_of_iterations = 100;
32 typedef void (*QuantizeFunc)(const tran_low_t *coeff, intptr_t count,
33 int skip_block, const int16_t *zbin,
34 const int16_t *round, const int16_t *quant,
35 const int16_t *quant_shift,
36 tran_low_t *qcoeff, tran_low_t *dqcoeff,
37 const int16_t *dequant,
38 uint16_t *eob, const int16_t *scan,
39 const int16_t *iscan);
40 typedef std::tr1::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t>
43 class VP9QuantizeTest : public ::testing::TestWithParam<QuantizeParam> {
45 virtual ~VP9QuantizeTest() {}
46 virtual void SetUp() {
47 quantize_op_ = GET_PARAM(0);
48 ref_quantize_op_ = GET_PARAM(1);
49 bit_depth_ = GET_PARAM(2);
50 mask_ = (1 << bit_depth_) - 1;
53 virtual void TearDown() { libvpx_test::ClearSystemState(); }
56 vpx_bit_depth_t bit_depth_;
58 QuantizeFunc quantize_op_;
59 QuantizeFunc ref_quantize_op_;
62 class VP9Quantize32Test : public ::testing::TestWithParam<QuantizeParam> {
64 virtual ~VP9Quantize32Test() {}
65 virtual void SetUp() {
66 quantize_op_ = GET_PARAM(0);
67 ref_quantize_op_ = GET_PARAM(1);
68 bit_depth_ = GET_PARAM(2);
69 mask_ = (1 << bit_depth_) - 1;
72 virtual void TearDown() { libvpx_test::ClearSystemState(); }
75 vpx_bit_depth_t bit_depth_;
77 QuantizeFunc quantize_op_;
78 QuantizeFunc ref_quantize_op_;
81 TEST_P(VP9QuantizeTest, OperationCheck) {
82 ACMRandom rnd(ACMRandom::DeterministicSeed());
83 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
84 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
85 DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
86 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
87 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
88 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
89 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
90 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
91 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
92 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
93 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
94 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
95 int err_count_total = 0;
96 int first_failure = -1;
97 for (int i = 0; i < number_of_iterations; ++i) {
98 const int skip_block = i == 0;
99 const TX_SIZE sz = (TX_SIZE)(i % 3); // TX_4X4, TX_8X8 TX_16X16
100 const TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
101 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
102 const int count = (4 << sz) * (4 << sz); // 16, 64, 256
104 *eob_ptr = rnd.Rand16();
105 *ref_eob_ptr = *eob_ptr;
106 for (int j = 0; j < count; j++) {
107 coeff_ptr[j] = rnd.Rand16()&mask_;
109 for (int j = 0; j < 2; j++) {
110 zbin_ptr[j] = rnd.Rand16()&mask_;
111 round_ptr[j] = rnd.Rand16();
112 quant_ptr[j] = rnd.Rand16();
113 quant_shift_ptr[j] = rnd.Rand16();
114 dequant_ptr[j] = rnd.Rand16();
116 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
117 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
118 ref_dqcoeff_ptr, dequant_ptr,
119 ref_eob_ptr, scan_order->scan, scan_order->iscan);
120 ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
121 zbin_ptr, round_ptr, quant_ptr,
122 quant_shift_ptr, qcoeff_ptr,
123 dqcoeff_ptr, dequant_ptr, eob_ptr,
124 scan_order->scan, scan_order->iscan));
125 for (int j = 0; j < sz; ++j) {
126 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
127 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
129 err_count += (*ref_eob_ptr != *eob_ptr);
130 if (err_count && !err_count_total) {
133 err_count_total += err_count;
135 EXPECT_EQ(0, err_count_total)
136 << "Error: Quantization Test, C output doesn't match SSE2 output. "
137 << "First failed at test case " << first_failure;
140 TEST_P(VP9Quantize32Test, OperationCheck) {
141 ACMRandom rnd(ACMRandom::DeterministicSeed());
142 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]);
143 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
144 DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
145 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
146 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
147 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]);
148 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]);
149 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]);
150 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]);
151 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
152 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
153 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
154 int err_count_total = 0;
155 int first_failure = -1;
156 for (int i = 0; i < number_of_iterations; ++i) {
157 const int skip_block = i == 0;
158 const TX_SIZE sz = TX_32X32;
159 const TX_TYPE tx_type = (TX_TYPE)(i % 4);
160 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
161 const int count = (4 << sz) * (4 << sz); // 1024
163 *eob_ptr = rnd.Rand16();
164 *ref_eob_ptr = *eob_ptr;
165 for (int j = 0; j < count; j++) {
166 coeff_ptr[j] = rnd.Rand16()&mask_;
168 for (int j = 0; j < 2; j++) {
169 zbin_ptr[j] = rnd.Rand16()&mask_;
170 round_ptr[j] = rnd.Rand16();
171 quant_ptr[j] = rnd.Rand16();
172 quant_shift_ptr[j] = rnd.Rand16();
173 dequant_ptr[j] = rnd.Rand16();
175 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
176 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
177 ref_dqcoeff_ptr, dequant_ptr,
178 ref_eob_ptr, scan_order->scan, scan_order->iscan);
179 ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
180 zbin_ptr, round_ptr, quant_ptr,
181 quant_shift_ptr, qcoeff_ptr,
182 dqcoeff_ptr, dequant_ptr, eob_ptr,
183 scan_order->scan, scan_order->iscan));
184 for (int j = 0; j < sz; ++j) {
185 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
186 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
188 err_count += (*ref_eob_ptr != *eob_ptr);
189 if (err_count && !err_count_total) {
192 err_count_total += err_count;
194 EXPECT_EQ(0, err_count_total)
195 << "Error: Quantization Test, C output doesn't match SSE2 output. "
196 << "First failed at test case " << first_failure;
199 TEST_P(VP9QuantizeTest, EOBCheck) {
200 ACMRandom rnd(ACMRandom::DeterministicSeed());
201 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
202 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
203 DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
204 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
205 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
206 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
207 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
208 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
209 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
210 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
211 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
212 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
213 int err_count_total = 0;
214 int first_failure = -1;
215 for (int i = 0; i < number_of_iterations; ++i) {
216 int skip_block = i == 0;
217 TX_SIZE sz = (TX_SIZE)(i % 3); // TX_4X4, TX_8X8 TX_16X16
218 TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
219 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
220 int count = (4 << sz) * (4 << sz); // 16, 64, 256
222 *eob_ptr = rnd.Rand16();
223 *ref_eob_ptr = *eob_ptr;
224 // Two random entries
225 for (int j = 0; j < count; j++) {
228 coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
229 coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
230 for (int j = 0; j < 2; j++) {
231 zbin_ptr[j] = rnd.Rand16()&mask_;
232 round_ptr[j] = rnd.Rand16();
233 quant_ptr[j] = rnd.Rand16();
234 quant_shift_ptr[j] = rnd.Rand16();
235 dequant_ptr[j] = rnd.Rand16();
238 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
239 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
240 ref_dqcoeff_ptr, dequant_ptr,
241 ref_eob_ptr, scan_order->scan, scan_order->iscan);
242 ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
243 zbin_ptr, round_ptr, quant_ptr,
244 quant_shift_ptr, qcoeff_ptr,
245 dqcoeff_ptr, dequant_ptr, eob_ptr,
246 scan_order->scan, scan_order->iscan));
248 for (int j = 0; j < sz; ++j) {
249 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
250 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
252 err_count += (*ref_eob_ptr != *eob_ptr);
253 if (err_count && !err_count_total) {
256 err_count_total += err_count;
258 EXPECT_EQ(0, err_count_total)
259 << "Error: Quantization Test, C output doesn't match SSE2 output. "
260 << "First failed at test case " << first_failure;
263 TEST_P(VP9Quantize32Test, EOBCheck) {
264 ACMRandom rnd(ACMRandom::DeterministicSeed());
265 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]);
266 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
267 DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
268 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
269 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
270 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]);
271 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]);
272 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]);
273 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]);
274 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
275 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
276 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
277 int err_count_total = 0;
278 int first_failure = -1;
279 for (int i = 0; i < number_of_iterations; ++i) {
280 int skip_block = i == 0;
281 TX_SIZE sz = TX_32X32;
282 TX_TYPE tx_type = (TX_TYPE)(i % 4);
283 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
284 int count = (4 << sz) * (4 << sz); // 1024
286 *eob_ptr = rnd.Rand16();
287 *ref_eob_ptr = *eob_ptr;
288 for (int j = 0; j < count; j++) {
291 // Two random entries
292 coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
293 coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
294 for (int j = 0; j < 2; j++) {
295 zbin_ptr[j] = rnd.Rand16()&mask_;
296 round_ptr[j] = rnd.Rand16();
297 quant_ptr[j] = rnd.Rand16();
298 quant_shift_ptr[j] = rnd.Rand16();
299 dequant_ptr[j] = rnd.Rand16();
302 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
303 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
304 ref_dqcoeff_ptr, dequant_ptr,
305 ref_eob_ptr, scan_order->scan, scan_order->iscan);
306 ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
307 zbin_ptr, round_ptr, quant_ptr,
308 quant_shift_ptr, qcoeff_ptr,
309 dqcoeff_ptr, dequant_ptr, eob_ptr,
310 scan_order->scan, scan_order->iscan));
312 for (int j = 0; j < sz; ++j) {
313 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
314 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
316 err_count += (*ref_eob_ptr != *eob_ptr);
317 if (err_count && !err_count_total) {
320 err_count_total += err_count;
322 EXPECT_EQ(0, err_count_total)
323 << "Error: Quantization Test, C output doesn't match SSE2 output. "
324 << "First failed at test case " << first_failure;
326 using std::tr1::make_tuple;
329 INSTANTIATE_TEST_CASE_P(
330 SSE2, VP9QuantizeTest,
332 make_tuple(&vp9_highbd_quantize_b_sse2,
333 &vp9_highbd_quantize_b_c, VPX_BITS_8),
334 make_tuple(&vp9_highbd_quantize_b_sse2,
335 &vp9_highbd_quantize_b_c, VPX_BITS_10),
336 make_tuple(&vp9_highbd_quantize_b_sse2,
337 &vp9_highbd_quantize_b_c, VPX_BITS_12)));
338 INSTANTIATE_TEST_CASE_P(
339 SSE2, VP9Quantize32Test,
341 make_tuple(&vp9_highbd_quantize_b_32x32_sse2,
342 &vp9_highbd_quantize_b_32x32_c, VPX_BITS_8),
343 make_tuple(&vp9_highbd_quantize_b_32x32_sse2,
344 &vp9_highbd_quantize_b_32x32_c, VPX_BITS_10),
345 make_tuple(&vp9_highbd_quantize_b_32x32_sse2,
346 &vp9_highbd_quantize_b_32x32_c, VPX_BITS_12)));
348 #endif // CONFIG_VP9_HIGHBITDEPTH