lpf_8_test.cc 27.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <cmath>
#include <cstdlib>
#include <string>

#include "third_party/googletest/src/include/gtest/gtest.h"
16 17 18

#include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h"
19 20 21 22 23
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "vp9/common/vp9_entropy.h"
Deb Mukherjee's avatar
Deb Mukherjee committed
24
#include "vp9/common/vp9_loopfilter.h"
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
#include "vpx/vpx_integer.h"

using libvpx_test::ACMRandom;

namespace {
// Horizontally and Vertically need 32x32: 8  Coeffs preceeding filtered section
//                                         16 Coefs within filtered section
//                                         8  Coeffs following filtered section
const int kNumCoeffs = 1024;

const int number_of_iterations = 10000;

#if CONFIG_VP9_HIGHBITDEPTH
typedef void (*loop_op_t)(uint16_t *s, int p, const uint8_t *blimit,
                          const uint8_t *limit, const uint8_t *thresh,
                          int count, int bd);
typedef void (*dual_loop_op_t)(uint16_t *s, int p, const uint8_t *blimit0,
                               const uint8_t *limit0, const uint8_t *thresh0,
                               const uint8_t *blimit1, const uint8_t *limit1,
                               const uint8_t *thresh1, int bd);
#else
typedef void (*loop_op_t)(uint8_t *s, int p, const uint8_t *blimit,
                          const uint8_t *limit, const uint8_t *thresh,
                          int count);
typedef void (*dual_loop_op_t)(uint8_t *s, int p, const uint8_t *blimit0,
                               const uint8_t *limit0, const uint8_t *thresh0,
                               const uint8_t *blimit1, const uint8_t *limit1,
                               const uint8_t *thresh1);
#endif  // CONFIG_VP9_HIGHBITDEPTH

Ed Baker's avatar
Ed Baker committed
55
typedef std::tr1::tuple<loop_op_t, loop_op_t, int, int> loop8_param_t;
56 57 58 59 60 61 62
typedef std::tr1::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t;

#if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH
void wrapper_vertical_16_sse2(uint16_t *s, int p, const uint8_t *blimit,
                              const uint8_t *limit, const uint8_t *thresh,
                              int count, int bd) {
63
  vpx_highbd_lpf_vertical_16_sse2(s, p, blimit, limit, thresh, bd);
64 65 66 67 68
}

void wrapper_vertical_16_c(uint16_t *s, int p, const uint8_t *blimit,
                           const uint8_t *limit, const uint8_t *thresh,
                           int count, int bd) {
69
  vpx_highbd_lpf_vertical_16_c(s, p, blimit, limit, thresh, bd);
70 71 72 73 74
}

void wrapper_vertical_16_dual_sse2(uint16_t *s, int p, const uint8_t *blimit,
                                   const uint8_t *limit, const uint8_t *thresh,
                                   int count, int bd) {
75
  vpx_highbd_lpf_vertical_16_dual_sse2(s, p, blimit, limit, thresh, bd);
76 77 78 79 80
}

void wrapper_vertical_16_dual_c(uint16_t *s, int p, const uint8_t *blimit,
                                const uint8_t *limit, const uint8_t *thresh,
                                int count, int bd) {
81
  vpx_highbd_lpf_vertical_16_dual_c(s, p, blimit, limit, thresh, bd);
82 83 84 85 86
}
#else
void wrapper_vertical_16_sse2(uint8_t *s, int p, const uint8_t *blimit,
                              const uint8_t *limit, const uint8_t *thresh,
                              int count) {
87
  vpx_lpf_vertical_16_sse2(s, p, blimit, limit, thresh);
88 89 90 91 92
}

void wrapper_vertical_16_c(uint8_t *s, int p, const uint8_t *blimit,
                           const uint8_t *limit, const uint8_t *thresh,
                           int count) {
93
  vpx_lpf_vertical_16_c(s, p, blimit, limit, thresh);
94 95 96 97 98
}

void wrapper_vertical_16_dual_sse2(uint8_t *s, int p, const uint8_t *blimit,
                                   const uint8_t *limit, const uint8_t *thresh,
                                   int count) {
99
  vpx_lpf_vertical_16_dual_sse2(s, p, blimit, limit, thresh);
100 101 102 103 104
}

void wrapper_vertical_16_dual_c(uint8_t *s, int p, const uint8_t *blimit,
                                const uint8_t *limit, const uint8_t *thresh,
                                int count) {
105
  vpx_lpf_vertical_16_dual_c(s, p, blimit, limit, thresh);
106 107 108 109
}
#endif  // CONFIG_VP9_HIGHBITDEPTH
#endif  // HAVE_SSE2

110 111 112 113 114 115 116
#if HAVE_NEON_ASM
#if CONFIG_VP9_HIGHBITDEPTH
// No neon high bitdepth functions.
#else
void wrapper_vertical_16_neon(uint8_t *s, int p, const uint8_t *blimit,
                              const uint8_t *limit, const uint8_t *thresh,
                              int count) {
117
  vpx_lpf_vertical_16_neon(s, p, blimit, limit, thresh);
118 119 120 121 122
}

void wrapper_vertical_16_c(uint8_t *s, int p, const uint8_t *blimit,
                           const uint8_t *limit, const uint8_t *thresh,
                           int count) {
123
  vpx_lpf_vertical_16_c(s, p, blimit, limit, thresh);
124 125 126 127 128
}

void wrapper_vertical_16_dual_neon(uint8_t *s, int p, const uint8_t *blimit,
                                   const uint8_t *limit, const uint8_t *thresh,
                                   int count) {
129
  vpx_lpf_vertical_16_dual_neon(s, p, blimit, limit, thresh);
130 131 132 133 134
}

void wrapper_vertical_16_dual_c(uint8_t *s, int p, const uint8_t *blimit,
                                const uint8_t *limit, const uint8_t *thresh,
                                int count) {
135
  vpx_lpf_vertical_16_dual_c(s, p, blimit, limit, thresh);
136 137 138 139
}
#endif  // CONFIG_VP9_HIGHBITDEPTH
#endif  // HAVE_NEON_ASM

140 141 142 143
#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
void wrapper_vertical_16_msa(uint8_t *s, int p, const uint8_t *blimit,
                             const uint8_t *limit, const uint8_t *thresh,
                             int count) {
144
  vpx_lpf_vertical_16_msa(s, p, blimit, limit, thresh);
145 146 147 148 149
}

void wrapper_vertical_16_c(uint8_t *s, int p, const uint8_t *blimit,
                           const uint8_t *limit, const uint8_t *thresh,
                           int count) {
150
  vpx_lpf_vertical_16_c(s, p, blimit, limit, thresh);
151 152 153
}
#endif  // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)

154 155 156 157 158 159 160
class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> {
 public:
  virtual ~Loop8Test6Param() {}
  virtual void SetUp() {
    loopfilter_op_ = GET_PARAM(0);
    ref_loopfilter_op_ = GET_PARAM(1);
    bit_depth_ = GET_PARAM(2);
Ed Baker's avatar
Ed Baker committed
161
    count_ = GET_PARAM(3);
162 163 164 165 166 167 168
    mask_ = (1 << bit_depth_) - 1;
  }

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

