diff options
-rw-r--r-- | include/libyuv/convert_from.h | 12 | ||||
-rw-r--r-- | source/convert_from.cc | 129 | ||||
-rw-r--r-- | source/row_gcc.cc | 3 | ||||
-rw-r--r-- | unit_test/convert_test.cc | 7 |
4 files changed, 142 insertions, 9 deletions
diff --git a/include/libyuv/convert_from.h b/include/libyuv/convert_from.h index 237f68f5..8c3999bb 100644 --- a/include/libyuv/convert_from.h +++ b/include/libyuv/convert_from.h @@ -276,6 +276,18 @@ int I420ToARGB4444(const uint8* src_y, int dst_stride_frame, int width, int height); +// Convert I420 to AR30. +LIBYUV_API +int I420ToAR30(const uint8* src_y, + int src_stride_y, + const uint8* src_u, + int src_stride_u, + const uint8* src_v, + int src_stride_v, + uint8* dst_ar30, + int dst_stride_ar30, + int width, + int height); // Convert I420 to specified format. // "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the diff --git a/source/convert_from.cc b/source/convert_from.cc index 0f52f9ef..509fe232 100644 --- a/source/convert_from.cc +++ b/source/convert_from.cc @@ -1125,6 +1125,122 @@ int I420ToRGB565Dither(const uint8* src_y, return 0; } +// Convert I420 to AR30 with matrix +static int I420ToAR30Matrix(const uint8* src_y, + int src_stride_y, + const uint8* src_u, + int src_stride_u, + const uint8* src_v, + int src_stride_v, + uint8* dst_ar30, + int dst_stride_ar30, + const struct YuvConstants* yuvconstants, + int width, + int height) { + int y; + void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf, + const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = + I422ToARGBRow_C; + void (*ARGBToAR30Row)(const uint8* src_argb, uint8* dst_rgb, int width) = + ARGBToAR30Row_C; + + if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30; + dst_stride_ar30 = -dst_stride_ar30; + } + +#if defined(HAS_ARGBTOAR30ROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3; + if (IS_ALIGNED(width, 4)) { + ARGBToAR30Row = ARGBToAR30Row_SSSE3; + } + } +#endif +#if defined(HAS_ARGBTOAR30ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToAR30Row = ARGBToAR30Row_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToAR30Row = ARGBToAR30Row_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToARGBRow = I422ToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_I422TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToARGBRow = I422ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGBRow = I422ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToARGBRow = I422ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_NEON; + } + } +#endif +#if defined(HAS_I422TOARGBROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + I422ToARGBRow = I422ToARGBRow_Any_MSA; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_MSA; + } + } +#endif + + { + // Row buffer for ARGB. + align_buffer_64(row_argb, width * 4); + + for (y = 0; y < height; ++y) { + I422ToARGBRow(src_y, src_u, src_v, row_argb, yuvconstants, width); + ARGBToAR30Row(row_argb, dst_ar30, width); + dst_ar30 += dst_stride_ar30; + src_y += src_stride_y; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } + } + + free_aligned_buffer_64(row_argb); + } + return 0; +} + +// Convert I420 to AR30. +LIBYUV_API +int I420ToAR30(const uint8* src_y, + int src_stride_y, + const uint8* src_u, + int src_stride_u, + const uint8* src_v, + int src_stride_v, + uint8* dst_ar30, + int dst_stride_ar30, + int width, + int height) { + return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v, + src_stride_v, dst_ar30, dst_stride_ar30, + &kYuvI601Constants, width, height); +} + // Convert I420 to specified format LIBYUV_API int ConvertFromI420(const uint8* y, @@ -1157,8 +1273,8 @@ int ConvertFromI420(const uint8* y, break; case FOURCC_RGBP: r = I420ToRGB565(y, y_stride, u, u_stride, v, v_stride, dst_sample, - dst_sample_stride ? dst_sample_stride : width * 2, width, - height); + dst_sample_stride ? dst_sample_stride : width * 2, + width, height); break; case FOURCC_RGBO: r = I420ToARGB1555(y, y_stride, u, u_stride, v, v_stride, dst_sample, @@ -1172,8 +1288,8 @@ int ConvertFromI420(const uint8* y, break; case FOURCC_24BG: r = I420ToRGB24(y, y_stride, u, u_stride, v, v_stride, dst_sample, - dst_sample_stride ? dst_sample_stride : width * 3, width, - height); + dst_sample_stride ? dst_sample_stride : width * 3, + width, height); break; case FOURCC_RAW: r = I420ToRAW(y, y_stride, u, u_stride, v, v_stride, dst_sample, @@ -1200,6 +1316,11 @@ int ConvertFromI420(const uint8* y, dst_sample_stride ? dst_sample_stride : width * 4, width, height); break; + case FOURCC_AR30: + r = I420ToAR30(y, y_stride, u, u_stride, v, v_stride, dst_sample, + dst_sample_stride ? dst_sample_stride : width * 4, width, + height); + break; case FOURCC_I400: r = I400Copy(y, y_stride, dst_sample, dst_sample_stride ? dst_sample_stride : width, width, diff --git a/source/row_gcc.cc b/source/row_gcc.cc index 4eda0597..10781cba 100644 --- a/source/row_gcc.cc +++ b/source/row_gcc.cc @@ -802,8 +802,7 @@ void ARGBToAR30Row_AVX2(const uint8* src, uint8* dst, int width) { "m"(kMaskRB10), // %5 "m"(kMaskAG10), // %6 "m"(kMulAG10) // %7 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6"); + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); } #endif diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 394bb782..ec04530f 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -30,6 +30,9 @@ namespace libyuv { +// Alias to copy pixels as is +#define AR30ToAR30 ARGBCopy + #define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a)) #define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ @@ -597,6 +600,7 @@ TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4) TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4) TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4) TESTPLANARTOB(J420, 2, 2, J400, 1, 1, 1, 0, ARGB, 4) +TESTPLANARTOB(I420, 2, 2, AR30, 4, 4, 1, 0, AR30, 4) #define TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ YALIGN, W1280, DIFF, N, NEG, OFF, ATTEN) \ @@ -1967,9 +1971,6 @@ TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) { } #endif // HAS_ARGBTOAR30ROW_AVX2 -// Alias to copy pixels as is -#define AR30ToAR30 ARGBToARGB - #define TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ ALIGN, YALIGN, W1280, DIFF, N, NEG, SOFF, DOFF, \ FMT_C, BPP_C) \ |