[libyuv] Fix color matrix, blend, NV layout and null pointer bugs

Correctness fixes:

- U010ToAB30 and U210ToAB30 swap U and V but passed
  kYuv2020Constants; use kYvu2020Constants as I010ToAB30 does.
- H420ToAR30 passed kYvuH709Constants without swapping U and V,
  so red and blue were swapped; use kYuvH709Constants.
- I420Blend with negative height flipped Y but not U and V.
- BlendPlaneRow_WASMSIMD processes 16 pixels per loop but was
  dispatched for widths that are a multiple of 8.
- I420Blend used ScaleRowDown2Box_RVV for odd widths, reading 1
  byte past the row. Add ScaleRowDown2Box_Odd_RVV.
- ConvertFromI420 to NV12/NV21/NV16 with odd width used a UV
  stride of width, overlapping UV rows and writing 1 byte past
  the plane. Use ((width + 1) / 2) * 2.
- ConvertToI420 (NV16/NV24) and ConvertToARGB (NV12/NV21/NV16/
  NV24) computed the Y plane size with the aligned width; the Y
  stride is src_width. NV24 UV stride is src_width * 2.
- I420Rect and I420Interpolate skipped a UV row for negative odd
  heights.
- DetilePlane and DetilePlane_16 accepted tile_height 0, reading
  past the source.
- Add null checks to NV12ToNV21, IxxxToPxxx, I422ToI210,
  I422ToNV21, YUY2ToI420, UYVYToI420, AYUVToNV12, AYUVToNV21,
  DetileSplitUVPlane and DetileToYUY2, and avoid pointer
  arithmetic on optional NULL src_y/dst_y with negative height.
  MT2TToP010 now returns -1 for NULL src_y with non-NULL dst_y.
- Replace unaligned uint32_t stores in row_common.cc with memcpy.
- Add LIBYUV_TARGET_AVX512VNNI to HammingDistance_AVX512VNNI so
  GCC accepts the k1 clobber on non-AVX512 builds.
- Check kCpuHasWASMSIMD instead of kCpuHasWASM in scale.cc and
  scale_uv.cc.
- Avoid the 16.16 fixed point NEON/LSX/RVV column scalers for
  src_width >= 32768, matching the existing AVX2 guard.

Performance:

- NV24ToI420 uses InterpolateRow, ScaleUVRowDown2Linear and
  SplitUVRow instead of a scalar loop (bit exact).
- Add HalfMergeUVRow_Any_NEON and MirrorSplitUVRow_Any_{NEON,
  LSX,LASX,WASMSIMD} so non-multiple-of-16 widths use SIMD.
- Enable BlendPlaneRow_SSSE3/AVX2 for row_win builds.
- Add missing LSX/LASX/RVV/SME dispatch for YUY2ToY,
  I422ToYUY2/UYVY, ARGBToY/UVMatrix, RAWToNVMatrix, AR64Shuffle,
  ARGBSobelize and Convert16To8Row in I010ToNV12, and coalesce
  rows in ARGBToI400Matrix.

Cleanup:

- UYVYToYRow_Any_AVX2 uses the same UVSHIFT/SBPP as YUY2.
- Add #ifdef HAS_* guards in compare_gcc.cc and row_gcc.cc.
- Remove unused clobbers and dead cnth/cmp/subs instructions in
  row_neon.cc, row_neon64.cc, row_sve.h, row_sve.cc and
  row_sme.cc, and order clobbers "memory", "cc" first.
- Re-enable the I420Blend_Any unit test.

Test: libyuv_unittest (x86-64 Release, rowwin, ASan, UBSan, MSan;
Arm64 SME, SVE2 and NEON on Samsung S26)
Bug: 579659306
Change-Id: Ic1afddbf961f7ef7deeba124a55907a31e09822d
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8702355
Reviewed-by: richard winterton <rrwinterton@gmail.com>
This commit is contained in:
Frank Barchard 2026-11-02 04:58:16 -08:00
parent 79ca9187e5
commit 38ca05f1eb
26 changed files with 677 additions and 193 deletions

View File

