media/libyuv/unit_test/scale_test.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libyuv/unit_test/scale_test.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,188 @@
     1.4 +/*
     1.5 + *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS. All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +#include <stdlib.h>
    1.15 +#include <time.h>
    1.16 +
    1.17 +#include "libyuv/cpu_id.h"
    1.18 +#include "libyuv/scale.h"
    1.19 +#include "../unit_test/unit_test.h"
    1.20 +
    1.21 +namespace libyuv {
    1.22 +
    1.23 +// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
    1.24 +static int TestFilter(int src_width, int src_height,
    1.25 +                      int dst_width, int dst_height,
    1.26 +                      FilterMode f, int benchmark_iterations) {
    1.27 +  int i, j;
    1.28 +  const int b = 128;
    1.29 +  int src_width_uv = (Abs(src_width) + 1) >> 1;
    1.30 +  int src_height_uv = (Abs(src_height) + 1) >> 1;
    1.31 +
    1.32 +  int src_y_plane_size = (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2);
    1.33 +  int src_uv_plane_size = (src_width_uv + b * 2) * (src_height_uv + b * 2);
    1.34 +
    1.35 +  int src_stride_y = b * 2 + Abs(src_width);
    1.36 +  int src_stride_uv = b * 2 + src_width_uv;
    1.37 +
    1.38 +  align_buffer_page_end(src_y, src_y_plane_size)
    1.39 +  align_buffer_page_end(src_u, src_uv_plane_size)
    1.40 +  align_buffer_page_end(src_v, src_uv_plane_size)
    1.41 +  srandom(time(NULL));
    1.42 +  MemRandomize(src_y, src_y_plane_size);
    1.43 +  MemRandomize(src_u, src_uv_plane_size);
    1.44 +  MemRandomize(src_v, src_uv_plane_size);
    1.45 +
    1.46 +  int dst_width_uv = (dst_width + 1) >> 1;
    1.47 +  int dst_height_uv = (dst_height + 1) >> 1;
    1.48 +
    1.49 +  int dst_y_plane_size = (dst_width + b * 2) * (dst_height + b * 2);
    1.50 +  int dst_uv_plane_size = (dst_width_uv + b * 2) * (dst_height_uv + b * 2);
    1.51 +
    1.52 +  int dst_stride_y = b * 2 + dst_width;
    1.53 +  int dst_stride_uv = b * 2 + dst_width_uv;
    1.54 +
    1.55 +  align_buffer_page_end(dst_y_c, dst_y_plane_size)
    1.56 +  align_buffer_page_end(dst_u_c, dst_uv_plane_size)
    1.57 +  align_buffer_page_end(dst_v_c, dst_uv_plane_size)
    1.58 +  align_buffer_page_end(dst_y_opt, dst_y_plane_size)
    1.59 +  align_buffer_page_end(dst_u_opt, dst_uv_plane_size)
    1.60 +  align_buffer_page_end(dst_v_opt, dst_uv_plane_size)
    1.61 +
    1.62 +
    1.63 +  MaskCpuFlags(0);  // Disable all CPU optimization.
    1.64 +  double c_time = get_time();
    1.65 +  I420Scale(src_y + (src_stride_y * b) + b, src_stride_y,
    1.66 +            src_u + (src_stride_uv * b) + b, src_stride_uv,
    1.67 +            src_v + (src_stride_uv * b) + b, src_stride_uv,
    1.68 +            src_width, src_height,
    1.69 +            dst_y_c + (dst_stride_y * b) + b, dst_stride_y,
    1.70 +            dst_u_c + (dst_stride_uv * b) + b, dst_stride_uv,
    1.71 +            dst_v_c + (dst_stride_uv * b) + b, dst_stride_uv,
    1.72 +            dst_width, dst_height, f);
    1.73 +  c_time = (get_time() - c_time);
    1.74 +
    1.75 +  MaskCpuFlags(-1);  // Enable all CPU optimization.
    1.76 +  double opt_time = get_time();
    1.77 +  for (i = 0; i < benchmark_iterations; ++i) {
    1.78 +    I420Scale(src_y + (src_stride_y * b) + b, src_stride_y,
    1.79 +              src_u + (src_stride_uv * b) + b, src_stride_uv,
    1.80 +              src_v + (src_stride_uv * b) + b, src_stride_uv,
    1.81 +              src_width, src_height,
    1.82 +              dst_y_opt + (dst_stride_y * b) + b, dst_stride_y,
    1.83 +              dst_u_opt + (dst_stride_uv * b) + b, dst_stride_uv,
    1.84 +              dst_v_opt + (dst_stride_uv * b) + b, dst_stride_uv,
    1.85 +              dst_width, dst_height, f);
    1.86 +  }
    1.87 +  opt_time = (get_time() - opt_time) / benchmark_iterations;
    1.88 +  // Report performance of C vs OPT
    1.89 +  printf("filter %d - %8d us C - %8d us OPT\n",
    1.90 +         f,
    1.91 +         static_cast<int>(c_time * 1e6),
    1.92 +         static_cast<int>(opt_time * 1e6));
    1.93 +
    1.94 +  // C version may be a little off from the optimized. Order of
    1.95 +  //  operations may introduce rounding somewhere. So do a difference
    1.96 +  //  of the buffers and look to see that the max difference isn't
    1.97 +  //  over 2.
    1.98 +  int max_diff = 0;
    1.99 +  for (i = b; i < (dst_height + b); ++i) {
   1.100 +    for (j = b; j < (dst_width + b); ++j) {
   1.101 +      int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
   1.102 +                         dst_y_opt[(i * dst_stride_y) + j]);
   1.103 +      if (abs_diff > max_diff) {
   1.104 +        max_diff = abs_diff;
   1.105 +      }
   1.106 +    }
   1.107 +  }
   1.108 +
   1.109 +  for (i = b; i < (dst_height_uv + b); ++i) {
   1.110 +    for (j = b; j < (dst_width_uv + b); ++j) {
   1.111 +      int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
   1.112 +                         dst_u_opt[(i * dst_stride_uv) + j]);
   1.113 +      if (abs_diff > max_diff) {
   1.114 +        max_diff = abs_diff;
   1.115 +      }
   1.116 +      abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
   1.117 +                     dst_v_opt[(i * dst_stride_uv) + j]);
   1.118 +      if (abs_diff > max_diff) {
   1.119 +        max_diff = abs_diff;
   1.120 +      }
   1.121 +    }
   1.122 +  }
   1.123 +
   1.124 +  free_aligned_buffer_page_end(dst_y_c)
   1.125 +  free_aligned_buffer_page_end(dst_u_c)
   1.126 +  free_aligned_buffer_page_end(dst_v_c)
   1.127 +  free_aligned_buffer_page_end(dst_y_opt)
   1.128 +  free_aligned_buffer_page_end(dst_u_opt)
   1.129 +  free_aligned_buffer_page_end(dst_v_opt)
   1.130 +
   1.131 +  free_aligned_buffer_page_end(src_y)
   1.132 +  free_aligned_buffer_page_end(src_u)
   1.133 +  free_aligned_buffer_page_end(src_v)
   1.134 +
   1.135 +  return max_diff;
   1.136 +}
   1.137 +
   1.138 +#define TEST_FACTOR1(name, filter, hfactor, vfactor, max_diff)                 \
   1.139 +    TEST_F(libyuvTest, ScaleDownBy##name##_##filter) {                         \
   1.140 +      int diff = TestFilter(benchmark_width_, benchmark_height_,               \
   1.141 +                            Abs(benchmark_width_) * hfactor,                   \
   1.142 +                            Abs(benchmark_height_) * vfactor,                  \
   1.143 +                            kFilter##filter, benchmark_iterations_);           \
   1.144 +      EXPECT_LE(diff, max_diff);                                               \
   1.145 +    }
   1.146 +
   1.147 +// Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
   1.148 +// filtering is different fixed point implementations for SSSE3, Neon and C.
   1.149 +#define TEST_FACTOR(name, hfactor, vfactor)                                    \
   1.150 +    TEST_FACTOR1(name, None, hfactor, vfactor, 0)                              \
   1.151 +    TEST_FACTOR1(name, Linear, hfactor, vfactor, 3)                            \
   1.152 +    TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 3)                          \
   1.153 +    TEST_FACTOR1(name, Box, hfactor, vfactor, 3)                               \
   1.154 +
   1.155 +TEST_FACTOR(2, 1 / 2, 1 / 2)
   1.156 +TEST_FACTOR(4, 1 / 4, 1 / 4)
   1.157 +TEST_FACTOR(8, 1 / 8, 1 / 8)
   1.158 +TEST_FACTOR(3by4, 3 / 4, 3 / 4)
   1.159 +#undef TEST_FACTOR1
   1.160 +#undef TEST_FACTOR
   1.161 +
   1.162 +#define TEST_SCALETO1(name, width, height, filter, max_diff)                   \
   1.163 +    TEST_F(libyuvTest, name##To##width##x##height##_##filter) {                \
   1.164 +      int diff = TestFilter(benchmark_width_, benchmark_height_,               \
   1.165 +                            width, height,                                     \
   1.166 +                            kFilter##filter, benchmark_iterations_);           \
   1.167 +      EXPECT_LE(diff, max_diff);                                               \
   1.168 +    }                                                                          \
   1.169 +    TEST_F(libyuvTest, name##From##width##x##height##_##filter) {              \
   1.170 +      int diff = TestFilter(width, height,                                     \
   1.171 +                            Abs(benchmark_width_), Abs(benchmark_height_),     \
   1.172 +                            kFilter##filter, benchmark_iterations_);           \
   1.173 +      EXPECT_LE(diff, max_diff);                                               \
   1.174 +    }
   1.175 +
   1.176 +// Test scale to a specified size with all 4 filters.
   1.177 +#define TEST_SCALETO(name, width, height)                                      \
   1.178 +    TEST_SCALETO1(name, width, height, None, 0)                                \
   1.179 +    TEST_SCALETO1(name, width, height, Linear, 3)                              \
   1.180 +    TEST_SCALETO1(name, width, height, Bilinear, 3)                            \
   1.181 +    TEST_SCALETO1(name, width, height, Box, 3)
   1.182 +
   1.183 +TEST_SCALETO(Scale, 1, 1)
   1.184 +TEST_SCALETO(Scale, 320, 240)
   1.185 +TEST_SCALETO(Scale, 352, 288)
   1.186 +TEST_SCALETO(Scale, 640, 360)
   1.187 +TEST_SCALETO(Scale, 1280, 720)
   1.188 +#undef TEST_SCALETO1
   1.189 +#undef TEST_SCALETO
   1.190 +
   1.191 +}  // namespace libyuv

mercurial