Commit 99a1298c authored by fbarchard@google.com's avatar fbarchard@google.com

I444ToI420 etc use ScalePlane on Y to allow mirroring.

BUG=291
TESTED=unittests still pass.
R=tpsiaki@google.com

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

git-svn-id: http://libyuv.googlecode.com/svn/trunk@893 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent a8e4dcb5
...@@ -22,7 +22,43 @@ namespace libyuv { ...@@ -22,7 +22,43 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
static __inline int Abs(int v) {
return v >= 0 ? v : -v;
}
// Any I4xx To I420 format with mirroring.
static int I4xxToI420(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int src_y_width, int src_y_height,
int src_uv_width, int src_uv_height) {
if (src_y_width == 0 || src_y_height == 0 ||
src_uv_width == 0 || src_uv_height == 0) {
return -1;
}
const int dst_y_width = Abs(src_y_width);
const int dst_y_height = Abs(src_y_height);
const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);
const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);
ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
dst_y, dst_stride_y, dst_y_width, dst_y_height,
kFilterBilinear);
ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
kFilterBilinear);
return 0;
}
// Copy I420 with optional flipping // Copy I420 with optional flipping
// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
// is does row coalescing.
LIBYUV_API LIBYUV_API
int I420Copy(const uint8* src_y, int src_stride_y, int I420Copy(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
...@@ -69,37 +105,15 @@ int I422ToI420(const uint8* src_y, int src_stride_y, ...@@ -69,37 +105,15 @@ int I422ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u || !src_v || const int src_uv_width = SUBSAMPLE(width, 1, 1);
!dst_y || !dst_u || !dst_v || return I4xxToI420(src_y, src_stride_y,
width <= 0 || height == 0) { src_u, src_stride_u,
return -1; src_v, src_stride_v,
} dst_y, dst_stride_y,
// Negative height means invert the image. dst_u, dst_stride_u,
if (height < 0) { dst_v, dst_stride_v,
height = -height; width, height,
src_y = src_y + (height - 1) * src_stride_y; src_uv_width, height);
src_u = src_u + (height - 1) * src_stride_u;
src_v = src_v + (height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
ScalePlane(src_u, src_stride_u, halfwidth, height,
dst_u, dst_stride_u, halfwidth, halfheight,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, halfwidth, height,
dst_v, dst_stride_v, halfwidth, halfheight,
kFilterBilinear);
return 0;
} }
// 444 chroma is 1x width, 1x height // 444 chroma is 1x width, 1x height
...@@ -112,37 +126,14 @@ int I444ToI420(const uint8* src_y, int src_stride_y, ...@@ -112,37 +126,14 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u || !src_v || return I4xxToI420(src_y, src_stride_y,
!dst_y || !dst_u || !dst_v || src_u, src_stride_u,
width <= 0 || height == 0) { src_v, src_stride_v,
return -1; dst_y, dst_stride_y,
} dst_u, dst_stride_u,
// Negative height means invert the image. dst_v, dst_stride_v,
if (height < 0) { width, height,
height = -height; width, height);
src_y = src_y + (height - 1) * src_stride_y;
src_u = src_u + (height - 1) * src_stride_u;
src_v = src_v + (height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
ScalePlane(src_u, src_stride_u, width, height,
dst_u, dst_stride_u, halfwidth, halfheight,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, width, height,
dst_v, dst_stride_v, halfwidth, halfheight,
kFilterBilinear);
return 0;
} }
// 411 chroma is 1/4 width, 1x height // 411 chroma is 1/4 width, 1x height
...@@ -155,38 +146,15 @@ int I411ToI420(const uint8* src_y, int src_stride_y, ...@@ -155,38 +146,15 @@ int I411ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u || !src_v || const int src_uv_width = SUBSAMPLE(width, 3, 2);
!dst_y || !dst_u || !dst_v || return I4xxToI420(src_y, src_stride_y,
width <= 0 || height == 0) { src_u, src_stride_u,
return -1; src_v, src_stride_v,
} dst_y, dst_stride_y,
// Negative height means invert the image. dst_u, dst_stride_u,
if (height < 0) { dst_v, dst_stride_v,
height = -height; width, height,
src_y = src_y + (height - 1) * src_stride_y; src_uv_width, height);
src_u = src_u + (height - 1) * src_stride_u;
src_v = src_v + (height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
const int quarterwidth = (width + 3) >> 2;
ScalePlane(src_u, src_stride_u, quarterwidth, height,
dst_u, dst_stride_u, halfwidth, halfheight,
kFilterNone);
ScalePlane(src_v, src_stride_v, quarterwidth, height,
dst_v, dst_stride_v, halfwidth, halfheight,
kFilterNone);
return 0;
} }
// I400 is greyscale typically used in MJPG // I400 is greyscale typically used in MJPG
...@@ -232,7 +200,6 @@ static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1, ...@@ -232,7 +200,6 @@ static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1,
} }
#endif #endif
#if defined(HAS_COPYROW_ERMS) #if defined(HAS_COPYROW_ERMS)
// TODO(fbarchard): Detect Fast String support.
if (TestCpuFlag(kCpuHasERMS)) { if (TestCpuFlag(kCpuHasERMS)) {
CopyRow = CopyRow_ERMS; CopyRow = CopyRow_ERMS;
} }
......
...@@ -25,6 +25,40 @@ namespace libyuv { ...@@ -25,6 +25,40 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
static __inline int Abs(int v) {
return v >= 0 ? v : -v;
}
// I420 To any I4xx YUV format with mirroring.
static int I420ToI4xx(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int src_y_width, int src_y_height,
int dst_uv_width, int dst_uv_height) {
if (src_y_width == 0 || src_y_height == 0 ||
dst_uv_width <= 0 || dst_uv_height <= 0) {
return -1;
}
const int dst_y_width = Abs(src_y_width);
const int dst_y_height = Abs(src_y_height);
const int src_uv_width = SUBSAMPLE(src_y_width, 1, 1);
const int src_uv_height = SUBSAMPLE(src_y_height, 1, 1);
ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
dst_y, dst_stride_y, dst_y_width, dst_y_height,
kFilterBilinear);
ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
kFilterBilinear);
return 0;
}
// 420 chroma is 1/2 width, 1/2 height // 420 chroma is 1/2 width, 1/2 height
// 422 chroma is 1/2 width, 1x height // 422 chroma is 1/2 width, 1x height
LIBYUV_API LIBYUV_API
...@@ -35,38 +69,16 @@ int I420ToI422(const uint8* src_y, int src_stride_y, ...@@ -35,38 +69,16 @@ int I420ToI422(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u || !src_v || const int dst_uv_width = (Abs(width) + 1) >> 1;
!dst_y || !dst_u || !dst_v || const int dst_uv_height = Abs(height);
width <= 0 || height == 0) { return I420ToI4xx(src_y, src_stride_y,
return -1; src_u, src_stride_u,
} src_v, src_stride_v,
// Negative height means invert the image. dst_y, dst_stride_y,
if (height < 0) { dst_u, dst_stride_u,
height = -height; dst_v, dst_stride_v,
dst_y = dst_y + (height - 1) * dst_stride_y; width, height,
dst_u = dst_u + (height - 1) * dst_stride_u; dst_uv_width, dst_uv_height);
dst_v = dst_v + (height - 1) * dst_stride_v;
dst_stride_y = -dst_stride_y;
dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v;
}
// Copy Y plane.
// TODO(fbarchard): Scale Y plane, which will do a copy, but allows mirror.
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
dst_u, dst_stride_u, halfwidth, height,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
dst_v, dst_stride_v, halfwidth, height,
kFilterBilinear);
return 0;
} }
// 420 chroma is 1/2 width, 1/2 height // 420 chroma is 1/2 width, 1/2 height
...@@ -79,37 +91,16 @@ int I420ToI444(const uint8* src_y, int src_stride_y, ...@@ -79,37 +91,16 @@ int I420ToI444(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u|| !src_v || const int dst_uv_width = Abs(width);
!dst_y || !dst_u || !dst_v || const int dst_uv_height = Abs(height);
width <= 0 || height == 0) { return I420ToI4xx(src_y, src_stride_y,
return -1; src_u, src_stride_u,
} src_v, src_stride_v,
// Negative height means invert the image. dst_y, dst_stride_y,
if (height < 0) { dst_u, dst_stride_u,
height = -height; dst_v, dst_stride_v,
dst_y = dst_y + (height - 1) * dst_stride_y; width, height,
dst_u = dst_u + (height - 1) * dst_stride_u; dst_uv_width, dst_uv_height);
dst_v = dst_v + (height - 1) * dst_stride_v;
dst_stride_y = -dst_stride_y;
dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
dst_u, dst_stride_u, width, height,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
dst_v, dst_stride_v, width, height,
kFilterBilinear);
return 0;
} }
// 420 chroma is 1/2 width, 1/2 height // 420 chroma is 1/2 width, 1/2 height
...@@ -122,38 +113,16 @@ int I420ToI411(const uint8* src_y, int src_stride_y, ...@@ -122,38 +113,16 @@ int I420ToI411(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u, uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height) { int width, int height) {
if (!src_y || !src_u || !src_v || const int dst_uv_width = (Abs(width) + 3) >> 2;
!dst_y || !dst_u || !dst_v || const int dst_uv_height = Abs(height);
width <= 0 || height == 0) { return I420ToI4xx(src_y, src_stride_y,
return -1; src_u, src_stride_u,
} src_v, src_stride_v,
// Negative height means invert the image. dst_y, dst_stride_y,
if (height < 0) { dst_u, dst_stride_u,
height = -height; dst_v, dst_stride_v,
dst_y = dst_y + (height - 1) * dst_stride_y; width, height,
dst_u = dst_u + (height - 1) * dst_stride_u; dst_uv_width, dst_uv_height);
dst_v = dst_v + (height - 1) * dst_stride_v;
dst_stride_y = -dst_stride_y;
dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
// Resample UV planes.
const int halfwidth = (width + 1) >> 1;
const int halfheight = (height + 1) >> 1;
const int quarterwidth = (width + 3) >> 2;
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
dst_u, dst_stride_u, quarterwidth, height,
kFilterBilinear);
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
dst_v, dst_stride_v, quarterwidth, height,
kFilterBilinear);
return 0;
} }
// Copy to I400. Source can be I420,422,444,400,NV12,NV21 // Copy to I400. Source can be I420,422,444,400,NV12,NV21
......
...@@ -30,10 +30,7 @@ static __inline int Abs(int v) { ...@@ -30,10 +30,7 @@ static __inline int Abs(int v) {
return v >= 0 ? v : -v; return v >= 0 ? v : -v;
} }
static __inline int Half(int v) { #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
return v >= 0 ? ((v + 1) >> 1) : -((-v + 1) >> 1);
}
// Scale plane, 1/2 // Scale plane, 1/2
// This is an optimized version for scaling down a plane to 1/2 of // This is an optimized version for scaling down a plane to 1/2 of
...@@ -763,8 +760,7 @@ static void ScalePlaneSimple(int src_width, int src_height, ...@@ -763,8 +760,7 @@ static void ScalePlaneSimple(int src_width, int src_height,
} }
// Scale a plane. // Scale a plane.
// This function in turn calls a scaling function suitable for handling // This function dispatches to a specialized scaler based on scale factor.
// the desired resolutions.
LIBYUV_API LIBYUV_API
void ScalePlane(const uint8* src, int src_stride, void ScalePlane(const uint8* src, int src_stride,
...@@ -772,6 +768,13 @@ void ScalePlane(const uint8* src, int src_stride, ...@@ -772,6 +768,13 @@ 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) {
// Negative height means invert the image.
if (src_height < 0) {
src_height = -src_height;
src = src + (src_height - 1) * src_stride;
src_stride = -src_stride;
}
// Use specialized scales to improve performance for common resolutions. // Use specialized scales to improve performance for common resolutions.
// For example, all the 1/2 scalings will use ScalePlaneDown2() // For example, all the 1/2 scalings will use ScalePlaneDown2()
if (dst_width == src_width && dst_height == src_height) { if (dst_width == src_width && dst_height == src_height) {
...@@ -841,8 +844,6 @@ void ScalePlane(const uint8* src, int src_stride, ...@@ -841,8 +844,6 @@ 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.
// TODO(fbarchard): Disable UNDER_ALLOCATED_HACK
#define UNDER_ALLOCATED_HACK 1
LIBYUV_API LIBYUV_API
int I420Scale(const uint8* src_y, int src_stride_y, int I420Scale(const uint8* src_y, int src_stride_y,
...@@ -858,43 +859,10 @@ int I420Scale(const uint8* src_y, int src_stride_y, ...@@ -858,43 +859,10 @@ int I420Scale(const uint8* src_y, int src_stride_y,
!dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) { !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
return -1; return -1;
} }
// Negative height means invert the image. int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
if (src_height < 0) { int src_halfheight = SUBSAMPLE(src_height, 1, 1);
src_height = -src_height; int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
int halfheight = Half(src_height); int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
src_y = src_y + (src_height - 1) * src_stride_y;
src_u = src_u + (halfheight - 1) * src_stride_u;
src_v = src_v + (halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
int src_halfwidth = Half(src_width);
int src_halfheight = Half(src_height);
int dst_halfwidth = Half(dst_width);
int dst_halfheight = Half(dst_height);
#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,
...@@ -917,59 +885,15 @@ int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v, ...@@ -917,59 +885,15 @@ int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
int dst_stride_y, int dst_stride_u, int dst_stride_v, int dst_stride_y, int dst_stride_u, int dst_stride_v,
int dst_width, int dst_height, int dst_width, int dst_height,
bool interpolate) { bool interpolate) {
if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 || return I420Scale(src_y, src_stride_y,
!dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) { src_u, src_stride_u,
return -1; src_v, src_stride_v,
} src_width, src_height,
// Negative height means invert the image. dst_y, dst_stride_y,
if (src_height < 0) { dst_u, dst_stride_u,
src_height = -src_height; dst_v, dst_stride_v,
int halfheight = Half(src_height); dst_width, dst_height,
src_y = src_y + (src_height - 1) * src_stride_y; interpolate ? kFilterBox : kFilterNone);
src_u = src_u + (halfheight - 1) * src_stride_u;
src_v = src_v + (halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
int src_halfwidth = Half(src_width);
int src_halfheight = Half(src_height);
int dst_halfwidth = Half(dst_width);
int dst_halfheight = Half(dst_height);
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,
dst_y, dst_stride_y, dst_width, dst_height,
filtering);
ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight,
dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
filtering);
ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight,
dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
filtering);
return 0;
} }
// Deprecated api // Deprecated api
...@@ -983,10 +907,10 @@ int ScaleOffset(const uint8* src, int src_width, int src_height, ...@@ -983,10 +907,10 @@ int ScaleOffset(const uint8* src, int src_width, int src_height,
return -1; return -1;
} }
dst_yoffset = dst_yoffset & ~1; // chroma requires offset to multiple of 2. dst_yoffset = dst_yoffset & ~1; // chroma requires offset to multiple of 2.
int src_halfwidth = Half(src_width); int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
int src_halfheight = Half(src_height); int src_halfheight = SUBSAMPLE(src_height, 1, 1);
int dst_halfwidth = Half(dst_width); int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
int dst_halfheight = Half(dst_height); int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
int aheight = dst_height - dst_yoffset * 2; // actual output height int aheight = dst_height - dst_yoffset * 2; // actual output height
const uint8* src_y = src; const uint8* src_y = src;
const uint8* src_u = src + src_width * src_height; const uint8* src_u = src + src_width * src_height;
...@@ -997,9 +921,15 @@ int ScaleOffset(const uint8* src, int src_width, int src_height, ...@@ -997,9 +921,15 @@ int ScaleOffset(const uint8* src, int src_width, int src_height,
(dst_yoffset >> 1) * dst_halfwidth; (dst_yoffset >> 1) * dst_halfwidth;
uint8* dst_v = dst + dst_width * dst_height + dst_halfwidth * dst_halfheight + uint8* dst_v = dst + dst_width * dst_height + dst_halfwidth * dst_halfheight +
(dst_yoffset >> 1) * dst_halfwidth; (dst_yoffset >> 1) * dst_halfwidth;
return Scale(src_y, src_u, src_v, src_width, src_halfwidth, src_halfwidth, return I420Scale(src_y, src_width,
src_width, src_height, dst_y, dst_u, dst_v, dst_width, src_u, src_halfwidth,
dst_halfwidth, dst_halfwidth, dst_width, aheight, interpolate); src_v, src_halfwidth,
src_width, src_height,
dst_y, dst_width,
dst_u, dst_halfwidth,
dst_v, dst_halfwidth,
dst_width, aheight,
interpolate ? kFilterBox : kFilterNone);
} }
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -462,7 +462,7 @@ void ScalePlaneVertical(int src_height, ...@@ -462,7 +462,7 @@ void ScalePlaneVertical(int src_height,
int bpp, FilterMode filtering) { int bpp, FilterMode filtering) {
int dst_widthx4 = dst_width * bpp; int dst_widthx4 = dst_width * bpp;
src_argb += (x >> 16) * bpp; src_argb += (x >> 16) * bpp;
assert(src_height > 0); assert(src_height != 0);
assert(dst_width > 0); assert(dst_width > 0);
assert(dst_height > 0); assert(dst_height > 0);
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb, void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
......
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