@ -137,6 +137,8 @@ extern "C" {
#define HAS_NV21TORGB24ROW_AVX2
#define HAS_SPLITUVROW_AVX2
#define HAS_UYVYTOARGBROW_AVX2
#define HAS_UYVYTOUV422ROW_AVX2
#define HAS_UYVYTOUVROW_AVX2
#define HAS_UYVYTOYROW_AVX2
#define HAS_YUY2TOARGBROW_AVX2
#define HAS_YUY2TOUV422ROW_AVX2
@ -340,8 +342,10 @@ extern "C" {
#define HAS_RAWTORGB24ROW_SSSE3
#define HAS_ARGBALPHABLENDROW_SSSE3
#define HAS_ARGBORROW_SSE2
#define HAS_BLENDPLANEROW_SSSE3
#define HAS_MIRRORSPLITUVROW_SSSE3
#if defined(VISUALC_HAS_AVX2)
#define HAS_BLENDPLANEROW_AVX2
#define HAS_RAWTORGB24ROW_AVX2
#define HAS_RAWTOARGBROW_AVX2
#define HAS_I422TORGB24ROW_AVX2
@ -3004,14 +3008,26 @@ void MirrorSplitUVRow_NEON(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_Any_NEON(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_LSX(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_Any_LSX(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_LASX(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_Any_LASX(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void MirrorSplitUVRow_C(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
@ -3337,6 +3353,12 @@ void HalfMergeUVRow_Any_AVX2(const uint8_t* src_u,
int src_stride_v,
uint8_t* dst_uv,
int width);
void HalfMergeUVRow_Any_NEON(const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_uv,
int width);
void SplitRGBRow_C(const uint8_t* src_rgb,
uint8_t* dst_r,
@ -8234,6 +8256,10 @@ void MirrorRow_Any_WASMSIMD(const uint8_t* src_ptr,
void MirrorUVRow_Any_WASMSIMD(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void MirrorSplitUVRow_Any_WASMSIMD(const uint8_t* src_uv,
uint8_t* dst_u,
uint8_t* dst_v,
int width);
void SwapUVRow_Any_WASMSIMD(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);

View File

@ -439,7 +439,6 @@ static inline void I444ToRGB24Row_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV444_SVE_2X I444TORGB_SVE_2X RGBTOARGB8_SVE_2X
"st3b {z16.b, z17.b, z18.b}, p1, [%[dst_rgb24]] \n"
@ -453,7 +452,7 @@ static inline void I444ToRGB24Row_SVE_SC(
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y,
@ -503,7 +502,7 @@ static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y,
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y,
@ -536,7 +535,6 @@ static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y,
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_2X
"st4b {z16.b, z17.b, z18.b, z19.b}, p1, [%[dst_argb]] \n"
@ -550,7 +548,7 @@ static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y,
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I422ToRGB24Row_SVE_SC(
@ -583,7 +581,6 @@ static inline void I422ToRGB24Row_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_2X
"st3b {z16.b, z17.b, z18.b}, p1, [%[dst_argb]] \n"
@ -597,7 +594,7 @@ static inline void I422ToRGB24Row_SVE_SC(
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
#define RGB8TORGB565_SVE_FROM_TOP_2X \
@ -638,7 +635,6 @@ static inline void I422ToRGB565Row_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X
RGBTOARGB8_SVE_TOP_2X RGB8TORGB565_SVE_FROM_TOP_2X
@ -657,7 +653,7 @@ static inline void I422ToRGB565Row_SVE_SC(
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
#define RGB8TOARGB1555_SVE_FROM_TOP_2X \
@ -701,7 +697,6 @@ static inline void I422ToARGB1555Row_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X
RGBTOARGB8_SVE_TOP_2X RGB8TOARGB1555_SVE_FROM_TOP_2X
@ -720,7 +715,7 @@ static inline void I422ToARGB1555Row_SVE_SC(
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
#define RGB8TOARGB4444_SVE_FROM_TOP_2X \
@ -764,7 +759,6 @@ static inline void I422ToARGB4444Row_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X
RGBTOARGB8_SVE_TOP_2X RGB8TOARGB4444_SVE_FROM_TOP_2X
@ -783,7 +777,7 @@ static inline void I422ToARGB4444Row_SVE_SC(
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y,
@ -829,7 +823,7 @@ static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y,
[vl] "=&r"(vl) // %[vl]
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y,
@ -879,7 +873,7 @@ static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y,
: [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff]
[kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias), // %[kRGBCoeffBias]
[limit] "r"(limit) // %[limit]
: "cc", "memory", YUVTORGB_SVE_REGS);
: "memory", "cc", YUVTORGB_SVE_REGS);
}
static inline void I422AlphaToARGBRow_SVE_SC(
@ -916,7 +910,6 @@ static inline void I422AlphaToARGBRow_SVE_SC(
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"cnth %[vl] \n"
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X
"ld1b {z19.b}, p1/z, [%[src_a]] \n" // Alpha
@ -1618,7 +1611,6 @@ static inline void I410AlphaToARGBRow_SVE_SC(
asm volatile(
"ptrue p0.b \n" //
YUVTORGB_SVE_SETUP
"cmp %w[width], %w[vl] \n"
"subs %w[width], %w[width], %w[vl] \n"
"b.lt 2f \n"

View File

@ -1789,6 +1789,10 @@ void ScaleRowDown2Box_RVV(const uint8_t* src_ptr,
ptrdiff_t src_stride,
uint8_t* dst,
int dst_width);
void ScaleRowDown2Box_Odd_RVV(const uint8_t* src_ptr,
ptrdiff_t src_stride,
uint8_t* dst,
int dst_width);
void ScaleRowDown4_RVV(const uint8_t* src_ptr,
ptrdiff_t src_stride,

View File

@ -76,14 +76,15 @@ uint32_t HammingDistance_SSE42(const uint8_t* src_a,
"+r"(count), // %2
"=&r"(diff) // %3
:
: "cc", "memory", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10");
: "memory", "cc", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10");
return (uint32_t)(diff);
}
#endif // HAS_HAMMINGDISTANCE_SSE42
#if defined(HAS_HAMMINGDISTANCE_SSSE3) || defined(HAS_HAMMINGDISTANCE_AVX2) || \
defined(HAS_HAMMINGDISTANCE_AVX512BW)
defined(HAS_HAMMINGDISTANCE_AVX512BW) || \
defined(HAS_HAMMINGDISTANCE_AVX512VNNI)
static const vec8 kNibbleMask = {15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15};
static const vec8 kBitCount = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
@ -144,7 +145,7 @@ uint32_t HammingDistance_SSSE3(const uint8_t* src_a,
"=r"(diff) // %3
: "m"(kNibbleMask), // %4
"m"(kBitCount) // %5
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
"xmm7");
return diff;
@ -201,12 +202,13 @@ uint32_t HammingDistance_AVX2(const uint8_t* src_a,
"=r"(diff) // %3
: "m"(kNibbleMask), // %4
"m"(kBitCount) // %5
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
return diff;
}
#endif // HAS_HAMMINGDISTANCE_AVX2
#ifdef HAS_SUMSQUAREERROR_SSE2
uint32_t SumSquareError_SSE2(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
@ -245,9 +247,10 @@ uint32_t SumSquareError_SSE2(const uint8_t* src_a,
"+r"(count), // %2
"=r"(sse) // %3
:
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
return sse;
}
#endif // HAS_SUMSQUAREERROR_SSE2
#ifdef HAS_SUMSQUAREERROR_AVX2
uint32_t SumSquareError_AVX2(const uint8_t* src_a,
@ -290,11 +293,12 @@ uint32_t SumSquareError_AVX2(const uint8_t* src_a,
"+r"(count), // %2
"=r"(sse) // %3
:
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
return sse;
}
#endif // HAS_SUMSQUAREERROR_AVX2
#ifdef HAS_HASHDJB2_SSE41
static const uvec32 kHash16x33 = {0x92d9e201, 0, 0, 0}; // 33 ^ 16
static const uvec32 kHashMul0 = {
0x0c3525e1, // 33 ^ 15
@ -371,10 +375,11 @@ uint32_t HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed) {
"m"(kHashMul1), // %6
"m"(kHashMul2), // %7
"m"(kHashMul3) // %8
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
"xmm7");
return hash;
}
#endif // HAS_HASHDJB2_SSE41
#if defined(HAS_HAMMINGDISTANCE_AVX512BW) || \
defined(HAS_HAMMINGDISTANCE_AVX512VNNI) || \
defined(HAS_SUMSQUAREERROR_AVX512BW) || \
@ -458,6 +463,7 @@ uint32_t HammingDistance_AVX512BW(const uint8_t* src_a,
#ifdef HAS_HAMMINGDISTANCE_AVX512VNNI
// Process 64 bytes per loop and the remainder of 1 to 63 bytes with masked
// loads that read zeros, accumulating byte popcounts with vpdpbusd.
LIBYUV_TARGET_AVX512VNNI
uint32_t HammingDistance_AVX512VNNI(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
@ -766,7 +772,7 @@ uint32_t HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed) {
:
[src] "+r"(src), [count] "+r"(count), [seed] "+r"(seed), [sum] "=&r"(sum)
: [tbl] "r"(kHashMulLoHi)
: "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
return seed;
}
#undef HASH32_AVX2
@ -854,7 +860,7 @@ uint32_t HashDjb2_AVX512BW(const uint8_t* src, int count, uint32_t seed) {
:
[src] "+r"(src), [width] "+r"(width), [seed] "+r"(seed), [sum] "=&r"(sum)
: [tbl] "r"(kHashMulLoHi), [pow_n] "m"(pow_n), [mask] "m"(mask)
: "cc", "memory", "k1", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
: "memory", "cc", "k1", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
"xmm6", "xmm7");
return seed;
}

View File

@ -105,10 +105,12 @@ int I420Copy(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -148,10 +150,12 @@ int I010Copy(const uint16_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -193,10 +197,12 @@ static int Planar16bitTo8bit(const uint16_t* src_y,
if (height < 0) {
height = -height;
uv_height = -uv_height;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(uv_height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(uv_height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -852,14 +858,17 @@ static int IxxxToPxxx(const uint16_t* src_y,
int subsample_x,
int subsample_y,
int depth) {
if (width <= 0 || height == 0 || height == INT_MIN) {
if ((!src_y && dst_y) || !src_u || !src_v || !dst_uv || width <= 0 ||
height == 0 || height == INT_MIN) {
return -1;
}
const int uv_width = SUBSAMPLE(width, subsample_x, subsample_x);
const int uv_height = SUBSAMPLE(height, subsample_y, subsample_y);
ConvertToMSBPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height,
depth);
if (dst_y) {
ConvertToMSBPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
height, depth);
}
MergeUVPlane_16(src_u, src_stride_u, src_v, src_stride_v, dst_uv,
dst_stride_uv, uv_width, uv_height, depth);
return 0;
@ -912,10 +921,12 @@ int I010ToNV12(const uint16_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -927,6 +938,11 @@ int I010ToNV12(const uint16_t* src_y,
}
}
#endif
#if defined(HAS_CONVERT16TO8ROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
Convert16To8Row = Convert16To8Row_SVE2;
}
#endif
#if defined(HAS_CONVERT16TO8ROW_SME)
if (TestCpuFlag(kCpuHasSME)) {
Convert16To8Row = Convert16To8Row_SME;
@ -953,6 +969,11 @@ int I010ToNV12(const uint16_t* src_y,
Convert16To8Row = Convert16To8Row_AVX512BW;
}
#endif
#if defined(HAS_CONVERT16TO8ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
Convert16To8Row = Convert16To8Row_RVV;
}
#endif
#if defined(HAS_CONVERT16TO8ROW_HVX)
if (TestCpuFlag(kCpuHasHVX)) {
Convert16To8Row = Convert16To8Row_HVX;
@ -1195,17 +1216,21 @@ int I422ToI210(const uint8_t* src_y,
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
// Convert Y plane.
Convert8To16Plane(src_y, src_stride_y, dst_y, dst_stride_y, 1024, width,
height);
if (dst_y) {
Convert8To16Plane(src_y, src_stride_y, dst_y, dst_stride_y, 1024, width,
height);
}
// Convert UV planes.
Convert8To16Plane(src_u, src_stride_u, dst_u, dst_stride_u, 1024, halfwidth,
height);
@ -1229,7 +1254,8 @@ int I422ToNV21(const uint8_t* src_y,
int width,
int height) {
int r;
if (width <= 0 || height == 0 || height == INT_MIN) {
if ((!src_y && dst_y) || !src_u || !src_v || !dst_vu || width <= 0 ||
height == 0 || height == INT_MIN) {
return -1;
}
int halfwidth = (width + 1) >> 1;
@ -1238,10 +1264,12 @@ int I422ToNV21(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -1355,7 +1383,8 @@ int MT2TToP010(const uint8_t* src_y,
int dst_stride_uv,
int width,
int height) {
if (width <= 0 || height == 0 || height == INT_MIN || !src_uv || !dst_uv) {
if ((!src_y && dst_y) || !src_uv || !dst_uv || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
@ -1674,10 +1703,12 @@ int I444ToNV12(const uint8_t* src_y,
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -1729,8 +1760,10 @@ int I400ToI420(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
}
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
@ -1760,8 +1793,10 @@ int I400ToNV21(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
}
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
@ -1795,9 +1830,11 @@ int NV12ToI420(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_uv = src_uv + (ptrdiff_t)(halfheight - 1) * src_stride_uv;
src_stride_y = -src_stride_y;
src_stride_uv = -src_stride_uv;
}
// Coalesce rows.
@ -2473,7 +2510,8 @@ int YUY2ToI420(const uint8_t* src_yuy2,
YUY2ToUVRow_C;
void (*YUY2ToYRow)(const uint8_t* src_yuy2, uint8_t* dst_y, int width) =
YUY2ToYRow_C;
if (width <= 0 || height == 0 || height == INT_MIN) {
if (!src_yuy2 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
// Negative height means invert the image.
@ -2585,7 +2623,8 @@ int UYVYToI420(const uint8_t* src_uyvy,
UYVYToUVRow_C;
void (*UYVYToYRow)(const uint8_t* src_uyvy, uint8_t* dst_y, int width) =
UYVYToYRow_C;
if (width <= 0 || height == 0 || height == INT_MIN) {
if (!src_uyvy || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
// Negative height means invert the image.
@ -2694,7 +2733,8 @@ int AYUVToNV12(const uint8_t* src_ayuv,
uint8_t* dst_uv, int width) = AYUVToUVRow_C;
void (*AYUVToYRow)(const uint8_t* src_ayuv, uint8_t* dst_y, int width) =
AYUVToYRow_C;
if (width <= 0 || height == 0 || height == INT_MIN) {
if (!src_ayuv || !dst_y || !dst_uv || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
// Negative height means invert the image.
@ -2770,7 +2810,8 @@ int AYUVToNV21(const uint8_t* src_ayuv,
uint8_t* dst_vu, int width) = AYUVToVURow_C;
void (*AYUVToYRow)(const uint8_t* src_ayuv, uint8_t* dst_y, int width) =
AYUVToYRow_C;
if (width <= 0 || height == 0 || height == INT_MIN) {
if (!src_ayuv || !dst_y || !dst_vu || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
// Negative height means invert the image.
@ -4192,6 +4233,16 @@ int RAWToI420(const uint8_t* src_raw,
}
}
#endif
#if defined(HAS_RGBTOUVMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBToUVMatrixRow = RGBToUVMatrixRow_RVV;
}
#endif
#if defined(HAS_RGBTOYMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBToYMatrixRow = RGBToYMatrixRow_RVV;
}
#endif
if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN) {
@ -4340,6 +4391,16 @@ int RAWToJ420(const uint8_t* src_raw,
}
}
#endif
#if defined(HAS_RGBTOUVMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBToUVMatrixRow = RGBToUVMatrixRow_RVV;
}
#endif
#if defined(HAS_RGBTOYMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBToYMatrixRow = RGBToYMatrixRow_RVV;
}
#endif
if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN) {
@ -5103,9 +5164,11 @@ static int Biplanar16bitTo8bit(const uint16_t* src_y,
if (height < 0) {
height = -height;
uv_height = -uv_height;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_uv = src_uv + (ptrdiff_t)(uv_height - 1) * src_stride_uv;
src_stride_y = -src_stride_y;
src_stride_uv = -src_stride_uv;
}
@ -5169,10 +5232,12 @@ static int Planar8bitTo8bit(const uint8_t* src_y,
if (height < 0) {
height = -height;
uv_height = -uv_height;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(uv_height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(uv_height - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}

View File

@ -1141,7 +1141,7 @@ int U010ToAB30(const uint16_t* src_y,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYuv2020Constants, width, height);
&kYvu2020Constants, width, height);
}
// Convert 12 bit YUV to ARGB with matrix.
@ -1405,7 +1405,7 @@ int U210ToAB30(const uint16_t* src_y,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYuv2020Constants, width, height);
&kYvu2020Constants, width, height);
}
LIBYUV_API
@ -7375,7 +7375,7 @@ int H420ToAR30(const uint8_t* src_y,
int height) {
return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYvuH709Constants, width, height);
&kYuvH709Constants, width, height);
}
// Convert I420 to AB30.

View File

@ -398,6 +398,22 @@ int I422ToYUY2(const uint8_t* src_y,
}
}
#endif
#if defined(HAS_I422TOYUY2ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToYUY2Row = I422ToYUY2Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToYUY2Row = I422ToYUY2Row_LSX;
}
}
#endif
#if defined(HAS_I422TOYUY2ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToYUY2Row = I422ToYUY2Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToYUY2Row = I422ToYUY2Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width);
@ -678,10 +694,12 @@ int I420ToNV12(const uint8_t* src_y,
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
if (src_y) {
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
}
@ -1110,25 +1128,26 @@ int ConvertFromI420(const uint8_t* y,
break;
case FOURCC_NV12: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_uv_stride =
dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
r = I420ToNV12(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride ? dst_sample_stride : width, dst_uv,
dst_sample_stride ? dst_sample_stride : width, width,
height);
dst_y_stride, dst_uv, dst_uv_stride, width, height);
break;
}
case FOURCC_NV21: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_vu_stride =
dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2;
uint8_t* dst_vu = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
r = I420ToNV21(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride ? dst_sample_stride : width, dst_vu,
dst_sample_stride ? dst_sample_stride : width, width,
height);
dst_y_stride, dst_vu, dst_vu_stride, width, height);
break;
}
case FOURCC_NV16: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_uv_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_uv_stride =
dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
int halfwidth = (width + 1) / 2;
int halfheight = SUBSAMPLE(height, 1, 1);

View File

@ -1714,6 +1714,13 @@ int ARGBToI400Matrix(const uint8_t* src_argb,
src_argb = src_argb + (ptrdiff_t)(height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
// Coalesce rows.
if (src_stride_argb == width * 4 && dst_stride_y == width &&
(ptrdiff_t)width * height <= INT_MAX) {
width *= height;
height = 1;
src_stride_argb = dst_stride_y = 0;
}
#if defined(HAS_ARGBTOYMATRIXROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_SSSE3;
@ -1771,6 +1778,27 @@ int ARGBToI400Matrix(const uint8_t* src_argb,
ARGBToYMatrixRow = ARGBToYMatrixRow_SME;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LSX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LASX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_RVV;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD;
@ -1877,6 +1905,27 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb,
ARGBToYMatrixRow = ARGBToYMatrixRow_SME;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LSX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LASX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_RVV;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD;
@ -1951,6 +2000,11 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb,
}
}
#endif
#if defined(HAS_ARGBTOUVMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToUVMatrixRow = ARGBToUVMatrixRow_RVV;
}
#endif
#if defined(HAS_ARGBTOUVMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_WASMSIMD;
@ -1988,6 +2042,22 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb,
}
}
#endif
#if defined(HAS_I422TOYUY2ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToYUY2Row = I422ToYUY2Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToYUY2Row = I422ToYUY2Row_LSX;
}
}
#endif
#if defined(HAS_I422TOYUY2ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToYUY2Row = I422ToYUY2Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToYUY2Row = I422ToYUY2Row_LASX;
}
}
#endif
{
align_buffer_64(row_y, ((width + 63) & ~63) * 2);
@ -2094,6 +2164,27 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb,
ARGBToYMatrixRow = ARGBToYMatrixRow_SME;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LSX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_LASX;
}
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_RVV;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD;
@ -2168,6 +2259,11 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb,
}
}
#endif
#if defined(HAS_ARGBTOUVMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToUVMatrixRow = ARGBToUVMatrixRow_RVV;
}
#endif
#if defined(HAS_ARGBTOUVMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_WASMSIMD;
@ -2205,6 +2301,22 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb,
}
}
#endif
#if defined(HAS_I422TOUYVYROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToUYVYRow = I422ToUYVYRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToUYVYRow = I422ToUYVYRow_LSX;
}
}
#endif
#if defined(HAS_I422TOUYVYROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToUYVYRow = I422ToUYVYRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToUYVYRow = I422ToUYVYRow_LASX;
}
}
#endif
{
align_buffer_64(row_y, ((width + 63) & ~63) * 2);
@ -4678,6 +4790,11 @@ static int RAWToNVMatrix(const uint8_t* src_raw,
}
}
#endif
#if defined(HAS_RGBTOUVMATRIXROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBToUVMatrixRow = RGBToUVMatrixRow_RVV;
}
#endif
#if defined(HAS_RGBTOUVMATRIXROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
RGBToUVMatrixRow = RGBToUVMatrixRow_Any_WASMSIMD;

View File

@ -461,35 +461,31 @@ int ConvertToARGB(const uint8_t* sample,
// Biplanar formats
case FOURCC_NV12:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample +
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) +
(crop_x & ~1);
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)(crop_y / 2) * aligned_src_width) + (crop_x & ~1);
r = NV12ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
break;
case FOURCC_NV21:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample +
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) +
(crop_x & ~1);
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)(crop_y / 2) * aligned_src_width) + (crop_x & ~1);
// Call NV12 but with u and v parameters swapped.
r = NV21ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
break;
case FOURCC_NV16:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample +
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y) +
(crop_x & ~1);
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)crop_y * aligned_src_width) + (crop_x & ~1);
r = NV16ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
break;
case FOURCC_NV24:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample + (ptrdiff_t)aligned_src_width * abs_src_height +
(ptrdiff_t)aligned_src_width * 2 * crop_y +
(ptrdiff_t)crop_x * 2;
r = NV24ToARGB(src, src_width, src_uv, aligned_src_width * 2, dst_argb,
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)crop_y * src_width * 2) + ((ptrdiff_t)crop_x * 2);
r = NV24ToARGB(src, src_width, src_uv, src_width * 2, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
break;
case FOURCC_P010: {

View File

@ -19,6 +19,7 @@
#include "libyuv/cpu_id.h"
#include "libyuv/planar_functions.h"
#include "libyuv/row.h"
#include "libyuv/scale_row.h"
#include "libyuv/video_common.h"
#ifdef __cplusplus
@ -213,11 +214,17 @@ static int NV24ToI420(const uint8_t* src_y,
int dst_stride_v,
int width,
int height) {
int x, y;
int y;
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
void (*HalfRow)(const uint8_t* src_uv, ptrdiff_t src_uv_stride,
uint8_t* dst_uv, int width) = HalfRow_C;
void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_C;
void (*ScaleUVRowDown2Linear)(const uint8_t* src_uv, ptrdiff_t src_stride,
uint8_t* dst_uv, int dst_width) =
ScaleUVRowDown2Linear_C;
void (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v,
int width) = SplitUVRow_C;
if ((!src_y && dst_y) || !src_uv || !dst_u || !dst_v || width <= 0 ||
height == 0 || height == INT_MIN) {
return -1;
@ -235,40 +242,180 @@ static int NV24ToI420(const uint8_t* src_y,
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
#if defined(HAS_HALFROW_AVX2)
#if defined(HAS_INTERPOLATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
HalfRow = HalfRow_Any_AVX2;
InterpolateRow = InterpolateRow_Any_AVX2;
if (IS_ALIGNED(width * 2, 32)) {
HalfRow = HalfRow_AVX2;
InterpolateRow = InterpolateRow_AVX2;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) {
InterpolateRow = InterpolateRow_AVX512BW;
}
#endif
#if defined(HAS_INTERPOLATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
InterpolateRow = InterpolateRow_Any_NEON;
if (IS_ALIGNED(width * 2, 16)) {
InterpolateRow = InterpolateRow_NEON;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
InterpolateRow = InterpolateRow_SVE2;
}
#endif
#if defined(HAS_INTERPOLATEROW_SME)
if (TestCpuFlag(kCpuHasSME)) {
InterpolateRow = InterpolateRow_SME;
}
#endif
#if defined(HAS_INTERPOLATEROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
InterpolateRow = InterpolateRow_Any_LSX;
if (IS_ALIGNED(width * 2, 16)) {
InterpolateRow = InterpolateRow_LSX;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
InterpolateRow = InterpolateRow_Any_LASX;
if (IS_ALIGNED(width * 2, 32)) {
InterpolateRow = InterpolateRow_LASX;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
InterpolateRow = InterpolateRow_RVV;
}
#endif
#if defined(HAS_INTERPOLATEROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
InterpolateRow = InterpolateRow_Any_WASMSIMD;
if (IS_ALIGNED(width * 2, 16)) {
InterpolateRow = InterpolateRow_WASMSIMD;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_HVX)
if (TestCpuFlag(kCpuHasHVX)) {
InterpolateRow = InterpolateRow_HVX;
}
#endif
#if defined(HAS_SCALEUVROWDOWN2_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_Any_AVX2;
if (IS_ALIGNED(halfwidth, 8)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_AVX2;
}
}
#endif
#if defined(HAS_SCALEUVROWDOWN2_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_Any_NEON;
if (IS_ALIGNED(halfwidth, 8)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_NEON;
}
}
#endif
#if defined(HAS_SCALEUVROWDOWN2_SME)
if (TestCpuFlag(kCpuHasSME)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_SME;
}
#endif
#if defined(HAS_SCALEUVROWDOWN2_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_RVV;
}
#endif
#if defined(HAS_SCALEUVROWDOWN2_HVX)
if (TestCpuFlag(kCpuHasHVX)) {
ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_HVX;
}
#endif
#if defined(HAS_SPLITUVROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
SplitUVRow = SplitUVRow_Any_SSE2;
if (IS_ALIGNED(halfwidth, 16)) {
SplitUVRow = SplitUVRow_SSE2;
}
}
#endif
#if defined(HAS_SPLITUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
SplitUVRow = SplitUVRow_Any_AVX2;
if (IS_ALIGNED(halfwidth, 32)) {
SplitUVRow = SplitUVRow_AVX2;
}
}
#endif
#if defined(HAS_SPLITUVROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) {
SplitUVRow = SplitUVRow_AVX512BW;
}
#endif
#if defined(HAS_SPLITUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
SplitUVRow = SplitUVRow_Any_NEON;
if (IS_ALIGNED(halfwidth, 16)) {
SplitUVRow = SplitUVRow_NEON;
}
}
#endif
#if defined(HAS_SPLITUVROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
SplitUVRow = SplitUVRow_SVE2;
}
#endif
#if defined(HAS_SPLITUVROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
SplitUVRow = SplitUVRow_Any_LSX;
if (IS_ALIGNED(halfwidth, 16)) {
SplitUVRow = SplitUVRow_LSX;
}
}
#endif
#if defined(HAS_SPLITUVROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
SplitUVRow = SplitUVRow_Any_LASX;
if (IS_ALIGNED(halfwidth, 32)) {
SplitUVRow = SplitUVRow_LASX;
}
}
#endif
#if defined(HAS_SPLITUVROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
SplitUVRow = SplitUVRow_RVV;
}
#endif
#if defined(HAS_SPLITUVROW_HVX)
if (TestCpuFlag(kCpuHasHVX)) {
SplitUVRow = SplitUVRow_HVX;
}
#endif
align_buffer_64(row_uv, width * 2);
align_buffer_64(row_uv, halfwidth * 6);
if (!row_uv) {
return 1;
}
uint8_t* row_uv_down = row_uv + halfwidth * 4;
for (y = 0; y < halfheight; ++y) {
if (y * 2 + 1 < height) {
HalfRow(src_uv, src_stride_uv, row_uv, width * 2);
InterpolateRow(row_uv, src_uv, src_stride_uv, width * 2, 128);
} else {
memcpy(row_uv, src_uv, (size_t)width * 2);
}
for (x = 0; x < halfwidth - 1; ++x) {
dst_u[x] = (row_uv[x * 4 + 0] + row_uv[x * 4 + 2] + 1) >> 1;
dst_v[x] = (row_uv[x * 4 + 1] + row_uv[x * 4 + 3] + 1) >> 1;
}
if (width & 1) {
dst_u[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 0];
dst_v[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 1];
} else {
dst_u[halfwidth - 1] = (row_uv[(halfwidth - 1) * 4 + 0] +
row_uv[(halfwidth - 1) * 4 + 2] + 1) >>
1;
dst_v[halfwidth - 1] = (row_uv[(halfwidth - 1) * 4 + 1] +
row_uv[(halfwidth - 1) * 4 + 3] + 1) >>
1;
row_uv[width * 2 + 0] = row_uv[width * 2 - 2];
row_uv[width * 2 + 1] = row_uv[width * 2 - 1];
}
ScaleUVRowDown2Linear(row_uv, 0, row_uv_down, halfwidth);
SplitUVRow(row_uv_down, dst_u, dst_v, halfwidth);
src_uv += (ptrdiff_t)src_stride_uv * 2;
dst_u += dst_stride_u;
dst_v += dst_stride_v;
@ -471,7 +618,7 @@ int ConvertToI420(const uint8_t* sample,
break;
case FOURCC_NV16:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) +
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)crop_y * aligned_src_width) + ((crop_x / 2) * 2);
r = NV16ToI420(src, src_width, src_uv, aligned_src_width, dst_y,
dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
@ -479,11 +626,11 @@ int ConvertToI420(const uint8_t* sample,
break;
case FOURCC_NV24:
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) +
((ptrdiff_t)crop_y * aligned_src_width * 2) + (crop_x * 2);
r = NV24ToI420(src, src_width, src_uv, aligned_src_width * 2, dst_y,
dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
crop_width, inv_crop_height);
src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) +
((ptrdiff_t)crop_y * src_width * 2) + (crop_x * 2);
r = NV24ToI420(src, src_width, src_uv, src_width * 2, dst_y, dst_stride_y,
dst_u, dst_stride_u, dst_v, dst_stride_v, crop_width,
inv_crop_height);
break;
case FOURCC_P010: {
const uint16_t* src16 = (const uint16_t*)sample;

View File

@ -1289,7 +1289,8 @@ int NV12ToNV21(const uint8_t* src_y,
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
if (!src_uv || !dst_vu || width <= 0 || height == 0 || height == INT_MIN) {
if ((!src_y && dst_y) || !src_uv || !dst_vu || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
@ -1331,7 +1332,7 @@ int DetilePlane(const uint8_t* src_y,
void (*DetileRow)(const uint8_t* src, ptrdiff_t src_tile_stride, uint8_t* dst,
int width) = DetileRow_C;
if (!src_y || !dst_y || width <= 0 || height == 0 || height == INT_MIN ||
!IS_POWEROFTWO(tile_height)) {
tile_height <= 0 || !IS_POWEROFTWO(tile_height)) {
return -1;
}
@ -1388,7 +1389,7 @@ int DetilePlane_16(const uint16_t* src_y,
void (*DetileRow_16)(const uint16_t* src, ptrdiff_t src_tile_stride,
uint16_t* dst, int width) = DetileRow_16_C;
if (!src_y || !dst_y || width <= 0 || height == 0 || height == INT_MIN ||
!IS_POWEROFTWO(tile_height)) {
tile_height <= 0 || !IS_POWEROFTWO(tile_height)) {
return -1;
}
@ -1450,8 +1451,8 @@ void DetileSplitUVPlane(const uint8_t* src_uv,
// tile_height must be a power of 2 (16 or 32); the row loop below uses it as
// a bit mask.
if (width <= 0 || height == 0 || height == INT_MIN || tile_height <= 0 ||
!IS_POWEROFTWO(tile_height)) {
if (!src_uv || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN || tile_height <= 0 || !IS_POWEROFTWO(tile_height)) {
return;
}
// Negative height means invert the image.
@ -1517,8 +1518,8 @@ void DetileToYUY2(const uint8_t* src_y,
// tile_height must be a power of 2 and at least 2 (16 or 32); the row loop
// uses it as a bit mask and the UV tile is tile_height / 2 rows.
if (width <= 0 || height == 0 || height == INT_MIN || tile_height < 2 ||
!IS_POWEROFTWO(tile_height)) {
if (!src_y || !src_uv || !dst_yuy2 || width <= 0 || height == 0 ||
height == INT_MIN || tile_height < 2 || !IS_POWEROFTWO(tile_height)) {
return;
}
// Negative height means invert the image.
@ -2162,7 +2163,7 @@ void MergeXR30Plane(const uint16_t* src_r,
}
} else {
MergeXR30Row = MergeXR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
if (IS_ALIGNED(width, 4)) {
MergeXR30Row = MergeXR30Row_NEON;
}
}
@ -2765,6 +2766,22 @@ int YUY2ToY(const uint8_t* src_yuy2,
YUY2ToYRow = YUY2ToYRow_SVE2;
}
#endif
#if defined(HAS_YUY2TOYROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
YUY2ToYRow = YUY2ToYRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
YUY2ToYRow = YUY2ToYRow_LSX;
}
}
#endif
#if defined(HAS_YUY2TOYROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
YUY2ToYRow = YUY2ToYRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
YUY2ToYRow = YUY2ToYRow_LASX;
}
}
#endif
#if defined(HAS_YUY2TOYROW_HVX)
if (TestCpuFlag(kCpuHasHVX)) {
YUY2ToYRow = YUY2ToYRow_HVX;
@ -3693,7 +3710,7 @@ int BlendPlane(const uint8_t* src_y0,
#if defined(HAS_BLENDPLANEROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
BlendPlaneRow = BlendPlaneRow_Any_WASMSIMD;
if (IS_ALIGNED(width, 8)) {
if (IS_ALIGNED(width, 16)) {
BlendPlaneRow = BlendPlaneRow_WASMSIMD;
}
}
@ -3757,8 +3774,13 @@ int I420Blend(const uint8_t* src_y0,
// Negative height means invert the image.
if (height < 0) {
height = -height;
int halfheight = (height + 1) >> 1;
dst_y = dst_y + (ptrdiff_t)(height - 1) * dst_stride_y;
dst_stride_y = -dst_stride_y;
dst_u = dst_u + (ptrdiff_t)(halfheight - 1) * dst_stride_u;
dst_stride_u = -dst_stride_u;
dst_v = dst_v + (ptrdiff_t)(halfheight - 1) * dst_stride_v;
dst_stride_v = -dst_stride_v;
}
// Blend Y plane.
@ -3802,7 +3824,7 @@ int I420Blend(const uint8_t* src_y0,
#if defined(HAS_BLENDPLANEROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
BlendPlaneRow = BlendPlaneRow_Any_WASMSIMD;
if (IS_ALIGNED(halfwidth, 8)) {
if (IS_ALIGNED(halfwidth, 16)) {
BlendPlaneRow = BlendPlaneRow_WASMSIMD;
}
}
@ -3856,9 +3878,10 @@ int I420Blend(const uint8_t* src_y0,
}
}
#endif
#if defined(HAS_SCALEROWDOWN2_RVV)
#if defined(HAS_SCALEROWDOWN2BOX_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ScaleRowDown2 = ScaleRowDown2Box_RVV;
ScaleRowDown2 =
IS_ALIGNED(width, 2) ? ScaleRowDown2Box_RVV : ScaleRowDown2Box_Odd_RVV;
}
#endif
#if defined(HAS_SCALEROWDOWN2_WASMSIMD)
@ -4486,18 +4509,18 @@ int I420Rect(uint8_t* dst_y,
int value_y,
int value_u,
int value_v) {
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
uint8_t* start_y = dst_y + y * dst_stride_y + x;
uint8_t* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2);
uint8_t* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2);
if (!dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN || x < 0 || y < 0 || value_y < 0 || value_y > 255 ||
value_u < 0 || value_u > 255 || value_v < 0 || value_v > 255) {
return -1;
}
int halfwidth = (width + 1) >> 1;
int halfheight = (height < 0) ? -((-height + 1) >> 1) : ((height + 1) >> 1);
uint8_t* start_y = dst_y + (ptrdiff_t)y * dst_stride_y + x;
uint8_t* start_u = dst_u + (ptrdiff_t)(y / 2) * dst_stride_u + (x / 2);
uint8_t* start_v = dst_v + (ptrdiff_t)(y / 2) * dst_stride_v + (x / 2);
SetPlane(start_y, dst_stride_y, width, height, value_y);
SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u);
SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v);
@ -5629,15 +5652,15 @@ int I420Interpolate(const uint8_t* src0_y,
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 ||
height == INT_MIN) {
return -1;
}
int halfwidth = (width + 1) >> 1;
int halfheight = (height < 0) ? -((-height + 1) >> 1) : ((height + 1) >> 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,
@ -5802,6 +5825,22 @@ int AR64Shuffle(const uint16_t* src_ar64,
}
}
#endif
#if defined(HAS_ARGBSHUFFLEROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
AR64ShuffleRow = ARGBShuffleRow_Any_LSX;
if (IS_ALIGNED(width, 4)) {
AR64ShuffleRow = ARGBShuffleRow_LSX;
}
}
#endif
#if defined(HAS_ARGBSHUFFLEROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
AR64ShuffleRow = ARGBShuffleRow_Any_LASX;
if (IS_ALIGNED(width, 8)) {
AR64ShuffleRow = ARGBShuffleRow_LASX;
}
}
#endif
#if defined(HAS_ARGBSHUFFLEROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD)) {
AR64ShuffleRow = ARGBShuffleRow_Any_WASMSIMD;
@ -5994,6 +6033,11 @@ static int ARGBSobelize(const uint8_t* src_argb,
ARGBToYMatrixRow = ARGBToYMatrixRow_SVE2;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_SME)
if (TestCpuFlag(kCpuHasSME)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_SME;
}
#endif
#if defined(HAS_ARGBTOYMATRIXROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX;
@ -6769,7 +6813,7 @@ int YUY2ToNV12(const uint8_t* src_yuy2,
YUY2ToYRow = YUY2ToYRow_SVE2;
}
#endif
#if defined(HAS_YUY2TOYROW_LSX) && defined(HAS_YUY2TOUV422ROW_LSX)
#if defined(HAS_YUY2TOYROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
YUY2ToYRow = YUY2ToYRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
@ -6777,7 +6821,7 @@ int YUY2ToNV12(const uint8_t* src_yuy2,
}
}
#endif
#if defined(HAS_YUY2TOYROW_LASX) && defined(HAS_YUY2TOUV422ROW_LASX)
#if defined(HAS_YUY2TOYROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
YUY2ToYRow = YUY2ToYRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
@ -7043,8 +7087,11 @@ void HalfMergeUVPlane(const uint8_t* src_u,
src_stride_v = -src_stride_v;
}
#if defined(HAS_HALFMERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
HalfMergeUVRow = HalfMergeUVRow_NEON;
if (TestCpuFlag(kCpuHasNEON)) {
HalfMergeUVRow = HalfMergeUVRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
HalfMergeUVRow = HalfMergeUVRow_NEON;
}
}
#endif
#if defined(HAS_HALFMERGEUVROW_SVE2)

View File

@ -555,8 +555,11 @@ void SplitRotateUV180(const uint8_t* src,
void (*MirrorSplitUVRow)(const uint8_t* src, uint8_t* dst_u, uint8_t* dst_v,
int width) = MirrorSplitUVRow_C;
#if defined(HAS_MIRRORSPLITUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_NEON;
if (TestCpuFlag(kCpuHasNEON)) {
MirrorSplitUVRow = MirrorSplitUVRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_NEON;
}
}
#endif
#if defined(HAS_MIRRORSPLITUVROW_SSSE3)
@ -581,18 +584,27 @@ void SplitRotateUV180(const uint8_t* src,
}
#endif
#if defined(HAS_MIRRORSPLITUVROW_LSX)
if (TestCpuFlag(kCpuHasLSX) && IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_LSX;
if (TestCpuFlag(kCpuHasLSX)) {
MirrorSplitUVRow = MirrorSplitUVRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_LSX;
}
}
#endif
#if defined(HAS_MIRRORSPLITUVROW_LASX)
if (TestCpuFlag(kCpuHasLASX) && IS_ALIGNED(width, 32)) {
MirrorSplitUVRow = MirrorSplitUVRow_LASX;
if (TestCpuFlag(kCpuHasLASX)) {
MirrorSplitUVRow = MirrorSplitUVRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
MirrorSplitUVRow = MirrorSplitUVRow_LASX;
}
}
#endif
#if defined(HAS_MIRRORSPLITUVROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASMSIMD) && IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_WASMSIMD;
if (TestCpuFlag(kCpuHasWASMSIMD)) {
MirrorSplitUVRow = MirrorSplitUVRow_Any_WASMSIMD;
if (IS_ALIGNED(width, 16)) {
MirrorSplitUVRow = MirrorSplitUVRow_WASMSIMD;
}
}
#endif
#if defined(HAS_MIRRORSPLITUVROW_HVX)

View File

@ -173,6 +173,13 @@ static int ARGBTranspose(const uint8_t* src_argb,
}
}
if (width > 0) {
#if defined(HAS_TRANSPOSEWXH_32_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
TransposeWxH_32_NEON(src_argb, src_stride_argb, dst_argb,
dst_stride_argb, width, height);
return 0;
}
#endif
TransposeWxH_32_C(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
width, height);
}

