selfguided_filter_test.cc 8.76 KB
Newer Older
David Barker's avatar
David Barker committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include <ctime>

#include "third_party/googletest/src/googletest/include/gtest/gtest.h"

#include "./av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"

#include "av1/common/mv.h"
#include "av1/common/restoration.h"

namespace {

using std::tr1::tuple;
using std::tr1::make_tuple;
using libaom_test::ACMRandom;

typedef tuple<> FilterTestParam;

class AV1SelfguidedFilterTest
    : public ::testing::TestWithParam<FilterTestParam> {
 public:
  virtual ~AV1SelfguidedFilterTest() {}
  virtual void SetUp() {}

  virtual void TearDown() { libaom_test::ClearSystemState(); }

 protected:
  void RunSpeedTest() {
    const int w = 256, h = 256;
    const int NUM_ITERS = 2000;
    int i, j;

    uint8_t *input = new uint8_t[w * h];
    uint8_t *output = new uint8_t[w * h];
    int32_t *tmpbuf = (int32_t *)aom_malloc(RESTORATION_TMPBUF_SIZE);
    memset(tmpbuf, 0, RESTORATION_TMPBUF_SIZE);

    ACMRandom rnd(ACMRandom::DeterministicSeed());

    for (i = 0; i < h; ++i)
      for (j = 0; j < w; ++j) input[i * w + j] = rnd.Rand16() & 0xFF;

    int xqd[2] = {
      SGRPROJ_PRJ_MIN0 +
          rnd.PseudoUniform(SGRPROJ_PRJ_MAX0 + 1 - SGRPROJ_PRJ_MIN0),
      SGRPROJ_PRJ_MIN1 +
          rnd.PseudoUniform(SGRPROJ_PRJ_MAX1 + 1 - SGRPROJ_PRJ_MIN1)
    };
    // Fix a parameter set, since the speed depends slightly on r.
    // Change this to test different combinations of values of r.
65
    int eps = 15;
David Barker's avatar
David Barker committed
66 67 68 69 70

    av1_loop_restoration_precal();

    std::clock_t start = std::clock();
    for (i = 0; i < NUM_ITERS; ++i) {
71
      apply_selfguided_restoration(input, w, h, w, eps, xqd, output, w, tmpbuf);
David Barker's avatar
David Barker committed
72 73 74 75 76 77 78 79 80 81 82 83 84
    }
    std::clock_t end = std::clock();
    double elapsed = ((end - start) / (double)CLOCKS_PER_SEC);

    printf("%5d %dx%d blocks in %7.3fs = %7.3fus/block\n", NUM_ITERS, w, h,
           elapsed, elapsed * 1000000. / NUM_ITERS);

    aom_free(tmpbuf);
    delete[] input;
    delete[] output;
  }

  void RunCorrectnessTest() {
David Barker's avatar
David Barker committed
85 86 87 88
    // Set the maximum width/height to test here. We actually test a small
    // range of sizes *up to* this size, so that we can check, eg.,
    // the behaviour on tiles which are not a multiple of 4 wide.
    const int max_w = 260, max_h = 260, stride = 672, out_stride = 672;
89
    const int NUM_ITERS = 81;
David Barker's avatar
David Barker committed
90 91
    int i, j, k;

David Barker's avatar
David Barker committed
92 93 94
    uint8_t *input = new uint8_t[stride * max_h];
    uint8_t *output = new uint8_t[out_stride * max_h];
    uint8_t *output2 = new uint8_t[out_stride * max_h];
David Barker's avatar
David Barker committed
95 96 97 98 99 100 101 102
    int32_t *tmpbuf = (int32_t *)aom_malloc(RESTORATION_TMPBUF_SIZE);
    memset(tmpbuf, 0, RESTORATION_TMPBUF_SIZE);

    ACMRandom rnd(ACMRandom::DeterministicSeed());

    av1_loop_restoration_precal();

    for (i = 0; i < NUM_ITERS; ++i) {
David Barker's avatar
David Barker committed
103 104
      for (j = 0; j < max_h; ++j)
        for (k = 0; k < max_w; ++k) input[j * stride + k] = rnd.Rand16() & 0xFF;
David Barker's avatar
David Barker committed
105 106 107 108 109 110 111 112 113

      int xqd[2] = {
        SGRPROJ_PRJ_MIN0 +
            rnd.PseudoUniform(SGRPROJ_PRJ_MAX0 + 1 - SGRPROJ_PRJ_MIN0),
        SGRPROJ_PRJ_MIN1 +
            rnd.PseudoUniform(SGRPROJ_PRJ_MAX1 + 1 - SGRPROJ_PRJ_MIN1)
      };
      int eps = rnd.PseudoUniform(1 << SGRPROJ_PARAMS_BITS);

114
      // Test various tile sizes around 256x256
David Barker's avatar
David Barker committed
115 116
      int test_w = max_w - (i / 9);
      int test_h = max_h - (i % 9);
117

118
      apply_selfguided_restoration(input, test_w, test_h, stride, eps, xqd,
119
                                   output, out_stride, tmpbuf);
120
      apply_selfguided_restoration_c(input, test_w, test_h, stride, eps, xqd,
121 122 123
                                     output2, out_stride, tmpbuf);
      for (j = 0; j < test_h; ++j)
        for (k = 0; k < test_w; ++k)
David Barker's avatar
David Barker committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
          ASSERT_EQ(output[j * out_stride + k], output2[j * out_stride + k]);
    }

    aom_free(tmpbuf);
    delete[] input;
    delete[] output;
    delete[] output2;
  }
};

TEST_P(AV1SelfguidedFilterTest, SpeedTest) { RunSpeedTest(); }
TEST_P(AV1SelfguidedFilterTest, CorrectnessTest) { RunCorrectnessTest(); }

const FilterTestParam params[] = { make_tuple() };

#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1SelfguidedFilterTest,
                        ::testing::ValuesIn(params));
