mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2025-12-07 17:26:49 +08:00
I420ToI010 for 8 to 10 bit YUV conversion.
Convert planar 8 bit formats to planar 16 bit formats. Includes msan fix for Convert8To16Row_Opt unittest. I420 is YUV bt.601 8 bits per channel with 420 subsampling. I010 is YUV bt.601 10 bits per channel with 420 subsampling. I is color space - bt.601. The function does no color space conversion so H420ToI010 is aliased to this function as well. 0 = 420 subsampling. The chroma channels are half width / height. 10 = 10 bits per channel, stored in low 10 bits of 16 bit samples. For SSSE3 version: out/Release/libyuv_unittest --gtest_filter=*LibYUVConvertTest.I420ToI010_Opt --libyuv_width=1280 --libyuv_height=720 --libyuv_repeat=999 --libyuv_flags=-1 --libyuv_cpu_info=-1 [ RUN ] LibYUVConvertTest.I420ToI010_Opt [ OK ] LibYUVConvertTest.I420ToI010_Opt (276 ms) Bug: libyuv:751 Test: LibYUVConvertTest.I420ToI010_Opt Change-Id: I072876ee4fd74a2b74f459b628838bc808f9bdd2 Reviewed-on: https://chromium-review.googlesource.com/846421 Reviewed-by: Miguel Casas <mcasas@chromium.org> Commit-Queue: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
parent
140fc0a261
commit
2ed2402fa0
@ -1,6 +1,6 @@
|
||||
Name: libyuv
|
||||
URL: http://code.google.com/p/libyuv/
|
||||
Version: 1685
|
||||
Version: 1686
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
|
||||
|
||||
@ -97,6 +97,7 @@ int I010Copy(const uint16* src_y,
|
||||
int height);
|
||||
|
||||
// Convert 10 bit YUV to 8 bit
|
||||
#define H010ToH420 I010ToI420
|
||||
LIBYUV_API
|
||||
int I010ToI420(const uint16* src_y,
|
||||
int src_stride_y,
|
||||
|
||||
@ -21,7 +21,22 @@ extern "C" {
|
||||
|
||||
// See Also convert.h for conversions from formats to I420.
|
||||
|
||||
// I420Copy in convert to I420ToI420.
|
||||
// Convert 8 bit YUV to 10 bit.
|
||||
#define H420ToH010 I420ToI010
|
||||
int I420ToI010(const uint8* src_y,
|
||||
int src_stride_y,
|
||||
const uint8* src_u,
|
||||
int src_stride_u,
|
||||
const uint8* src_v,
|
||||
int src_stride_v,
|
||||
uint16* dst_y,
|
||||
int dst_stride_y,
|
||||
uint16* dst_u,
|
||||
int dst_stride_u,
|
||||
uint16* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToI422(const uint8* src_y,
|
||||
|
||||
@ -48,6 +48,15 @@ void Convert16To8Plane(const uint16* src_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
LIBYUV_API
|
||||
void Convert8To16Plane(const uint8* src_y,
|
||||
int src_stride_y,
|
||||
uint16* dst_y,
|
||||
int dst_stride_y,
|
||||
int scale, // 1024 for 10 bits
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Set a plane of data to a 32 bit value.
|
||||
LIBYUV_API
|
||||
void SetPlane(uint8* dst_y,
|
||||
|
||||
@ -11,6 +11,6 @@
|
||||
#ifndef INCLUDE_LIBYUV_VERSION_H_
|
||||
#define INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
#define LIBYUV_VERSION 1685
|
||||
#define LIBYUV_VERSION 1686
|
||||
|
||||
#endif // INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
@ -62,7 +62,7 @@ static int I4xxToI420(const uint8* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy I420 with optional flipping
|
||||
// Copy I420 with optional flipping.
|
||||
// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
|
||||
// is does row coalescing.
|
||||
LIBYUV_API
|
||||
@ -106,7 +106,7 @@ int I420Copy(const uint8* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy I010 with optional flipping
|
||||
// Copy I010 with optional flipping.
|
||||
LIBYUV_API
|
||||
int I010Copy(const uint16* src_y,
|
||||
int src_stride_y,
|
||||
@ -148,7 +148,7 @@ int I010Copy(const uint16* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert 10 bit YUV to 8 bit
|
||||
// Convert 10 bit YUV to 8 bit.
|
||||
LIBYUV_API
|
||||
int I010ToI420(const uint16* src_y,
|
||||
int src_stride_y,
|
||||
|
||||
@ -65,6 +65,50 @@ static int I420ToI4xx(const uint8* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert 8 bit YUV to 10 bit.
|
||||
LIBYUV_API
|
||||
int I420ToI010(const uint8* src_y,
|
||||
int src_stride_y,
|
||||
const uint8* src_u,
|
||||
int src_stride_u,
|
||||
const uint8* src_v,
|
||||
int src_stride_v,
|
||||
uint16* dst_y,
|
||||
int dst_stride_y,
|
||||
uint16* dst_u,
|
||||
int dst_stride_u,
|
||||
uint16* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
if (!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;
|
||||
halfheight = (height + 1) >> 1;
|
||||
src_y = src_y + (height - 1) * src_stride_y;
|
||||
src_u = src_u + (halfheight - 1) * src_stride_u;
|
||||
src_v = src_v + (halfheight - 1) * src_stride_v;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_u = -src_stride_u;
|
||||
src_stride_v = -src_stride_v;
|
||||
}
|
||||
|
||||
// Convert Y plane.
|
||||
Convert8To16Plane(src_y, src_stride_y, dst_y, dst_stride_y, 1024, width,
|
||||
height);
|
||||
// Convert UV planes.
|
||||
Convert8To16Plane(src_u, src_stride_u, dst_u, dst_stride_u, 1024, halfwidth,
|
||||
halfheight);
|
||||
Convert8To16Plane(src_v, src_stride_v, dst_v, dst_stride_v, 1024, halfwidth,
|
||||
halfheight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 420 chroma is 1/2 width, 1/2 height
|
||||
// 422 chroma is 1/2 width, 1x height
|
||||
LIBYUV_API
|
||||
|
||||
@ -163,7 +163,7 @@ void Convert16To8Plane(const uint16* src_y,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy plane
|
||||
// Convert plane
|
||||
for (y = 0; y < height; ++y) {
|
||||
Convert16To8Row(src_y, dst_y, scale, width);
|
||||
src_y += src_stride_y;
|
||||
@ -171,6 +171,56 @@ void Convert16To8Plane(const uint16* src_y,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a plane of 8 bit data to 16 bit
|
||||
LIBYUV_API
|
||||
void Convert8To16Plane(const uint8* src_y,
|
||||
int src_stride_y,
|
||||
uint16* dst_y,
|
||||
int dst_stride_y,
|
||||
int scale, // 16384 for 10 bits
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void (*Convert8To16Row)(const uint8* src_y, uint16* dst_y, int scale,
|
||||
int width) = Convert8To16Row_C;
|
||||
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_y = dst_y + (height - 1) * dst_stride_y;
|
||||
dst_stride_y = -dst_stride_y;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_y == width && dst_stride_y == width) {
|
||||
width *= height;
|
||||
height = 1;
|
||||
src_stride_y = dst_stride_y = 0;
|
||||
}
|
||||
#if defined(HAS_CONVERT8TO16ROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
Convert8To16Row = Convert8To16Row_Any_SSE2;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
Convert8To16Row = Convert8To16Row_SSE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_CONVERT8TO16ROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
Convert8To16Row = Convert8To16Row_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
Convert8To16Row = Convert8To16Row_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Convert plane
|
||||
for (y = 0; y < height; ++y) {
|
||||
Convert8To16Row(src_y, dst_y, scale, width);
|
||||
src_y += src_stride_y;
|
||||
dst_y += dst_stride_y;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy I422.
|
||||
LIBYUV_API
|
||||
int I422Copy(const uint8* src_y,
|
||||
|
||||
@ -146,6 +146,10 @@ TESTPLANARTOP(I422, uint8, 1, 2, 1, I422, uint8, 1, 2, 1)
|
||||
TESTPLANARTOP(I444, uint8, 1, 1, 1, I444, uint8, 1, 1, 1)
|
||||
TESTPLANARTOP(I010, uint16, 2, 2, 2, I010, uint16, 2, 2, 2)
|
||||
TESTPLANARTOP(I010, uint16, 2, 2, 2, I420, uint8, 1, 2, 2)
|
||||
TESTPLANARTOP(I420, uint8, 1, 2, 2, I010, uint16, 2, 2, 2)
|
||||
TESTPLANARTOP(H010, uint16, 2, 2, 2, H010, uint16, 2, 2, 2)
|
||||
TESTPLANARTOP(H010, uint16, 2, 2, 2, H420, uint8, 1, 2, 2)
|
||||
TESTPLANARTOP(H420, uint8, 1, 2, 2, H010, uint16, 2, 2, 2)
|
||||
|
||||
// Test Android 420 to I420
|
||||
#define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \
|
||||
|
||||
@ -2776,6 +2776,38 @@ TEST_F(LibYUVPlanarTest, Convert16To8Row_Opt) {
|
||||
}
|
||||
#endif // HAS_CONVERT16TO8ROW_AVX2
|
||||
|
||||
TEST_F(LibYUVPlanarTest, Convert8To16Plane) {
|
||||
const int kPixels = benchmark_width_ * benchmark_height_;
|
||||
align_buffer_page_end(src_pixels_y, kPixels);
|
||||
align_buffer_page_end(dst_pixels_y_opt, kPixels * 2);
|
||||
align_buffer_page_end(dst_pixels_y_c, kPixels * 2);
|
||||
|
||||
MemRandomize(src_pixels_y, kPixels);
|
||||
memset(dst_pixels_y_opt, 0, kPixels * 2);
|
||||
memset(dst_pixels_y_c, 1, kPixels * 2);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags_);
|
||||
Convert8To16Plane(src_pixels_y, benchmark_width_,
|
||||
reinterpret_cast<uint16*>(dst_pixels_y_c), benchmark_width_,
|
||||
1024, benchmark_width_, benchmark_height_);
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
Convert8To16Plane(src_pixels_y, benchmark_width_,
|
||||
reinterpret_cast<uint16*>(dst_pixels_y_opt),
|
||||
benchmark_width_, 1024, benchmark_width_,
|
||||
benchmark_height_);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kPixels * 2; ++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);
|
||||
}
|
||||
|
||||
// TODO(fbarchard): Improve test for more platforms.
|
||||
#ifdef HAS_CONVERT8TO16ROW_AVX2
|
||||
TEST_F(LibYUVPlanarTest, Convert8To16Row_Opt) {
|
||||
@ -2785,9 +2817,8 @@ TEST_F(LibYUVPlanarTest, Convert8To16Row_Opt) {
|
||||
align_buffer_page_end(dst_pixels_y_c, kPixels * 2);
|
||||
|
||||
MemRandomize(src_pixels_y, kPixels);
|
||||
|
||||
memset(dst_pixels_y_opt, 0, kPixels);
|
||||
memset(dst_pixels_y_c, 1, kPixels);
|
||||
memset(dst_pixels_y_opt, 0, kPixels * 2);
|
||||
memset(dst_pixels_y_c, 1, kPixels * 2);
|
||||
|
||||
Convert8To16Row_C(src_pixels_y, reinterpret_cast<uint16*>(dst_pixels_y_c),
|
||||
1024, kPixels);
|
||||
@ -2810,7 +2841,7 @@ TEST_F(LibYUVPlanarTest, Convert8To16Row_Opt) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kPixels; ++i) {
|
||||
for (int i = 0; i < kPixels * 2; ++i) {
|
||||
EXPECT_EQ(dst_pixels_y_opt[i], dst_pixels_y_c[i]);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user