| Index: source/planar_functions.cc
 | 
| diff --git a/source/planar_functions.cc b/source/planar_functions.cc
 | 
| index 6379217862bb7cbbaab7dfa0a72031263e56d512..b15b6e523b35229a7e162a1b239b8ef23194b718 100644
 | 
| --- a/source/planar_functions.cc
 | 
| +++ b/source/planar_functions.cc
 | 
| @@ -1681,37 +1681,37 @@ int ARGBShade(const uint8* src_argb, int src_stride_argb,
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| -// Interpolate 2 ARGB images by specified amount (0 to 255).
 | 
| +// Interpolate 2 planes by specified amount (0 to 255).
 | 
|  LIBYUV_API
 | 
| -int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
 | 
| -                    const uint8* src_argb1, int src_stride_argb1,
 | 
| -                    uint8* dst_argb, int dst_stride_argb,
 | 
| -                    int width, int height, int interpolation) {
 | 
| +int InterpolatePlane(const uint8* src0, int src_stride0,
 | 
| +                     const uint8* src1, int src_stride1,
 | 
| +                     uint8* dst, int dst_stride,
 | 
| +                     int width, int height, int interpolation) {
 | 
|    int y;
 | 
|    void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
 | 
|                           ptrdiff_t src_stride, int dst_width,
 | 
|                           int source_y_fraction) = InterpolateRow_C;
 | 
| -  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
 | 
| +  if (!src0 || !src1 || !dst || width <= 0 || height == 0) {
 | 
|      return -1;
 | 
|    }
 | 
|    // Negative height means invert the image.
 | 
|    if (height < 0) {
 | 
|      height = -height;
 | 
| -    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
 | 
| -    dst_stride_argb = -dst_stride_argb;
 | 
| +    dst = dst + (height - 1) * dst_stride;
 | 
| +    dst_stride = -dst_stride;
 | 
|    }
 | 
|    // Coalesce rows.
 | 
| -  if (src_stride_argb0 == width * 4 &&
 | 
| -      src_stride_argb1 == width * 4 &&
 | 
| -      dst_stride_argb == width * 4) {
 | 
| +  if (src_stride0 == width &&
 | 
| +      src_stride1 == width &&
 | 
| +      dst_stride == width) {
 | 
|      width *= height;
 | 
|      height = 1;
 | 
| -    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
 | 
| +    src_stride0 = src_stride1 = dst_stride = 0;
 | 
|    }
 | 
|  #if defined(HAS_INTERPOLATEROW_SSE2)
 | 
|    if (TestCpuFlag(kCpuHasSSE2)) {
 | 
|      InterpolateRow = InterpolateRow_Any_SSE2;
 | 
| -    if (IS_ALIGNED(width, 4)) {
 | 
| +    if (IS_ALIGNED(width, 16)) {
 | 
|        InterpolateRow = InterpolateRow_SSE2;
 | 
|      }
 | 
|    }
 | 
| @@ -1719,7 +1719,7 @@ int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
 | 
|  #if defined(HAS_INTERPOLATEROW_SSSE3)
 | 
|    if (TestCpuFlag(kCpuHasSSSE3)) {
 | 
|      InterpolateRow = InterpolateRow_Any_SSSE3;
 | 
| -    if (IS_ALIGNED(width, 4)) {
 | 
| +    if (IS_ALIGNED(width, 16)) {
 | 
|        InterpolateRow = InterpolateRow_SSSE3;
 | 
|      }
 | 
|    }
 | 
| @@ -1727,7 +1727,7 @@ int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
 | 
|  #if defined(HAS_INTERPOLATEROW_AVX2)
 | 
|    if (TestCpuFlag(kCpuHasAVX2)) {
 | 
|      InterpolateRow = InterpolateRow_Any_AVX2;
 | 
| -    if (IS_ALIGNED(width, 8)) {
 | 
| +    if (IS_ALIGNED(width, 32)) {
 | 
|        InterpolateRow = InterpolateRow_AVX2;
 | 
|      }
 | 
|    }
 | 
| @@ -1735,27 +1735,75 @@ int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
 | 
|  #if defined(HAS_INTERPOLATEROW_NEON)
 | 
|    if (TestCpuFlag(kCpuHasNEON)) {
 | 
|      InterpolateRow = InterpolateRow_Any_NEON;
 | 
| -    if (IS_ALIGNED(width, 4)) {
 | 
| +    if (IS_ALIGNED(width, 16)) {
 | 
|        InterpolateRow = InterpolateRow_NEON;
 | 
|      }
 | 
|    }
 | 
|  #endif
 | 
|  #if defined(HAS_INTERPOLATEROW_MIPS_DSPR2)
 | 
|    if (TestCpuFlag(kCpuHasMIPS_DSPR2) &&
 | 
| -      IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) &&
 | 
| -      IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) &&
 | 
| -      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
 | 
| +      IS_ALIGNED(src0, 4) && IS_ALIGNED(src_stride0, 4) &&
 | 
| +      IS_ALIGNED(src1, 4) && IS_ALIGNED(src_stride1, 4) &&
 | 
| +      IS_ALIGNED(dst, 4) && IS_ALIGNED(dst_stride, 4) &&
 | 
| +      IS_ALIGNED(width, 4)) {
 | 
|      InterpolateRow = InterpolateRow_MIPS_DSPR2;
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
|    for (y = 0; y < height; ++y) {
 | 
| -    InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0,
 | 
| -                   width * 4, interpolation);
 | 
| -    src_argb0 += src_stride_argb0;
 | 
| -    src_argb1 += src_stride_argb1;
 | 
| -    dst_argb += dst_stride_argb;
 | 
| +    InterpolateRow(dst, src0, src1 - src0,
 | 
| +                   width, interpolation);
 | 
| +    src0 += src_stride0;
 | 
| +    src1 += src_stride1;
 | 
| +    dst += dst_stride;
 | 
| +  }
 | 
| +  return 0;
 | 
| +}
 | 
| +
 | 
| +// Interpolate 2 ARGB images by specified amount (0 to 255).
 | 
| +LIBYUV_API
 | 
| +int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
 | 
| +                    const uint8* src_argb1, int src_stride_argb1,
 | 
| +                    uint8* dst_argb, int dst_stride_argb,
 | 
| +                    int width, int height, int interpolation) {
 | 
| +  return InterpolatePlane(src_argb0, src_stride_argb0,
 | 
| +                          src_argb1, src_stride_argb1,
 | 
| +                          dst_argb, dst_stride_argb,
 | 
| +                          width * 4, height, interpolation);
 | 
| +}
 | 
| +
 | 
| +// Interpolate 2 YUV images by specified amount (0 to 255).
 | 
| +LIBYUV_API
 | 
| +int I420Interpolate(const uint8* src0_y, int src0_stride_y,
 | 
| +                    const uint8* src0_u, int src0_stride_u,
 | 
| +                    const uint8* src0_v, int src0_stride_v,
 | 
| +                    const uint8* src1_y, int src1_stride_y,
 | 
| +                    const uint8* src1_u, int src1_stride_u,
 | 
| +                    const uint8* src1_v, int src1_stride_v,
 | 
| +                    uint8* dst_y, int dst_stride_y,
 | 
| +                    uint8* dst_u, int dst_stride_u,
 | 
| +                    uint8* dst_v, int dst_stride_v,
 | 
| +                    int width, int height, int interpolation) {
 | 
| +  int halfwidth = (width + 1) >> 1;
 | 
| +  int halfheight = (height + 1) >> 1;
 | 
| +  if (!src0_y || !src0_u || !src0_v ||
 | 
| +      !src1_y || !src1_u || !src1_v ||
 | 
| +      !dst_y || !dst_u || !dst_v ||
 | 
| +      width <= 0 || height == 0) {
 | 
| +    return -1;
 | 
|    }
 | 
| +  InterpolatePlane(src0_y, src0_stride_y,
 | 
| +                   src1_y, src1_stride_y,
 | 
| +                   dst_y, dst_stride_y,
 | 
| +                   width, height, interpolation);
 | 
| +  InterpolatePlane(src0_u, src0_stride_u,
 | 
| +                   src1_u, src1_stride_u,
 | 
| +                   dst_u, dst_stride_u,
 | 
| +                   halfwidth, halfheight, interpolation);
 | 
| +  InterpolatePlane(src0_v, src0_stride_v,
 | 
| +                   src1_v, src1_stride_v,
 | 
| +                   dst_v, dst_stride_v,
 | 
| +                   halfwidth, halfheight, interpolation);
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| 
 |