View File

@ -878,6 +878,9 @@ ANY21HMS(HalfMergeUVRow_Any_SSSE3, HalfMergeUVRow_SSSE3, 15)
#ifdef HAS_HALFMERGEUVROW_AVX2
ANY21HMS(HalfMergeUVRow_Any_AVX2, HalfMergeUVRow_AVX2, 31)
#endif
#ifdef HAS_HALFMERGEUVROW_NEON
ANY21HMS(HalfMergeUVRow_Any_NEON, HalfMergeUVRow_NEON, 15)
#endif
#undef ANY21HMS
// Any 2 planes to 1 with yuvconstants
@ -1244,7 +1247,7 @@ ANY11(RAWToRGB24Row_Any_WASMSIMD, RAWToRGB24Row_WASMSIMD, 0, 3, 3, 15)
#endif
#ifdef HAS_UYVYTOYROW_AVX2
ANY11(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 0, 2, 1, 31)
ANY11(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 1, 4, 1, 31)
#endif
#ifdef HAS_YUY2TOYROW_AVX2
ANY11(YUY2ToYRow_Any_AVX2, YUY2ToYRow_AVX2, 1, 4, 1, 31)
@ -2332,6 +2335,18 @@ ANY12MR(MirrorSplitUVRow_Any_SSSE3, MirrorSplitUVRow_SSSE3, 7)
#ifdef HAS_MIRRORSPLITUVROW_AVX2
ANY12MR(MirrorSplitUVRow_Any_AVX2, MirrorSplitUVRow_AVX2, 15)
#endif
#ifdef HAS_MIRRORSPLITUVROW_NEON
ANY12MR(MirrorSplitUVRow_Any_NEON, MirrorSplitUVRow_NEON, 15)
#endif
#ifdef HAS_MIRRORSPLITUVROW_LSX
ANY12MR(MirrorSplitUVRow_Any_LSX, MirrorSplitUVRow_LSX, 15)
#endif
#ifdef HAS_MIRRORSPLITUVROW_LASX
ANY12MR(MirrorSplitUVRow_Any_LASX, MirrorSplitUVRow_LASX, 31)
#endif
#ifdef HAS_MIRRORSPLITUVROW_WASMSIMD
ANY12MR(MirrorSplitUVRow_Any_WASMSIMD, MirrorSplitUVRow_WASMSIMD, 15)
#endif
#undef ANY12MR
// Any 1 plane. (memset)
@ -2417,6 +2432,8 @@ ANY12(SplitUVRow_Any_LASX, SplitUVRow_LASX, 0, 2, 0, 31)
#endif
#ifdef HAS_YUY2TOUV422ROW_AVX2
ANY12(YUY2ToUV422Row_Any_AVX2, YUY2ToUV422Row_AVX2, 1, 4, 1, 31)
#endif
#ifdef HAS_UYVYTOUV422ROW_AVX2
ANY12(UYVYToUV422Row_Any_AVX2, UYVYToUV422Row_AVX2, 1, 4, 1, 31)
#endif
#ifdef HAS_YUY2TOUV422ROW_SSE2
@ -2816,6 +2833,8 @@ ANY11MC(ARGB4444ToYMatrixRow_Any_WASMSIMD, ARGB4444ToYMatrixRow_WASMSIMD, 2, 15)
#ifdef HAS_YUY2TOUVROW_AVX2
ANY12S(YUY2ToUVRow_Any_AVX2, YUY2ToUVRow_AVX2, 1, 4, 31)
#endif
#ifdef HAS_UYVYTOUVROW_AVX2
ANY12S(UYVYToUVRow_Any_AVX2, UYVYToUVRow_AVX2, 1, 4, 31)
#endif
#ifdef HAS_YUY2TOUVROW_SSE2

