xref: /aosp_15_r20/external/libvpx/test/consistency_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2012 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 <limits.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <tuple>
15*fb1b10abSAndroid Build Coastguard Worker 
16*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h"
17*fb1b10abSAndroid Build Coastguard Worker 
18*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
19*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
20*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
21*fb1b10abSAndroid Build Coastguard Worker #endif
22*fb1b10abSAndroid Build Coastguard Worker 
23*fb1b10abSAndroid Build Coastguard Worker #include "test/acm_random.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "test/clear_system_state.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "test/register_state_check.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "test/util.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/ssim.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
29*fb1b10abSAndroid Build Coastguard Worker 
30*fb1b10abSAndroid Build Coastguard Worker extern "C" double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch,
31*fb1b10abSAndroid Build Coastguard Worker                                        uint8_t *img2, int img2_pitch, int width,
32*fb1b10abSAndroid Build Coastguard Worker                                        int height, Ssimv *sv2, Metrics *m,
33*fb1b10abSAndroid Build Coastguard Worker                                        int do_inconsistency);
34*fb1b10abSAndroid Build Coastguard Worker 
35*fb1b10abSAndroid Build Coastguard Worker using libvpx_test::ACMRandom;
36*fb1b10abSAndroid Build Coastguard Worker 
37*fb1b10abSAndroid Build Coastguard Worker namespace {
38*fb1b10abSAndroid Build Coastguard Worker class ConsistencyTestBase : public ::testing::Test {
39*fb1b10abSAndroid Build Coastguard Worker  public:
ConsistencyTestBase(int width,int height)40*fb1b10abSAndroid Build Coastguard Worker   ConsistencyTestBase(int width, int height) : width_(width), height_(height) {}
41*fb1b10abSAndroid Build Coastguard Worker 
SetUpTestSuite()42*fb1b10abSAndroid Build Coastguard Worker   static void SetUpTestSuite() {
43*fb1b10abSAndroid Build Coastguard Worker     source_data_[0] = reinterpret_cast<uint8_t *>(
44*fb1b10abSAndroid Build Coastguard Worker         vpx_memalign(kDataAlignment, kDataBufferSize));
45*fb1b10abSAndroid Build Coastguard Worker     reference_data_[0] = reinterpret_cast<uint8_t *>(
46*fb1b10abSAndroid Build Coastguard Worker         vpx_memalign(kDataAlignment, kDataBufferSize));
47*fb1b10abSAndroid Build Coastguard Worker     source_data_[1] = reinterpret_cast<uint8_t *>(
48*fb1b10abSAndroid Build Coastguard Worker         vpx_memalign(kDataAlignment, kDataBufferSize));
49*fb1b10abSAndroid Build Coastguard Worker     reference_data_[1] = reinterpret_cast<uint8_t *>(
50*fb1b10abSAndroid Build Coastguard Worker         vpx_memalign(kDataAlignment, kDataBufferSize));
51*fb1b10abSAndroid Build Coastguard Worker     ssim_array_ = new Ssimv[kDataBufferSize / 16];
52*fb1b10abSAndroid Build Coastguard Worker   }
53*fb1b10abSAndroid Build Coastguard Worker 
ClearSsim()54*fb1b10abSAndroid Build Coastguard Worker   static void ClearSsim() { memset(ssim_array_, 0, kDataBufferSize / 16); }
TearDownTestSuite()55*fb1b10abSAndroid Build Coastguard Worker   static void TearDownTestSuite() {
56*fb1b10abSAndroid Build Coastguard Worker     vpx_free(source_data_[0]);
57*fb1b10abSAndroid Build Coastguard Worker     source_data_[0] = nullptr;
58*fb1b10abSAndroid Build Coastguard Worker     vpx_free(reference_data_[0]);
59*fb1b10abSAndroid Build Coastguard Worker     reference_data_[0] = nullptr;
60*fb1b10abSAndroid Build Coastguard Worker     vpx_free(source_data_[1]);
61*fb1b10abSAndroid Build Coastguard Worker     source_data_[1] = nullptr;
62*fb1b10abSAndroid Build Coastguard Worker     vpx_free(reference_data_[1]);
63*fb1b10abSAndroid Build Coastguard Worker     reference_data_[1] = nullptr;
64*fb1b10abSAndroid Build Coastguard Worker 
65*fb1b10abSAndroid Build Coastguard Worker     delete[] ssim_array_;
66*fb1b10abSAndroid Build Coastguard Worker   }
67*fb1b10abSAndroid Build Coastguard Worker 
TearDown()68*fb1b10abSAndroid Build Coastguard Worker   void TearDown() override { libvpx_test::ClearSystemState(); }
69*fb1b10abSAndroid Build Coastguard Worker 
70*fb1b10abSAndroid Build Coastguard Worker  protected:
71*fb1b10abSAndroid Build Coastguard Worker   // Handle frames up to 640x480
72*fb1b10abSAndroid Build Coastguard Worker   static const int kDataAlignment = 16;
73*fb1b10abSAndroid Build Coastguard Worker   static const int kDataBufferSize = 640 * 480;
74*fb1b10abSAndroid Build Coastguard Worker 
SetUp()75*fb1b10abSAndroid Build Coastguard Worker   void SetUp() override {
76*fb1b10abSAndroid Build Coastguard Worker     source_stride_ = (width_ + 31) & ~31;
77*fb1b10abSAndroid Build Coastguard Worker     reference_stride_ = width_ * 2;
78*fb1b10abSAndroid Build Coastguard Worker     rnd_.Reset(ACMRandom::DeterministicSeed());
79*fb1b10abSAndroid Build Coastguard Worker   }
80*fb1b10abSAndroid Build Coastguard Worker 
FillRandom(uint8_t * data,int stride,int width,int height)81*fb1b10abSAndroid Build Coastguard Worker   void FillRandom(uint8_t *data, int stride, int width, int height) {
82*fb1b10abSAndroid Build Coastguard Worker     for (int h = 0; h < height; ++h) {
83*fb1b10abSAndroid Build Coastguard Worker       for (int w = 0; w < width; ++w) {
84*fb1b10abSAndroid Build Coastguard Worker         data[h * stride + w] = rnd_.Rand8();
85*fb1b10abSAndroid Build Coastguard Worker       }
86*fb1b10abSAndroid Build Coastguard Worker     }
87*fb1b10abSAndroid Build Coastguard Worker   }
88*fb1b10abSAndroid Build Coastguard Worker 
FillRandom(uint8_t * data,int stride)89*fb1b10abSAndroid Build Coastguard Worker   void FillRandom(uint8_t *data, int stride) {
90*fb1b10abSAndroid Build Coastguard Worker     FillRandom(data, stride, width_, height_);
91*fb1b10abSAndroid Build Coastguard Worker   }
92*fb1b10abSAndroid Build Coastguard Worker 
Copy(uint8_t * reference,uint8_t * source)93*fb1b10abSAndroid Build Coastguard Worker   void Copy(uint8_t *reference, uint8_t *source) {
94*fb1b10abSAndroid Build Coastguard Worker     memcpy(reference, source, kDataBufferSize);
95*fb1b10abSAndroid Build Coastguard Worker   }
96*fb1b10abSAndroid Build Coastguard Worker 
Blur(uint8_t * data,int stride,int taps)97*fb1b10abSAndroid Build Coastguard Worker   void Blur(uint8_t *data, int stride, int taps) {
98*fb1b10abSAndroid Build Coastguard Worker     int sum = 0;
99*fb1b10abSAndroid Build Coastguard Worker     int half_taps = taps / 2;
100*fb1b10abSAndroid Build Coastguard Worker     for (int h = 0; h < height_; ++h) {
101*fb1b10abSAndroid Build Coastguard Worker       for (int w = 0; w < taps; ++w) {
102*fb1b10abSAndroid Build Coastguard Worker         sum += data[w + h * stride];
103*fb1b10abSAndroid Build Coastguard Worker       }
104*fb1b10abSAndroid Build Coastguard Worker       for (int w = taps; w < width_; ++w) {
105*fb1b10abSAndroid Build Coastguard Worker         sum += data[w + h * stride] - data[w - taps + h * stride];
106*fb1b10abSAndroid Build Coastguard Worker         data[w - half_taps + h * stride] = (sum + half_taps) / taps;
107*fb1b10abSAndroid Build Coastguard Worker       }
108*fb1b10abSAndroid Build Coastguard Worker     }
109*fb1b10abSAndroid Build Coastguard Worker     for (int w = 0; w < width_; ++w) {
110*fb1b10abSAndroid Build Coastguard Worker       for (int h = 0; h < taps; ++h) {
111*fb1b10abSAndroid Build Coastguard Worker         sum += data[h + w * stride];
112*fb1b10abSAndroid Build Coastguard Worker       }
113*fb1b10abSAndroid Build Coastguard Worker       for (int h = taps; h < height_; ++h) {
114*fb1b10abSAndroid Build Coastguard Worker         sum += data[w + h * stride] - data[(h - taps) * stride + w];
115*fb1b10abSAndroid Build Coastguard Worker         data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
116*fb1b10abSAndroid Build Coastguard Worker       }
117*fb1b10abSAndroid Build Coastguard Worker     }
118*fb1b10abSAndroid Build Coastguard Worker   }
119*fb1b10abSAndroid Build Coastguard Worker   int width_, height_;
120*fb1b10abSAndroid Build Coastguard Worker   static uint8_t *source_data_[2];
121*fb1b10abSAndroid Build Coastguard Worker   int source_stride_;
122*fb1b10abSAndroid Build Coastguard Worker   static uint8_t *reference_data_[2];
123*fb1b10abSAndroid Build Coastguard Worker   int reference_stride_;
124*fb1b10abSAndroid Build Coastguard Worker   static Ssimv *ssim_array_;
125*fb1b10abSAndroid Build Coastguard Worker   Metrics metrics_;
126*fb1b10abSAndroid Build Coastguard Worker 
127*fb1b10abSAndroid Build Coastguard Worker   ACMRandom rnd_;
128*fb1b10abSAndroid Build Coastguard Worker };
129*fb1b10abSAndroid Build Coastguard Worker 
130*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
131*fb1b10abSAndroid Build Coastguard Worker typedef std::tuple<int, int> ConsistencyParam;
132*fb1b10abSAndroid Build Coastguard Worker class ConsistencyVP9Test
133*fb1b10abSAndroid Build Coastguard Worker     : public ConsistencyTestBase,
134*fb1b10abSAndroid Build Coastguard Worker       public ::testing::WithParamInterface<ConsistencyParam> {
135*fb1b10abSAndroid Build Coastguard Worker  public:
ConsistencyVP9Test()136*fb1b10abSAndroid Build Coastguard Worker   ConsistencyVP9Test() : ConsistencyTestBase(GET_PARAM(0), GET_PARAM(1)) {}
137*fb1b10abSAndroid Build Coastguard Worker 
138*fb1b10abSAndroid Build Coastguard Worker  protected:
CheckConsistency(int frame)139*fb1b10abSAndroid Build Coastguard Worker   double CheckConsistency(int frame) {
140*fb1b10abSAndroid Build Coastguard Worker     EXPECT_LT(frame, 2) << "Frame to check has to be less than 2.";
141*fb1b10abSAndroid Build Coastguard Worker     return vpx_get_ssim_metrics(source_data_[frame], source_stride_,
142*fb1b10abSAndroid Build Coastguard Worker                                 reference_data_[frame], reference_stride_,
143*fb1b10abSAndroid Build Coastguard Worker                                 width_, height_, ssim_array_, &metrics_, 1);
144*fb1b10abSAndroid Build Coastguard Worker   }
145*fb1b10abSAndroid Build Coastguard Worker };
146*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_ENCODER
147*fb1b10abSAndroid Build Coastguard Worker 
148*fb1b10abSAndroid Build Coastguard Worker uint8_t *ConsistencyTestBase::source_data_[2] = { nullptr, nullptr };
149*fb1b10abSAndroid Build Coastguard Worker uint8_t *ConsistencyTestBase::reference_data_[2] = { nullptr, nullptr };
150*fb1b10abSAndroid Build Coastguard Worker Ssimv *ConsistencyTestBase::ssim_array_ = nullptr;
151*fb1b10abSAndroid Build Coastguard Worker 
152*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
TEST_P(ConsistencyVP9Test,ConsistencyIsZero)153*fb1b10abSAndroid Build Coastguard Worker TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
154*fb1b10abSAndroid Build Coastguard Worker   FillRandom(source_data_[0], source_stride_);
155*fb1b10abSAndroid Build Coastguard Worker   Copy(source_data_[1], source_data_[0]);
156*fb1b10abSAndroid Build Coastguard Worker   Copy(reference_data_[0], source_data_[0]);
157*fb1b10abSAndroid Build Coastguard Worker   Blur(reference_data_[0], reference_stride_, 3);
158*fb1b10abSAndroid Build Coastguard Worker   Copy(reference_data_[1], source_data_[0]);
159*fb1b10abSAndroid Build Coastguard Worker   Blur(reference_data_[1], reference_stride_, 3);
160*fb1b10abSAndroid Build Coastguard Worker 
161*fb1b10abSAndroid Build Coastguard Worker   double inconsistency = CheckConsistency(1);
162*fb1b10abSAndroid Build Coastguard Worker   inconsistency = CheckConsistency(0);
163*fb1b10abSAndroid Build Coastguard Worker   EXPECT_EQ(inconsistency, 0.0)
164*fb1b10abSAndroid Build Coastguard Worker       << "Should have 0 inconsistency if they are exactly the same.";
165*fb1b10abSAndroid Build Coastguard Worker 
166*fb1b10abSAndroid Build Coastguard Worker   // If sources are not consistent reference frames inconsistency should
167*fb1b10abSAndroid Build Coastguard Worker   // be less than if the source is consistent.
168*fb1b10abSAndroid Build Coastguard Worker   FillRandom(source_data_[0], source_stride_);
169*fb1b10abSAndroid Build Coastguard Worker   FillRandom(source_data_[1], source_stride_);
170*fb1b10abSAndroid Build Coastguard Worker   FillRandom(reference_data_[0], reference_stride_);
171*fb1b10abSAndroid Build Coastguard Worker   FillRandom(reference_data_[1], reference_stride_);
172*fb1b10abSAndroid Build Coastguard Worker   CheckConsistency(0);
173*fb1b10abSAndroid Build Coastguard Worker   inconsistency = CheckConsistency(1);
174*fb1b10abSAndroid Build Coastguard Worker 
175*fb1b10abSAndroid Build Coastguard Worker   Copy(source_data_[1], source_data_[0]);
176*fb1b10abSAndroid Build Coastguard Worker   CheckConsistency(0);
177*fb1b10abSAndroid Build Coastguard Worker   double inconsistency2 = CheckConsistency(1);
178*fb1b10abSAndroid Build Coastguard Worker   EXPECT_LT(inconsistency, inconsistency2)
179*fb1b10abSAndroid Build Coastguard Worker       << "Should have less inconsistency if source itself is inconsistent.";
180*fb1b10abSAndroid Build Coastguard Worker 
181*fb1b10abSAndroid Build Coastguard Worker   // Less of a blur should be less inconsistent than more blur coming off a
182*fb1b10abSAndroid Build Coastguard Worker   // a frame with no blur.
183*fb1b10abSAndroid Build Coastguard Worker   ClearSsim();
184*fb1b10abSAndroid Build Coastguard Worker   FillRandom(source_data_[0], source_stride_);
185*fb1b10abSAndroid Build Coastguard Worker   Copy(source_data_[1], source_data_[0]);
186*fb1b10abSAndroid Build Coastguard Worker   Copy(reference_data_[0], source_data_[0]);
187*fb1b10abSAndroid Build Coastguard Worker   Copy(reference_data_[1], source_data_[0]);
188*fb1b10abSAndroid Build Coastguard Worker   Blur(reference_data_[1], reference_stride_, 4);
189*fb1b10abSAndroid Build Coastguard Worker   CheckConsistency(0);
190*fb1b10abSAndroid Build Coastguard Worker   inconsistency = CheckConsistency(1);
191*fb1b10abSAndroid Build Coastguard Worker   ClearSsim();
192*fb1b10abSAndroid Build Coastguard Worker   Copy(reference_data_[1], source_data_[0]);
193*fb1b10abSAndroid Build Coastguard Worker   Blur(reference_data_[1], reference_stride_, 8);
194*fb1b10abSAndroid Build Coastguard Worker   CheckConsistency(0);
195*fb1b10abSAndroid Build Coastguard Worker   inconsistency2 = CheckConsistency(1);
196*fb1b10abSAndroid Build Coastguard Worker 
197*fb1b10abSAndroid Build Coastguard Worker   EXPECT_LT(inconsistency, inconsistency2)
198*fb1b10abSAndroid Build Coastguard Worker       << "Stronger Blur should produce more inconsistency.";
199*fb1b10abSAndroid Build Coastguard Worker }
200*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_ENCODER
201*fb1b10abSAndroid Build Coastguard Worker 
202*fb1b10abSAndroid Build Coastguard Worker using std::make_tuple;
203*fb1b10abSAndroid Build Coastguard Worker 
204*fb1b10abSAndroid Build Coastguard Worker //------------------------------------------------------------------------------
205*fb1b10abSAndroid Build Coastguard Worker // C functions
206*fb1b10abSAndroid Build Coastguard Worker 
207*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
208*fb1b10abSAndroid Build Coastguard Worker const ConsistencyParam c_vp9_tests[] = { make_tuple(320, 240),
209*fb1b10abSAndroid Build Coastguard Worker                                          make_tuple(318, 242),
210*fb1b10abSAndroid Build Coastguard Worker                                          make_tuple(318, 238) };
211*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(C, ConsistencyVP9Test,
212*fb1b10abSAndroid Build Coastguard Worker                          ::testing::ValuesIn(c_vp9_tests));
213*fb1b10abSAndroid Build Coastguard Worker #endif
214*fb1b10abSAndroid Build Coastguard Worker 
215*fb1b10abSAndroid Build Coastguard Worker }  // namespace
216