From 08815a29766a78398a8e2b9ed095280e9d0a73c2 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Fri, 19 Feb 2021 08:58:07 -0800 Subject: Scale 12 functions that are scale 16 but with only low 12 bits valid Rename yuvconstants to .c and use round from math.h Bug: libyuv:882, b/180472591 Change-Id: I70720bf3e0833ba00df0d721f12020fba0b07a03 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2706966 Reviewed-by: Mirko Bonadei --- Android.bp | 2 +- BUILD.gn | 8 +-- README.chromium | 2 +- include/libyuv/scale.h | 38 +++++++++++ include/libyuv/version.h | 2 +- linux.mk | 8 +-- source/scale.cc | 70 +++++++++++++++++++ unit_test/scale_argb_test.cc | 1 + unit_test/scale_test.cc | 155 ++++++++++++++++++++++--------------------- unit_test/scale_uv_test.cc | 1 + unit_test/unit_test.cc | 3 - util/yuvconstants.c | 105 +++++++++++++++++++++++++++++ util/yuvconstants.cc | 106 ----------------------------- 13 files changed, 303 insertions(+), 198 deletions(-) create mode 100644 util/yuvconstants.c delete mode 100644 util/yuvconstants.cc diff --git a/Android.bp b/Android.bp index ae59dffb..ce1f62e0 100644 --- a/Android.bp +++ b/Android.bp @@ -150,7 +150,7 @@ cc_test { name: "yuvconstants", gtest: false, srcs: [ - "util/yuvconstants.cc", + "util/yuvconstants.c", ], static_libs: ["libyuv"], } diff --git a/BUILD.gn b/BUILD.gn index f84144ad..e1c7c1da 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -40,8 +40,8 @@ group("default") { ":i444tonv12_eg", ":libyuv_unittest", ":psnr", - ":yuvconvert", ":yuvconstants", + ":yuvconvert", ] } } @@ -364,7 +364,7 @@ if (libyuv_include_tests) { executable("yuvconstants") { sources = [ # sources - "util/yuvconstants.cc", + "util/yuvconstants.c", ] deps = [ ":libyuv" ] if (is_linux || is_chromeos) { @@ -391,9 +391,7 @@ if (libyuv_include_tests) { # sources "util/i444tonv12_eg.cc", ] - deps = [ - ":libyuv", - ] + deps = [ ":libyuv" ] } executable("cpuid") { diff --git a/README.chromium b/README.chromium index 25445f1a..01b05888 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1777 +Version: 1778 License: BSD License File: LICENSE diff --git a/include/libyuv/scale.h b/include/libyuv/scale.h index d06f8b52..3d4b6005 100644 --- a/include/libyuv/scale.h +++ b/include/libyuv/scale.h @@ -109,6 +109,25 @@ int I420Scale_16(const uint16_t* src_y, int dst_height, enum FilterMode filtering); +LIBYUV_API +int I420Scale_12(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + // Scales a YUV 4:4:4 image from the src width and height to the // dst width and height. // If filtering is kFilterNone, a simple nearest-neighbor algorithm is @@ -157,6 +176,25 @@ int I444Scale_16(const uint16_t* src_y, int dst_height, enum FilterMode filtering); +LIBYUV_API +int I444Scale_12(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + // Scales an NV12 image from the src width and height to the // dst width and height. // If filtering is kFilterNone, a simple nearest-neighbor algorithm is diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 911f038c..ff6531bd 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 1777 +#define LIBYUV_VERSION 1778 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/linux.mk b/linux.mk index 083f1fa2..f5e73ea4 100644 --- a/linux.mk +++ b/linux.mk @@ -75,9 +75,9 @@ libyuv.a: $(LOCAL_OBJ_FILES) yuvconvert: util/yuvconvert.cc libyuv.a $(CXX) $(CXXFLAGS) -Iutil/ -o $@ util/yuvconvert.cc libyuv.a -# A C++ test utility that generates yuvconstants for yuv to rgb. -yuvconstants: util/yuvconstants.cc libyuv.a - $(CXX) $(CXXFLAGS) -Iutil/ -o $@ util/yuvconstants.cc libyuv.a +# A C test utility that generates yuvconstants for yuv to rgb. +yuvconstants: util/yuvconstants.c libyuv.a + $(CXX) $(CXXFLAGS) -Iutil/ -lm -o $@ util/yuvconstants.c libyuv.a # A standalone test utility psnr: util/psnr.cc @@ -85,7 +85,7 @@ psnr: util/psnr.cc # A simple conversion example. i444tonv12_eg: util/i444tonv12_eg.cc libyuv.a - $(CC) $(CFLAGS) -o $@ util/i444tonv12_eg.cc libyuv.a + $(CXX) $(CXXFLAGS) -o $@ util/i444tonv12_eg.cc libyuv.a # A C test utility that uses libyuv conversion from C. # gcc 4.4 and older require -fno-exceptions to avoid link error on __gxx_personality_v0 diff --git a/source/scale.cc b/source/scale.cc index 5f0ff646..4a5dc94a 100644 --- a/source/scale.cc +++ b/source/scale.cc @@ -2073,6 +2073,43 @@ int I420Scale_16(const uint16_t* src_y, return 0; } +LIBYUV_API +int I420Scale_12(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering) { + int src_halfwidth = SUBSAMPLE(src_width, 1, 1); + int src_halfheight = SUBSAMPLE(src_height, 1, 1); + int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1); + int dst_halfheight = SUBSAMPLE(dst_height, 1, 1); + if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 || + src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v || + dst_width <= 0 || dst_height <= 0) { + return -1; + } + + ScalePlane_12(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y, + dst_width, dst_height, filtering); + ScalePlane_12(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u, + dst_stride_u, dst_halfwidth, dst_halfheight, filtering); + ScalePlane_12(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v, + dst_stride_v, dst_halfwidth, dst_halfheight, filtering); + return 0; +} + // Scale an I444 image. // This function in turn calls a scaling function for each plane. @@ -2142,6 +2179,39 @@ int I444Scale_16(const uint16_t* src_y, return 0; } +LIBYUV_API +int I444Scale_12(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering) { + if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 || + src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v || + dst_width <= 0 || dst_height <= 0) { + return -1; + } + + ScalePlane_12(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y, + dst_width, dst_height, filtering); + ScalePlane_12(src_u, src_stride_u, src_width, src_height, dst_u, dst_stride_u, + dst_width, dst_height, filtering); + ScalePlane_12(src_v, src_stride_v, src_width, src_height, dst_v, dst_stride_v, + dst_width, dst_height, filtering); + return 0; +} + // Scale an NV12 image. // This function in turn calls a scaling function for each plane. diff --git a/unit_test/scale_argb_test.cc b/unit_test/scale_argb_test.cc index c04a236a..ac976612 100644 --- a/unit_test/scale_argb_test.cc +++ b/unit_test/scale_argb_test.cc @@ -302,6 +302,7 @@ TEST_FACTOR(3, 1, 3) TEST_SCALETO1(name, width, height, Bilinear, 3) TEST_SCALETO(ARGBScale, 1, 1) +TEST_SCALETO(ARGBScale, 256, 144) /* 128x72 * 2 */ TEST_SCALETO(ARGBScale, 320, 240) TEST_SCALETO(ARGBScale, 569, 480) TEST_SCALETO(ARGBScale, 640, 360) diff --git a/unit_test/scale_test.cc b/unit_test/scale_test.cc index d5294110..d24806a6 100644 --- a/unit_test/scale_test.cc +++ b/unit_test/scale_test.cc @@ -142,9 +142,9 @@ static int I420TestFilter(int src_width, return max_diff; } -// Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference. +// Test scaling with 8 bit C vs 12 bit C and return maximum pixel difference. // 0 = exact. -static int I420TestFilter_16(int src_width, +static int I420TestFilter_12(int src_width, int src_height, int dst_width, int dst_height, @@ -169,27 +169,27 @@ static int I420TestFilter_16(int src_width, align_buffer_page_end(src_y, src_y_plane_size); align_buffer_page_end(src_u, src_uv_plane_size); align_buffer_page_end(src_v, src_uv_plane_size); - align_buffer_page_end(src_y_16, src_y_plane_size * 2); - align_buffer_page_end(src_u_16, src_uv_plane_size * 2); - align_buffer_page_end(src_v_16, src_uv_plane_size * 2); - if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) { + align_buffer_page_end(src_y_12, src_y_plane_size * 2); + align_buffer_page_end(src_u_12, src_uv_plane_size * 2); + align_buffer_page_end(src_v_12, src_uv_plane_size * 2); + if (!src_y || !src_u || !src_v || !src_y_12 || !src_u_12 || !src_v_12) { printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n"); return 0; } - uint16_t* p_src_y_16 = reinterpret_cast(src_y_16); - uint16_t* p_src_u_16 = reinterpret_cast(src_u_16); - uint16_t* p_src_v_16 = reinterpret_cast(src_v_16); + uint16_t* p_src_y_12 = reinterpret_cast(src_y_12); + uint16_t* p_src_u_12 = reinterpret_cast(src_u_12); + uint16_t* p_src_v_12 = reinterpret_cast(src_v_12); MemRandomize(src_y, src_y_plane_size); MemRandomize(src_u, src_uv_plane_size); MemRandomize(src_v, src_uv_plane_size); for (i = 0; i < src_y_plane_size; ++i) { - p_src_y_16[i] = src_y[i]; + p_src_y_12[i] = src_y[i]; } for (i = 0; i < src_uv_plane_size; ++i) { - p_src_u_16[i] = src_u[i]; - p_src_v_16[i] = src_v[i]; + p_src_u_12[i] = src_u[i]; + p_src_v_12[i] = src_v[i]; } int dst_width_uv = (dst_width + 1) >> 1; @@ -204,13 +204,13 @@ static int I420TestFilter_16(int src_width, align_buffer_page_end(dst_y_8, dst_y_plane_size); align_buffer_page_end(dst_u_8, dst_uv_plane_size); align_buffer_page_end(dst_v_8, dst_uv_plane_size); - align_buffer_page_end(dst_y_16, dst_y_plane_size * 2); - align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2); - align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2); + align_buffer_page_end(dst_y_12, dst_y_plane_size * 2); + align_buffer_page_end(dst_u_12, dst_uv_plane_size * 2); + align_buffer_page_end(dst_v_12, dst_uv_plane_size * 2); - uint16_t* p_dst_y_16 = reinterpret_cast(dst_y_16); - uint16_t* p_dst_u_16 = reinterpret_cast(dst_u_16); - uint16_t* p_dst_v_16 = reinterpret_cast(dst_v_16); + uint16_t* p_dst_y_12 = reinterpret_cast(dst_y_12); + uint16_t* p_dst_u_12 = reinterpret_cast(dst_u_12); + uint16_t* p_dst_v_12 = reinterpret_cast(dst_v_12); MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization. I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv, @@ -218,26 +218,26 @@ static int I420TestFilter_16(int src_width, dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f); MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization. for (i = 0; i < benchmark_iterations; ++i) { - I420Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv, - p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16, - dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16, + I420Scale_12(p_src_y_12, src_stride_y, p_src_u_12, src_stride_uv, + p_src_v_12, src_stride_uv, src_width, src_height, p_dst_y_12, + dst_stride_y, p_dst_u_12, dst_stride_uv, p_dst_v_12, dst_stride_uv, dst_width, dst_height, f); } // Expect an exact match. int max_diff = 0; for (i = 0; i < dst_y_plane_size; ++i) { - int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]); + int abs_diff = Abs(dst_y_8[i] - p_dst_y_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } } for (i = 0; i < dst_uv_plane_size; ++i) { - int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]); + int abs_diff = Abs(dst_u_8[i] - p_dst_u_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } - abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]); + abs_diff = Abs(dst_v_8[i] - p_dst_v_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } @@ -246,15 +246,15 @@ static int I420TestFilter_16(int src_width, free_aligned_buffer_page_end(dst_y_8); free_aligned_buffer_page_end(dst_u_8); free_aligned_buffer_page_end(dst_v_8); - free_aligned_buffer_page_end(dst_y_16); - free_aligned_buffer_page_end(dst_u_16); - free_aligned_buffer_page_end(dst_v_16); + free_aligned_buffer_page_end(dst_y_12); + free_aligned_buffer_page_end(dst_u_12); + free_aligned_buffer_page_end(dst_v_12); free_aligned_buffer_page_end(src_y); free_aligned_buffer_page_end(src_u); free_aligned_buffer_page_end(src_v); - free_aligned_buffer_page_end(src_y_16); - free_aligned_buffer_page_end(src_u_16); - free_aligned_buffer_page_end(src_v_16); + free_aligned_buffer_page_end(src_y_12); + free_aligned_buffer_page_end(src_u_12); + free_aligned_buffer_page_end(src_v_12); return max_diff; } @@ -377,9 +377,9 @@ static int I444TestFilter(int src_width, return max_diff; } -// Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference. +// Test scaling with 8 bit C vs 12 bit C and return maximum pixel difference. // 0 = exact. -static int I444TestFilter_16(int src_width, +static int I444TestFilter_12(int src_width, int src_height, int dst_width, int dst_height, @@ -404,27 +404,27 @@ static int I444TestFilter_16(int src_width, align_buffer_page_end(src_y, src_y_plane_size); align_buffer_page_end(src_u, src_uv_plane_size); align_buffer_page_end(src_v, src_uv_plane_size); - align_buffer_page_end(src_y_16, src_y_plane_size * 2); - align_buffer_page_end(src_u_16, src_uv_plane_size * 2); - align_buffer_page_end(src_v_16, src_uv_plane_size * 2); - if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) { + align_buffer_page_end(src_y_12, src_y_plane_size * 2); + align_buffer_page_end(src_u_12, src_uv_plane_size * 2); + align_buffer_page_end(src_v_12, src_uv_plane_size * 2); + if (!src_y || !src_u || !src_v || !src_y_12 || !src_u_12 || !src_v_12) { printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n"); return 0; } - uint16_t* p_src_y_16 = reinterpret_cast(src_y_16); - uint16_t* p_src_u_16 = reinterpret_cast(src_u_16); - uint16_t* p_src_v_16 = reinterpret_cast(src_v_16); + uint16_t* p_src_y_12 = reinterpret_cast(src_y_12); + uint16_t* p_src_u_12 = reinterpret_cast(src_u_12); + uint16_t* p_src_v_12 = reinterpret_cast(src_v_12); MemRandomize(src_y, src_y_plane_size); MemRandomize(src_u, src_uv_plane_size); MemRandomize(src_v, src_uv_plane_size); for (i = 0; i < src_y_plane_size; ++i) { - p_src_y_16[i] = src_y[i]; + p_src_y_12[i] = src_y[i]; } for (i = 0; i < src_uv_plane_size; ++i) { - p_src_u_16[i] = src_u[i]; - p_src_v_16[i] = src_v[i]; + p_src_u_12[i] = src_u[i]; + p_src_v_12[i] = src_v[i]; } int dst_width_uv = dst_width; @@ -439,13 +439,13 @@ static int I444TestFilter_16(int src_width, align_buffer_page_end(dst_y_8, dst_y_plane_size); align_buffer_page_end(dst_u_8, dst_uv_plane_size); align_buffer_page_end(dst_v_8, dst_uv_plane_size); - align_buffer_page_end(dst_y_16, dst_y_plane_size * 2); - align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2); - align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2); + align_buffer_page_end(dst_y_12, dst_y_plane_size * 2); + align_buffer_page_end(dst_u_12, dst_uv_plane_size * 2); + align_buffer_page_end(dst_v_12, dst_uv_plane_size * 2); - uint16_t* p_dst_y_16 = reinterpret_cast(dst_y_16); - uint16_t* p_dst_u_16 = reinterpret_cast(dst_u_16); - uint16_t* p_dst_v_16 = reinterpret_cast(dst_v_16); + uint16_t* p_dst_y_12 = reinterpret_cast(dst_y_12); + uint16_t* p_dst_u_12 = reinterpret_cast(dst_u_12); + uint16_t* p_dst_v_12 = reinterpret_cast(dst_v_12); MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization. I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv, @@ -453,26 +453,26 @@ static int I444TestFilter_16(int src_width, dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f); MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization. for (i = 0; i < benchmark_iterations; ++i) { - I444Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv, - p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16, - dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16, + I444Scale_12(p_src_y_12, src_stride_y, p_src_u_12, src_stride_uv, + p_src_v_12, src_stride_uv, src_width, src_height, p_dst_y_12, + dst_stride_y, p_dst_u_12, dst_stride_uv, p_dst_v_12, dst_stride_uv, dst_width, dst_height, f); } // Expect an exact match. int max_diff = 0; for (i = 0; i < dst_y_plane_size; ++i) { - int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]); + int abs_diff = Abs(dst_y_8[i] - p_dst_y_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } } for (i = 0; i < dst_uv_plane_size; ++i) { - int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]); + int abs_diff = Abs(dst_u_8[i] - p_dst_u_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } - abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]); + abs_diff = Abs(dst_v_8[i] - p_dst_v_12[i]); if (abs_diff > max_diff) { max_diff = abs_diff; } @@ -481,15 +481,15 @@ static int I444TestFilter_16(int src_width, free_aligned_buffer_page_end(dst_y_8); free_aligned_buffer_page_end(dst_u_8); free_aligned_buffer_page_end(dst_v_8); - free_aligned_buffer_page_end(dst_y_16); - free_aligned_buffer_page_end(dst_u_16); - free_aligned_buffer_page_end(dst_v_16); + free_aligned_buffer_page_end(dst_y_12); + free_aligned_buffer_page_end(dst_u_12); + free_aligned_buffer_page_end(dst_v_12); free_aligned_buffer_page_end(src_y); free_aligned_buffer_page_end(src_u); free_aligned_buffer_page_end(src_v); - free_aligned_buffer_page_end(src_y_16); - free_aligned_buffer_page_end(src_u_16); - free_aligned_buffer_page_end(src_v_16); + free_aligned_buffer_page_end(src_y_12); + free_aligned_buffer_page_end(src_u_12); + free_aligned_buffer_page_end(src_v_12); return max_diff; } @@ -621,16 +621,16 @@ static int NV12TestFilter(int src_width, benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ - TEST_F(LibYUVScaleTest, DISABLED_##I420ScaleDownBy##name##_##filter##_16) { \ - int diff = I420TestFilter_16( \ + TEST_F(LibYUVScaleTest, DISABLED_##I420ScaleDownBy##name##_##filter##_12) { \ + int diff = I420TestFilter_12( \ SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \ DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \ kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \ benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ - TEST_F(LibYUVScaleTest, DISABLED_##I444ScaleDownBy##name##_##filter##_16) { \ - int diff = I444TestFilter_16( \ + TEST_F(LibYUVScaleTest, DISABLED_##I444ScaleDownBy##name##_##filter##_12) { \ + int diff = I444TestFilter_12( \ SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \ DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \ kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \ @@ -687,15 +687,15 @@ TEST_FACTOR(3, 1, 3, 0) EXPECT_LE(diff, max_diff); \ } \ TEST_F(LibYUVScaleTest, \ - DISABLED_##I420##name##To##width##x##height##_##filter##_16) { \ - int diff = I420TestFilter_16( \ + DISABLED_##I420##name##To##width##x##height##_##filter##_12) { \ + int diff = I420TestFilter_12( \ benchmark_width_, benchmark_height_, width, height, kFilter##filter, \ benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ TEST_F(LibYUVScaleTest, \ - DISABLED_##I444##name##To##width##x##height##_##filter##_16) { \ - int diff = I444TestFilter_16( \ + DISABLED_##I444##name##To##width##x##height##_##filter##_12) { \ + int diff = I444TestFilter_12( \ benchmark_width_, benchmark_height_, width, height, kFilter##filter, \ benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ @@ -721,16 +721,16 @@ TEST_FACTOR(3, 1, 3, 0) EXPECT_LE(diff, max_diff); \ } \ TEST_F(LibYUVScaleTest, \ - DISABLED_##I420##name##From##width##x##height##_##filter##_16) { \ - int diff = I420TestFilter_16(width, height, Abs(benchmark_width_), \ + DISABLED_##I420##name##From##width##x##height##_##filter##_12) { \ + int diff = I420TestFilter_12(width, height, Abs(benchmark_width_), \ Abs(benchmark_height_), kFilter##filter, \ benchmark_iterations_, disable_cpu_flags_, \ benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ TEST_F(LibYUVScaleTest, \ - DISABLED_##I444##name##From##width##x##height##_##filter##_16) { \ - int diff = I444TestFilter_16(width, height, Abs(benchmark_width_), \ + DISABLED_##I444##name##From##width##x##height##_##filter##_12) { \ + int diff = I444TestFilter_12(width, height, Abs(benchmark_width_), \ Abs(benchmark_height_), kFilter##filter, \ benchmark_iterations_, disable_cpu_flags_, \ benchmark_cpu_info_); \ @@ -761,6 +761,7 @@ TEST_FACTOR(3, 1, 3, 0) #endif TEST_SCALETO(Scale, 1, 1) +TEST_SCALETO(Scale, 256, 144) /* 128x72 * 2 */ TEST_SCALETO(Scale, 320, 240) TEST_SCALETO(Scale, 569, 480) TEST_SCALETO(Scale, 640, 360) @@ -786,15 +787,15 @@ TEST_SCALETO(Scale, 1920, 1080) disable_cpu_flags_, benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ - TEST_F(LibYUVScaleTest, DISABLED_##I420##name##SwapXY_##filter##_16) { \ - int diff = I420TestFilter_16(benchmark_width_, benchmark_height_, \ + TEST_F(LibYUVScaleTest, DISABLED_##I420##name##SwapXY_##filter##_12) { \ + int diff = I420TestFilter_12(benchmark_width_, benchmark_height_, \ benchmark_height_, benchmark_width_, \ kFilter##filter, benchmark_iterations_, \ disable_cpu_flags_, benchmark_cpu_info_); \ EXPECT_LE(diff, max_diff); \ } \ - TEST_F(LibYUVScaleTest, DISABLED_##I444##name##SwapXY_##filter##_16) { \ - int diff = I444TestFilter_16(benchmark_width_, benchmark_height_, \ + TEST_F(LibYUVScaleTest, DISABLED_##I444##name##SwapXY_##filter##_12) { \ + int diff = I444TestFilter_12(benchmark_width_, benchmark_height_, \ benchmark_height_, benchmark_width_, \ kFilter##filter, benchmark_iterations_, \ disable_cpu_flags_, benchmark_cpu_info_); \ @@ -1007,7 +1008,7 @@ TEST_F(LibYUVScaleTest, TestScaleRowDown2Box_16) { } #endif // ENABLE_ROW_TESTS -// Test scaling plane with 8 bit C vs 16 bit C and return maximum pixel +// Test scaling plane with 8 bit C vs 12 bit C and return maximum pixel // difference. // 0 = exact. static int TestPlaneFilter_16(int src_width, diff --git a/unit_test/scale_uv_test.cc b/unit_test/scale_uv_test.cc index e45a25da..59eeee30 100644 --- a/unit_test/scale_uv_test.cc +++ b/unit_test/scale_uv_test.cc @@ -166,6 +166,7 @@ TEST_FACTOR(3, 1, 3) TEST_SCALETO1(name, width, height, Bilinear, 3) TEST_SCALETO(UVScale, 1, 1) +TEST_SCALETO(UVScale, 256, 144) /* 128x72 * 2 */ TEST_SCALETO(UVScale, 320, 240) TEST_SCALETO(UVScale, 569, 480) TEST_SCALETO(UVScale, 640, 360) diff --git a/unit_test/unit_test.cc b/unit_test/unit_test.cc index 58f7f844..85e3b717 100644 --- a/unit_test/unit_test.cc +++ b/unit_test/unit_test.cc @@ -18,9 +18,6 @@ #include "absl/flags/flag.h" #include "absl/flags/parse.h" #endif -#ifdef LIBYUV_USE_BASE_FLAGS -#include "base/commandlineflags.h" -#endif #include "libyuv/cpu_id.h" unsigned int fastrand_seed = 0xfb; diff --git a/util/yuvconstants.c b/util/yuvconstants.c new file mode 100644 index 00000000..037e0824 --- /dev/null +++ b/util/yuvconstants.c @@ -0,0 +1,105 @@ +/* + * Copyright 2021 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include +#include +#include + +// This utility computes values needed to generate yuvconstants based on +// white point values. +// The yuv formulas are tuned for 8 bit YUV channels. + +// See Also +// https://mymusing.co/bt601-yuv-to-rgb-conversion-color/ + +// BT.709 full range YUV to RGB reference +// R = Y + V * 1.5748 +// G = Y - U * 0.18732 - V * 0.46812 +// B = Y + U * 1.8556 +// KR = 0.2126 +// KB = 0.0722 + +// // Y contribution to R,G,B. Scale and bias. +// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ +// #define YB 32 /* 64 / 2 */ +// +// // U and V contributions to R,G,B. +// #define UB 113 /* round(1.77200 * 64) */ +// #define UG 22 /* round(0.34414 * 64) */ +// #define VG 46 /* round(0.71414 * 64) */ +// #define VR 90 /* round(1.40200 * 64) */ +// +// // Bias values to round, and subtract 128 from U and V. +// #define BB (-UB * 128 + YB) +// #define BG (UG * 128 + VG * 128 + YB) +// #define BR (-VR * 128 + YB) + +int main(int argc, const char* argv[]) { + if (argc < 2) { + printf("yuvconstants Kr Kb\n"); + printf(" MC BT KR = 0.2126; KB = 0.0722\n"); + printf(" 1 BT.709 KR = 0.2126; KB = 0.0722\n"); + printf(" 4 FCC KR = 0.30; KB = 0.11\n"); + printf(" 6 BT.601 KR = 0.299; KB = 0.114\n"); + printf(" 7 SMPTE 240M KR = 0.212; KB = 0.087\n"); + printf(" 9 BT.2020 KR = 0.2627; KB = 0.0593\n"); + return -1; + } + float kr = atof(argv[1]); + float kb = atof(argv[2]); + float kg = 1 - kr - kb; + + float vr = 2 * (1 - kr); + float ug = 2 * ((1 - kb) * kb / kg); + float vg = 2 * ((1 - kr) * kr / kg); + float ub = 2 * (1 - kb); + + printf("Full range\n"); + printf("R = Y + V * %5f\n", vr); + printf("G = Y - U * %6f - V * %6f\n", ug, vg); + printf("B = Y + U * %5f\n", ub); + + printf("KR = %4f; ", kr); + printf("KB = %4f\n", kb); + // printf("KG = %4f\n", kg); + // #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ + // #define YB 32 /* 64 / 2 */ + // + // // U and V contributions to R,G,B. + + printf("UB %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ub * 64), ub, ub * 64); + printf("UG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ug * 64), ug, ug * 64); + printf("VG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vg * 64), vg, vg * 64); + printf("VR %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vr * 64), vr, vr * 64); + + vr = 255.f / 224.f * 2 * (1 - kr); + ug = 255.f / 224.f * 2 * ((1 - kb) * kb / kg); + vg = 255.f / 224.f * 2 * ((1 - kr) * kr / kg); + ub = 255.f / 224.f * 2 * (1 - kb); + + printf("\nLimited range\n"); + printf("R = (Y - 16) * 1.164 + V * %5f\n", vr); + printf("G = (Y - 16) * 1.164 - U * %6f - V * %6f\n", ug, vg); + printf("B = (Y - 16) * 1.164 + U * %5f\n", ub); + + // printf("KG = %4f\n", kg); + // #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ + // #define YB 32 /* 64 / 2 */ + // + // // U and V contributions to R,G,B. + + printf("UB %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ub * 64), ub, ub * 64); + printf("UG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ug * 64), ug, ug * 64); + printf("VG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vg * 64), vg, vg * 64); + printf("VR %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vr * 64), vr, vr * 64); + + return 0; +} diff --git a/util/yuvconstants.cc b/util/yuvconstants.cc deleted file mode 100644 index be900878..00000000 --- a/util/yuvconstants.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2021 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include -#include -#include - -// This utility computes values needed to generate yuvconstants based on -// white point values. -// The yuv formulas are tuned for 8 bit YUV channels. - -// See Also -// https://mymusing.co/bt601-yuv-to-rgb-conversion-color/ - -// BT.709 full range YUV to RGB reference -// R = Y + V * 1.5748 -// G = Y - U * 0.18732 - V * 0.46812 -// B = Y + U * 1.8556 -// KR = 0.2126 -// KB = 0.0722 - -// // Y contribution to R,G,B. Scale and bias. -// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ -// #define YB 32 /* 64 / 2 */ -// -// // U and V contributions to R,G,B. -// #define UB 113 /* round(1.77200 * 64) */ -// #define UG 22 /* round(0.34414 * 64) */ -// #define VG 46 /* round(0.71414 * 64) */ -// #define VR 90 /* round(1.40200 * 64) */ -// -// // Bias values to round, and subtract 128 from U and V. -// #define BB (-UB * 128 + YB) -// #define BG (UG * 128 + VG * 128 + YB) -// #define BR (-VR * 128 + YB) - -#define round(v) ((int)(v + 0.5)) - -int main(int argc, const char* argv[]) { - if (argc < 2) { - printf("yuvconstants Kr Kb\n"); - printf(" MC BT KR = 0.2126; KB = 0.0722\n"); - printf(" 1 BT.709 KR = 0.2126; KB = 0.0722\n"); - printf(" 4 FCC KR = 0.30; KB = 0.11\n"); - printf(" 6 BT.601 KR = 0.299; KB = 0.114\n"); - printf(" 7 SMPTE 240M KR = 0.212; KB = 0.087\n"); - printf(" 9 BT.2020 KR = 0.2627; KB = 0.0593\n"); - return -1; - } - float kr = atof(argv[1]); - float kb = atof(argv[2]); - float kg = 1 - kr - kb; - - float vr = 2 * (1 - kr); - float ug = 2 * ((1 - kb) * kb / kg); - float vg = 2 * ((1 - kr) * kr / kg); - float ub = 2 * (1 - kb); - - printf("Full range\n"); - printf("R = Y + V * %5f\n", vr); - printf("G = Y - U * %6f - V * %6f\n", ug, vg); - printf("B = Y + U * %5f\n", ub); - - printf("KR = %4f; ", kr); - printf("KB = %4f\n", kb); - // printf("KG = %4f\n", kg); - // #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ - // #define YB 32 /* 64 / 2 */ - // - // // U and V contributions to R,G,B. - - printf("UB %-3d /* round(%f * 64 = %f) */\n", round(ub * 64), ub, ub * 64); - printf("UG %-3d /* round(%f * 64 = %f) */\n", round(ug * 64), ug, ug * 64); - printf("VG %-3d /* round(%f * 64 = %f) */\n", round(vg * 64), vg, vg * 64); - printf("VR %-3d /* round(%f * 64 = %f) */\n", round(vr * 64), vr, vr * 64); - - vr = 255.f / 224.f * 2 * (1 - kr); - ug = 255.f / 224.f * 2 * ((1 - kb) * kb / kg); - vg = 255.f / 224.f * 2 * ((1 - kr) * kr / kg); - ub = 255.f / 224.f * 2 * (1 - kb); - - printf("\nLimited range\n"); - printf("R = (Y - 16) * 1.164 + V * %5f\n", vr); - printf("G = (Y - 16) * 1.164 - U * %6f - V * %6f\n", ug, vg); - printf("B = (Y - 16) * 1.164 + U * %5f\n", ub); - - // printf("KG = %4f\n", kg); - // #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ - // #define YB 32 /* 64 / 2 */ - // - // // U and V contributions to R,G,B. - - printf("UB %-3d /* round(%f * 64 = %f) */\n", round(ub * 64), ub, ub * 64); - printf("UG %-3d /* round(%f * 64 = %f) */\n", round(ug * 64), ug, ug * 64); - printf("VG %-3d /* round(%f * 64 = %f) */\n", round(vg * 64), vg, vg * 64); - printf("VR %-3d /* round(%f * 64 = %f) */\n", round(vr * 64), vr, vr * 64); - - return 0; -} -- cgit v1.2.3