diff --git a/README.chromium b/README.chromium index c0f30dc98..056328302 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: https://chromium.googlesource.com/libyuv/libyuv/ -Version: 1970 +Version: 1971 Revision: DEPS License: BSD-3-Clause License File: LICENSE diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 7429e8a87..bb8968490 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -479,21 +479,21 @@ int UYVYToNV12(const uint8_t* src_uyvy, int width, int height); -// Convert NV21 to NV12. +// Convert NV12 to NV21. LIBYUV_API -int NV21ToNV12(const uint8_t* src_y, +int NV12ToNV21(const uint8_t* src_y, int src_stride_y, - const uint8_t* src_vu, - int src_stride_vu, + const uint8_t* src_uv, + int src_stride_uv, uint8_t* dst_y, int dst_stride_y, - uint8_t* dst_uv, - int dst_stride_uv, + uint8_t* dst_vu, + int dst_stride_vu, int width, int height); // Alias -#define NV12ToNV21 NV21ToNV12 +#define NV21ToNV12 NV12ToNV21 LIBYUV_API int YUY2ToY(const uint8_t* src_yuy2, diff --git a/include/libyuv/row.h b/include/libyuv/row.h index b0ce5d05d..736d2f9bc 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -405,6 +405,7 @@ extern "C" { #define HAS_INTERPOLATEROW_AVX2 #define HAS_INTERPOLATEROW_16_AVX2 #define HAS_MULTIPLYROW_16_AVX2 +#define HAS_SWAPUVROW_AVX2 #endif // The following are available for AVX512 clang x64 platforms: diff --git a/include/libyuv/version.h b/include/libyuv/version.h index b5e916c22..1aad36e2d 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1970 +#define LIBYUV_VERSION 1971 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 2eb4d7b01..b7ae2a3e4 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -1108,22 +1108,22 @@ void SwapUVPlane(const uint8_t* src_uv, } } -// Convert NV21 to NV12. +// Convert NV12 to NV21. LIBYUV_API -int NV21ToNV12(const uint8_t* src_y, +int NV12ToNV21(const uint8_t* src_y, int src_stride_y, - const uint8_t* src_vu, - int src_stride_vu, + const uint8_t* src_uv, + int src_stride_uv, uint8_t* dst_y, int dst_stride_y, - uint8_t* dst_uv, - int dst_stride_uv, + uint8_t* dst_vu, + int dst_stride_vu, int width, int height) { int halfwidth = (width + 1) >> 1; int halfheight = (height + 1) >> 1; - if (!src_vu || !dst_uv || width <= 0 || height == 0 || height == INT_MIN) { + if (!src_uv || !dst_vu || width <= 0 || height == 0 || height == INT_MIN) { return -1; } @@ -1135,11 +1135,11 @@ int NV21ToNV12(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_vu = src_vu + (ptrdiff_t)(halfheight - 1) * src_stride_vu; - src_stride_vu = -src_stride_vu; + src_uv = src_uv + (ptrdiff_t)(halfheight - 1) * src_stride_uv; + src_stride_uv = -src_stride_uv; } - SwapUVPlane(src_vu, src_stride_vu, dst_uv, dst_stride_uv, halfwidth, + SwapUVPlane(src_uv, src_stride_uv, dst_vu, dst_stride_vu, halfwidth, halfheight); return 0; } diff --git a/source/row_gcc.cc b/source/row_gcc.cc index ec2b51ae9..90d6786df 100644 --- a/source/row_gcc.cc +++ b/source/row_gcc.cc @@ -10498,12 +10498,14 @@ void NV21ToYUV24Row_AVX512(const uint8_t* src_y, #endif // HAS_NV21ToYUV24ROW_AVX512 -#ifdef HAS_SWAPUVROW_SSSE3 +#if defined(HAS_SWAPUVROW_SSSE3) || defined(HAS_SWAPUVROW_AVX2) // Shuffle table for reversing the bytes. static const uvec8 kShuffleUVToVU = {1u, 0u, 3u, 2u, 5u, 4u, 7u, 6u, 9u, 8u, 11u, 10u, 13u, 12u, 15u, 14u}; +#endif +#ifdef HAS_SWAPUVROW_SSSE3 // Convert UV plane of NV12 to VU of NV21. void SwapUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_vu, int width) { asm volatile("movdqu %3,%%xmm5 \n" diff --git a/source/row_win.cc b/source/row_win.cc index 961235489..6831137d5 100644 --- a/source/row_win.cc +++ b/source/row_win.cc @@ -874,6 +874,26 @@ void MirrorUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_uv, int width) { } #endif // HAS_MIRRORUVROW_AVX2 +#ifdef HAS_SWAPUVROW_AVX2 +LIBYUV_TARGET_AVX2 +void SwapUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_vu, int width) { + __m256i ymm_shuf = _mm256_broadcastsi128_si256( + _mm_setr_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14)); + while (width > 0) { + __m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_uv); + __m256i ymm1 = _mm256_loadu_si256((const __m256i*)(src_uv + 32)); + ymm0 = _mm256_shuffle_epi8(ymm0, ymm_shuf); + ymm1 = _mm256_shuffle_epi8(ymm1, ymm_shuf); + _mm256_storeu_si256((__m256i*)dst_vu, ymm0); + _mm256_storeu_si256((__m256i*)(dst_vu + 32), ymm1); + src_uv += 64; + dst_vu += 64; + width -= 32; + } + _mm256_zeroupper(); +} +#endif // HAS_SWAPUVROW_AVX2 + #ifdef HAS_MIRRORSPLITUVROW_AVX2 LIBYUV_TARGET_AVX2 void MirrorSplitUVRow_AVX2(const uint8_t* src_uv, diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 8ea10a414..d8d9a0a0f 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -588,6 +588,7 @@ TESTPLANARTOBP(I212, uint16_t, 2, 2, 1, P212, uint16_t, 2, 2, 1, 12) TILE_HEIGHT) #endif +TESTBPTOBP(NV12, uint8_t, 1, 2, 2, NV21, uint8_t, 1, 2, 2, 8, 1, 1) TESTBPTOBP(NV21, uint8_t, 1, 2, 2, NV12, uint8_t, 1, 2, 2, 8, 1, 1) TESTBPTOBP(NV12, uint8_t, 1, 2, 2, NV12Mirror, uint8_t, 1, 2, 2, 8, 1, 1) TESTBPTOBP(NV12, uint8_t, 1, 2, 2, NV24, uint8_t, 1, 1, 1, 8, 1, 1) diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 03a1c1883..b9965a62e 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -4794,6 +4794,22 @@ TEST_F(LibYUVPlanarTest, SwapUVRow) { MemRandomize(src_pixels_vu, kPixels * 2); memset(dst_pixels_uv, 1, kPixels * 2); +#if defined(HAS_SWAPUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + SwapUVRow = SwapUVRow_Any_SSSE3; + if (IS_ALIGNED(kPixels, 16)) { + SwapUVRow = SwapUVRow_SSSE3; + } + } +#endif +#if defined(HAS_SWAPUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + SwapUVRow = SwapUVRow_Any_AVX2; + if (IS_ALIGNED(kPixels, 32)) { + SwapUVRow = SwapUVRow_AVX2; + } + } +#endif #if defined(HAS_SWAPUVROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { SwapUVRow = SwapUVRow_Any_NEON;