xref: /aosp_15_r20/external/libaom/test/fwht4x4_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include <math.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <stdlib.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <string.h>
15*77c1e3ccSAndroid Build Coastguard Worker #include <tuple>
16*77c1e3ccSAndroid Build Coastguard Worker 
17*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "gtest/gtest.h"
19*77c1e3ccSAndroid Build Coastguard Worker 
20*77c1e3ccSAndroid Build Coastguard Worker #include "config/av1_rtcd.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "test/acm_random.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "test/register_state_check.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "test/transform_test_base.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "test/util.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/entropy.h"
27*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_codec.h"
28*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_integer.h"
29*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
30*77c1e3ccSAndroid Build Coastguard Worker 
31*77c1e3ccSAndroid Build Coastguard Worker using libaom_test::ACMRandom;
32*77c1e3ccSAndroid Build Coastguard Worker 
33*77c1e3ccSAndroid Build Coastguard Worker namespace {
34*77c1e3ccSAndroid Build Coastguard Worker typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
35*77c1e3ccSAndroid Build Coastguard Worker typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
36*77c1e3ccSAndroid Build Coastguard Worker 
37*77c1e3ccSAndroid Build Coastguard Worker using libaom_test::FhtFunc;
38*77c1e3ccSAndroid Build Coastguard Worker 
39*77c1e3ccSAndroid Build Coastguard Worker typedef std::tuple<FdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t, int, FdctFunc>
40*77c1e3ccSAndroid Build Coastguard Worker     Dct4x4Param;
41*77c1e3ccSAndroid Build Coastguard Worker 
fwht4x4_ref(const int16_t * in,tran_low_t * out,int stride,TxfmParam *)42*77c1e3ccSAndroid Build Coastguard Worker void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
43*77c1e3ccSAndroid Build Coastguard Worker                  TxfmParam * /*txfm_param*/) {
44*77c1e3ccSAndroid Build Coastguard Worker   av1_fwht4x4_c(in, out, stride);
45*77c1e3ccSAndroid Build Coastguard Worker }
46*77c1e3ccSAndroid Build Coastguard Worker 
iwht4x4_10_c(const tran_low_t * in,uint8_t * out,int stride)47*77c1e3ccSAndroid Build Coastguard Worker void iwht4x4_10_c(const tran_low_t *in, uint8_t *out, int stride) {
48*77c1e3ccSAndroid Build Coastguard Worker   av1_highbd_iwht4x4_16_add_c(in, out, stride, 10);
49*77c1e3ccSAndroid Build Coastguard Worker }
50*77c1e3ccSAndroid Build Coastguard Worker 
iwht4x4_12_c(const tran_low_t * in,uint8_t * out,int stride)51*77c1e3ccSAndroid Build Coastguard Worker void iwht4x4_12_c(const tran_low_t *in, uint8_t *out, int stride) {
52*77c1e3ccSAndroid Build Coastguard Worker   av1_highbd_iwht4x4_16_add_c(in, out, stride, 12);
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker 
55*77c1e3ccSAndroid Build Coastguard Worker #if HAVE_SSE4_1
56*77c1e3ccSAndroid Build Coastguard Worker 
iwht4x4_10_sse4_1(const tran_low_t * in,uint8_t * out,int stride)57*77c1e3ccSAndroid Build Coastguard Worker void iwht4x4_10_sse4_1(const tran_low_t *in, uint8_t *out, int stride) {
58*77c1e3ccSAndroid Build Coastguard Worker   av1_highbd_iwht4x4_16_add_sse4_1(in, out, stride, 10);
59*77c1e3ccSAndroid Build Coastguard Worker }
60*77c1e3ccSAndroid Build Coastguard Worker 
iwht4x4_12_sse4_1(const tran_low_t * in,uint8_t * out,int stride)61*77c1e3ccSAndroid Build Coastguard Worker void iwht4x4_12_sse4_1(const tran_low_t *in, uint8_t *out, int stride) {
62*77c1e3ccSAndroid Build Coastguard Worker   av1_highbd_iwht4x4_16_add_sse4_1(in, out, stride, 12);
63*77c1e3ccSAndroid Build Coastguard Worker }
64*77c1e3ccSAndroid Build Coastguard Worker 
65*77c1e3ccSAndroid Build Coastguard Worker #endif
66*77c1e3ccSAndroid Build Coastguard Worker 
67*77c1e3ccSAndroid Build Coastguard Worker class Trans4x4WHT : public libaom_test::TransformTestBase<tran_low_t>,
68*77c1e3ccSAndroid Build Coastguard Worker                     public ::testing::TestWithParam<Dct4x4Param> {
69*77c1e3ccSAndroid Build Coastguard Worker  public:
70*77c1e3ccSAndroid Build Coastguard Worker   ~Trans4x4WHT() override = default;
71*77c1e3ccSAndroid Build Coastguard Worker 
SetUp()72*77c1e3ccSAndroid Build Coastguard Worker   void SetUp() override {
73*77c1e3ccSAndroid Build Coastguard Worker     fwd_txfm_ = GET_PARAM(0);
74*77c1e3ccSAndroid Build Coastguard Worker     inv_txfm_ = GET_PARAM(1);
75*77c1e3ccSAndroid Build Coastguard Worker     pitch_ = 4;
76*77c1e3ccSAndroid Build Coastguard Worker     height_ = 4;
77*77c1e3ccSAndroid Build Coastguard Worker     fwd_txfm_ref = fwht4x4_ref;
78*77c1e3ccSAndroid Build Coastguard Worker     bit_depth_ = GET_PARAM(3);
79*77c1e3ccSAndroid Build Coastguard Worker     mask_ = (1 << bit_depth_) - 1;
80*77c1e3ccSAndroid Build Coastguard Worker     num_coeffs_ = GET_PARAM(4);
81*77c1e3ccSAndroid Build Coastguard Worker     fwd_txfm_c_ = GET_PARAM(5);
82*77c1e3ccSAndroid Build Coastguard Worker   }
83*77c1e3ccSAndroid Build Coastguard Worker 
84*77c1e3ccSAndroid Build Coastguard Worker  protected:
RunFwdTxfm(const int16_t * in,tran_low_t * out,int stride)85*77c1e3ccSAndroid Build Coastguard Worker   void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) override {
86*77c1e3ccSAndroid Build Coastguard Worker     fwd_txfm_(in, out, stride);
87*77c1e3ccSAndroid Build Coastguard Worker   }
RunInvTxfm(const tran_low_t * out,uint8_t * dst,int stride)88*77c1e3ccSAndroid Build Coastguard Worker   void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) override {
89*77c1e3ccSAndroid Build Coastguard Worker     inv_txfm_(out, dst, stride);
90*77c1e3ccSAndroid Build Coastguard Worker   }
RunSpeedTest()91*77c1e3ccSAndroid Build Coastguard Worker   void RunSpeedTest() {
92*77c1e3ccSAndroid Build Coastguard Worker     if (!fwd_txfm_c_) {
93*77c1e3ccSAndroid Build Coastguard Worker       GTEST_SKIP();
94*77c1e3ccSAndroid Build Coastguard Worker     } else {
95*77c1e3ccSAndroid Build Coastguard Worker       ACMRandom rnd(ACMRandom::DeterministicSeed());
96*77c1e3ccSAndroid Build Coastguard Worker       const int count_test_block = 10;
97*77c1e3ccSAndroid Build Coastguard Worker       const int numIter = 5000;
98*77c1e3ccSAndroid Build Coastguard Worker 
99*77c1e3ccSAndroid Build Coastguard Worker       int c_sum_time = 0;
100*77c1e3ccSAndroid Build Coastguard Worker       int simd_sum_time = 0;
101*77c1e3ccSAndroid Build Coastguard Worker 
102*77c1e3ccSAndroid Build Coastguard Worker       int stride = 96;
103*77c1e3ccSAndroid Build Coastguard Worker 
104*77c1e3ccSAndroid Build Coastguard Worker       int16_t *input_block = reinterpret_cast<int16_t *>(
105*77c1e3ccSAndroid Build Coastguard Worker           aom_memalign(16, sizeof(int16_t) * stride * height_));
106*77c1e3ccSAndroid Build Coastguard Worker       ASSERT_NE(input_block, nullptr);
107*77c1e3ccSAndroid Build Coastguard Worker       tran_low_t *output_ref_block = reinterpret_cast<tran_low_t *>(
108*77c1e3ccSAndroid Build Coastguard Worker           aom_memalign(16, sizeof(output_ref_block[0]) * num_coeffs_));
109*77c1e3ccSAndroid Build Coastguard Worker       ASSERT_NE(output_ref_block, nullptr);
110*77c1e3ccSAndroid Build Coastguard Worker       tran_low_t *output_block = reinterpret_cast<tran_low_t *>(
111*77c1e3ccSAndroid Build Coastguard Worker           aom_memalign(16, sizeof(output_block[0]) * num_coeffs_));
112*77c1e3ccSAndroid Build Coastguard Worker       ASSERT_NE(output_block, nullptr);
113*77c1e3ccSAndroid Build Coastguard Worker 
114*77c1e3ccSAndroid Build Coastguard Worker       for (int i = 0; i < count_test_block; ++i) {
115*77c1e3ccSAndroid Build Coastguard Worker         for (int j = 0; j < height_; ++j) {
116*77c1e3ccSAndroid Build Coastguard Worker           for (int k = 0; k < pitch_; ++k) {
117*77c1e3ccSAndroid Build Coastguard Worker             int in_idx = j * stride + k;
118*77c1e3ccSAndroid Build Coastguard Worker             int out_idx = j * pitch_ + k;
119*77c1e3ccSAndroid Build Coastguard Worker             input_block[in_idx] =
120*77c1e3ccSAndroid Build Coastguard Worker                 (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
121*77c1e3ccSAndroid Build Coastguard Worker             if (bit_depth_ == AOM_BITS_8) {
122*77c1e3ccSAndroid Build Coastguard Worker               output_block[out_idx] = output_ref_block[out_idx] = rnd.Rand8();
123*77c1e3ccSAndroid Build Coastguard Worker             } else {
124*77c1e3ccSAndroid Build Coastguard Worker               output_block[out_idx] = output_ref_block[out_idx] =
125*77c1e3ccSAndroid Build Coastguard Worker                   rnd.Rand16() & mask_;
126*77c1e3ccSAndroid Build Coastguard Worker             }
127*77c1e3ccSAndroid Build Coastguard Worker           }
128*77c1e3ccSAndroid Build Coastguard Worker         }
129*77c1e3ccSAndroid Build Coastguard Worker 
130*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer c_timer_;
131*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer_start(&c_timer_);
132*77c1e3ccSAndroid Build Coastguard Worker         for (int iter = 0; iter < numIter; iter++) {
133*77c1e3ccSAndroid Build Coastguard Worker           API_REGISTER_STATE_CHECK(
134*77c1e3ccSAndroid Build Coastguard Worker               fwd_txfm_c_(input_block, output_ref_block, stride));
135*77c1e3ccSAndroid Build Coastguard Worker         }
136*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer_mark(&c_timer_);
137*77c1e3ccSAndroid Build Coastguard Worker 
138*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer simd_timer_;
139*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer_start(&simd_timer_);
140*77c1e3ccSAndroid Build Coastguard Worker 
141*77c1e3ccSAndroid Build Coastguard Worker         for (int iter = 0; iter < numIter; iter++) {
142*77c1e3ccSAndroid Build Coastguard Worker           API_REGISTER_STATE_CHECK(
143*77c1e3ccSAndroid Build Coastguard Worker               fwd_txfm_(input_block, output_block, stride));
144*77c1e3ccSAndroid Build Coastguard Worker         }
145*77c1e3ccSAndroid Build Coastguard Worker         aom_usec_timer_mark(&simd_timer_);
146*77c1e3ccSAndroid Build Coastguard Worker 
147*77c1e3ccSAndroid Build Coastguard Worker         c_sum_time += static_cast<int>(aom_usec_timer_elapsed(&c_timer_));
148*77c1e3ccSAndroid Build Coastguard Worker         simd_sum_time += static_cast<int>(aom_usec_timer_elapsed(&simd_timer_));
149*77c1e3ccSAndroid Build Coastguard Worker 
150*77c1e3ccSAndroid Build Coastguard Worker         // The minimum quant value is 4.
151*77c1e3ccSAndroid Build Coastguard Worker         for (int j = 0; j < height_; ++j) {
152*77c1e3ccSAndroid Build Coastguard Worker           for (int k = 0; k < pitch_; ++k) {
153*77c1e3ccSAndroid Build Coastguard Worker             int out_idx = j * pitch_ + k;
154*77c1e3ccSAndroid Build Coastguard Worker             ASSERT_EQ(output_block[out_idx], output_ref_block[out_idx])
155*77c1e3ccSAndroid Build Coastguard Worker                 << "Error: not bit-exact result at index: " << out_idx
156*77c1e3ccSAndroid Build Coastguard Worker                 << " at test block: " << i;
157*77c1e3ccSAndroid Build Coastguard Worker           }
158*77c1e3ccSAndroid Build Coastguard Worker         }
159*77c1e3ccSAndroid Build Coastguard Worker       }
160*77c1e3ccSAndroid Build Coastguard Worker 
161*77c1e3ccSAndroid Build Coastguard Worker       printf(
162*77c1e3ccSAndroid Build Coastguard Worker           "c_time = %d \t simd_time = %d \t Gain = %4.2f \n", c_sum_time,
163*77c1e3ccSAndroid Build Coastguard Worker           simd_sum_time,
164*77c1e3ccSAndroid Build Coastguard Worker           (static_cast<float>(c_sum_time) / static_cast<float>(simd_sum_time)));
165*77c1e3ccSAndroid Build Coastguard Worker 
166*77c1e3ccSAndroid Build Coastguard Worker       aom_free(input_block);
167*77c1e3ccSAndroid Build Coastguard Worker       aom_free(output_ref_block);
168*77c1e3ccSAndroid Build Coastguard Worker       aom_free(output_block);
169*77c1e3ccSAndroid Build Coastguard Worker     }
170*77c1e3ccSAndroid Build Coastguard Worker   }
171*77c1e3ccSAndroid Build Coastguard Worker 
172*77c1e3ccSAndroid Build Coastguard Worker   FdctFunc fwd_txfm_;
173*77c1e3ccSAndroid Build Coastguard Worker   IdctFunc inv_txfm_;
174*77c1e3ccSAndroid Build Coastguard Worker 
175*77c1e3ccSAndroid Build Coastguard Worker   FdctFunc fwd_txfm_c_;  // C version of forward transform for speed test.
176*77c1e3ccSAndroid Build Coastguard Worker };
177*77c1e3ccSAndroid Build Coastguard Worker 
TEST_P(Trans4x4WHT,AccuracyCheck)178*77c1e3ccSAndroid Build Coastguard Worker TEST_P(Trans4x4WHT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
179*77c1e3ccSAndroid Build Coastguard Worker 
TEST_P(Trans4x4WHT,CoeffCheck)180*77c1e3ccSAndroid Build Coastguard Worker TEST_P(Trans4x4WHT, CoeffCheck) { RunCoeffCheck(); }
181*77c1e3ccSAndroid Build Coastguard Worker 
TEST_P(Trans4x4WHT,MemCheck)182*77c1e3ccSAndroid Build Coastguard Worker TEST_P(Trans4x4WHT, MemCheck) { RunMemCheck(); }
183*77c1e3ccSAndroid Build Coastguard Worker 
TEST_P(Trans4x4WHT,InvAccuracyCheck)184*77c1e3ccSAndroid Build Coastguard Worker TEST_P(Trans4x4WHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
185*77c1e3ccSAndroid Build Coastguard Worker 
TEST_P(Trans4x4WHT,DISABLED_Speed)186*77c1e3ccSAndroid Build Coastguard Worker TEST_P(Trans4x4WHT, DISABLED_Speed) { RunSpeedTest(); }
187*77c1e3ccSAndroid Build Coastguard Worker 
188*77c1e3ccSAndroid Build Coastguard Worker using std::make_tuple;
189*77c1e3ccSAndroid Build Coastguard Worker 
190*77c1e3ccSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
191*77c1e3ccSAndroid Build Coastguard Worker     C, Trans4x4WHT,
192*77c1e3ccSAndroid Build Coastguard Worker     ::testing::Values(make_tuple(&av1_fwht4x4_c, &iwht4x4_10_c, DCT_DCT,
193*77c1e3ccSAndroid Build Coastguard Worker                                  AOM_BITS_10, 16,
194*77c1e3ccSAndroid Build Coastguard Worker                                  static_cast<FdctFunc>(nullptr)),
195*77c1e3ccSAndroid Build Coastguard Worker                       make_tuple(&av1_fwht4x4_c, &iwht4x4_12_c, DCT_DCT,
196*77c1e3ccSAndroid Build Coastguard Worker                                  AOM_BITS_12, 16,
197*77c1e3ccSAndroid Build Coastguard Worker                                  static_cast<FdctFunc>(nullptr))));
198*77c1e3ccSAndroid Build Coastguard Worker 
199*77c1e3ccSAndroid Build Coastguard Worker #if HAVE_SSE4_1
200*77c1e3ccSAndroid Build Coastguard Worker 
201*77c1e3ccSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
202*77c1e3ccSAndroid Build Coastguard Worker     SSE4_1, Trans4x4WHT,
203*77c1e3ccSAndroid Build Coastguard Worker     ::testing::Values(make_tuple(&av1_fwht4x4_sse4_1, &iwht4x4_10_sse4_1,
204*77c1e3ccSAndroid Build Coastguard Worker                                  DCT_DCT, AOM_BITS_10, 16,
205*77c1e3ccSAndroid Build Coastguard Worker                                  static_cast<FdctFunc>(nullptr)),
206*77c1e3ccSAndroid Build Coastguard Worker                       make_tuple(&av1_fwht4x4_sse4_1, &iwht4x4_12_sse4_1,
207*77c1e3ccSAndroid Build Coastguard Worker                                  DCT_DCT, AOM_BITS_12, 16,
208*77c1e3ccSAndroid Build Coastguard Worker                                  static_cast<FdctFunc>(nullptr))));
209*77c1e3ccSAndroid Build Coastguard Worker 
210*77c1e3ccSAndroid Build Coastguard Worker #endif  // HAVE_SSE4_1
211*77c1e3ccSAndroid Build Coastguard Worker 
212*77c1e3ccSAndroid Build Coastguard Worker #if HAVE_NEON
213*77c1e3ccSAndroid Build Coastguard Worker 
214*77c1e3ccSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
215*77c1e3ccSAndroid Build Coastguard Worker     NEON, Trans4x4WHT,
216*77c1e3ccSAndroid Build Coastguard Worker     ::testing::Values(make_tuple(&av1_fwht4x4_neon, &iwht4x4_10_c, DCT_DCT,
217*77c1e3ccSAndroid Build Coastguard Worker                                  AOM_BITS_10, 16, &av1_fwht4x4_c),
218*77c1e3ccSAndroid Build Coastguard Worker                       make_tuple(&av1_fwht4x4_neon, &iwht4x4_12_c, DCT_DCT,
219*77c1e3ccSAndroid Build Coastguard Worker                                  AOM_BITS_12, 16, &av1_fwht4x4_c)));
220*77c1e3ccSAndroid Build Coastguard Worker 
221*77c1e3ccSAndroid Build Coastguard Worker #endif  // HAVE_NEON
222*77c1e3ccSAndroid Build Coastguard Worker 
223*77c1e3ccSAndroid Build Coastguard Worker }  // namespace
224