1741 lines · 57.0 KB · C++
RawDownload
/* *  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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t