xref: /aosp_15_r20/external/libaom/test/hbd_metrics_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <math.h>
13 #include <stdlib.h>
14 #include <new>
15 #include <tuple>
16 
17 #include "gtest/gtest.h"
18 #include "test/acm_random.h"
19 #include "test/util.h"
20 
21 #include "config/aom_config.h"
22 
23 #include "aom_dsp/psnr.h"
24 #include "aom_dsp/ssim.h"
25 #include "aom_ports/mem.h"
26 #include "aom_scale/yv12config.h"
27 
28 using libaom_test::ACMRandom;
29 
30 namespace {
31 
32 typedef double (*LBDMetricFunc)(const YV12_BUFFER_CONFIG *source,
33                                 const YV12_BUFFER_CONFIG *dest);
34 typedef double (*HBDMetricFunc)(const YV12_BUFFER_CONFIG *source,
35                                 const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
36                                 uint32_t bd);
37 
compute_hbd_psnr(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest,uint32_t in_bd,uint32_t bd)38 double compute_hbd_psnr(const YV12_BUFFER_CONFIG *source,
39                         const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
40                         uint32_t bd) {
41   PSNR_STATS psnr;
42   aom_calc_highbd_psnr(source, dest, &psnr, bd, in_bd);
43   return psnr.psnr[0];
44 }
45 
compute_psnr(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest)46 double compute_psnr(const YV12_BUFFER_CONFIG *source,
47                     const YV12_BUFFER_CONFIG *dest) {
48   PSNR_STATS psnr;
49   aom_calc_psnr(source, dest, &psnr);
50   return psnr.psnr[0];
51 }
52 
compute_hbd_psnrhvs(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest,uint32_t in_bd,uint32_t bd)53 double compute_hbd_psnrhvs(const YV12_BUFFER_CONFIG *source,
54                            const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
55                            uint32_t bd) {
56   double tempy, tempu, tempv;
57   return aom_psnrhvs(source, dest, &tempy, &tempu, &tempv, bd, in_bd);
58 }
59 
compute_psnrhvs(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest)60 double compute_psnrhvs(const YV12_BUFFER_CONFIG *source,
61                        const YV12_BUFFER_CONFIG *dest) {
62   double tempy, tempu, tempv;
63   return aom_psnrhvs(source, dest, &tempy, &tempu, &tempv, 8, 8);
64 }
65 
compute_hbd_fastssim(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest,uint32_t in_bd,uint32_t bd)66 double compute_hbd_fastssim(const YV12_BUFFER_CONFIG *source,
67                             const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
68                             uint32_t bd) {
69   double tempy, tempu, tempv;
70   return aom_calc_fastssim(source, dest, &tempy, &tempu, &tempv, bd, in_bd);
71 }
72 
compute_fastssim(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest)73 double compute_fastssim(const YV12_BUFFER_CONFIG *source,
74                         const YV12_BUFFER_CONFIG *dest) {
75   double tempy, tempu, tempv;
76   return aom_calc_fastssim(source, dest, &tempy, &tempu, &tempv, 8, 8);
77 }
78 
compute_hbd_aomssim(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest,uint32_t in_bd,uint32_t bd)79 double compute_hbd_aomssim(const YV12_BUFFER_CONFIG *source,
80                            const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
81                            uint32_t bd) {
82   double ssim[2], weight[2];
83   aom_highbd_calc_ssim(source, dest, weight, bd, in_bd, ssim);
84   return 100 * pow(ssim[0] / weight[0], 8.0);
85 }
86 
compute_aomssim(const YV12_BUFFER_CONFIG * source,const YV12_BUFFER_CONFIG * dest)87 double compute_aomssim(const YV12_BUFFER_CONFIG *source,
88                        const YV12_BUFFER_CONFIG *dest) {
89   double ssim, weight;
90   aom_lowbd_calc_ssim(source, dest, &weight, &ssim);
91   return 100 * pow(ssim / weight, 8.0);
92 }
93 
94 class HBDMetricsTestBase {
95  public:
96   virtual ~HBDMetricsTestBase() = default;
97 
98  protected:
RunAccuracyCheck()99   void RunAccuracyCheck() {
100     const int width = 1920;
101     const int height = 1080;
102     size_t i = 0;
103     const uint8_t kPixFiller = 128;
104     YV12_BUFFER_CONFIG lbd_src, lbd_dst;
105     YV12_BUFFER_CONFIG hbd_src, hbd_dst;
106     ACMRandom rnd(ACMRandom::DeterministicSeed());
107     double lbd_db, hbd_db;
108 
109     memset(&lbd_src, 0, sizeof(lbd_src));
110     memset(&lbd_dst, 0, sizeof(lbd_dst));
111     memset(&hbd_src, 0, sizeof(hbd_src));
112     memset(&hbd_dst, 0, sizeof(hbd_dst));
113 
114     aom_alloc_frame_buffer(&lbd_src, width, height, 1, 1, 0, 32, 16, false, 0);
115     aom_alloc_frame_buffer(&lbd_dst, width, height, 1, 1, 0, 32, 16, false, 0);
116     aom_alloc_frame_buffer(&hbd_src, width, height, 1, 1, 1, 32, 16, false, 0);
117     aom_alloc_frame_buffer(&hbd_dst, width, height, 1, 1, 1, 32, 16, false, 0);
118 
119     memset(lbd_src.buffer_alloc, kPixFiller, lbd_src.buffer_alloc_sz);
120     while (i < lbd_src.buffer_alloc_sz) {
121       uint16_t spel, dpel;
122       spel = lbd_src.buffer_alloc[i];
123       // Create some distortion for dst buffer.
124       dpel = rnd.Rand8();
125       lbd_dst.buffer_alloc[i] = (uint8_t)dpel;
126       ((uint16_t *)(hbd_src.buffer_alloc))[i] = spel << (bit_depth_ - 8);
127       ((uint16_t *)(hbd_dst.buffer_alloc))[i] = dpel << (bit_depth_ - 8);
128       i++;
129     }
130 
131     lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
132     hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
133     EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
134 
135     i = 0;
136     while (i < lbd_src.buffer_alloc_sz) {
137       uint16_t dpel;
138       // Create some small distortion for dst buffer.
139       dpel = 120 + (rnd.Rand8() >> 4);
140       lbd_dst.buffer_alloc[i] = (uint8_t)dpel;
141       ((uint16_t *)(hbd_dst.buffer_alloc))[i] = dpel << (bit_depth_ - 8);
142       i++;
143     }
144 
145     lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
146     hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
147     EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
148 
149     i = 0;
150     while (i < lbd_src.buffer_alloc_sz) {
151       uint16_t dpel;
152       // Create some small distortion for dst buffer.
153       dpel = 126 + (rnd.Rand8() >> 6);
154       lbd_dst.buffer_alloc[i] = (uint8_t)dpel;
155       ((uint16_t *)(hbd_dst.buffer_alloc))[i] = dpel << (bit_depth_ - 8);
156       i++;
157     }
158 
159     lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
160     hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
161     EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
162 
163     aom_free_frame_buffer(&lbd_src);
164     aom_free_frame_buffer(&lbd_dst);
165     aom_free_frame_buffer(&hbd_src);
166     aom_free_frame_buffer(&hbd_dst);
167   }
168 
169   int input_bit_depth_;
170   int bit_depth_;
171   double threshold_;
172   LBDMetricFunc lbd_metric_;
173   HBDMetricFunc hbd_metric_;
174 };
175 
176 typedef std::tuple<LBDMetricFunc, HBDMetricFunc, int, int, double>
177     MetricTestTParam;
178 class HBDMetricsTest : public HBDMetricsTestBase,
179                        public ::testing::TestWithParam<MetricTestTParam> {
180  public:
SetUp()181   void SetUp() override {
182     lbd_metric_ = GET_PARAM(0);
183     hbd_metric_ = GET_PARAM(1);
184     input_bit_depth_ = GET_PARAM(2);
185     bit_depth_ = GET_PARAM(3);
186     threshold_ = GET_PARAM(4);
187   }
188 };
189 
TEST_P(HBDMetricsTest,RunAccuracyCheck)190 TEST_P(HBDMetricsTest, RunAccuracyCheck) { RunAccuracyCheck(); }
191 
192 // Allow small variation due to floating point operations.
193 static const double kSsim_thresh = 0.001;
194 // Allow some additional errors accumulated in floating point operations.
195 static const double kFSsim_thresh = 0.03;
196 // Allow some extra variation due to rounding error accumulated in dct.
197 static const double kPhvs_thresh = 0.3;
198 
199 INSTANTIATE_TEST_SUITE_P(
200     AOMSSIM, HBDMetricsTest,
201     ::testing::Values(MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
202                                        8, 10, kSsim_thresh),
203                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
204                                        10, 10, kPhvs_thresh),
205                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
206                                        8, 12, kSsim_thresh),
207                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
208                                        12, 12, kPhvs_thresh)));
209 INSTANTIATE_TEST_SUITE_P(
210     FASTSSIM, HBDMetricsTest,
211     ::testing::Values(MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
212                                        8, 10, kFSsim_thresh),
213                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
214                                        10, 10, kFSsim_thresh),
215                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
216                                        8, 12, kFSsim_thresh),
217                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
218                                        12, 12, kFSsim_thresh)));
219 INSTANTIATE_TEST_SUITE_P(
220     PSNRHVS, HBDMetricsTest,
221     ::testing::Values(MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
222                                        8, 10, kPhvs_thresh),
223                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
224                                        10, 10, kPhvs_thresh),
225                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
226                                        8, 12, kPhvs_thresh),
227                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
228                                        12, 12, kPhvs_thresh)));
229 INSTANTIATE_TEST_SUITE_P(
230     PSNR, HBDMetricsTest,
231     ::testing::Values(
232         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 10, kPhvs_thresh),
233         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 10, 10,
234                          kPhvs_thresh),
235         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 12, kPhvs_thresh),
236         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 12, 12,
237                          kPhvs_thresh)));
238 }  // namespace
239