Add support for BT.2020.

This pulls in the changes that Firefox made to add BT.2020 support as well
as expands them to the existing 10-bit support. So we now have the following
input formats: U420, U422, U444, U010.

BUG=960620, libyuv:845

Change-Id: If0c47853a465d0ed660f849db08e71489fe1b9c2
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/1884468
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
Dale Curtis 2019-10-29 12:30:45 -07:00 committed by Commit Bot
parent 4205d7a6c9
commit f15793d6af
6 changed files with 247 additions and 4 deletions

View File

@ -36,7 +36,7 @@ This is how OSX formats map to libyuv
The following is extracted from video_common.h as a complete list of formats supported by libyuv.
enum FourCC {
// 9 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
// 10 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
FOURCC_I422 = FOURCC('I', '4', '2', '2'),
FOURCC_I444 = FOURCC('I', '4', '4', '4'),
@ -46,6 +46,8 @@ The following is extracted from video_common.h as a complete list of formats sup
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
FOURCC_H010 = FOURCC('H', '0', '1', '0'), // unofficial fourcc. 10 bit lsb
FOURCC_U010 = FOURCC('U', '0', '1', '0'), // bt.2020, unofficial fourcc.
// 10 bit lsb
// 1 Secondary YUV format: row biplanar.
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
@ -66,7 +68,7 @@ The following is extracted from video_common.h as a complete list of formats sup
// 1 Primary Compressed YUV format.
FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
// 8 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias.
// 11 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias.
FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'),
FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'),
FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'),
@ -75,6 +77,9 @@ The following is extracted from video_common.h as a complete list of formats sup
FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc
FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc
FOURCC_H422 = FOURCC('H', '4', '2', '2'), // unofficial fourcc
FOURCC_U420 = FOURCC('U', '4', '2', '0'), // bt.2020, unofficial fourcc
FOURCC_U422 = FOURCC('U', '4', '2', '2'), // bt.2020, unofficial fourcc
FOURCC_U444 = FOURCC('U', '4', '4', '4'), // bt.2020, unofficial fourcc
// 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc.
FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420.

View File

@ -128,6 +128,32 @@ int H010ToABGR(const uint16_t* src_y,
int width,
int height);
// Convert U010 to ARGB.
LIBYUV_API
int U010ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height);
// Convert U010 to ABGR.
LIBYUV_API
int U010ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height);
// Convert I422 to ARGB.
LIBYUV_API
int I422ToARGB(const uint8_t* src_y,
@ -154,6 +180,19 @@ int I444ToARGB(const uint8_t* src_y,
int width,
int height);
// Convert U444 to ARGB.
LIBYUV_API
int U444ToARGB(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,
int width,
int height);
// Convert J444 to ARGB.
LIBYUV_API
int J444ToARGB(const uint8_t* src_y,
@ -424,6 +463,19 @@ int H420ToARGB(const uint8_t* src_y,
int width,
int height);
// Convert U420 to ARGB.
LIBYUV_API
int U420ToARGB(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,
int width,
int height);
// Convert H422 to ARGB.
LIBYUV_API
int H422ToARGB(const uint8_t* src_y,
@ -437,6 +489,19 @@ int H422ToARGB(const uint8_t* src_y,
int width,
int height);
// Convert U422 to ARGB.
LIBYUV_API
int U422ToARGB(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,
int width,
int height);
// Convert H420 to ABGR.
LIBYUV_API
int H420ToABGR(const uint8_t* src_y,

View File

@ -690,11 +690,13 @@ 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
extern const struct YuvConstants SIMD_ALIGNED(kYuv2020Constants); // BT.2020
// 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
extern const struct YuvConstants SIMD_ALIGNED(kYvu2020Constants); // BT.2020
#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a)-1)))

View File

@ -50,7 +50,7 @@ extern "C" {
// Secondary formats are converted in 2 steps.
// Auxilliary formats call primary converters.
enum FourCC {
// 9 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
// 10 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
FOURCC_I422 = FOURCC('I', '4', '2', '2'),
FOURCC_I444 = FOURCC('I', '4', '4', '4'),
@ -60,6 +60,8 @@ enum FourCC {
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
FOURCC_H010 = FOURCC('H', '0', '1', '0'), // unofficial fourcc. 10 bit lsb
FOURCC_U010 = FOURCC('U', '0', '1', '0'), // bt.2020, unofficial fourcc.
// 10 bit lsb
// 1 Secondary YUV format: row biplanar.
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
@ -80,7 +82,7 @@ enum FourCC {
// 1 Primary Compressed YUV format.
FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
// 8 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias.
// 11 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias.
FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'),
FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'),
FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'),
@ -89,6 +91,9 @@ enum FourCC {
FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc
FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc
FOURCC_H422 = FOURCC('H', '4', '2', '2'), // unofficial fourcc
FOURCC_U420 = FOURCC('U', '4', '2', '0'), // bt.2020, unofficial fourcc
FOURCC_U422 = FOURCC('U', '4', '2', '2'), // bt.2020, unofficial fourcc
FOURCC_U444 = FOURCC('U', '4', '4', '4'), // bt.2020, unofficial fourcc
// 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc.
FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420.

View File

@ -234,6 +234,23 @@ int H420ToABGR(const uint8_t* src_y,
width, height);
}
// Convert U420 to ARGB.
LIBYUV_API
int U420ToARGB(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,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert I422 to ARGB with matrix
static int I422ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
@ -516,6 +533,23 @@ int H010ToAR30(const uint16_t* src_y,
&kYuvH709Constants, width, height);
}
// Convert U010 to AR30.
LIBYUV_API
int U010ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuv2020Constants, width, height);
}
// Convert I010 to AB30.
LIBYUV_API
int I010ToAB30(const uint16_t* src_y,
@ -550,6 +584,23 @@ int H010ToAB30(const uint16_t* src_y,
&kYvuH709Constants, width, height);
}
// Convert U010 to AB30.
LIBYUV_API
int U010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYuv2020Constants, width, height);
}
// Convert 10 bit YUV to ARGB with matrix
static int I010ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
@ -684,6 +735,23 @@ int H010ToABGR(const uint16_t* src_y,
width, height);
}
// Convert U422 to ARGB.
LIBYUV_API
int U422ToARGB(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,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert I444 to ARGB with matrix
static int I444ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
@ -785,6 +853,23 @@ int I444ToARGB(const uint8_t* src_y,
&kYuvI601Constants, width, height);
}
// Convert U444 to ARGB.
LIBYUV_API
int U444ToARGB(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,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert I444 to ABGR.
LIBYUV_API
int I444ToABGR(const uint8_t* src_y,

View File

@ -1355,6 +1355,87 @@ const struct YuvConstants SIMD_ALIGNED(kYvuH709Constants) = {
#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
// B = (Y - 16) * 1.164384 - U * -2.14177
// Y contribution to R,G,B. Scale and bias.
#define YG 19003 /* round(1.164384 * 64 * 256 * 256 / 257) */
#define YGB -1160 /* 1.164384 * 64 * -16 + 64 / 2 */
// TODO(fbarchard): Improve accuracy; the B channel is off by 7%.
#define UB -128 /* max(-128, round(-2.142 * 64)) */
#define UG 12 /* round(0.187326 * 64) */
#define VG 42 /* round(0.65042 * 64) */
#define VR -107 /* round(-1.67867 * 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(kYuv2020Constants) = {
{-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(kYvu2020Constants) = {
{-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(kYuv2020Constants) = {
{-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(kYvu2020Constants) = {
{-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(kYuv2020Constants) = {
{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(kYvu2020Constants) = {
{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.