View File

@ -231,7 +231,8 @@ void AR30ToARGBRow_C(const uint8_t* src_ar30, uint8_t* dst_argb, int width) {
uint32_t g = (ar30 >> 12) & 0xff;
uint32_t r = (ar30 >> 22) & 0xff;
uint32_t a = (ar30 >> 30) * 0x55; // Replicate 2 bits to 8 bits.
*(uint32_t*)(dst_argb) = b | (g << 8) | (r << 16) | (a << 24);
uint32_t argb = b | (g << 8) | (r << 16) | (a << 24);
memcpy(dst_argb, &argb, sizeof argb);
dst_argb += 4;
src_ar30 += 4;
}
@ -246,7 +247,8 @@ void AR30ToABGRRow_C(const uint8_t* src_ar30, uint8_t* dst_abgr, int width) {
uint32_t g = (ar30 >> 12) & 0xff;
uint32_t r = (ar30 >> 22) & 0xff;
uint32_t a = (ar30 >> 30) * 0x55; // Replicate 2 bits to 8 bits.
*(uint32_t*)(dst_abgr) = r | (g << 8) | (b << 16) | (a << 24);
uint32_t abgr = r | (g << 8) | (b << 16) | (a << 24);
memcpy(dst_abgr, &abgr, sizeof abgr);
dst_abgr += 4;
src_ar30 += 4;
}
@ -260,7 +262,8 @@ void AR30ToAB30Row_C(const uint8_t* src_ar30, uint8_t* dst_ab30, int width) {
uint32_t b = ar30 & 0x3ff;
uint32_t ga = ar30 & 0xc00ffc00;
uint32_t r = (ar30 >> 20) & 0x3ff;
*(uint32_t*)(dst_ab30) = r | ga | (b << 20);
uint32_t ab30 = r | ga | (b << 20);
memcpy(dst_ab30, &ab30, sizeof ab30);
dst_ab30 += 4;
src_ar30 += 4;
}
@ -481,8 +484,9 @@ void ABGRToAR30Row_C(const uint8_t* src_abgr, uint8_t* dst_ar30, int width) {
uint32_t g0 = (src_abgr[1] >> 6) | ((uint32_t)(src_abgr[1]) << 2);
uint32_t b0 = (src_abgr[2] >> 6) | ((uint32_t)(src_abgr[2]) << 2);
uint32_t a0 = (src_abgr[3] >> 6);
*(uint32_t*)(dst_ar30) =
uint32_t ar30 =
STATIC_CAST(uint32_t, b0 | (g0 << 10) | (r0 << 20) | (a0 << 30));
memcpy(dst_ar30, &ar30, sizeof ar30);
dst_ar30 += 4;
src_abgr += 4;
}
@ -495,8 +499,9 @@ void ARGBToAR30Row_C(const uint8_t* src_argb, uint8_t* dst_ar30, int width) {
uint32_t g0 = (src_argb[1] >> 6) | ((uint32_t)(src_argb[1]) << 2);
uint32_t r0 = (src_argb[2] >> 6) | ((uint32_t)(src_argb[2]) << 2);
uint32_t a0 = (src_argb[3] >> 6);
*(uint32_t*)(dst_ar30) =
uint32_t ar30 =
STATIC_CAST(uint32_t, b0 | (g0 << 10) | (r0 << 20) | (a0 << 30));
memcpy(dst_ar30, &ar30, sizeof ar30);
dst_ar30 += 4;
src_argb += 4;
}
@ -2067,7 +2072,7 @@ static void StoreAR30(uint8_t* rgb_buf, int b, int g, int r) {
g = Clamp10(g);
r = Clamp10(r);
ar30 = b | ((uint32_t)g << 10) | ((uint32_t)r << 20) | 0xc0000000;
(*(uint32_t*)rgb_buf) = ar30;
memcpy(rgb_buf, &ar30, sizeof ar30);
}
// 10 bit YUV to 10 bit AR30
@ -2966,12 +2971,13 @@ void MergeXR30Row_C(const uint16_t* src_r,
assert(depth <= 16);
int x;
int shift = depth - 10;
uint32_t* dst_ar30_32 = (uint32_t*)dst_ar30;
for (x = 0; x < width; ++x) {
uint32_t r = clamp1023(src_r[x] >> shift);
uint32_t g = clamp1023(src_g[x] >> shift);
uint32_t b = clamp1023(src_b[x] >> shift);
dst_ar30_32[x] = b | (g << 10) | (r << 20) | 0xc0000000;
uint32_t ar30 = b | (g << 10) | (r << 20) | 0xc0000000;
memcpy(dst_ar30, &ar30, sizeof ar30);
dst_ar30 += 4;
}
}
@ -3634,9 +3640,8 @@ void ARGBAffineRow_C(const uint8_t* src_argb,
for (i = 0; i < width; ++i) {
int x = (int)(uv[0]);
int y = (int)(uv[1]);
*(uint32_t*)(dst_argb) =
*(const uint32_t*)(src_argb + (ptrdiff_t)y * src_argb_stride +
(ptrdiff_t)x * 4);
memcpy(dst_argb,
src_argb + (ptrdiff_t)y * src_argb_stride + (ptrdiff_t)x * 4, 4);
dst_argb += 4;
uv[0] += uv_dudv[2];
uv[1] += uv_dudv[3];

View File

@ -11107,7 +11107,9 @@ void YUY2ToYRow_AVX2(const uint8_t* src_yuy2, uint8_t* dst_y, int width) {
:
: "memory", "cc", "xmm0", "xmm1", "xmm5");
}
#endif // HAS_YUY2TOYROW_AVX2
#ifdef HAS_YUY2TONVUVROW_AVX2
void YUY2ToNVUVRow_AVX2(const uint8_t* src_yuy2,
int stride_yuy2,
uint8_t* dst_uv,
@ -11134,7 +11136,9 @@ void YUY2ToNVUVRow_AVX2(const uint8_t* src_yuy2,
: "r"((ptrdiff_t)(stride_yuy2)) // %3
: "memory", "cc", "xmm0", "xmm1");
}
#endif // HAS_YUY2TONVUVROW_AVX2
#ifdef HAS_YUY2TOUVROW_AVX2
void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2,
int stride_yuy2,
uint8_t* dst_u,
@ -11175,7 +11179,9 @@ void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2,
: "r"((ptrdiff_t)(stride_yuy2)) // %4
: "memory", "cc", "xmm0", "xmm1", "xmm5");
}
#endif // HAS_YUY2TOUVROW_AVX2
#ifdef HAS_YUY2TOUV422ROW_AVX2
void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2,
uint8_t* dst_u,
uint8_t* dst_v,
@ -11213,7 +11219,9 @@ void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2,
:
: "memory", "cc", "xmm0", "xmm1", "xmm5");
}
#endif // HAS_YUY2TOUV422ROW_AVX2
#ifdef HAS_UYVYTOYROW_AVX2
void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) {
asm volatile(
"1: \n"
@ -11233,8 +11241,11 @@ void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) {
"+r"(dst_y), // %1
"+r"(width) // %2
:
: "memory", "cc", "xmm0", "xmm1", "xmm5");
: "memory", "cc", "xmm0", "xmm1");
}
#endif // HAS_UYVYTOYROW_AVX2
#ifdef HAS_UYVYTOUVROW_AVX2
void UYVYToUVRow_AVX2(const uint8_t* src_uyvy,
int stride_uyvy,
uint8_t* dst_u,
@ -11275,7 +11286,9 @@ void UYVYToUVRow_AVX2(const uint8_t* src_uyvy,
: "r"((ptrdiff_t)(stride_uyvy)) // %4
: "memory", "cc", "xmm0", "xmm1", "xmm5");
}
#endif // HAS_UYVYTOUVROW_AVX2
#ifdef HAS_UYVYTOUV422ROW_AVX2
void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy,
uint8_t* dst_u,
uint8_t* dst_v,
@ -11313,7 +11326,7 @@ void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy,
:
: "memory", "cc", "xmm0", "xmm1", "xmm5");
}
#endif // HAS_YUY2TOYROW_AVX2
#endif // HAS_UYVYTOUV422ROW_AVX2
#ifdef HAS_YUY2TOYROW_AVX512BW
LIBYUV_TARGET_AVX512BW

