Add UYVYToY function

This function reads 2 byte values and writes the 2nd byte to the destination.
It turns out this is useful for P010ToNV12 as well, so adding the planar function allows a high level to call this.
And adds UYVY support for something YUY2 already had.  Which is writing the 1st byte.

Bug: b/233233302, b/233634772
Change-Id: I10a9454cb4f5b2c4ac5532fa86feddf78284d8b8
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/3659055
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
Frank Barchard 2022-05-23 11:12:25 -07:00 committed by libyuv LUCI CQ
parent 966768e899
commit 715150b5aa
7 changed files with 164 additions and 7 deletions

View File

@ -27,10 +27,6 @@ config("libyuv_config") {
if (is_android && current_cpu != "arm64") {
ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker" ]
}
if (!libyuv_use_neon) {
defines = [ "LIBYUV_DISABLE_NEON" ]
}
}
# This target is built when no specific target is specified on the command line.

1
OWNERS
View File

@ -1,7 +1,6 @@
mbonadei@chromium.org
fbarchard@chromium.org
magjed@chromium.org
pbos@chromium.org
per-file *.gn=mbonadei@chromium.org
per-file .gitignore=*

View File

@ -1,6 +1,6 @@
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 1823
Version: 1824
License: BSD
License File: LICENSE

View File

@ -461,6 +461,14 @@ int YUY2ToY(const uint8_t* src_yuy2,
int width,
int height);
LIBYUV_API
int UYVYToY(const uint8_t* src_uyvy,
int src_stride_uyvy,
uint8_t* dst_y,
int dst_stride_y,
int width,
int height);
// Convert I420 to I400. (calls CopyPlane ignoring u/v).
LIBYUV_API
int I420ToI400(const uint8_t* src_y,

View File

@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1823
#define LIBYUV_VERSION 1824
#endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -2053,6 +2053,73 @@ int YUY2ToY(const uint8_t* src_yuy2,
return 0;
}
// Convert UYVY to Y.
LIBYUV_API
int UYVYToY(const uint8_t* src_uyvy,
int src_stride_uyvy,
uint8_t* dst_y,
int dst_stride_y,
int width,
int height) {
int y;
void (*UYVYToYRow)(const uint8_t* src_uyvy, uint8_t* dst_y, int width) =
UYVYToYRow_C;
if (!src_uyvy || !dst_y || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
src_stride_uyvy = -src_stride_uyvy;
}
// Coalesce rows.
if (src_stride_uyvy == width * 2 && dst_stride_y == width) {
width *= height;
height = 1;
src_stride_uyvy = dst_stride_y = 0;
}
#if defined(HAS_UYVYTOYROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
UYVYToYRow = UYVYToYRow_Any_SSE2;
if (IS_ALIGNED(width, 16)) {
UYVYToYRow = UYVYToYRow_SSE2;
}
}
#endif
#if defined(HAS_UYVYTOYROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
UYVYToYRow = UYVYToYRow_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
UYVYToYRow = UYVYToYRow_AVX2;
}
}
#endif
#if defined(HAS_UYVYTOYROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
UYVYToYRow = UYVYToYRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
UYVYToYRow = UYVYToYRow_NEON;
}
}
#endif
#if defined(HAS_UYVYTOYROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
UYVYToYRow = UYVYToYRow_Any_MSA;
if (IS_ALIGNED(width, 32)) {
UYVYToYRow = UYVYToYRow_MSA;
}
}
#endif
for (y = 0; y < height; ++y) {
UYVYToYRow(src_uyvy, dst_y, width);
src_uyvy += src_stride_uyvy;
dst_y += dst_stride_y;
}
return 0;
}
// Mirror a plane of data.
// See Also I400Mirror
LIBYUV_API

View File

