• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 VPX_TEST_BUFFER_H_
12 #define VPX_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 #include "vpx_mem/vpx_mem.h"
23 
24 namespace libvpx_test {
25 
26 template <typename T>
27 class Buffer {
28  public:
Buffer(int width,int height,int top_padding,int left_padding,int right_padding,int bottom_padding)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) {}
35 
Buffer(int width,int height,int top_padding,int left_padding,int right_padding,int bottom_padding,unsigned int alignment)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) {}
43 
Buffer(int width,int height,int padding)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) {}
49 
Buffer(int width,int height,int padding,unsigned int alignment)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) {}
55 
~Buffer()56   ~Buffer() {
57     if (alignment_) {
58       vpx_free(raw_buffer_);
59     } else {
60       delete[] raw_buffer_;
61     }
62   }
63 
64   T *TopLeftPixel() const;
65 
stride()66   int stride() const { return stride_; }
67 
68   // Set the buffer (excluding padding) to 'value'.
69   void Set(const T value);
70 
71   // Set the buffer (excluding padding) to the output of ACMRandom function
72   // 'rand_func'.
73   void Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)());
74 
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
79   // here.
80   void Set(ACMRandom *rand_class, const T low, const T high);
81 
82   // Copy the contents of Buffer 'a' (excluding padding).
83   void CopyFrom(const Buffer<T> &a);
84 
85   void DumpBuffer() const;
86 
87   // Highlight the differences between two buffers if they are the same size.
88   void PrintDifference(const Buffer<T> &a) const;
89 
90   bool HasPadding() const;
91 
92   // Sets all the values in the buffer to 'padding_value'.
93   void SetPadding(const T padding_value);
94 
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;
98 
99   // Check that padding matches the expected value or there is no padding.
100   bool CheckPadding() const;
101 
102   // Compare the non-padding portion of two buffers if they are the same size.
103   bool CheckValues(const Buffer<T> &a) const;
104 
Init()105   bool Init() {
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);
116     if (alignment_) {
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
121       // a stride.
122       if (stride_ != width_) {
123         EXPECT_EQ((stride_ * sizeof(T)) % alignment_, 0u);
124       }
125       raw_buffer_ = reinterpret_cast<T *>(vpx_memalign(alignment_, raw_size_));
126     } else {
127       raw_buffer_ = new (std::nothrow) T[num_elements_];
128     }
129     EXPECT_NE(raw_buffer_, nullptr);
130     SetPadding(std::numeric_limits<T>::max());
131     return !::testing::Test::HasFailure();
132   }
133 
134  private:
135   bool BufferSizesMatch(const Buffer<T> &a) const;
136 
137   const int width_;
138   const int height_;
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_;
144   T padding_value_;
145   int stride_;
146   int raw_size_;
147   int num_elements_;
148   T *raw_buffer_;
149 };
150 
151 template <typename T>
TopLeftPixel()152 T *Buffer<T>::TopLeftPixel() const {
153   if (!raw_buffer_) return nullptr;
154   return raw_buffer_ + (top_padding_ * stride_) + left_padding_;
155 }
156 
157 template <typename T>
Set(const T value)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) {
163       src[width] = value;
164     }
165     src += stride_;
166   }
167 }
168 
169 template <typename T>
Set(ACMRandom * rand_class,T (ACMRandom::* rand_func)())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)();
176     }
177     src += stride_;
178   }
179 }
180 
181 template <typename T>
Set(ACMRandom * rand_class,const T low,const T high)182 void Buffer<T>::Set(ACMRandom *rand_class, const T low, const T high) {
183   if (!raw_buffer_) return;
184 
185   EXPECT_LE(low, high);
186   EXPECT_LE(static_cast<int64_t>(high) - low,
187             std::numeric_limits<int32_t>::max());
188 
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);
198     }
199     src += stride_;
200   }
201 }
202 
203 template <typename T>
CopyFrom(const Buffer<T> & a)204 void Buffer<T>::CopyFrom(const Buffer<T> &a) {
205   if (!raw_buffer_) return;
206   if (!BufferSizesMatch(a)) return;
207 
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];
213     }
214     a_src += a.stride();
215     b_src += this->stride();
216   }
217 }
218 
219 template <typename T>
DumpBuffer()220 void Buffer<T>::DumpBuffer() const {
221   if (!raw_buffer_) return;
222   for (int height = 0; height < height_ + top_padding_ + bottom_padding_;
223        ++height) {
224     for (int width = 0; width < stride_; ++width) {
225       printf("%4d", raw_buffer_[height + width * stride_]);
226     }
227     printf("\n");
228   }
229 }
230 
231 template <typename T>
HasPadding()232 bool Buffer<T>::HasPadding() const {
233   if (!raw_buffer_) return false;
234   return top_padding_ || left_padding_ || right_padding_ || bottom_padding_;
235 }
236 
237 template <typename T>
PrintDifference(const Buffer<T> & a)238 void Buffer<T>::PrintDifference(const Buffer<T> &a) const {
239   if (!raw_buffer_) return;
240   if (!BufferSizesMatch(a)) return;
241 
242   T *a_src = a.TopLeftPixel();
243   T *b_src = TopLeftPixel();
244 
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]);
250       } else {
251         printf("%4d", b_src[width]);
252       }
253     }
254     printf("\n");
255     a_src += a.stride();
256     b_src += this->stride();
257   }
258 
259   a_src = a.TopLeftPixel();
260   b_src = TopLeftPixel();
261 
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]);
267       } else {
268         printf("%4d", a_src[width]);
269       }
270     }
271     printf("\n");
272     a_src += a.stride();
273     b_src += this->stride();
274   }
275 }
276 
277 template <typename T>
SetPadding(const T padding_value)278 void Buffer<T>::SetPadding(const T padding_value) {
279   if (!raw_buffer_) return;
280   padding_value_ = padding_value;
281 
282   T *src = raw_buffer_;
283   for (int i = 0; i < num_elements_; ++i) {
284     src[i] = padding_value;
285   }
286 }
287 
288 template <typename T>
CheckValues(const T value)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]) {
295         return false;
296       }
297     }
298     src += stride_;
299   }
300   return true;
301 }
302 
303 template <typename T>
CheckPadding()304 bool Buffer<T>::CheckPadding() const {
305   if (!raw_buffer_) return false;
306   if (!HasPadding()) return true;
307 
308   // Top padding.
309   T const *top = raw_buffer_;
310   for (int i = 0; i < stride_ * top_padding_; ++i) {
311     if (padding_value_ != top[i]) {
312       return false;
313     }
314   }
315 
316   // Left padding.
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]) {
321         return false;
322       }
323     }
324     left += stride_;
325   }
326 
327   // Right padding.
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]) {
332         return false;
333       }
334     }
335     right += stride_;
336   }
337 
338   // Bottom padding
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]) {
342       return false;
343     }
344   }
345 
346   return true;
347 }
348 
349 template <typename T>
CheckValues(const Buffer<T> & a)350 bool Buffer<T>::CheckValues(const Buffer<T> &a) const {
351   if (!raw_buffer_) return false;
352   if (!BufferSizesMatch(a)) return false;
353 
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]) {
359         return false;
360       }
361     }
362     a_src += a.stride();
363     b_src += this->stride();
364   }
365   return true;
366 }
367 
368 template <typename T>
BufferSizesMatch(const Buffer<T> & a)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_) {
372     printf(
373         "Reference buffer of size %dx%d does not match this buffer which is "
374         "size %dx%d\n",
375         a.width_, a.height_, this->width_, this->height_);
376     return false;
377   }
378 
379   return true;
380 }
381 }  // namespace libvpx_test
382 #endif  // VPX_TEST_BUFFER_H_
383