diff --git a/test/comp_avg_pred_test.cc b/test/comp_avg_pred_test.cc new file mode 100644 index 000000000..bdc0e70a2 --- /dev/null +++ b/test/comp_avg_pred_test.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017 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 "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_dsp_rtcd.h" + +#include "test/acm_random.h" +#include "test/buffer.h" +#include "test/register_state_check.h" +#include "vpx_ports/vpx_timer.h" + +namespace { + +using ::libvpx_test::ACMRandom; +using ::libvpx_test::Buffer; + +typedef void (*AvgPredFunc)(uint8_t *a, const uint8_t *b, int w, int h, + const uint8_t *c, int c_stride); + +uint8_t avg_with_rounding(uint8_t a, uint8_t b) { return (a + b + 1) >> 1; } + +void reference_pred(const Buffer &pred, const Buffer &ref, + int width, int height, Buffer *avg) { + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + avg->TopLeftPixel()[y * avg->stride() + x] = + avg_with_rounding(pred.TopLeftPixel()[y * pred.stride() + x], + ref.TopLeftPixel()[y * ref.stride() + x]); + } + } +} + +class AvgPredTest : public ::testing::TestWithParam { + public: + virtual void SetUp() { + avg_pred_func_ = GetParam(); + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + protected: + AvgPredFunc avg_pred_func_; + ACMRandom rnd_; +}; + +TEST_P(AvgPredTest, SizeCombinations) { + // This is called as part of the sub pixel variance. As such it must be one of + // the variance block sizes. + + for (int width_pow = 2; width_pow <= 6; ++width_pow) { + for (int height_pow = width_pow - 1; height_pow <= width_pow + 1; + ++height_pow) { + // Don't test 4x2 or 64x128 + if (height_pow == 1 || height_pow == 7) continue; + + const int width = 1 << width_pow; + const int height = 1 << height_pow; + Buffer pred = Buffer(width, height, 0); + // Only the reference buffer may have a stride not equal to width. + Buffer ref = Buffer(width, height, 8); + Buffer avg_ref = Buffer(width, height, 0); + Buffer avg_chk = Buffer(width, height, 0); + + pred.Set(&rnd_, &ACMRandom::Rand8); + ref.Set(&rnd_, &ACMRandom::Rand8); + + reference_pred(pred, ref, width, height, &avg_ref); + ASM_REGISTER_STATE_CHECK( + avg_pred_func_(avg_chk.TopLeftPixel(), pred.TopLeftPixel(), width, + height, ref.TopLeftPixel(), ref.stride())); + EXPECT_TRUE(avg_chk.CheckValues(avg_ref)); + if (HasFailure()) { + avg_chk.PrintDifference(avg_ref); + return; + } + } + } +} + +TEST_P(AvgPredTest, CompareReferenceRandom) { + const int width = 64; + const int height = 32; + Buffer pred = Buffer(width, height, 0); + Buffer ref = Buffer(width, height, 8); + Buffer avg_ref = Buffer(width, height, 0); + Buffer avg_chk = Buffer(width, height, 0); + + for (int i = 0; i < 500; ++i) { + pred.Set(&rnd_, &ACMRandom::Rand8); + ref.Set(&rnd_, &ACMRandom::Rand8); + + reference_pred(pred, ref, width, height, &avg_ref); + ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk.TopLeftPixel(), + pred.TopLeftPixel(), width, height, + ref.TopLeftPixel(), ref.stride())); + EXPECT_TRUE(avg_chk.CheckValues(avg_ref)); + if (HasFailure()) { + avg_chk.PrintDifference(avg_ref); + return; + } + } +} + +TEST_P(AvgPredTest, DISABLED_Speed) { + for (int width_pow = 2; width_pow <= 6; ++width_pow) { + for (int height_pow = width_pow - 1; height_pow <= width_pow + 1; + ++height_pow) { + // Don't test 4x2 or 64x128 + if (height_pow == 1 || height_pow == 7) continue; + + const int width = 1 << width_pow; + const int height = 1 << height_pow; + Buffer pred = Buffer(width, height, 0); + Buffer ref = Buffer(width, height, 8); + Buffer avg = Buffer(width, height, 0); + + pred.Set(&rnd_, &ACMRandom::Rand8); + ref.Set(&rnd_, &ACMRandom::Rand8); + + vpx_usec_timer timer; + vpx_usec_timer_start(&timer); + for (int i = 0; i < 100000; ++i) { + avg_pred_func_(avg.TopLeftPixel(), pred.TopLeftPixel(), width, height, + ref.TopLeftPixel(), ref.stride()); + } + vpx_usec_timer_mark(&timer); + + const int elapsed_time = + static_cast(vpx_usec_timer_elapsed(&timer) / 1000); + printf("Average Test %dx%d time: %5d ms\n", width, height, elapsed_time); + } + } +} + +INSTANTIATE_TEST_CASE_P(C, AvgPredTest, + ::testing::Values(&vpx_comp_avg_pred_c)); + +/* TODO(johannkoenig): https://bugs.chromium.org/p/webm/issues/detail?id=1390 +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, AvgPredTest, + ::testing::Values(&vpx_comp_avg_pred_sse2)); +#endif // HAVE_SSE2 +*/ +} // namespace diff --git a/test/test.mk b/test/test.mk index 0bbed54fa..ba74cef02 100644 --- a/test/test.mk +++ b/test/test.mk @@ -150,6 +150,7 @@ LIBVPX_TEST_SRCS-yes += vp9_intrapred_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_decrypt_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_thread_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += avg_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += comp_avg_pred_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct4x4_test.cc