1/*
2 *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10#include <math.h>
11#include "test/clear_system_state.h"
12#include "test/register_state_check.h"
13#include "third_party/googletest/src/include/gtest/gtest.h"
14#include "./vpx_dsp_rtcd.h"
15#include "vpx/vpx_integer.h"
16#include "vpx_dsp/postproc.h"
17#include "vpx_mem/vpx_mem.h"
18
19namespace {
20
21static const int kNoiseSize = 3072;
22
23// TODO(jimbankoski): make width and height integers not unsigned.
24typedef void (*AddNoiseFunc)(uint8_t *start, const int8_t *noise,
25                             int blackclamp, int whiteclamp, int width,
26                             int height, int pitch);
27
28class AddNoiseTest : public ::testing::TestWithParam<AddNoiseFunc> {
29 public:
30  virtual void TearDown() { libvpx_test::ClearSystemState(); }
31  virtual ~AddNoiseTest() {}
32};
33
34double stddev6(char a, char b, char c, char d, char e, char f) {
35  const double n = (a + b + c + d + e + f) / 6.0;
36  const double v = ((a - n) * (a - n) + (b - n) * (b - n) + (c - n) * (c - n) +
37                    (d - n) * (d - n) + (e - n) * (e - n) + (f - n) * (f - n)) /
38                   6.0;
39  return sqrt(v);
40}
41
42TEST_P(AddNoiseTest, CheckNoiseAdded) {
43  const int width = 64;
44  const int height = 64;
45  const int image_size = width * height;
46  int8_t noise[kNoiseSize];
47  const int clamp = vpx_setup_noise(4.4, noise, kNoiseSize);
48  uint8_t *const s =
49      reinterpret_cast<uint8_t *>(vpx_calloc(image_size, sizeof(*s)));
50  ASSERT_TRUE(s != NULL);
51  memset(s, 99, image_size * sizeof(*s));
52
53  ASM_REGISTER_STATE_CHECK(
54      GetParam()(s, noise, clamp, clamp, width, height, width));
55
56  // Check to make sure we don't end up having either the same or no added
57  // noise either vertically or horizontally.
58  for (int i = 0; i < image_size - 6 * width - 6; ++i) {
59    const double hd = stddev6(s[i] - 99, s[i + 1] - 99, s[i + 2] - 99,
60                              s[i + 3] - 99, s[i + 4] - 99, s[i + 5] - 99);
61    const double vd = stddev6(s[i] - 99, s[i + width] - 99,
62                              s[i + 2 * width] - 99, s[i + 3 * width] - 99,
63                              s[i + 4 * width] - 99, s[i + 5 * width] - 99);
64
65    EXPECT_NE(hd, 0);
66    EXPECT_NE(vd, 0);
67  }
68
69  // Initialize pixels in the image to 255 and check for roll over.
70  memset(s, 255, image_size);
71
72  ASM_REGISTER_STATE_CHECK(
73      GetParam()(s, noise, clamp, clamp, width, height, width));
74
75  // Check to make sure don't roll over.
76  for (int i = 0; i < image_size; ++i) {
77    EXPECT_GT(static_cast<int>(s[i]), clamp) << "i = " << i;
78  }
79
80  // Initialize pixels in the image to 0 and check for roll under.
81  memset(s, 0, image_size);
82
83  ASM_REGISTER_STATE_CHECK(
84      GetParam()(s, noise, clamp, clamp, width, height, width));
85
86  // Check to make sure don't roll under.
87  for (int i = 0; i < image_size; ++i) {
88    EXPECT_LT(static_cast<int>(s[i]), 255 - clamp) << "i = " << i;
89  }
90
91  vpx_free(s);
92}
93
94TEST_P(AddNoiseTest, CheckCvsAssembly) {
95  const int width = 64;
96  const int height = 64;
97  const int image_size = width * height;
98  int8_t noise[kNoiseSize];
99  const int clamp = vpx_setup_noise(4.4, noise, kNoiseSize);
100
101  uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
102  uint8_t *const d = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
103  ASSERT_TRUE(s != NULL);
104  ASSERT_TRUE(d != NULL);
105
106  memset(s, 99, image_size);
107  memset(d, 99, image_size);
108
109  srand(0);
110  ASM_REGISTER_STATE_CHECK(
111      GetParam()(s, noise, clamp, clamp, width, height, width));
112  srand(0);
113  ASM_REGISTER_STATE_CHECK(
114      vpx_plane_add_noise_c(d, noise, clamp, clamp, width, height, width));
115
116  for (int i = 0; i < image_size; ++i) {
117    EXPECT_EQ(static_cast<int>(s[i]), static_cast<int>(d[i])) << "i = " << i;
118  }
119
120  vpx_free(d);
121  vpx_free(s);
122}
123
124INSTANTIATE_TEST_CASE_P(C, AddNoiseTest,
125                        ::testing::Values(vpx_plane_add_noise_c));
126
127#if HAVE_SSE2
128INSTANTIATE_TEST_CASE_P(SSE2, AddNoiseTest,
129                        ::testing::Values(vpx_plane_add_noise_sse2));
130#endif
131
132#if HAVE_MSA
133INSTANTIATE_TEST_CASE_P(MSA, AddNoiseTest,
134                        ::testing::Values(vpx_plane_add_noise_msa));
135#endif
136}  // namespace
137