View File

@ -2159,7 +2159,7 @@ void RGB24ToUVRow_NEON(const uint8_t* src_rgb24,
"+r"(dst_v), // %3
"+r"(width) // %4
:
: "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
);
}
@ -2204,7 +2204,7 @@ void RAWToUVRow_NEON(const uint8_t* src_raw,
"+r"(dst_v), // %3
"+r"(width) // %4
:
: "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
);
}
@ -2270,8 +2270,8 @@ void RGB565ToUVRow_NEON(const uint8_t* src_rgb565,
"+r"(dst_v), // %3
"+r"(width) // %4
:
: "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
"q9", "q10", "q11", "q12", "q13", "q14", "q15");
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9",
"q10", "q11", "q12", "q13", "q14", "q15");
}
// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16.
@ -2335,8 +2335,8 @@ void ARGB1555ToUVRow_NEON(const uint8_t* src_argb1555,
"+r"(dst_v), // %3
"+r"(width) // %4
:
: "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
"q9", "q10", "q11", "q12", "q13", "q14", "q15");
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9",
"q10", "q11", "q12", "q13", "q14", "q15");
}
// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16.
@ -2391,7 +2391,7 @@ void ARGB4444ToUVRow_NEON(const uint8_t* src_argb4444,
"+r"(dst_v), // %3
"+r"(width) // %4
:
: "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8",
"q9", "q10", "q11", "q12", "q13", "q14", "q15");
}

