From d5aa3d4a76930cde9527f5be5bc89524b48fc069 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Fri, 13 Jan 2023 10:05:00 -0800 Subject: [PATCH] P010ToI010 and P012ToI012 conversion functions - Convert 10 and 12 bit biplanar formats to planar. - Shift 10 MSB to 10 LSB - P010 is similar to NV12 in layout, but uses 10 MSB of 16 bit values. - I010 is similar to I420 in layout, but uses 10 LSB of 16 bit values. Bug: libyuv:951 Change-Id: I16a1bc64239d0fa4f41810910da448bf5720935f Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4166560 Reviewed-by: Justin Green Commit-Queue: Frank Barchard --- README.chromium | 2 +- include/libyuv/convert.h | 30 ++++++++++++++++++ include/libyuv/version.h | 2 +- source/convert.cc | 66 +++++++++++++++++++++++++++++++++++++++ unit_test/convert_test.cc | 3 ++ 5 files changed, 101 insertions(+), 2 deletions(-) diff --git a/README.chromium b/README.chromium index 08afafbad..77eac367f 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1856 +Version: 1857 License: BSD License File: LICENSE diff --git a/include/libyuv/convert.h b/include/libyuv/convert.h index 85b0338f2..2f1ce4214 100644 --- a/include/libyuv/convert.h +++ b/include/libyuv/convert.h @@ -604,6 +604,36 @@ int NV16ToNV24(const uint8_t* src_y, int width, int height); +// Convert P010 to I010. +LIBYUV_API +int P010ToI010(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_uv, + int src_stride_uv, + 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 width, + int height); + +// Convert P012 to I012. +LIBYUV_API +int P012ToI012(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_uv, + int src_stride_uv, + 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 width, + int height); + // Convert P010 to P410. LIBYUV_API int P010ToP410(const uint16_t* src_y, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index dfcef8d8f..adc49c4e4 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 1856 +#define LIBYUV_VERSION 1857 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/convert.cc b/source/convert.cc index d88efce08..a41974a2a 100644 --- a/source/convert.cc +++ b/source/convert.cc @@ -24,6 +24,7 @@ namespace libyuv { extern "C" { #endif +// subsample amount uses a shift. #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) static __inline int Abs(int v) { return v >= 0 ? v : -v; @@ -1269,6 +1270,71 @@ int NV16ToNV24(const uint8_t* src_y, return 0; } +// Any P[420]1[02] to I[420]1[02] format with mirroring. +static int PxxxToIxxx(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_uv, + int src_stride_uv, + 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 width, + int height, + int subsample_x, + int subsample_y, + int depth) { + const int uv_width = SUBSAMPLE(width, subsample_x, subsample_x); + const int uv_height = SUBSAMPLE(height, subsample_y, subsample_y); + if (width <= 0 || height == 0) { + return -1; + } + + ConvertToLSBPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height, + depth); + SplitUVPlane_16(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v, + dst_stride_v, uv_width, uv_height, depth); + return 0; +} + +LIBYUV_API +int P010ToI010(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_uv, + int src_stride_uv, + 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 width, + int height) { + return PxxxToIxxx(src_y, src_stride_y, src_uv, src_stride_uv, dst_y, + dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, + width, height, 1, 1, 10); +} + +LIBYUV_API +int P012ToI012(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_uv, + int src_stride_uv, + 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 width, + int height) { + return PxxxToIxxx(src_y, src_stride_y, src_uv, src_stride_uv, dst_y, + dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, + width, height, 1, 1, 12); +} + LIBYUV_API int P010ToP410(const uint16_t* src_y, int src_stride_y, diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 0d6df1545..f94a7d31c 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -48,6 +48,7 @@ namespace libyuv { #define AR30ToAR30 ARGBCopy #define ABGRToABGR ARGBCopy +// subsample amount uses a divide. #define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a)) // Planar test @@ -649,6 +650,8 @@ TESTBPTOBP(MT2T, uint8_t, 10 / 8, 2, 2, P010, uint16_t, 2, 2, 2, 10, 16, 32) TESTBPTOP(NV12, uint8_t, 1, 2, 2, I420, uint8_t, 1, 2, 2, 8, 1, 1) TESTBPTOP(NV21, uint8_t, 1, 2, 2, I420, uint8_t, 1, 2, 2, 8, 1, 1) TESTBPTOP(MM21, uint8_t, 1, 2, 2, I420, uint8_t, 1, 2, 2, 8, 16, 32) +TESTBPTOP(P010, uint16_t, 2, 2, 2, I010, uint16_t, 2, 2, 2, 10, 1, 1) +TESTBPTOP(P012, uint16_t, 2, 2, 2, I012, uint16_t, 2, 2, 2, 12, 1, 1) // Provide matrix wrappers for full range bt.709 #define F420ToABGR(a, b, c, d, e, f, g, h, i, j) \