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

UNDER_ALLOCATED_HACK for scale that detects odd width and odd height were…

UNDER_ALLOCATED_HACK for scale that detects odd width and odd height were miscalculated and adjusts scaler for it.
BUG=none
TEST=none
Review URL: https://webrtc-codereview.appspot.com/663007

git-svn-id: http://libyuv.googlecode.com/svn/trunk@290 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent 81b804e3
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 289 Version: 290
License: BSD License: BSD
License File: LICENSE License File: LICENSE
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 289 #define LIBYUV_VERSION 290
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_
...@@ -3361,6 +3361,8 @@ void ScalePlane(const uint8* src, int src_stride, ...@@ -3361,6 +3361,8 @@ void ScalePlane(const uint8* src, int src_stride,
// Scale an I420 image. // Scale an I420 image.
// This function in turn calls a scaling function for each plane. // This function in turn calls a scaling function for each plane.
#define UNDER_ALLOCATED_HACK 1
int I420Scale(const uint8* src_y, int src_stride_y, int I420Scale(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v, const uint8* src_v, int src_stride_v,
...@@ -3390,6 +3392,28 @@ int I420Scale(const uint8* src_y, int src_stride_y, ...@@ -3390,6 +3392,28 @@ int I420Scale(const uint8* src_y, int src_stride_y,
int dst_halfwidth = (dst_width + 1) >> 1; int dst_halfwidth = (dst_width + 1) >> 1;
int dst_halfheight = (dst_height + 1) >> 1; int dst_halfheight = (dst_height + 1) >> 1;
#ifdef UNDER_ALLOCATED_HACK
// If caller passed width / 2 for stride, adjust halfwidth to match.
if ((src_width & 1) && src_stride_u && src_halfwidth > abs(src_stride_u)) {
src_halfwidth = src_width >> 1;
}
if ((dst_width & 1) && dst_stride_u && dst_halfwidth > abs(dst_stride_u)) {
dst_halfwidth = dst_width >> 1;
}
// If caller used height / 2 when computing src_v, it will point into what
// should be the src_u plane. Detect this and reduce halfheight to match.
int uv_src_plane_size = src_halfwidth * src_halfheight;
if ((src_height & 1) &&
(src_v > src_u) && (src_v < (src_u + uv_src_plane_size))) {
src_halfheight = src_height >> 1;
}
int uv_dst_plane_size = dst_halfwidth * dst_halfheight;
if ((dst_height & 1) &&
(dst_v > dst_u) && (dst_v < (dst_u + uv_dst_plane_size))) {
dst_halfheight = dst_height >> 1;
}
#endif
ScalePlane(src_y, src_stride_y, src_width, src_height, ScalePlane(src_y, src_stride_y, src_width, src_height,
dst_y, dst_stride_y, dst_width, dst_height, dst_y, dst_stride_y, dst_width, dst_height,
filtering); filtering);
...@@ -3431,6 +3455,28 @@ int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v, ...@@ -3431,6 +3455,28 @@ int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
int dst_halfheight = (dst_height + 1) >> 1; int dst_halfheight = (dst_height + 1) >> 1;
FilterMode filtering = interpolate ? kFilterBox : kFilterNone; FilterMode filtering = interpolate ? kFilterBox : kFilterNone;
#ifdef UNDER_ALLOCATED_HACK
// If caller passed width / 2 for stride, adjust halfwidth to match.
if ((src_width & 1) && src_stride_u && src_halfwidth > abs(src_stride_u)) {
src_halfwidth = src_width >> 1;
}
if ((dst_width & 1) && dst_stride_u && dst_halfwidth > abs(dst_stride_u)) {
dst_halfwidth = dst_width >> 1;
}
// If caller used height / 2 when computing src_v, it will point into what
// should be the src_u plane. Detect this and reduce halfheight to match.
int uv_src_plane_size = src_halfwidth * src_halfheight;
if ((src_height & 1) &&
(src_v > src_u) && (src_v < (src_u + uv_src_plane_size))) {
src_halfheight = src_height >> 1;
}
int uv_dst_plane_size = dst_halfwidth * dst_halfheight;
if ((dst_height & 1) &&
(dst_v > dst_u) && (dst_v < (dst_u + uv_dst_plane_size))) {
dst_halfheight = dst_height >> 1;
}
#endif
ScalePlane(src_y, src_stride_y, src_width, src_height, ScalePlane(src_y, src_stride_y, src_width, src_height,
dst_y, dst_stride_y, dst_width, dst_height, dst_y, dst_stride_y, dst_width, dst_height,
filtering); filtering);
......
...@@ -18,17 +18,17 @@ ...@@ -18,17 +18,17 @@
namespace libyuv { namespace libyuv {
static int ARGBTestFilter(int src_width, int src_height, static int ARGBTestFilter(int src_width, int src_height,
int dst_width, int dst_height, int dst_width, int dst_height,
FilterMode f) { FilterMode f) {
const int b = 128; const int b = 128;
int src_argb_plane_size = (src_width + (2 * b)) * (src_height + (2 * b)) * 4; int src_argb_plane_size = (src_width + b * 2) * (src_height + b * 2) * 4;
int src_stride_argb = (2 * b + src_width) * 4; int src_stride_argb = (b * 2 + src_width) * 4;
align_buffer_16(src_argb, src_argb_plane_size) align_buffer_16(src_argb, src_argb_plane_size)
memset(src_argb, 1, src_argb_plane_size); memset(src_argb, 1, src_argb_plane_size);
int dst_argb_plane_size = (dst_width + (2 * b)) * (dst_height + (2 * b)) * 4; int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
int dst_stride_argb = (2 * b + dst_width) * 4; int dst_stride_argb = (b * 2 + dst_width) * 4;
srandom(time(NULL)); srandom(time(NULL));
...@@ -213,4 +213,18 @@ TEST_F(libyuvTest, ARGBScaleTo1366) { ...@@ -213,4 +213,18 @@ TEST_F(libyuvTest, ARGBScaleTo1366) {
} }
} }
TEST_F(libyuvTest, ARGBScaleTo853) {
int src_width = 1280;
int src_height = 720;
int dst_width = 853;
int dst_height = 480;
for (int f = 0; f < 2; ++f) {
int err = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
static_cast<FilterMode>(f));
EXPECT_GE(1, err);
}
}
} // namespace libyuv } // namespace libyuv
...@@ -19,29 +19,29 @@ namespace libyuv { ...@@ -19,29 +19,29 @@ namespace libyuv {
static int TestFilter(int src_width, int src_height, static int TestFilter(int src_width, int src_height,
int dst_width, int dst_height, int dst_width, int dst_height,
FilterMode f) { FilterMode f, int rounding) {
const int b = 128; const int b = 128 * rounding;
int src_width_uv = (src_width + 1) >> 1; int src_width_uv = (src_width + rounding) >> 1;
int src_height_uv = (src_height + 1) >> 1; int src_height_uv = (src_height + rounding) >> 1;
int src_y_plane_size = (src_width + (2 * b)) * (src_height + (2 * b)); int src_y_plane_size = (src_width + b * 2) * (src_height + b * 2);
int src_uv_plane_size = (src_width_uv + (2 * b)) * (src_height_uv + (2 * b)); int src_uv_plane_size = (src_width_uv + b * 2) * (src_height_uv + b * 2);
int src_stride_y = 2 * b + src_width; int src_stride_y = b * 2 + src_width;
int src_stride_uv = 2 * b + src_width_uv; int src_stride_uv = b * 2 + src_width_uv;
align_buffer_16(src_y, src_y_plane_size) align_buffer_page_end(src_y, src_y_plane_size)
align_buffer_16(src_u, src_uv_plane_size) align_buffer_page_end(src_u, src_uv_plane_size)
align_buffer_16(src_v, src_uv_plane_size) align_buffer_page_end(src_v, src_uv_plane_size)
int dst_width_uv = (dst_width + 1) >> 1; int dst_width_uv = (dst_width + rounding) >> 1;
int dst_height_uv = (dst_height + 1) >> 1; int dst_height_uv = (dst_height + rounding) >> 1;
int dst_y_plane_size = (dst_width + (2 * b)) * (dst_height + (2 * b)); int dst_y_plane_size = (dst_width + b * 2) * (dst_height + b * 2);
int dst_uv_plane_size = (dst_width_uv + (2 * b)) * (dst_height_uv + (2 * b)); int dst_uv_plane_size = (dst_width_uv + b * 2) * (dst_height_uv + b * 2);
int dst_stride_y = 2 * b + dst_width; int dst_stride_y = b * 2 + dst_width;
int dst_stride_uv = 2 * b + dst_width_uv; int dst_stride_uv = b * 2 + dst_width_uv;
srandom(time(NULL)); srandom(time(NULL));
...@@ -60,12 +60,12 @@ static int TestFilter(int src_width, int src_height, ...@@ -60,12 +60,12 @@ static int TestFilter(int src_width, int src_height,
} }
const int runs = 1000; const int runs = 1000;
align_buffer_16(dst_y_c, dst_y_plane_size) align_buffer_page_end(dst_y_c, dst_y_plane_size)
align_buffer_16(dst_u_c, dst_uv_plane_size) align_buffer_page_end(dst_u_c, dst_uv_plane_size)
align_buffer_16(dst_v_c, dst_uv_plane_size) align_buffer_page_end(dst_v_c, dst_uv_plane_size)
align_buffer_16(dst_y_opt, dst_y_plane_size) align_buffer_page_end(dst_y_opt, dst_y_plane_size)
align_buffer_16(dst_u_opt, dst_uv_plane_size) align_buffer_page_end(dst_u_opt, dst_uv_plane_size)
align_buffer_16(dst_v_opt, dst_uv_plane_size) align_buffer_page_end(dst_v_opt, dst_uv_plane_size)
// Warm up both versions for consistent benchmarks. // Warm up both versions for consistent benchmarks.
MaskCpuFlags(0); // Disable all CPU optimization. MaskCpuFlags(0); // Disable all CPU optimization.
...@@ -149,16 +149,16 @@ static int TestFilter(int src_width, int src_height, ...@@ -149,16 +149,16 @@ static int TestFilter(int src_width, int src_height,
} }
} }
free_aligned_buffer_16(dst_y_c) free_aligned_buffer_page_end(dst_y_c)
free_aligned_buffer_16(dst_u_c) free_aligned_buffer_page_end(dst_u_c)
free_aligned_buffer_16(dst_v_c) free_aligned_buffer_page_end(dst_v_c)
free_aligned_buffer_16(dst_y_opt) free_aligned_buffer_page_end(dst_y_opt)
free_aligned_buffer_16(dst_u_opt) free_aligned_buffer_page_end(dst_u_opt)
free_aligned_buffer_16(dst_v_opt) free_aligned_buffer_page_end(dst_v_opt)
free_aligned_buffer_16(src_y) free_aligned_buffer_page_end(src_y)
free_aligned_buffer_16(src_u) free_aligned_buffer_page_end(src_u)
free_aligned_buffer_16(src_v) free_aligned_buffer_page_end(src_v)
return max_diff; return max_diff;
} }
...@@ -172,7 +172,7 @@ TEST_F(libyuvTest, ScaleDownBy2) { ...@@ -172,7 +172,7 @@ TEST_F(libyuvTest, ScaleDownBy2) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -186,7 +186,7 @@ TEST_F(libyuvTest, ScaleDownBy4) { ...@@ -186,7 +186,7 @@ TEST_F(libyuvTest, ScaleDownBy4) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(2, err); // This is the only scale factor with error of 2. EXPECT_GE(2, err); // This is the only scale factor with error of 2.
} }
} }
...@@ -200,7 +200,7 @@ TEST_F(libyuvTest, ScaleDownBy5) { ...@@ -200,7 +200,7 @@ TEST_F(libyuvTest, ScaleDownBy5) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -214,7 +214,7 @@ TEST_F(libyuvTest, ScaleDownBy8) { ...@@ -214,7 +214,7 @@ TEST_F(libyuvTest, ScaleDownBy8) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -228,7 +228,7 @@ TEST_F(libyuvTest, ScaleDownBy16) { ...@@ -228,7 +228,7 @@ TEST_F(libyuvTest, ScaleDownBy16) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -242,7 +242,7 @@ TEST_F(libyuvTest, ScaleDownBy34) { ...@@ -242,7 +242,7 @@ TEST_F(libyuvTest, ScaleDownBy34) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -256,7 +256,7 @@ TEST_F(libyuvTest, ScaleDownBy38) { ...@@ -256,7 +256,7 @@ TEST_F(libyuvTest, ScaleDownBy38) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
...@@ -270,7 +270,35 @@ TEST_F(libyuvTest, ScaleTo1366) { ...@@ -270,7 +270,35 @@ TEST_F(libyuvTest, ScaleTo1366) {
for (int f = 0; f < 3; ++f) { for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height, int err = TestFilter(src_width, src_height,
dst_width, dst_height, dst_width, dst_height,
static_cast<FilterMode>(f)); static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err);
}
}
TEST_F(libyuvTest, ScaleTo853) {
int src_width = 1280;
int src_height = 720;
int dst_width = 853;
int dst_height = 480;
for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height,
dst_width, dst_height,
static_cast<FilterMode>(f), 1);
EXPECT_GE(1, err);
}
}
TEST_F(libyuvTest, ScaleTo853Wrong) {
int src_width = 1280;
int src_height = 720;
int dst_width = 853;
int dst_height = 480;
for (int f = 0; f < 3; ++f) {
int err = TestFilter(src_width, src_height,
dst_width, dst_height,
static_cast<FilterMode>(f), 0);
EXPECT_GE(1, err); EXPECT_GE(1, err);
} }
} }
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
uint8* var; \ uint8* var; \
uint8* var##_mem; \ uint8* var##_mem; \
var##_mem = reinterpret_cast<uint8*>(malloc(((size) + 4095) & ~4095)); \ var##_mem = reinterpret_cast<uint8*>(malloc(((size) + 4095) & ~4095)); \
var = var##_mem + (-(size) & 4095) var = var##_mem + (-(size) & 4095);
#define free_aligned_buffer_page_end(var) \ #define free_aligned_buffer_page_end(var) \
free(var##_mem); \ free(var##_mem); \
......
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