2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
17 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
18 #include "test/acm_random.h"
19 #include "test/util.h"
21 #include "config/aom_config.h"
23 #include "aom_dsp/psnr.h"
24 #include "aom_dsp/ssim.h"
25 #include "aom_ports/mem.h"
26 #include "aom_scale/yv12config.h"
28 using libaom_test::ACMRandom
;
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
,
38 double compute_hbd_psnr(const YV12_BUFFER_CONFIG
*source
,
39 const YV12_BUFFER_CONFIG
*dest
, uint32_t in_bd
,
42 aom_calc_highbd_psnr(source
, dest
, &psnr
, bd
, in_bd
);
46 double compute_psnr(const YV12_BUFFER_CONFIG
*source
,
47 const YV12_BUFFER_CONFIG
*dest
) {
49 aom_calc_psnr(source
, dest
, &psnr
);
53 double compute_hbd_psnrhvs(const YV12_BUFFER_CONFIG
*source
,
54 const YV12_BUFFER_CONFIG
*dest
, uint32_t in_bd
,
56 double tempy
, tempu
, tempv
;
57 return aom_psnrhvs(source
, dest
, &tempy
, &tempu
, &tempv
, bd
, in_bd
);
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);
66 double compute_hbd_fastssim(const YV12_BUFFER_CONFIG
*source
,
67 const YV12_BUFFER_CONFIG
*dest
, uint32_t in_bd
,
69 double tempy
, tempu
, tempv
;
70 return aom_calc_fastssim(source
, dest
, &tempy
, &tempu
, &tempv
, bd
, in_bd
);
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);
79 double compute_hbd_aomssim(const YV12_BUFFER_CONFIG
*source
,
80 const YV12_BUFFER_CONFIG
*dest
, uint32_t in_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);
87 double compute_aomssim(const YV12_BUFFER_CONFIG
*source
,
88 const YV12_BUFFER_CONFIG
*dest
) {
90 aom_lowbd_calc_ssim(source
, dest
, &weight
, &ssim
);
91 return 100 * pow(ssim
/ weight
, 8.0);
94 class HBDMetricsTestBase
{
96 virtual ~HBDMetricsTestBase() = default;
99 void RunAccuracyCheck() {
100 const int width
= 1920;
101 const int height
= 1080;
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
;
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
));
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);
119 memset(lbd_src
.buffer_alloc
, kPixFiller
, lbd_src
.buffer_alloc_sz
);
120 while (i
< lbd_src
.buffer_alloc_sz
) {
122 spel
= lbd_src
.buffer_alloc
[i
];
123 // Create some distortion for dst buffer.
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);
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_
);
136 while (i
< lbd_src
.buffer_alloc_sz
) {
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);
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_
);
150 while (i
< lbd_src
.buffer_alloc_sz
) {
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);
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_
);
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
);
169 int input_bit_depth_
;
172 LBDMetricFunc lbd_metric_
;
173 HBDMetricFunc hbd_metric_
;
176 typedef std::tuple
<LBDMetricFunc
, HBDMetricFunc
, int, int, double>
178 class HBDMetricsTest
: public HBDMetricsTestBase
,
179 public ::testing::TestWithParam
<MetricTestTParam
> {
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);
190 TEST_P(HBDMetricsTest
, RunAccuracyCheck
) { RunAccuracyCheck(); }
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;
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
,
232 MetricTestTParam(&compute_psnr
, &compute_hbd_psnr
, 8, 10, kPhvs_thresh
),
233 MetricTestTParam(&compute_psnr
, &compute_hbd_psnr
, 10, 10,
235 MetricTestTParam(&compute_psnr
, &compute_hbd_psnr
, 8, 12, kPhvs_thresh
),
236 MetricTestTParam(&compute_psnr
, &compute_hbd_psnr
, 12, 12,