Commit faa4b14f authored by Frank Barchard's avatar Frank Barchard

uyvy to nv12

R=harryjin@google.com
BUG=libyuv:466

Review URL: https://webrtc-codereview.appspot.com/50339004.
parent faebf89c
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 1446
Version: 1447
License: BSD
License File: LICENSE
......
......@@ -436,6 +436,12 @@ int ARGBSobelXY(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
LIBYUV_API
int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy,
uint8* dst_y, int dst_stride_y,
uint8* dst_uv, int dst_stride_uv,
int width, int height);
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
......@@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1446
#define LIBYUV_VERSION 1447
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
......@@ -2341,6 +2341,112 @@ int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y,
return 0;
}
// TODO(fbarchard): YUY2ToNV12
LIBYUV_API
int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy,
uint8* dst_y, int dst_stride_y,
uint8* dst_uv, int dst_stride_uv,
int width, int height) {
int y;
int halfwidth = (width + 1) >> 1;
void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) =
SplitUVRow_C;
void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_C;
if (!src_uyvy ||
!dst_y || !dst_uv ||
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;
}
#if defined(HAS_SPLITUVROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
SplitUVRow = SplitUVRow_Any_SSE2;
if (IS_ALIGNED(width, 16)) {
SplitUVRow = SplitUVRow_SSE2;
}
}
#endif
#if defined(HAS_SPLITUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
SplitUVRow = SplitUVRow_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
SplitUVRow = SplitUVRow_AVX2;
}
}
#endif
#if defined(HAS_SPLITUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
SplitUVRow = SplitUVRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
SplitUVRow = SplitUVRow_NEON;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
InterpolateRow = InterpolateRow_Any_SSE2;
if (IS_ALIGNED(width, 16)) {
InterpolateRow = InterpolateRow_SSE2;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
InterpolateRow = InterpolateRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
InterpolateRow = InterpolateRow_SSSE3;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
InterpolateRow = InterpolateRow_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
InterpolateRow = InterpolateRow_AVX2;
}
}
#endif
#if defined(HAS_INTERPOLATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
InterpolateRow = InterpolateRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
InterpolateRow = InterpolateRow_NEON;
}
}
#endif
{
int awidth = halfwidth * 2;
// 2 rows of uv
align_buffer_64(rows, awidth * 2);
for (y = 0; y < height - 1; y += 2) {
// Split Y from UV.
SplitUVRow(src_uyvy, rows, dst_y, awidth);
SplitUVRow(src_uyvy + src_stride_uyvy, rows + awidth,
dst_y + dst_stride_y,
awidth);
InterpolateRow(dst_uv, rows, awidth, awidth, 128);
src_uyvy += src_stride_uyvy * 2;
dst_y += dst_stride_y * 2;
dst_uv += dst_stride_uv;
}
if (height & 1) {
// Split Y from UV.
SplitUVRow(src_uyvy, dst_y, dst_uv, width);
}
free_aligned_buffer_64(rows);
}
return 0;
}
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
......@@ -796,6 +796,7 @@ TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) { \
TESTATOBIPLANAR(ARGB, 4, NV12, 2, 2)
TESTATOBIPLANAR(ARGB, 4, NV21, 2, 2)
TESTATOBIPLANAR(UYVY, 2, NV12, 2, 2)
#define TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \
FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \
......@@ -1529,4 +1530,72 @@ TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##Dither##N) { \
TESTPLANARTOBD(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
TEST_F(libyuvTest, TestUYVYToNV12) {
const int kWidth = benchmark_width_;
const int kHeight = benchmark_height_;
align_buffer_64(orig_uyvy,
2 * SUBSAMPLE(kWidth, 2) * kHeight);
align_buffer_64(orig_y, kWidth * kHeight);
align_buffer_64(orig_u,
SUBSAMPLE(kWidth, 2) *
SUBSAMPLE(kHeight, 2));
align_buffer_64(orig_v,
SUBSAMPLE(kWidth, 2) *
SUBSAMPLE(kHeight, 2));
align_buffer_64(dst_y_orig, kWidth * kHeight);
align_buffer_64(dst_uv_orig, 2 *
SUBSAMPLE(kWidth, 2) *
SUBSAMPLE(kHeight, 2));
align_buffer_64(dst_y, kWidth * kHeight);
align_buffer_64(dst_uv, 2 *
SUBSAMPLE(kWidth, 2) *
SUBSAMPLE(kHeight, 2));
srandom(time(NULL));
MemRandomize(orig_uyvy, 2 * SUBSAMPLE(kWidth, 2) * kHeight);
/* Convert UYVY to NV12 in 2 steps for reference */
libyuv::UYVYToI420(orig_uyvy, 2 * SUBSAMPLE(kWidth, 2),
orig_y, kWidth,
orig_u, SUBSAMPLE(kWidth, 2),
orig_v, SUBSAMPLE(kWidth, 2),
kWidth, kHeight);
libyuv::I420ToNV12(orig_y, kWidth,
orig_u, SUBSAMPLE(kWidth, 2),
orig_v, SUBSAMPLE(kWidth, 2),
dst_y_orig, kWidth,
dst_uv_orig, 2 * SUBSAMPLE(kWidth, 2),
kWidth, kHeight);
/* Convert to NV12 */
for (int i = 0; i < benchmark_iterations_; ++i) {
libyuv::UYVYToNV12(orig_uyvy, 2 * SUBSAMPLE(kWidth, 2),
dst_y, kWidth,
dst_uv, 2 * SUBSAMPLE(kWidth, 2),
kWidth, kHeight);
}
for (int i = 0; i < kWidth * kHeight; ++i) {
EXPECT_EQ(orig_y[i], dst_y[i]);
}
for (int i = 0; i < kWidth * kHeight; ++i) {
EXPECT_EQ(dst_y_orig[i], dst_y[i]);
}
for (int i = 0; i < 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2); ++i) {
EXPECT_EQ(dst_uv_orig[i], dst_uv[i]);
}
free_aligned_buffer_64(orig_uyvy);
free_aligned_buffer_64(orig_y);
free_aligned_buffer_64(orig_u);
free_aligned_buffer_64(orig_v);
free_aligned_buffer_64(dst_y_orig);
free_aligned_buffer_64(dst_uv_orig);
free_aligned_buffer_64(dst_y);
free_aligned_buffer_64(dst_uv);
}
} // namespace libyuv
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment