diff --git a/README.chromium b/README.chromium index 4ff4ea445..4a7e30b08 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1767 +Version: 1768 License: BSD License File: LICENSE diff --git a/include/libyuv.h b/include/libyuv.h index aeffd5ef7..a06e1233a 100644 --- a/include/libyuv.h +++ b/include/libyuv.h @@ -26,6 +26,7 @@ #include "libyuv/scale.h" #include "libyuv/scale_argb.h" #include "libyuv/scale_row.h" +#include "libyuv/scale_uv.h" #include "libyuv/version.h" #include "libyuv/video_common.h" diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 9e0038f47..8d868b954 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -200,6 +200,16 @@ int I444Copy(const uint8_t* src_y, int width, int height); +// Copy NV12. Supports inverting. +int NV12Copy(const uint8_t* src_y, int src_stride_y, const uint8_t* src_uv, + int src_stride_uv, uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_uv, int dst_stride_uv, int width, int height); + +// Copy NV21. Supports inverting. +int NV21Copy(const uint8_t* src_y, int src_stride_y, const uint8_t* src_vu, + int src_stride_vu, uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_vu, int dst_stride_vu, int width, int height); + // Convert YUY2 to I422. LIBYUV_API int YUY2ToI422(const uint8_t* src_yuy2, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 1d085960e..efaac73e3 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 1767 +#define LIBYUV_VERSION 1768 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/planar_functions.cc b/source/planar_functions.cc index d5cd7e680..4e8908c2e 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -349,6 +349,39 @@ int I420ToI400(const uint8_t* src_y, return 0; } +// Copy NV12. Supports inverting. +int NV12Copy(const uint8_t* src_y, int src_stride_y, const uint8_t* src_uv, + int src_stride_uv, uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_uv, int dst_stride_uv, int width, int height) { + if (!src_y || !dst_y || !src_uv || !dst_uv || width <= 0 || height == 0) { + return -1; + } + + int halfwidth = (width + 1) >> 1; + int halfheight = (height + 1) >> 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_uv = src_uv + (halfheight - 1) * src_stride_uv; + src_stride_y = -src_stride_y; + src_stride_uv = -src_stride_uv; + } + CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); + CopyPlane(src_uv, src_stride_uv, dst_uv, dst_stride_uv, halfwidth * 2, + halfheight); + return 0; +} + +// Copy NV21. Supports inverting. +int NV21Copy(const uint8_t* src_y, int src_stride_y, const uint8_t* src_vu, + int src_stride_vu, uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_vu, int dst_stride_vu, int width, int height) { + return NV12Copy(src_y, src_stride_y, src_vu, src_stride_vu, dst_y, + dst_stride_y, dst_vu, dst_stride_vu, width, height); +} + // Support function for NV12 etc UV channels. // Width and height are plane sizes (typically half pixel width). LIBYUV_API diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 65aa46e0d..e05ff1564 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -3562,4 +3562,68 @@ TEST_F(LibYUVPlanarTest, HalfMergeUVPlane_Opt) { free_aligned_buffer_page_end(dst_pixels_uv_c); } +TEST_F(LibYUVPlanarTest, NV12Copy) { + const int halfwidth = (benchmark_width_ + 1) >> 1; + const int halfheight = (benchmark_height_ + 1) >> 1; + align_buffer_page_end(src_y, benchmark_width_ * benchmark_height_); + align_buffer_page_end(src_uv, halfwidth * 2 * halfheight); + align_buffer_page_end(dst_y, benchmark_width_ * benchmark_height_); + align_buffer_page_end(dst_uv, halfwidth * 2 * halfheight); + + MemRandomize(src_y, benchmark_width_ * benchmark_height_); + MemRandomize(src_uv, halfwidth * 2 * halfheight); + MemRandomize(dst_y, benchmark_width_ * benchmark_height_); + MemRandomize(dst_uv, halfwidth * 2 * halfheight); + + for (int i = 0; i < benchmark_iterations_; ++i) { + NV12Copy(src_y, benchmark_width_, src_uv, halfwidth * 2, dst_y, + benchmark_width_, dst_uv, halfwidth * 2, benchmark_width_, + benchmark_height_); + } + + for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) { + EXPECT_EQ(src_y[i], dst_y[i]); + } + for (int i = 0; i < halfwidth * 2 * halfheight; ++i) { + EXPECT_EQ(src_uv[i], dst_uv[i]); + } + + free_aligned_buffer_page_end(src_y); + free_aligned_buffer_page_end(src_uv); + free_aligned_buffer_page_end(dst_y); + free_aligned_buffer_page_end(dst_uv); +} + +TEST_F(LibYUVPlanarTest, NV21Copy) { + const int halfwidth = (benchmark_width_ + 1) >> 1; + const int halfheight = (benchmark_height_ + 1) >> 1; + align_buffer_page_end(src_y, benchmark_width_ * benchmark_height_); + align_buffer_page_end(src_vu, halfwidth * 2 * halfheight); + align_buffer_page_end(dst_y, benchmark_width_ * benchmark_height_); + align_buffer_page_end(dst_vu, halfwidth * 2 * halfheight); + + MemRandomize(src_y, benchmark_width_ * benchmark_height_); + MemRandomize(src_vu, halfwidth * 2 * halfheight); + MemRandomize(dst_y, benchmark_width_ * benchmark_height_); + MemRandomize(dst_vu, halfwidth * 2 * halfheight); + + for (int i = 0; i < benchmark_iterations_; ++i) { + NV21Copy(src_y, benchmark_width_, src_vu, halfwidth * 2, dst_y, + benchmark_width_, dst_vu, halfwidth * 2, benchmark_width_, + benchmark_height_); + } + + for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) { + EXPECT_EQ(src_y[i], dst_y[i]); + } + for (int i = 0; i < halfwidth * 2 * halfheight; ++i) { + EXPECT_EQ(src_vu[i], dst_vu[i]); + } + + free_aligned_buffer_page_end(src_y); + free_aligned_buffer_page_end(src_vu); + free_aligned_buffer_page_end(dst_y); + free_aligned_buffer_page_end(dst_vu); +} + } // namespace libyuv diff --git a/winarm.mk b/winarm.mk index c4307a431..b0a344ae0 100644 --- a/winarm.mk +++ b/winarm.mk @@ -31,6 +31,7 @@ LOCAL_OBJ_FILES = \ source/scale_any.o\ source/scale_argb.o\ source/scale_common.o\ + source/scale_uv.o\ source/video_common.o .cc.o: