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
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
|
BIN
image/test/gtest/gray-235-10bit-full-range-bt2020.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-full-range-bt601.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-full-range-bt709.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-full-range-grayscale.avif
Normal file
After Width: | Height: | Size: 301 B |
BIN
image/test/gtest/gray-235-10bit-limited-range-bt2020.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-limited-range-bt601.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-limited-range-bt709.avif
Normal file
After Width: | Height: | Size: 310 B |
BIN
image/test/gtest/gray-235-10bit-limited-range-grayscale.avif
Normal file
After Width: | Height: | Size: 301 B |
BIN
image/test/gtest/gray-235-12bit-full-range-bt2020.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-full-range-bt601.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-full-range-bt709.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-full-range-grayscale.avif
Normal file
After Width: | Height: | Size: 301 B |
BIN
image/test/gtest/gray-235-12bit-limited-range-bt2020.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-limited-range-bt601.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-limited-range-bt709.avif
Normal file
After Width: | Height: | Size: 307 B |
BIN
image/test/gtest/gray-235-12bit-limited-range-grayscale.avif
Normal file
After Width: | Height: | Size: 301 B |
BIN
image/test/gtest/gray-235-8bit-full-range-bt2020.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-full-range-bt601.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-full-range-bt709.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-full-range-grayscale.avif
Normal file
After Width: | Height: | Size: 300 B |
BIN
image/test/gtest/gray-235-8bit-limited-range-bt2020.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-limited-range-bt601.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-limited-range-bt709.avif
Normal file
After Width: | Height: | Size: 309 B |
BIN
image/test/gtest/gray-235-8bit-limited-range-grayscale.avif
Normal file
After Width: | Height: | Size: 300 B |
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 321 B |
@ -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",
|
||||
|
@ -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.
|
||||
|
@ -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)))
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
||||
|