media/libyuv/unit_test/scale_test.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
     3  *
     4  *  Use of this source code is governed by a BSD-style license
     5  *  that can be found in the LICENSE file in the root of the source
     6  *  tree. An additional intellectual property rights grant can be found
     7  *  in the file PATENTS. All contributing project authors may
     8  *  be found in the AUTHORS file in the root of the source tree.
     9  */
    11 #include <stdlib.h>
    12 #include <time.h>
    14 #include "libyuv/cpu_id.h"
    15 #include "libyuv/scale.h"
    16 #include "../unit_test/unit_test.h"
    18 namespace libyuv {
    20 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
    21 static int TestFilter(int src_width, int src_height,
    22                       int dst_width, int dst_height,
    23                       FilterMode f, int benchmark_iterations) {
    24   int i, j;
    25   const int b = 128;
    26   int src_width_uv = (Abs(src_width) + 1) >> 1;
    27   int src_height_uv = (Abs(src_height) + 1) >> 1;
    29   int src_y_plane_size = (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2);
    30   int src_uv_plane_size = (src_width_uv + b * 2) * (src_height_uv + b * 2);
    32   int src_stride_y = b * 2 + Abs(src_width);
    33   int src_stride_uv = b * 2 + src_width_uv;
    35   align_buffer_page_end(src_y, src_y_plane_size)
    36   align_buffer_page_end(src_u, src_uv_plane_size)
    37   align_buffer_page_end(src_v, src_uv_plane_size)
    38   srandom(time(NULL));
    39   MemRandomize(src_y, src_y_plane_size);
    40   MemRandomize(src_u, src_uv_plane_size);
    41   MemRandomize(src_v, src_uv_plane_size);
    43   int dst_width_uv = (dst_width + 1) >> 1;
    44   int dst_height_uv = (dst_height + 1) >> 1;
    46   int dst_y_plane_size = (dst_width + b * 2) * (dst_height + b * 2);
    47   int dst_uv_plane_size = (dst_width_uv + b * 2) * (dst_height_uv + b * 2);
    49   int dst_stride_y = b * 2 + dst_width;
    50   int dst_stride_uv = b * 2 + dst_width_uv;
    52   align_buffer_page_end(dst_y_c, dst_y_plane_size)
    53   align_buffer_page_end(dst_u_c, dst_uv_plane_size)
    54   align_buffer_page_end(dst_v_c, dst_uv_plane_size)
    55   align_buffer_page_end(dst_y_opt, dst_y_plane_size)
    56   align_buffer_page_end(dst_u_opt, dst_uv_plane_size)
    57   align_buffer_page_end(dst_v_opt, dst_uv_plane_size)
    60   MaskCpuFlags(0);  // Disable all CPU optimization.
    61   double c_time = get_time();
    62   I420Scale(src_y + (src_stride_y * b) + b, src_stride_y,
    63             src_u + (src_stride_uv * b) + b, src_stride_uv,
    64             src_v + (src_stride_uv * b) + b, src_stride_uv,
    65             src_width, src_height,
    66             dst_y_c + (dst_stride_y * b) + b, dst_stride_y,
    67             dst_u_c + (dst_stride_uv * b) + b, dst_stride_uv,
    68             dst_v_c + (dst_stride_uv * b) + b, dst_stride_uv,
    69             dst_width, dst_height, f);
    70   c_time = (get_time() - c_time);
    72   MaskCpuFlags(-1);  // Enable all CPU optimization.
    73   double opt_time = get_time();
    74   for (i = 0; i < benchmark_iterations; ++i) {
    75     I420Scale(src_y + (src_stride_y * b) + b, src_stride_y,
    76               src_u + (src_stride_uv * b) + b, src_stride_uv,
    77               src_v + (src_stride_uv * b) + b, src_stride_uv,
    78               src_width, src_height,
    79               dst_y_opt + (dst_stride_y * b) + b, dst_stride_y,
    80               dst_u_opt + (dst_stride_uv * b) + b, dst_stride_uv,
    81               dst_v_opt + (dst_stride_uv * b) + b, dst_stride_uv,
    82               dst_width, dst_height, f);
    83   }
    84   opt_time = (get_time() - opt_time) / benchmark_iterations;
    85   // Report performance of C vs OPT
    86   printf("filter %d - %8d us C - %8d us OPT\n",
    87          f,
    88          static_cast<int>(c_time * 1e6),
    89          static_cast<int>(opt_time * 1e6));
    91   // C version may be a little off from the optimized. Order of
    92   //  operations may introduce rounding somewhere. So do a difference
    93   //  of the buffers and look to see that the max difference isn't
    94   //  over 2.
    95   int max_diff = 0;
    96   for (i = b; i < (dst_height + b); ++i) {
    97     for (j = b; j < (dst_width + b); ++j) {
    98       int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
    99                          dst_y_opt[(i * dst_stride_y) + j]);
   100       if (abs_diff > max_diff) {
   101         max_diff = abs_diff;
   102       }
   103     }
   104   }
   106   for (i = b; i < (dst_height_uv + b); ++i) {
   107     for (j = b; j < (dst_width_uv + b); ++j) {
   108       int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
   109                          dst_u_opt[(i * dst_stride_uv) + j]);
   110       if (abs_diff > max_diff) {
   111         max_diff = abs_diff;
   112       }
   113       abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
   114                      dst_v_opt[(i * dst_stride_uv) + j]);
   115       if (abs_diff > max_diff) {
   116         max_diff = abs_diff;
   117       }
   118     }
   119   }
   121   free_aligned_buffer_page_end(dst_y_c)
   122   free_aligned_buffer_page_end(dst_u_c)
   123   free_aligned_buffer_page_end(dst_v_c)
   124   free_aligned_buffer_page_end(dst_y_opt)
   125   free_aligned_buffer_page_end(dst_u_opt)
   126   free_aligned_buffer_page_end(dst_v_opt)
   128   free_aligned_buffer_page_end(src_y)
   129   free_aligned_buffer_page_end(src_u)
   130   free_aligned_buffer_page_end(src_v)
   132   return max_diff;
   133 }
   135 #define TEST_FACTOR1(name, filter, hfactor, vfactor, max_diff)                 \
   136     TEST_F(libyuvTest, ScaleDownBy##name##_##filter) {                         \
   137       int diff = TestFilter(benchmark_width_, benchmark_height_,               \
   138                             Abs(benchmark_width_) * hfactor,                   \
   139                             Abs(benchmark_height_) * vfactor,                  \
   140                             kFilter##filter, benchmark_iterations_);           \
   141       EXPECT_LE(diff, max_diff);                                               \
   142     }
   144 // Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
   145 // filtering is different fixed point implementations for SSSE3, Neon and C.
   146 #define TEST_FACTOR(name, hfactor, vfactor)                                    \
   147     TEST_FACTOR1(name, None, hfactor, vfactor, 0)                              \
   148     TEST_FACTOR1(name, Linear, hfactor, vfactor, 3)                            \
   149     TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 3)                          \
   150     TEST_FACTOR1(name, Box, hfactor, vfactor, 3)                               \
   152 TEST_FACTOR(2, 1 / 2, 1 / 2)
   153 TEST_FACTOR(4, 1 / 4, 1 / 4)
   154 TEST_FACTOR(8, 1 / 8, 1 / 8)
   155 TEST_FACTOR(3by4, 3 / 4, 3 / 4)
   156 #undef TEST_FACTOR1
   157 #undef TEST_FACTOR
   159 #define TEST_SCALETO1(name, width, height, filter, max_diff)                   \
   160     TEST_F(libyuvTest, name##To##width##x##height##_##filter) {                \
   161       int diff = TestFilter(benchmark_width_, benchmark_height_,               \
   162                             width, height,                                     \
   163                             kFilter##filter, benchmark_iterations_);           \
   164       EXPECT_LE(diff, max_diff);                                               \
   165     }                                                                          \
   166     TEST_F(libyuvTest, name##From##width##x##height##_##filter) {              \
   167       int diff = TestFilter(width, height,                                     \
   168                             Abs(benchmark_width_), Abs(benchmark_height_),     \
   169                             kFilter##filter, benchmark_iterations_);           \
   170       EXPECT_LE(diff, max_diff);                                               \
   171     }
   173 // Test scale to a specified size with all 4 filters.
   174 #define TEST_SCALETO(name, width, height)                                      \
   175     TEST_SCALETO1(name, width, height, None, 0)                                \
   176     TEST_SCALETO1(name, width, height, Linear, 3)                              \
   177     TEST_SCALETO1(name, width, height, Bilinear, 3)                            \
   178     TEST_SCALETO1(name, width, height, Box, 3)
   180 TEST_SCALETO(Scale, 1, 1)
   181 TEST_SCALETO(Scale, 320, 240)
   182 TEST_SCALETO(Scale, 352, 288)
   183 TEST_SCALETO(Scale, 640, 360)
   184 TEST_SCALETO(Scale, 1280, 720)
   185 #undef TEST_SCALETO1
   186 #undef TEST_SCALETO
   188 }  // namespace libyuv

mercurial