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/media/base/testutils.h"
33#include "webrtc/base/basictypes.h"
34#include "webrtc/base/flags.h"
35#include "webrtc/base/gunit.h"
36#include "webrtc/base/scoped_ptr.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
44using cricket::LoadPlanarYuvTestImage;
45using cricket::DumpPlanarYuvTestImage;
46using rtc::scoped_ptr;
47
48DEFINE_bool(yuvscaler_dump, false,
49    "whether to write out scaled images for inspection");
50DEFINE_int(yuvscaler_repeat, 1,
51    "how many times to perform each scaling operation (for perf testing)");
52
53static 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__)
68static 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
74static inline void _mm_clflush(volatile void *__p) {
75  asm volatile("clflush %0" : "+m" (*(volatile char *)__p));
76}
77#endif
78
79static 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
88class YuvScalerTest : public testing::Test {
89 protected:
90  virtual void SetUp() {
91    dump_ = *rtc::FlagList::Lookup("yuvscaler_dump")->bool_variable();
92    repeat_ = *rtc::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.
189TEST_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.
205TEST_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) \
246TEST_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} \
252TEST_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} \
258TEST_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} \
264TEST_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} \
270TEST_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} \
276TEST_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} \
282TEST_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} \
288TEST_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} \
294TEST_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} \
300TEST_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) \
308TEST_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.
318TEST_M(TestScale4by3Down11, 640, 480, 640, 480, 0)
319
320// Tests 3/4x scale down.
321TEST_M(TestScale4by3Down34, 640, 480, 480, 360, 60)
322
323// Tests 1/2x scale down.
324TEST_M(TestScale4by3Down12, 640, 480, 320, 240, 60)
325
326// Tests 3/8x scale down.
327TEST_M(TestScale4by3Down38, 640, 480, 240, 180, 60)
328
329// Tests 1/4x scale down..
330TEST_M(TestScale4by3Down14, 640, 480, 160, 120, 60)
331
332// Tests 3/16x scale down.
333TEST_M(TestScale4by3Down316, 640, 480, 120, 90, 120)
334
335// Tests 1/8x scale down.
336TEST_M(TestScale4by3Down18, 640, 480, 80, 60, 150)
337
338// Tests 2/3x scale down.
339TEST_M(TestScale4by3Down23, 480, 360, 320, 240, 60)
340
341// Tests 4/3x scale up.
342TEST_M(TestScale4by3Up43, 480, 360, 640, 480, 60)
343
344// Tests 2/1x scale up.
345TEST_M(TestScale4by3Up21, 320, 240, 640, 480, 60)
346
347// Tests 4/1x scale up.
348TEST_M(TestScale4by3Up41, 160, 120, 640, 480, 80)
349
350// Test 16x10 aspect ratio scaling
351
352// Tests 1/1x scale down.
353TEST_M(TestScale16by10Down11, 640, 400, 640, 400, 0)
354
355// Tests 3/4x scale down.
356TEST_M(TestScale16by10Down34, 640, 400, 480, 300, 60)
357
358// Tests 1/2x scale down.
359TEST_M(TestScale16by10Down12, 640, 400, 320, 200, 60)
360
361// Tests 3/8x scale down.
362TEST_M(TestScale16by10Down38, 640, 400, 240, 150, 60)
363
364// Tests 1/4x scale down..
365TEST_M(TestScale16by10Down14, 640, 400, 160, 100, 60)
366
367// Tests 3/16x scale down.
368TEST_M(TestScale16by10Down316, 640, 400, 120, 75, 120)
369
370// Tests 1/8x scale down.
371TEST_M(TestScale16by10Down18, 640, 400, 80, 50, 150)
372
373// Tests 2/3x scale down.
374TEST_M(TestScale16by10Down23, 480, 300, 320, 200, 60)
375
376// Tests 4/3x scale up.
377TEST_M(TestScale16by10Up43, 480, 300, 640, 400, 60)
378
379// Tests 2/1x scale up.
380TEST_M(TestScale16by10Up21, 320, 200, 640, 400, 60)
381
382// Tests 4/1x scale up.
383TEST_M(TestScale16by10Up41, 160, 100, 640, 400, 80)
384
385// Test 16x9 aspect ratio scaling
386
387// Tests 1/1x scale down.
388TEST_M(TestScaleDown11, 640, 360, 640, 360, 0)
389
390// Tests 3/4x scale down.
391TEST_M(TestScaleDown34, 640, 360, 480, 270, 60)
392
393// Tests 1/2x scale down.
394TEST_M(TestScaleDown12, 640, 360, 320, 180, 60)
395
396// Tests 3/8x scale down.
397TEST_M(TestScaleDown38, 640, 360, 240, 135, 60)
398
399// Tests 1/4x scale down..
400TEST_M(TestScaleDown14, 640, 360, 160, 90, 60)
401
402// Tests 3/16x scale down.
403TEST_M(TestScaleDown316, 640, 360, 120, 68, 120)
404
405// Tests 1/8x scale down.
406TEST_M(TestScaleDown18, 640, 360, 80, 45, 150)
407
408// Tests 2/3x scale down.
409TEST_M(TestScaleDown23, 480, 270, 320, 180, 60)
410
411// Tests 4/3x scale up.
412TEST_M(TestScaleUp43, 480, 270, 640, 360, 60)
413
414// Tests 2/1x scale up.
415TEST_M(TestScaleUp21, 320, 180, 640, 360, 60)
416
417// Tests 4/1x scale up.
418TEST_M(TestScaleUp41, 160, 90, 640, 360, 80)
419
420// Test HD 4x3 aspect ratio scaling
421
422// Tests 1/1x scale down.
423TEST_M(TestScaleHD4x3Down11, 1280, 960, 1280, 960, 0)
424
425// Tests 3/4x scale down.
426TEST_M(TestScaleHD4x3Down34, 1280, 960, 960, 720, 60)
427
428// Tests 1/2x scale down.
429TEST_M(TestScaleHD4x3Down12, 1280, 960, 640, 480, 60)
430
431// Tests 3/8x scale down.
432TEST_M(TestScaleHD4x3Down38, 1280, 960, 480, 360, 60)
433
434// Tests 1/4x scale down..
435TEST_M(TestScaleHD4x3Down14, 1280, 960, 320, 240, 60)
436
437// Tests 3/16x scale down.
438TEST_M(TestScaleHD4x3Down316, 1280, 960, 240, 180, 120)
439
440// Tests 1/8x scale down.
441TEST_M(TestScaleHD4x3Down18, 1280, 960, 160, 120, 150)
442
443// Tests 2/3x scale down.
444TEST_M(TestScaleHD4x3Down23, 960, 720, 640, 480, 60)
445
446// Tests 4/3x scale up.
447TEST_M(TestScaleHD4x3Up43, 960, 720, 1280, 960, 60)
448
449// Tests 2/1x scale up.
450TEST_M(TestScaleHD4x3Up21, 640, 480, 1280, 960, 60)
451
452// Tests 4/1x scale up.
453TEST_M(TestScaleHD4x3Up41, 320, 240, 1280, 960, 80)
454
455// Test HD 16x10 aspect ratio scaling
456
457// Tests 1/1x scale down.
458TEST_M(TestScaleHD16x10Down11, 1280, 800, 1280, 800, 0)
459
460// Tests 3/4x scale down.
461TEST_M(TestScaleHD16x10Down34, 1280, 800, 960, 600, 60)
462
463// Tests 1/2x scale down.
464TEST_M(TestScaleHD16x10Down12, 1280, 800, 640, 400, 60)
465
466// Tests 3/8x scale down.
467TEST_M(TestScaleHD16x10Down38, 1280, 800, 480, 300, 60)
468
469// Tests 1/4x scale down..
470TEST_M(TestScaleHD16x10Down14, 1280, 800, 320, 200, 60)
471
472// Tests 3/16x scale down.
473TEST_M(TestScaleHD16x10Down316, 1280, 800, 240, 150, 120)
474
475// Tests 1/8x scale down.
476TEST_M(TestScaleHD16x10Down18, 1280, 800, 160, 100, 150)
477
478// Tests 2/3x scale down.
479TEST_M(TestScaleHD16x10Down23, 960, 600, 640, 400, 60)
480
481// Tests 4/3x scale up.
482TEST_M(TestScaleHD16x10Up43, 960, 600, 1280, 800, 60)
483
484// Tests 2/1x scale up.
485TEST_M(TestScaleHD16x10Up21, 640, 400, 1280, 800, 60)
486
487// Tests 4/1x scale up.
488TEST_M(TestScaleHD16x10Up41, 320, 200, 1280, 800, 80)
489
490// Test HD 16x9 aspect ratio scaling
491
492// Tests 1/1x scale down.
493TEST_M(TestScaleHDDown11, 1280, 720, 1280, 720, 0)
494
495// Tests 3/4x scale down.
496TEST_M(TestScaleHDDown34, 1280, 720, 960, 540, 60)
497
498// Tests 1/2x scale down.
499TEST_M(TestScaleHDDown12, 1280, 720, 640, 360, 60)
500
501// Tests 3/8x scale down.
502TEST_M(TestScaleHDDown38, 1280, 720, 480, 270, 60)
503
504// Tests 1/4x scale down..
505TEST_M(TestScaleHDDown14, 1280, 720, 320, 180, 60)
506
507// Tests 3/16x scale down.
508TEST_M(TestScaleHDDown316, 1280, 720, 240, 135, 120)
509
510// Tests 1/8x scale down.
511TEST_M(TestScaleHDDown18, 1280, 720, 160, 90, 150)
512
513// Tests 2/3x scale down.
514TEST_M(TestScaleHDDown23, 960, 540, 640, 360, 60)
515
516// Tests 4/3x scale up.
517TEST_M(TestScaleHDUp43, 960, 540, 1280, 720, 60)
518
519// Tests 2/1x scale up.
520TEST_M(TestScaleHDUp21, 640, 360, 1280, 720, 60)
521
522// Tests 4/1x scale up.
523TEST_M(TestScaleHDUp41, 320, 180, 1280, 720, 80)
524
525// Tests 1366x768 resolution for comparison to chromium scaler_bench
526TEST_M(TestScaleHDUp1366, 1280, 720, 1366, 768, 10)
527
528// Tests odd source/dest sizes.  3 less to make chroma odd as well.
529TEST_M(TestScaleHDUp1363, 1277, 717, 1363, 765, 10)
530
531// Tests 1/2x scale down, using optimized algorithm.
532TEST_M(TestScaleOddDown12, 180, 100, 90, 50, 50)
533
534// Tests bilinear scale down
535TEST_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.
542TEST_H(TestScaleDown18HDOptInt, 6144, 48, 768, 6, true, ALLFLAGS, true, 1)
543
544// Tests interpolated 1/8x scale down, using c_only optimized algorithm.
545TEST_H(TestScaleDown18HDCOnlyOptInt, 6144, 48, 768, 6, true, NOSSE, true, 1)
546
547// Tests interpolated 3/8x scale down, using optimized algorithm.
548TEST_H(TestScaleDown38HDOptInt, 2048, 16, 768, 6, true, ALLFLAGS, true, 1)
549
550// Tests interpolated 3/8x scale down, using no SSSE3 optimized algorithm.
551TEST_H(TestScaleDown38HDNoSSSE3OptInt, 2048, 16, 768, 6, true, NOSSSE3, true, 1)
552
553// Tests interpolated 3/8x scale down, using c_only optimized algorithm.
554TEST_H(TestScaleDown38HDCOnlyOptInt, 2048, 16, 768, 6, true, NOSSE, true, 1)
555
556// Tests interpolated 3/16x scale down, using optimized algorithm.
557TEST_H(TestScaleDown316HDOptInt, 4096, 32, 768, 6, true, ALLFLAGS, true, 1)
558
559// Tests interpolated 3/16x scale down, using no SSSE3 optimized algorithm.
560TEST_H(TestScaleDown316HDNoSSSE3OptInt, 4096, 32, 768, 6, true, NOSSSE3, true,
561       1)
562
563// Tests interpolated 3/16x scale down, using c_only optimized algorithm.
564TEST_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
568TEST_H(TestScaleDown1x6OptInt, 3, 24, 1, 6, true, ALLFLAGS, true, 4)
569
570// Tests scaling down to 1 pixel height
571TEST_H(TestScaleDown6x1OptInt, 24, 3, 6, 1, true, ALLFLAGS, true, 4)
572
573// Tests scaling up from 1 pixel width
574TEST_H(TestScaleUp1x6OptInt, 1, 6, 3, 24, true, ALLFLAGS, true, 4)
575
576// Tests scaling up from 1 pixel height
577TEST_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.
582TEST_H(TestScaleDown2xHDOptInt, 1280, 720, 1280 / 2, 720 / 2, true, ALLFLAGS,
583       true, 1)
584
585// Tests interpolated 1/3x scale down, using optimized algorithm.
586TEST_H(TestScaleDown3xHDOptInt, 1280, 720, 1280 / 3, 720 / 3, true, ALLFLAGS,
587       true, 1)
588
589// Tests interpolated 1/4x scale down, using optimized algorithm.
590TEST_H(TestScaleDown4xHDOptInt, 1280, 720, 1280 / 4, 720 / 4, true, ALLFLAGS,
591       true, 1)
592
593// Tests interpolated 1/5x scale down, using optimized algorithm.
594TEST_H(TestScaleDown5xHDOptInt, 1280, 720, 1280 / 5, 720 / 5, true, ALLFLAGS,
595       true, 1)
596
597// Tests interpolated 1/6x scale down, using optimized algorithm.
598TEST_H(TestScaleDown6xHDOptInt, 1280, 720, 1280 / 6, 720 / 6, true, ALLFLAGS,
599       true, 1)
600
601// Tests interpolated 1/7x scale down, using optimized algorithm.
602TEST_H(TestScaleDown7xHDOptInt, 1280, 720, 1280 / 7, 720 / 7, true, ALLFLAGS,
603       true, 1)
604
605// Tests interpolated 1/8x scale down, using optimized algorithm.
606TEST_H(TestScaleDown8xHDOptInt, 1280, 720, 1280 / 8, 720 / 8, true, ALLFLAGS,
607       true, 1)
608
609// Tests interpolated 1/8x scale down, using optimized algorithm.
610TEST_H(TestScaleDown9xHDOptInt, 1280, 720, 1280 / 9, 720 / 9, true, ALLFLAGS,
611       true, 1)
612
613// Tests interpolated 1/8x scale down, using optimized algorithm.
614TEST_H(TestScaleDown10xHDOptInt, 1280, 720, 1280 / 10, 720 / 10, true, ALLFLAGS,
615       true, 1)
616