tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

frame_resize_test.cc (9314B)


      1 /*
      2 * Copyright (c) 2024, 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 <memory>
     13 #include <new>
     14 
     15 #include "config/av1_rtcd.h"
     16 #include "aom_ports/aom_timer.h"
     17 #include "aom_ports/bitops.h"
     18 #include "gtest/gtest.h"
     19 #include "test/acm_random.h"
     20 #include "test/util.h"
     21 
     22 namespace {
     23 
     24 using ::testing::Combine;
     25 using ::testing::Values;
     26 using ::testing::ValuesIn;
     27 
     28 using std::make_tuple;
     29 using std::tuple;
     30 
     31 const int kIters = 1000;
     32 
     33 using FrameDimension = tuple<int, int>;
     34 
     35 // Check that two 8-bit output buffers are identical.
     36 void AssertOutputBufferEq(const uint8_t *p1, const uint8_t *p2, int width,
     37                          int height) {
     38  ASSERT_TRUE(p1 != p2) << "Buffers must be at different memory locations";
     39  for (int j = 0; j < height; ++j) {
     40    if (memcmp(p1, p2, sizeof(*p1) * width) == 0) {
     41      p1 += width;
     42      p2 += width;
     43      continue;
     44    }
     45    for (int i = 0; i < width; ++i) {
     46      ASSERT_EQ(p1[i], p2[i])
     47          << width << "x" << height << " Pixel mismatch at (" << i << ", " << j
     48          << ")";
     49    }
     50  }
     51 }
     52 
     53 using LowBDResizeFunc = bool (*)(uint8_t *intbuf, uint8_t *output,
     54                                 int out_stride, int height, int height2,
     55                                 int stride, int start_wd);
     56 // Test parameter list:
     57 //  <tst_fun, dims>
     58 using ResizeTestParams = tuple<LowBDResizeFunc, FrameDimension>;
     59 
     60 class AV1ResizeYTest : public ::testing::TestWithParam<ResizeTestParams> {
     61 public:
     62  void SetUp() {
     63    test_fun_ = GET_PARAM(0);
     64    frame_dim_ = GET_PARAM(1);
     65    width_ = std::get<0>(frame_dim_);
     66    height_ = std::get<1>(frame_dim_);
     67    const int msb = get_msb(AOMMIN(width_, height_));
     68    n_levels_ = AOMMAX(msb - MIN_PYRAMID_SIZE_LOG2, 1);
     69    const int src_buf_size = (width_ / 2) * height_;
     70    const int dest_buf_size = (width_ * height_) / 4;
     71    src_ = std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[src_buf_size]);
     72    ASSERT_NE(src_, nullptr);
     73 
     74    ref_dest_ =
     75        std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[dest_buf_size]);
     76    ASSERT_NE(ref_dest_, nullptr);
     77 
     78    test_dest_ =
     79        std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[dest_buf_size]);
     80    ASSERT_NE(test_dest_, nullptr);
     81  }
     82 
     83  void RunTest() {
     84    for (int i = 0; i < (width_ / 2) * height_; i++) src_[i] = rng_.Rand8();
     85    for (int level = 1; level < n_levels_; level++) {
     86      const int width2 = (width_ >> level);
     87      const int height2 = (height_ >> level);
     88      av1_resize_vert_dir_c(src_.get(), ref_dest_.get(), width2, height2 << 1,
     89                            height2, width2, 0);
     90      test_fun_(src_.get(), test_dest_.get(), width2, height2 << 1, height2,
     91                width2, 0);
     92 
     93      AssertOutputBufferEq(ref_dest_.get(), test_dest_.get(), width2, height2);
     94    }
     95  }
     96 
     97  void SpeedTest() {
     98    for (int i = 0; i < (width_ / 2) * height_; i++) src_[i] = rng_.Rand8();
     99    for (int level = 1; level < n_levels_; level++) {
    100      const int width2 = (width_ >> level);
    101      const int height2 = (height_ >> level);
    102      aom_usec_timer ref_timer;
    103      aom_usec_timer_start(&ref_timer);
    104      for (int j = 0; j < kIters; j++) {
    105        av1_resize_vert_dir_c(src_.get(), ref_dest_.get(), width2, height2 << 1,
    106                              height2, width2, 0);
    107      }
    108      aom_usec_timer_mark(&ref_timer);
    109      const int64_t ref_time = aom_usec_timer_elapsed(&ref_timer);
    110 
    111      aom_usec_timer tst_timer;
    112      aom_usec_timer_start(&tst_timer);
    113      for (int j = 0; j < kIters; j++) {
    114        test_fun_(src_.get(), test_dest_.get(), width2, height2 << 1, height2,
    115                  width2, 0);
    116      }
    117      aom_usec_timer_mark(&tst_timer);
    118      const int64_t tst_time = aom_usec_timer_elapsed(&tst_timer);
    119 
    120      std::cout << "level: " << level << " [" << width2 << " x " << height2
    121                << "] C time = " << ref_time << " , SIMD time = " << tst_time
    122                << " scaling=" << float(1.00) * ref_time / tst_time << "x \n";
    123    }
    124  }
    125 
    126 private:
    127  LowBDResizeFunc test_fun_;
    128  FrameDimension frame_dim_;
    129  int width_;
    130  int height_;
    131  int n_levels_;
    132  std::unique_ptr<uint8_t[]> src_;
    133  std::unique_ptr<uint8_t[]> ref_dest_;
    134  std::unique_ptr<uint8_t[]> test_dest_;
    135  libaom_test::ACMRandom rng_;
    136 };
    137 
    138 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1ResizeYTest);
    139 
    140 TEST_P(AV1ResizeYTest, RunTest) { RunTest(); }
    141 
    142 TEST_P(AV1ResizeYTest, DISABLED_SpeedTest) { SpeedTest(); }
    143 
    144 #if HAVE_AVX2 || HAVE_SSE2
    145 // Resolutions (width x height) to be tested for resizing.
    146 const FrameDimension kFrameDim[] = {
    147  make_tuple(3840, 2160), make_tuple(2560, 1440), make_tuple(1920, 1080),
    148  make_tuple(1280, 720),  make_tuple(640, 480),   make_tuple(640, 360),
    149  make_tuple(286, 286),   make_tuple(284, 284),   make_tuple(282, 282),
    150  make_tuple(280, 280),   make_tuple(262, 262),   make_tuple(258, 258),
    151  make_tuple(256, 256),   make_tuple(34, 34),
    152 };
    153 #endif
    154 
    155 #if HAVE_AVX2
    156 INSTANTIATE_TEST_SUITE_P(
    157    AVX2, AV1ResizeYTest,
    158    ::testing::Combine(::testing::Values(av1_resize_vert_dir_avx2),
    159                       ::testing::ValuesIn(kFrameDim)));
    160 #endif
    161 
    162 #if HAVE_SSE2
    163 INSTANTIATE_TEST_SUITE_P(
    164    SSE2, AV1ResizeYTest,
    165    ::testing::Combine(::testing::Values(av1_resize_vert_dir_sse2),
    166                       ::testing::ValuesIn(kFrameDim)));
    167 #endif
    168 
    169 using LowBDResize_x_Func = void (*)(const uint8_t *const input, int in_stride,
    170                                    uint8_t *intbuf, int height,
    171                                    int filtered_length, int width2);
    172 
    173 using Resize_x_TestParams = tuple<LowBDResize_x_Func, FrameDimension>;
    174 
    175 class AV1ResizeXTest : public ::testing::TestWithParam<Resize_x_TestParams> {
    176 public:
    177  void SetUp() {
    178    test_fun_ = GET_PARAM(0);
    179    frame_dim_ = GET_PARAM(1);
    180    width_ = std::get<0>(frame_dim_);
    181    height_ = std::get<1>(frame_dim_);
    182    const int msb = get_msb(AOMMIN(width_, height_));
    183    n_levels_ = AOMMAX(msb - MIN_PYRAMID_SIZE_LOG2, 1);
    184    const int src_buf_size = width_ * height_;
    185    const int dest_buf_size = (width_ * height_) / 2;
    186    src_ = std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[src_buf_size]);
    187    ASSERT_NE(src_, nullptr);
    188 
    189    ref_dest_ =
    190        std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[dest_buf_size]);
    191    ASSERT_NE(ref_dest_, nullptr);
    192 
    193    test_dest_ =
    194        std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[dest_buf_size]);
    195    ASSERT_NE(test_dest_, nullptr);
    196  }
    197 
    198  void RunTest() {
    199    for (int i = 0; i < width_ * height_; ++i) src_[i] = rng_.Rand8();
    200 
    201    for (int level = 1; level < n_levels_; ++level) {
    202      const int width2 = (width_ >> level);
    203      av1_resize_horz_dir_c(src_.get(), width_, ref_dest_.get(), height_,
    204                            width2 << 1, width2);
    205      test_fun_(src_.get(), width_, test_dest_.get(), height_, width2 << 1,
    206                width2);
    207      AssertOutputBufferEq(ref_dest_.get(), test_dest_.get(), width2, height_);
    208    }
    209  }
    210 
    211  void SpeedTest() {
    212    for (int i = 0; i < width_ * height_; ++i) src_[i] = rng_.Rand8();
    213 
    214    for (int level = 1; level < n_levels_; ++level) {
    215      const int width2 = (width_ >> level);
    216      aom_usec_timer ref_timer;
    217      aom_usec_timer_start(&ref_timer);
    218      for (int j = 0; j < kIters; ++j) {
    219        av1_resize_horz_dir_c(src_.get(), width_, ref_dest_.get(), height_,
    220                              width2 << 1, width2);
    221      }
    222      aom_usec_timer_mark(&ref_timer);
    223      const int64_t ref_time = aom_usec_timer_elapsed(&ref_timer);
    224 
    225      aom_usec_timer tst_timer;
    226      aom_usec_timer_start(&tst_timer);
    227      for (int j = 0; j < kIters; ++j) {
    228        test_fun_(src_.get(), width_, test_dest_.get(), height_, width2 << 1,
    229                  width2);
    230      }
    231      aom_usec_timer_mark(&tst_timer);
    232      const int64_t tst_time = aom_usec_timer_elapsed(&tst_timer);
    233 
    234      std::cout << "level: " << level << " [" << width2 << " x " << height_
    235                << "] C time = " << ref_time << " , SIMD time = " << tst_time
    236                << " scaling=" << float(1.00) * ref_time / tst_time << "x \n";
    237    }
    238  }
    239 
    240 private:
    241  LowBDResize_x_Func test_fun_;
    242  FrameDimension frame_dim_;
    243  int width_;
    244  int height_;
    245  int n_levels_;
    246  std::unique_ptr<uint8_t[]> src_;
    247  std::unique_ptr<uint8_t[]> ref_dest_;
    248  std::unique_ptr<uint8_t[]> test_dest_;
    249  libaom_test::ACMRandom rng_;
    250 };
    251 
    252 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1ResizeXTest);
    253 
    254 TEST_P(AV1ResizeXTest, RunTest) { RunTest(); }
    255 
    256 TEST_P(AV1ResizeXTest, DISABLED_SpeedTest) { SpeedTest(); }
    257 
    258 #if HAVE_SSE2
    259 INSTANTIATE_TEST_SUITE_P(
    260    SSE2, AV1ResizeXTest,
    261    ::testing::Combine(::testing::Values(av1_resize_horz_dir_sse2),
    262                       ::testing::ValuesIn(kFrameDim)));
    263 #endif
    264 
    265 #if HAVE_AVX2
    266 INSTANTIATE_TEST_SUITE_P(
    267    AVX2, AV1ResizeXTest,
    268    ::testing::Combine(::testing::Values(av1_resize_horz_dir_avx2),
    269                       ::testing::ValuesIn(kFrameDim)));
    270 #endif
    271 
    272 }  // namespace