 protected:
  int bit_depth_;
Ed Baker's avatar
Ed Baker committed
169
  int count_;
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
  int mask_;
  loop_op_t loopfilter_op_;
  loop_op_t ref_loopfilter_op_;
};

class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> {
 public:
  virtual ~Loop8Test9Param() {}
  virtual void SetUp() {
    loopfilter_op_ = GET_PARAM(0);
    ref_loopfilter_op_ = GET_PARAM(1);
    bit_depth_ = GET_PARAM(2);
    mask_ = (1 << bit_depth_) - 1;
  }

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

 protected:
  int bit_depth_;
  int mask_;
  dual_loop_op_t loopfilter_op_;
  dual_loop_op_t ref_loopfilter_op_;
};

TEST_P(Loop8Test6Param, OperationCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  const int count_test_block = number_of_iterations;
#if CONFIG_VP9_HIGHBITDEPTH
  int32_t bd = bit_depth_;
199 200
  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
201
#else
202 203
  DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
204 205 206 207 208
#endif  // CONFIG_VP9_HIGHBITDEPTH
  int err_count_total = 0;
  int first_failure = -1;
  for (int i = 0; i < count_test_block; ++i) {
    int err_count = 0;
Deb Mukherjee's avatar
Deb Mukherjee committed
209
    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
210 211 212 213
    DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
214
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    DECLARE_ALIGNED(16, const uint8_t, limit[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    int32_t p = kNumCoeffs/32;

    uint16_t tmp_s[kNumCoeffs];
    int j = 0;
    while (j < kNumCoeffs) {
      uint8_t val = rnd.Rand8();
      if (val & 0x80) {  // 50% chance to choose a new value.
        tmp_s[j] = rnd.Rand16();
        j++;
      } else {  // 50% chance to repeat previous value in row X times
        int k = 0;
        while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
          if (j < 1) {
            tmp_s[j] = rnd.Rand16();
          } else if (val & 0x20) {  // Increment by an value within the limit
            tmp_s[j] = (tmp_s[j - 1] + (*limit - 1));
          } else {  // Decrement by an value within the limit
            tmp_s[j] = (tmp_s[j - 1] - (*limit - 1));
          }
          j++;
        }
      }
    }
    for (j = 0; j < kNumCoeffs; j++) {
      if (i % 2) {
        s[j] = tmp_s[j] & mask_;
      } else {
        s[j] = tmp_s[p * (j % p) + j / p] & mask_;
      }
      ref_s[j] = s[j];
    }
#if CONFIG_VP9_HIGHBITDEPTH
Ed Baker's avatar
Ed Baker committed
256
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, count_, bd);
257
    ASM_REGISTER_STATE_CHECK(
Ed Baker's avatar
Ed Baker committed
258
        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, count_, bd));
259
#else
Ed Baker's avatar
Ed Baker committed
260
    ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh, count_);
261
    ASM_REGISTER_STATE_CHECK(
Ed Baker's avatar
Ed Baker committed
262
        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, count_));
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
#endif  // CONFIG_VP9_HIGHBITDEPTH

    for (int j = 0; j < kNumCoeffs; ++j) {
      err_count += ref_s[j] != s[j];
    }
    if (err_count && !err_count_total) {
      first_failure = i;
    }
    err_count_total += err_count;
  }
  EXPECT_EQ(0, err_count_total)
      << "Error: Loop8Test6Param, C output doesn't match SSE2 "
         "loopfilter output. "
      << "First failed at test case " << first_failure;
}