@ -3463,6 +3463,64 @@ TEST_F(LibYUVPlanarTest, Convert16To8Plane) {
free_aligned_buffer_page_end(dst_pixels_y_c);
}
TEST_F(LibYUVPlanarTest, YUY2ToY) {
const int kPixels = benchmark_width_ * benchmark_height_;
align_buffer_page_end(src_pixels_y, kPixels * 2);
align_buffer_page_end(dst_pixels_y_opt, kPixels);
align_buffer_page_end(dst_pixels_y_c, kPixels);
MemRandomize(src_pixels_y, kPixels * 2);
memset(dst_pixels_y_opt, 0, kPixels);
memset(dst_pixels_y_c, 1, kPixels);
MaskCpuFlags(disable_cpu_flags_);
YUY2ToY(src_pixels_y, benchmark_width_ * 2, dst_pixels_y_c,
benchmark_width_, benchmark_width_, benchmark_height_);
MaskCpuFlags(benchmark_cpu_info_);
for (int i = 0; i < benchmark_iterations_; ++i) {
YUY2ToY(src_pixels_y, benchmark_width_ * 2, dst_pixels_y_opt,
benchmark_width_, benchmark_width_, benchmark_height_);
}
for (int i = 0; i < kPixels; ++i) {
EXPECT_EQ(dst_pixels_y_opt[i], dst_pixels_y_c[i]);
}
free_aligned_buffer_page_end(src_pixels_y);
free_aligned_buffer_page_end(dst_pixels_y_opt);
free_aligned_buffer_page_end(dst_pixels_y_c);
}
TEST_F(LibYUVPlanarTest, UYVYToY) {
const int kPixels = benchmark_width_ * benchmark_height_;
align_buffer_page_end(src_pixels_y, kPixels * 2);
align_buffer_page_end(dst_pixels_y_opt, kPixels);
align_buffer_page_end(dst_pixels_y_c, kPixels);
MemRandomize(src_pixels_y, kPixels * 2);
memset(dst_pixels_y_opt, 0, kPixels);
memset(dst_pixels_y_c, 1, kPixels);
MaskCpuFlags(disable_cpu_flags_);
UYVYToY(src_pixels_y, benchmark_width_ * 2, dst_pixels_y_c,
benchmark_width_, benchmark_width_, benchmark_height_);
MaskCpuFlags(benchmark_cpu_info_);
for (int i = 0; i < benchmark_iterations_; ++i) {
UYVYToY(src_pixels_y, benchmark_width_ * 2, dst_pixels_y_opt,
benchmark_width_, benchmark_width_, benchmark_height_);
}
for (int i = 0; i < kPixels; ++i) {
EXPECT_EQ(dst_pixels_y_opt[i], dst_pixels_y_c[i]);
}
free_aligned_buffer_page_end(src_pixels_y);
free_aligned_buffer_page_end(dst_pixels_y_opt);
free_aligned_buffer_page_end(dst_pixels_y_c);
}
#ifdef ENABLE_ROW_TESTS
// TODO(fbarchard): Improve test for more platforms.
#ifdef HAS_CONVERT16TO8ROW_AVX2
@ -3509,6 +3567,35 @@ TEST_F(LibYUVPlanarTest, Convert16To8Row_Opt) {
free_aligned_buffer_page_end(dst_pixels_y_c);
}
#endif // HAS_CONVERT16TO8ROW_AVX2
#ifdef HAS_UYVYTOYROW_NEON
TEST_F(LibYUVPlanarTest, UYVYToYRow_Opt) {
// NEON does multiple of 16, so round count up
const int kPixels = (benchmark_width_ * benchmark_height_ + 15) & ~15;
align_buffer_page_end(src_pixels_y, kPixels * 2);
align_buffer_page_end(dst_pixels_y_opt, kPixels);
align_buffer_page_end(dst_pixels_y_c, kPixels);
MemRandomize(src_pixels_y, kPixels * 2);
memset(dst_pixels_y_opt, 0, kPixels);
memset(dst_pixels_y_c, 1, kPixels);
UYVYToYRow_C(src_pixels_y, dst_pixels_y_c, kPixels);
for (int i = 0; i < benchmark_iterations_; ++i) {
UYVYToYRow_NEON(src_pixels_y, dst_pixels_y_opt, kPixels);
}
for (int i = 0; i < kPixels; ++i) {
EXPECT_EQ(dst_pixels_y_opt[i], dst_pixels_y_c[i]);
}
free_aligned_buffer_page_end(src_pixels_y);
free_aligned_buffer_page_end(dst_pixels_y_opt);
free_aligned_buffer_page_end(dst_pixels_y_c);
}
#endif // HAS_UYVYTOYROW_NEON
#endif // ENABLE_ROW_TESTS
TEST_F(LibYUVPlanarTest, Convert8To16Plane) {