From f583b1b4b82ef71eba776c3591c82227db615c75 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Murillo Date: Wed, 21 Dec 2022 08:34:00 +0100 Subject: [PATCH] Add I410Copy and I410ToI420 methods The I410To420 implementation does a two step approach for scaling down and 10-to-8 bit conversion using the Y plane as temporal storage. Bug: libyuv:950 Change-Id: I3d35fad4b99e17253230456233fbd947e013c0ec Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4110783 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- README.chromium | 2 +- include/libyuv/convert.h | 17 ++++++++++ include/libyuv/planar_functions.h | 18 ++++++++++ include/libyuv/version.h | 2 +- source/convert.cc | 55 +++++++++++++++++++++++++++++++ source/planar_functions.cc | 39 ++++++++++++++++++++++ unit_test/convert_test.cc | 1 + 7 files changed, 132 insertions(+), 2 deletions(-) diff --git a/README.chromium b/README.chromium index a33b46b93..233036bb4 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1854 +Version: 1855 License: BSD License File: LICENSE diff --git a/include/libyuv/convert.h b/include/libyuv/convert.h index ae9b954f5..85b0338f2 100644 --- a/include/libyuv/convert.h +++ b/include/libyuv/convert.h @@ -299,6 +299,23 @@ int I210ToI422(const uint16_t* src_y, int width, int height); +#define H410ToH420 I410ToI420 +LIBYUV_API +int I410ToI420(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, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + #define H410ToH444 I410ToI444 LIBYUV_API int I410ToI444(const uint16_t* src_y, diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index ffe637056..154f2f213 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -392,6 +392,24 @@ int I210Copy(const uint16_t* src_y, int width, int height); +// Copy I410 to I410. +#define I410ToI410 I410Copy +LIBYUV_API +int I410Copy(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, + 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); + // Copy NV12. Supports inverting. LIBYUV_API int NV12Copy(const uint8_t* src_y, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index c72f74616..efad56b32 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 1854 +#define LIBYUV_VERSION 1855 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/convert.cc b/source/convert.cc index b62e513a6..8b2373ec3 100644 --- a/source/convert.cc +++ b/source/convert.cc @@ -291,6 +291,61 @@ int I210ToI422(const uint16_t* src_y, 0, 10); } +LIBYUV_API +int I410ToI420(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, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height) { + const int depth = 10; + const int scale = 1 << (24 - depth); + + if (width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_y = src_y + (height - 1) * src_stride_y; + src_u = src_u + (height - 1) * src_stride_u; + src_v = src_v + (height - 1) * src_stride_v; + src_stride_y = -src_stride_y; + src_stride_u = -src_stride_u; + src_stride_v = -src_stride_v; + } + + { + const int uv_width = SUBSAMPLE(width, 1, 1); + const int uv_stride = uv_width; + const int uv_height = SUBSAMPLE(height, 1, 1); + + // Scale uv planes using Y plane as temp buffer and then convert to 8 bits. + ScalePlane_12(src_u, src_stride_u, width, height, (uint16_t*)dst_y, + uv_stride, uv_width, uv_height, kFilterBilinear); + Convert16To8Plane((uint16_t*)dst_y, uv_stride, dst_u, dst_stride_u, scale, + uv_width, uv_height); + + ScalePlane_12(src_v, src_stride_v, width, height, (uint16_t*)dst_y, + uv_stride, uv_width, uv_height, kFilterBilinear); + Convert16To8Plane((uint16_t*)dst_y, uv_stride, dst_v, dst_stride_v, scale, + uv_width, uv_height); + + // Convert Y plane last. + Convert16To8Plane(src_y, src_stride_y, dst_y, dst_stride_y, scale, width, + height); + } + return 0; +} + LIBYUV_API int I410ToI444(const uint16_t* src_y, int src_stride_y, diff --git a/source/planar_functions.cc b/source/planar_functions.cc index f43525d57..0df22f7b0 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -333,6 +333,45 @@ int I210Copy(const uint16_t* src_y, return 0; } +// Copy I444. +LIBYUV_API +int I410Copy(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, + 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) { + if ((!src_y && dst_y) || !src_u || !src_v || !dst_u || !dst_v || width <= 0 || + height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_y = src_y + (height - 1) * src_stride_y; + src_u = src_u + (height - 1) * src_stride_u; + src_v = src_v + (height - 1) * src_stride_v; + src_stride_y = -src_stride_y; + src_stride_u = -src_stride_u; + src_stride_v = -src_stride_v; + } + + if (dst_y) { + CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height); + } + CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, width, height); + CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, width, height); + return 0; +} + // Copy I400. LIBYUV_API int I400ToI400(const uint8_t* src_y, diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 89ff99ba6..0d6df1545 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -180,6 +180,7 @@ TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I012, uint16_t, 2, 2, 2, 12) TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I420, uint8_t, 1, 2, 2, 10) TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I420, uint8_t, 1, 2, 2, 10) TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I422, uint8_t, 1, 2, 1, 10) +TESTPLANARTOP(I410, uint16_t, 2, 1, 1, I420, uint8_t, 1, 2, 2, 10) TESTPLANARTOP(I410, uint16_t, 2, 1, 1, I444, uint8_t, 1, 1, 1, 10) TESTPLANARTOP(I012, uint16_t, 2, 2, 2, I420, uint8_t, 1, 2, 2, 12) TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I422, uint8_t, 1, 2, 1, 12)