mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2025-12-08 01:36:47 +08:00
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:
parent
4205d7a6c9
commit
f15793d6af
@ -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.
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)))
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user