View File

@ -1287,8 +1287,8 @@ void UnpackMT2T_NEON(const uint8_t* src, uint16_t* dst, size_t size) {
"+r"(dst), // %1
"+r"(size) // %2
:
: "cc", "memory", "w0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16",
"v17", "v18", "v19", "v20", "v21", "v22", "v23");
}
#if defined(LIBYUV_USE_ST2)

View File

@ -500,7 +500,6 @@ __arm_locally_streaming void MergeUVRow_SME(const uint8_t* src_u,
"whilelt p0.b, wzr, %w[width] \n"
"ld1b {z1.b}, p0/z, [%[src_u]] \n"
"ld1b {z2.b}, p0/z, [%[src_v]] \n"
"subs %w[width], %w[width], %w[vl] \n"
"st2b {z1.b, z2.b}, p0, [%[dst_uv]] \n"
"99: \n"
@ -510,7 +509,7 @@ __arm_locally_streaming void MergeUVRow_SME(const uint8_t* src_u,
[width] "+r"(width), // %[width]
[vl] "=&r"(vl) // %[vl]
:
: "memory", "cc", "z0", "z1", "z2", "p0");
: "memory", "cc", "z1", "z2", "p0");
}
__arm_locally_streaming void MergeUVRow_16_SME(const uint16_t* src_u,
@ -552,7 +551,6 @@ __arm_locally_streaming void MergeUVRow_16_SME(const uint16_t* src_u,
"ld1h {z2.h}, p0/z, [%[src_v]] \n"
"lsl z1.h, p0/m, z1.h, z0.h \n"
"lsl z2.h, p0/m, z2.h, z0.h \n"
"subs %w[width], %w[width], %w[vl] \n"
"st2h {z1.h, z2.h}, p0, [%[dst_uv]] \n"
"99: \n"
@ -624,7 +622,7 @@ __arm_locally_streaming void Convert16To8Row_SME(const uint16_t* src_y,
[width] "+r"(width), // %[width]
[vl] "=&r"(vl) // %[vl]
: [shift] "r"(shift) // %[shift]
: "cc", "memory", "z0", "z1", "z2", "p0", "p1", "p2");
: "memory", "cc", "z0", "z1", "z2", "p0", "p1", "p2");
}
__arm_locally_streaming void CopyRow_SME(const uint8_t* src,
@ -701,7 +699,6 @@ __arm_locally_streaming static void HalfRow_SME(uint8_t* dst_ptr,
"ld1b {z2.b}, p0/z, [%[src_ptr]] \n"
"ld1b {z3.b}, p0/z, [%[src_ptr1]] \n"
"urhadd z2.b, p0/m, z2.b, z3.b \n"
"subs %w[width], %w[width], %w[vl] \n"
"st1b {z2.b}, p0, [%[dst_ptr]] \n"
"99: \n"
@ -711,7 +708,7 @@ __arm_locally_streaming static void HalfRow_SME(uint8_t* dst_ptr,
[width] "+r"(width), // %[width]
[vl] "=&r"(vl) // %[vl]
:
: "cc", "memory", "z0", "z1", "z2", "z3", "p0");
: "memory", "cc", "z2", "z3", "p0");
}
__arm_locally_streaming void InterpolateRow_SME(uint8_t* dst_ptr,
@ -787,7 +784,7 @@ __arm_locally_streaming void InterpolateRow_SME(uint8_t* dst_ptr,
[vl] "=&r"(vl) // %[vl]
: [y0_fraction] "r"(y0_fraction), // %[y0_fraction]
[y1_fraction] "r"(y1_fraction) // %[y1_fraction]
: "cc", "memory", "z0", "z1", "z2", "z3", "z4", "p0");
: "memory", "cc", "z0", "z1", "z2", "z3", "z4", "p0");
}
__arm_locally_streaming static void HalfRow_16_SME(uint16_t* dst_ptr,
@ -834,7 +831,7 @@ __arm_locally_streaming static void HalfRow_16_SME(uint16_t* dst_ptr,
[width] "+r"(width), // %[width]
[vl] "=&r"(vl) // %[vl]
:
: "cc", "memory", "z0", "z1", "z2", "z3", "p0");
: "memory", "cc", "z2", "z3", "p0");
}
__arm_locally_streaming void InterpolateRow_16_SME(uint16_t* dst_ptr,

View File

@ -480,7 +480,6 @@ void AYUVToVURow_SVE2(const uint8_t* src_ayuv,
int vl;
asm volatile (
"cntb %x[vl] \n"
"cmp %w[width], %w[vl] \n"
"subs %w[width], %w[width], %w[vl] \n"
"b.lt 2f \n"

View File

@ -3570,6 +3570,7 @@ void ARGBBlendRow_AVX2(const uint8_t* src_argb0,
#endif // HAS_ARGBBLENDROW_AVX2
#ifdef HAS_BLENDPLANEROW_SSSE3
LIBYUV_TARGET_SSSE3
void BlendPlaneRow_SSSE3(const uint8_t* src0,
const uint8_t* src1,
const uint8_t* alpha,

View File

@ -990,7 +990,7 @@ static int ScalePlaneBox(int src_width,
}
#endif
#if defined(HAS_SCALEADDROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASM)) {
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ScaleAddRow = ScaleAddRow_Any_WASMSIMD;
if (IS_ALIGNED(src_width, 16)) {
ScaleAddRow = ScaleAddRow_WASMSIMD;

View File

@ -450,7 +450,7 @@ static int ScaleARGBBilinearDown(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBFilterCols = ScaleARGBFilterCols_NEON;
@ -458,7 +458,7 @@ static int ScaleARGBBilinearDown(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
if (TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_Any_LSX;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBFilterCols = ScaleARGBFilterCols_LSX;
@ -466,7 +466,7 @@ static int ScaleARGBBilinearDown(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
if (TestCpuFlag(kCpuHasRVV) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_RVV;
}
#endif
@ -613,7 +613,7 @@ static int ScaleARGBBilinearUp(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_NEON)
if (filtering && TestCpuFlag(kCpuHasNEON)) {
if (filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBFilterCols = ScaleARGBFilterCols_NEON;
@ -621,7 +621,7 @@ static int ScaleARGBBilinearUp(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_LSX)
if (filtering && TestCpuFlag(kCpuHasLSX)) {
if (filtering && TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_Any_LSX;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBFilterCols = ScaleARGBFilterCols_LSX;
@ -629,7 +629,7 @@ static int ScaleARGBBilinearUp(int src_width,
}
#endif
#if defined(HAS_SCALEARGBFILTERCOLS_RVV)
if (filtering && TestCpuFlag(kCpuHasRVV)) {
if (filtering && TestCpuFlag(kCpuHasRVV) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBFilterCols_RVV;
}
#endif
@ -639,7 +639,7 @@ static int ScaleARGBBilinearUp(int src_width,
}
#endif
#if defined(HAS_SCALEARGBCOLS_NEON)
if (!filtering && TestCpuFlag(kCpuHasNEON)) {
if (!filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBCols_Any_NEON;
if (IS_ALIGNED(dst_width, 8)) {
ScaleARGBFilterCols = ScaleARGBCols_NEON;
@ -647,7 +647,7 @@ static int ScaleARGBBilinearUp(int src_width,
}
#endif
#if defined(HAS_SCALEARGBCOLS_LSX)
if (!filtering && TestCpuFlag(kCpuHasLSX)) {
if (!filtering && TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
ScaleARGBFilterCols = ScaleARGBCols_Any_LSX;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBFilterCols = ScaleARGBCols_LSX;
@ -778,7 +778,7 @@ static void ScaleARGBSimple(int src_width,
}
#endif
#if defined(HAS_SCALEARGBCOLS_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
ScaleARGBCols = ScaleARGBCols_Any_NEON;
if (IS_ALIGNED(dst_width, 8)) {
ScaleARGBCols = ScaleARGBCols_NEON;
@ -786,7 +786,7 @@ static void ScaleARGBSimple(int src_width,
}
#endif
#if defined(HAS_SCALEARGBCOLS_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
if (TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
ScaleARGBCols = ScaleARGBCols_Any_LSX;
if (IS_ALIGNED(dst_width, 4)) {
ScaleARGBCols = ScaleARGBCols_LSX;

View File

@ -393,6 +393,19 @@ void ScaleRowDown2Box_RVV(const uint8_t* src_ptr,
: RVV_VL_CLOBBER "memory", "v8", "v9", "v10", "v11", "v16", "v17", "v18",
"v19", "v20", "v21", "v22", "v23");
}
void ScaleRowDown2Box_Odd_RVV(const uint8_t* src_ptr,
ptrdiff_t src_stride,
uint8_t* dst,
int dst_width) {
dst_width -= 1;
if (dst_width > 0) {
ScaleRowDown2Box_RVV(src_ptr, src_stride, dst, dst_width);
}
const uint8_t* s = src_ptr + dst_width * 2;
const uint8_t* t = s + src_stride;
dst[dst_width] = (s[0] + t[0] + 1) >> 1;
}
#endif
#ifdef HAS_SCALEROWDOWN4_RVV

View File

@ -454,7 +454,7 @@ static int ScaleUVBox(int src_width,
}
#endif
#if defined(HAS_SCALEUVADDCOLS3_WASMSIMD)
if (TestCpuFlag(kCpuHasWASM)) {
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ScaleUVAddCols3 = ScaleUVAddCols3_Any_WASMSIMD;
if (IS_ALIGNED(dst_width, 8)) {
ScaleUVAddCols3 = ScaleUVAddCols3_WASMSIMD;
@ -515,7 +515,7 @@ static int ScaleUVBox(int src_width,
}
#endif
#if defined(HAS_SCALEADDROW_WASMSIMD)
if (TestCpuFlag(kCpuHasWASM)) {
if (TestCpuFlag(kCpuHasWASMSIMD)) {
ScaleAddRow = ScaleAddRow_Any_WASMSIMD;
if (IS_ALIGNED(row_samples, 16)) {
ScaleAddRow = ScaleAddRow_WASMSIMD;

View File

@ -1582,8 +1582,7 @@ TEST_F(LibYUVPlanarTest, I420Blend_Unaligned) {
disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
}
// TODO(fbarchard): DISABLED because _Any uses C. Avoid C and re-enable.
TEST_F(LibYUVPlanarTest, DISABLED_I420Blend_Any) {
TEST_F(LibYUVPlanarTest, I420Blend_Any) {
TestI420Blend(benchmark_width_ + 1, benchmark_height_, benchmark_iterations_,
disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
}