TEST_P(Loop8Test6Param, ValueCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  const int count_test_block = number_of_iterations;
#if CONFIG_VP9_HIGHBITDEPTH
  const int32_t bd = bit_depth_;
284 285
  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
286
#else
287 288
  DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
289 290 291
#endif  // CONFIG_VP9_HIGHBITDEPTH
  int err_count_total = 0;
  int first_failure = -1;
Deb Mukherjee's avatar
Deb Mukherjee committed
292 293 294 295 296

  // NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a
  // function of sharpness_lvl and the loopfilter lvl as:
  // block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
  // ...
James Zern's avatar
James Zern committed
297 298
  // memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
  //        SIMD_WIDTH);
Deb Mukherjee's avatar
Deb Mukherjee committed
299 300 301 302 303 304
  // This means that the largest value for mblim will occur when sharpness_lvl
  // is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER).
  // In this case block_inside_limit will be equal to MAX_LOOP_FILTER and
  // therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) =
  // 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4

305 306
  for (int i = 0; i < count_test_block; ++i) {
    int err_count = 0;
Deb Mukherjee's avatar
Deb Mukherjee committed
307
    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
308 309 310 311
    DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
312
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    DECLARE_ALIGNED(16, const uint8_t, limit[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    int32_t p = kNumCoeffs / 32;
    for (int j = 0; j < kNumCoeffs; ++j) {
      s[j] = rnd.Rand16() & mask_;
      ref_s[j] = s[j];
    }
#if CONFIG_VP9_HIGHBITDEPTH
Ed Baker's avatar
Ed Baker committed
328
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, count_, bd);
329
    ASM_REGISTER_STATE_CHECK(
Ed Baker's avatar
Ed Baker committed
330
        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, count_, bd));
331
#else
Ed Baker's avatar
Ed Baker committed
332
    ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh, count_);
333
    ASM_REGISTER_STATE_CHECK(
Ed Baker's avatar
Ed Baker committed
334
        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, count_));
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
#endif  // CONFIG_VP9_HIGHBITDEPTH
    for (int j = 0; j < kNumCoeffs; ++j) {
      err_count += ref_s[j] != s[j];
    }
    if (err_count && !err_count_total) {
      first_failure = i;
    }
    err_count_total += err_count;
  }
  EXPECT_EQ(0, err_count_total)
      << "Error: Loop8Test6Param, C output doesn't match SSE2 "
         "loopfilter output. "
      << "First failed at test case " << first_failure;
}

