2 * Copyright (c) 2016 The WebM project authors. All Rights Reserved.
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.
11 #ifndef VPX_TEST_BUFFER_H_
12 #define VPX_TEST_BUFFER_H_
18 #include "third_party/googletest/src/include/gtest/gtest.h"
20 #include "test/acm_random.h"
21 #include "vpx/vpx_integer.h"
22 #include "vpx_mem/vpx_mem.h"
24 namespace libvpx_test {
29 Buffer(int width, int height, int top_padding, int left_padding,
30 int right_padding, int bottom_padding)
31 : width_(width), height_(height), top_padding_(top_padding),
32 left_padding_(left_padding), right_padding_(right_padding),
33 bottom_padding_(bottom_padding), alignment_(0), padding_value_(0),
34 stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
36 Buffer(int width, int height, int top_padding, int left_padding,
37 int right_padding, int bottom_padding, unsigned int alignment)
38 : width_(width), height_(height), top_padding_(top_padding),
39 left_padding_(left_padding), right_padding_(right_padding),
40 bottom_padding_(bottom_padding), alignment_(alignment),
41 padding_value_(0), stride_(0), raw_size_(0), num_elements_(0),
42 raw_buffer_(nullptr) {}
44 Buffer(int width, int height, int padding)
45 : width_(width), height_(height), top_padding_(padding),
46 left_padding_(padding), right_padding_(padding),
47 bottom_padding_(padding), alignment_(0), padding_value_(0), stride_(0),
48 raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
50 Buffer(int width, int height, int padding, unsigned int alignment)
51 : width_(width), height_(height), top_padding_(padding),
52 left_padding_(padding), right_padding_(padding),
53 bottom_padding_(padding), alignment_(alignment), padding_value_(0),
54 stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
58 vpx_free(raw_buffer_);
64 T *TopLeftPixel() const;
66 int stride() const { return stride_; }
68 // Set the buffer (excluding padding) to 'value'.
69 void Set(const T value);
71 // Set the buffer (excluding padding) to the output of ACMRandom function
73 void Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)());
75 // Set the buffer (excluding padding) to the output of ACMRandom function
76 // 'RandRange' with range 'low' to 'high' which typically must be within
77 // testing::internal::Random::kMaxRange (1u << 31). However, because we want
78 // to allow negative low (and high) values, it is restricted to INT32_MAX
80 void Set(ACMRandom *rand_class, const T low, const T high);
82 // Copy the contents of Buffer 'a' (excluding padding).
83 void CopyFrom(const Buffer<T> &a);
85 void DumpBuffer() const;
87 // Highlight the differences between two buffers if they are the same size.
88 void PrintDifference(const Buffer<T> &a) const;
90 bool HasPadding() const;
92 // Sets all the values in the buffer to 'padding_value'.
93 void SetPadding(const T padding_value);
95 // Checks if all the values (excluding padding) are equal to 'value' if the
96 // Buffers are the same size.
97 bool CheckValues(const T value) const;
99 // Check that padding matches the expected value or there is no padding.
100 bool CheckPadding() const;
102 // Compare the non-padding portion of two buffers if they are the same size.
103 bool CheckValues(const Buffer<T> &a) const;
106 if (raw_buffer_ != nullptr) return false;
107 EXPECT_GT(width_, 0);
108 EXPECT_GT(height_, 0);
109 EXPECT_GE(top_padding_, 0);
110 EXPECT_GE(left_padding_, 0);
111 EXPECT_GE(right_padding_, 0);
112 EXPECT_GE(bottom_padding_, 0);
113 stride_ = left_padding_ + width_ + right_padding_;
114 num_elements_ = stride_ * (top_padding_ + height_ + bottom_padding_);
115 raw_size_ = num_elements_ * sizeof(T);
117 EXPECT_GE(alignment_, sizeof(T));
118 // Ensure alignment of the first value will be preserved.
119 EXPECT_EQ((left_padding_ * sizeof(T)) % alignment_, 0u);
120 // Ensure alignment of the subsequent rows will be preserved when there is
122 if (stride_ != width_) {
123 EXPECT_EQ((stride_ * sizeof(T)) % alignment_, 0u);
125 raw_buffer_ = reinterpret_cast<T *>(vpx_memalign(alignment_, raw_size_));
127 raw_buffer_ = new (std::nothrow) T[num_elements_];
129 EXPECT_NE(raw_buffer_, nullptr);
130 SetPadding(std::numeric_limits<T>::max());
131 return !::testing::Test::HasFailure();
135 bool BufferSizesMatch(const Buffer<T> &a) const;
139 const int top_padding_;
140 const int left_padding_;
141 const int right_padding_;
142 const int bottom_padding_;
143 const unsigned int alignment_;
151 template <typename T>
152 T *Buffer<T>::TopLeftPixel() const {
153 if (!raw_buffer_) return nullptr;
154 return raw_buffer_ + (top_padding_ * stride_) + left_padding_;
157 template <typename T>
158 void Buffer<T>::Set(const T value) {
159 if (!raw_buffer_) return;
160 T *src = TopLeftPixel();
161 for (int height = 0; height < height_; ++height) {
162 for (int width = 0; width < width_; ++width) {
169 template <typename T>
170 void Buffer<T>::Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)()) {
171 if (!raw_buffer_) return;
172 T *src = TopLeftPixel();
173 for (int height = 0; height < height_; ++height) {
174 for (int width = 0; width < width_; ++width) {
175 src[width] = (*rand_class.*rand_func)();
181 template <typename T>
182 void Buffer<T>::Set(ACMRandom *rand_class, const T low, const T high) {
183 if (!raw_buffer_) return;
185 EXPECT_LE(low, high);
186 EXPECT_LE(static_cast<int64_t>(high) - low,
187 std::numeric_limits<int32_t>::max());
189 T *src = TopLeftPixel();
190 for (int height = 0; height < height_; ++height) {
191 for (int width = 0; width < width_; ++width) {
192 // 'low' will be promoted to unsigned given the return type of RandRange.
193 // Store the value as an int to avoid unsigned overflow warnings when
194 // 'low' is negative.
195 const int32_t value =
196 static_cast<int32_t>((*rand_class).RandRange(high - low));
197 src[width] = static_cast<T>(value + low);
203 template <typename T>
204 void Buffer<T>::CopyFrom(const Buffer<T> &a) {
205 if (!raw_buffer_) return;
206 if (!BufferSizesMatch(a)) return;
208 T *a_src = a.TopLeftPixel();
209 T *b_src = this->TopLeftPixel();
210 for (int height = 0; height < height_; ++height) {
211 for (int width = 0; width < width_; ++width) {
212 b_src[width] = a_src[width];
215 b_src += this->stride();
219 template <typename T>
220 void Buffer<T>::DumpBuffer() const {
221 if (!raw_buffer_) return;
222 for (int height = 0; height < height_ + top_padding_ + bottom_padding_;
224 for (int width = 0; width < stride_; ++width) {
225 printf("%4d", raw_buffer_[height + width * stride_]);
231 template <typename T>
232 bool Buffer<T>::HasPadding() const {
233 if (!raw_buffer_) return false;
234 return top_padding_ || left_padding_ || right_padding_ || bottom_padding_;
237 template <typename T>
238 void Buffer<T>::PrintDifference(const Buffer<T> &a) const {
239 if (!raw_buffer_) return;
240 if (!BufferSizesMatch(a)) return;
242 T *a_src = a.TopLeftPixel();
243 T *b_src = TopLeftPixel();
245 printf("This buffer:\n");
246 for (int height = 0; height < height_; ++height) {
247 for (int width = 0; width < width_; ++width) {
248 if (a_src[width] != b_src[width]) {
249 printf("*%3d", b_src[width]);
251 printf("%4d", b_src[width]);
256 b_src += this->stride();
259 a_src = a.TopLeftPixel();
260 b_src = TopLeftPixel();
262 printf("Reference buffer:\n");
263 for (int height = 0; height < height_; ++height) {
264 for (int width = 0; width < width_; ++width) {
265 if (a_src[width] != b_src[width]) {
266 printf("*%3d", a_src[width]);
268 printf("%4d", a_src[width]);
273 b_src += this->stride();
277 template <typename T>
278 void Buffer<T>::SetPadding(const T padding_value) {
279 if (!raw_buffer_) return;
280 padding_value_ = padding_value;
282 T *src = raw_buffer_;
283 for (int i = 0; i < num_elements_; ++i) {
284 src[i] = padding_value;
288 template <typename T>
289 bool Buffer<T>::CheckValues(const T value) const {
290 if (!raw_buffer_) return false;
291 T *src = TopLeftPixel();
292 for (int height = 0; height < height_; ++height) {
293 for (int width = 0; width < width_; ++width) {
294 if (value != src[width]) {
303 template <typename T>
304 bool Buffer<T>::CheckPadding() const {
305 if (!raw_buffer_) return false;
306 if (!HasPadding()) return true;
309 T const *top = raw_buffer_;
310 for (int i = 0; i < stride_ * top_padding_; ++i) {
311 if (padding_value_ != top[i]) {
317 T const *left = TopLeftPixel() - left_padding_;
318 for (int height = 0; height < height_; ++height) {
319 for (int width = 0; width < left_padding_; ++width) {
320 if (padding_value_ != left[width]) {
328 T const *right = TopLeftPixel() + width_;
329 for (int height = 0; height < height_; ++height) {
330 for (int width = 0; width < right_padding_; ++width) {
331 if (padding_value_ != right[width]) {
339 T const *bottom = raw_buffer_ + (top_padding_ + height_) * stride_;
340 for (int i = 0; i < stride_ * bottom_padding_; ++i) {
341 if (padding_value_ != bottom[i]) {
349 template <typename T>
350 bool Buffer<T>::CheckValues(const Buffer<T> &a) const {
351 if (!raw_buffer_) return false;
352 if (!BufferSizesMatch(a)) return false;
354 T *a_src = a.TopLeftPixel();
355 T *b_src = this->TopLeftPixel();
356 for (int height = 0; height < height_; ++height) {
357 for (int width = 0; width < width_; ++width) {
358 if (a_src[width] != b_src[width]) {
363 b_src += this->stride();
368 template <typename T>
369 bool Buffer<T>::BufferSizesMatch(const Buffer<T> &a) const {
370 if (!raw_buffer_) return false;
371 if (a.width_ != this->width_ || a.height_ != this->height_) {
373 "Reference buffer of size %dx%d does not match this buffer which is "
375 a.width_, a.height_, this->width_, this->height_);
381 } // namespace libvpx_test
382 #endif // VPX_TEST_BUFFER_H_