xref: /aosp_15_r20/external/libvpx/test/vp8_fdct4x4_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stddef.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
15*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
16*fb1b10abSAndroid Build Coastguard Worker #include <sys/types.h>
17*fb1b10abSAndroid Build Coastguard Worker 
18*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h"
19*fb1b10abSAndroid Build Coastguard Worker 
20*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "./vp8_rtcd.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "test/acm_random.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_integer.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
25*fb1b10abSAndroid Build Coastguard Worker 
26*fb1b10abSAndroid Build Coastguard Worker namespace {
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker typedef void (*FdctFunc)(int16_t *a, int16_t *b, int a_stride);
29*fb1b10abSAndroid Build Coastguard Worker 
30*fb1b10abSAndroid Build Coastguard Worker const int cospi8sqrt2minus1 = 20091;
31*fb1b10abSAndroid Build Coastguard Worker const int sinpi8sqrt2 = 35468;
32*fb1b10abSAndroid Build Coastguard Worker 
reference_idct4x4(const int16_t * input,int16_t * output)33*fb1b10abSAndroid Build Coastguard Worker void reference_idct4x4(const int16_t *input, int16_t *output) {
34*fb1b10abSAndroid Build Coastguard Worker   const int16_t *ip = input;
35*fb1b10abSAndroid Build Coastguard Worker   int16_t *op = output;
36*fb1b10abSAndroid Build Coastguard Worker 
37*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < 4; ++i) {
38*fb1b10abSAndroid Build Coastguard Worker     const int a1 = ip[0] + ip[8];
39*fb1b10abSAndroid Build Coastguard Worker     const int b1 = ip[0] - ip[8];
40*fb1b10abSAndroid Build Coastguard Worker     const int temp1 = (ip[4] * sinpi8sqrt2) >> 16;
41*fb1b10abSAndroid Build Coastguard Worker     const int temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
42*fb1b10abSAndroid Build Coastguard Worker     const int c1 = temp1 - temp2;
43*fb1b10abSAndroid Build Coastguard Worker     const int temp3 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16);
44*fb1b10abSAndroid Build Coastguard Worker     const int temp4 = (ip[12] * sinpi8sqrt2) >> 16;
45*fb1b10abSAndroid Build Coastguard Worker     const int d1 = temp3 + temp4;
46*fb1b10abSAndroid Build Coastguard Worker     op[0] = a1 + d1;
47*fb1b10abSAndroid Build Coastguard Worker     op[12] = a1 - d1;
48*fb1b10abSAndroid Build Coastguard Worker     op[4] = b1 + c1;
49*fb1b10abSAndroid Build Coastguard Worker     op[8] = b1 - c1;
50*fb1b10abSAndroid Build Coastguard Worker     ++ip;
51*fb1b10abSAndroid Build Coastguard Worker     ++op;
52*fb1b10abSAndroid Build Coastguard Worker   }
53*fb1b10abSAndroid Build Coastguard Worker   ip = output;
54*fb1b10abSAndroid Build Coastguard Worker   op = output;
55*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < 4; ++i) {
56*fb1b10abSAndroid Build Coastguard Worker     const int a1 = ip[0] + ip[2];
57*fb1b10abSAndroid Build Coastguard Worker     const int b1 = ip[0] - ip[2];
58*fb1b10abSAndroid Build Coastguard Worker     const int temp1 = (ip[1] * sinpi8sqrt2) >> 16;
59*fb1b10abSAndroid Build Coastguard Worker     const int temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16);
60*fb1b10abSAndroid Build Coastguard Worker     const int c1 = temp1 - temp2;
61*fb1b10abSAndroid Build Coastguard Worker     const int temp3 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16);
62*fb1b10abSAndroid Build Coastguard Worker     const int temp4 = (ip[3] * sinpi8sqrt2) >> 16;
63*fb1b10abSAndroid Build Coastguard Worker     const int d1 = temp3 + temp4;
64*fb1b10abSAndroid Build Coastguard Worker     op[0] = (a1 + d1 + 4) >> 3;
65*fb1b10abSAndroid Build Coastguard Worker     op[3] = (a1 - d1 + 4) >> 3;
66*fb1b10abSAndroid Build Coastguard Worker     op[1] = (b1 + c1 + 4) >> 3;
67*fb1b10abSAndroid Build Coastguard Worker     op[2] = (b1 - c1 + 4) >> 3;
68*fb1b10abSAndroid Build Coastguard Worker     ip += 4;
69*fb1b10abSAndroid Build Coastguard Worker     op += 4;
70*fb1b10abSAndroid Build Coastguard Worker   }
71*fb1b10abSAndroid Build Coastguard Worker }
72*fb1b10abSAndroid Build Coastguard Worker 
73*fb1b10abSAndroid Build Coastguard Worker using libvpx_test::ACMRandom;
74*fb1b10abSAndroid Build Coastguard Worker 
75*fb1b10abSAndroid Build Coastguard Worker class FdctTest : public ::testing::TestWithParam<FdctFunc> {
76*fb1b10abSAndroid Build Coastguard Worker  public:
SetUp()77*fb1b10abSAndroid Build Coastguard Worker   void SetUp() override {
78*fb1b10abSAndroid Build Coastguard Worker     fdct_func_ = GetParam();
79*fb1b10abSAndroid Build Coastguard Worker     rnd_.Reset(ACMRandom::DeterministicSeed());
80*fb1b10abSAndroid Build Coastguard Worker   }
81*fb1b10abSAndroid Build Coastguard Worker 
82*fb1b10abSAndroid Build Coastguard Worker  protected:
83*fb1b10abSAndroid Build Coastguard Worker   FdctFunc fdct_func_;
84*fb1b10abSAndroid Build Coastguard Worker   ACMRandom rnd_;
85*fb1b10abSAndroid Build Coastguard Worker };
86*fb1b10abSAndroid Build Coastguard Worker 
TEST_P(FdctTest,SignBiasCheck)87*fb1b10abSAndroid Build Coastguard Worker TEST_P(FdctTest, SignBiasCheck) {
88*fb1b10abSAndroid Build Coastguard Worker   int16_t test_input_block[16];
89*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, test_output_block[16]);
90*fb1b10abSAndroid Build Coastguard Worker   const int pitch = 8;
91*fb1b10abSAndroid Build Coastguard Worker   int count_sign_block[16][2];
92*fb1b10abSAndroid Build Coastguard Worker   const int count_test_block = 1000000;
93*fb1b10abSAndroid Build Coastguard Worker 
94*fb1b10abSAndroid Build Coastguard Worker   memset(count_sign_block, 0, sizeof(count_sign_block));
95*fb1b10abSAndroid Build Coastguard Worker 
96*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < count_test_block; ++i) {
97*fb1b10abSAndroid Build Coastguard Worker     // Initialize a test block with input range [-255, 255].
98*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
99*fb1b10abSAndroid Build Coastguard Worker       test_input_block[j] = rnd_.Rand8() - rnd_.Rand8();
100*fb1b10abSAndroid Build Coastguard Worker     }
101*fb1b10abSAndroid Build Coastguard Worker 
102*fb1b10abSAndroid Build Coastguard Worker     fdct_func_(test_input_block, test_output_block, pitch);
103*fb1b10abSAndroid Build Coastguard Worker 
104*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
105*fb1b10abSAndroid Build Coastguard Worker       if (test_output_block[j] < 0) {
106*fb1b10abSAndroid Build Coastguard Worker         ++count_sign_block[j][0];
107*fb1b10abSAndroid Build Coastguard Worker       } else if (test_output_block[j] > 0) {
108*fb1b10abSAndroid Build Coastguard Worker         ++count_sign_block[j][1];
109*fb1b10abSAndroid Build Coastguard Worker       }
110*fb1b10abSAndroid Build Coastguard Worker     }
111*fb1b10abSAndroid Build Coastguard Worker   }
112*fb1b10abSAndroid Build Coastguard Worker 
113*fb1b10abSAndroid Build Coastguard Worker   bool bias_acceptable = true;
114*fb1b10abSAndroid Build Coastguard Worker   for (int j = 0; j < 16; ++j) {
115*fb1b10abSAndroid Build Coastguard Worker     bias_acceptable =
116*fb1b10abSAndroid Build Coastguard Worker         bias_acceptable &&
117*fb1b10abSAndroid Build Coastguard Worker         (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 10000);
118*fb1b10abSAndroid Build Coastguard Worker   }
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(true, bias_acceptable)
121*fb1b10abSAndroid Build Coastguard Worker       << "Error: 4x4 FDCT has a sign bias > 1% for input range [-255, 255]";
122*fb1b10abSAndroid Build Coastguard Worker 
123*fb1b10abSAndroid Build Coastguard Worker   memset(count_sign_block, 0, sizeof(count_sign_block));
124*fb1b10abSAndroid Build Coastguard Worker 
125*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < count_test_block; ++i) {
126*fb1b10abSAndroid Build Coastguard Worker     // Initialize a test block with input range [-15, 15].
127*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
128*fb1b10abSAndroid Build Coastguard Worker       test_input_block[j] = (rnd_.Rand8() >> 4) - (rnd_.Rand8() >> 4);
129*fb1b10abSAndroid Build Coastguard Worker     }
130*fb1b10abSAndroid Build Coastguard Worker 
131*fb1b10abSAndroid Build Coastguard Worker     fdct_func_(test_input_block, test_output_block, pitch);
132*fb1b10abSAndroid Build Coastguard Worker 
133*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
134*fb1b10abSAndroid Build Coastguard Worker       if (test_output_block[j] < 0) {
135*fb1b10abSAndroid Build Coastguard Worker         ++count_sign_block[j][0];
136*fb1b10abSAndroid Build Coastguard Worker       } else if (test_output_block[j] > 0) {
137*fb1b10abSAndroid Build Coastguard Worker         ++count_sign_block[j][1];
138*fb1b10abSAndroid Build Coastguard Worker       }
139*fb1b10abSAndroid Build Coastguard Worker     }
140*fb1b10abSAndroid Build Coastguard Worker   }
141*fb1b10abSAndroid Build Coastguard Worker 
142*fb1b10abSAndroid Build Coastguard Worker   bias_acceptable = true;
143*fb1b10abSAndroid Build Coastguard Worker   for (int j = 0; j < 16; ++j) {
144*fb1b10abSAndroid Build Coastguard Worker     bias_acceptable =
145*fb1b10abSAndroid Build Coastguard Worker         bias_acceptable &&
146*fb1b10abSAndroid Build Coastguard Worker         (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 100000);
147*fb1b10abSAndroid Build Coastguard Worker   }
148*fb1b10abSAndroid Build Coastguard Worker 
149*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(true, bias_acceptable)
150*fb1b10abSAndroid Build Coastguard Worker       << "Error: 4x4 FDCT has a sign bias > 10% for input range [-15, 15]";
151*fb1b10abSAndroid Build Coastguard Worker }
152*fb1b10abSAndroid Build Coastguard Worker 
TEST_P(FdctTest,RoundTripErrorCheck)153*fb1b10abSAndroid Build Coastguard Worker TEST_P(FdctTest, RoundTripErrorCheck) {
154*fb1b10abSAndroid Build Coastguard Worker   int max_error = 0;
155*fb1b10abSAndroid Build Coastguard Worker   double total_error = 0;
156*fb1b10abSAndroid Build Coastguard Worker   const int count_test_block = 1000000;
157*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < count_test_block; ++i) {
158*fb1b10abSAndroid Build Coastguard Worker     int16_t test_input_block[16];
159*fb1b10abSAndroid Build Coastguard Worker     int16_t test_output_block[16];
160*fb1b10abSAndroid Build Coastguard Worker     DECLARE_ALIGNED(16, int16_t, test_temp_block[16]);
161*fb1b10abSAndroid Build Coastguard Worker 
162*fb1b10abSAndroid Build Coastguard Worker     // Initialize a test block with input range [-255, 255].
163*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
164*fb1b10abSAndroid Build Coastguard Worker       test_input_block[j] = rnd_.Rand8() - rnd_.Rand8();
165*fb1b10abSAndroid Build Coastguard Worker     }
166*fb1b10abSAndroid Build Coastguard Worker 
167*fb1b10abSAndroid Build Coastguard Worker     const int pitch = 8;
168*fb1b10abSAndroid Build Coastguard Worker     fdct_func_(test_input_block, test_temp_block, pitch);
169*fb1b10abSAndroid Build Coastguard Worker     reference_idct4x4(test_temp_block, test_output_block);
170*fb1b10abSAndroid Build Coastguard Worker 
171*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 16; ++j) {
172*fb1b10abSAndroid Build Coastguard Worker       const int diff = test_input_block[j] - test_output_block[j];
173*fb1b10abSAndroid Build Coastguard Worker       const int error = diff * diff;
174*fb1b10abSAndroid Build Coastguard Worker       if (max_error < error) max_error = error;
175*fb1b10abSAndroid Build Coastguard Worker       total_error += error;
176*fb1b10abSAndroid Build Coastguard Worker     }
177*fb1b10abSAndroid Build Coastguard Worker   }
178*fb1b10abSAndroid Build Coastguard Worker 
179*fb1b10abSAndroid Build Coastguard Worker   EXPECT_GE(1, max_error)
180*fb1b10abSAndroid Build Coastguard Worker       << "Error: FDCT/IDCT has an individual roundtrip error > 1";
181*fb1b10abSAndroid Build Coastguard Worker 
182*fb1b10abSAndroid Build Coastguard Worker   EXPECT_GE(count_test_block, total_error)
183*fb1b10abSAndroid Build Coastguard Worker       << "Error: FDCT/IDCT has average roundtrip error > 1 per block";
184*fb1b10abSAndroid Build Coastguard Worker }
185*fb1b10abSAndroid Build Coastguard Worker 
186*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(C, FdctTest, ::testing::Values(vp8_short_fdct4x4_c));
187*fb1b10abSAndroid Build Coastguard Worker 
188*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
189*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(NEON, FdctTest,
190*fb1b10abSAndroid Build Coastguard Worker                          ::testing::Values(vp8_short_fdct4x4_neon));
191*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
192*fb1b10abSAndroid Build Coastguard Worker 
193*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SSE2
194*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(SSE2, FdctTest,
195*fb1b10abSAndroid Build Coastguard Worker                          ::testing::Values(vp8_short_fdct4x4_sse2));
196*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SSE2
197*fb1b10abSAndroid Build Coastguard Worker 
198*fb1b10abSAndroid Build Coastguard Worker #if HAVE_MSA
199*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(MSA, FdctTest,
200*fb1b10abSAndroid Build Coastguard Worker                          ::testing::Values(vp8_short_fdct4x4_msa));
201*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_MSA
202*fb1b10abSAndroid Build Coastguard Worker #if HAVE_MMI
203*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(MMI, FdctTest,
204*fb1b10abSAndroid Build Coastguard Worker                          ::testing::Values(vp8_short_fdct4x4_mmi));
205*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_MMI
206*fb1b10abSAndroid Build Coastguard Worker 
207*fb1b10abSAndroid Build Coastguard Worker #if HAVE_LSX
208*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(LSX, FdctTest,
209*fb1b10abSAndroid Build Coastguard Worker                          ::testing::Values(vp8_short_fdct4x4_lsx));
210*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_LSX
211*fb1b10abSAndroid Build Coastguard Worker }  // namespace
212