Commit dd2fca5f authored by fbarchard@google.com's avatar fbarchard@google.com

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
parent a6b8e0da
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 906
Version: 907
License: BSD
License File: LICENSE
......
......@@ -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
......@@ -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,
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment