From edd3a84d0524a6ad2d9f9bc3c19742e79648354d Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Fri, 7 Oct 2016 17:20:30 -0700 Subject: [PATCH] libyuv::YUY2ToY for isolating Y channel of YUY2. This function is the first step of YUY2 To I420. Provided primarily for diagnostics. TBR=wangcheng@google.com BUG=libyuv:647 TESTED=LibYUVConvertTest.YUY2ToY_Opt Review URL: https://codereview.chromium.org/2399153004 . --- include/libyuv/planar_functions.h | 5 +++ source/planar_functions.cc | 66 +++++++++++++++++++++++++++++++ source/row_neon.cc | 2 + unit_test/convert_test.cc | 3 +- 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 1b57b2926..1098dd64c 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -111,6 +111,11 @@ int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_uv, int dst_stride_uv, int width, int height); +LIBYUV_API +int YUY2ToY(const uint8* src_yuy2, int src_stride_yuy2, + uint8* dst_y, int dst_stride_y, + int width, int height); + // Convert I420 to I400. (calls CopyPlane ignoring u/v). LIBYUV_API int I420ToI400(const uint8* src_y, int src_stride_y, diff --git a/source/planar_functions.cc b/source/planar_functions.cc index f9fa212f3..d24393f68 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -588,6 +588,71 @@ int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, return 0; } +// Convert YUY2 to Y. +LIBYUV_API +int YUY2ToY(const uint8* src_yuy2, int src_stride_yuy2, + uint8* dst_y, int dst_stride_y, + int width, int height) { + int y; + void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int width) = + YUY2ToYRow_C; + if (!src_yuy2 || !dst_y || width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; + src_stride_yuy2 = -src_stride_yuy2; + } + // Coalesce rows. + if (src_stride_yuy2 == width * 2 && + dst_stride_y == width) { + width *= height; + height = 1; + src_stride_yuy2 = dst_stride_y = 0; + } +#if defined(HAS_YUY2TOYROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + YUY2ToYRow = YUY2ToYRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + YUY2ToYRow = YUY2ToYRow_SSE2; + } + } +#endif +#if defined(HAS_YUY2TOYROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + YUY2ToYRow = YUY2ToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + YUY2ToYRow = YUY2ToYRow_AVX2; + } + } +#endif +#if defined(HAS_YUY2TOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + YUY2ToYRow = YUY2ToYRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + YUY2ToYRow = YUY2ToYRow_NEON; + } + } +#endif +#if defined(HAS_YUY2TOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + YUY2ToYRow = YUY2ToYRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + YUY2ToYRow = YUY2ToYRow_MSA; + } + } +#endif + + for (y = 0; y < height; ++y) { + YUY2ToYRow(src_yuy2, dst_y, width); + src_yuy2 += src_stride_yuy2; + dst_y += dst_stride_y; + } + return 0; +} + // Mirror I400 with optional flipping LIBYUV_API int I400Mirror(const uint8* src_y, int src_stride_y, @@ -2699,6 +2764,7 @@ int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, return 0; } + // TODO(fbarchard): Consider if width is even Y channel can be split // directly. A SplitUVRow_Odd function could copy the remaining chroma. diff --git a/source/row_neon.cc b/source/row_neon.cc index 909df060c..4a41d8a22 100644 --- a/source/row_neon.cc +++ b/source/row_neon.cc @@ -10,6 +10,8 @@ #include "libyuv/row.h" +#include + #ifdef __cplusplus namespace libyuv { extern "C" { diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 7542ddf44..44c8fa1d8 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -315,8 +315,6 @@ TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##_##PN##N) {\ TESTAPLANARTOP(Android420, I420, 1, 0, 0, 2, 2, I420, 2, 2) TESTAPLANARTOP(Android420, NV12, 2, 0, 1, 2, 2, I420, 2, 2) TESTAPLANARTOP(Android420, NV21, 2, 1, 0, 2, 2, I420, 2, 2) -// YUV3 causes msan failure. skip for now. -//TESTAPLANARTOP(Android420, YUV3, 3, 0, 1, 2, 2, I420, 2, 2) #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \ @@ -1139,6 +1137,7 @@ TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4) TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4) +TESTATOB(YUY2, 2, 4, 1, Y, 1, 1, 1, 0) TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0) TESTATOB(J400, 1, 1, 1, ARGB, 4, 4, 1, 0) TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0)