10a39d0a697ff3603e8c100300fda363658e10b23James Zern/*
20a39d0a697ff3603e8c100300fda363658e10b23James Zern *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
30a39d0a697ff3603e8c100300fda363658e10b23James Zern *
40a39d0a697ff3603e8c100300fda363658e10b23James Zern *  Use of this source code is governed by a BSD-style license
50a39d0a697ff3603e8c100300fda363658e10b23James Zern *  that can be found in the LICENSE file in the root of the source
60a39d0a697ff3603e8c100300fda363658e10b23James Zern *  tree. An additional intellectual property rights grant can be found
70a39d0a697ff3603e8c100300fda363658e10b23James Zern *  in the file PATENTS.  All contributing project authors may
80a39d0a697ff3603e8c100300fda363658e10b23James Zern *  be found in the AUTHORS file in the root of the source tree.
90a39d0a697ff3603e8c100300fda363658e10b23James Zern */
100a39d0a697ff3603e8c100300fda363658e10b23James Zern
11df37111358d02836cb29bbcb9c6e4c95dff90a16Johann#include <limits>
12df37111358d02836cb29bbcb9c6e4c95dff90a16Johann
130a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "third_party/googletest/src/include/gtest/gtest.h"
140a39d0a697ff3603e8c100300fda363658e10b23James Zern
150a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "./vp9_rtcd.h"
160a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "test/acm_random.h"
170a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "test/buffer.h"
180a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "test/register_state_check.h"
190a39d0a697ff3603e8c100300fda363658e10b23James Zern#include "vpx_ports/vpx_timer.h"
200a39d0a697ff3603e8c100300fda363658e10b23James Zern
210a39d0a697ff3603e8c100300fda363658e10b23James Zernnamespace {
220a39d0a697ff3603e8c100300fda363658e10b23James Zern
230a39d0a697ff3603e8c100300fda363658e10b23James Zernusing ::libvpx_test::ACMRandom;
240a39d0a697ff3603e8c100300fda363658e10b23James Zernusing ::libvpx_test::Buffer;
250a39d0a697ff3603e8c100300fda363658e10b23James Zern
260a39d0a697ff3603e8c100300fda363658e10b23James Zerntypedef void (*TemporalFilterFunc)(const uint8_t *a, unsigned int stride,
270a39d0a697ff3603e8c100300fda363658e10b23James Zern                                   const uint8_t *b, unsigned int w,
280a39d0a697ff3603e8c100300fda363658e10b23James Zern                                   unsigned int h, int filter_strength,
290a39d0a697ff3603e8c100300fda363658e10b23James Zern                                   int filter_weight, unsigned int *accumulator,
300a39d0a697ff3603e8c100300fda363658e10b23James Zern                                   uint16_t *count);
310a39d0a697ff3603e8c100300fda363658e10b23James Zern
320a39d0a697ff3603e8c100300fda363658e10b23James Zern// Calculate the difference between 'a' and 'b', sum in blocks of 9, and apply
330a39d0a697ff3603e8c100300fda363658e10b23James Zern// filter based on strength and weight. Store the resulting filter amount in
340a39d0a697ff3603e8c100300fda363658e10b23James Zern// 'count' and apply it to 'b' and store it in 'accumulator'.
350a39d0a697ff3603e8c100300fda363658e10b23James Zernvoid reference_filter(const Buffer<uint8_t> &a, const Buffer<uint8_t> &b, int w,
360a39d0a697ff3603e8c100300fda363658e10b23James Zern                      int h, int filter_strength, int filter_weight,
370a39d0a697ff3603e8c100300fda363658e10b23James Zern                      Buffer<unsigned int> *accumulator,
380a39d0a697ff3603e8c100300fda363658e10b23James Zern                      Buffer<uint16_t> *count) {
390a39d0a697ff3603e8c100300fda363658e10b23James Zern  Buffer<int> diff_sq = Buffer<int>(w, h, 0);
40df37111358d02836cb29bbcb9c6e4c95dff90a16Johann  ASSERT_TRUE(diff_sq.Init());
410a39d0a697ff3603e8c100300fda363658e10b23James Zern  diff_sq.Set(0);
420a39d0a697ff3603e8c100300fda363658e10b23James Zern
430a39d0a697ff3603e8c100300fda363658e10b23James Zern  int rounding = 0;
440a39d0a697ff3603e8c100300fda363658e10b23James Zern  if (filter_strength > 0) {
450a39d0a697ff3603e8c100300fda363658e10b23James Zern    rounding = 1 << (filter_strength - 1);
460a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
470a39d0a697ff3603e8c100300fda363658e10b23James Zern
480a39d0a697ff3603e8c100300fda363658e10b23James Zern  // Calculate all the differences. Avoids re-calculating a bunch of extra
490a39d0a697ff3603e8c100300fda363658e10b23James Zern  // values.
500a39d0a697ff3603e8c100300fda363658e10b23James Zern  for (int height = 0; height < h; ++height) {
510a39d0a697ff3603e8c100300fda363658e10b23James Zern    for (int width = 0; width < w; ++width) {
520a39d0a697ff3603e8c100300fda363658e10b23James Zern      int diff = a.TopLeftPixel()[height * a.stride() + width] -
530a39d0a697ff3603e8c100300fda363658e10b23James Zern                 b.TopLeftPixel()[height * b.stride() + width];
540a39d0a697ff3603e8c100300fda363658e10b23James Zern      diff_sq.TopLeftPixel()[height * diff_sq.stride() + width] = diff * diff;
550a39d0a697ff3603e8c100300fda363658e10b23James Zern    }
560a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
570a39d0a697ff3603e8c100300fda363658e10b23James Zern
580a39d0a697ff3603e8c100300fda363658e10b23James Zern  // For any given point, sum the neighboring values and calculate the
590a39d0a697ff3603e8c100300fda363658e10b23James Zern  // modifier.
600a39d0a697ff3603e8c100300fda363658e10b23James Zern  for (int height = 0; height < h; ++height) {
610a39d0a697ff3603e8c100300fda363658e10b23James Zern    for (int width = 0; width < w; ++width) {
620a39d0a697ff3603e8c100300fda363658e10b23James Zern      // Determine how many values are being summed.
630a39d0a697ff3603e8c100300fda363658e10b23James Zern      int summed_values = 9;
640a39d0a697ff3603e8c100300fda363658e10b23James Zern
650a39d0a697ff3603e8c100300fda363658e10b23James Zern      if (height == 0 || height == (h - 1)) {
660a39d0a697ff3603e8c100300fda363658e10b23James Zern        summed_values -= 3;
670a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
680a39d0a697ff3603e8c100300fda363658e10b23James Zern
690a39d0a697ff3603e8c100300fda363658e10b23James Zern      if (width == 0 || width == (w - 1)) {
700a39d0a697ff3603e8c100300fda363658e10b23James Zern        if (summed_values == 6) {  // corner
710a39d0a697ff3603e8c100300fda363658e10b23James Zern          summed_values -= 2;
720a39d0a697ff3603e8c100300fda363658e10b23James Zern        } else {
730a39d0a697ff3603e8c100300fda363658e10b23James Zern          summed_values -= 3;
740a39d0a697ff3603e8c100300fda363658e10b23James Zern        }
750a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
760a39d0a697ff3603e8c100300fda363658e10b23James Zern
770a39d0a697ff3603e8c100300fda363658e10b23James Zern      // Sum the diff_sq of the surrounding values.
780a39d0a697ff3603e8c100300fda363658e10b23James Zern      int sum = 0;
790a39d0a697ff3603e8c100300fda363658e10b23James Zern      for (int idy = -1; idy <= 1; ++idy) {
800a39d0a697ff3603e8c100300fda363658e10b23James Zern        for (int idx = -1; idx <= 1; ++idx) {
810a39d0a697ff3603e8c100300fda363658e10b23James Zern          const int y = height + idy;
820a39d0a697ff3603e8c100300fda363658e10b23James Zern          const int x = width + idx;
830a39d0a697ff3603e8c100300fda363658e10b23James Zern
840a39d0a697ff3603e8c100300fda363658e10b23James Zern          // If inside the border.
850a39d0a697ff3603e8c100300fda363658e10b23James Zern          if (y >= 0 && y < h && x >= 0 && x < w) {
860a39d0a697ff3603e8c100300fda363658e10b23James Zern            sum += diff_sq.TopLeftPixel()[y * diff_sq.stride() + x];
870a39d0a697ff3603e8c100300fda363658e10b23James Zern          }
880a39d0a697ff3603e8c100300fda363658e10b23James Zern        }
890a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
900a39d0a697ff3603e8c100300fda363658e10b23James Zern
910a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum *= 3;
920a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum /= summed_values;
930a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum += rounding;
940a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum >>= filter_strength;
950a39d0a697ff3603e8c100300fda363658e10b23James Zern
960a39d0a697ff3603e8c100300fda363658e10b23James Zern      // Clamp the value and invert it.
970a39d0a697ff3603e8c100300fda363658e10b23James Zern      if (sum > 16) sum = 16;
980a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum = 16 - sum;
990a39d0a697ff3603e8c100300fda363658e10b23James Zern
1000a39d0a697ff3603e8c100300fda363658e10b23James Zern      sum *= filter_weight;
1010a39d0a697ff3603e8c100300fda363658e10b23James Zern
1020a39d0a697ff3603e8c100300fda363658e10b23James Zern      count->TopLeftPixel()[height * count->stride() + width] += sum;
1030a39d0a697ff3603e8c100300fda363658e10b23James Zern      accumulator->TopLeftPixel()[height * accumulator->stride() + width] +=
1040a39d0a697ff3603e8c100300fda363658e10b23James Zern          sum * b.TopLeftPixel()[height * b.stride() + width];
1050a39d0a697ff3603e8c100300fda363658e10b23James Zern    }
1060a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
1070a39d0a697ff3603e8c100300fda363658e10b23James Zern}
1080a39d0a697ff3603e8c100300fda363658e10b23James Zern
1090a39d0a697ff3603e8c100300fda363658e10b23James Zernclass TemporalFilterTest : public ::testing::TestWithParam<TemporalFilterFunc> {
1100a39d0a697ff3603e8c100300fda363658e10b23James Zern public:
1110a39d0a697ff3603e8c100300fda363658e10b23James Zern  virtual void SetUp() {
1120a39d0a697ff3603e8c100300fda363658e10b23James Zern    filter_func_ = GetParam();
1130a39d0a697ff3603e8c100300fda363658e10b23James Zern    rnd_.Reset(ACMRandom::DeterministicSeed());
1140a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
1150a39d0a697ff3603e8c100300fda363658e10b23James Zern
1160a39d0a697ff3603e8c100300fda363658e10b23James Zern protected:
1170a39d0a697ff3603e8c100300fda363658e10b23James Zern  TemporalFilterFunc filter_func_;
1180a39d0a697ff3603e8c100300fda363658e10b23James Zern  ACMRandom rnd_;
1190a39d0a697ff3603e8c100300fda363658e10b23James Zern};
1200a39d0a697ff3603e8c100300fda363658e10b23James Zern
1210a39d0a697ff3603e8c100300fda363658e10b23James ZernTEST_P(TemporalFilterTest, SizeCombinations) {
1220a39d0a697ff3603e8c100300fda363658e10b23James Zern  // Depending on subsampling this function may be called with values of 8 or 16
1230a39d0a697ff3603e8c100300fda363658e10b23James Zern  // for width and height, in any combination.
1240a39d0a697ff3603e8c100300fda363658e10b23James Zern  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
125df37111358d02836cb29bbcb9c6e4c95dff90a16Johann  ASSERT_TRUE(a.Init());
1260a39d0a697ff3603e8c100300fda363658e10b23James Zern
1270a39d0a697ff3603e8c100300fda363658e10b23James Zern  const int filter_weight = 2;
1280a39d0a697ff3603e8c100300fda363658e10b23James Zern  const int filter_strength = 6;
1290a39d0a697ff3603e8c100300fda363658e10b23James Zern
1300a39d0a697ff3603e8c100300fda363658e10b23James Zern  for (int width = 8; width <= 16; width += 8) {
1310a39d0a697ff3603e8c100300fda363658e10b23James Zern    for (int height = 8; height <= 16; height += 8) {
1320a39d0a697ff3603e8c100300fda363658e10b23James Zern      // The second buffer must not have any border.
1330a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
134df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(b.Init());
1350a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
136df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_ref.Init());
1370a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
138df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_chk.Init());
1390a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
140df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_ref.Init());
1410a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
142df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_chk.Init());
1430a39d0a697ff3603e8c100300fda363658e10b23James Zern
144df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      // The difference between the buffers must be small to pass the threshold
145df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      // to apply the filter.
146df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      a.Set(&rnd_, 0, 7);
147df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      b.Set(&rnd_, 0, 7);
1480a39d0a697ff3603e8c100300fda363658e10b23James Zern
1490a39d0a697ff3603e8c100300fda363658e10b23James Zern      accum_ref.Set(rnd_.Rand8());
1500a39d0a697ff3603e8c100300fda363658e10b23James Zern      accum_chk.CopyFrom(accum_ref);
1510a39d0a697ff3603e8c100300fda363658e10b23James Zern      count_ref.Set(rnd_.Rand8());
1520a39d0a697ff3603e8c100300fda363658e10b23James Zern      count_chk.CopyFrom(count_ref);
1530a39d0a697ff3603e8c100300fda363658e10b23James Zern      reference_filter(a, b, width, height, filter_strength, filter_weight,
1540a39d0a697ff3603e8c100300fda363658e10b23James Zern                       &accum_ref, &count_ref);
1550a39d0a697ff3603e8c100300fda363658e10b23James Zern      ASM_REGISTER_STATE_CHECK(
1560a39d0a697ff3603e8c100300fda363658e10b23James Zern          filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
1570a39d0a697ff3603e8c100300fda363658e10b23James Zern                       height, filter_strength, filter_weight,
1580a39d0a697ff3603e8c100300fda363658e10b23James Zern                       accum_chk.TopLeftPixel(), count_chk.TopLeftPixel()));
1590a39d0a697ff3603e8c100300fda363658e10b23James Zern      EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
1600a39d0a697ff3603e8c100300fda363658e10b23James Zern      EXPECT_TRUE(count_chk.CheckValues(count_ref));
1610a39d0a697ff3603e8c100300fda363658e10b23James Zern      if (HasFailure()) {
1620a39d0a697ff3603e8c100300fda363658e10b23James Zern        printf("Width: %d Height: %d\n", width, height);
1630a39d0a697ff3603e8c100300fda363658e10b23James Zern        count_chk.PrintDifference(count_ref);
1640a39d0a697ff3603e8c100300fda363658e10b23James Zern        accum_chk.PrintDifference(accum_ref);
1650a39d0a697ff3603e8c100300fda363658e10b23James Zern        return;
1660a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
1670a39d0a697ff3603e8c100300fda363658e10b23James Zern    }
1680a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
1690a39d0a697ff3603e8c100300fda363658e10b23James Zern}
1700a39d0a697ff3603e8c100300fda363658e10b23James Zern
1710a39d0a697ff3603e8c100300fda363658e10b23James ZernTEST_P(TemporalFilterTest, CompareReferenceRandom) {
1720a39d0a697ff3603e8c100300fda363658e10b23James Zern  for (int width = 8; width <= 16; width += 8) {
1730a39d0a697ff3603e8c100300fda363658e10b23James Zern    for (int height = 8; height <= 16; height += 8) {
1740a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint8_t> a = Buffer<uint8_t>(width, height, 8);
175df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(a.Init());
1760a39d0a697ff3603e8c100300fda363658e10b23James Zern      // The second buffer must not have any border.
1770a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
178df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(b.Init());
1790a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
180df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_ref.Init());
1810a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
182df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_chk.Init());
1830a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
184df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_ref.Init());
1850a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
186df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_chk.Init());
1870a39d0a697ff3603e8c100300fda363658e10b23James Zern
1880a39d0a697ff3603e8c100300fda363658e10b23James Zern      for (int filter_strength = 0; filter_strength <= 6; ++filter_strength) {
1890a39d0a697ff3603e8c100300fda363658e10b23James Zern        for (int filter_weight = 0; filter_weight <= 2; ++filter_weight) {
190df37111358d02836cb29bbcb9c6e4c95dff90a16Johann          for (int repeat = 0; repeat < 100; ++repeat) {
191df37111358d02836cb29bbcb9c6e4c95dff90a16Johann            if (repeat < 50) {
192df37111358d02836cb29bbcb9c6e4c95dff90a16Johann              a.Set(&rnd_, 0, 7);
193df37111358d02836cb29bbcb9c6e4c95dff90a16Johann              b.Set(&rnd_, 0, 7);
194df37111358d02836cb29bbcb9c6e4c95dff90a16Johann            } else {
195df37111358d02836cb29bbcb9c6e4c95dff90a16Johann              // Check large (but close) values as well.
196df37111358d02836cb29bbcb9c6e4c95dff90a16Johann              a.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
197df37111358d02836cb29bbcb9c6e4c95dff90a16Johann                    std::numeric_limits<uint8_t>::max());
198df37111358d02836cb29bbcb9c6e4c95dff90a16Johann              b.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
199df37111358d02836cb29bbcb9c6e4c95dff90a16Johann                    std::numeric_limits<uint8_t>::max());
200df37111358d02836cb29bbcb9c6e4c95dff90a16Johann            }
2010a39d0a697ff3603e8c100300fda363658e10b23James Zern
2020a39d0a697ff3603e8c100300fda363658e10b23James Zern            accum_ref.Set(rnd_.Rand8());
2030a39d0a697ff3603e8c100300fda363658e10b23James Zern            accum_chk.CopyFrom(accum_ref);
2040a39d0a697ff3603e8c100300fda363658e10b23James Zern            count_ref.Set(rnd_.Rand8());
2050a39d0a697ff3603e8c100300fda363658e10b23James Zern            count_chk.CopyFrom(count_ref);
2060a39d0a697ff3603e8c100300fda363658e10b23James Zern            reference_filter(a, b, width, height, filter_strength,
2070a39d0a697ff3603e8c100300fda363658e10b23James Zern                             filter_weight, &accum_ref, &count_ref);
2080a39d0a697ff3603e8c100300fda363658e10b23James Zern            ASM_REGISTER_STATE_CHECK(filter_func_(
2090a39d0a697ff3603e8c100300fda363658e10b23James Zern                a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width, height,
2100a39d0a697ff3603e8c100300fda363658e10b23James Zern                filter_strength, filter_weight, accum_chk.TopLeftPixel(),
2110a39d0a697ff3603e8c100300fda363658e10b23James Zern                count_chk.TopLeftPixel()));
2120a39d0a697ff3603e8c100300fda363658e10b23James Zern            EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
2130a39d0a697ff3603e8c100300fda363658e10b23James Zern            EXPECT_TRUE(count_chk.CheckValues(count_ref));
2140a39d0a697ff3603e8c100300fda363658e10b23James Zern            if (HasFailure()) {
2150a39d0a697ff3603e8c100300fda363658e10b23James Zern              printf("Weight: %d Strength: %d\n", filter_weight,
2160a39d0a697ff3603e8c100300fda363658e10b23James Zern                     filter_strength);
2170a39d0a697ff3603e8c100300fda363658e10b23James Zern              count_chk.PrintDifference(count_ref);
2180a39d0a697ff3603e8c100300fda363658e10b23James Zern              accum_chk.PrintDifference(accum_ref);
2190a39d0a697ff3603e8c100300fda363658e10b23James Zern              return;
2200a39d0a697ff3603e8c100300fda363658e10b23James Zern            }
2210a39d0a697ff3603e8c100300fda363658e10b23James Zern          }
2220a39d0a697ff3603e8c100300fda363658e10b23James Zern        }
2230a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
2240a39d0a697ff3603e8c100300fda363658e10b23James Zern    }
2250a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
2260a39d0a697ff3603e8c100300fda363658e10b23James Zern}
2270a39d0a697ff3603e8c100300fda363658e10b23James Zern
2280a39d0a697ff3603e8c100300fda363658e10b23James ZernTEST_P(TemporalFilterTest, DISABLED_Speed) {
2290a39d0a697ff3603e8c100300fda363658e10b23James Zern  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
230df37111358d02836cb29bbcb9c6e4c95dff90a16Johann  ASSERT_TRUE(a.Init());
2310a39d0a697ff3603e8c100300fda363658e10b23James Zern
2320a39d0a697ff3603e8c100300fda363658e10b23James Zern  const int filter_weight = 2;
2330a39d0a697ff3603e8c100300fda363658e10b23James Zern  const int filter_strength = 6;
2340a39d0a697ff3603e8c100300fda363658e10b23James Zern
2350a39d0a697ff3603e8c100300fda363658e10b23James Zern  for (int width = 8; width <= 16; width += 8) {
2360a39d0a697ff3603e8c100300fda363658e10b23James Zern    for (int height = 8; height <= 16; height += 8) {
2370a39d0a697ff3603e8c100300fda363658e10b23James Zern      // The second buffer must not have any border.
2380a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
239df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(b.Init());
2400a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
241df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_ref.Init());
2420a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
243df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(accum_chk.Init());
2440a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
245df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_ref.Init());
2460a39d0a697ff3603e8c100300fda363658e10b23James Zern      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
247df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      ASSERT_TRUE(count_chk.Init());
2480a39d0a697ff3603e8c100300fda363658e10b23James Zern
249df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      a.Set(&rnd_, 0, 7);
250df37111358d02836cb29bbcb9c6e4c95dff90a16Johann      b.Set(&rnd_, 0, 7);
2510a39d0a697ff3603e8c100300fda363658e10b23James Zern
2520a39d0a697ff3603e8c100300fda363658e10b23James Zern      accum_chk.Set(0);
2530a39d0a697ff3603e8c100300fda363658e10b23James Zern      count_chk.Set(0);
2540a39d0a697ff3603e8c100300fda363658e10b23James Zern
2550a39d0a697ff3603e8c100300fda363658e10b23James Zern      vpx_usec_timer timer;
2560a39d0a697ff3603e8c100300fda363658e10b23James Zern      vpx_usec_timer_start(&timer);
2570a39d0a697ff3603e8c100300fda363658e10b23James Zern      for (int i = 0; i < 10000; ++i) {
2580a39d0a697ff3603e8c100300fda363658e10b23James Zern        filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
2590a39d0a697ff3603e8c100300fda363658e10b23James Zern                     height, filter_strength, filter_weight,
2600a39d0a697ff3603e8c100300fda363658e10b23James Zern                     accum_chk.TopLeftPixel(), count_chk.TopLeftPixel());
2610a39d0a697ff3603e8c100300fda363658e10b23James Zern      }
2620a39d0a697ff3603e8c100300fda363658e10b23James Zern      vpx_usec_timer_mark(&timer);
2630a39d0a697ff3603e8c100300fda363658e10b23James Zern      const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
2640a39d0a697ff3603e8c100300fda363658e10b23James Zern      printf("Temporal filter %dx%d time: %5d us\n", width, height,
2650a39d0a697ff3603e8c100300fda363658e10b23James Zern             elapsed_time);
2660a39d0a697ff3603e8c100300fda363658e10b23James Zern    }
2670a39d0a697ff3603e8c100300fda363658e10b23James Zern  }
2680a39d0a697ff3603e8c100300fda363658e10b23James Zern}
2690a39d0a697ff3603e8c100300fda363658e10b23James Zern
2700a39d0a697ff3603e8c100300fda363658e10b23James ZernINSTANTIATE_TEST_CASE_P(C, TemporalFilterTest,
2710a39d0a697ff3603e8c100300fda363658e10b23James Zern                        ::testing::Values(&vp9_temporal_filter_apply_c));
2720a39d0a697ff3603e8c100300fda363658e10b23James Zern
2730a39d0a697ff3603e8c100300fda363658e10b23James Zern#if HAVE_SSE4_1
2740a39d0a697ff3603e8c100300fda363658e10b23James ZernINSTANTIATE_TEST_CASE_P(SSE4_1, TemporalFilterTest,
2750a39d0a697ff3603e8c100300fda363658e10b23James Zern                        ::testing::Values(&vp9_temporal_filter_apply_sse4_1));
2760a39d0a697ff3603e8c100300fda363658e10b23James Zern#endif  // HAVE_SSE4_1
2770a39d0a697ff3603e8c100300fda363658e10b23James Zern}  // namespace
278