/* * Copyright (c) 2018, 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 "third_party/googletest/src/googletest/include/gtest/gtest.h" #include "test/register_state_check.h" #include "test/acm_random.h" #include "test/util.h" #include "config/aom_config.h" #include "config/aom_dsp_rtcd.h" #include "aom/aom_integer.h" #include "aom_ports/aom_timer.h" #include "av1/encoder/pickrst.h" #define MAX_DATA_BLOCK 384 namespace pickrst_test_lowbd { static const int kIterations = 100; typedef int64_t (*lowbd_pixel_proj_error_func)( const uint8_t *src8, int width, int height, int src_stride, const uint8_t *dat8, int dat_stride, int32_t *flt0, int flt0_stride, int32_t *flt1, int flt1_stride, int xq[2], const sgr_params_type *params); //////////////////////////////////////////////////////////////////////////////// // 8 bit //////////////////////////////////////////////////////////////////////////////// typedef ::testing::tuple PixelProjErrorTestParam; class PixelProjErrorTest : public ::testing::TestWithParam { public: virtual void SetUp() { target_func_ = GET_PARAM(0); src_ = (uint8_t *)(aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*src_))); ASSERT_NE(src_, nullptr); dgd_ = (uint8_t *)(aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*dgd_))); ASSERT_NE(dgd_, nullptr); flt0_ = (int32_t *)(aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*flt0_))); ASSERT_NE(flt0_, nullptr); flt1_ = (int32_t *)(aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*flt1_))); ASSERT_NE(flt1_, nullptr); } virtual void TearDown() { aom_free(src_); aom_free(dgd_); aom_free(flt0_); aom_free(flt1_); } void RunPixelProjErrorTest(int32_t run_times); void RunPixelProjErrorTest_ExtremeValues(); private: lowbd_pixel_proj_error_func target_func_; libaom_test::ACMRandom rng_; uint8_t *src_; uint8_t *dgd_; int32_t *flt0_; int32_t *flt1_; }; void PixelProjErrorTest::RunPixelProjErrorTest(int32_t run_times) { int h_end = run_times != 1 ? 128 : (rng_.Rand16() % MAX_DATA_BLOCK) + 1; int v_end = run_times != 1 ? 128 : (rng_.Rand16() % MAX_DATA_BLOCK) + 1; const int dgd_stride = MAX_DATA_BLOCK; const int src_stride = MAX_DATA_BLOCK; const int flt0_stride = MAX_DATA_BLOCK; const int flt1_stride = MAX_DATA_BLOCK; sgr_params_type params; int xq[2]; const int iters = run_times == 1 ? kIterations : 4; for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) { int64_t err_ref = 0, err_test = 1; for (int i = 0; i < MAX_DATA_BLOCK * MAX_DATA_BLOCK; ++i) { dgd_[i] = rng_.Rand8(); src_[i] = rng_.Rand8(); flt0_[i] = rng_.Rand15Signed(); flt1_[i] = rng_.Rand15Signed(); } xq[0] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); xq[1] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); params.r[0] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter % 2); params.r[1] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter / 2); params.s[0] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter % 2); params.s[1] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter / 2); uint8_t *dgd = dgd_; uint8_t *src = src_; aom_usec_timer timer; aom_usec_timer_start(&timer); for (int i = 0; i < run_times; ++i) { err_ref = av1_lowbd_pixel_proj_error_c(src, h_end, v_end, src_stride, dgd, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); } aom_usec_timer_mark(&timer); const double time1 = static_cast(aom_usec_timer_elapsed(&timer)); aom_usec_timer_start(&timer); for (int i = 0; i < run_times; ++i) { err_test = target_func_(src, h_end, v_end, src_stride, dgd, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); } aom_usec_timer_mark(&timer); const double time2 = static_cast(aom_usec_timer_elapsed(&timer)); if (run_times > 10) { printf("r0 %d r1 %d %3dx%-3d:%7.2f/%7.2fns (%3.2f)\n", params.r[0], params.r[1], h_end, v_end, time1, time2, time1 / time2); } ASSERT_EQ(err_ref, err_test); } } void PixelProjErrorTest::RunPixelProjErrorTest_ExtremeValues() { const int h_start = 0; int h_end = 192; const int v_start = 0; int v_end = 192; const int dgd_stride = MAX_DATA_BLOCK; const int src_stride = MAX_DATA_BLOCK; const int flt0_stride = MAX_DATA_BLOCK; const int flt1_stride = MAX_DATA_BLOCK; sgr_params_type params; int xq[2]; const int iters = kIterations; for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) { int64_t err_ref = 0, err_test = 1; for (int i = 0; i < MAX_DATA_BLOCK * MAX_DATA_BLOCK; ++i) { dgd_[i] = 0; src_[i] = 255; flt0_[i] = rng_.Rand15Signed(); flt1_[i] = rng_.Rand15Signed(); } xq[0] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); xq[1] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); params.r[0] = rng_.Rand8() % MAX_RADIUS; params.r[1] = rng_.Rand8() % MAX_RADIUS; params.s[0] = rng_.Rand8() % MAX_RADIUS; params.s[1] = rng_.Rand8() % MAX_RADIUS; uint8_t *dgd = dgd_; uint8_t *src = src_; err_ref = av1_lowbd_pixel_proj_error_c( src, h_end - h_start, v_end - v_start, src_stride, dgd, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); err_test = target_func_(src, h_end - h_start, v_end - v_start, src_stride, dgd, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); ASSERT_EQ(err_ref, err_test); } } TEST_P(PixelProjErrorTest, RandomValues) { RunPixelProjErrorTest(1); } TEST_P(PixelProjErrorTest, ExtremeValues) { RunPixelProjErrorTest_ExtremeValues(); } TEST_P(PixelProjErrorTest, DISABLED_Speed) { RunPixelProjErrorTest(200000); } #if HAVE_SSE4_1 INSTANTIATE_TEST_CASE_P(SSE4_1, PixelProjErrorTest, ::testing::Values(av1_lowbd_pixel_proj_error_sse4_1)); #endif // HAVE_SSE4_1 #if HAVE_AVX2 INSTANTIATE_TEST_CASE_P(AVX2, PixelProjErrorTest, ::testing::Values(av1_lowbd_pixel_proj_error_avx2)); #endif // HAVE_AVX2 } // namespace pickrst_test_lowbd namespace pickrst_test_highbd { static const int kIterations = 100; typedef int64_t (*highbd_pixel_proj_error_func)( const uint8_t *src8, int width, int height, int src_stride, const uint8_t *dat8, int dat_stride, int32_t *flt0, int flt0_stride, int32_t *flt1, int flt1_stride, int xq[2], const sgr_params_type *params); //////////////////////////////////////////////////////////////////////////////// // High bit-depth //////////////////////////////////////////////////////////////////////////////// typedef ::testing::tuple PixelProjErrorTestParam; class PixelProjHighbdErrorTest : public ::testing::TestWithParam { public: virtual void SetUp() { target_func_ = GET_PARAM(0); src_ = (uint16_t *)aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*src_)); ASSERT_NE(src_, nullptr); dgd_ = (uint16_t *)aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*dgd_)); ASSERT_NE(dgd_, nullptr); flt0_ = (int32_t *)aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*flt0_)); ASSERT_NE(flt0_, nullptr); flt1_ = (int32_t *)aom_malloc(MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*flt1_)); ASSERT_NE(flt1_, nullptr); } virtual void TearDown() { aom_free(src_); aom_free(dgd_); aom_free(flt0_); aom_free(flt1_); } void RunPixelProjErrorTest(int32_t run_times); void RunPixelProjErrorTest_ExtremeValues(); private: highbd_pixel_proj_error_func target_func_; libaom_test::ACMRandom rng_; uint16_t *src_; uint16_t *dgd_; int32_t *flt0_; int32_t *flt1_; }; void PixelProjHighbdErrorTest::RunPixelProjErrorTest(int32_t run_times) { int h_end = run_times != 1 ? 128 : (rng_.Rand16() % MAX_DATA_BLOCK) + 1; int v_end = run_times != 1 ? 128 : (rng_.Rand16() % MAX_DATA_BLOCK) + 1; const int dgd_stride = MAX_DATA_BLOCK; const int src_stride = MAX_DATA_BLOCK; const int flt0_stride = MAX_DATA_BLOCK; const int flt1_stride = MAX_DATA_BLOCK; sgr_params_type params; int xq[2]; const int iters = run_times == 1 ? kIterations : 4; for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) { int64_t err_ref = 0, err_test = 1; for (int i = 0; i < MAX_DATA_BLOCK * MAX_DATA_BLOCK; ++i) { dgd_[i] = rng_.Rand16() % (1 << 12); src_[i] = rng_.Rand16() % (1 << 12); flt0_[i] = rng_.Rand15Signed(); flt1_[i] = rng_.Rand15Signed(); } xq[0] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); xq[1] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); params.r[0] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter % 2); params.r[1] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter / 2); params.s[0] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter % 2); params.s[1] = run_times == 1 ? (rng_.Rand8() % MAX_RADIUS) : (iter / 2); uint8_t *dgd8 = CONVERT_TO_BYTEPTR(dgd_); uint8_t *src8 = CONVERT_TO_BYTEPTR(src_); aom_usec_timer timer; aom_usec_timer_start(&timer); for (int i = 0; i < run_times; ++i) { err_ref = av1_highbd_pixel_proj_error_c( src8, h_end, v_end, src_stride, dgd8, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); } aom_usec_timer_mark(&timer); const double time1 = static_cast(aom_usec_timer_elapsed(&timer)); aom_usec_timer_start(&timer); for (int i = 0; i < run_times; ++i) { err_test = target_func_(src8, h_end, v_end, src_stride, dgd8, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); } aom_usec_timer_mark(&timer); const double time2 = static_cast(aom_usec_timer_elapsed(&timer)); if (run_times > 10) { printf("r0 %d r1 %d %3dx%-3d:%7.2f/%7.2fns (%3.2f)\n", params.r[0], params.r[1], h_end, v_end, time1, time2, time1 / time2); } ASSERT_EQ(err_ref, err_test); } } void PixelProjHighbdErrorTest::RunPixelProjErrorTest_ExtremeValues() { const int h_start = 0; int h_end = 192; const int v_start = 0; int v_end = 192; const int dgd_stride = MAX_DATA_BLOCK; const int src_stride = MAX_DATA_BLOCK; const int flt0_stride = MAX_DATA_BLOCK; const int flt1_stride = MAX_DATA_BLOCK; sgr_params_type params; int xq[2]; const int iters = kIterations; for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) { int64_t err_ref = 0, err_test = 1; for (int i = 0; i < MAX_DATA_BLOCK * MAX_DATA_BLOCK; ++i) { dgd_[i] = 0; src_[i] = (1 << 12) - 1; flt0_[i] = rng_.Rand15Signed(); flt1_[i] = rng_.Rand15Signed(); } xq[0] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); xq[1] = rng_.Rand8() % (1 << SGRPROJ_PRJ_BITS); params.r[0] = rng_.Rand8() % MAX_RADIUS; params.r[1] = rng_.Rand8() % MAX_RADIUS; params.s[0] = rng_.Rand8() % MAX_RADIUS; params.s[1] = rng_.Rand8() % MAX_RADIUS; uint8_t *dgd8 = CONVERT_TO_BYTEPTR(dgd_); uint8_t *src8 = CONVERT_TO_BYTEPTR(src_); err_ref = av1_highbd_pixel_proj_error_c( src8, h_end - h_start, v_end - v_start, src_stride, dgd8, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); err_test = target_func_(src8, h_end - h_start, v_end - v_start, src_stride, dgd8, dgd_stride, flt0_, flt0_stride, flt1_, flt1_stride, xq, ¶ms); ASSERT_EQ(err_ref, err_test); } } TEST_P(PixelProjHighbdErrorTest, RandomValues) { RunPixelProjErrorTest(1); } TEST_P(PixelProjHighbdErrorTest, ExtremeValues) { RunPixelProjErrorTest_ExtremeValues(); } TEST_P(PixelProjHighbdErrorTest, DISABLED_Speed) { RunPixelProjErrorTest(200000); } #if HAVE_SSE4_1 INSTANTIATE_TEST_CASE_P(SSE4_1, PixelProjHighbdErrorTest, ::testing::Values(av1_highbd_pixel_proj_error_sse4_1)); #endif // HAVE_SSE4_1 #if HAVE_AVX2 INSTANTIATE_TEST_CASE_P(AVX2, PixelProjHighbdErrorTest, ::testing::Values(av1_highbd_pixel_proj_error_avx2)); #endif // HAVE_AVX2 } // namespace pickrst_test_highbd