xref: /aosp_15_r20/external/libgav1/src/warp_prediction_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/warp_prediction.h"
16 
17 #include <cstddef>
18 #include <cstdint>
19 #include <ostream>
20 
21 #include "absl/base/macros.h"
22 #include "gtest/gtest.h"
23 #include "src/obu_parser.h"
24 #include "src/utils/common.h"
25 #include "src/utils/constants.h"
26 #include "src/utils/types.h"
27 #include "tests/third_party/libvpx/acm_random.h"
28 
29 namespace libgav1 {
30 namespace {
31 
32 constexpr int16_t kExpectedWarpParamsOutput[10][4] = {
33     {0, 0, 0, 0},
34     {2880, 2880, 2752, 2752},
35     {-1408, -1408, -1472, -1472},
36     {0, 0, 0, 0},
37     {6784, 6784, 6144, 6144},  // Invalid.
38     {-5312, -5312, -5824, -5824},
39     {-3904, -3904, -4160, -4160},
40     {2496, 2496, 2368, 2368},
41     {1024, 1024, 1024, 1024},
42     {-7808, -7808, -8832, -8832},  // Invalid.
43 };
44 
45 constexpr bool kExpectedWarpValid[10] = {
46     true, true, true, true, false, true, true, true, true, false,
47 };
48 
RandomWarpedParam(int seed_offset,int bits)49 int RandomWarpedParam(int seed_offset, int bits) {
50   libvpx_test::ACMRandom rnd(seed_offset +
51                              libvpx_test::ACMRandom::DeterministicSeed());
52   // 1 in 8 chance of generating zero (arbitrary).
53   const bool zero = (rnd.Rand16() & 7) == 0;
54   if (zero) return 0;
55   // Generate uniform values in the range [-(1 << bits), 1] U [1, 1 << bits].
56   const int mask = (1 << bits) - 1;
57   const int value = 1 + (rnd.RandRange(1U << 31) & mask);
58   const bool sign = (rnd.Rand16() & 1) != 0;
59   return sign ? value : -value;
60 }
61 
GenerateWarpedModel(GlobalMotion * warp_params,int seed)62 void GenerateWarpedModel(GlobalMotion* warp_params, int seed) {
63   do {
64     warp_params->params[0] =
65         RandomWarpedParam(seed, kWarpedModelPrecisionBits + 6);
66     warp_params->params[1] =
67         RandomWarpedParam(seed, kWarpedModelPrecisionBits + 6);
68     warp_params->params[2] =
69         RandomWarpedParam(seed, kWarpedModelPrecisionBits - 3) +
70         (1 << kWarpedModelPrecisionBits);
71     warp_params->params[3] =
72         RandomWarpedParam(seed, kWarpedModelPrecisionBits - 3);
73     warp_params->params[4] =
74         RandomWarpedParam(seed, kWarpedModelPrecisionBits - 3);
75     warp_params->params[5] =
76         RandomWarpedParam(seed, kWarpedModelPrecisionBits - 3) +
77         (1 << kWarpedModelPrecisionBits);
78   } while (warp_params->params[2] == 0);
79 }
80 
TEST(WarpPredictionTest,SetupShear)81 TEST(WarpPredictionTest, SetupShear) {
82   for (size_t i = 0; i < ABSL_ARRAYSIZE(kExpectedWarpParamsOutput); ++i) {
83     GlobalMotion warp_params;
84     GenerateWarpedModel(&warp_params, static_cast<int>(i));
85     const bool warp_valid = SetupShear(&warp_params);
86 
87     SCOPED_TRACE(testing::Message() << "Test failure at iteration: " << i);
88     EXPECT_EQ(warp_valid, kExpectedWarpValid[i]);
89     EXPECT_EQ(warp_params.alpha, kExpectedWarpParamsOutput[i][0]);
90     EXPECT_EQ(warp_params.beta, kExpectedWarpParamsOutput[i][1]);
91     EXPECT_EQ(warp_params.gamma, kExpectedWarpParamsOutput[i][2]);
92     EXPECT_EQ(warp_params.delta, kExpectedWarpParamsOutput[i][3]);
93   }
94 
95   // Test signed shift behavior in delta and gamma generation.
96   GlobalMotion warp_params;
97   warp_params.params[0] = 24748;
98   warp_params.params[1] = -142530;
99   warp_params.params[2] = 65516;
100   warp_params.params[3] = -640;
101   warp_params.params[4] = 256;
102   warp_params.params[5] = 65310;
103   EXPECT_TRUE(SetupShear(&warp_params));
104   EXPECT_EQ(warp_params.alpha, 0);
105   EXPECT_EQ(warp_params.beta, -640);
106   EXPECT_EQ(warp_params.gamma, 256);
107   EXPECT_EQ(warp_params.delta, -192);
108 
109   warp_params.params[0] = 24748;
110   warp_params.params[1] = -142530;
111   warp_params.params[2] = 61760;
112   warp_params.params[3] = -640;
113   warp_params.params[4] = -13312;
114   warp_params.params[5] = 65310;
115   EXPECT_TRUE(SetupShear(&warp_params));
116   EXPECT_EQ(warp_params.alpha, -3776);
117   EXPECT_EQ(warp_params.beta, -640);
118   EXPECT_EQ(warp_params.gamma, -14144);
119   EXPECT_EQ(warp_params.delta, -384);
120 }
121 
122 struct WarpInputParam {
WarpInputParamlibgav1::__anona5d33bf00111::WarpInputParam123   WarpInputParam(int num_samples, int block_width4x4, int block_height4x4)
124       : num_samples(num_samples),
125         block_width4x4(block_width4x4),
126         block_height4x4(block_height4x4) {}
127   int num_samples;
128   int block_width4x4;
129   int block_height4x4;
130 };
131 
operator <<(std::ostream & os,const WarpInputParam & param)132 std::ostream& operator<<(std::ostream& os, const WarpInputParam& param) {
133   return os << "num_samples: " << param.num_samples
134             << ", block_(width/height)4x4: " << param.block_width4x4 << "x"
135             << param.block_height4x4;
136 }
137 
138 const WarpInputParam warp_test_param[] = {
139     // sample = 1.
140     WarpInputParam(1, 1, 1),
141     WarpInputParam(1, 1, 2),
142     WarpInputParam(1, 2, 1),
143     WarpInputParam(1, 2, 2),
144     WarpInputParam(1, 2, 4),
145     WarpInputParam(1, 4, 2),
146     WarpInputParam(1, 4, 4),
147     WarpInputParam(1, 4, 8),
148     WarpInputParam(1, 8, 4),
149     WarpInputParam(1, 8, 8),
150     WarpInputParam(1, 8, 16),
151     WarpInputParam(1, 16, 8),
152     WarpInputParam(1, 16, 16),
153     WarpInputParam(1, 16, 32),
154     WarpInputParam(1, 32, 16),
155     WarpInputParam(1, 32, 32),
156     // sample = 8.
157     WarpInputParam(8, 1, 1),
158     WarpInputParam(8, 1, 2),
159     WarpInputParam(8, 2, 1),
160     WarpInputParam(8, 2, 2),
161     WarpInputParam(8, 2, 4),
162     WarpInputParam(8, 4, 2),
163     WarpInputParam(8, 4, 4),
164     WarpInputParam(8, 4, 8),
165     WarpInputParam(8, 8, 4),
166     WarpInputParam(8, 8, 8),
167     WarpInputParam(8, 8, 16),
168     WarpInputParam(8, 16, 8),
169     WarpInputParam(8, 16, 16),
170     WarpInputParam(8, 16, 32),
171     WarpInputParam(8, 32, 16),
172     WarpInputParam(8, 32, 32),
173 };
174 
175 constexpr bool kExpectedWarpEstimationValid[2] = {false, true};
176 
177 constexpr int kExpectedWarpEstimationOutput[16][6] = {
178     {8388607, 8388607, 57345, -8191, -8191, 57345},
179     {8388607, 8388607, 57345, -8191, -8191, 57345},
180     {8388607, 8388607, 57345, -8191, -8191, 57345},
181     {8388607, 8388607, 57345, -8191, -8191, 57345},
182     {8388607, 8388607, 57345, -8191, -8191, 57345},
183     {8388607, 8388607, 57345, -8191, -8191, 57345},
184     {8388607, 8388607, 57345, -8191, -8191, 57345},
185     {8388607, 8388607, 57345, -8191, -8191, 57345},
186     {8388607, 8388607, 57345, -8191, -8191, 57345},
187     {8388607, 8388607, 57345, -8191, -8191, 57345},
188     {2146296, 1589240, 57345, 8191, -8191, 73727},
189     {1753128, 1196072, 73727, -8191, 8191, 57345},
190     {-8388608, -8388608, 73727, 8191, 8191, 73727},
191     {-4435485, -8388608, 65260, 8191, 8191, 73727},
192     {-8388608, -7552929, 73727, 8191, 8191, 68240},
193     {-8388608, -8388608, 73727, 8191, 8191, 70800},
194 };
195 
196 class WarpEstimationTest : public testing::TestWithParam<WarpInputParam> {
197  public:
198   WarpEstimationTest() = default;
199   ~WarpEstimationTest() override = default;
200 
201  protected:
202   WarpInputParam param_ = GetParam();
203 };
204 
TEST_P(WarpEstimationTest,WarpEstimation)205 TEST_P(WarpEstimationTest, WarpEstimation) {
206   // Set input params.
207   libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
208   const int row4x4 = rnd.Rand8();
209   const int column4x4 = rnd.Rand8();
210   MotionVector mv;
211   mv.mv[0] = rnd.Rand8();
212   mv.mv[1] = rnd.Rand8();
213   int candidates[kMaxLeastSquaresSamples][4];
214   for (int i = 0; i < param_.num_samples; ++i) {
215     // Make candidates relative to the top left of frame.
216     candidates[i][0] = rnd.Rand8() + MultiplyBy32(row4x4);
217     candidates[i][1] = rnd.Rand8() + MultiplyBy32(column4x4);
218     candidates[i][2] = rnd.Rand8() + MultiplyBy32(row4x4);
219     candidates[i][3] = rnd.Rand8() + MultiplyBy32(column4x4);
220   }
221 
222   // Get output.
223   GlobalMotion warp_params;
224   const bool warp_success = WarpEstimation(
225       param_.num_samples, param_.block_width4x4, param_.block_height4x4, row4x4,
226       column4x4, mv, candidates, &warp_params);
227   if (param_.num_samples == 1) {
228     EXPECT_EQ(warp_success, kExpectedWarpEstimationValid[0]);
229   } else {
230     EXPECT_EQ(warp_success, kExpectedWarpEstimationValid[1]);
231     int index = FloorLog2(param_.block_width4x4) * 3 - 1;
232     if (param_.block_width4x4 == param_.block_height4x4) {
233       index += 1;
234     } else if (param_.block_width4x4 < param_.block_height4x4) {
235       index += 2;
236     }
237     for (size_t i = 0; i < ABSL_ARRAYSIZE(warp_params.params); ++i) {
238       EXPECT_EQ(warp_params.params[i], kExpectedWarpEstimationOutput[index][i]);
239     }
240   }
241 }
242 
243 INSTANTIATE_TEST_SUITE_P(WarpFuncTest, WarpEstimationTest,
244                          testing::ValuesIn(warp_test_param));
245 }  // namespace
246 }  // namespace libgav1
247