Bug 1654461 - Make ConvertYCbCrToRGB32 color range aware r=jbauman,aosmond

Fix for ConvertYCbCrToRGB32 to use full range convert functions for full range data.

Some changes of libyuv are backported from newer version, to get support of full range BT.709 and BT.2020 colorspace.

Differential Revision: https://phabricator.services.mozilla.com/D105937
This commit is contained in:
Yuan Tong 2021-05-19 18:03:43 +00:00
parent d8fe2ac176
commit 83f1c42ade
36 changed files with 732 additions and 103 deletions

View File

@ -137,6 +137,7 @@ ConvertYCbCrToRGBInternal(const layers::PlanarYCbCrData& aData,
dstData.mCbCrStride = (aData.mCbCrSize.width + 31) & ~31;
dstData.mYUVColorSpace = aData.mYUVColorSpace;
dstData.mColorDepth = ColorDepth::COLOR_8;
dstData.mColorRange = aData.mColorRange;
size_t ySize = GetAlignedStride<1>(dstData.mYStride, aData.mYSize.height);
size_t cbcrSize =
@ -254,7 +255,8 @@ ConvertYCbCrToRGBInternal(const layers::PlanarYCbCrData& aData,
srcData.mCbCrStride,
aStride,
yuvtype,
srcData.mYUVColorSpace);
srcData.mYUVColorSpace,
srcData.mColorRange);
}
}

View File

