]> granicus.if.org Git - libvpx/blob - test/vp9_quantize_test.cc
Merge "Removal of legacy zbin_extra / zbin_oq_value."
[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 "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"
25
26 using libvpx_test::ACMRandom;
27
28 namespace {
29 #if CONFIG_VP9_HIGHBITDEPTH
30 const int number_of_iterations = 100;
31
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>
41     QuantizeParam;
42
43 class VP9QuantizeTest : public ::testing::TestWithParam<QuantizeParam> {
44  public:
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;
51   }
52
53   virtual void TearDown() { libvpx_test::ClearSystemState(); }
54
55  protected:
56   vpx_bit_depth_t bit_depth_;
57   int mask_;
58   QuantizeFunc quantize_op_;
59   QuantizeFunc ref_quantize_op_;
60 };
61
62 class VP9Quantize32Test : public ::testing::TestWithParam<QuantizeParam> {
63  public:
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;
70   }
71
72   virtual void TearDown() { libvpx_test::ClearSystemState(); }
73
74  protected:
75   vpx_bit_depth_t bit_depth_;
76   int mask_;
77   QuantizeFunc quantize_op_;
78   QuantizeFunc ref_quantize_op_;
79 };
80
81 TEST_P(VP9QuantizeTest, OperationCheck) {
82   ACMRandom rnd(ACMRandom::DeterministicSeed());
83   DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff_ptr, 256);
84   DECLARE_ALIGNED_ARRAY(16, int16_t, zbin_ptr, 2);
85   DECLARE_ALIGNED_ARRAY(16, int16_t, round_ptr, 2);
86   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_ptr, 2);
87   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_shift_ptr, 2);
88   DECLARE_ALIGNED_ARRAY(16, tran_low_t, qcoeff_ptr, 256);
89   DECLARE_ALIGNED_ARRAY(16, tran_low_t, dqcoeff_ptr, 256);
90   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_qcoeff_ptr, 256);
91   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_dqcoeff_ptr, 256);
92   DECLARE_ALIGNED_ARRAY(16, int16_t, dequant_ptr, 2);
93   DECLARE_ALIGNED_ARRAY(16, uint16_t, eob_ptr, 1);
94   DECLARE_ALIGNED_ARRAY(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
103     int err_count = 0;
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_;
108     }
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();
115     }
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]);
128     }
129     err_count += (*ref_eob_ptr != *eob_ptr);
130     if (err_count && !err_count_total) {
131       first_failure = i;
132     }
133     err_count_total += err_count;
134   }
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;
138 }
139
140 TEST_P(VP9Quantize32Test, OperationCheck) {
141   ACMRandom rnd(ACMRandom::DeterministicSeed());
142   DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff_ptr, 1024);
143   DECLARE_ALIGNED_ARRAY(16, int16_t, zbin_ptr, 2);
144   DECLARE_ALIGNED_ARRAY(16, int16_t, round_ptr, 2);
145   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_ptr, 2);
146   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_shift_ptr, 2);
147   DECLARE_ALIGNED_ARRAY(16, tran_low_t, qcoeff_ptr, 1024);
148   DECLARE_ALIGNED_ARRAY(16, tran_low_t, dqcoeff_ptr, 1024);
149   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_qcoeff_ptr, 1024);
150   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_dqcoeff_ptr, 1024);
151   DECLARE_ALIGNED_ARRAY(16, int16_t, dequant_ptr, 2);
152   DECLARE_ALIGNED_ARRAY(16, uint16_t, eob_ptr, 1);
153   DECLARE_ALIGNED_ARRAY(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
162     int err_count = 0;
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_;
167     }
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();
174     }
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]);
187     }
188     err_count += (*ref_eob_ptr != *eob_ptr);
189     if (err_count && !err_count_total) {
190       first_failure = i;
191     }
192     err_count_total += err_count;
193   }
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;
197 }
198
199 TEST_P(VP9QuantizeTest, EOBCheck) {
200   ACMRandom rnd(ACMRandom::DeterministicSeed());
201   DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff_ptr, 256);
202   DECLARE_ALIGNED_ARRAY(16, int16_t, zbin_ptr, 2);
203   DECLARE_ALIGNED_ARRAY(16, int16_t, round_ptr, 2);
204   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_ptr, 2);
205   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_shift_ptr, 2);
206   DECLARE_ALIGNED_ARRAY(16, tran_low_t, qcoeff_ptr, 256);
207   DECLARE_ALIGNED_ARRAY(16, tran_low_t, dqcoeff_ptr, 256);
208   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_qcoeff_ptr, 256);
209   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_dqcoeff_ptr, 256);
210   DECLARE_ALIGNED_ARRAY(16, int16_t, dequant_ptr, 2);
211   DECLARE_ALIGNED_ARRAY(16, uint16_t, eob_ptr, 1);
212   DECLARE_ALIGNED_ARRAY(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
221     int err_count = 0;
222     *eob_ptr = rnd.Rand16();
223     *ref_eob_ptr = *eob_ptr;
224     // Two random entries
225     for (int j = 0; j < count; j++) {
226       coeff_ptr[j] = 0;
227     }
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();
236     }
237
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));
247
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]);
251     }
252     err_count += (*ref_eob_ptr != *eob_ptr);
253     if (err_count && !err_count_total) {
254       first_failure = i;
255     }
256     err_count_total += err_count;
257   }
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;
261 }
262
263 TEST_P(VP9Quantize32Test, EOBCheck) {
264   ACMRandom rnd(ACMRandom::DeterministicSeed());
265   DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff_ptr, 1024);
266   DECLARE_ALIGNED_ARRAY(16, int16_t, zbin_ptr, 2);
267   DECLARE_ALIGNED_ARRAY(16, int16_t, round_ptr, 2);
268   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_ptr, 2);
269   DECLARE_ALIGNED_ARRAY(16, int16_t, quant_shift_ptr, 2);
270   DECLARE_ALIGNED_ARRAY(16, tran_low_t, qcoeff_ptr, 1024);
271   DECLARE_ALIGNED_ARRAY(16, tran_low_t, dqcoeff_ptr, 1024);
272   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_qcoeff_ptr, 1024);
273   DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_dqcoeff_ptr, 1024);
274   DECLARE_ALIGNED_ARRAY(16, int16_t, dequant_ptr, 2);
275   DECLARE_ALIGNED_ARRAY(16, uint16_t, eob_ptr, 1);
276   DECLARE_ALIGNED_ARRAY(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
285     int err_count = 0;
286     *eob_ptr = rnd.Rand16();
287     *ref_eob_ptr = *eob_ptr;
288     for (int j = 0; j < count; j++) {
289       coeff_ptr[j] = 0;
290     }
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();
300     }
301
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));
311
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]);
315     }
316     err_count += (*ref_eob_ptr != *eob_ptr);
317     if (err_count && !err_count_total) {
318       first_failure = i;
319     }
320     err_count_total += err_count;
321   }
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;
325 }
326 using std::tr1::make_tuple;
327
328 #if HAVE_SSE2
329 INSTANTIATE_TEST_CASE_P(
330     SSE2, VP9QuantizeTest,
331     ::testing::Values(
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,
340     ::testing::Values(
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)));
347 #endif  // HAVE_SSE2
348 #endif  // CONFIG_VP9_HIGHBITDEPTH
349 }  // namespace