• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <tuple>
16 
17 #include "config/av1_rtcd.h"
18 
19 #include "aom_mem/aom_mem.h"
20 #include "aom_ports/aom_timer.h"
21 #include "aom_ports/mem.h"
22 #include "test/acm_random.h"
23 #include "test/util.h"
24 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
25 
26 namespace {
27 typedef int64_t (*frame_error_func)(const uint8_t *const ref, int stride,
28                                     const uint8_t *const dst, int p_width,
29                                     int p_height, int p_stride);
30 #if HAVE_AVX2 || HAVE_SSE2
31 const int kBlockWidth[] = {
32   832, 834, 640, 1280, 1920,
33 };
34 const int kBlockHeight[] = {
35   480, 482, 360, 720, 1080,
36 };
37 #endif
38 typedef std::tuple<frame_error_func, int, int> FrameErrorParam;
39 
40 class AV1FrameErrorTest : public ::testing::TestWithParam<FrameErrorParam> {
41  public:
~AV1FrameErrorTest()42   virtual ~AV1FrameErrorTest() {}
SetUp()43   virtual void SetUp() {
44     rnd_.Reset(libaom_test::ACMRandom::DeterministicSeed());
45   }
TearDown()46   virtual void TearDown() {}
47 
48  protected:
49   void RandomValues(frame_error_func test_impl, int width, int height);
50   void ExtremeValues(frame_error_func test_impl, int width, int height);
51   void RunSpeedTest(frame_error_func test_impl, int width, int height);
52   libaom_test::ACMRandom rnd_;
53 };
54 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1FrameErrorTest);
55 
RandomValues(frame_error_func test_impl,int width,int height)56 void AV1FrameErrorTest::RandomValues(frame_error_func test_impl, int width,
57                                      int height) {
58   const int stride = (((width * 3) / 2) + 15) & ~15;
59   const int max_blk_size = stride * height;
60   uint8_t *const dst =
61       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*dst)));
62   uint8_t *const ref =
63       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*ref)));
64   ASSERT_NE(dst, nullptr);
65   ASSERT_NE(ref, nullptr);
66   for (int i = 0; i < max_blk_size; ++i) {
67     dst[i] = rnd_.Rand8();
68     ref[i] = rnd_.Rand8();
69   }
70   const int64_t ref_error =
71       av1_calc_frame_error_c(ref, stride, dst, width, height, stride);
72   const int64_t test_error = test_impl(ref, stride, dst, width, height, stride);
73   ASSERT_EQ(test_error, ref_error) << width << "x" << height;
74   aom_free(dst);
75   aom_free(ref);
76 }
77 
ExtremeValues(frame_error_func test_impl,int width,int height)78 void AV1FrameErrorTest::ExtremeValues(frame_error_func test_impl, int width,
79                                       int height) {
80   const int stride = (((width * 3) / 2) + 15) & ~15;
81   const int max_blk_size = stride * height;
82   uint8_t *const dst =
83       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*dst)));
84   uint8_t *const ref =
85       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*ref)));
86   ASSERT_NE(dst, nullptr);
87   ASSERT_NE(ref, nullptr);
88   for (int r = 0; r < 2; r++) {
89     if (r == 0) {
90       memset(dst, 0, max_blk_size);
91       memset(ref, 255, max_blk_size);
92     } else if (r == 1) {
93       memset(dst, 255, max_blk_size);
94       memset(ref, 0, max_blk_size);
95     }
96     const int64_t ref_error =
97         av1_calc_frame_error_c(ref, stride, dst, width, height, stride);
98     const int64_t test_error =
99         test_impl(ref, stride, dst, width, height, stride);
100     ASSERT_EQ(test_error, ref_error) << width << "x" << height;
101   }
102   aom_free(dst);
103   aom_free(ref);
104 }
105 
RunSpeedTest(frame_error_func test_impl,int width,int height)106 void AV1FrameErrorTest::RunSpeedTest(frame_error_func test_impl, int width,
107                                      int height) {
108   const int stride = (((width * 3) / 2) + 15) & ~15;
109   const int max_blk_size = stride * height;
110   uint8_t *const dst =
111       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*dst)));
112   uint8_t *const ref =
113       static_cast<uint8_t *>(aom_memalign(16, max_blk_size * sizeof(*ref)));
114   ASSERT_NE(dst, nullptr);
115   ASSERT_NE(ref, nullptr);
116   for (int i = 0; i < max_blk_size; ++i) {
117     dst[i] = ref[i] = rnd_.Rand8();
118   }
119   const int num_loops = 10000000 / (width + height);
120   frame_error_func funcs[2] = { av1_calc_frame_error_c, test_impl };
121   double elapsed_time[2] = { 0 };
122   for (int i = 0; i < 2; ++i) {
123     aom_usec_timer timer;
124     aom_usec_timer_start(&timer);
125     frame_error_func func = funcs[i];
126     for (int j = 0; j < num_loops; ++j) {
127       func(ref, stride, dst, width, height, stride);
128     }
129     aom_usec_timer_mark(&timer);
130     double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
131     elapsed_time[i] = 1000.0 * time / num_loops;
132   }
133   aom_free(dst);
134   aom_free(ref);
135   printf("av1_calc_frame_error %3dx%-3d: %7.2f/%7.2fns", width, height,
136          elapsed_time[0], elapsed_time[1]);
137   printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
138 }
139 
TEST_P(AV1FrameErrorTest,CheckOutput)140 TEST_P(AV1FrameErrorTest, CheckOutput) {
141   RandomValues(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2));
142   ExtremeValues(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2));
143 }
144 
TEST_P(AV1FrameErrorTest,DISABLED_Speed)145 TEST_P(AV1FrameErrorTest, DISABLED_Speed) {
146   RunSpeedTest(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2));
147 }
148 
149 #if HAVE_SSE2
150 INSTANTIATE_TEST_SUITE_P(
151     SSE2, AV1FrameErrorTest,
152     ::testing::Combine(::testing::Values(&av1_calc_frame_error_sse2),
153                        ::testing::ValuesIn(kBlockWidth),
154                        ::testing::ValuesIn(kBlockHeight)));
155 #endif
156 
157 #if HAVE_AVX2
158 INSTANTIATE_TEST_SUITE_P(
159     AVX2, AV1FrameErrorTest,
160     ::testing::Combine(::testing::Values(&av1_calc_frame_error_avx2),
161                        ::testing::ValuesIn(kBlockWidth),
162                        ::testing::ValuesIn(kBlockHeight)));
163 #endif
164 }  // namespace
165