henrike@webrtc.org | 704bf9e | 2014-02-27 17:52:04 +0000 | [diff] [blame] | 1 | /* |
| 2 | * libjingle |
| 3 | * Copyright 2010 Google Inc. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions are met: |
| 7 | * |
| 8 | * 1. Redistributions of source code must retain the above copyright notice, |
| 9 | * this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 | * this list of conditions and the following disclaimer in the documentation |
| 12 | * and/or other materials provided with the distribution. |
| 13 | * 3. The name of the author may not be used to endorse or promote products |
| 14 | * derived from this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| 19 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #include <sstream> |
| 29 | |
| 30 | #include "libyuv/cpu_id.h" |
| 31 | #include "libyuv/scale.h" |
| 32 | #include "talk/base/basictypes.h" |
| 33 | #include "talk/base/flags.h" |
| 34 | #include "talk/base/gunit.h" |
| 35 | #include "talk/base/scoped_ptr.h" |
| 36 | #include "talk/media/base/testutils.h" |
| 37 | |
| 38 | #if defined(_MSC_VER) |
| 39 | #define ALIGN16(var) __declspec(align(16)) var |
| 40 | #else |
| 41 | #define ALIGN16(var) var __attribute__((aligned(16))) |
| 42 | #endif |
| 43 | |
| 44 | using cricket::LoadPlanarYuvTestImage; |
| 45 | using cricket::DumpPlanarYuvTestImage; |
| 46 | using talk_base::scoped_ptr; |
| 47 | |
| 48 | DEFINE_bool(yuvscaler_dump, false, |
| 49 | "whether to write out scaled images for inspection"); |
| 50 | DEFINE_int(yuvscaler_repeat, 1, |
| 51 | "how many times to perform each scaling operation (for perf testing)"); |
| 52 | |
| 53 | static const int kAlignment = 16; |
| 54 | |
| 55 | // TEST_UNCACHED flushes cache to test real memory performance. |
| 56 | // TEST_RSTSC uses cpu cycles for more accurate benchmark of the scale function. |
| 57 | #ifndef __arm__ |
| 58 | // #define TEST_UNCACHED 1 |
| 59 | // #define TEST_RSTSC 1 |
| 60 | #endif |
| 61 | |
| 62 | #if defined(TEST_UNCACHED) || defined(TEST_RSTSC) |
| 63 | #ifdef _MSC_VER |
| 64 | #include <emmintrin.h> // NOLINT |
| 65 | #endif |
| 66 | |
| 67 | #if defined(__GNUC__) && defined(__i386__) |
| 68 | static inline uint64 __rdtsc(void) { |
| 69 | uint32_t a, d; |
| 70 | __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); |
| 71 | return (reinterpret_cast<uint64>(d) << 32) + a; |
| 72 | } |
| 73 | |
| 74 | static inline void _mm_clflush(volatile void *__p) { |
| 75 | asm volatile("clflush %0" : "+m" (*(volatile char *)__p)); |
| 76 | } |
| 77 | #endif |
| 78 | |
| 79 | static void FlushCache(uint8* dst, int count) { |
| 80 | while (count >= 32) { |
| 81 | _mm_clflush(dst); |
| 82 | dst += 32; |
| 83 | count -= 32; |
| 84 | } |
| 85 | } |
| 86 | #endif |
| 87 | |
| 88 | class YuvScalerTest : public testing::Test { |
| 89 | protected: |
| 90 | virtual void SetUp() { |
| 91 | dump_ = *FlagList::Lookup("yuvscaler_dump")->bool_variable(); |
| 92 | repeat_ = *FlagList::Lookup("yuvscaler_repeat")->int_variable(); |
| 93 | } |
| 94 | |
| 95 | // Scale an image and compare against a Lanczos-filtered test image. |
| 96 | // Lanczos is considered to be the "ideal" image resampling method, so we try |
| 97 | // to get as close to that as possible, while being as fast as possible. |
| 98 | bool TestScale(int iw, int ih, int ow, int oh, int offset, bool usefile, |
| 99 | bool optimize, int cpuflags, bool interpolate, |
| 100 | int memoffset, double* error) { |
| 101 | *error = 0.; |
| 102 | size_t isize = I420_SIZE(iw, ih); |
| 103 | size_t osize = I420_SIZE(ow, oh); |
| 104 | scoped_ptr<uint8[]> ibuffer(new uint8[isize + kAlignment + memoffset]()); |
| 105 | scoped_ptr<uint8[]> obuffer(new uint8[osize + kAlignment + memoffset]()); |
| 106 | scoped_ptr<uint8[]> xbuffer(new uint8[osize + kAlignment + memoffset]()); |
| 107 | |
| 108 | uint8 *ibuf = ALIGNP(ibuffer.get(), kAlignment) + memoffset; |
| 109 | uint8 *obuf = ALIGNP(obuffer.get(), kAlignment) + memoffset; |
| 110 | uint8 *xbuf = ALIGNP(xbuffer.get(), kAlignment) + memoffset; |
| 111 | |
| 112 | if (usefile) { |
| 113 | if (!LoadPlanarYuvTestImage("faces", iw, ih, ibuf) || |
| 114 | !LoadPlanarYuvTestImage("faces", ow, oh, xbuf)) { |
| 115 | LOG(LS_ERROR) << "Failed to load image"; |
| 116 | return false; |
| 117 | } |
| 118 | } else { |
| 119 | // These are used to test huge images. |
| 120 | memset(ibuf, 213, isize); // Input is constant color. |
| 121 | memset(obuf, 100, osize); // Output set to something wrong for now. |
| 122 | memset(xbuf, 213, osize); // Expected result. |
| 123 | } |
| 124 | |
| 125 | #ifdef TEST_UNCACHED |
| 126 | FlushCache(ibuf, isize); |
| 127 | FlushCache(obuf, osize); |
| 128 | FlushCache(xbuf, osize); |
| 129 | #endif |
| 130 | |
| 131 | // Scale down. |
| 132 | // If cpu true, disable cpu optimizations. Else allow auto detect |
| 133 | // TODO(fbarchard): set flags for libyuv |
| 134 | libyuv::MaskCpuFlags(cpuflags); |
| 135 | #ifdef TEST_RSTSC |
| 136 | uint64 t = 0; |
| 137 | #endif |
| 138 | for (int i = 0; i < repeat_; ++i) { |
| 139 | #ifdef TEST_UNCACHED |
| 140 | FlushCache(ibuf, isize); |
| 141 | FlushCache(obuf, osize); |
| 142 | #endif |
| 143 | #ifdef TEST_RSTSC |
| 144 | uint64 t1 = __rdtsc(); |
| 145 | #endif |
| 146 | EXPECT_EQ(0, libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, |
| 147 | offset, interpolate)); |
| 148 | #ifdef TEST_RSTSC |
| 149 | uint64 t2 = __rdtsc(); |
| 150 | t += t2 - t1; |
| 151 | #endif |
| 152 | } |
| 153 | |
| 154 | #ifdef TEST_RSTSC |
| 155 | LOG(LS_INFO) << "Time: " << std::setw(9) << t; |
| 156 | #endif |
| 157 | |
| 158 | if (dump_) { |
| 159 | const testing::TestInfo* const test_info = |
| 160 | testing::UnitTest::GetInstance()->current_test_info(); |
| 161 | std::string test_name(test_info->name()); |
| 162 | DumpPlanarYuvTestImage(test_name, obuf, ow, oh); |
| 163 | } |
| 164 | |
| 165 | double sse = cricket::ComputeSumSquareError(obuf, xbuf, osize); |
| 166 | *error = sse / osize; // Mean Squared Error. |
| 167 | double PSNR = cricket::ComputePSNR(sse, osize); |
| 168 | LOG(LS_INFO) << "Image MSE: " << |
| 169 | std::setw(6) << std::setprecision(4) << *error << |
| 170 | " Image PSNR: " << PSNR; |
| 171 | return true; |
| 172 | } |
| 173 | |
| 174 | // Returns the index of the first differing byte. Easier to debug than memcmp. |
| 175 | static int FindDiff(const uint8* buf1, const uint8* buf2, int len) { |
| 176 | int i = 0; |
| 177 | while (i < len && buf1[i] == buf2[i]) { |
| 178 | i++; |
| 179 | } |
| 180 | return (i < len) ? i : -1; |
| 181 | } |
| 182 | |
| 183 | protected: |
| 184 | bool dump_; |
| 185 | int repeat_; |
| 186 | }; |
| 187 | |
| 188 | // Tests straight copy of data. |
| 189 | TEST_F(YuvScalerTest, TestCopy) { |
| 190 | const int iw = 640, ih = 360; |
| 191 | const int ow = 640, oh = 360; |
| 192 | ALIGN16(uint8 ibuf[I420_SIZE(iw, ih)]); |
| 193 | ALIGN16(uint8 obuf[I420_SIZE(ow, oh)]); |
| 194 | |
| 195 | // Load the frame, scale it, check it. |
| 196 | ASSERT_TRUE(LoadPlanarYuvTestImage("faces", iw, ih, ibuf)); |
| 197 | for (int i = 0; i < repeat_; ++i) { |
| 198 | libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, 0, false); |
| 199 | } |
| 200 | if (dump_) DumpPlanarYuvTestImage("TestCopy", obuf, ow, oh); |
| 201 | EXPECT_EQ(-1, FindDiff(obuf, ibuf, sizeof(ibuf))); |
| 202 | } |
| 203 | |
| 204 | // Tests copy from 4:3 to 16:9. |
| 205 | TEST_F(YuvScalerTest, TestOffset16_10Copy) { |
| 206 | const int iw = 640, ih = 360; |
| 207 | const int ow = 640, oh = 480; |
| 208 | const int offset = (480 - 360) / 2; |
| 209 | scoped_ptr<uint8[]> ibuffer(new uint8[I420_SIZE(iw, ih) + kAlignment]); |
| 210 | scoped_ptr<uint8[]> obuffer(new uint8[I420_SIZE(ow, oh) + kAlignment]); |
| 211 | |
| 212 | uint8 *ibuf = ALIGNP(ibuffer.get(), kAlignment); |
| 213 | uint8 *obuf = ALIGNP(obuffer.get(), kAlignment); |
| 214 | |
| 215 | // Load the frame, scale it, check it. |
| 216 | ASSERT_TRUE(LoadPlanarYuvTestImage("faces", iw, ih, ibuf)); |
| 217 | |
| 218 | // Clear to black, which is Y = 0 and U and V = 128 |
| 219 | memset(obuf, 0, ow * oh); |
| 220 | memset(obuf + ow * oh, 128, ow * oh / 2); |
| 221 | for (int i = 0; i < repeat_; ++i) { |
| 222 | libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, offset, false); |
| 223 | } |
| 224 | if (dump_) DumpPlanarYuvTestImage("TestOffsetCopy16_9", obuf, ow, oh); |
| 225 | EXPECT_EQ(-1, FindDiff(obuf + ow * offset, |
| 226 | ibuf, |
| 227 | iw * ih)); |
| 228 | EXPECT_EQ(-1, FindDiff(obuf + ow * oh + ow * offset / 4, |
| 229 | ibuf + iw * ih, |
| 230 | iw * ih / 4)); |
| 231 | EXPECT_EQ(-1, FindDiff(obuf + ow * oh * 5 / 4 + ow * offset / 4, |
| 232 | ibuf + iw * ih * 5 / 4, |
| 233 | iw * ih / 4)); |
| 234 | } |
| 235 | |
| 236 | // The following are 'cpu' flag values: |
| 237 | // Allow all SIMD optimizations |
| 238 | #define ALLFLAGS -1 |
| 239 | // Disable SSSE3 but allow other forms of SIMD (SSE2) |
| 240 | #define NOSSSE3 ~libyuv::kCpuHasSSSE3 |
| 241 | // Disable SSE2 and SSSE3 |
| 242 | #define NOSSE ~libyuv::kCpuHasSSE2 & ~libyuv::kCpuHasSSSE3 |
| 243 | |
| 244 | // TEST_M scale factor with variations of opt, align, int |
| 245 | #define TEST_M(name, iwidth, iheight, owidth, oheight, mse) \ |
| 246 | TEST_F(YuvScalerTest, name##Ref) { \ |
| 247 | double error; \ |
| 248 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 249 | 0, true, false, ALLFLAGS, false, 0, &error)); \ |
| 250 | EXPECT_LE(error, mse); \ |
| 251 | } \ |
| 252 | TEST_F(YuvScalerTest, name##OptAligned) { \ |
| 253 | double error; \ |
| 254 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 255 | 0, true, true, ALLFLAGS, false, 0, &error)); \ |
| 256 | EXPECT_LE(error, mse); \ |
| 257 | } \ |
| 258 | TEST_F(YuvScalerTest, name##OptUnaligned) { \ |
| 259 | double error; \ |
| 260 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 261 | 0, true, true, ALLFLAGS, false, 1, &error)); \ |
| 262 | EXPECT_LE(error, mse); \ |
| 263 | } \ |
| 264 | TEST_F(YuvScalerTest, name##OptSSE2) { \ |
| 265 | double error; \ |
| 266 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 267 | 0, true, true, NOSSSE3, false, 0, &error)); \ |
| 268 | EXPECT_LE(error, mse); \ |
| 269 | } \ |
| 270 | TEST_F(YuvScalerTest, name##OptC) { \ |
| 271 | double error; \ |
| 272 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 273 | 0, true, true, NOSSE, false, 0, &error)); \ |
| 274 | EXPECT_LE(error, mse); \ |
| 275 | } \ |
| 276 | TEST_F(YuvScalerTest, name##IntRef) { \ |
| 277 | double error; \ |
| 278 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 279 | 0, true, false, ALLFLAGS, true, 0, &error)); \ |
| 280 | EXPECT_LE(error, mse); \ |
| 281 | } \ |
| 282 | TEST_F(YuvScalerTest, name##IntOptAligned) { \ |
| 283 | double error; \ |
| 284 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 285 | 0, true, true, ALLFLAGS, true, 0, &error)); \ |
| 286 | EXPECT_LE(error, mse); \ |
| 287 | } \ |
| 288 | TEST_F(YuvScalerTest, name##IntOptUnaligned) { \ |
| 289 | double error; \ |
| 290 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 291 | 0, true, true, ALLFLAGS, true, 1, &error)); \ |
| 292 | EXPECT_LE(error, mse); \ |
| 293 | } \ |
| 294 | TEST_F(YuvScalerTest, name##IntOptSSE2) { \ |
| 295 | double error; \ |
| 296 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 297 | 0, true, true, NOSSSE3, true, 0, &error)); \ |
| 298 | EXPECT_LE(error, mse); \ |
| 299 | } \ |
| 300 | TEST_F(YuvScalerTest, name##IntOptC) { \ |
| 301 | double error; \ |
| 302 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 303 | 0, true, true, NOSSE, true, 0, &error)); \ |
| 304 | EXPECT_LE(error, mse); \ |
| 305 | } |
| 306 | |
| 307 | #define TEST_H(name, iwidth, iheight, owidth, oheight, opt, cpu, intr, mse) \ |
| 308 | TEST_F(YuvScalerTest, name) { \ |
| 309 | double error; \ |
| 310 | EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ |
| 311 | 0, false, opt, cpu, intr, 0, &error)); \ |
| 312 | EXPECT_LE(error, mse); \ |
| 313 | } |
| 314 | |
| 315 | // Test 4x3 aspect ratio scaling |
| 316 | |
| 317 | // Tests 1/1x scale down. |
| 318 | TEST_M(TestScale4by3Down11, 640, 480, 640, 480, 0) |
| 319 | |
| 320 | // Tests 3/4x scale down. |
| 321 | TEST_M(TestScale4by3Down34, 640, 480, 480, 360, 60) |
| 322 | |
| 323 | // Tests 1/2x scale down. |
| 324 | TEST_M(TestScale4by3Down12, 640, 480, 320, 240, 60) |
| 325 | |
| 326 | // Tests 3/8x scale down. |
| 327 | TEST_M(TestScale4by3Down38, 640, 480, 240, 180, 60) |
| 328 | |
| 329 | // Tests 1/4x scale down.. |
| 330 | TEST_M(TestScale4by3Down14, 640, 480, 160, 120, 60) |
| 331 | |
| 332 | // Tests 3/16x scale down. |
| 333 | TEST_M(TestScale4by3Down316, 640, 480, 120, 90, 120) |
| 334 | |
| 335 | // Tests 1/8x scale down. |
| 336 | TEST_M(TestScale4by3Down18, 640, 480, 80, 60, 150) |
| 337 | |
| 338 | // Tests 2/3x scale down. |
| 339 | TEST_M(TestScale4by3Down23, 480, 360, 320, 240, 60) |
| 340 | |
| 341 | // Tests 4/3x scale up. |
| 342 | TEST_M(TestScale4by3Up43, 480, 360, 640, 480, 60) |
| 343 | |
| 344 | // Tests 2/1x scale up. |
| 345 | TEST_M(TestScale4by3Up21, 320, 240, 640, 480, 60) |
| 346 | |
| 347 | // Tests 4/1x scale up. |
| 348 | TEST_M(TestScale4by3Up41, 160, 120, 640, 480, 80) |
| 349 | |
| 350 | // Test 16x10 aspect ratio scaling |
| 351 | |
| 352 | // Tests 1/1x scale down. |
| 353 | TEST_M(TestScale16by10Down11, 640, 400, 640, 400, 0) |
| 354 | |
| 355 | // Tests 3/4x scale down. |
| 356 | TEST_M(TestScale16by10Down34, 640, 400, 480, 300, 60) |
| 357 | |
| 358 | // Tests 1/2x scale down. |
| 359 | TEST_M(TestScale16by10Down12, 640, 400, 320, 200, 60) |
| 360 | |
| 361 | // Tests 3/8x scale down. |
| 362 | TEST_M(TestScale16by10Down38, 640, 400, 240, 150, 60) |
| 363 | |
| 364 | // Tests 1/4x scale down.. |
| 365 | TEST_M(TestScale16by10Down14, 640, 400, 160, 100, 60) |
| 366 | |
| 367 | // Tests 3/16x scale down. |
| 368 | TEST_M(TestScale16by10Down316, 640, 400, 120, 75, 120) |
| 369 | |
| 370 | // Tests 1/8x scale down. |
| 371 | TEST_M(TestScale16by10Down18, 640, 400, 80, 50, 150) |
| 372 | |
| 373 | // Tests 2/3x scale down. |
| 374 | TEST_M(TestScale16by10Down23, 480, 300, 320, 200, 60) |
| 375 | |
| 376 | // Tests 4/3x scale up. |
| 377 | TEST_M(TestScale16by10Up43, 480, 300, 640, 400, 60) |
| 378 | |
| 379 | // Tests 2/1x scale up. |
| 380 | TEST_M(TestScale16by10Up21, 320, 200, 640, 400, 60) |
| 381 | |
| 382 | // Tests 4/1x scale up. |
| 383 | TEST_M(TestScale16by10Up41, 160, 100, 640, 400, 80) |
| 384 | |
| 385 | // Test 16x9 aspect ratio scaling |
| 386 | |
| 387 | // Tests 1/1x scale down. |
| 388 | TEST_M(TestScaleDown11, 640, 360, 640, 360, 0) |
| 389 | |
| 390 | // Tests 3/4x scale down. |
| 391 | TEST_M(TestScaleDown34, 640, 360, 480, 270, 60) |
| 392 | |
| 393 | // Tests 1/2x scale down. |
| 394 | TEST_M(TestScaleDown12, 640, 360, 320, 180, 60) |
| 395 | |
| 396 | // Tests 3/8x scale down. |
| 397 | TEST_M(TestScaleDown38, 640, 360, 240, 135, 60) |
| 398 | |
| 399 | // Tests 1/4x scale down.. |
| 400 | TEST_M(TestScaleDown14, 640, 360, 160, 90, 60) |
| 401 | |
| 402 | // Tests 3/16x scale down. |
| 403 | TEST_M(TestScaleDown316, 640, 360, 120, 68, 120) |
| 404 | |
| 405 | // Tests 1/8x scale down. |
| 406 | TEST_M(TestScaleDown18, 640, 360, 80, 45, 150) |
| 407 | |
| 408 | // Tests 2/3x scale down. |
| 409 | TEST_M(TestScaleDown23, 480, 270, 320, 180, 60) |
| 410 | |
| 411 | // Tests 4/3x scale up. |
| 412 | TEST_M(TestScaleUp43, 480, 270, 640, 360, 60) |
| 413 | |
| 414 | // Tests 2/1x scale up. |
| 415 | TEST_M(TestScaleUp21, 320, 180, 640, 360, 60) |
| 416 | |
| 417 | // Tests 4/1x scale up. |
| 418 | TEST_M(TestScaleUp41, 160, 90, 640, 360, 80) |
| 419 | |
| 420 | // Test HD 4x3 aspect ratio scaling |
| 421 | |
| 422 | // Tests 1/1x scale down. |
| 423 | TEST_M(TestScaleHD4x3Down11, 1280, 960, 1280, 960, 0) |
| 424 | |
| 425 | // Tests 3/4x scale down. |
| 426 | TEST_M(TestScaleHD4x3Down34, 1280, 960, 960, 720, 60) |
| 427 | |
| 428 | // Tests 1/2x scale down. |
| 429 | TEST_M(TestScaleHD4x3Down12, 1280, 960, 640, 480, 60) |
| 430 | |
| 431 | // Tests 3/8x scale down. |
| 432 | TEST_M(TestScaleHD4x3Down38, 1280, 960, 480, 360, 60) |
| 433 | |
| 434 | // Tests 1/4x scale down.. |
| 435 | TEST_M(TestScaleHD4x3Down14, 1280, 960, 320, 240, 60) |
| 436 | |
| 437 | // Tests 3/16x scale down. |
| 438 | TEST_M(TestScaleHD4x3Down316, 1280, 960, 240, 180, 120) |
| 439 | |
| 440 | // Tests 1/8x scale down. |
| 441 | TEST_M(TestScaleHD4x3Down18, 1280, 960, 160, 120, 150) |
| 442 | |
| 443 | // Tests 2/3x scale down. |
| 444 | TEST_M(TestScaleHD4x3Down23, 960, 720, 640, 480, 60) |
| 445 | |
| 446 | // Tests 4/3x scale up. |
| 447 | TEST_M(TestScaleHD4x3Up43, 960, 720, 1280, 960, 60) |
| 448 | |
| 449 | // Tests 2/1x scale up. |
| 450 | TEST_M(TestScaleHD4x3Up21, 640, 480, 1280, 960, 60) |
| 451 | |
| 452 | // Tests 4/1x scale up. |
| 453 | TEST_M(TestScaleHD4x3Up41, 320, 240, 1280, 960, 80) |
| 454 | |
| 455 | // Test HD 16x10 aspect ratio scaling |
| 456 | |
| 457 | // Tests 1/1x scale down. |
| 458 | TEST_M(TestScaleHD16x10Down11, 1280, 800, 1280, 800, 0) |
| 459 | |
| 460 | // Tests 3/4x scale down. |
| 461 | TEST_M(TestScaleHD16x10Down34, 1280, 800, 960, 600, 60) |
| 462 | |
| 463 | // Tests 1/2x scale down. |
| 464 | TEST_M(TestScaleHD16x10Down12, 1280, 800, 640, 400, 60) |
| 465 | |
| 466 | // Tests 3/8x scale down. |
| 467 | TEST_M(TestScaleHD16x10Down38, 1280, 800, 480, 300, 60) |
| 468 | |
| 469 | // Tests 1/4x scale down.. |
| 470 | TEST_M(TestScaleHD16x10Down14, 1280, 800, 320, 200, 60) |
| 471 | |
| 472 | // Tests 3/16x scale down. |
| 473 | TEST_M(TestScaleHD16x10Down316, 1280, 800, 240, 150, 120) |
| 474 | |
| 475 | // Tests 1/8x scale down. |
| 476 | TEST_M(TestScaleHD16x10Down18, 1280, 800, 160, 100, 150) |
| 477 | |
| 478 | // Tests 2/3x scale down. |
| 479 | TEST_M(TestScaleHD16x10Down23, 960, 600, 640, 400, 60) |
| 480 | |
| 481 | // Tests 4/3x scale up. |
| 482 | TEST_M(TestScaleHD16x10Up43, 960, 600, 1280, 800, 60) |
| 483 | |
| 484 | // Tests 2/1x scale up. |
| 485 | TEST_M(TestScaleHD16x10Up21, 640, 400, 1280, 800, 60) |
| 486 | |
| 487 | // Tests 4/1x scale up. |
| 488 | TEST_M(TestScaleHD16x10Up41, 320, 200, 1280, 800, 80) |
| 489 | |
| 490 | // Test HD 16x9 aspect ratio scaling |
| 491 | |
| 492 | // Tests 1/1x scale down. |
| 493 | TEST_M(TestScaleHDDown11, 1280, 720, 1280, 720, 0) |
| 494 | |
| 495 | // Tests 3/4x scale down. |
| 496 | TEST_M(TestScaleHDDown34, 1280, 720, 960, 540, 60) |
| 497 | |
| 498 | // Tests 1/2x scale down. |
| 499 | TEST_M(TestScaleHDDown12, 1280, 720, 640, 360, 60) |
| 500 | |
| 501 | // Tests 3/8x scale down. |
| 502 | TEST_M(TestScaleHDDown38, 1280, 720, 480, 270, 60) |
| 503 | |
| 504 | // Tests 1/4x scale down.. |
| 505 | TEST_M(TestScaleHDDown14, 1280, 720, 320, 180, 60) |
| 506 | |
| 507 | // Tests 3/16x scale down. |
| 508 | TEST_M(TestScaleHDDown316, 1280, 720, 240, 135, 120) |
| 509 | |
| 510 | // Tests 1/8x scale down. |
| 511 | TEST_M(TestScaleHDDown18, 1280, 720, 160, 90, 150) |
| 512 | |
| 513 | // Tests 2/3x scale down. |
| 514 | TEST_M(TestScaleHDDown23, 960, 540, 640, 360, 60) |
| 515 | |
| 516 | // Tests 4/3x scale up. |
| 517 | TEST_M(TestScaleHDUp43, 960, 540, 1280, 720, 60) |
| 518 | |
| 519 | // Tests 2/1x scale up. |
| 520 | TEST_M(TestScaleHDUp21, 640, 360, 1280, 720, 60) |
| 521 | |
| 522 | // Tests 4/1x scale up. |
| 523 | TEST_M(TestScaleHDUp41, 320, 180, 1280, 720, 80) |
| 524 | |
| 525 | // Tests 1366x768 resolution for comparison to chromium scaler_bench |
| 526 | TEST_M(TestScaleHDUp1366, 1280, 720, 1366, 768, 10) |
| 527 | |
| 528 | // Tests odd source/dest sizes. 3 less to make chroma odd as well. |
| 529 | TEST_M(TestScaleHDUp1363, 1277, 717, 1363, 765, 10) |
| 530 | |
| 531 | // Tests 1/2x scale down, using optimized algorithm. |
| 532 | TEST_M(TestScaleOddDown12, 180, 100, 90, 50, 50) |
| 533 | |
| 534 | // Tests bilinear scale down |
| 535 | TEST_M(TestScaleOddDownBilin, 160, 100, 90, 50, 120) |
| 536 | |
| 537 | // Test huge buffer scales that are expected to use a different code path |
| 538 | // that avoids stack overflow but still work using point sampling. |
| 539 | // Max output size is 640 wide. |
| 540 | |
| 541 | // Tests interpolated 1/8x scale down, using optimized algorithm. |
| 542 | TEST_H(TestScaleDown18HDOptInt, 6144, 48, 768, 6, true, ALLFLAGS, true, 1) |
| 543 | |
| 544 | // Tests interpolated 1/8x scale down, using c_only optimized algorithm. |
| 545 | TEST_H(TestScaleDown18HDCOnlyOptInt, 6144, 48, 768, 6, true, NOSSE, true, 1) |
| 546 | |
| 547 | // Tests interpolated 3/8x scale down, using optimized algorithm. |
| 548 | TEST_H(TestScaleDown38HDOptInt, 2048, 16, 768, 6, true, ALLFLAGS, true, 1) |
| 549 | |
| 550 | // Tests interpolated 3/8x scale down, using no SSSE3 optimized algorithm. |
| 551 | TEST_H(TestScaleDown38HDNoSSSE3OptInt, 2048, 16, 768, 6, true, NOSSSE3, true, 1) |
| 552 | |
| 553 | // Tests interpolated 3/8x scale down, using c_only optimized algorithm. |
| 554 | TEST_H(TestScaleDown38HDCOnlyOptInt, 2048, 16, 768, 6, true, NOSSE, true, 1) |
| 555 | |
| 556 | // Tests interpolated 3/16x scale down, using optimized algorithm. |
| 557 | TEST_H(TestScaleDown316HDOptInt, 4096, 32, 768, 6, true, ALLFLAGS, true, 1) |
| 558 | |
| 559 | // Tests interpolated 3/16x scale down, using no SSSE3 optimized algorithm. |
| 560 | TEST_H(TestScaleDown316HDNoSSSE3OptInt, 4096, 32, 768, 6, true, NOSSSE3, true, |
| 561 | 1) |
| 562 | |
| 563 | // Tests interpolated 3/16x scale down, using c_only optimized algorithm. |
| 564 | TEST_H(TestScaleDown316HDCOnlyOptInt, 4096, 32, 768, 6, true, NOSSE, true, 1) |
| 565 | |
| 566 | // Test special sizes dont crash |
| 567 | // Tests scaling down to 1 pixel width |
| 568 | TEST_H(TestScaleDown1x6OptInt, 3, 24, 1, 6, true, ALLFLAGS, true, 4) |
| 569 | |
| 570 | // Tests scaling down to 1 pixel height |
| 571 | TEST_H(TestScaleDown6x1OptInt, 24, 3, 6, 1, true, ALLFLAGS, true, 4) |
| 572 | |
| 573 | // Tests scaling up from 1 pixel width |
| 574 | TEST_H(TestScaleUp1x6OptInt, 1, 6, 3, 24, true, ALLFLAGS, true, 4) |
| 575 | |
| 576 | // Tests scaling up from 1 pixel height |
| 577 | TEST_H(TestScaleUp6x1OptInt, 6, 1, 24, 3, true, ALLFLAGS, true, 4) |
| 578 | |
| 579 | // Test performance of a range of box filter scale sizes |
| 580 | |
| 581 | // Tests interpolated 1/2x scale down, using optimized algorithm. |
| 582 | TEST_H(TestScaleDown2xHDOptInt, 1280, 720, 1280 / 2, 720 / 2, true, ALLFLAGS, |
| 583 | true, 1) |
| 584 | |
| 585 | // Tests interpolated 1/3x scale down, using optimized algorithm. |
| 586 | TEST_H(TestScaleDown3xHDOptInt, 1280, 720, 1280 / 3, 720 / 3, true, ALLFLAGS, |
| 587 | true, 1) |
| 588 | |
| 589 | // Tests interpolated 1/4x scale down, using optimized algorithm. |
| 590 | TEST_H(TestScaleDown4xHDOptInt, 1280, 720, 1280 / 4, 720 / 4, true, ALLFLAGS, |
| 591 | true, 1) |
| 592 | |
| 593 | // Tests interpolated 1/5x scale down, using optimized algorithm. |
| 594 | TEST_H(TestScaleDown5xHDOptInt, 1280, 720, 1280 / 5, 720 / 5, true, ALLFLAGS, |
| 595 | true, 1) |
| 596 | |
| 597 | // Tests interpolated 1/6x scale down, using optimized algorithm. |
| 598 | TEST_H(TestScaleDown6xHDOptInt, 1280, 720, 1280 / 6, 720 / 6, true, ALLFLAGS, |
| 599 | true, 1) |
| 600 | |
| 601 | // Tests interpolated 1/7x scale down, using optimized algorithm. |
| 602 | TEST_H(TestScaleDown7xHDOptInt, 1280, 720, 1280 / 7, 720 / 7, true, ALLFLAGS, |
| 603 | true, 1) |
| 604 | |
| 605 | // Tests interpolated 1/8x scale down, using optimized algorithm. |
| 606 | TEST_H(TestScaleDown8xHDOptInt, 1280, 720, 1280 / 8, 720 / 8, true, ALLFLAGS, |
| 607 | true, 1) |
| 608 | |
| 609 | // Tests interpolated 1/8x scale down, using optimized algorithm. |
| 610 | TEST_H(TestScaleDown9xHDOptInt, 1280, 720, 1280 / 9, 720 / 9, true, ALLFLAGS, |
| 611 | true, 1) |
| 612 | |
| 613 | // Tests interpolated 1/8x scale down, using optimized algorithm. |
| 614 | TEST_H(TestScaleDown10xHDOptInt, 1280, 720, 1280 / 10, 720 / 10, true, ALLFLAGS, |
| 615 | true, 1) |