Home | History | Annotate | Download | only in test
      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 
     16 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
     17 #include "test/acm_random.h"
     18 #include "test/util.h"
     19 
     20 #include "config/aom_config.h"
     21 
     22 #include "aom_dsp/psnr.h"
     23 #include "aom_dsp/ssim.h"
     24 #include "aom_ports/mem.h"
     25 #include "aom_ports/msvc.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 
     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 
     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 
     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 
     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 
     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 
     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 
     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, weight;
     83   ssim = aom_highbd_calc_ssim(source, dest, &weight, bd, in_bd);
     84   return 100 * pow(ssim / weight, 8.0);
     85 }
     86 
     87 double compute_aomssim(const YV12_BUFFER_CONFIG *source,
     88                        const YV12_BUFFER_CONFIG *dest) {
     89   double ssim, weight;
     90   ssim = aom_calc_ssim(source, dest, &weight);
     91   return 100 * pow(ssim / weight, 8.0);
     92 }
     93 
     94 class HBDMetricsTestBase {
     95  public:
     96   virtual ~HBDMetricsTestBase() {}
     97 
     98  protected:
     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);
    115     aom_alloc_frame_buffer(&lbd_dst, width, height, 1, 1, 0, 32, 16);
    116     aom_alloc_frame_buffer(&hbd_src, width, height, 1, 1, 1, 32, 16);
    117     aom_alloc_frame_buffer(&hbd_dst, width, height, 1, 1, 1, 32, 16);
    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 ::testing::tuple<LBDMetricFunc, HBDMetricFunc, int, int, double>
    177     MetricTestTParam;
    178 class HBDMetricsTest : public HBDMetricsTestBase,
    179                        public ::testing::TestWithParam<MetricTestTParam> {
    180  public:
    181   virtual void SetUp() {
    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   virtual void TearDown() {}
    189 };
    190 
    191 TEST_P(HBDMetricsTest, RunAccuracyCheck) { RunAccuracyCheck(); }
    192 
    193 // Allow small variation due to floating point operations.
    194 static const double kSsim_thresh = 0.001;
    195 // Allow some additional errors accumulated in floating point operations.
    196 static const double kFSsim_thresh = 0.03;
    197 // Allow some extra variation due to rounding error accumulated in dct.
    198 static const double kPhvs_thresh = 0.3;
    199 
    200 INSTANTIATE_TEST_CASE_P(
    201     AOMSSIM, HBDMetricsTest,
    202     ::testing::Values(MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
    203                                        8, 10, kSsim_thresh),
    204                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
    205                                        10, 10, kPhvs_thresh),
    206                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
    207                                        8, 12, kSsim_thresh),
    208                       MetricTestTParam(&compute_aomssim, &compute_hbd_aomssim,
    209                                        12, 12, kPhvs_thresh)));
    210 INSTANTIATE_TEST_CASE_P(
    211     FASTSSIM, HBDMetricsTest,
    212     ::testing::Values(MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
    213                                        8, 10, kFSsim_thresh),
    214                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
    215                                        10, 10, kFSsim_thresh),
    216                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
    217                                        8, 12, kFSsim_thresh),
    218                       MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim,
    219                                        12, 12, kFSsim_thresh)));
    220 INSTANTIATE_TEST_CASE_P(
    221     PSNRHVS, HBDMetricsTest,
    222     ::testing::Values(MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
    223                                        8, 10, kPhvs_thresh),
    224                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
    225                                        10, 10, kPhvs_thresh),
    226                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
    227                                        8, 12, kPhvs_thresh),
    228                       MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs,
    229                                        12, 12, kPhvs_thresh)));
    230 INSTANTIATE_TEST_CASE_P(
    231     PSNR, HBDMetricsTest,
    232     ::testing::Values(
    233         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 10, kPhvs_thresh),
    234         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 10, 10,
    235                          kPhvs_thresh),
    236         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 12, kPhvs_thresh),
    237         MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 12, 12,
    238                          kPhvs_thresh)));
    239 }  // namespace
    240