From dd2fca5f9c688d1e3dffc819aa07e8be1ffb9a76 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Mon, 9 Dec 2013 21:07:37 +0000 Subject: [PATCH] scale down 4 BUG=none TEST=none R=ryanpetrie@google.com Review URL: https://webrtc-codereview.appspot.com/5389004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@907 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/version.h | 2 +- source/scale_argb.cc | 62 +++++++++++++++++++++++++++++++----- unit_test/scale_argb_test.cc | 11 ++++--- unit_test/scale_test.cc | 1 + 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/README.chromium b/README.chromium index e0559ad5a..47527e86a 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 906 +Version: 907 License: BSD License File: LICENSE diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 41807190f..492bd27f3 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 906 +#define LIBYUV_VERSION 907 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/scale_argb.cc b/source/scale_argb.cc index 5ed6b6d31..fb2222e2a 100644 --- a/source/scale_argb.cc +++ b/source/scale_argb.cc @@ -30,7 +30,6 @@ static __inline int Abs(int v) { // ScaleARGB ARGB, 1/2 // This is an optimized version for scaling down a ARGB to 1/2 of // its original size. - static void ScaleARGBDown2(int /* src_width */, int /* src_height */, int dst_width, int dst_height, int src_stride, int dst_stride, @@ -40,7 +39,7 @@ static void ScaleARGBDown2(int /* src_width */, int /* src_height */, assert(dx == 65536 * 2); // Test scale factor of 2. assert((dy & 0x1ffff) == 0); // Test vertical scale is multiple of 2. // Advance to odd row, even column. - if (filtering) { + if (filtering == kFilterBilinear) { src_argb += (y >> 16) * src_stride + (x >> 16) * 4; } else { src_argb += (y >> 16) * src_stride + ((x >> 16) - 1) * 4; @@ -77,6 +76,49 @@ static void ScaleARGBDown2(int /* src_width */, int /* src_height */, } } +// ScaleARGB ARGB, 1/4 +// This is an optimized version for scaling down a ARGB to 1/4 of +// its original size. +static void ScaleARGBDown4Box(int /* src_width */, int /* src_height */, + int dst_width, int dst_height, + int src_stride, int dst_stride, + const uint8* src_argb, uint8* dst_argb, + int x, int dx, int y, int dy) { + assert(dx == 65536 * 4); // Test scale factor of 4. + assert((dy & 0x3ffff) == 0); // Test vertical scale is multiple of 4. + + assert(dst_width * 2 <= kMaxStride); + // TODO(fbarchard): Remove clip_src_width alignment checks. + SIMD_ALIGNED(uint8 row[kMaxStride * 2 + 16]); + + // Advance to odd row, even column. + src_argb += (y >> 16) * src_stride + (x >> 16) * 4; + int row_stride = src_stride * (dy >> 16); + void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width) = ScaleARGBRowDown2Box_C; +#if defined(HAS_SCALEARGBROWDOWN2_SSE2) + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) && + IS_ALIGNED(src_argb, 16) && IS_ALIGNED(row_stride, 16) && + IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_SSE2; + } +#elif defined(HAS_SCALEARGBROWDOWN2_NEON) + if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8) && + IS_ALIGNED(src_argb, 4) && IS_ALIGNED(row_stride, 4)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_NEON; + } +#endif + + for (int y = 0; y < dst_height; ++y) { + ScaleARGBRowDown2(src_argb, src_stride, row, dst_width * 2); + ScaleARGBRowDown2(src_argb + src_stride * 2, src_stride, + row + kMaxStride, dst_width * 2); + ScaleARGBRowDown2(row, kMaxStride, dst_argb, dst_width); + src_argb += row_stride; + dst_argb += dst_stride; + } +} + // ScaleARGB ARGB Even // This is an optimized version for scaling down a ARGB to even // multiple of its original size. @@ -578,10 +620,6 @@ static void ScaleARGB(const uint8* src, int src_stride, int clip_x, int clip_y, int clip_width, int clip_height, FilterMode filtering) { // ARGB does not support box filter yet, but allow the user to pass it. - // TODO(fbarchard): Support Box filter. Move row function to common. - if (filtering == kFilterBox) { - filtering = kFilterBilinear; - } // Simplify filtering when possible. filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height, @@ -616,14 +654,22 @@ static void ScaleARGB(const uint8* src, int src_stride, } else { // Optimized even scale down. ie 2, 4, 6, 8, 10x. if (!(dx & 0x10000) && !(dy & 0x10000)) { - if ((dx >> 16) == 2) { - // Optimized 1/2 horizontal. + if (dx == 0x20000) { + // Optimized 1/2 downsample. ScaleARGBDown2(src_width, src_height, clip_width, clip_height, src_stride, dst_stride, src, dst, x, dx, y, dy, filtering); return; } + if (dx == 0x40000 && filtering == kFilterBox) { + // Optimized 1/4 box downsample. + ScaleARGBDown4Box(src_width, src_height, + clip_width, clip_height, + src_stride, dst_stride, src, dst, + x, dx, y, dy); + return; + } ScaleARGBDownEven(src_width, src_height, clip_width, clip_height, src_stride, dst_stride, src, dst, diff --git a/unit_test/scale_argb_test.cc b/unit_test/scale_argb_test.cc index 92f1a7a56..23fc3ea54 100644 --- a/unit_test/scale_argb_test.cc +++ b/unit_test/scale_argb_test.cc @@ -215,7 +215,8 @@ static int ARGBClipTestFilter(int src_width, int src_height, #define TEST_FACTOR(name, hfactor, vfactor) \ TEST_FACTOR1(name, None, hfactor, vfactor, 2) \ TEST_FACTOR1(name, Linear, hfactor, vfactor, 2) \ - TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 2) + TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 2) \ + TEST_FACTOR1(name, Box, hfactor, vfactor, 2) // TODO(fbarchard): ScaleDownBy1 should be lossless, but Box has error of 2. TEST_FACTOR(1, 1 / 1, 1 / 1) @@ -256,17 +257,19 @@ TEST_FACTOR(Vertical2by3, 1, 2 / 3) EXPECT_LE(diff, max_diff); \ } -// Test scale to a specified size with all 3 filters. +/// Test scale to a specified size with all 4 filters. #define TEST_SCALETO(name, width, height) \ TEST_SCALETO1(name, width, height, None, 0) \ - TEST_SCALETO1(name, width, height, Linear, 2) \ - TEST_SCALETO1(name, width, height, Bilinear, 2) + TEST_SCALETO1(name, width, height, Linear, 3) \ + TEST_SCALETO1(name, width, height, Bilinear, 3) \ + TEST_SCALETO1(name, width, height, Box, 3) TEST_SCALETO(ARGBScale, 320, 240) TEST_SCALETO(ARGBScale, 352, 288) TEST_SCALETO(ARGBScale, 640, 360) TEST_SCALETO(ARGBScale, 853, 480) TEST_SCALETO(ARGBScale, 1280, 720) +TEST_SCALETO(ARGBScale, 1920, 1080) #undef TEST_SCALETO1 #undef TEST_SCALETO diff --git a/unit_test/scale_test.cc b/unit_test/scale_test.cc index 84682d37b..a81990beb 100644 --- a/unit_test/scale_test.cc +++ b/unit_test/scale_test.cc @@ -188,6 +188,7 @@ TEST_SCALETO(Scale, 352, 288) TEST_SCALETO(Scale, 640, 360) TEST_SCALETO(Scale, 853, 480) TEST_SCALETO(Scale, 1280, 720) +TEST_SCALETO(Scale, 1920, 1080) #undef TEST_SCALETO1 #undef TEST_SCALETO