TEST_P(Loop8Test9Param, OperationCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  const int count_test_block = number_of_iterations;
#if CONFIG_VP9_HIGHBITDEPTH
  const int32_t bd = bit_depth_;
355 356
  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
357
#else
358 359
  DECLARE_ALIGNED(8,  uint8_t,  s[kNumCoeffs]);
  DECLARE_ALIGNED(8,  uint8_t,  ref_s[kNumCoeffs]);
360 361 362 363 364
#endif  // CONFIG_VP9_HIGHBITDEPTH
  int err_count_total = 0;
  int first_failure = -1;
  for (int i = 0; i < count_test_block; ++i) {
    int err_count = 0;
Deb Mukherjee's avatar
Deb Mukherjee committed
365
    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
366 367 368 369
    DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
370
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
371 372 373 374 375 376 377 378 379
    DECLARE_ALIGNED(16, const uint8_t, limit0[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
380
    tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
381 382 383 384
    DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
385
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
    DECLARE_ALIGNED(16, const uint8_t, limit1[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    int32_t p = kNumCoeffs / 32;
    uint16_t tmp_s[kNumCoeffs];
    int j = 0;
    const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1;
    while (j < kNumCoeffs) {
      uint8_t val = rnd.Rand8();
      if (val & 0x80) {  // 50% chance to choose a new value.
        tmp_s[j] = rnd.Rand16();
        j++;
      } else {  // 50% chance to repeat previous value in row X times.
        int k = 0;
        while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
          if (j < 1) {
            tmp_s[j] = rnd.Rand16();
          } else if (val & 0x20) {  // Increment by a value within the limit.
            tmp_s[j] = (tmp_s[j - 1] + (limit - 1));
          } else {  // Decrement by an value within the limit.
            tmp_s[j] = (tmp_s[j - 1] - (limit - 1));
          }
          j++;
        }
      }
    }
    for (j = 0; j < kNumCoeffs; j++) {
      if (i % 2) {
        s[j] = tmp_s[j] & mask_;
      } else {
        s[j] = tmp_s[p * (j % p) + j / p] & mask_;
      }
      ref_s[j] = s[j];
    }
#if CONFIG_VP9_HIGHBITDEPTH
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1, bd);
    ASM_REGISTER_STATE_CHECK(
        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1, bd));
#else
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1);
    ASM_REGISTER_STATE_CHECK(
        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1));
#endif  // CONFIG_VP9_HIGHBITDEPTH
    for (int j = 0; j < kNumCoeffs; ++j) {
      err_count += ref_s[j] != s[j];
    }
    if (err_count && !err_count_total) {
      first_failure = i;
    }
    err_count_total += err_count;
  }
  EXPECT_EQ(0, err_count_total)
      << "Error: Loop8Test9Param, C output doesn't match SSE2 "
         "loopfilter output. "
      << "First failed at test case " << first_failure;
}

