MJPGToNV12 added and build files sorted

Bug: None
Change-Id: I87aa64a14bb3f0785f984f492e56fcf2313431ce
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2502780
Reviewed-by: Evan Shrubsole <eshr@google.com>
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
Frank Barchard 2020-10-27 09:39:59 -07:00 committed by Commit Bot
parent 19d71f6b35
commit 5c4dc242f4
7 changed files with 352 additions and 34 deletions

View File

@ -9,17 +9,20 @@ cc_library {
"source/compare.cc",
"source/compare_common.cc",
"source/compare_gcc.cc",
"source/compare_neon.cc",
"source/compare_neon64.cc",
"source/compare_mmi.cc",
"source/compare_msa.cc",
"source/compare_neon.cc",
"source/compare_neon64.cc",
"source/convert.cc",
"source/convert_argb.cc",
"source/convert_from.cc",
"source/convert_from_argb.cc",
"source/convert_jpeg.cc",
"source/convert_to_argb.cc",
"source/convert_to_i420.cc",
"source/cpu_id.cc",
"source/mjpeg_decoder.cc",
"source/mjpeg_validate.cc",
"source/planar_functions.cc",
"source/rotate.cc",
"source/rotate_any.cc",
@ -40,17 +43,14 @@ cc_library {
"source/scale.cc",
"source/scale_any.cc",
"source/scale_argb.cc",
"source/scale_uv.cc",
"source/scale_common.cc",
"source/scale_gcc.cc",
"source/scale_mmi.cc",
"source/scale_msa.cc",
"source/scale_neon.cc",
"source/scale_neon64.cc",
"source/scale_uv.cc",
"source/video_common.cc",
"source/convert_jpeg.cc",
"source/mjpeg_decoder.cc",
"source/mjpeg_validate.cc",
],
cflags: [
@ -80,7 +80,6 @@ cc_test {
shared_libs: ["libjpeg"],
cflags: ["-Wall", "-Werror"],
srcs: [
"unit_test/unit_test.cc",
"unit_test/basictypes_test.cc",
"unit_test/color_test.cc",
"unit_test/compare_test.cc",
@ -92,8 +91,9 @@ cc_test {
"unit_test/rotate_argb_test.cc",
"unit_test/rotate_test.cc",
"unit_test/scale_argb_test.cc",
"unit_test/scale_uv_test.cc",
"unit_test/scale_test.cc",
"unit_test/scale_uv_test.cc",
"unit_test/unit_test.cc",
"unit_test/video_common_test.cc",
],
}

View File

@ -11,45 +11,45 @@ LOCAL_SRC_FILES := \
source/compare_gcc.cc \
source/compare_mmi.cc \
source/compare_msa.cc \
source/compare_neon64.cc \
source/compare_neon.cc \
source/compare_neon64.cc \
source/compare_win.cc \
source/convert_argb.cc \
source/convert.cc \
source/convert_from_argb.cc \
source/convert_argb.cc \
source/convert_from.cc \
source/convert_from_argb.cc \
source/convert_to_argb.cc \
source/convert_to_i420.cc \
source/cpu_id.cc \
source/planar_functions.cc \
source/rotate.cc \
source/rotate_any.cc \
source/rotate_argb.cc \
source/rotate.cc \
source/rotate_common.cc \
source/rotate_gcc.cc \
source/rotate_mmi.cc \
source/rotate_msa.cc \
source/rotate_neon64.cc \
source/rotate_neon.cc \
source/rotate_neon64.cc \
source/rotate_win.cc \
source/row_any.cc \
source/row_common.cc \
source/row_gcc.cc \
source/row_mmi.cc \
source/row_msa.cc \
source/row_neon64.cc \
source/row_neon.cc \
source/row_neon64.cc \
source/row_win.cc \
source/scale.cc \
source/scale_any.cc \
source/scale_argb.cc \
source/scale_uv.cc \
source/scale.cc \
source/scale_common.cc \
source/scale_gcc.cc \
source/scale_mmi.cc \
source/scale_msa.cc \
source/scale_neon64.cc \
source/scale_neon.cc \
source/scale_neon64.cc \
source/scale_uv.cc \
source/scale_win.cc \
source/video_common.cc
@ -90,7 +90,6 @@ LOCAL_MODULE_TAGS := tests
LOCAL_CPP_EXTENSION := .cc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
unit_test/unit_test.cc \
unit_test/basictypes_test.cc \
unit_test/color_test.cc \
unit_test/compare_test.cc \
@ -102,8 +101,9 @@ LOCAL_SRC_FILES := \
unit_test/rotate_argb_test.cc \
unit_test/rotate_test.cc \
unit_test/scale_argb_test.cc \
unit_test/scale_uv_test.cc \
unit_test/scale_test.cc \
unit_test/scale_uv_test.cc \
unit_test/unit_test.cc \
unit_test/video_common_test.cc
LOCAL_MODULE := libyuv_unittest

View File

@ -97,8 +97,8 @@ static_library("libyuv_internal") {
"include/libyuv/row.h",
"include/libyuv/scale.h",
"include/libyuv/scale_argb.h",
"include/libyuv/scale_uv.h",
"include/libyuv/scale_row.h",
"include/libyuv/scale_uv.h",
"include/libyuv/version.h",
"include/libyuv/video_common.h",
@ -131,9 +131,9 @@ static_library("libyuv_internal") {
"source/scale.cc",
"source/scale_any.cc",
"source/scale_argb.cc",
"source/scale_uv.cc",
"source/scale_common.cc",
"source/scale_gcc.cc",
"source/scale_uv.cc",
"source/scale_win.cc",
"source/video_common.cc",
]
@ -280,8 +280,8 @@ if (libyuv_include_tests) {
"unit_test/rotate_argb_test.cc",
"unit_test/rotate_test.cc",
"unit_test/scale_argb_test.cc",
"unit_test/scale_uv_test.cc",
"unit_test/scale_test.cc",
"unit_test/scale_uv_test.cc",
"unit_test/unit_test.cc",
"unit_test/unit_test.h",
"unit_test/video_common_test.cc",
@ -376,9 +376,7 @@ if (libyuv_include_tests) {
# sources
"util/i444tonv12_eg.cc",
]
deps = [
":libyuv",
]
deps = [ ":libyuv" ]
}
executable("cpuid") {

View File

@ -458,6 +458,12 @@ int MJPGToNV21(const uint8_t* sample,
int dst_width,
int dst_height);
// JPEG to NV12
LIBYUV_API
int MJPGToNV12(const uint8_t* sample, size_t sample_size, uint8_t* dst_y,
int dst_stride_y, uint8_t* dst_uv, int dst_stride_uv,
int src_width, int src_height, int dst_width, int dst_height);
// Query size of MJPG in pixels.
LIBYUV_API
int MJPGSize(const uint8_t* sample,

View File

@ -15,13 +15,13 @@ LOCAL_OBJ_FILES := \
source/compare_gcc.o \
source/compare_mmi.o \
source/compare_msa.o \
source/compare_neon64.o \
source/compare_neon.o \
source/compare_neon64.o \
source/compare_win.o \
source/convert_argb.o \
source/convert.o \
source/convert_from_argb.o \
source/convert_argb.o \
source/convert_from.o \
source/convert_from_argb.o \
source/convert_jpeg.o \
source/convert_to_argb.o \
source/convert_to_i420.o \
@ -29,34 +29,34 @@ LOCAL_OBJ_FILES := \
source/mjpeg_decoder.o \
source/mjpeg_validate.o \
source/planar_functions.o \
source/rotate.o \
source/rotate_any.o \
source/rotate_argb.o \
source/rotate.o \
source/rotate_common.o \
source/rotate_gcc.o \
source/rotate_mmi.o \
source/rotate_msa.o \
source/rotate_neon64.o \
source/rotate_neon.o \
source/rotate_neon64.o \
source/rotate_win.o \
source/row_any.o \
source/row_common.o \
source/row_gcc.o \
source/row_mmi.o \
source/row_msa.o \
source/row_neon64.o \
source/row_neon.o \
source/row_neon64.o \
source/row_win.o \
source/scale.o \
source/scale_any.o \
source/scale_argb.o \
source/scale_uv.o \
source/scale.o \
source/scale_common.o \
source/scale_gcc.o \
source/scale_mmi.o \
source/scale_msa.o \
source/scale_neon64.o \
source/scale_neon.o \
source/scale_neon64.o \
source/scale_uv.o \
source/scale_win.o \
source/video_common.o

View File

@ -328,6 +328,125 @@ int MJPGToNV21(const uint8_t* src_mjpg,
return ret ? 0 : 1;
}
static void JpegI420ToNV12(void* opaque, const uint8_t* const* data,
const int* strides, int rows) {
NV21Buffers* dest = (NV21Buffers*)(opaque);
// Use NV21 with VU swapped.
I420ToNV21(data[0], strides[0], data[2], strides[2], data[1], strides[1],
dest->y, dest->y_stride, dest->vu, dest->vu_stride, dest->w, rows);
dest->y += rows * dest->y_stride;
dest->vu += ((rows + 1) >> 1) * dest->vu_stride;
dest->h -= rows;
}
static void JpegI422ToNV12(void* opaque, const uint8_t* const* data,
const int* strides, int rows) {
NV21Buffers* dest = (NV21Buffers*)(opaque);
// Use NV21 with VU swapped.
I422ToNV21(data[0], strides[0], data[2], strides[2], data[1], strides[1],
dest->y, dest->y_stride, dest->vu, dest->vu_stride, dest->w, rows);
dest->y += rows * dest->y_stride;
dest->vu += ((rows + 1) >> 1) * dest->vu_stride;
dest->h -= rows;
}
static void JpegI444ToNV12(void* opaque, const uint8_t* const* data,
const int* strides, int rows) {
NV21Buffers* dest = (NV21Buffers*)(opaque);
// Use NV21 with VU swapped.
I444ToNV21(data[0], strides[0], data[2], strides[2], data[1], strides[1],
dest->y, dest->y_stride, dest->vu, dest->vu_stride, dest->w, rows);
dest->y += rows * dest->y_stride;
dest->vu += ((rows + 1) >> 1) * dest->vu_stride;
dest->h -= rows;
}
static void JpegI400ToNV12(void* opaque, const uint8_t* const* data,
const int* strides, int rows) {
NV21Buffers* dest = (NV21Buffers*)(opaque);
// Use NV21 since there is no UV plane.
I400ToNV21(data[0], strides[0], dest->y, dest->y_stride, dest->vu,
dest->vu_stride, dest->w, rows);
dest->y += rows * dest->y_stride;
dest->vu += ((rows + 1) >> 1) * dest->vu_stride;
dest->h -= rows;
}
// MJPG (Motion JPEG) to NV12.
LIBYUV_API
int MJPGToNV12(const uint8_t* sample, size_t sample_size, uint8_t* dst_y,
int dst_stride_y, uint8_t* dst_uv, int dst_stride_uv,
int src_width, int src_height, int dst_width, int dst_height) {
if (sample_size == kUnknownDataSize) {
// ERROR: MJPEG frame size unknown
return -1;
}
// TODO(fbarchard): Port MJpeg to C.
MJpegDecoder mjpeg_decoder;
LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
if (ret && (mjpeg_decoder.GetWidth() != src_width ||
mjpeg_decoder.GetHeight() != src_height)) {
// ERROR: MJPEG frame has unexpected dimensions
mjpeg_decoder.UnloadFrame();
return 1; // runtime failure
}
if (ret) {
// Use NV21Buffers but with UV instead of VU.
NV21Buffers bufs = {dst_y, dst_stride_y, dst_uv,
dst_stride_uv, dst_width, dst_height};
// YUV420
if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
mjpeg_decoder.GetNumComponents() == 3 &&
mjpeg_decoder.GetVertSampFactor(0) == 2 &&
mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
mjpeg_decoder.GetVertSampFactor(1) == 1 &&
mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
mjpeg_decoder.GetVertSampFactor(2) == 1 &&
mjpeg_decoder.GetHorizSampFactor(2) == 1) {
ret = mjpeg_decoder.DecodeToCallback(&JpegI420ToNV12, &bufs, dst_width,
dst_height);
// YUV422
} else if (mjpeg_decoder.GetColorSpace() ==
MJpegDecoder::kColorSpaceYCbCr &&
mjpeg_decoder.GetNumComponents() == 3 &&
mjpeg_decoder.GetVertSampFactor(0) == 1 &&
mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
mjpeg_decoder.GetVertSampFactor(1) == 1 &&
mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
mjpeg_decoder.GetVertSampFactor(2) == 1 &&
mjpeg_decoder.GetHorizSampFactor(2) == 1) {
ret = mjpeg_decoder.DecodeToCallback(&JpegI422ToNV12, &bufs, dst_width,
dst_height);
// YUV444
} else if (mjpeg_decoder.GetColorSpace() ==
MJpegDecoder::kColorSpaceYCbCr &&
mjpeg_decoder.GetNumComponents() == 3 &&
mjpeg_decoder.GetVertSampFactor(0) == 1 &&
mjpeg_decoder.GetHorizSampFactor(0) == 1 &&
mjpeg_decoder.GetVertSampFactor(1) == 1 &&
mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
mjpeg_decoder.GetVertSampFactor(2) == 1 &&
mjpeg_decoder.GetHorizSampFactor(2) == 1) {
ret = mjpeg_decoder.DecodeToCallback(&JpegI444ToNV12, &bufs, dst_width,
dst_height);
// YUV400
} else if (mjpeg_decoder.GetColorSpace() ==
MJpegDecoder::kColorSpaceGrayscale &&
mjpeg_decoder.GetNumComponents() == 1 &&
mjpeg_decoder.GetVertSampFactor(0) == 1 &&
mjpeg_decoder.GetHorizSampFactor(0) == 1) {
ret = mjpeg_decoder.DecodeToCallback(&JpegI400ToNV12, &bufs, dst_width,
dst_height);
} else {
// Unknown colorspace.
mjpeg_decoder.UnloadFrame();
return 1;
}
}
return ret ? 0 : 1;
}
struct ARGBBuffers {
uint8_t* argb;
int argb_stride;

View File

@ -1810,6 +1810,65 @@ TEST_F(LibYUVConvertTest, TestMJPGToI420_NV21) {
free_aligned_buffer_page_end(dst_vu);
}
TEST_F(LibYUVConvertTest, TestMJPGToI420_NV12) {
int width = 0;
int height = 0;
int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
EXPECT_EQ(0, ret);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
benchmark_height_ / (width * height);
// Convert to NV12
align_buffer_page_end(dst_y, width * height);
align_buffer_page_end(dst_uv, half_width * half_height * 2);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToNV12(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
half_width * 2, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Convert to I420
align_buffer_page_end(dst2_y, width * height);
align_buffer_page_end(dst2_u, half_width * half_height);
align_buffer_page_end(dst2_v, half_width * half_height);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst2_y, width, dst2_u, half_width,
dst2_v, half_width, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Convert I420 to NV12
align_buffer_page_end(dst3_y, width * height);
align_buffer_page_end(dst3_uv, half_width * half_height * 2);
I420ToNV12(dst2_y, width, dst2_u, half_width, dst2_v, half_width, dst3_y,
width, dst3_uv, half_width * 2, width, height);
for (int i = 0; i < width * height; ++i) {
EXPECT_EQ(dst_y[i], dst3_y[i]);
}
for (int i = 0; i < half_width * half_height * 2; ++i) {
EXPECT_EQ(dst_uv[i], dst3_uv[i]);
EXPECT_EQ(dst_uv[i], dst3_uv[i]);
}
free_aligned_buffer_page_end(dst3_y);
free_aligned_buffer_page_end(dst3_uv);
free_aligned_buffer_page_end(dst2_y);
free_aligned_buffer_page_end(dst2_u);
free_aligned_buffer_page_end(dst2_v);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_uv);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV21_420) {
int width = 0;
int height = 0;
@ -1840,6 +1899,40 @@ TEST_F(LibYUVConvertTest, TestMJPGToNV21_420) {
free_aligned_buffer_page_end(dst_uv);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV12_420) {
int width = 0;
int height = 0;
int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
EXPECT_EQ(0, ret);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
benchmark_height_ / (width * height);
align_buffer_page_end(dst_y, width * height);
align_buffer_page_end(dst_uv, half_width * half_height * 2);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToNV12(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
half_width * 2, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Test result matches known hash value. Hashes are for VU so flip the plane.
uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
align_buffer_page_end(dst_vu, half_width * half_height * 2);
SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
half_height);
uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
EXPECT_EQ(dst_y_hash, 2682851208u);
EXPECT_EQ(dst_vu_hash, 1069662856u);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_uv);
free_aligned_buffer_page_end(dst_vu);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV21_422) {
int width = 0;
int height = 0;
@ -1870,6 +1963,40 @@ TEST_F(LibYUVConvertTest, TestMJPGToNV21_422) {
free_aligned_buffer_page_end(dst_uv);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV12_422) {
int width = 0;
int height = 0;
int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
EXPECT_EQ(0, ret);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
benchmark_height_ / (width * height);
align_buffer_page_end(dst_y, width * height);
align_buffer_page_end(dst_uv, half_width * half_height * 2);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToNV12(kTest3Jpg, kTest3JpgLen, dst_y, width, dst_uv,
half_width * 2, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Test result matches known hash value. Hashes are for VU so flip the plane.
uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
align_buffer_page_end(dst_vu, half_width * half_height * 2);
SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
half_height);
uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
EXPECT_EQ(dst_y_hash, 2682851208u);
EXPECT_EQ(dst_vu_hash, 3543430771u);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_uv);
free_aligned_buffer_page_end(dst_vu);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV21_400) {
int width = 0;
int height = 0;
@ -1900,6 +2027,40 @@ TEST_F(LibYUVConvertTest, TestMJPGToNV21_400) {
free_aligned_buffer_page_end(dst_uv);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV12_400) {
int width = 0;
int height = 0;
int ret = MJPGSize(kTest0Jpg, kTest0JpgLen, &width, &height);
EXPECT_EQ(0, ret);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
benchmark_height_ / (width * height);
align_buffer_page_end(dst_y, width * height);
align_buffer_page_end(dst_uv, half_width * half_height * 2);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToNV12(kTest0Jpg, kTest0JpgLen, dst_y, width, dst_uv,
half_width * 2, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Test result matches known hash value. Hashes are for VU so flip the plane.
uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
align_buffer_page_end(dst_vu, half_width * half_height * 2);
SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
half_height);
uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
EXPECT_EQ(dst_y_hash, 330644005u);
EXPECT_EQ(dst_vu_hash, 135214341u);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_uv);
free_aligned_buffer_page_end(dst_vu);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV21_444) {
int width = 0;
int height = 0;
@ -1930,6 +2091,40 @@ TEST_F(LibYUVConvertTest, TestMJPGToNV21_444) {
free_aligned_buffer_page_end(dst_uv);
}
TEST_F(LibYUVConvertTest, TestMJPGToNV12_444) {
int width = 0;
int height = 0;
int ret = MJPGSize(kTest1Jpg, kTest1JpgLen, &width, &height);
EXPECT_EQ(0, ret);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
benchmark_height_ / (width * height);
align_buffer_page_end(dst_y, width * height);
align_buffer_page_end(dst_uv, half_width * half_height * 2);
for (int times = 0; times < benchmark_iterations; ++times) {
ret = MJPGToNV12(kTest1Jpg, kTest1JpgLen, dst_y, width, dst_uv,
half_width * 2, width, height, width, height);
}
// Expect sucesss
EXPECT_EQ(0, ret);
// Test result matches known hash value. Hashes are for VU so flip the plane.
uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
align_buffer_page_end(dst_vu, half_width * half_height * 2);
SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
half_height);
uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
EXPECT_EQ(dst_y_hash, 2682851208u);
EXPECT_EQ(dst_vu_hash, 506143297u);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_uv);
free_aligned_buffer_page_end(dst_vu);
}
TEST_F(LibYUVConvertTest, TestMJPGToARGB) {
int width = 0;
int height = 0;