From 3541e46a7ec6ca2e712193325f67e7f4659a82b8 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Thu, 7 Dec 2017 11:28:23 -0800 Subject: [PATCH] Add H010ToARGB for 10 bit YUV to ARGB Bug: libyuv:751 Test: LibYUVConvertTest.H010ToARGB_Opt Change-Id: I668d3f3810e59a4fb6611503aae1c8edc7d596e7 Reviewed-on: https://chromium-review.googlesource.com/815015 Commit-Queue: Frank Barchard Reviewed-by: richard winterton --- BUILD.gn | 1 - include/libyuv/convert_argb.h | 13 ++++ source/convert_argb.cc | 122 ++++++++++++++++++++++++++++++++++ unit_test/convert_test.cc | 4 +- unit_test/cpu_test.cc | 2 + 5 files changed, 140 insertions(+), 2 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 9badf08c8..5bc130d58 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -152,7 +152,6 @@ static_library("libyuv_internal") { # crbug.com/538243). if (!is_debug || is_nacl) { configs -= [ "//build/config/compiler:default_optimization" ] - # Enable optimize for speed (-O2) over size (-Os). configs += [ "//build/config/compiler:optimize_max" ] } diff --git a/include/libyuv/convert_argb.h b/include/libyuv/convert_argb.h index 1aaf4eb5f..ca87dc769 100644 --- a/include/libyuv/convert_argb.h +++ b/include/libyuv/convert_argb.h @@ -342,6 +342,19 @@ int H422ToABGR(const uint8* src_y, int width, int height); +// Convert H010 to ARGB. +LIBYUV_API +int H010ToARGB(const uint16* src_y, + int src_stride_y, + const uint16* src_u, + int src_stride_u, + const uint16* src_v, + int src_stride_v, + uint8* dst_argb, + int dst_stride_argb, + int width, + int height); + // Convert H010 to AR30. LIBYUV_API int H010ToAR30(const uint16* src_y, diff --git a/source/convert_argb.cc b/source/convert_argb.cc index de50ce697..fe8c49160 100644 --- a/source/convert_argb.cc +++ b/source/convert_argb.cc @@ -564,6 +564,128 @@ int H010ToAR30(const uint16* src_y, &kYuvH709Constants, 16384, width, height); } +// Convert 10 bit YUV to ARGB with matrix +static int H010ToARGBMatrix(const uint16* src_y, + int src_stride_y, + const uint16* src_u, + int src_stride_u, + const uint16* src_v, + int src_stride_v, + uint8* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int scale, // 16384 for 10 bits + int width, + int height) { + int y; + int halfwidth = (width + 1) >> 1; + void (*Convert16To8Row)(const uint16* src_y, uint8* dst_y, int scale, + int width) = Convert16To8Row_C; + 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; + + if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_argb = dst_argb + (height - 1) * dst_stride_argb; + dst_stride_argb = -dst_stride_argb; + } + +#if defined(HAS_CONVERT16TO8ROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + Convert16To8Row = Convert16To8Row_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + Convert16To8Row = Convert16To8Row_SSSE3; + } + } +#endif +#if defined(HAS_CONVERT16TO8ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + Convert16To8Row = Convert16To8Row_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + Convert16To8Row = Convert16To8Row_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 + + align_buffer_64(row_y, width); + align_buffer_64(row_u, halfwidth); + align_buffer_64(row_v, halfwidth); + + for (y = 0; y < height; ++y) { + Convert16To8Row(src_y, row_y, scale, width); + Convert16To8Row(src_u, row_u, scale, halfwidth); + Convert16To8Row(src_v, row_v, scale, halfwidth); + + I422ToARGBRow(row_y, row_u, row_v, dst_argb, yuvconstants, width); + + dst_argb += dst_stride_argb; + src_y += src_stride_y; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } + } + free_aligned_buffer_64(row_y); + free_aligned_buffer_64(row_u); + free_aligned_buffer_64(row_v); + return 0; +} + +// Convert H010 to ARGB. +LIBYUV_API +int H010ToARGB(const uint16* src_y, + int src_stride_y, + const uint16* src_u, + int src_stride_u, + const uint16* src_v, + int src_stride_v, + uint8* dst_argb, + int dst_stride_argb, + int width, + int height) { + return H010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, + src_stride_v, dst_argb, dst_stride_argb, + &kYuvH709Constants, 16384, width, height); +} + // Convert I444 to ARGB with matrix static int I444ToARGBMatrix(const uint8* src_y, int src_stride_y, diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index aff7a7a06..cf3447395 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -1935,7 +1935,8 @@ TEST_F(LibYUVConvertTest, RotateWithARGBSource) { #ifdef HAS_ARGBTOAR30ROW_AVX2 TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) { - const int kPixels = benchmark_width_ * benchmark_height_; + // ARGBToAR30Row_AVX2 expects a multiple of 8 pixels. + const int kPixels = (benchmark_width_ * benchmark_height_ + 7) & ~7; align_buffer_page_end(src, kPixels * 4); align_buffer_page_end(dst_opt, kPixels * 4); align_buffer_page_end(dst_c, kPixels * 4); @@ -2037,5 +2038,6 @@ TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) { BPP_C) TESTPLANAR16TOB(H010, 2, 2, AR30, 4, 4, 1, 2, AR30, 4) +TESTPLANAR16TOB(H010, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4) } // namespace libyuv diff --git a/unit_test/cpu_test.cc b/unit_test/cpu_test.cc index 4e694f55c..5fd438a59 100644 --- a/unit_test/cpu_test.cc +++ b/unit_test/cpu_test.cc @@ -147,6 +147,8 @@ static int FileExists(const char* file_name) { TEST_F(LibYUVBaseTest, TestLinuxNeon) { if (FileExists("../../unit_test/testdata/arm_v7.txt")) { + printf("Note: testing to load \"../../unit_test/testdata/arm_v7.txt\"\n"); + EXPECT_EQ(0, ArmCpuCaps("../../unit_test/testdata/arm_v7.txt")); EXPECT_EQ(kCpuHasNEON, ArmCpuCaps("../../unit_test/testdata/tegra3.txt")); EXPECT_EQ(kCpuHasNEON, ArmCpuCaps("../../unit_test/testdata/juno.txt"));