mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-10-28 18:07:12 +08:00
convert_from_argb: Add ARGB to NV16 and NV24
Add matrix and BT.601 wrapper APIs for converting ARGB to NV16 and NV24. Reuse the optimized ARGB Y and UV row functions, then merge the planar chroma rows into the interleaved destination plane. NV16 performs horizontal 2:1 chroma subsampling on every source row. NV24 preserves full-resolution 4:4:4 chroma. Both paths support odd widths, negative heights, and the existing matrix constants. Add tests that compare scalar and optimized paths at an odd width and height through the matrix API and its BT.601 wrapper. Bug: 537818862 Change-Id: Iddefc714a800cdec4dd1394ac7a52bf7b51fd350 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8314188 Reviewed-by: Frank Barchard <fbarchard@google.com> Reviewed-by: richard winterton <rrwinterton@gmail.com>
This commit is contained in:
parent
af714f0810
commit
bcb6b76283
@ -196,7 +196,7 @@ int ARGBToI444(const uint8_t* src_argb,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// RGB to I444 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
// ARGB to I444 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToI444Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
@ -260,7 +260,7 @@ int ABGRToI422(const uint8_t* src_abgr,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// RGB to I444 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
// ARGB to I422 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToI422Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
@ -408,7 +408,7 @@ int ARGBToNV12(const uint8_t* src_argb,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// RGB to NV12 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
// ARGB to NV12 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToNV12Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
@ -420,7 +420,53 @@ int ARGBToNV12Matrix(const uint8_t* src_argb,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// RGB to NV21 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
// Convert ARGB To NV16.
|
||||
LIBYUV_API
|
||||
int ARGBToNV16(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// ARGB to NV16 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToNV16Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
const struct ArgbConstants* argbconstants,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert ARGB To NV24.
|
||||
LIBYUV_API
|
||||
int ARGBToNV24(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// ARGB to NV24 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToNV24Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
const struct ArgbConstants* argbconstants,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// ARGB to NV21 with matrix. See ArgbConstants at the top of this file for usage.
|
||||
LIBYUV_API
|
||||
int ARGBToNV21Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
|
||||
@ -638,6 +638,498 @@ int ARGBToNV12Matrix(const uint8_t* src_argb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBToNV16(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
int width,
|
||||
int height) {
|
||||
return ARGBToNV16Matrix(src_argb, src_stride_argb, dst_y, dst_stride_y,
|
||||
dst_uv, dst_stride_uv, &kArgbI601Constants, width,
|
||||
height);
|
||||
}
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBToNV16Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
const struct ArgbConstants* argbconstants,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
int halfwidth = (width >> 1) + (width & 1);
|
||||
void (*ARGBToYMatrixRow)(const uint8_t* src_argb, uint8_t* dst_y, int width,
|
||||
const struct ArgbConstants* c) = ARGBToYMatrixRow_C;
|
||||
void (*ARGBToUVMatrixRow)(const uint8_t* src_argb, int src_stride_argb,
|
||||
uint8_t* dst_u, uint8_t* dst_v, int width,
|
||||
const struct ArgbConstants* c) =
|
||||
ARGBToUVMatrixRow_C;
|
||||
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(width, 64)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_NEON_DOTPROD)
|
||||
if (TestCpuFlag(kCpuHasNeonDotProd)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_NEON_DotProd;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_NEON_DotProd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
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;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_LSX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_LASX)
|
||||
if (TestCpuFlag(kCpuHasLASX)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_LASX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_NEON_I8MM)
|
||||
if (TestCpuFlag(kCpuHasNEON) && TestCpuFlag(kCpuHasNeonI8MM)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_NEON_I8MM;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_NEON_I8MM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
if (IS_ALIGNED(width, 2)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_SVE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_SME)
|
||||
if (TestCpuFlag(kCpuHasSME)) {
|
||||
if (IS_ALIGNED(width, 2)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_SME;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(width, 64)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUVMATRIXROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
ARGBToUVMatrixRow = ARGBToUVMatrixRow_RVV;
|
||||
}
|
||||
#endif
|
||||
void (*MergeUVRow)(const uint8_t* src_u, const uint8_t* src_v,
|
||||
uint8_t* dst_uv, int width) = MergeUVRow_C;
|
||||
if (!src_argb || !dst_y || !dst_uv || !argbconstants || width <= 0 ||
|
||||
height == 0 || height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
src_argb = src_argb + (ptrdiff_t)(height - 1) * src_stride_argb;
|
||||
src_stride_argb = -src_stride_argb;
|
||||
}
|
||||
#if defined(HAS_MERGEUVROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
MergeUVRow = MergeUVRow_Any_SSE2;
|
||||
if (IS_ALIGNED(halfwidth, 16)) {
|
||||
MergeUVRow = MergeUVRow_SSE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
MergeUVRow = MergeUVRow_Any_AVX2;
|
||||
if (IS_ALIGNED(halfwidth, 32)) {
|
||||
MergeUVRow = MergeUVRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
MergeUVRow = MergeUVRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(halfwidth, 32)) {
|
||||
MergeUVRow = MergeUVRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
MergeUVRow = MergeUVRow_Any_NEON;
|
||||
if (IS_ALIGNED(halfwidth, 16)) {
|
||||
MergeUVRow = MergeUVRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
MergeUVRow = MergeUVRow_SVE2;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_SME)
|
||||
if (TestCpuFlag(kCpuHasSME)) {
|
||||
MergeUVRow = MergeUVRow_SME;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_LSX)
|
||||
if (TestCpuFlag(kCpuHasLSX)) {
|
||||
MergeUVRow = MergeUVRow_Any_LSX;
|
||||
if (IS_ALIGNED(halfwidth, 16)) {
|
||||
MergeUVRow = MergeUVRow_LSX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
MergeUVRow = MergeUVRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t row_size = (static_cast<size_t>(halfwidth) + 31) &
|
||||
~static_cast<size_t>(31);
|
||||
if (row_size > SIZE_MAX / 2) {
|
||||
return -1;
|
||||
}
|
||||
align_buffer_64(row_u, row_size * 2);
|
||||
if (!row_u)
|
||||
return 1;
|
||||
uint8_t* row_v = row_u + row_size;
|
||||
|
||||
for (y = 0; y < height; ++y) {
|
||||
ARGBToUVMatrixRow(src_argb, 0, row_u, row_v, width, argbconstants);
|
||||
ARGBToYMatrixRow(src_argb, dst_y, width, argbconstants);
|
||||
MergeUVRow(row_u, row_v, dst_uv, halfwidth);
|
||||
src_argb += src_stride_argb;
|
||||
dst_y += dst_stride_y;
|
||||
dst_uv += dst_stride_uv;
|
||||
}
|
||||
free_aligned_buffer_64(row_u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBToNV24(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
int width,
|
||||
int height) {
|
||||
return ARGBToNV24Matrix(src_argb, src_stride_argb, dst_y, dst_stride_y,
|
||||
dst_uv, dst_stride_uv, &kArgbI601Constants, width,
|
||||
height);
|
||||
}
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBToNV24Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_uv,
|
||||
int dst_stride_uv,
|
||||
const struct ArgbConstants* argbconstants,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void (*ARGBToYMatrixRow)(const uint8_t* src_argb, uint8_t* dst_y, int width,
|
||||
const struct ArgbConstants* c) = ARGBToYMatrixRow_C;
|
||||
void (*ARGBToUV444MatrixRow)(
|
||||
const uint8_t* src_argb, uint8_t* dst_u, uint8_t* dst_v, int width,
|
||||
const struct ArgbConstants* c) = ARGBToUV444MatrixRow_C;
|
||||
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(width, 64)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_NEON_DOTPROD)
|
||||
if (TestCpuFlag(kCpuHasNeonDotProd)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_NEON_DotProd;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_NEON_DotProd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
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;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_LSX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_LASX)
|
||||
if (TestCpuFlag(kCpuHasLASX)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_LASX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOYMATRIXROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
ARGBToYMatrixRow = ARGBToYMatrixRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(width, 64)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_NEON_I8MM)
|
||||
if (TestCpuFlag(kCpuHasNeonI8MM)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_Any_NEON_I8MM;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_NEON_I8MM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_ARGBTOUV444MATRIXROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
ARGBToUV444MatrixRow = ARGBToUV444MatrixRow_RVV;
|
||||
}
|
||||
#endif
|
||||
void (*MergeUVRow)(const uint8_t* src_u, const uint8_t* src_v,
|
||||
uint8_t* dst_uv, int width) = MergeUVRow_C;
|
||||
if (!src_argb || !dst_y || !dst_uv || !argbconstants || width <= 0 ||
|
||||
height == 0 || height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
src_argb = src_argb + (ptrdiff_t)(height - 1) * src_stride_argb;
|
||||
src_stride_argb = -src_stride_argb;
|
||||
}
|
||||
#if defined(HAS_MERGEUVROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
MergeUVRow = MergeUVRow_Any_SSE2;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
MergeUVRow = MergeUVRow_SSE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
MergeUVRow = MergeUVRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
MergeUVRow = MergeUVRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_AVX512BW)
|
||||
if (TestCpuFlag(kCpuHasAVX512BW)) {
|
||||
MergeUVRow = MergeUVRow_Any_AVX512BW;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
MergeUVRow = MergeUVRow_AVX512BW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
MergeUVRow = MergeUVRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
MergeUVRow = MergeUVRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
MergeUVRow = MergeUVRow_SVE2;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_SME)
|
||||
if (TestCpuFlag(kCpuHasSME)) {
|
||||
MergeUVRow = MergeUVRow_SME;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_LSX)
|
||||
if (TestCpuFlag(kCpuHasLSX)) {
|
||||
MergeUVRow = MergeUVRow_Any_LSX;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
MergeUVRow = MergeUVRow_LSX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_MERGEUVROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
MergeUVRow = MergeUVRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t row_size = (static_cast<size_t>(width) + 31) &
|
||||
~static_cast<size_t>(31);
|
||||
if (row_size > SIZE_MAX / 2) {
|
||||
return -1;
|
||||
}
|
||||
align_buffer_64(row_u, row_size * 2);
|
||||
if (!row_u)
|
||||
return 1;
|
||||
uint8_t* row_v = row_u + row_size;
|
||||
|
||||
for (y = 0; y < height; ++y) {
|
||||
ARGBToUV444MatrixRow(src_argb, row_u, row_v, width, argbconstants);
|
||||
ARGBToYMatrixRow(src_argb, dst_y, width, argbconstants);
|
||||
MergeUVRow(row_u, row_v, dst_uv, width);
|
||||
src_argb += src_stride_argb;
|
||||
dst_y += dst_stride_y;
|
||||
dst_uv += dst_stride_uv;
|
||||
}
|
||||
free_aligned_buffer_64(row_u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBToNV21Matrix(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
|
||||
@ -834,6 +834,8 @@ TESTATOPLANARA(ARGB, 4, 1, I420Alpha, 2, 2)
|
||||
|
||||
TESTATOBP(ARGB, 1, 4, NV12, 2, 2)
|
||||
TESTATOBP(ARGB, 1, 4, NV21, 2, 2)
|
||||
TESTATOBP(ARGB, 1, 4, NV16, 2, 1)
|
||||
TESTATOBP(ARGB, 1, 4, NV24, 1, 1)
|
||||
TESTATOBP(ABGR, 1, 4, NV12, 2, 2)
|
||||
TESTATOBP(ABGR, 1, 4, NV21, 2, 2)
|
||||
TESTATOBP(YUY2, 2, 4, NV12, 2, 2)
|
||||
@ -841,6 +843,44 @@ TESTATOBP(UYVY, 2, 4, NV12, 2, 2)
|
||||
TESTATOBP(AYUV, 1, 4, NV12, 2, 2)
|
||||
TESTATOBP(AYUV, 1, 4, NV21, 2, 2)
|
||||
|
||||
// Matrix API with I601 constants matches the non-matrix wrapper.
|
||||
#define TESTATOBPMATRIX(FMT_A, BPP_A, FMT_B, SUBSAMP_X, SUBSAMP_Y) \
|
||||
TEST_F(LibYUVConvertTest, Test##FMT_A##To##FMT_B##Matrix) { \
|
||||
const int kWidth = 16; \
|
||||
const int kHeight = 16; \
|
||||
const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
|
||||
const int kHeightUV = SUBSAMPLE(kHeight, SUBSAMP_Y); \
|
||||
align_buffer_page_end(src_argb, kWidth * kHeight * BPP_A); \
|
||||
align_buffer_page_end(dst_y, kWidth * kHeight); \
|
||||
align_buffer_page_end(dst_uv, kStrideUV * 2 * kHeightUV); \
|
||||
align_buffer_page_end(ref_y, kWidth * kHeight); \
|
||||
align_buffer_page_end(ref_uv, kStrideUV * 2 * kHeightUV); \
|
||||
\
|
||||
MemRandomize(src_argb, kWidth * kHeight * BPP_A); \
|
||||
\
|
||||
FMT_A##To##FMT_B##Matrix(src_argb, kWidth * BPP_A, dst_y, kWidth, dst_uv, \
|
||||
kStrideUV * 2, &kArgbI601Constants, kWidth, \
|
||||
kHeight); \
|
||||
FMT_A##To##FMT_B(src_argb, kWidth * BPP_A, ref_y, kWidth, ref_uv, \
|
||||
kStrideUV * 2, kWidth, kHeight); \
|
||||
for (int i = 0; i < kWidth * kHeight; ++i) { \
|
||||
ASSERT_EQ(dst_y[i], ref_y[i]); \
|
||||
} \
|
||||
for (int i = 0; i < kStrideUV * 2 * kHeightUV; ++i) { \
|
||||
ASSERT_EQ(dst_uv[i], ref_uv[i]); \
|
||||
} \
|
||||
\
|
||||
free_aligned_buffer_page_end(src_argb); \
|
||||
free_aligned_buffer_page_end(dst_y); \
|
||||
free_aligned_buffer_page_end(dst_uv); \
|
||||
free_aligned_buffer_page_end(ref_y); \
|
||||
free_aligned_buffer_page_end(ref_uv); \
|
||||
}
|
||||
|
||||
TESTATOBPMATRIX(ARGB, 4, NV12, 2, 2)
|
||||
TESTATOBPMATRIX(ARGB, 4, NV16, 2, 1)
|
||||
TESTATOBPMATRIX(ARGB, 4, NV24, 1, 1)
|
||||
|
||||
#if !defined(LEAN_TESTS)
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
@ -2420,37 +2460,6 @@ TEST_F(LibYUVConvertTest, TestRGB24ToNV12) {
|
||||
free_aligned_buffer_page_end(ref_uv);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, TestARGBToNV12Matrix) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 16;
|
||||
align_buffer_page_end(src_argb, kWidth * kHeight * 4);
|
||||
align_buffer_page_end(dst_y, kWidth * kHeight);
|
||||
align_buffer_page_end(dst_uv, kWidth * kHeight / 2);
|
||||
|
||||
MemRandomize(src_argb, kWidth * kHeight * 4);
|
||||
|
||||
// BT.601
|
||||
ARGBToNV12Matrix(src_argb, kWidth * 4, dst_y, kWidth, dst_uv, kWidth,
|
||||
&kArgbI601Constants, kWidth, kHeight);
|
||||
// Verify against non-matrix version
|
||||
align_buffer_page_end(ref_y, kWidth * kHeight);
|
||||
align_buffer_page_end(ref_uv, kWidth * kHeight / 2);
|
||||
ARGBToNV12(src_argb, kWidth * 4, ref_y, kWidth, ref_uv, kWidth, kWidth,
|
||||
kHeight);
|
||||
for (int i = 0; i < kWidth * kHeight; ++i) {
|
||||
ASSERT_EQ(dst_y[i], ref_y[i]);
|
||||
}
|
||||
for (int i = 0; i < kWidth * kHeight / 2; ++i) {
|
||||
ASSERT_EQ(dst_uv[i], ref_uv[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
free_aligned_buffer_page_end(dst_y);
|
||||
free_aligned_buffer_page_end(dst_uv);
|
||||
free_aligned_buffer_page_end(ref_y);
|
||||
free_aligned_buffer_page_end(ref_uv);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, TestABGRToNV12Matrix) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 16;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user