133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp/*
233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *
433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *  Use of this source code is governed by a BSD-style license
533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *  that can be found in the LICENSE file in the root of the source
633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *  tree. An additional intellectual property rights grant can be found
7f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  in the file PATENTS. All contributing project authors may
833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp *  be found in the AUTHORS file in the root of the source tree.
933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp */
1033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
1133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp#include <stdlib.h>
1233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp#include <time.h>
1333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
14b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard#include "../unit_test/unit_test.h"
15f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/convert_argb.h"
1633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp#include "libyuv/cpu_id.h"
1733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp#include "libyuv/scale_argb.h"
18f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/video_common.h"
1933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
2033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkampnamespace libyuv {
2133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
22f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define STRINGIZE(line) #line
23f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define FILELINESTR(file, line) file ":" STRINGIZE(line)
24f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
25f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
26b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchardstatic int ARGBTestFilter(int src_width,
27b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int src_height,
28b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int dst_width,
29b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int dst_height,
30b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          FilterMode f,
31b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int benchmark_iterations,
32b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int disable_cpu_flags,
33b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          int benchmark_cpu_info) {
34f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
35f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
36f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
3733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
38f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i, j;
39f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const int b = 0;  // 128 to test for padding/stride.
40b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int64 src_argb_plane_size =
41b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4LL;
42f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
43f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
44f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(src_argb, src_argb_plane_size);
45f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!src_argb) {
46f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
47f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
48f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
49f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(src_argb, src_argb_plane_size);
5033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
51f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4LL;
5233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  int dst_stride_argb = (b * 2 + dst_width) * 4;
5333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
54f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
55f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
56f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!dst_argb_c || !dst_argb_opt) {
57f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
58f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
5933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
6033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  memset(dst_argb_c, 2, dst_argb_plane_size);
6133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  memset(dst_argb_opt, 3, dst_argb_plane_size);
6233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
6333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  // Warm up both versions for consistent benchmarks.
64f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
6533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
66b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
67b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            dst_stride_argb, dst_width, dst_height, f);
68f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
6933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
70b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            src_width, src_height, dst_argb_opt + (dst_stride_argb * b) + b * 4,
71b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            dst_stride_argb, dst_width, dst_height, f);
7233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
73f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
7433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  double c_time = get_time();
75f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
76b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
77b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            dst_stride_argb, dst_width, dst_height, f);
78f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
79f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  c_time = (get_time() - c_time);
8033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
81f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
8233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  double opt_time = get_time();
8333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  for (i = 0; i < benchmark_iterations; ++i) {
8433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp    ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
8533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp              src_width, src_height,
8633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp              dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
8733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp              dst_width, dst_height, f);
8833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
8933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  opt_time = (get_time() - opt_time) / benchmark_iterations;
9033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
9133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  // Report performance of C vs OPT
92b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  printf("filter %d - %8d us C - %8d us OPT\n", f,
93b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard         static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
9433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
9533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  // C version may be a little off from the optimized. Order of
9633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  //  operations may introduce rounding somewhere. So do a difference
9733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  //  of the buffers and look to see that the max difference isn't
9833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  //  over 2.
9933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  int max_diff = 0;
10033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  for (i = b; i < (dst_height + b); ++i) {
10133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
102f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
10333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp                         dst_argb_opt[(i * dst_stride_argb) + j]);
10433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp      if (abs_diff > max_diff) {
10533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp        max_diff = abs_diff;
10633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp      }
10733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp    }
10833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
10933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
110f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_c);
111f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_opt);
112f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(src_argb);
11333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  return max_diff;
11433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}
11533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
116f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangstatic const int kTileX = 8;
117f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangstatic const int kTileY = 8;
118f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
119b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchardstatic int TileARGBScale(const uint8* src_argb,
120b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int src_stride_argb,
121b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int src_width,
122b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int src_height,
123b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         uint8* dst_argb,
124b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int dst_stride_argb,
125b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int dst_width,
126b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                         int dst_height,
127f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         FilterMode filtering) {
128f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int y = 0; y < dst_height; y += kTileY) {
129f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (int x = 0; x < dst_width; x += kTileX) {
130f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      int clip_width = kTileX;
131f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (x + clip_width > dst_width) {
132f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        clip_width = dst_width - x;
133f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
134f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      int clip_height = kTileY;
135f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (y + clip_height > dst_height) {
136f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        clip_height = dst_height - y;
137f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
138b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      int r = ARGBScaleClip(src_argb, src_stride_argb, src_width, src_height,
139b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                            dst_argb, dst_stride_argb, dst_width, dst_height, x,
140b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                            y, clip_width, clip_height, filtering);
141f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (r) {
142f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        return r;
143f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
144f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
14533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
146f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return 0;
14733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}
14833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
149b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchardstatic int ARGBClipTestFilter(int src_width,
150b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              int src_height,
151b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              int dst_width,
152b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              int dst_height,
153b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              FilterMode f,
154b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              int benchmark_iterations) {
155f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
156f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
157f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
15833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
159f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const int b = 128;
160b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int64 src_argb_plane_size =
161b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4;
162f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
163f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
164f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(src_argb, src_argb_plane_size);
165f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!src_argb) {
166f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
167f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
16833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
169f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  memset(src_argb, 1, src_argb_plane_size);
17033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
171f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
172f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int dst_stride_argb = (b * 2 + dst_width) * 4;
17333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
174f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i, j;
175f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = b; i < (Abs(src_height) + b); ++i) {
176f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
177f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      src_argb[(i * src_stride_argb) + j] = (fastrand() & 0xff);
178f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
17933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
18033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
181f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
182f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
183f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!dst_argb_c || !dst_argb_opt) {
184f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
185f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
18633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
187f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  memset(dst_argb_c, 2, dst_argb_plane_size);
188f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  memset(dst_argb_opt, 3, dst_argb_plane_size);
18933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
190f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Do full image, no clipping.
191f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  double c_time = get_time();
192f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
193b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
194b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard            dst_stride_argb, dst_width, dst_height, f);
195f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  c_time = (get_time() - c_time);
19633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
197f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Do tiled image, clipping scale to a tile at a time.
198f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  double opt_time = get_time();
199f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = 0; i < benchmark_iterations; ++i) {
200f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    TileARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
201f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_width, src_height,
202f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
203f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  dst_width, dst_height, f);
20433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
205f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  opt_time = (get_time() - opt_time) / benchmark_iterations;
20633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
207f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Report performance of Full vs Tiled.
208b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  printf("filter %d - %8d us Full - %8d us Tiled\n", f,
209b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard         static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
21033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
211f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Compare full scaled image vs tiled image.
212f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int max_diff = 0;
213f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = b; i < (dst_height + b); ++i) {
214f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
215f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
216f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         dst_argb_opt[(i * dst_stride_argb) + j]);
217f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (abs_diff > max_diff) {
218f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        max_diff = abs_diff;
219f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
220f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
22133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
222f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
223f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_c);
224f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_opt);
225f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(src_argb);
226f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return max_diff;
22733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}
22833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
229f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// The following adjustments in dimensions ensure the scale factor will be
230f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// exactly achieved.
231f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define DX(x, nom, denom) static_cast<int>((Abs(x) / nom) * nom)
232f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define SX(x, nom, denom) static_cast<int>((x / nom) * denom)
233f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
234b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard#define TEST_FACTOR1(name, filter, nom, denom, max_diff)                     \
235b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, ARGBScaleDownBy##name##_##filter) {                \
236b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff = ARGBTestFilter(                                               \
237b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
238b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
239b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        kFilter##filter, benchmark_iterations_, disable_cpu_flags_,          \
240b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        benchmark_cpu_info_);                                                \
241b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                               \
242b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }                                                                          \
243b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, ARGBScaleDownClipBy##name##_##filter) {            \
244b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff = ARGBClipTestFilter(                                           \
245b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
246b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
247b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        kFilter##filter, benchmark_iterations_);                             \
248b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                               \
249b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }
25033cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
251f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
252f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// filtering is different fixed point implementations for SSSE3, Neon and C.
253b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard#define TEST_FACTOR(name, nom, denom)         \
254b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_FACTOR1(name, None, nom, denom, 0)     \
255b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_FACTOR1(name, Linear, nom, denom, 3)   \
256b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_FACTOR1(name, Bilinear, nom, denom, 3) \
257b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_FACTOR1(name, Box, nom, denom, 3)
258f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
259f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(2, 1, 2)
260f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(4, 1, 4)
261f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(8, 1, 8)
262f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(3by4, 3, 4)
263f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(3by8, 3, 8)
264f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_FACTOR(3, 1, 3)
265f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef TEST_FACTOR1
266f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef TEST_FACTOR
267f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef SX
268f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef DX
269f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
270f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define TEST_SCALETO1(name, width, height, filter, max_diff)                   \
271b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, name##To##width##x##height##_##filter) {             \
272b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff = ARGBTestFilter(benchmark_width_, benchmark_height_, width,      \
273b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              height, kFilter##filter, benchmark_iterations_,  \
274b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              disable_cpu_flags_, benchmark_cpu_info_);        \
275b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                                 \
276b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }                                                                            \
277b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, name##From##width##x##height##_##filter) {           \
278b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff = ARGBTestFilter(width, height, Abs(benchmark_width_),            \
279b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              Abs(benchmark_height_), kFilter##filter,         \
280b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              benchmark_iterations_, disable_cpu_flags_,       \
281b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                              benchmark_cpu_info_);                            \
282b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                                 \
283b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }                                                                            \
284b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, name##ClipTo##width##x##height##_##filter) {         \
285b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff =                                                                 \
286b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        ARGBClipTestFilter(benchmark_width_, benchmark_height_, width, height, \
287b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                           kFilter##filter, benchmark_iterations_);            \
288b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                                 \
289b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }                                                                            \
290b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_F(LibYUVScaleTest, name##ClipFrom##width##x##height##_##filter) {       \
291b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    int diff = ARGBClipTestFilter(width, height, Abs(benchmark_width_),        \
292b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                                  Abs(benchmark_height_), kFilter##filter,     \
293b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                                  benchmark_iterations_);                      \
294b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    EXPECT_LE(diff, max_diff);                                                 \
295b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  }
29633cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
297f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang/// Test scale to a specified size with all 4 filters.
298b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard#define TEST_SCALETO(name, width, height)       \
299b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_SCALETO1(name, width, height, None, 0)   \
300b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_SCALETO1(name, width, height, Linear, 3) \
301b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  TEST_SCALETO1(name, width, height, Bilinear, 3)
302f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
303f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 1, 1)
304f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 320, 240)
305f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 352, 288)
306f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 569, 480)
307f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 640, 360)
308f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_SCALETO(ARGBScale, 1280, 720)
309f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef TEST_SCALETO1
310f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef TEST_SCALETO
311f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
312f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scale with YUV conversion to ARGB and clipping.
313f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangLIBYUV_API
314b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchardint YUVToARGBScaleReference2(const uint8* src_y,
315b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int src_stride_y,
316b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             const uint8* src_u,
317b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int src_stride_u,
318b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             const uint8* src_v,
319b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int src_stride_v,
320b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             uint32 /* src_fourcc */,  // TODO: Add support.
321b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int src_width,
322b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int src_height,
323b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             uint8* dst_argb,
324b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int dst_stride_argb,
325b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             uint32 /* dst_fourcc */,  // TODO: Add support.
326b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int dst_width,
327b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int dst_height,
328b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int clip_x,
329b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int clip_y,
330b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int clip_width,
331b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                             int clip_height,
332f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                             enum FilterMode filtering) {
333f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint8* argb_buffer = static_cast<uint8*>(malloc(src_width * src_height * 4));
334f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int r;
335b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  I420ToARGB(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
336b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard             argb_buffer, src_width * 4, src_width, src_height);
337b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard
338b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  r = ARGBScaleClip(argb_buffer, src_width * 4, src_width, src_height, dst_argb,
339b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                    dst_stride_argb, dst_width, dst_height, clip_x, clip_y,
340b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                    clip_width, clip_height, filtering);
341f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free(argb_buffer);
342f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return r;
343f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
34433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
345f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangstatic void FillRamp(uint8* buf, int width, int height, int v, int dx, int dy) {
346f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int rv = v;
347f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int y = 0; y < height; ++y) {
348f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (int x = 0; x < width; ++x) {
349f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *buf++ = v;
350f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      v += dx;
351f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (v < 0 || v > 255) {
352f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        dx = -dx;
353f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        v += dx;
354f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
355f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
356f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    v = rv + dy;
357f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (v < 0 || v > 255) {
358f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      dy = -dy;
359f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      v += dy;
360f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
361f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    rv = v;
36233cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
36333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}
36433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
365f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
366b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchardstatic int YUVToARGBTestFilter(int src_width,
367b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                               int src_height,
368b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                               int dst_width,
369b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                               int dst_height,
370b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                               FilterMode f,
371b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                               int benchmark_iterations) {
372f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 src_y_plane_size = Abs(src_width) * Abs(src_height);
373b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int64 src_uv_plane_size =
374b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      ((Abs(src_width) + 1) / 2) * ((Abs(src_height) + 1) / 2);
375f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int src_stride_y = Abs(src_width);
376f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int src_stride_uv = (Abs(src_width) + 1) / 2;
377f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
378f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(src_y, src_y_plane_size);
379f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(src_u, src_uv_plane_size);
380f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(src_v, src_uv_plane_size);
381f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
382b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int64 dst_argb_plane_size = (dst_width) * (dst_height)*4LL;
383b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int dst_stride_argb = (dst_width)*4;
384f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
385f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
386f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (!dst_argb_c || !dst_argb_opt || !src_y || !src_u || !src_v) {
387f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
388f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    return 0;
389f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
390f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Fill YUV image with continuous ramp, which is less sensitive to
391f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // subsampling and filtering differences for test purposes.
392f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  FillRamp(src_y, Abs(src_width), Abs(src_height), 128, 1, 1);
393f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  FillRamp(src_u, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 3, 1, 1);
394f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  FillRamp(src_v, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 4, 1, 1);
395f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  memset(dst_argb_c, 2, dst_argb_plane_size);
396f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  memset(dst_argb_opt, 3, dst_argb_plane_size);
39733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
398b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  YUVToARGBScaleReference2(src_y, src_stride_y, src_u, src_stride_uv, src_v,
399b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                           src_stride_uv, libyuv::FOURCC_I420, src_width,
400b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                           src_height, dst_argb_c, dst_stride_argb,
401b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                           libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
402b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                           dst_width, dst_height, f);
403f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
404f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 0; i < benchmark_iterations; ++i) {
405b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard    YUVToARGBScaleClip(src_y, src_stride_y, src_u, src_stride_uv, src_v,
406b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                       src_stride_uv, libyuv::FOURCC_I420, src_width,
407b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                       src_height, dst_argb_opt, dst_stride_argb,
408b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                       libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
409b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                       dst_width, dst_height, f);
410f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
411f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int max_diff = 0;
412f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 0; i < dst_height; ++i) {
413f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (int j = 0; j < dst_width * 4; ++j) {
414f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
415f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         dst_argb_opt[(i * dst_stride_argb) + j]);
416f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      if (abs_diff > max_diff) {
417b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard        printf("error %d at %d,%d c %d opt %d", abs_diff, j, i,
418f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang               dst_argb_c[(i * dst_stride_argb) + j],
419f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang               dst_argb_opt[(i * dst_stride_argb) + j]);
420f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        EXPECT_LE(abs_diff, 40);
421f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        max_diff = abs_diff;
422f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
423f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
42433cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp  }
42533cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
426f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_c);
427f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(dst_argb_opt);
428f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(src_y);
429f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(src_u);
430f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  free_aligned_buffer_page_end(src_v);
431f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return max_diff;
432f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
43333cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
434f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_F(LibYUVScaleTest, YUVToRGBScaleUp) {
435b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int diff =
436b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      YUVToARGBTestFilter(benchmark_width_, benchmark_height_,
437b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2,
438b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard                          libyuv::kFilterBilinear, benchmark_iterations_);
439f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_LE(diff, 10);
440f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
44133cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
442f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_F(LibYUVScaleTest, YUVToRGBScaleDown) {
443b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard  int diff = YUVToARGBTestFilter(
444b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2, benchmark_width_,
445b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard      benchmark_height_, libyuv::kFilterBilinear, benchmark_iterations_);
446f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_LE(diff, 10);
44733cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}
44833cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp
44933cfdeb7b267ab635413797fffb046b73272f7ecHendrik Dahlkamp}  // namespace libyuv
450