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
11 #ifndef TEST_BUFFER_H_
12 #define TEST_BUFFER_H_
13
14 #include <stdio.h>
15
16 #include <limits>
17
18 #include "third_party/googletest/src/include/gtest/gtest.h"
19
20 #include "test/acm_random.h"
21 #include "vpx/vpx_integer.h"
22
23 namespace libvpx_test {
24
25 template <typename T>
26 class Buffer {
27 public:
Buffer(int width,int height,int top_padding,int left_padding,int right_padding,int bottom_padding)28 Buffer(int width, int height, int top_padding, int left_padding,
29 int right_padding, int bottom_padding)
30 : width_(width), height_(height), top_padding_(top_padding),
31 left_padding_(left_padding), right_padding_(right_padding),
32 bottom_padding_(bottom_padding) {
33 Init();
34 }
35
Buffer(int width,int height,int padding)36 Buffer(int width, int height, int padding)
37 : width_(width), height_(height), top_padding_(padding),
38 left_padding_(padding), right_padding_(padding),
39 bottom_padding_(padding) {
40 Init();
41 }
42
~Buffer()43 ~Buffer() { delete[] raw_buffer_; }
44
45 T *TopLeftPixel() const;
46
stride()47 int stride() const { return stride_; }
48
49 // Set the buffer (excluding padding) to 'value'.
50 void Set(const int value);
51
52 // Set the buffer (excluding padding) to the output of ACMRandom function 'b'.
53 void Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)());
54
55 // Copy the contents of Buffer 'a' (excluding padding).
56 void CopyFrom(const Buffer<T> &a);
57
58 void DumpBuffer() const;
59
60 // Highlight the differences between two buffers if they are the same size.
61 void PrintDifference(const Buffer<T> &a) const;
62
63 bool HasPadding() const;
64
65 // Sets all the values in the buffer to 'padding_value'.
66 void SetPadding(const int padding_value);
67
68 // Checks if all the values (excluding padding) are equal to 'value' if the
69 // Buffers are the same size.
70 bool CheckValues(const int value) const;
71
72 // Check that padding matches the expected value or there is no padding.
73 bool CheckPadding() const;
74
75 // Compare the non-padding portion of two buffers if they are the same size.
76 bool CheckValues(const Buffer<T> &a) const;
77
78 private:
Init()79 void Init() {
80 ASSERT_GT(width_, 0);
81 ASSERT_GT(height_, 0);
82 ASSERT_GE(top_padding_, 0);
83 ASSERT_GE(left_padding_, 0);
84 ASSERT_GE(right_padding_, 0);
85 ASSERT_GE(bottom_padding_, 0);
86 stride_ = left_padding_ + width_ + right_padding_;
87 raw_size_ = stride_ * (top_padding_ + height_ + bottom_padding_);
88 raw_buffer_ = new (std::nothrow) T[raw_size_];
89 ASSERT_TRUE(raw_buffer_ != NULL);
90 SetPadding(std::numeric_limits<T>::max());
91 }
92
93 bool BufferSizesMatch(const Buffer<T> &a) const;
94
95 const int width_;
96 const int height_;
97 const int top_padding_;
98 const int left_padding_;
99 const int right_padding_;
100 const int bottom_padding_;
101 int padding_value_;
102 int stride_;
103 int raw_size_;
104 T *raw_buffer_;
105 };
106
107 template <typename T>
TopLeftPixel()108 T *Buffer<T>::TopLeftPixel() const {
109 return raw_buffer_ + (top_padding_ * stride()) + left_padding_;
110 }
111
112 template <typename T>
Set(const int value)113 void Buffer<T>::Set(const int value) {
114 T *src = TopLeftPixel();
115 for (int height = 0; height < height_; ++height) {
116 for (int width = 0; width < width_; ++width) {
117 src[width] = value;
118 }
119 src += stride();
120 }
121 }
122
123 template <typename T>
Set(ACMRandom * rand_class,T (ACMRandom::* rand_func)())124 void Buffer<T>::Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)()) {
125 T *src = TopLeftPixel();
126 for (int height = 0; height < height_; ++height) {
127 for (int width = 0; width < width_; ++width) {
128 src[width] = (*rand_class.*rand_func)();
129 }
130 src += stride();
131 }
132 }
133
134 template <typename T>
CopyFrom(const Buffer<T> & a)135 void Buffer<T>::CopyFrom(const Buffer<T> &a) {
136 if (!BufferSizesMatch(a)) {
137 return;
138 }
139
140 T *a_src = a.TopLeftPixel();
141 T *b_src = this->TopLeftPixel();
142 for (int height = 0; height < height_; ++height) {
143 for (int width = 0; width < width_; ++width) {
144 b_src[width] = a_src[width];
145 }
146 a_src += a.stride();
147 b_src += this->stride();
148 }
149 }
150
151 template <typename T>
DumpBuffer()152 void Buffer<T>::DumpBuffer() const {
153 for (int height = 0; height < height_ + top_padding_ + bottom_padding_;
154 ++height) {
155 for (int width = 0; width < stride(); ++width) {
156 printf("%4d", raw_buffer_[height + width * stride()]);
157 }
158 printf("\n");
159 }
160 }
161
162 template <typename T>
HasPadding()163 bool Buffer<T>::HasPadding() const {
164 return top_padding_ || left_padding_ || right_padding_ || bottom_padding_;
165 }
166
167 template <typename T>
PrintDifference(const Buffer<T> & a)168 void Buffer<T>::PrintDifference(const Buffer<T> &a) const {
169 if (!BufferSizesMatch(a)) {
170 return;
171 }
172
173 T *a_src = a.TopLeftPixel();
174 T *b_src = TopLeftPixel();
175
176 printf("This buffer:\n");
177 for (int height = 0; height < height_; ++height) {
178 for (int width = 0; width < width_; ++width) {
179 if (a_src[width] != b_src[width]) {
180 printf("*%3d", b_src[width]);
181 } else {
182 printf("%4d", b_src[width]);
183 }
184 }
185 printf("\n");
186 a_src += a.stride();
187 b_src += this->stride();
188 }
189
190 a_src = a.TopLeftPixel();
191 b_src = TopLeftPixel();
192
193 printf("Reference buffer:\n");
194 for (int height = 0; height < height_; ++height) {
195 for (int width = 0; width < width_; ++width) {
196 if (a_src[width] != b_src[width]) {
197 printf("*%3d", a_src[width]);
198 } else {
199 printf("%4d", a_src[width]);
200 }
201 }
202 printf("\n");
203 a_src += a.stride();
204 b_src += this->stride();
205 }
206 }
207
208 template <typename T>
SetPadding(const int padding_value)209 void Buffer<T>::SetPadding(const int padding_value) {
210 padding_value_ = padding_value;
211
212 T *src = raw_buffer_;
213 for (int i = 0; i < raw_size_; ++i) {
214 src[i] = padding_value;
215 }
216 }
217
218 template <typename T>
CheckValues(const int value)219 bool Buffer<T>::CheckValues(const int value) const {
220 T *src = TopLeftPixel();
221 for (int height = 0; height < height_; ++height) {
222 for (int width = 0; width < width_; ++width) {
223 if (value != src[width]) {
224 return false;
225 }
226 }
227 src += stride();
228 }
229 return true;
230 }
231
232 template <typename T>
CheckPadding()233 bool Buffer<T>::CheckPadding() const {
234 if (!HasPadding()) {
235 return true;
236 }
237
238 // Top padding.
239 T const *top = raw_buffer_;
240 for (int i = 0; i < stride() * top_padding_; ++i) {
241 if (padding_value_ != top[i]) {
242 return false;
243 }
244 }
245
246 // Left padding.
247 T const *left = TopLeftPixel() - left_padding_;
248 for (int height = 0; height < height_; ++height) {
249 for (int width = 0; width < left_padding_; ++width) {
250 if (padding_value_ != left[width]) {
251 return false;
252 }
253 }
254 left += stride();
255 }
256
257 // Right padding.
258 T const *right = TopLeftPixel() + width_;
259 for (int height = 0; height < height_; ++height) {
260 for (int width = 0; width < right_padding_; ++width) {
261 if (padding_value_ != right[width]) {
262 return false;
263 }
264 }
265 right += stride();
266 }
267
268 // Bottom padding
269 T const *bottom = raw_buffer_ + (top_padding_ + height_) * stride();
270 for (int i = 0; i < stride() * bottom_padding_; ++i) {
271 if (padding_value_ != bottom[i]) {
272 return false;
273 }
274 }
275
276 return true;
277 }
278
279 template <typename T>
CheckValues(const Buffer<T> & a)280 bool Buffer<T>::CheckValues(const Buffer<T> &a) const {
281 if (!BufferSizesMatch(a)) {
282 return false;
283 }
284
285 T *a_src = a.TopLeftPixel();
286 T *b_src = this->TopLeftPixel();
287 for (int height = 0; height < height_; ++height) {
288 for (int width = 0; width < width_; ++width) {
289 if (a_src[width] != b_src[width]) {
290 return false;
291 }
292 }
293 a_src += a.stride();
294 b_src += this->stride();
295 }
296 return true;
297 }
298
299 template <typename T>
BufferSizesMatch(const Buffer<T> & a)300 bool Buffer<T>::BufferSizesMatch(const Buffer<T> &a) const {
301 if (a.width_ != this->width_ || a.height_ != this->height_) {
302 printf(
303 "Reference buffer of size %dx%d does not match this buffer which is "
304 "size %dx%d\n",
305 a.width_, a.height_, this->width_, this->height_);
306 return false;
307 }
308
309 return true;
310 }
311 } // namespace libvpx_test
312 #endif // TEST_BUFFER_H_
313