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

Use scaling for YUV to YUV.

BUG=none
TEST=I4*ToI4*
R=tpsiaki@google.com

Review URL: https://webrtc-codereview.appspot.com/4969004

git-svn-id: http://libyuv.googlecode.com/svn/trunk@892 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent 48e53643
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 891 Version: 892
License: BSD License: BSD
License File: LICENSE License File: LICENSE
......
...@@ -11,6 +11,6 @@ ...@@ -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 891 #define LIBYUV_VERSION 892
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
...@@ -39,7 +39,7 @@ int I420Copy(const uint8* src_y, int src_stride_y, ...@@ -39,7 +39,7 @@ int I420Copy(const uint8* src_y, int src_stride_y,
// Negative height means invert the image. // Negative height means invert the image.
if (height < 0) { if (height < 0) {
height = -height; height = -height;
int halfheight = (height + 1) >> 1; const int halfheight = (height + 1) >> 1;
src_y = src_y + (height - 1) * src_stride_y; src_y = src_y + (height - 1) * src_stride_y;
src_u = src_u + (halfheight - 1) * src_stride_u; src_u = src_u + (halfheight - 1) * src_stride_u;
src_v = src_v + (halfheight - 1) * src_stride_v; src_v = src_v + (halfheight - 1) * src_stride_v;
...@@ -48,11 +48,12 @@ int I420Copy(const uint8* src_y, int src_stride_y, ...@@ -48,11 +48,12 @@ int I420Copy(const uint8* src_y, int src_stride_y,
src_stride_v = -src_stride_v; src_stride_v = -src_stride_v;
} }
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
if (dst_y) { if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
// Copy UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight); CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight); CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
return 0; return 0;
...@@ -89,15 +90,12 @@ int I422ToI420(const uint8* src_y, int src_stride_y, ...@@ -89,15 +90,12 @@ int I422ToI420(const uint8* src_y, int src_stride_y,
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
int halfwidth = (width + 1) >> 1; // Resample UV planes.
int halfheight = (height + 1) >> 1; const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
// Resample U plane.
ScalePlane(src_u, src_stride_u, halfwidth, height, ScalePlane(src_u, src_stride_u, halfwidth, height,
dst_u, dst_stride_u, halfwidth, halfheight, dst_u, dst_stride_u, halfwidth, halfheight,
kFilterBilinear); kFilterBilinear);
// Resample V plane.
ScalePlane(src_v, src_stride_v, halfwidth, height, ScalePlane(src_v, src_stride_v, halfwidth, height,
dst_v, dst_stride_v, halfwidth, halfheight, dst_v, dst_stride_v, halfwidth, halfheight,
kFilterBilinear); kFilterBilinear);
...@@ -135,15 +133,12 @@ int I444ToI420(const uint8* src_y, int src_stride_y, ...@@ -135,15 +133,12 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
int halfwidth = (width + 1) >> 1; // Resample UV planes.
int halfheight = (height + 1) >> 1; const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
// Resample U plane.
ScalePlane(src_u, src_stride_u, width, height, ScalePlane(src_u, src_stride_u, width, height,
dst_u, dst_stride_u, halfwidth, halfheight, dst_u, dst_stride_u, halfwidth, halfheight,
kFilterBilinear); kFilterBilinear);
// Resample V plane.
ScalePlane(src_v, src_stride_v, width, height, ScalePlane(src_v, src_stride_v, width, height,
dst_v, dst_stride_v, halfwidth, halfheight, dst_v, dst_stride_v, halfwidth, halfheight,
kFilterBilinear); kFilterBilinear);
...@@ -152,8 +147,6 @@ int I444ToI420(const uint8* src_y, int src_stride_y, ...@@ -152,8 +147,6 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
// 411 chroma is 1/4 width, 1x height // 411 chroma is 1/4 width, 1x height
// 420 chroma is 1/2 width, 1/2 height // 420 chroma is 1/2 width, 1/2 height
// TODO(fbarchard): Change to kFilterBilinear; Test with valgrind.
// TODO(fbarchard): Share code for 444 and 422 to 420.
LIBYUV_API LIBYUV_API
int I411ToI420(const uint8* src_y, int src_stride_y, int I411ToI420(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
...@@ -183,16 +176,13 @@ int I411ToI420(const uint8* src_y, int src_stride_y, ...@@ -183,16 +176,13 @@ int I411ToI420(const uint8* src_y, int src_stride_y,
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
int halfwidth = (width + 1) >> 1; // Resample UV planes.
int halfheight = (height + 1) >> 1; const int halfwidth = (width + 1) >> 1;
int quarterwidth = (width + 3) >> 2; const int halfheight = (height + 1) >> 1;
const int quarterwidth = (width + 3) >> 2;
// Resample U plane.
ScalePlane(src_u, src_stride_u, quarterwidth, height, ScalePlane(src_u, src_stride_u, quarterwidth, height,
dst_u, dst_stride_u, halfwidth, halfheight, dst_u, dst_stride_u, halfwidth, halfheight,
kFilterNone); kFilterNone);
// Resample V plane.
ScalePlane(src_v, src_stride_v, quarterwidth, height, ScalePlane(src_v, src_stride_v, quarterwidth, height,
dst_v, dst_stride_v, halfwidth, halfheight, dst_v, dst_stride_v, halfwidth, halfheight,
kFilterNone); kFilterNone);
......
...@@ -25,6 +25,8 @@ namespace libyuv { ...@@ -25,6 +25,8 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
// 420 chroma is 1/2 width, 1/2 height
// 422 chroma is 1/2 width, 1x height
LIBYUV_API LIBYUV_API
int I420ToI422(const uint8* src_y, int src_stride_y, int I420ToI422(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
...@@ -48,69 +50,27 @@ int I420ToI422(const uint8* src_y, int src_stride_y, ...@@ -48,69 +50,27 @@ int I420ToI422(const uint8* src_y, int src_stride_y,
dst_stride_u = -dst_stride_u; dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v; dst_stride_v = -dst_stride_v;
} }
int halfwidth = (width + 1) >> 1;
void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
#if defined(HAS_COPYROW_X86)
if (IS_ALIGNED(halfwidth, 4)) {
CopyRow = CopyRow_X86;
}
#endif
#if defined(HAS_COPYROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(halfwidth, 32) &&
IS_ALIGNED(src_u, 16) && IS_ALIGNED(src_stride_u, 16) &&
IS_ALIGNED(src_v, 16) && IS_ALIGNED(src_stride_v, 16) &&
IS_ALIGNED(dst_u, 16) && IS_ALIGNED(dst_stride_u, 16) &&
IS_ALIGNED(dst_v, 16) && IS_ALIGNED(dst_stride_v, 16)) {
CopyRow = CopyRow_SSE2;
}
#endif
#if defined(HAS_COPYROW_ERMS)
if (TestCpuFlag(kCpuHasERMS)) {
CopyRow = CopyRow_ERMS;
}
#endif
#if defined(HAS_COPYROW_NEON)
if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(halfwidth, 32)) {
CopyRow = CopyRow_NEON;
}
#endif
#if defined(HAS_COPYROW_MIPS)
if (TestCpuFlag(kCpuHasMIPS)) {
CopyRow = CopyRow_MIPS;
}
#endif
// Copy Y plane // Copy Y plane.
// TODO(fbarchard): Scale Y plane, which will do a copy, but allows mirror.
if (dst_y) { if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
// UpSample U plane. // Resample UV planes.
int y; const int halfwidth = (width + 1) >> 1;
for (y = 0; y < height - 1; y += 2) { const int halfheight = (height + 1) >> 1;
CopyRow(src_u, dst_u, halfwidth); ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
CopyRow(src_u, dst_u + dst_stride_u, halfwidth); dst_u, dst_stride_u, halfwidth, height,
src_u += src_stride_u; kFilterBilinear);
dst_u += dst_stride_u * 2; ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
} dst_v, dst_stride_v, halfwidth, height,
if (height & 1) { kFilterBilinear);
CopyRow(src_u, dst_u, halfwidth);
}
// UpSample V plane.
for (y = 0; y < height - 1; y += 2) {
CopyRow(src_v, dst_v, halfwidth);
CopyRow(src_v, dst_v + dst_stride_v, halfwidth);
src_v += src_stride_v;
dst_v += dst_stride_v * 2;
}
if (height & 1) {
CopyRow(src_v, dst_v, halfwidth);
}
return 0; return 0;
} }
// TODO(fbarchard): Enable bilinear when fast enough or specialized upsampler. // 420 chroma is 1/2 width, 1/2 height
// 444 chroma is 1x width, 1x height
LIBYUV_API LIBYUV_API
int I420ToI444(const uint8* src_y, int src_stride_y, int I420ToI444(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
...@@ -140,18 +100,15 @@ int I420ToI444(const uint8* src_y, int src_stride_y, ...@@ -140,18 +100,15 @@ int I420ToI444(const uint8* src_y, int src_stride_y,
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
int halfwidth = (width + 1) >> 1; // Resample UV planes.
int halfheight = (height + 1) >> 1; const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
// Upsample U plane from from 1/2 width, 1/2 height to 1x width, 1x height.
ScalePlane(src_u, src_stride_u, halfwidth, halfheight, ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
dst_u, dst_stride_u, width, height, dst_u, dst_stride_u, width, height,
kFilterNone); kFilterBilinear);
// Upsample V plane.
ScalePlane(src_v, src_stride_v, halfwidth, halfheight, ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
dst_v, dst_stride_v, width, height, dst_v, dst_stride_v, width, height,
kFilterNone); kFilterBilinear);
return 0; return 0;
} }
...@@ -186,19 +143,16 @@ int I420ToI411(const uint8* src_y, int src_stride_y, ...@@ -186,19 +143,16 @@ int I420ToI411(const uint8* src_y, int src_stride_y,
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
} }
int halfwidth = (width + 1) >> 1; // Resample UV planes.
int halfheight = (height + 1) >> 1; const int halfwidth = (width + 1) >> 1;
int quarterwidth = (width + 3) >> 2; const int halfheight = (height + 1) >> 1;
const int quarterwidth = (width + 3) >> 2;
// Resample U plane from 1/2 width, 1/2 height to 1/4 width, 1x height
ScalePlane(src_u, src_stride_u, halfwidth, halfheight, ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
dst_u, dst_stride_u, quarterwidth, height, dst_u, dst_stride_u, quarterwidth, height,
kFilterNone); kFilterBilinear);
// Resample V plane.
ScalePlane(src_v, src_stride_v, halfwidth, halfheight, ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
dst_v, dst_stride_v, quarterwidth, height, dst_v, dst_stride_v, quarterwidth, height,
kFilterNone); kFilterBilinear);
return 0; return 0;
} }
......
...@@ -718,16 +718,29 @@ static void ScalePlaneSimple(int src_width, int src_height, ...@@ -718,16 +718,29 @@ static void ScalePlaneSimple(int src_width, int src_height,
int dst_width, int dst_height, int dst_width, int dst_height,
int src_stride, int dst_stride, int src_stride, int dst_stride,
const uint8* src_ptr, uint8* dst_ptr) { const uint8* src_ptr, uint8* dst_ptr) {
int dx = FixedDiv(Abs(src_width), dst_width); int dx = 0;
int dy = FixedDiv(src_height, dst_height); int dy = 0;
int x = dx >> 1; int x = 0;
int y = dy >> 1; int y = 0;
if (dst_width <= Abs(src_width)) {
dx = FixedDiv(Abs(src_width), dst_width);
x = (dx >> 1) - 32768;
} else if (dst_width > 1) {
dx = FixedDiv(Abs(src_width) - 1, dst_width - 1);
}
// Negative src_width means horizontally mirror. // Negative src_width means horizontally mirror.
if (src_width < 0) { if (src_width < 0) {
x += (dst_width - 1) * dx; x += (dst_width - 1) * dx;
dx = -dx; dx = -dx;
src_width = -src_width; src_width = -src_width;
} }
if (dst_height <= src_height) {
dy = FixedDiv(src_height, dst_height);
y = (dy >> 1) - 32768;
} else if (dst_height > 1) {
dy = FixedDiv(src_height - 1, dst_height - 1);
}
void (*ScaleCols)(uint8* dst_ptr, const uint8* src_ptr, void (*ScaleCols)(uint8* dst_ptr, const uint8* src_ptr,
int dst_width, int x, int dx) = ScaleCols_C; int dst_width, int x, int dx) = ScaleCols_C;
if (src_width * 2 == dst_width && x < 0x8000) { if (src_width * 2 == dst_width && x < 0x8000) {
......
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