]> granicus.if.org Git - libvpx/blob - test/vp9_quantize_test.cc
Merge "third_party/libwebm: pull from upstream"
[libvpx] / test / vp9_quantize_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 <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16
17 #include "./vpx_config.h"
18 #include "./vpx_dsp_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 "vp9/common/vp9_scan.h"
25 #include "vpx/vpx_codec.h"
26 #include "vpx/vpx_integer.h"
27
28 using libvpx_test::ACMRandom;
29
30 namespace {
31 #if CONFIG_VP9_HIGHBITDEPTH
32 const int number_of_iterations = 100;
33
34 typedef void (*QuantizeFunc)(const tran_low_t *coeff, intptr_t count,
35                              int skip_block, const int16_t *zbin,
36                              const int16_t *round, const int16_t *quant,
37                              const int16_t *quant_shift,
38                              tran_low_t *qcoeff, tran_low_t *dqcoeff,
39                              const int16_t *dequant,
40                              uint16_t *eob, const int16_t *scan,
41                              const int16_t *iscan);
42 typedef std::tr1::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t>
43     QuantizeParam;
44
45 class VP9QuantizeTest : public ::testing::TestWithParam<QuantizeParam> {
46  public:
47   virtual ~VP9QuantizeTest() {}
48   virtual void SetUp() {
49     quantize_op_   = GET_PARAM(0);
50     ref_quantize_op_ = GET_PARAM(1);
51     bit_depth_  = GET_PARAM(2);
52     mask_ = (1 << bit_depth_) - 1;
53   }
54
55   virtual void TearDown() { libvpx_test::ClearSystemState(); }
56
57  protected:
58   vpx_bit_depth_t bit_depth_;
59   int mask_;
60   QuantizeFunc quantize_op_;
61   QuantizeFunc ref_quantize_op_;
62 };
63
64 class VP9Quantize32Test : public ::testing::TestWithParam<QuantizeParam> {
65  public:
66   virtual ~VP9Quantize32Test() {}
67   virtual void SetUp() {
68     quantize_op_   = GET_PARAM(0);
69     ref_quantize_op_ = GET_PARAM(1);
70     bit_depth_  = GET_PARAM(2);
71     mask_ = (1 << bit_depth_) - 1;
72   }
73
74   virtual void TearDown() { libvpx_test::ClearSystemState(); }
75
76  protected:
77   vpx_bit_depth_t bit_depth_;
78   int mask_;
79   QuantizeFunc quantize_op_;
80   QuantizeFunc ref_quantize_op_;
81 };
82
83 TEST_P(VP9QuantizeTest, OperationCheck) {
84   ACMRandom rnd(ACMRandom::DeterministicSeed());
85   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
86   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
87   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
88   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
89   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
90   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
91   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
92   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
93   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
94   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
95   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
96   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
97   int err_count_total = 0;
98   int first_failure = -1;
99   for (int i = 0; i < number_of_iterations; ++i) {
100     const int skip_block = i == 0;
101     const TX_SIZE sz = (TX_SIZE)(i % 3);  // TX_4X4, TX_8X8 TX_16X16
102     const TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
103     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
104     const int count = (4 << sz) * (4 << sz);  // 16, 64, 256
105     int err_count = 0;
106     *eob_ptr = rnd.Rand16();
107     *ref_eob_ptr = *eob_ptr;
108     for (int j = 0; j < count; j++) {
109       coeff_ptr[j] = rnd.Rand16()&mask_;
110     }
111     for (int j = 0; j < 2; j++) {
112       zbin_ptr[j] = rnd.Rand16()&mask_;
113       round_ptr[j] = rnd.Rand16();
114       quant_ptr[j] = rnd.Rand16();
115       quant_shift_ptr[j] = rnd.Rand16();
116       dequant_ptr[j] = rnd.Rand16();
117     }
118     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
119                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
120                      ref_dqcoeff_ptr, dequant_ptr,
121                      ref_eob_ptr, scan_order->scan, scan_order->iscan);
122     ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
123                                           zbin_ptr, round_ptr, quant_ptr,
124                                           quant_shift_ptr, qcoeff_ptr,
125                                           dqcoeff_ptr, dequant_ptr, eob_ptr,
126                                           scan_order->scan, scan_order->iscan));
127     for (int j = 0; j < sz; ++j) {
128       err_count += (ref_qcoeff_ptr[j]  != qcoeff_ptr[j]) |
129           (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
130     }
131     err_count += (*ref_eob_ptr != *eob_ptr);
132     if (err_count && !err_count_total) {
133       first_failure = i;
134     }
135     err_count_total += err_count;
136   }
137   EXPECT_EQ(0, err_count_total)
138       << "Error: Quantization Test, C output doesn't match SSE2 output. "
139       << "First failed at test case " << first_failure;
140 }
141
142 TEST_P(VP9Quantize32Test, OperationCheck) {
143   ACMRandom rnd(ACMRandom::DeterministicSeed());
144   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]);
145   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
146   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
147   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
148   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
149   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]);
150   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]);
151   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]);
152   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]);
153   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
154   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
155   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
156   int err_count_total = 0;
157   int first_failure = -1;
158   for (int i = 0; i < number_of_iterations; ++i) {
159     const int skip_block = i == 0;
160     const TX_SIZE sz = TX_32X32;
161     const TX_TYPE tx_type = (TX_TYPE)(i % 4);
162     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
163     const int count = (4 << sz) * (4 << sz);  // 1024
164     int err_count = 0;
165     *eob_ptr = rnd.Rand16();
166     *ref_eob_ptr = *eob_ptr;
167     for (int j = 0; j < count; j++) {
168       coeff_ptr[j] = rnd.Rand16()&mask_;
169     }
170     for (int j = 0; j < 2; j++) {
171       zbin_ptr[j] = rnd.Rand16()&mask_;
172       round_ptr[j] = rnd.Rand16();
173       quant_ptr[j] = rnd.Rand16();
174       quant_shift_ptr[j] = rnd.Rand16();
175       dequant_ptr[j] = rnd.Rand16();
176     }
177     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
178                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
179                      ref_dqcoeff_ptr, dequant_ptr,
180                      ref_eob_ptr, scan_order->scan, scan_order->iscan);
181     ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
182                                           zbin_ptr, round_ptr, quant_ptr,
183                                           quant_shift_ptr, qcoeff_ptr,
184                                           dqcoeff_ptr, dequant_ptr, eob_ptr,
185                                           scan_order->scan, scan_order->iscan));
186     for (int j = 0; j < sz; ++j) {
187       err_count += (ref_qcoeff_ptr[j]  != qcoeff_ptr[j]) |
188           (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
189     }
190     err_count += (*ref_eob_ptr != *eob_ptr);
191     if (err_count && !err_count_total) {
192       first_failure = i;
193     }
194     err_count_total += err_count;
195   }
196   EXPECT_EQ(0, err_count_total)
197       << "Error: Quantization Test, C output doesn't match SSE2 output. "
198       << "First failed at test case " << first_failure;
199 }
200
201 TEST_P(VP9QuantizeTest, EOBCheck) {
202   ACMRandom rnd(ACMRandom::DeterministicSeed());
203   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
204   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
205   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
206   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
207   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
208   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
209   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
210   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
211   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
212   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
213   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
214   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
215   int err_count_total = 0;
216   int first_failure = -1;
217   for (int i = 0; i < number_of_iterations; ++i) {
218     int skip_block = i == 0;
219     TX_SIZE sz = (TX_SIZE)(i % 3);  // TX_4X4, TX_8X8 TX_16X16
220     TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
221     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
222     int count = (4 << sz) * (4 << sz);  // 16, 64, 256
223     int err_count = 0;
224     *eob_ptr = rnd.Rand16();
225     *ref_eob_ptr = *eob_ptr;
226     // Two random entries
227     for (int j = 0; j < count; j++) {
228       coeff_ptr[j] = 0;
229     }
230     coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
231     coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
232     for (int j = 0; j < 2; j++) {
233       zbin_ptr[j] = rnd.Rand16()&mask_;
234       round_ptr[j] = rnd.Rand16();
235       quant_ptr[j] = rnd.Rand16();
236       quant_shift_ptr[j] = rnd.Rand16();
237       dequant_ptr[j] = rnd.Rand16();
238     }
239
240     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
241                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
242                      ref_dqcoeff_ptr, dequant_ptr,
243                      ref_eob_ptr, scan_order->scan, scan_order->iscan);
244     ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
245                                           zbin_ptr, round_ptr, quant_ptr,
246                                           quant_shift_ptr, qcoeff_ptr,
247                                           dqcoeff_ptr, dequant_ptr, eob_ptr,
248                                           scan_order->scan, scan_order->iscan));
249
250     for (int j = 0; j < sz; ++j) {
251       err_count += (ref_qcoeff_ptr[j]  != qcoeff_ptr[j]) |
252           (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
253     }
254     err_count += (*ref_eob_ptr != *eob_ptr);
255     if (err_count && !err_count_total) {
256       first_failure = i;
257     }
258     err_count_total += err_count;
259   }
260   EXPECT_EQ(0, err_count_total)
261       << "Error: Quantization Test, C output doesn't match SSE2 output. "
262       << "First failed at test case " << first_failure;
263 }
264
265 TEST_P(VP9Quantize32Test, EOBCheck) {
266   ACMRandom rnd(ACMRandom::DeterministicSeed());
267   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]);
268   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
269   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
270   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
271   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
272   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]);
273   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]);
274   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]);
275   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]);
276   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
277   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
278   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
279   int err_count_total = 0;
280   int first_failure = -1;
281   for (int i = 0; i < number_of_iterations; ++i) {
282     int skip_block = i == 0;
283     TX_SIZE sz = TX_32X32;
284     TX_TYPE tx_type = (TX_TYPE)(i % 4);
285     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
286     int count = (4 << sz) * (4 << sz);  // 1024
287     int err_count = 0;
288     *eob_ptr = rnd.Rand16();
289     *ref_eob_ptr = *eob_ptr;
290     for (int j = 0; j < count; j++) {
291       coeff_ptr[j] = 0;
292     }
293     // Two random entries
294     coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
295     coeff_ptr[rnd(count)] = rnd.Rand16()&mask_;
296     for (int j = 0; j < 2; j++) {
297       zbin_ptr[j] = rnd.Rand16()&mask_;
298       round_ptr[j] = rnd.Rand16();
299       quant_ptr[j] = rnd.Rand16();
300       quant_shift_ptr[j] = rnd.Rand16();
301       dequant_ptr[j] = rnd.Rand16();
302     }
303
304     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
305                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
306                      ref_dqcoeff_ptr, dequant_ptr,
307                      ref_eob_ptr, scan_order->scan, scan_order->iscan);
308     ASM_REGISTER_STATE_CHECK(quantize_op_(coeff_ptr, count, skip_block,
309                                           zbin_ptr, round_ptr, quant_ptr,
310                                           quant_shift_ptr, qcoeff_ptr,
311                                           dqcoeff_ptr, dequant_ptr, eob_ptr,
312                                           scan_order->scan, scan_order->iscan));
313
314     for (int j = 0; j < sz; ++j) {
315       err_count += (ref_qcoeff_ptr[j]  != qcoeff_ptr[j]) |
316           (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
317     }
318     err_count += (*ref_eob_ptr != *eob_ptr);
319     if (err_count && !err_count_total) {
320       first_failure = i;
321     }
322     err_count_total += err_count;
323   }
324   EXPECT_EQ(0, err_count_total)
325       << "Error: Quantization Test, C output doesn't match SSE2 output. "
326       << "First failed at test case " << first_failure;
327 }
328 using std::tr1::make_tuple;
329
330 #if HAVE_SSE2
331 INSTANTIATE_TEST_CASE_P(
332     SSE2, VP9QuantizeTest,
333     ::testing::Values(
334         make_tuple(&vpx_highbd_quantize_b_sse2,
335                    &vpx_highbd_quantize_b_c, VPX_BITS_8),
336         make_tuple(&vpx_highbd_quantize_b_sse2,
337                    &vpx_highbd_quantize_b_c, VPX_BITS_10),
338         make_tuple(&vpx_highbd_quantize_b_sse2,
339                    &vpx_highbd_quantize_b_c, VPX_BITS_12)));
340 INSTANTIATE_TEST_CASE_P(
341     SSE2, VP9Quantize32Test,
342     ::testing::Values(
343         make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
344                    &vpx_highbd_quantize_b_32x32_c, VPX_BITS_8),
345         make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
346                    &vpx_highbd_quantize_b_32x32_c, VPX_BITS_10),
347         make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
348                    &vpx_highbd_quantize_b_32x32_c, VPX_BITS_12)));
349 #endif  // HAVE_SSE2
350 #endif  // CONFIG_VP9_HIGHBITDEPTH
351 }  // namespace