mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-01-01 03:12:16 +08:00
Remove M420 and refactor NV12ToI420
M420 is a row biplanar variation of NV12 supported on Microsoft webcams. The code was hardcoded to bt.601 and should be jpeg, but the format is very old and rare. Is a variation on NV12, so if someone needs it, it can be re-implemented easily. Bug: libyuv:858 Change-Id: I246167dba3c190cc76af741b8e91e58e68fde28f Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2212608 Reviewed-by: richard winterton <rrwinterton@gmail.com> Commit-Queue: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
parent
da41bca02b
commit
94af5319f4
@ -1,6 +1,6 @@
|
||||
Name: libyuv
|
||||
URL: http://code.google.com/p/libyuv/
|
||||
Version: 1756
|
||||
Version: 1757
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ The following is extracted from video_common.h as a complete list of formats sup
|
||||
// 10 bit lsb
|
||||
|
||||
// 1 Secondary YUV format: row biplanar.
|
||||
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
|
||||
FOURCC_M420 = FOURCC('M', '4', '2', '0'), // deprecated.
|
||||
|
||||
// 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
|
||||
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
|
||||
|
||||
@ -263,19 +263,6 @@ int AYUVToNV21(const uint8_t* src_ayuv,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert M420 to I420.
|
||||
LIBYUV_API
|
||||
int M420ToI420(const uint8_t* src_m420,
|
||||
int src_stride_m420,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint8_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert Android420 to I420.
|
||||
LIBYUV_API
|
||||
int Android420ToI420(const uint8_t* src_y,
|
||||
|
||||
@ -664,15 +664,6 @@ int NV21ToRAW(const uint8_t* src_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert M420 to ARGB.
|
||||
LIBYUV_API
|
||||
int M420ToARGB(const uint8_t* src_m420,
|
||||
int src_stride_m420,
|
||||
uint8_t* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert YUY2 to ARGB.
|
||||
LIBYUV_API
|
||||
int YUY2ToARGB(const uint8_t* src_yuy2,
|
||||
|
||||
@ -11,6 +11,6 @@
|
||||
#ifndef INCLUDE_LIBYUV_VERSION_H_
|
||||
#define INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
#define LIBYUV_VERSION 1756
|
||||
#define LIBYUV_VERSION 1757
|
||||
|
||||
#endif // INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
@ -62,7 +62,7 @@ enum FourCC {
|
||||
FOURCC_I010 = FOURCC('I', '0', '1', '0'), // bt.601 10 bit 420
|
||||
FOURCC_I210 = FOURCC('I', '0', '1', '0'), // bt.601 10 bit 422
|
||||
|
||||
// 1 Secondary YUV format: row biplanar.
|
||||
// 1 Secondary YUV format: row biplanar. deprecated.
|
||||
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
|
||||
|
||||
// 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
|
||||
@ -148,7 +148,7 @@ enum FourCCBpp {
|
||||
FOURCC_BPP_NV12 = 12,
|
||||
FOURCC_BPP_YUY2 = 16,
|
||||
FOURCC_BPP_UYVY = 16,
|
||||
FOURCC_BPP_M420 = 12,
|
||||
FOURCC_BPP_M420 = 12, // deprecated
|
||||
FOURCC_BPP_Q420 = 12,
|
||||
FOURCC_BPP_ARGB = 32,
|
||||
FOURCC_BPP_BGRA = 32,
|
||||
|
||||
@ -540,120 +540,8 @@ int I400ToNV21(const uint8_t* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CopyPlane2(const uint8_t* src,
|
||||
int src_stride_0,
|
||||
int src_stride_1,
|
||||
uint8_t* dst,
|
||||
int dst_stride,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C;
|
||||
#if defined(HAS_COPYROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_COPYROW_AVX)
|
||||
if (TestCpuFlag(kCpuHasAVX)) {
|
||||
CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_COPYROW_ERMS)
|
||||
if (TestCpuFlag(kCpuHasERMS)) {
|
||||
CopyRow = CopyRow_ERMS;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_COPYROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy plane
|
||||
for (y = 0; y < height - 1; y += 2) {
|
||||
CopyRow(src, dst, width);
|
||||
CopyRow(src + src_stride_0, dst + dst_stride, width);
|
||||
src += src_stride_0 + src_stride_1;
|
||||
dst += dst_stride * 2;
|
||||
}
|
||||
if (height & 1) {
|
||||
CopyRow(src, dst, width);
|
||||
}
|
||||
}
|
||||
|
||||
// Support converting from FOURCC_M420
|
||||
// Useful for bandwidth constrained transports like USB 1.0 and 2.0 and for
|
||||
// easy conversion to I420.
|
||||
// M420 format description:
|
||||
// M420 is row biplanar 420: 2 rows of Y and 1 row of UV.
|
||||
// Chroma is half width / half height. (420)
|
||||
// src_stride_m420 is row planar. Normally this will be the width in pixels.
|
||||
// The UV plane is half width, but 2 values, so src_stride_m420 applies to
|
||||
// this as well as the two Y planes.
|
||||
static int X420ToI420(const uint8_t* src_y,
|
||||
int src_stride_y0,
|
||||
int src_stride_y1,
|
||||
const uint8_t* src_uv,
|
||||
int src_stride_uv,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint8_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
if (!src_uv || !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;
|
||||
if (dst_y) {
|
||||
dst_y = dst_y + (height - 1) * dst_stride_y;
|
||||
}
|
||||
dst_u = dst_u + (halfheight - 1) * dst_stride_u;
|
||||
dst_v = dst_v + (halfheight - 1) * dst_stride_v;
|
||||
dst_stride_y = -dst_stride_y;
|
||||
dst_stride_u = -dst_stride_u;
|
||||
dst_stride_v = -dst_stride_v;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_y0 == width && src_stride_y1 == width &&
|
||||
dst_stride_y == width) {
|
||||
width *= height;
|
||||
height = 1;
|
||||
src_stride_y0 = src_stride_y1 = dst_stride_y = 0;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_uv == halfwidth * 2 && dst_stride_u == halfwidth &&
|
||||
dst_stride_v == halfwidth) {
|
||||
halfwidth *= halfheight;
|
||||
halfheight = 1;
|
||||
src_stride_uv = dst_stride_u = dst_stride_v = 0;
|
||||
}
|
||||
|
||||
if (dst_y) {
|
||||
if (src_stride_y0 == src_stride_y1) {
|
||||
CopyPlane(src_y, src_stride_y0, dst_y, dst_stride_y, width, height);
|
||||
} else {
|
||||
CopyPlane2(src_y, src_stride_y0, src_stride_y1, dst_y, dst_stride_y,
|
||||
width, height);
|
||||
}
|
||||
}
|
||||
|
||||
// Split UV plane - NV12 / NV21
|
||||
SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v, dst_stride_v,
|
||||
halfwidth, halfheight);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert NV12 to I420.
|
||||
// TODO(fbarchard): Consider inverting destination. Faster on ARM with prfm.
|
||||
LIBYUV_API
|
||||
int NV12ToI420(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
@ -667,9 +555,43 @@ int NV12ToI420(const uint8_t* src_y,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
return X420ToI420(src_y, src_stride_y, src_stride_y, src_uv, src_stride_uv,
|
||||
dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v,
|
||||
dst_stride_v, width, height);
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
if (!src_uv || !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_uv = src_uv + (halfheight - 1) * src_stride_uv;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_uv = -src_stride_uv;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_y == width && dst_stride_y == width) {
|
||||
width *= height;
|
||||
height = 1;
|
||||
src_stride_y = dst_stride_y = 0;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_uv == halfwidth * 2 && dst_stride_u == halfwidth &&
|
||||
dst_stride_v == halfwidth) {
|
||||
halfwidth *= halfheight;
|
||||
halfheight = 1;
|
||||
src_stride_uv = dst_stride_u = dst_stride_v = 0;
|
||||
}
|
||||
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Split UV plane - NV12 / NV21
|
||||
SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v, dst_stride_v,
|
||||
halfwidth, halfheight);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert NV21 to I420. Same as NV12 but u and v pointers swapped.
|
||||
@ -686,27 +608,11 @@ int NV21ToI420(const uint8_t* src_y,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
return X420ToI420(src_y, src_stride_y, src_stride_y, src_vu, src_stride_vu,
|
||||
dst_y, dst_stride_y, dst_v, dst_stride_v, dst_u,
|
||||
dst_stride_u, width, height);
|
||||
}
|
||||
|
||||
// Convert M420 to I420.
|
||||
LIBYUV_API
|
||||
int M420ToI420(const uint8_t* src_m420,
|
||||
int src_stride_m420,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint8_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
return X420ToI420(src_m420, src_stride_m420, src_stride_m420 * 2,
|
||||
src_m420 + src_stride_m420 * 2, src_stride_m420 * 3, dst_y,
|
||||
dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
|
||||
width, height);
|
||||
return NV12ToI420(src_y, src_stride_y,
|
||||
src_vu, src_stride_vu,
|
||||
dst_y, dst_stride_y,
|
||||
dst_v, dst_stride_v,
|
||||
dst_u, dst_stride_u, width, height);
|
||||
}
|
||||
|
||||
// Convert YUY2 to I420.
|
||||
|
||||
@ -2753,83 +2753,6 @@ int NV21ToYUV24(const uint8_t* src_y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert M420 to ARGB.
|
||||
LIBYUV_API
|
||||
int M420ToARGB(const uint8_t* src_m420,
|
||||
int src_stride_m420,
|
||||
uint8_t* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void (*NV12ToARGBRow)(
|
||||
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
|
||||
const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
|
||||
if (!src_m420 || !dst_argb || width <= 0 || height == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
|
||||
dst_stride_argb = -dst_stride_argb;
|
||||
}
|
||||
#if defined(HAS_NV12TOARGBROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NV12TOARGBROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NV12TOARGBROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NV12TOARGBROW_MMI)
|
||||
if (TestCpuFlag(kCpuHasMMI)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_Any_MMI;
|
||||
if (IS_ALIGNED(width, 4)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_MMI;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NV12TOARGBROW_MSA)
|
||||
if (TestCpuFlag(kCpuHasMSA)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_MSA;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (y = 0; y < height - 1; y += 2) {
|
||||
NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
|
||||
&kYuvI601Constants, width);
|
||||
NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
|
||||
dst_argb + dst_stride_argb, &kYuvI601Constants, width);
|
||||
dst_argb += dst_stride_argb * 2;
|
||||
src_m420 += src_stride_m420 * 3;
|
||||
}
|
||||
if (height & 1) {
|
||||
NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
|
||||
&kYuvI601Constants, width);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert YUY2 to ARGB.
|
||||
LIBYUV_API
|
||||
int YUY2ToARGB(const uint8_t* src_yuy2,
|
||||
|
||||
@ -645,7 +645,6 @@ int ConvertFromI420(const uint8_t* y,
|
||||
height);
|
||||
break;
|
||||
}
|
||||
// TODO(fbarchard): Add M420.
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -180,12 +180,6 @@ int ConvertToARGB(const uint8_t* sample,
|
||||
r = NV21ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
|
||||
dst_stride_argb, crop_width, inv_crop_height);
|
||||
break;
|
||||
case FOURCC_M420:
|
||||
src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
|
||||
r = M420ToARGB(src, src_width, dst_argb, dst_stride_argb, crop_width,
|
||||
inv_crop_height);
|
||||
break;
|
||||
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -179,11 +179,6 @@ int ConvertToI420(const uint8_t* sample,
|
||||
dst_stride_y, dst_v, dst_stride_v, dst_u,
|
||||
dst_stride_u, crop_width, inv_crop_height, rotation);
|
||||
break;
|
||||
case FOURCC_M420:
|
||||
src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
|
||||
r = M420ToI420(src, src_width, dst_y, dst_stride_y, dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v, crop_width, inv_crop_height);
|
||||
break;
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -3140,8 +3140,7 @@ void I400ToARGBRow_AVX2(const uint8_t* y_buf,
|
||||
int width) {
|
||||
asm volatile(
|
||||
"vmovdqa 192(%3),%%ymm2 \n" // yg = 18997 = 1.164
|
||||
"vmovdqa 224(%3),%%ymm3 \n" // ygb = -1160 = 1.164 *
|
||||
// 16
|
||||
"vmovdqa 224(%3),%%ymm3 \n" // ygb = -1160 = 1.164*16
|
||||
"vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n" // 0xff000000
|
||||
"vpslld $0x18,%%ymm4,%%ymm4 \n"
|
||||
|
||||
|
||||
@ -351,7 +351,9 @@ void I400ToARGBRow_NEON(const uint8_t* src_y,
|
||||
asm volatile(
|
||||
YUVTORGB_SETUP
|
||||
"vmov.u8 d23, #255 \n"
|
||||
"1: \n" READYUV400 YUVTORGB
|
||||
"1: \n"
|
||||
READYUV400
|
||||
YUVTORGB
|
||||
"subs %2, %2, #8 \n"
|
||||
"vst4.8 {d20, d21, d22, d23}, [%1]! \n"
|
||||
"bgt 1b \n"
|
||||
|
||||
@ -65,7 +65,7 @@ TEST_F(LibYUVBaseTest, TestFourCC) {
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_NV12, FOURCC_BPP_NV12));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YUY2, FOURCC_BPP_YUY2));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_UYVY, FOURCC_BPP_UYVY));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_M420, FOURCC_BPP_M420));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_M420, FOURCC_BPP_M420)); // deprecated.
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_Q420, FOURCC_BPP_Q420)); // deprecated.
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_ARGB, FOURCC_BPP_ARGB));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_BGRA, FOURCC_BPP_BGRA));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user