@ -93,7 +93,8 @@ void ConvertYCbCrToRGB32(const uint8* y_buf, const uint8* u_buf,
const uint8* v_buf, uint8* rgb_buf, int pic_x,
int pic_y, int pic_width, int pic_height, int y_pitch,
int uv_pitch, int rgb_pitch, YUVType yuv_type,
YUVColorSpace yuv_color_space) {
YUVColorSpace yuv_color_space,
ColorRange color_range) {
// Deprecated function's conversion is accurate.
// libyuv converion is a bit inaccurate to get performance. It dynamically
// calculates RGB from YUV to use simd. In it, signed byte is used for
@ -104,7 +105,8 @@ void ConvertYCbCrToRGB32(const uint8* y_buf, const uint8* u_buf,
// See Bug 1256475.
bool use_deprecated = StaticPrefs::gfx_ycbcr_accurate_conversion() ||
(supports_mmx() && supports_sse() && !supports_sse3() &&
yuv_color_space == YUVColorSpace::BT601);
yuv_color_space == YUVColorSpace::BT601 &&
color_range == ColorRange::LIMITED);
// The deprecated function only support BT601.
// See Bug 1210357.
if (yuv_color_space != YUVColorSpace::BT601) {
@ -117,88 +119,99 @@ void ConvertYCbCrToRGB32(const uint8* y_buf, const uint8* u_buf,
return;
}
decltype(libyuv::U444ToARGB)* fConvertYUVToARGB = nullptr;
decltype(libyuv::I420ToARGBMatrix)* fConvertYUVToARGB = nullptr;
const uint8* src_y = nullptr;
const uint8* src_u = nullptr;
const uint8* src_v = nullptr;
const libyuv::YuvConstants* yuv_constant = nullptr;
switch (yuv_color_space) {
case YUVColorSpace::BT2020:
yuv_constant = color_range == ColorRange::LIMITED
? &libyuv::kYuv2020Constants
: &libyuv::kYuvV2020Constants;
break;
case YUVColorSpace::BT709:
yuv_constant = color_range == ColorRange::LIMITED
? &libyuv::kYuvH709Constants
: &libyuv::kYuvF709Constants;
break;
case YUVColorSpace::Identity:
MOZ_ASSERT(yuv_type == YV24, "Identity (aka RGB) with chroma subsampling is unsupported");
if (yuv_type == YV24) {
break;
}
[[fallthrough]]; // Assuming BT601 for unsupported input is better than crashing
default:
MOZ_FALLTHROUGH_ASSERT("Unsupported YUVColorSpace");
case YUVColorSpace::BT601:
yuv_constant = color_range == ColorRange::LIMITED
? &libyuv::kYuvI601Constants
: &libyuv::kYuvJPEGConstants;
break;
}
switch (yuv_type) {
case YV24: {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x;
const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x;
switch (yuv_color_space) {
case YUVColorSpace::BT2020:
fConvertYUVToARGB = libyuv::U444ToARGB;
break;
case YUVColorSpace::BT709:
fConvertYUVToARGB = libyuv::H444ToARGB;
break;
case YUVColorSpace::Identity:
fConvertYUVToARGB = GBRPlanarToARGB;
break;
default:
fConvertYUVToARGB = libyuv::I444ToARGB;
break;
}
DebugOnly<int> err =
fConvertYUVToARGB(src_y, y_pitch, src_u, uv_pitch, src_v, uv_pitch,
src_y = y_buf + y_pitch * pic_y + pic_x;
src_u = u_buf + uv_pitch * pic_y + pic_x;
src_v = v_buf + uv_pitch * pic_y + pic_x;
if (yuv_color_space == YUVColorSpace::Identity) {
// Special case for RGB image
DebugOnly<int> err =
GBRPlanarToARGB(src_y, y_pitch, src_u, uv_pitch, src_v, uv_pitch,
rgb_buf, rgb_pitch, pic_width, pic_height);
MOZ_ASSERT(!err);
MOZ_ASSERT(!err);
return;
}
fConvertYUVToARGB = libyuv::I444ToARGBMatrix;
break;
}
case YV16: {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x / 2;
const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x / 2;
switch (yuv_color_space) {
case YUVColorSpace::BT2020:
fConvertYUVToARGB = libyuv::U422ToARGB;
break;
case YUVColorSpace::BT709:
fConvertYUVToARGB = libyuv::H422ToARGB;
break;
default:
fConvertYUVToARGB = libyuv::I422ToARGB;
break;
}
DebugOnly<int> err =
fConvertYUVToARGB(src_y, y_pitch, src_u, uv_pitch, src_v, uv_pitch,
rgb_buf, rgb_pitch, pic_width, pic_height);
MOZ_ASSERT(!err);
src_y = y_buf + y_pitch * pic_y + pic_x;
src_u = u_buf + uv_pitch * pic_y + pic_x / 2;
src_v = v_buf + uv_pitch * pic_y + pic_x / 2;
fConvertYUVToARGB = libyuv::I422ToARGBMatrix;
break;
}
case YV12: {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
switch (yuv_color_space) {
case YUVColorSpace::BT2020:
fConvertYUVToARGB = libyuv::U420ToARGB;
break;
case YUVColorSpace::BT709:
fConvertYUVToARGB = libyuv::H420ToARGB;
break;
default:
fConvertYUVToARGB = libyuv::I420ToARGB;
break;
}
DebugOnly<int> err =
fConvertYUVToARGB(src_y, y_pitch, src_u, uv_pitch, src_v, uv_pitch,
rgb_buf, rgb_pitch, pic_width, pic_height);
MOZ_ASSERT(!err);
src_y = y_buf + y_pitch * pic_y + pic_x;
src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
fConvertYUVToARGB = libyuv::I420ToARGBMatrix;
break;
}
case Y8: {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
src_y = y_buf + y_pitch * pic_y + pic_x;
MOZ_ASSERT(u_buf == nullptr);
MOZ_ASSERT(v_buf == nullptr);
DebugOnly<int> err =
libyuv::I400ToARGB(src_y, y_pitch, rgb_buf, rgb_pitch, pic_width,
pic_height);
MOZ_ASSERT(!err);
break;
if (color_range == ColorRange::LIMITED) {
DebugOnly<int> err =
libyuv::I400ToARGB(src_y, y_pitch, rgb_buf, rgb_pitch, pic_width,
pic_height);
MOZ_ASSERT(!err);
} else {
DebugOnly<int> err =
libyuv::J400ToARGB(src_y, y_pitch, rgb_buf, rgb_pitch, pic_width,
pic_height);
MOZ_ASSERT(!err);
}
return;
}
default:
MOZ_ASSERT_UNREACHABLE("Unsupported YUV type");
}
DebugOnly<int> err =
fConvertYUVToARGB(src_y, y_pitch, src_u, uv_pitch, src_v, uv_pitch,
rgb_buf, rgb_pitch, yuv_constant, pic_width, pic_height);
MOZ_ASSERT(!err);
}
// Convert a frame of YUV to 32 bit ARGB.

View File

@ -60,7 +60,8 @@ void ConvertYCbCrToRGB32(const uint8* yplane,
int uvstride,
int rgbstride,
YUVType yuv_type,
YUVColorSpace yuv_color_space);
YUVColorSpace yuv_color_space,
ColorRange color_range);
void ConvertYCbCrToRGB32_deprecated(const uint8* yplane,
const uint8* uplane,

View File

@ -519,7 +519,8 @@ ImageTestCase Transparent8bit420AVIFTestCase() {
ImageTestCase("transparent-green-50pct-8bit-yuv420.avif", "image/avif",
IntSize(100, 100), TEST_CASE_IS_TRANSPARENT)
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
// Small error is expected
testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
return testCase;
}
@ -530,7 +531,8 @@ ImageTestCase Transparent8bit422AVIFTestCase() {
ImageTestCase("transparent-green-50pct-8bit-yuv422.avif", "image/avif",
IntSize(100, 100), TEST_CASE_IS_TRANSPARENT)
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
// Small error is expected
testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
return testCase;
}
@ -541,7 +543,256 @@ ImageTestCase Transparent8bit444AVIFTestCase() {
ImageTestCase("transparent-green-50pct-8bit-yuv444.avif", "image/avif",
IntSize(100, 100), TEST_CASE_IS_TRANSPARENT)
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
// Small error is expected
testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitLimitedRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitLimitedRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitLimitedRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitFullRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-full-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitFullRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-full-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitFullRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-full-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitLimitedRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitLimitedRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitLimitedRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitFullRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-full-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitFullRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-full-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitFullRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-full-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitLimitedRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitLimitedRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitLimitedRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitFullRangeBT601AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-full-range-bt601.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitFullRangeBT709AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-full-range-bt709.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitFullRangeBT2020AVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-full-range-bt2020.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitLimitedRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-limited-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray8bitFullRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-8bit-full-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitLimitedRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-limited-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray10bitFullRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-10bit-full-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitLimitedRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-limited-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
// Small error is expected
testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
return testCase;
}
// Forcing sRGB is required until nsAVIFDecoder supports ICC profiles
// See bug 1634741
ImageTestCase Gray12bitFullRangeGrayscaleAVIFTestCase() {
auto testCase = ImageTestCase("gray-235-12bit-full-range-grayscale.avif",
"image/avif", IntSize(100, 100))
.WithSurfaceFlags(SurfaceFlags::TO_SRGB_COLORSPACE);
testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
return testCase;
}

View File

@ -488,6 +488,31 @@ ImageTestCase Transparent8bit420AVIFTestCase();
ImageTestCase Transparent8bit422AVIFTestCase();
ImageTestCase Transparent8bit444AVIFTestCase();
ImageTestCase Gray8bitLimitedRangeBT601AVIFTestCase();
ImageTestCase Gray8bitLimitedRangeBT709AVIFTestCase();
ImageTestCase Gray8bitLimitedRangeBT2020AVIFTestCase();
ImageTestCase Gray8bitFullRangeBT601AVIFTestCase();
ImageTestCase Gray8bitFullRangeBT709AVIFTestCase();
ImageTestCase Gray8bitFullRangeBT2020AVIFTestCase();
ImageTestCase Gray10bitLimitedRangeBT601AVIFTestCase();
ImageTestCase Gray10bitLimitedRangeBT709AVIFTestCase();
ImageTestCase Gray10bitLimitedRangeBT2020AVIFTestCase();
ImageTestCase Gray10bitFullRangeBT601AVIFTestCase();
ImageTestCase Gray10bitFullRangeBT709AVIFTestCase();
ImageTestCase Gray10bitFullRangeBT2020AVIFTestCase();
ImageTestCase Gray12bitLimitedRangeBT601AVIFTestCase();
ImageTestCase Gray12bitLimitedRangeBT709AVIFTestCase();
ImageTestCase Gray12bitLimitedRangeBT2020AVIFTestCase();
ImageTestCase Gray12bitFullRangeBT601AVIFTestCase();
ImageTestCase Gray12bitFullRangeBT709AVIFTestCase();
ImageTestCase Gray12bitFullRangeBT2020AVIFTestCase();
ImageTestCase Gray8bitLimitedRangeGrayscaleAVIFTestCase();
ImageTestCase Gray8bitFullRangeGrayscaleAVIFTestCase();
ImageTestCase Gray10bitLimitedRangeGrayscaleAVIFTestCase();
ImageTestCase Gray10bitFullRangeGrayscaleAVIFTestCase();
ImageTestCase Gray12bitLimitedRangeGrayscaleAVIFTestCase();
ImageTestCase Gray12bitFullRangeGrayscaleAVIFTestCase();
ImageTestCase StackCheckAVIFTestCase();
ImageTestCase LargeWebPTestCase();

View File

@ -742,6 +742,102 @@ TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit444) {
CheckDecoderSingleChunk(Transparent8bit444AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT601) {
CheckDecoderSingleChunk(Gray8bitLimitedRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT709) {
CheckDecoderSingleChunk(Gray8bitLimitedRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT2020) {
CheckDecoderSingleChunk(Gray8bitLimitedRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT601) {
CheckDecoderSingleChunk(Gray8bitFullRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT709) {
CheckDecoderSingleChunk(Gray8bitFullRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT2020) {
CheckDecoderSingleChunk(Gray8bitFullRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT601) {
CheckDecoderSingleChunk(Gray10bitLimitedRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT709) {
CheckDecoderSingleChunk(Gray10bitLimitedRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT2020) {
CheckDecoderSingleChunk(Gray10bitLimitedRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT601) {
CheckDecoderSingleChunk(Gray10bitFullRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT709) {
CheckDecoderSingleChunk(Gray10bitFullRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT2020) {
CheckDecoderSingleChunk(Gray10bitFullRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT601) {
CheckDecoderSingleChunk(Gray12bitLimitedRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT709) {
CheckDecoderSingleChunk(Gray12bitLimitedRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT2020) {
CheckDecoderSingleChunk(Gray12bitLimitedRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT601) {
CheckDecoderSingleChunk(Gray12bitFullRangeBT601AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT709) {
CheckDecoderSingleChunk(Gray12bitFullRangeBT709AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT2020) {
CheckDecoderSingleChunk(Gray12bitFullRangeBT2020AVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeGrayscale) {
CheckDecoderSingleChunk(Gray8bitLimitedRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeGrayscale) {
CheckDecoderSingleChunk(Gray8bitFullRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeGrayscale) {
CheckDecoderSingleChunk(Gray10bitLimitedRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeGrayscale) {
CheckDecoderSingleChunk(Gray10bitFullRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeGrayscale) {
CheckDecoderSingleChunk(Gray12bitLimitedRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeGrayscale) {
CheckDecoderSingleChunk(Gray12bitFullRangeGrayscaleAVIFTestCase());
}
TEST_F(ImageDecoders, AVIFMultiLayerSingleChunk) {
CheckDecoderSingleChunk(MultiLayerAVIFTestCase());
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 321 B

View File

@ -68,6 +68,30 @@ TEST_HARNESS_FILES.gtest += [
"first-frame-green.png",
"first-frame-green.webp",
"first-frame-padding.gif",
"gray-235-10bit-full-range-bt2020.avif",
"gray-235-10bit-full-range-bt601.avif",
"gray-235-10bit-full-range-bt709.avif",
"gray-235-10bit-full-range-grayscale.avif",
"gray-235-10bit-limited-range-bt2020.avif",
"gray-235-10bit-limited-range-bt601.avif",
"gray-235-10bit-limited-range-bt709.avif",
"gray-235-10bit-limited-range-grayscale.avif",
"gray-235-12bit-full-range-bt2020.avif",
"gray-235-12bit-full-range-bt601.avif",
"gray-235-12bit-full-range-bt709.avif",
"gray-235-12bit-full-range-grayscale.avif",
"gray-235-12bit-limited-range-bt2020.avif",
"gray-235-12bit-limited-range-bt601.avif",
"gray-235-12bit-limited-range-bt709.avif",
"gray-235-12bit-limited-range-grayscale.avif",
"gray-235-8bit-full-range-bt2020.avif",
"gray-235-8bit-full-range-bt601.avif",
"gray-235-8bit-full-range-bt709.avif",
"gray-235-8bit-full-range-grayscale.avif",
"gray-235-8bit-limited-range-bt2020.avif",
"gray-235-8bit-limited-range-bt601.avif",
"gray-235-8bit-limited-range-bt709.avif",
"gray-235-8bit-limited-range-grayscale.avif",
"green-1x1-truncated.gif",
"green-large-bmp.ico",
"green-large-png.ico",

View File

@ -693,6 +693,48 @@ int Android420ToABGR(const uint8_t* src_y,
int width,
int height);
// Convert I420 to ARGB with matrix
LIBYUV_API
int I420ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height);
// Convert I422 to ARGB with matrix
LIBYUV_API
int I422ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height);
// Convert I444 to ARGB with matrix
LIBYUV_API
int I444ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height);
// Convert camera sample to ARGB with cropping, rotation and vertical flip.
// "sample_size" is needed to parse MJPG.
// "dst_stride_argb" number of bytes in a row of the dst_argb plane.

View File

@ -558,13 +558,21 @@ struct YuvConstants {
extern const struct YuvConstants SIMD_ALIGNED(kYuvI601Constants); // BT.601
extern const struct YuvConstants SIMD_ALIGNED(kYuvJPEGConstants); // JPeg
extern const struct YuvConstants SIMD_ALIGNED(kYuvH709Constants); // BT.709
// BT.709 Full
extern const struct YuvConstants SIMD_ALIGNED(kYuvF709Constants);
extern const struct YuvConstants SIMD_ALIGNED(kYuv2020Constants); // BT.2020
// BT.2020 Full
extern const struct YuvConstants SIMD_ALIGNED(kYuvV2020Constants);
// Conversion matrix for YVU to BGR
extern const struct YuvConstants SIMD_ALIGNED(kYvuI601Constants); // BT.601
extern const struct YuvConstants SIMD_ALIGNED(kYvuJPEGConstants); // JPeg
extern const struct YuvConstants SIMD_ALIGNED(kYvuH709Constants); // BT.709
// BT.709 Full
extern const struct YuvConstants SIMD_ALIGNED(kYvuF709Constants);
extern const struct YuvConstants SIMD_ALIGNED(kYvu2020Constants); // BT.2020
// BT.2020 Full
extern const struct YuvConstants SIMD_ALIGNED(kYvuV2020Constants);
#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a)-1)))

View File

@ -48,17 +48,18 @@ int ARGBCopy(const uint8_t* src_argb,
}
// Convert I420 to ARGB with matrix
static int I420ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
LIBYUV_API
int I420ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
@ -244,17 +245,18 @@ int U420ToARGB(const uint8_t* src_y,
}
// Convert I422 to ARGB with matrix
static int I422ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
LIBYUV_API
int I422ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
@ -695,17 +697,18 @@ int U422ToARGB(const uint8* src_y,
}
// Convert I444 to ARGB with matrix
static int I444ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
LIBYUV_API
int I444ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,

View File

@ -1306,6 +1306,88 @@ const struct YuvConstants SIMD_ALIGNED(kYvuH709Constants) = {
#undef VR
#undef YG
// BT.709 full range YUV to RGB reference
// R = Y + V * 1.5748
// G = Y - U * 0.18732 - V * 0.46812
// B = Y + U * 1.8556
// KR = 0.2126, KB = 0.0722
// Y contribution to R,G,B. Scale and bias.
#define YG 16320 /* round(1 * 64 * 256 * 256 / 257) */
#define YGB 32 /* 64 / 2 */
// U and V contributions to R,G,B.
#define UB -119 /* round(-1.8556 * 64) */
#define UG 12 /* round(0.18732 * 64) */
#define VG 30 /* round(0.46812 * 64) */
#define VR -101 /* round(-1.5748 * 64) */
// Bias values to round, and subtract 128 from U and V.
#define BB (UB * 128 + YGB)
#define BG (UG * 128 + VG * 128 + YGB)
#define BR (VR * 128 + YGB)
#if defined(__aarch64__)
const struct YuvConstants SIMD_ALIGNED(kYuvF709Constants) = {
{-UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR},
{-UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR},
{UG, VG, UG, VG, UG, VG, UG, VG},
{UG, VG, UG, VG, UG, VG, UG, VG},
{BB, BG, BR, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
const struct YuvConstants SIMD_ALIGNED(kYvuF709Constants) = {
{-VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB},
{-VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB},
{VG, UG, VG, UG, VG, UG, VG, UG},
{VG, UG, VG, UG, VG, UG, VG, UG},
{BR, BG, BB, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
#elif defined(__arm__)
const struct YuvConstants SIMD_ALIGNED(kYuvF709Constants) = {
{-UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0},
{UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0},
{BB, BG, BR, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
const struct YuvConstants SIMD_ALIGNED(kYvuF709Constants) = {
{-VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0},
{VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0},
{BR, BG, BB, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
#else
const struct YuvConstants SIMD_ALIGNED(kYuvF709Constants) = {
{UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0,
UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0},
{UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG,
UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG},
{0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR,
0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR},
{BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB},
{BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG},
{BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR},
{YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG}};
const struct YuvConstants SIMD_ALIGNED(kYvuF709Constants) = {
{VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0,
VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0},
{VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG,
VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG},
{0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB,
0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB},
{BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR},
{BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG},
{BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB},
{YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG}};
#endif
#undef BB
#undef BG
#undef BR
#undef YGB
#undef UB
#undef UG
#undef VG
#undef VR
#undef YG
// BT.2020 YUV to RGB reference
// R = (Y - 16) * 1.164384 - V * -1.67867
// G = (Y - 16) * 1.164384 - U * 0.187326 - V * -0.65042
@ -1386,6 +1468,88 @@ const struct YuvConstants SIMD_ALIGNED(kYvu2020Constants) = {
#undef VR
#undef YG
// BT.2020 full range YUV to RGB reference
// R = Y + V * 1.474600
// G = Y - U * 0.164553 - V * 0.571353
// B = Y + U * 1.881400
// KR = 0.2627; KB = 0.0593
// Y contribution to R,G,B. Scale and bias.
#define YG 16320 /* round(1 * 64 * 256 * 256 / 257) */
#define YGB 32 /* 64 / 2 */
// U and V contributions to R,G,B.
#define UB -120 /* round(-1.881400 * 64) */
#define UG 11 /* round(0.164553 * 64) */
#define VG 37 /* round(0.571353 * 64) */
#define VR -94 /* round(-1.474600 * 64) */
// Bias values to round, and subtract 128 from U and V.
#define BB (UB * 128 + YGB)
#define BG (UG * 128 + VG * 128 + YGB)
#define BR (VR * 128 + YGB)
#if defined(__aarch64__)
const struct YuvConstants SIMD_ALIGNED(kYuvV2020Constants) = {
{-UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR},
{-UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR},
{UG, VG, UG, VG, UG, VG, UG, VG},
{UG, VG, UG, VG, UG, VG, UG, VG},
{BB, BG, BR, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
const struct YuvConstants SIMD_ALIGNED(kYvuV2020Constants) = {
{-VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB},
{-VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB},
{VG, UG, VG, UG, VG, UG, VG, UG},
{VG, UG, VG, UG, VG, UG, VG, UG},
{BR, BG, BB, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
#elif defined(__arm__)
const struct YuvConstants SIMD_ALIGNED(kYuvV2020Constants) = {
{-UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0},
{UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0},
{BB, BG, BR, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
const struct YuvConstants SIMD_ALIGNED(kYvuV2020Constants) = {
{-VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0},
{VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0},
{BR, BG, BB, 0, 0, 0, 0, 0},
{0x0101 * YG, 0, 0, 0}};
#else
const struct YuvConstants SIMD_ALIGNED(kYuvV2020Constants) = {
{UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0,
UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0},
{UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG,
UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG},
{0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR,
0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR},
{BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB},
{BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG},
{BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR},
{YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG}};
const struct YuvConstants SIMD_ALIGNED(kYvuV2020Constants) = {
{VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0,
VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0},
{VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG,
VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG},
{0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB,
0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB},
{BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR},
{BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG},
{BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB},
{YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG}};
#endif
#undef BB
#undef BG
#undef BR
#undef YGB
#undef UB
#undef UG
#undef VG
#undef VR
#undef YG
// C reference code that mimics the YUV assembly.
// Reads 8 bit YUV and leaves result as 16 bit.