TEST_P(Loop8Test9Param, ValueCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  const int count_test_block = number_of_iterations;
#if CONFIG_VP9_HIGHBITDEPTH
457 458
  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
459
#else
460 461
  DECLARE_ALIGNED(8,  uint8_t, s[kNumCoeffs]);
  DECLARE_ALIGNED(8,  uint8_t, ref_s[kNumCoeffs]);
462 463 464 465 466
#endif  // CONFIG_VP9_HIGHBITDEPTH
  int err_count_total = 0;
  int first_failure = -1;
  for (int i = 0; i < count_test_block; ++i) {
    int err_count = 0;
Deb Mukherjee's avatar
Deb Mukherjee committed
467
    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
468 469 470 471
    DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
472
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
473 474 475 476 477 478 479 480 481
    DECLARE_ALIGNED(16, const uint8_t, limit0[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
482
    tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
483 484 485 486
    DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
Deb Mukherjee's avatar
Deb Mukherjee committed
487
    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
    DECLARE_ALIGNED(16, const uint8_t, limit1[16])  = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    tmp = rnd.Rand8();
    DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
    };
    int32_t p = kNumCoeffs / 32;  // TODO(pdlf) can we have non-square here?
    for (int j = 0; j < kNumCoeffs; ++j) {
      s[j] = rnd.Rand16() & mask_;
      ref_s[j] = s[j];
    }
#if CONFIG_VP9_HIGHBITDEPTH
    const int32_t bd = bit_depth_;
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1, bd);
    ASM_REGISTER_STATE_CHECK(
        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
                       thresh0, blimit1, limit1, thresh1, bd));
#else
    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1);
    ASM_REGISTER_STATE_CHECK(
        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
                       blimit1, limit1, thresh1));
#endif  // CONFIG_VP9_HIGHBITDEPTH
    for (int j = 0; j < kNumCoeffs; ++j) {
      err_count += ref_s[j] != s[j];
    }
    if (err_count && !err_count_total) {
      first_failure = i;
    }
    err_count_total += err_count;
  }
  EXPECT_EQ(0, err_count_total)
      << "Error: Loop8Test9Param, C output doesn't match SSE2"
         "loopfilter output. "
      << "First failed at test case " << first_failure;
}

using std::tr1::make_tuple;

#if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
535
    SSE2, Loop8Test6Param,
536
    ::testing::Values(
537 538 539 540 541 542 543 544 545 546 547 548
        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
                   &vpx_highbd_lpf_horizontal_4_c, 8, 1),
        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
                   &vpx_highbd_lpf_vertical_4_c, 8, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
                   &vpx_highbd_lpf_horizontal_8_c, 8, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 8, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 8, 2),
        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
                   &vpx_highbd_lpf_vertical_8_c, 8, 1),
549
        make_tuple(&wrapper_vertical_16_sse2,
Ed Baker's avatar
Ed Baker committed
550
                   &wrapper_vertical_16_c, 8, 1),
551 552 553 554 555 556 557 558 559 560 561 562
        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
                   &vpx_highbd_lpf_horizontal_4_c, 10, 1),
        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
                   &vpx_highbd_lpf_vertical_4_c, 10, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
                   &vpx_highbd_lpf_horizontal_8_c, 10, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 10, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 10, 2),
        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
                   &vpx_highbd_lpf_vertical_8_c, 10, 1),
563
        make_tuple(&wrapper_vertical_16_sse2,
Ed Baker's avatar
Ed Baker committed
564
                   &wrapper_vertical_16_c, 10, 1),
565 566 567 568 569 570 571 572 573 574 575 576
        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
                   &vpx_highbd_lpf_horizontal_4_c, 12, 1),
        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
                   &vpx_highbd_lpf_vertical_4_c, 12, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
                   &vpx_highbd_lpf_horizontal_8_c, 12, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 12, 1),
        make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
                   &vpx_highbd_lpf_horizontal_16_c, 12, 2),
        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
                   &vpx_highbd_lpf_vertical_8_c, 12, 1),
