/* * Copyright 2011 The LibYuv Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/scale.h" #include <assert.h>#include <string.h> #include "libyuv/cpu_id.h"#include "libyuv/planar_functions.h" // For CopyPlane#include "libyuv/row.h"#include "libyuv/scale_row.h" #ifdef __cplusplusnamespace libyuv {extern "C" {#endif static __inline int Abs(int v) { return v >= 0 ? v : -v;} #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) // Scale plane, 1/2// This is an optimized version for scaling down a plane to 1/2 of// its original size. static void ScalePlaneDown2(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown2)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width) = filtering == kFilterNone ? ScaleRowDown2_C : (filtering == kFilterLinear ? ScaleRowDown2Linear_C : ScaleRowDown2Box_C); int row_stride = src_stride << 1; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride; // Point to odd rows. src_stride = 0; } #if defined(HAS_SCALEROWDOWN2_NEON) if (TestCpuFlag(kCpuHasNEON)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_NEON : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_NEON : ScaleRowDown2Box_Any_NEON); if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_NEON : (filtering == kFilterLinear ? ScaleRowDown2Linear_NEON : ScaleRowDown2Box_NEON); } }#endif#if defined(HAS_SCALEROWDOWN2_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_SSSE3 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3 : ScaleRowDown2Box_Any_SSSE3); if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_SSSE3 : (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3 : ScaleRowDown2Box_SSSE3); } }#endif#if defined(HAS_SCALEROWDOWN2_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_AVX2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2 : ScaleRowDown2Box_Any_AVX2); if (IS_ALIGNED(dst_width, 32)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_AVX2 : ScaleRowDown2Box_AVX2); } }#endif#if defined(HAS_SCALEROWDOWN2_MSA) if (TestCpuFlag(kCpuHasMSA)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_MSA : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_MSA : ScaleRowDown2Box_Any_MSA); if (IS_ALIGNED(dst_width, 32)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_MSA : (filtering == kFilterLinear ? ScaleRowDown2Linear_MSA : ScaleRowDown2Box_MSA); } }#endif if (filtering == kFilterLinear) { src_stride = 0; } // TODO(fbarchard): Loop through source height to allow odd height. for (y = 0; y < dst_height; ++y) { ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; }} static void ScalePlaneDown2_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width) = filtering == kFilterNone ? ScaleRowDown2_16_C : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_C : ScaleRowDown2Box_16_C); int row_stride = src_stride << 1; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride; // Point to odd rows. src_stride = 0; } #if defined(HAS_SCALEROWDOWN2_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering ? ScaleRowDown2Box_16_NEON : ScaleRowDown2_16_NEON; }#endif#if defined(HAS_SCALEROWDOWN2_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_SSE2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2 : ScaleRowDown2Box_16_SSE2); }#endif if (filtering == kFilterLinear) { src_stride = 0; } // TODO(fbarchard): Loop through source height to allow odd height. for (y = 0; y < dst_height; ++y) { ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; }} // Scale plane, 1/4// This is an optimized version for scaling down a plane to 1/4 of// its original size. static void ScalePlaneDown4(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown4)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width) = filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C; int row_stride = src_stride << 2; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride * 2; // Point to row 2. src_stride = 0; }#if defined(HAS_SCALEROWDOWN4_NEON) if (TestCpuFlag(kCpuHasNEON)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_NEON : ScaleRowDown4_Any_NEON; if (IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON; } }#endif#if defined(HAS_SCALEROWDOWN4_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3; if (IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3; } }#endif#if defined(HAS_SCALEROWDOWN4_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2; if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2; } }#endif#if defined(HAS_SCALEROWDOWN4_MSA) if (TestCpuFlag(kCpuHasMSA)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_MSA : ScaleRowDown4_Any_MSA; if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_MSA : ScaleRowDown4_MSA; } }#endif if (filtering == kFilterLinear) { src_stride = 0; } for (y = 0; y < dst_height; ++y) { ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; }} static void ScalePlaneDown4_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown4)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width) = filtering ? ScaleRowDown4Box_16_C : ScaleRowDown4_16_C; int row_stride = src_stride << 2; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride * 2; // Point to row 2. src_stride = 0; }#if defined(HAS_SCALEROWDOWN4_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_NEON : ScaleRowDown4_16_NEON; }#endif#if defined(HAS_SCALEROWDOWN4_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_SSE2 : ScaleRowDown4_16_SSE2; }#endif if (filtering == kFilterLinear) { src_stride = 0; } for (y = 0; y < dst_height; ++y) { ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; }} // Scale plane down, 3/4static void ScalePlaneDown34(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown34_0)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width); void (*ScaleRowDown34_1)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width); const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; (void)src_width; (void)src_height; assert(dst_width % 3 == 0); if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_C; ScaleRowDown34_1 = ScaleRowDown34_C; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_C; ScaleRowDown34_1 = ScaleRowDown34_1_Box_C; }#if defined(HAS_SCALEROWDOWN34_NEON) if (TestCpuFlag(kCpuHasNEON)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_NEON; ScaleRowDown34_1 = ScaleRowDown34_Any_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_NEON; } if (dst_width % 24 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_NEON; ScaleRowDown34_1 = ScaleRowDown34_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON; } } }#endif#if defined(HAS_SCALEROWDOWN34_MSA) if (TestCpuFlag(kCpuHasMSA)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_MSA; ScaleRowDown34_1 = ScaleRowDown34_Any_MSA; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_MSA; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_MSA; } if (dst_width % 48 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_MSA; ScaleRowDown34_1 = ScaleRowDown34_MSA; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_MSA; ScaleRowDown34_1 = ScaleRowDown34_1_Box_MSA; } } }#endif#if defined(HAS_SCALEROWDOWN34_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3; } if (dst_width % 24 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3; } } }#endif for (y = 0; y < dst_height - 2; y += 3) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width); src_ptr += src_stride * 2; dst_ptr += dst_stride; } // Remainder 1 or 2 rows with last row vertically unfiltered if ((dst_height % 3) == 2) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width); } else if ((dst_height % 3) == 1) { ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width); }} static void ScalePlaneDown34_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown34_0)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width); void (*ScaleRowDown34_1)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width); const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; (void)src_width; (void)src_height; assert(dst_width % 3 == 0); if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_C; ScaleRowDown34_1 = ScaleRowDown34_16_C; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_C; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_C; }#if defined(HAS_SCALEROWDOWN34_16_NEON) if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_NEON; ScaleRowDown34_1 = ScaleRowDown34_16_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_NEON; } }#endif#if defined(HAS_SCALEROWDOWN34_16_SSSE3) if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_SSSE3; } }#endif for (y = 0; y < dst_height - 2; y += 3) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width); src_ptr += src_stride * 2; dst_ptr += dst_stride; } // Remainder 1 or 2 rows with last row vertically unfiltered if ((dst_height % 3) == 2) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width); } else if ((dst_height % 3) == 1) { ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width); }} // Scale plane, 3/8// This is an optimized version for scaling down a plane to 3/8// of its original size.//// Uses box filter arranges like this// aaabbbcc -> abc// aaabbbcc def// aaabbbcc ghi// dddeeeff// dddeeeff// dddeeeff// ggghhhii// ggghhhii// Boxes are 3x3, 2x3, 3x2 and 2x2 static void ScalePlaneDown38(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr,Lines 1–500 of 1741. Load more
/* * Copyright 2011 The LibYuv Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/scale.h" #include <assert.h> #include <string.h> #include "libyuv/cpu_id.h" #include "libyuv/planar_functions.h" // For CopyPlane #include "libyuv/row.h" #include "libyuv/scale_row.h" #ifdef __cplusplus namespace libyuv { extern "C" { #endif static __inline int Abs(int v) { return v >= 0 ? v : -v; } #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) // Scale plane, 1/2 // This is an optimized version for scaling down a plane to 1/2 of // its original size. static void ScalePlaneDown2(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown2)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width) = filtering == kFilterNone ? ScaleRowDown2_C : (filtering == kFilterLinear ? ScaleRowDown2Linear_C : ScaleRowDown2Box_C); int row_stride = src_stride << 1; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride; // Point to odd rows. src_stride = 0; } #if defined(HAS_SCALEROWDOWN2_NEON) if (TestCpuFlag(kCpuHasNEON)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_NEON : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_NEON : ScaleRowDown2Box_Any_NEON); if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_NEON : (filtering == kFilterLinear ? ScaleRowDown2Linear_NEON : ScaleRowDown2Box_NEON); } } #endif #if defined(HAS_SCALEROWDOWN2_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_SSSE3 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3 : ScaleRowDown2Box_Any_SSSE3); if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_SSSE3 : (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3 : ScaleRowDown2Box_SSSE3); } } #endif #if defined(HAS_SCALEROWDOWN2_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_AVX2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2 : ScaleRowDown2Box_Any_AVX2); if (IS_ALIGNED(dst_width, 32)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_AVX2 : ScaleRowDown2Box_AVX2); } } #endif #if defined(HAS_SCALEROWDOWN2_MSA) if (TestCpuFlag(kCpuHasMSA)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_MSA : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_MSA : ScaleRowDown2Box_Any_MSA); if (IS_ALIGNED(dst_width, 32)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_MSA : (filtering == kFilterLinear ? ScaleRowDown2Linear_MSA : ScaleRowDown2Box_MSA); } } #endif if (filtering == kFilterLinear) { src_stride = 0; } // TODO(fbarchard): Loop through source height to allow odd height. for (y = 0; y < dst_height; ++y) { ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; } } static void ScalePlaneDown2_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width) = filtering == kFilterNone ? ScaleRowDown2_16_C : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_C : ScaleRowDown2Box_16_C); int row_stride = src_stride << 1; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride; // Point to odd rows. src_stride = 0; } #if defined(HAS_SCALEROWDOWN2_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering ? ScaleRowDown2Box_16_NEON : ScaleRowDown2_16_NEON; } #endif #if defined(HAS_SCALEROWDOWN2_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) { ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_SSE2 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2 : ScaleRowDown2Box_16_SSE2); } #endif if (filtering == kFilterLinear) { src_stride = 0; } // TODO(fbarchard): Loop through source height to allow odd height. for (y = 0; y < dst_height; ++y) { ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; } } // Scale plane, 1/4 // This is an optimized version for scaling down a plane to 1/4 of // its original size. static void ScalePlaneDown4(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown4)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width) = filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C; int row_stride = src_stride << 2; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride * 2; // Point to row 2. src_stride = 0; } #if defined(HAS_SCALEROWDOWN4_NEON) if (TestCpuFlag(kCpuHasNEON)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_NEON : ScaleRowDown4_Any_NEON; if (IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON; } } #endif #if defined(HAS_SCALEROWDOWN4_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3; if (IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3; } } #endif #if defined(HAS_SCALEROWDOWN4_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2; if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2; } } #endif #if defined(HAS_SCALEROWDOWN4_MSA) if (TestCpuFlag(kCpuHasMSA)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_Any_MSA : ScaleRowDown4_Any_MSA; if (IS_ALIGNED(dst_width, 16)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_MSA : ScaleRowDown4_MSA; } } #endif if (filtering == kFilterLinear) { src_stride = 0; } for (y = 0; y < dst_height; ++y) { ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; } } static void ScalePlaneDown4_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown4)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width) = filtering ? ScaleRowDown4Box_16_C : ScaleRowDown4_16_C; int row_stride = src_stride << 2; (void)src_width; (void)src_height; if (!filtering) { src_ptr += src_stride * 2; // Point to row 2. src_stride = 0; } #if defined(HAS_SCALEROWDOWN4_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_NEON : ScaleRowDown4_16_NEON; } #endif #if defined(HAS_SCALEROWDOWN4_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_SSE2 : ScaleRowDown4_16_SSE2; } #endif if (filtering == kFilterLinear) { src_stride = 0; } for (y = 0; y < dst_height; ++y) { ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width); src_ptr += row_stride; dst_ptr += dst_stride; } } // Scale plane down, 3/4 static void ScalePlaneDown34(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown34_0)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width); void (*ScaleRowDown34_1)(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width); const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; (void)src_width; (void)src_height; assert(dst_width % 3 == 0); if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_C; ScaleRowDown34_1 = ScaleRowDown34_C; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_C; ScaleRowDown34_1 = ScaleRowDown34_1_Box_C; } #if defined(HAS_SCALEROWDOWN34_NEON) if (TestCpuFlag(kCpuHasNEON)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_NEON; ScaleRowDown34_1 = ScaleRowDown34_Any_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_NEON; } if (dst_width % 24 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_NEON; ScaleRowDown34_1 = ScaleRowDown34_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON; } } } #endif #if defined(HAS_SCALEROWDOWN34_MSA) if (TestCpuFlag(kCpuHasMSA)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_MSA; ScaleRowDown34_1 = ScaleRowDown34_Any_MSA; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_MSA; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_MSA; } if (dst_width % 48 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_MSA; ScaleRowDown34_1 = ScaleRowDown34_MSA; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_MSA; ScaleRowDown34_1 = ScaleRowDown34_1_Box_MSA; } } } #endif #if defined(HAS_SCALEROWDOWN34_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3; } if (dst_width % 24 == 0) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3; } } } #endif for (y = 0; y < dst_height - 2; y += 3) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width); src_ptr += src_stride * 2; dst_ptr += dst_stride; } // Remainder 1 or 2 rows with last row vertically unfiltered if ((dst_height % 3) == 2) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width); } else if ((dst_height % 3) == 1) { ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width); } } static void ScalePlaneDown34_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { int y; void (*ScaleRowDown34_0)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width); void (*ScaleRowDown34_1)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr, int dst_width); const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; (void)src_width; (void)src_height; assert(dst_width % 3 == 0); if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_C; ScaleRowDown34_1 = ScaleRowDown34_16_C; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_C; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_C; } #if defined(HAS_SCALEROWDOWN34_16_NEON) if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_NEON; ScaleRowDown34_1 = ScaleRowDown34_16_NEON; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_NEON; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_NEON; } } #endif #if defined(HAS_SCALEROWDOWN34_16_SSSE3) if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3; } else { ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_SSSE3; } } #endif for (y = 0; y < dst_height - 2; y += 3) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width); src_ptr += src_stride * 2; dst_ptr += dst_stride; } // Remainder 1 or 2 rows with last row vertically unfiltered if ((dst_height % 3) == 2) { ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); src_ptr += src_stride; dst_ptr += dst_stride; ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width); } else if ((dst_height % 3) == 1) { ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width); } } // Scale plane, 3/8 // This is an optimized version for scaling down a plane to 3/8 // of its original size. // // Uses box filter arranges like this // aaabbbcc -> abc // aaabbbcc def // aaabbbcc ghi // dddeeeff // dddeeeff // dddeeeff // ggghhhii // ggghhhii // Boxes are 3x3, 2x3, 3x2 and 2x2 static void ScalePlaneDown38(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8_t* src_ptr,