• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, tran_low_t *qcoeff,
38                              tran_low_t *dqcoeff, const int16_t *dequant,
39                              uint16_t *eob, const int16_t *scan,
40                              const int16_t *iscan);
41 typedef std::tr1::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t>
42     QuantizeParam;
43 
44 class VP9QuantizeTest : public ::testing::TestWithParam<QuantizeParam> {
45  public:
~VP9QuantizeTest()46   virtual ~VP9QuantizeTest() {}
SetUp()47   virtual void SetUp() {
48     quantize_op_ = GET_PARAM(0);
49     ref_quantize_op_ = GET_PARAM(1);
50     bit_depth_ = GET_PARAM(2);
51     mask_ = (1 << bit_depth_) - 1;
52   }
53 
TearDown()54   virtual void TearDown() { libvpx_test::ClearSystemState(); }
55 
56  protected:
57   vpx_bit_depth_t bit_depth_;
58   int mask_;
59   QuantizeFunc quantize_op_;
60   QuantizeFunc ref_quantize_op_;
61 };
62 
63 class VP9Quantize32Test : public ::testing::TestWithParam<QuantizeParam> {
64  public:
~VP9Quantize32Test()65   virtual ~VP9Quantize32Test() {}
SetUp()66   virtual void SetUp() {
67     quantize_op_ = GET_PARAM(0);
68     ref_quantize_op_ = GET_PARAM(1);
69     bit_depth_ = GET_PARAM(2);
70     mask_ = (1 << bit_depth_) - 1;
71   }
72 
TearDown()73   virtual void TearDown() { libvpx_test::ClearSystemState(); }
74 
75  protected:
76   vpx_bit_depth_t bit_depth_;
77   int mask_;
78   QuantizeFunc quantize_op_;
79   QuantizeFunc ref_quantize_op_;
80 };
81 
TEST_P(VP9QuantizeTest,OperationCheck)82 TEST_P(VP9QuantizeTest, OperationCheck) {
83   ACMRandom rnd(ACMRandom::DeterministicSeed());
84   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
85   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
86   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
87   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
88   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
89   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
90   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
91   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
92   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
93   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
94   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
95   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
96   int err_count_total = 0;
97   int first_failure = -1;
98   for (int i = 0; i < number_of_iterations; ++i) {
99     const int skip_block = i == 0;
100     const TX_SIZE sz = (TX_SIZE)(i % 3);  // TX_4X4, TX_8X8 TX_16X16
101     const TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
102     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
103     const int count = (4 << sz) * (4 << sz);  // 16, 64, 256
104     int err_count = 0;
105     *eob_ptr = rnd.Rand16();
106     *ref_eob_ptr = *eob_ptr;
107     for (int j = 0; j < count; j++) {
108       coeff_ptr[j] = rnd.Rand16() & mask_;
109     }
110     for (int j = 0; j < 2; j++) {
111       zbin_ptr[j] = rnd.Rand16() & mask_;
112       round_ptr[j] = rnd.Rand16();
113       quant_ptr[j] = rnd.Rand16();
114       quant_shift_ptr[j] = rnd.Rand16();
115       dequant_ptr[j] = rnd.Rand16();
116     }
117     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
118                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
119                      ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr,
120                      scan_order->scan, scan_order->iscan);
121     ASM_REGISTER_STATE_CHECK(quantize_op_(
122         coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
123         quant_shift_ptr, qcoeff_ptr, 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 
TEST_P(VP9Quantize32Test,OperationCheck)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
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, ref_eob_ptr,
178                      scan_order->scan, scan_order->iscan);
179     ASM_REGISTER_STATE_CHECK(quantize_op_(
180         coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
181         quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr,
182         scan_order->scan, scan_order->iscan));
183     for (int j = 0; j < sz; ++j) {
184       err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
185                    (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
186     }
187     err_count += (*ref_eob_ptr != *eob_ptr);
188     if (err_count && !err_count_total) {
189       first_failure = i;
190     }
191     err_count_total += err_count;
192   }
193   EXPECT_EQ(0, err_count_total)
194       << "Error: Quantization Test, C output doesn't match SSE2 output. "
195       << "First failed at test case " << first_failure;
196 }
197 
TEST_P(VP9QuantizeTest,EOBCheck)198 TEST_P(VP9QuantizeTest, EOBCheck) {
199   ACMRandom rnd(ACMRandom::DeterministicSeed());
200   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]);
201   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
202   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
203   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
204   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
205   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]);
206   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]);
207   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]);
208   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]);
209   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
210   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
211   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
212   int err_count_total = 0;
213   int first_failure = -1;
214   for (int i = 0; i < number_of_iterations; ++i) {
215     int skip_block = i == 0;
216     TX_SIZE sz = (TX_SIZE)(i % 3);  // TX_4X4, TX_8X8 TX_16X16
217     TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3);
218     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
219     int count = (4 << sz) * (4 << sz);  // 16, 64, 256
220     int err_count = 0;
221     *eob_ptr = rnd.Rand16();
222     *ref_eob_ptr = *eob_ptr;
223     // Two random entries
224     for (int j = 0; j < count; j++) {
225       coeff_ptr[j] = 0;
226     }
227     coeff_ptr[rnd(count)] = rnd.Rand16() & mask_;
228     coeff_ptr[rnd(count)] = rnd.Rand16() & mask_;
229     for (int j = 0; j < 2; j++) {
230       zbin_ptr[j] = rnd.Rand16() & mask_;
231       round_ptr[j] = rnd.Rand16();
232       quant_ptr[j] = rnd.Rand16();
233       quant_shift_ptr[j] = rnd.Rand16();
234       dequant_ptr[j] = rnd.Rand16();
235     }
236 
237     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
238                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
239                      ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr,
240                      scan_order->scan, scan_order->iscan);
241     ASM_REGISTER_STATE_CHECK(quantize_op_(
242         coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
243         quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr,
244         scan_order->scan, scan_order->iscan));
245 
246     for (int j = 0; j < sz; ++j) {
247       err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
248                    (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
249     }
250     err_count += (*ref_eob_ptr != *eob_ptr);
251     if (err_count && !err_count_total) {
252       first_failure = i;
253     }
254     err_count_total += err_count;
255   }
256   EXPECT_EQ(0, err_count_total)
257       << "Error: Quantization Test, C output doesn't match SSE2 output. "
258       << "First failed at test case " << first_failure;
259 }
260 
TEST_P(VP9Quantize32Test,EOBCheck)261 TEST_P(VP9Quantize32Test, EOBCheck) {
262   ACMRandom rnd(ACMRandom::DeterministicSeed());
263   DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]);
264   DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
265   DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
266   DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
267   DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
268   DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]);
269   DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]);
270   DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]);
271   DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]);
272   DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
273   DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]);
274   DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]);
275   int err_count_total = 0;
276   int first_failure = -1;
277   for (int i = 0; i < number_of_iterations; ++i) {
278     int skip_block = i == 0;
279     TX_SIZE sz = TX_32X32;
280     TX_TYPE tx_type = (TX_TYPE)(i % 4);
281     const scan_order *scan_order = &vp9_scan_orders[sz][tx_type];
282     int count = (4 << sz) * (4 << sz);  // 1024
283     int err_count = 0;
284     *eob_ptr = rnd.Rand16();
285     *ref_eob_ptr = *eob_ptr;
286     for (int j = 0; j < count; j++) {
287       coeff_ptr[j] = 0;
288     }
289     // Two random entries
290     coeff_ptr[rnd(count)] = rnd.Rand16() & mask_;
291     coeff_ptr[rnd(count)] = rnd.Rand16() & mask_;
292     for (int j = 0; j < 2; j++) {
293       zbin_ptr[j] = rnd.Rand16() & mask_;
294       round_ptr[j] = rnd.Rand16();
295       quant_ptr[j] = rnd.Rand16();
296       quant_shift_ptr[j] = rnd.Rand16();
297       dequant_ptr[j] = rnd.Rand16();
298     }
299 
300     ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr,
301                      quant_ptr, quant_shift_ptr, ref_qcoeff_ptr,
302                      ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr,
303                      scan_order->scan, scan_order->iscan);
304     ASM_REGISTER_STATE_CHECK(quantize_op_(
305         coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
306         quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr,
307         scan_order->scan, scan_order->iscan));
308 
309     for (int j = 0; j < sz; ++j) {
310       err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
311                    (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
312     }
313     err_count += (*ref_eob_ptr != *eob_ptr);
314     if (err_count && !err_count_total) {
315       first_failure = i;
316     }
317     err_count_total += err_count;
318   }
319   EXPECT_EQ(0, err_count_total)
320       << "Error: Quantization Test, C output doesn't match SSE2 output. "
321       << "First failed at test case " << first_failure;
322 }
323 using std::tr1::make_tuple;
324 
325 #if HAVE_SSE2
326 INSTANTIATE_TEST_CASE_P(
327     SSE2, VP9QuantizeTest,
328     ::testing::Values(make_tuple(&vpx_highbd_quantize_b_sse2,
329                                  &vpx_highbd_quantize_b_c, VPX_BITS_8),
330                       make_tuple(&vpx_highbd_quantize_b_sse2,
331                                  &vpx_highbd_quantize_b_c, VPX_BITS_10),
332                       make_tuple(&vpx_highbd_quantize_b_sse2,
333                                  &vpx_highbd_quantize_b_c, VPX_BITS_12)));
334 INSTANTIATE_TEST_CASE_P(
335     SSE2, VP9Quantize32Test,
336     ::testing::Values(make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
337                                  &vpx_highbd_quantize_b_32x32_c, VPX_BITS_8),
338                       make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
339                                  &vpx_highbd_quantize_b_32x32_c, VPX_BITS_10),
340                       make_tuple(&vpx_highbd_quantize_b_32x32_sse2,
341                                  &vpx_highbd_quantize_b_32x32_c, VPX_BITS_12)));
342 #endif  // HAVE_SSE2
343 #endif  // CONFIG_VP9_HIGHBITDEPTH
344 }  // namespace
345