577
        make_tuple(&wrapper_vertical_16_sse2,
Ed Baker's avatar
Ed Baker committed
578
                   &wrapper_vertical_16_c, 12, 1),
579
        make_tuple(&wrapper_vertical_16_dual_sse2,
Ed Baker's avatar
Ed Baker committed
580
                   &wrapper_vertical_16_dual_c, 8, 1),
581
        make_tuple(&wrapper_vertical_16_dual_sse2,
Ed Baker's avatar
Ed Baker committed
582
                   &wrapper_vertical_16_dual_c, 10, 1),
583
        make_tuple(&wrapper_vertical_16_dual_sse2,
Ed Baker's avatar
Ed Baker committed
584
                   &wrapper_vertical_16_dual_c, 12, 1)));
585 586
#else
INSTANTIATE_TEST_CASE_P(
Deb Mukherjee's avatar
Deb Mukherjee committed
587
    SSE2, Loop8Test6Param,
588
    ::testing::Values(
589 590 591 592
        make_tuple(&vpx_lpf_horizontal_8_sse2, &vpx_lpf_horizontal_8_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_sse2, &vpx_lpf_horizontal_16_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_sse2, &vpx_lpf_horizontal_16_c, 8, 2),
        make_tuple(&vpx_lpf_vertical_8_sse2, &vpx_lpf_vertical_8_c, 8, 1),
Johann's avatar
Johann committed
593 594 595
        make_tuple(&wrapper_vertical_16_sse2, &wrapper_vertical_16_c, 8, 1),
        make_tuple(&wrapper_vertical_16_dual_sse2,
                   &wrapper_vertical_16_dual_c, 8, 1)));
596 597 598
#endif  // CONFIG_VP9_HIGHBITDEPTH
#endif

599 600
#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH)
INSTANTIATE_TEST_CASE_P(
Deb Mukherjee's avatar
Deb Mukherjee committed
601
    AVX2, Loop8Test6Param,
602
    ::testing::Values(
603 604
        make_tuple(&vpx_lpf_horizontal_16_avx2, &vpx_lpf_horizontal_16_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_avx2, &vpx_lpf_horizontal_16_c, 8,
Ed Baker's avatar
Ed Baker committed
605
                   2)));
606 607
#endif

608 609 610
#if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
611
    SSE2, Loop8Test9Param,
612
    ::testing::Values(
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
                   &vpx_highbd_lpf_horizontal_4_dual_c, 8),
        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
                   &vpx_highbd_lpf_horizontal_8_dual_c, 8),
        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
                   &vpx_highbd_lpf_vertical_4_dual_c, 8),
        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
                   &vpx_highbd_lpf_vertical_8_dual_c, 8),
        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
                   &vpx_highbd_lpf_horizontal_4_dual_c, 10),
        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
                   &vpx_highbd_lpf_horizontal_8_dual_c, 10),
        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
                   &vpx_highbd_lpf_vertical_4_dual_c, 10),
        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
                   &vpx_highbd_lpf_vertical_8_dual_c, 10),
        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
                   &vpx_highbd_lpf_horizontal_4_dual_c, 12),
        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
                   &vpx_highbd_lpf_horizontal_8_dual_c, 12),
        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
                   &vpx_highbd_lpf_vertical_4_dual_c, 12),
        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
                   &vpx_highbd_lpf_vertical_8_dual_c, 12)));
637 638
#else
INSTANTIATE_TEST_CASE_P(
Deb Mukherjee's avatar
Deb Mukherjee committed
639
    SSE2, Loop8Test9Param,
640
    ::testing::Values(
641 642 643 644 645 646 647 648
        make_tuple(&vpx_lpf_horizontal_4_dual_sse2,
                   &vpx_lpf_horizontal_4_dual_c, 8),
        make_tuple(&vpx_lpf_horizontal_8_dual_sse2,
                   &vpx_lpf_horizontal_8_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_4_dual_sse2,
                   &vpx_lpf_vertical_4_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_8_dual_sse2,
                   &vpx_lpf_vertical_8_dual_c, 8)));
