From bb3180ae807ddf55335926d5f53b3856e2882b1c Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Tue, 12 Dec 2017 14:53:10 -0800 Subject: Add I420ToAR30 10 bit RGB For more complete support of AR30 format, add I420ToAR30 allowing the new RGB 10 bit format to be used from standard 8 bit I420 format. Bug: libyuv:751 Test: I420ToAR30 unittest added Change-Id: Ia8b0857447408bd6adab485158ce5f38d6dc2faa Reviewed-on: https://chromium-review.googlesource.com/823243 Reviewed-by: Weiyong Yao Commit-Queue: Frank Barchard --- source/convert_from.cc | 129 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) (limited to 'source/convert_from.cc') 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, -- cgit v1.2.3