mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-02-09 03:06:44 +08:00
Function to switch filters to a simplier one based on scale factors.
BUG=none TEST=untested R=tpsiaki@google.com Review URL: https://webrtc-codereview.appspot.com/4989004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@894 16f28f9a-4ce2-e073-06de-1de4eb20be90
This commit is contained in:
parent
99a1298c54
commit
ec0cc5bb2d
@ -1,6 +1,6 @@
|
|||||||
Name: libyuv
|
Name: libyuv
|
||||||
URL: http://code.google.com/p/libyuv/
|
URL: http://code.google.com/p/libyuv/
|
||||||
Version: 892
|
Version: 894
|
||||||
License: BSD
|
License: BSD
|
||||||
License File: LICENSE
|
License File: LICENSE
|
||||||
|
|
||||||
|
|||||||
@ -18,12 +18,12 @@ namespace libyuv {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Supported filtering
|
// Supported filtering.
|
||||||
enum FilterMode {
|
enum FilterMode {
|
||||||
kFilterNone = 0, // Point sample; Fastest.
|
kFilterNone = 0, // Point sample; Fastest.
|
||||||
kFilterBilinear = 1, // Faster than box, but lower quality scaling down.
|
kFilterLinear = 1, // Filter horizontally only.
|
||||||
kFilterBox = 2, // Highest quality.
|
kFilterBilinear = 2, // Faster than box, but lower quality scaling down.
|
||||||
kFilterLinear = 3 // Faster than bilinear, slower than None.
|
kFilterBox = 3 // Highest quality.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scale a YUV plane.
|
// Scale a YUV plane.
|
||||||
|
|||||||
@ -55,6 +55,10 @@ extern "C" {
|
|||||||
#define HAS_SCALEROWDOWN38_MIPS_DSPR2
|
#define HAS_SCALEROWDOWN38_MIPS_DSPR2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FilterMode ScaleFilterReduce(int src_width, int src_height,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
FilterMode filtering);
|
||||||
|
|
||||||
// Scale ARGB vertically with bilinear interpolation.
|
// Scale ARGB vertically with bilinear interpolation.
|
||||||
void ScalePlaneVertical(int src_height,
|
void ScalePlaneVertical(int src_height,
|
||||||
int dst_width, int dst_height,
|
int dst_width, int dst_height,
|
||||||
|
|||||||
@ -11,6 +11,6 @@
|
|||||||
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
|
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
|
||||||
#define INCLUDE_LIBYUV_VERSION_H_
|
#define INCLUDE_LIBYUV_VERSION_H_
|
||||||
|
|
||||||
#define LIBYUV_VERSION 892
|
#define LIBYUV_VERSION 894
|
||||||
|
|
||||||
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
|
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
|
||||||
|
|||||||
@ -768,6 +768,11 @@ void ScalePlane(const uint8* src, int src_stride,
|
|||||||
uint8* dst, int dst_stride,
|
uint8* dst, int dst_stride,
|
||||||
int dst_width, int dst_height,
|
int dst_width, int dst_height,
|
||||||
FilterMode filtering) {
|
FilterMode filtering) {
|
||||||
|
// Simplify filtering when possible.
|
||||||
|
filtering = ScaleFilterReduce(src_width, src_height,
|
||||||
|
dst_width, dst_height,
|
||||||
|
filtering);
|
||||||
|
|
||||||
// Negative height means invert the image.
|
// Negative height means invert the image.
|
||||||
if (src_height < 0) {
|
if (src_height < 0) {
|
||||||
src_height = -src_height;
|
src_height = -src_height;
|
||||||
|
|||||||
@ -572,6 +572,16 @@ static void ScaleARGB(const uint8* src, int src_stride,
|
|||||||
int dst_width, int dst_height,
|
int dst_width, int dst_height,
|
||||||
int clip_x, int clip_y, int clip_width, int clip_height,
|
int clip_x, int clip_y, int clip_width, int clip_height,
|
||||||
FilterMode filtering) {
|
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,
|
||||||
|
filtering);
|
||||||
|
|
||||||
// Negative src_height means invert the image.
|
// Negative src_height means invert the image.
|
||||||
if (src_height < 0) {
|
if (src_height < 0) {
|
||||||
src_height = -src_height;
|
src_height = -src_height;
|
||||||
|
|||||||
@ -460,18 +460,20 @@ void ScalePlaneVertical(int src_height,
|
|||||||
const uint8* src_argb, uint8* dst_argb,
|
const uint8* src_argb, uint8* dst_argb,
|
||||||
int x, int y, int dy,
|
int x, int y, int dy,
|
||||||
int bpp, FilterMode filtering) {
|
int bpp, FilterMode filtering) {
|
||||||
int dst_widthx4 = dst_width * bpp;
|
// TODO(fbarchard): Allow higher bpp.
|
||||||
src_argb += (x >> 16) * bpp;
|
assert(bpp >= 1 && bpp <= 4);
|
||||||
assert(src_height != 0);
|
assert(src_height != 0);
|
||||||
assert(dst_width > 0);
|
assert(dst_width > 0);
|
||||||
assert(dst_height > 0);
|
assert(dst_height > 0);
|
||||||
|
int dst_width_bytes = dst_width * bpp;
|
||||||
|
src_argb += (x >> 16) * bpp;
|
||||||
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
|
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
|
||||||
ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
|
ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
|
||||||
InterpolateRow_C;
|
InterpolateRow_C;
|
||||||
#if defined(HAS_INTERPOLATEROW_SSE2)
|
#if defined(HAS_INTERPOLATEROW_SSE2)
|
||||||
if (TestCpuFlag(kCpuHasSSE2) && dst_widthx4 >= 16) {
|
if (TestCpuFlag(kCpuHasSSE2) && dst_width_bytes >= 16) {
|
||||||
InterpolateRow = InterpolateRow_Any_SSE2;
|
InterpolateRow = InterpolateRow_Any_SSE2;
|
||||||
if (IS_ALIGNED(dst_widthx4, 16)) {
|
if (IS_ALIGNED(dst_width_bytes, 16)) {
|
||||||
InterpolateRow = InterpolateRow_Unaligned_SSE2;
|
InterpolateRow = InterpolateRow_Unaligned_SSE2;
|
||||||
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
|
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
|
||||||
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
|
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
|
||||||
@ -481,9 +483,9 @@ void ScalePlaneVertical(int src_height,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAS_INTERPOLATEROW_SSSE3)
|
#if defined(HAS_INTERPOLATEROW_SSSE3)
|
||||||
if (TestCpuFlag(kCpuHasSSSE3) && dst_widthx4 >= 16) {
|
if (TestCpuFlag(kCpuHasSSSE3) && dst_width_bytes >= 16) {
|
||||||
InterpolateRow = InterpolateRow_Any_SSSE3;
|
InterpolateRow = InterpolateRow_Any_SSSE3;
|
||||||
if (IS_ALIGNED(dst_widthx4, 16)) {
|
if (IS_ALIGNED(dst_width_bytes, 16)) {
|
||||||
InterpolateRow = InterpolateRow_Unaligned_SSSE3;
|
InterpolateRow = InterpolateRow_Unaligned_SSSE3;
|
||||||
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
|
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
|
||||||
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
|
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
|
||||||
@ -493,27 +495,27 @@ void ScalePlaneVertical(int src_height,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAS_INTERPOLATEROW_AVX2)
|
#if defined(HAS_INTERPOLATEROW_AVX2)
|
||||||
if (TestCpuFlag(kCpuHasAVX2) && dst_widthx4 >= 32) {
|
if (TestCpuFlag(kCpuHasAVX2) && dst_width_bytes >= 32) {
|
||||||
InterpolateRow = InterpolateRow_Any_AVX2;
|
InterpolateRow = InterpolateRow_Any_AVX2;
|
||||||
if (IS_ALIGNED(dst_widthx4, 32)) {
|
if (IS_ALIGNED(dst_width_bytes, 32)) {
|
||||||
InterpolateRow = InterpolateRow_AVX2;
|
InterpolateRow = InterpolateRow_AVX2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAS_INTERPOLATEROW_NEON)
|
#if defined(HAS_INTERPOLATEROW_NEON)
|
||||||
if (TestCpuFlag(kCpuHasNEON) && dst_widthx4 >= 16) {
|
if (TestCpuFlag(kCpuHasNEON) && dst_width_bytes >= 16) {
|
||||||
InterpolateRow = InterpolateRow_Any_NEON;
|
InterpolateRow = InterpolateRow_Any_NEON;
|
||||||
if (IS_ALIGNED(dst_widthx4, 16)) {
|
if (IS_ALIGNED(dst_width_bytes, 16)) {
|
||||||
InterpolateRow = InterpolateRow_NEON;
|
InterpolateRow = InterpolateRow_NEON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
|
#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
|
||||||
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_widthx4 >= 4 &&
|
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width_bytes >= 4 &&
|
||||||
IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
|
IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
|
||||||
IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
|
IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
|
||||||
InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
|
InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
|
||||||
if (IS_ALIGNED(dst_widthx4, 4)) {
|
if (IS_ALIGNED(dst_width_bytes, 4)) {
|
||||||
InterpolateRow = InterpolateRow_MIPS_DSPR2;
|
InterpolateRow = InterpolateRow_MIPS_DSPR2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,12 +528,53 @@ void ScalePlaneVertical(int src_height,
|
|||||||
int yi = y >> 16;
|
int yi = y >> 16;
|
||||||
int yf = filtering ? ((y >> 8) & 255) : 0;
|
int yf = filtering ? ((y >> 8) & 255) : 0;
|
||||||
const uint8* src = src_argb + yi * src_stride;
|
const uint8* src = src_argb + yi * src_stride;
|
||||||
InterpolateRow(dst_argb, src, src_stride, dst_widthx4, yf);
|
InterpolateRow(dst_argb, src, src_stride, dst_width_bytes, yf);
|
||||||
dst_argb += dst_stride;
|
dst_argb += dst_stride;
|
||||||
y += dy;
|
y += dy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale plane vertically with bilinear interpolation.
|
||||||
|
FilterMode ScaleFilterReduce(int src_width, int src_height,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
FilterMode filtering) {
|
||||||
|
if (src_width < 0) {
|
||||||
|
src_width = -src_width;
|
||||||
|
}
|
||||||
|
if (src_height < 0) {
|
||||||
|
src_height = -src_height;
|
||||||
|
}
|
||||||
|
if (filtering == kFilterBox) {
|
||||||
|
// If scaling both axis to 0.5 or larger, switch from Box to Bilinear.
|
||||||
|
if (dst_width * 2 >= src_width && dst_height * 2 >= src_height) {
|
||||||
|
filtering = kFilterBilinear;
|
||||||
|
}
|
||||||
|
// If scaling to larger, switch from Box to Bilinear.
|
||||||
|
if (dst_width >= src_width || dst_height >= src_height) {
|
||||||
|
filtering = kFilterBilinear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filtering == kFilterBilinear) {
|
||||||
|
if (src_height == 1) {
|
||||||
|
filtering = kFilterLinear;
|
||||||
|
}
|
||||||
|
// TODO(fbarchard): Detect any odd scale factor and reduce to Linear.
|
||||||
|
if (dst_height == src_height || dst_height * 3 == src_height) {
|
||||||
|
filtering = kFilterLinear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filtering == kFilterLinear) {
|
||||||
|
if (src_width == 1) {
|
||||||
|
filtering = kFilterNone;
|
||||||
|
}
|
||||||
|
// TODO(fbarchard): Detect any odd scale factor and reduce to None.
|
||||||
|
if (dst_width == src_width || dst_width * 3 == src_width) {
|
||||||
|
filtering = kFilterNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtering;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
} // namespace libyuv
|
} // namespace libyuv
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user