649 650
#endif  // CONFIG_VP9_HIGHBITDEPTH
#endif
651

652 653 654 655
#if HAVE_NEON
#if CONFIG_VP9_HIGHBITDEPTH
// No neon high bitdepth functions.
#else
656 657 658 659
INSTANTIATE_TEST_CASE_P(
    NEON, Loop8Test6Param,
    ::testing::Values(
#if HAVE_NEON_ASM
660 661
// Using #if inside the macro is unsupported on MSVS but the tests are not
// currently built for MSVS with ARM and NEON.
662 663 664 665
        make_tuple(&vpx_lpf_horizontal_16_neon,
                   &vpx_lpf_horizontal_16_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_neon,
                   &vpx_lpf_horizontal_16_c, 8, 2),
666
        make_tuple(&wrapper_vertical_16_neon,
Ed Baker's avatar
Ed Baker committed
667
                   &wrapper_vertical_16_c, 8, 1),
668
        make_tuple(&wrapper_vertical_16_dual_neon,
Ed Baker's avatar
Ed Baker committed
669
                   &wrapper_vertical_16_dual_c, 8, 1),
670
#endif  // HAVE_NEON_ASM
671 672 673 674 675 676 677 678
        make_tuple(&vpx_lpf_horizontal_8_neon,
                   &vpx_lpf_horizontal_8_c, 8, 1),
        make_tuple(&vpx_lpf_vertical_8_neon,
                   &vpx_lpf_vertical_8_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_4_neon,
                   &vpx_lpf_horizontal_4_c, 8, 1),
        make_tuple(&vpx_lpf_vertical_4_neon,
                   &vpx_lpf_vertical_4_c, 8, 1)));
679 680 681
INSTANTIATE_TEST_CASE_P(
    NEON, Loop8Test9Param,
    ::testing::Values(
Johann's avatar
Johann committed
682
#if HAVE_NEON_ASM
683 684 685 686
        make_tuple(&vpx_lpf_horizontal_8_dual_neon,
                   &vpx_lpf_horizontal_8_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_8_dual_neon,
                   &vpx_lpf_vertical_8_dual_c, 8),
Johann's avatar
Johann committed
687
#endif  // HAVE_NEON_ASM
688 689 690 691
        make_tuple(&vpx_lpf_horizontal_4_dual_neon,
                   &vpx_lpf_horizontal_4_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_4_dual_neon,
                   &vpx_lpf_vertical_4_dual_c, 8)));
692 693
#endif  // CONFIG_VP9_HIGHBITDEPTH
#endif  // HAVE_NEON
694

695 696 697 698
#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
INSTANTIATE_TEST_CASE_P(
    MSA, Loop8Test6Param,
    ::testing::Values(
699 700 701 702
        make_tuple(&vpx_lpf_horizontal_8_msa, &vpx_lpf_horizontal_8_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_msa, &vpx_lpf_horizontal_16_c, 8, 1),
        make_tuple(&vpx_lpf_horizontal_16_msa, &vpx_lpf_horizontal_16_c, 8, 2),
        make_tuple(&vpx_lpf_vertical_8_msa, &vpx_lpf_vertical_8_c, 8, 1),
703
        make_tuple(&wrapper_vertical_16_msa, &wrapper_vertical_16_c, 8, 1)));
704 705 706 707

INSTANTIATE_TEST_CASE_P(
    MSA, Loop8Test9Param,
    ::testing::Values(
708 709 710 711 712 713 714 715
        make_tuple(&vpx_lpf_horizontal_4_dual_msa,
                   &vpx_lpf_horizontal_4_dual_c, 8),
        make_tuple(&vpx_lpf_horizontal_8_dual_msa,
                   &vpx_lpf_horizontal_8_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_4_dual_msa,
                   &vpx_lpf_vertical_4_dual_c, 8),
        make_tuple(&vpx_lpf_vertical_8_dual_msa,
                   &vpx_lpf_vertical_8_dual_c, 8)));
716 717
#endif  // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)

718
}  // namespace