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 23namespace libvpx_test { 24 25template <typename T> 26class Buffer { 27 public: 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 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 43 ~Buffer() { delete[] raw_buffer_; } 44 45 T *TopLeftPixel() const; 46 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: 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 107template <typename T> 108T *Buffer<T>::TopLeftPixel() const { 109 return raw_buffer_ + (top_padding_ * stride()) + left_padding_; 110} 111 112template <typename T> 113void 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 123template <typename T> 124void 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 134template <typename T> 135void 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 151template <typename T> 152void 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 162template <typename T> 163bool Buffer<T>::HasPadding() const { 164 return top_padding_ || left_padding_ || right_padding_ || bottom_padding_; 165} 166 167template <typename T> 168void 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 208template <typename T> 209void 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 218template <typename T> 219bool 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 232template <typename T> 233bool 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 279template <typename T> 280bool 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 299template <typename T> 300bool 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