#endif

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
#if CONFIG_AOM_HIGHBITDEPTH

typedef tuple<int> HighbdFilterTestParam;

class AV1HighbdSelfguidedFilterTest
    : public ::testing::TestWithParam<HighbdFilterTestParam> {
 public:
  virtual ~AV1HighbdSelfguidedFilterTest() {}
  virtual void SetUp() {}

  virtual void TearDown() { libaom_test::ClearSystemState(); }

 protected:
  void RunSpeedTest() {
    const int w = 256, h = 256;
    const int NUM_ITERS = 2000;
    int i, j;
    int bit_depth = GET_PARAM(0);
    int mask = (1 << bit_depth) - 1;

    uint16_t *input = new uint16_t[w * h];
    uint16_t *output = new uint16_t[w * h];
    int32_t *tmpbuf = (int32_t *)aom_malloc(RESTORATION_TMPBUF_SIZE);
    memset(tmpbuf, 0, RESTORATION_TMPBUF_SIZE);

    ACMRandom rnd(ACMRandom::DeterministicSeed());

    for (i = 0; i < h; ++i)
      for (j = 0; j < w; ++j) input[i * w + j] = rnd.Rand16() & mask;

    int xqd[2] = {
      SGRPROJ_PRJ_MIN0 +
          rnd.PseudoUniform(SGRPROJ_PRJ_MAX0 + 1 - SGRPROJ_PRJ_MIN0),
      SGRPROJ_PRJ_MIN1 +
          rnd.PseudoUniform(SGRPROJ_PRJ_MAX1 + 1 - SGRPROJ_PRJ_MIN1)
    };
    // Fix a parameter set, since the speed depends slightly on r.
    // Change this to test different combinations of values of r.
    int eps = 15;

    av1_loop_restoration_precal();

    std::clock_t start = std::clock();
    for (i = 0; i < NUM_ITERS; ++i) {
      apply_selfguided_restoration_highbd(input, w, h, w, bit_depth, eps, xqd,
                                          output, w, tmpbuf);
    }
    std::clock_t end = std::clock();
    double elapsed = ((end - start) / (double)CLOCKS_PER_SEC);

    printf("%5d %dx%d blocks in %7.3fs = %7.3fus/block\n", NUM_ITERS, w, h,
           elapsed, elapsed * 1000000. / NUM_ITERS);

    aom_free(tmpbuf);
    delete[] input;
    delete[] output;
  }

  void RunCorrectnessTest() {
David Barker's avatar
David Barker committed
203 204 205 206
    // Set the maximum width/height to test here. We actually test a small
    // range of sizes *up to* this size, so that we can check, eg.,
    // the behaviour on tiles which are not a multiple of 4 wide.
    const int max_w = 260, max_h = 260, stride = 672, out_stride = 672;
207 208 209 210 211
    const int NUM_ITERS = 81;
    int i, j, k;
    int bit_depth = GET_PARAM(0);
    int mask = (1 << bit_depth) - 1;

David Barker's avatar
David Barker committed
212 213 214
    uint16_t *input = new uint16_t[stride * max_h];
    uint16_t *output = new uint16_t[out_stride * max_h];
    uint16_t *output2 = new uint16_t[out_stride * max_h];
215 216 217 218 219 220 221 222
    int32_t *tmpbuf = (int32_t *)aom_malloc(RESTORATION_TMPBUF_SIZE);
    memset(tmpbuf, 0, RESTORATION_TMPBUF_SIZE);

    ACMRandom rnd(ACMRandom::DeterministicSeed());

    av1_loop_restoration_precal();

    for (i = 0; i < NUM_ITERS; ++i) {
David Barker's avatar
David Barker committed
223 224
      for (j = 0; j < max_h; ++j)
        for (k = 0; k < max_w; ++k) input[j * stride + k] = rnd.Rand16() & mask;
225 226 227 228 229 230 231 232 233 234

      int xqd[2] = {
        SGRPROJ_PRJ_MIN0 +
            rnd.PseudoUniform(SGRPROJ_PRJ_MAX0 + 1 - SGRPROJ_PRJ_MIN0),
        SGRPROJ_PRJ_MIN1 +
            rnd.PseudoUniform(SGRPROJ_PRJ_MAX1 + 1 - SGRPROJ_PRJ_MIN1)
      };
      int eps = rnd.PseudoUniform(1 << SGRPROJ_PARAMS_BITS);

      // Test various tile sizes around 256x256
David Barker's avatar
David Barker committed
235 236
      int test_w = max_w - (i / 9);
      int test_h = max_h - (i % 9);
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267

      apply_selfguided_restoration_highbd(input, test_w, test_h, stride,
                                          bit_depth, eps, xqd, output,
                                          out_stride, tmpbuf);
      apply_selfguided_restoration_highbd_c(input, test_w, test_h, stride,
                                            bit_depth, eps, xqd, output2,
                                            out_stride, tmpbuf);
      for (j = 0; j < test_h; ++j)
        for (k = 0; k < test_w; ++k)
          ASSERT_EQ(output[j * out_stride + k], output2[j * out_stride + k]);
    }

    aom_free(tmpbuf);
    delete[] input;
    delete[] output;
    delete[] output2;
  }
};

TEST_P(AV1HighbdSelfguidedFilterTest, SpeedTest) { RunSpeedTest(); }
TEST_P(AV1HighbdSelfguidedFilterTest, CorrectnessTest) { RunCorrectnessTest(); }

const HighbdFilterTestParam highbd_params[] = { make_tuple(8), make_tuple(10),
                                                make_tuple(12) };

#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdSelfguidedFilterTest,
                        ::testing::ValuesIn(highbd_params));
#endif
#endif

David Barker's avatar
David Barker committed
268
}  // namespace