Commit ed55d24d authored by Frank Barchard's avatar Frank Barchard

H420 functionality

R=harryjin@google.com
BUG=libyuv:488

Review URL: https://webrtc-codereview.appspot.com/54869004 .
parent 3f893126
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 1478
Version: 1479
License: BSD
License File: LICENSE
......
......@@ -165,6 +165,38 @@ int J422ToABGR(const uint8* src_y, int src_stride_y,
uint8* dst_abgr, int dst_stride_abgr,
int width, int height);
// Convert H420 to ARGB.
LIBYUV_API
int H420ToARGB(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Convert H422 to ARGB.
LIBYUV_API
int H422ToARGB(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Convert H420 to ABGR.
LIBYUV_API
int H420ToABGR(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_abgr, int dst_stride_abgr,
int width, int height);
// Convert H422 to ABGR.
LIBYUV_API
int H422ToABGR(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_abgr, int dst_stride_abgr,
int width, int height);
// BGRA little endian (argb in memory) to ARGB.
LIBYUV_API
int BGRAToARGB(const uint8* src_frame, int src_stride_frame,
......
......@@ -101,6 +101,8 @@ extern "C" {
#define HAS_J400TOARGBROW_SSE2
#define HAS_J422TOARGBROW_SSSE3
#define HAS_J422TOABGRROW_SSSE3
#define HAS_H422TOARGBROW_SSSE3
#define HAS_H422TOABGRROW_SSSE3
#define HAS_MERGEUVROW_SSE2
#define HAS_MIRRORROW_SSE2
#define HAS_MIRRORROW_SSSE3
......@@ -238,6 +240,8 @@ extern "C" {
#define HAS_INTERPOLATEROW_AVX2
#define HAS_J422TOARGBROW_AVX2
#define HAS_J422TOABGRROW_AVX2
#define HAS_H422TOARGBROW_AVX2
#define HAS_H422TOABGRROW_AVX2
#define HAS_MERGEUVROW_AVX2
#define HAS_MIRRORROW_AVX2
#define HAS_SPLITUVROW_AVX2
......@@ -1047,6 +1051,16 @@ void J422ToABGRRow_C(const uint8* src_y,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToARGBRow_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToABGRRow_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void I422ToBGRARow_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
......@@ -1220,6 +1234,26 @@ void J422ToABGRRow_AVX2(const uint8* src_y,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToARGBRow_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToABGRRow_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToARGBRow_AVX2(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToABGRRow_AVX2(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void I422ToBGRARow_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
......@@ -1394,6 +1428,26 @@ void J422ToABGRRow_Any_AVX2(const uint8* src_y,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToARGBRow_Any_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToABGRRow_Any_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToARGBRow_Any_AVX2(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void H422ToABGRRow_Any_AVX2(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* dst_argb,
int width);
void I422ToBGRARow_Any_SSSE3(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
......
......@@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1478
#define LIBYUV_VERSION 1479
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
......@@ -62,7 +62,7 @@ enum FourCC {
// 2 Secondary YUV formats: row biplanar.
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), // deprecated.
FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), // deprecated.
// 9 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp.
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
......@@ -90,7 +90,8 @@ enum FourCC {
FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'),
FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420.
FOURCC_J420 = FOURCC('J', '4', '2', '0'),
FOURCC_J400 = FOURCC('J', '4', '0', '0'),
FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc
FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc
// 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc.
FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420.
......@@ -150,6 +151,7 @@ enum FourCCBpp {
FOURCC_BPP_YU12 = 12,
FOURCC_BPP_J420 = 12,
FOURCC_BPP_J400 = 8,
FOURCC_BPP_H420 = 12,
FOURCC_BPP_MJPG = 0, // 0 means unknown.
FOURCC_BPP_H264 = 0,
FOURCC_BPP_IYUV = 12,
......
......@@ -1544,6 +1544,298 @@ int J422ToABGR(const uint8* src_y, int src_stride_y,
return 0;
}
// Convert H420 to ARGB.
LIBYUV_API
int H420ToARGB(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
int y;
void (*H422ToARGBRow)(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width) = H422ToARGBRow_C;
if (!src_y || !src_u || !src_v || !dst_argb ||
width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_H422TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
H422ToARGBRow = H422ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
H422ToARGBRow = H422ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_H422TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
H422ToARGBRow = H422ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
H422ToARGBRow = H422ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_H422TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
H422ToARGBRow = H422ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
H422ToARGBRow = H422ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_H422TOARGBROW_MIPS_DSPR2)
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
H422ToARGBRow = H422ToARGBRow_MIPS_DSPR2;
}
#endif
for (y = 0; y < height; ++y) {
H422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert H422 to ARGB.
LIBYUV_API
int H422ToARGB(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
int y;
void (*H422ToARGBRow)(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width) = H422ToARGBRow_C;
if (!src_y || !src_u || !src_v ||
!dst_argb ||
width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
// Coalesce rows.
if (src_stride_y == width &&
src_stride_u * 2 == width &&
src_stride_v * 2 == width &&
dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
}
#if defined(HAS_H422TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
H422ToARGBRow = H422ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
H422ToARGBRow = H422ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_H422TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
H422ToARGBRow = H422ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
H422ToARGBRow = H422ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_H422TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
H422ToARGBRow = H422ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
H422ToARGBRow = H422ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_H422TOARGBROW_MIPS_DSPR2)
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
H422ToARGBRow = H422ToARGBRow_MIPS_DSPR2;
}
#endif
for (y = 0; y < height; ++y) {
H422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert H420 to ABGR.
LIBYUV_API
int H420ToABGR(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_abgr, int dst_stride_abgr,
int width, int height) {
int y;
void (*H422ToABGRRow)(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width) = H422ToABGRRow_C;
if (!src_y || !src_u || !src_v || !dst_abgr ||
width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr;
dst_stride_abgr = -dst_stride_abgr;
}
#if defined(HAS_H422TOABGRROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
H422ToABGRRow = H422ToABGRRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
H422ToABGRRow = H422ToABGRRow_SSSE3;
}
}
#endif
#if defined(HAS_H422TOABGRROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
H422ToABGRRow = H422ToABGRRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
H422ToABGRRow = H422ToABGRRow_AVX2;
}
}
#endif
#if defined(HAS_H422TOABGRROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
H422ToABGRRow = H422ToABGRRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
H422ToABGRRow = H422ToABGRRow_NEON;
}
}
#endif
#if defined(HAS_H422TOABGRROW_MIPS_DSPR2)
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
IS_ALIGNED(dst_abgr, 4) && IS_ALIGNED(dst_stride_abgr, 4)) {
H422ToABGRRow = H422ToABGRRow_MIPS_DSPR2;
}
#endif
for (y = 0; y < height; ++y) {
H422ToABGRRow(src_y, src_u, src_v, dst_abgr, width);
dst_abgr += dst_stride_abgr;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert H422 to ABGR.
LIBYUV_API
int H422ToABGR(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_abgr, int dst_stride_abgr,
int width, int height) {
int y;
void (*H422ToABGRRow)(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width) = H422ToABGRRow_C;
if (!src_y || !src_u || !src_v ||
!dst_abgr ||
width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr;
dst_stride_abgr = -dst_stride_abgr;
}
// Coalesce rows.
if (src_stride_y == width &&
src_stride_u * 2 == width &&
src_stride_v * 2 == width &&
dst_stride_abgr == width * 4) {
width *= height;
height = 1;
src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0;
}
#if defined(HAS_H422TOABGRROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
H422ToABGRRow = H422ToABGRRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
H422ToABGRRow = H422ToABGRRow_SSSE3;
}
}
#endif
#if defined(HAS_H422TOABGRROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
H422ToABGRRow = H422ToABGRRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
H422ToABGRRow = H422ToABGRRow_AVX2;
}
}
#endif
#if defined(HAS_H422TOABGRROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
H422ToABGRRow = H422ToABGRRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
H422ToABGRRow = H422ToABGRRow_NEON;
}
}
#endif
#if defined(HAS_H422TOABGRROW_MIPS_DSPR2)
if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
IS_ALIGNED(dst_abgr, 4) && IS_ALIGNED(dst_stride_abgr, 4)) {
H422ToABGRRow = H422ToABGRRow_MIPS_DSPR2;
}
#endif
for (y = 0; y < height; ++y) {
H422ToABGRRow(src_y, src_u, src_v, dst_abgr, width);
dst_abgr += dst_stride_abgr;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
......@@ -46,6 +46,8 @@ ANY31(I422ToARGBRow_Any_SSSE3, I422ToARGBRow_SSSE3, 1, 0, 4, 7)
ANY31(I422ToABGRRow_Any_SSSE3, I422ToABGRRow_SSSE3, 1, 0, 4, 7)
ANY31(J422ToARGBRow_Any_SSSE3, J422ToARGBRow_SSSE3, 1, 0, 4, 7)
ANY31(J422ToABGRRow_Any_SSSE3, J422ToABGRRow_SSSE3, 1, 0, 4, 7)
ANY31(H422ToARGBRow_Any_SSSE3, H422ToARGBRow_SSSE3, 1, 0, 4, 7)
ANY31(H422ToABGRRow_Any_SSSE3, H422ToABGRRow_SSSE3, 1, 0, 4, 7)
#endif
#ifdef HAS_I444TOARGBROW_SSSE3
ANY31(I444ToARGBRow_Any_SSSE3, I444ToARGBRow_SSSE3, 0, 0, 4, 7)
......@@ -72,6 +74,12 @@ ANY31(J422ToARGBRow_Any_AVX2, J422ToARGBRow_AVX2, 1, 0, 4, 15)
#ifdef HAS_J422TOABGRROW_AVX2
ANY31(J422ToABGRRow_Any_AVX2, J422ToABGRRow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_H422TOARGBROW_AVX2
ANY31(H422ToARGBRow_Any_AVX2, H422ToARGBRow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_H422TOABGRROW_AVX2
ANY31(H422ToABGRRow_Any_AVX2, H422ToABGRRow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_I422TOARGBROW_AVX2
ANY31(I422ToARGBRow_Any_AVX2, I422ToARGBRow_AVX2, 1, 0, 4, 15)
#endif
......
......@@ -1010,7 +1010,7 @@ void J400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) {
#define VG 52 /* round(0.813 * 64) */
#define VR -102 /* round(-1.596 * 64) */
// Bias values to subtract 16 from Y and 128 from U and V.
// Bias values to subtract 16 from Y and 128 from U and V, with rounding.
#define BB (UB * 128 + YGB)
#define BG (UG * 128 + VG * 128 + YGB)
#define BR (VR * 128 + YGB)
......@@ -1058,7 +1058,7 @@ static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) {
#define VGJ 46 /* round(0.71414 * 64) */
#define VRJ -90 /* round(-1.40200 * 64) */
// Bias values to subtract 16 from Y and 128 from U and V.
// Bias values to round Y and subtract 128 from U and V.
#define BBJ (UBJ * 128 + YGBJ)
#define BGJ (UGJ * 128 + VGJ * 128 + YGBJ)
#define BRJ (VRJ * 128 + YGBJ)
......@@ -1082,6 +1082,46 @@ static __inline void YuvJPixel(uint8 y, uint8 u, uint8 v,
#undef BGJ
#undef BRJ
// BT.709 YUV to RGB reference
// * R = Y - V * -1.28033
// * G = Y - U * 0.21482 - V * 0.38059
// * B = Y - U * -2.12798
// Y contribution to R,G,B. Scale and bias.
// TODO(fbarchard): Consider moving constants into a common header.
#define YGH 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
#define YGBH 32 /* 64 / 2 */
// U and V contributions to R,G,B.
#define UBH -128 /* max(-128, round(-2.12798 * 64)) */
#define UGH 14 /* round(0.21482 * 64) */
#define VGH 24 /* round(0.38059 * 64) */
#define VRH -82 /* round(-1.28033 * 64) */
// Bias values to round, and subtract 128 from U and V.
#define BBH (UBH * 128 + YGBH)
#define BGH (UGH * 128 + VGH * 128 + YGBH)
#define BRH (VRH * 128 + YGBH)
// C reference code that mimics the YUV assembly.
static __inline void YuvHPixel(uint8 y, uint8 u, uint8 v,
uint8* b, uint8* g, uint8* r) {
uint32 y1 = (uint32)(y * 0x0101 * YGH) >> 16;
*b = Clamp((int32)(-(u * UBH) + y1 + BBH) >> 6);
*g = Clamp((int32)(-(v * VGH + u * UGH) + y1 + BGH) >> 6);
*r = Clamp((int32)(-(v * VRH) + y1 + BRH) >> 6);
}
#undef YGH
#undef YGBH
#undef UBH
#undef UGH
#undef VGH
#undef VRH
#undef BBH
#undef BGH
#undef BRH
#if !defined(LIBYUV_DISABLE_NEON) && \
(defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON))
// C mimic assembly.
......@@ -1204,6 +1244,58 @@ void J422ToABGRRow_C(const uint8* src_y,
}
}
// TODO(fbarchard): replace with common matrix function.
void H422ToARGBRow_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* rgb_buf,
int width) {
int x;
for (x = 0; x < width - 1; x += 2) {
YuvHPixel(src_y[0], src_u[0], src_v[0],
rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
rgb_buf[3] = 255;
YuvHPixel(src_y[1], src_u[0], src_v[0],
rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
rgb_buf[7] = 255;
src_y += 2;
src_u += 1;
src_v += 1;
rgb_buf += 8; // Advance 2 pixels.
}
if (width & 1) {
YuvHPixel(src_y[0], src_u[0], src_v[0],
rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
rgb_buf[3] = 255;
}
}
void H422ToABGRRow_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
uint8* rgb_buf,
int width) {
int x;
for (x = 0; x < width - 1; x += 2) {
YuvHPixel(src_y[0], src_u[0], src_v[0],
rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
rgb_buf[3] = 255;
YuvHPixel(src_y[1], src_u[0], src_v[0],
rgb_buf + 6, rgb_buf + 5, rgb_buf + 4);
rgb_buf[7] = 255;
src_y += 2;
src_u += 1;
src_v += 1;
rgb_buf += 8; // Advance 2 pixels.
}
if (width & 1) {
YuvHPixel(src_y[0], src_u[0], src_v[0],
rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
rgb_buf[3] = 255;
}
}
void I422ToRGB24Row_C(const uint8* src_y,
const uint8* src_u,
const uint8* src_v,
......@@ -2183,6 +2275,7 @@ void I422ToUYVYRow_C(const uint8* src_y,
extern struct YuvConstants kYuvConstants;
extern struct YuvConstants kYuvJConstants;
extern struct YuvConstants kYuvHConstants;
#define ANYYUV(NAMEANY, ANY_SIMD, YUVCONSTANTS) \
void NAMEANY(const uint8* y_buf, \
......@@ -2196,18 +2289,22 @@ extern struct YuvConstants kYuvJConstants;
#ifdef HAS_I422TOARGBMATRIXROW_SSSE3
ANYYUV(I422ToARGBRow_SSSE3, I422ToARGBMatrixRow_SSSE3, kYuvConstants)
ANYYUV(J422ToARGBRow_SSSE3, I422ToARGBMatrixRow_SSSE3, kYuvJConstants)
ANYYUV(H422ToARGBRow_SSSE3, I422ToARGBMatrixRow_SSSE3, kYuvHConstants)
#endif
#ifdef HAS_I422TOARGBMATRIXROW_AVX2
ANYYUV(I422ToARGBRow_AVX2, I422ToARGBMatrixRow_AVX2, kYuvConstants)
ANYYUV(J422ToARGBRow_AVX2, I422ToARGBMatrixRow_AVX2, kYuvJConstants)
ANYYUV(H422ToARGBRow_AVX2, I422ToARGBMatrixRow_AVX2, kYuvHConstants)
#endif
#ifdef HAS_I422TOABGRMATRIXROW_SSSE3
ANYYUV(I422ToABGRRow_SSSE3, I422ToABGRMatrixRow_SSSE3, kYuvConstants)
ANYYUV(J422ToABGRRow_SSSE3, I422ToABGRMatrixRow_SSSE3, kYuvJConstants)
ANYYUV(H422ToABGRRow_SSSE3, I422ToABGRMatrixRow_SSSE3, kYuvHConstants)
#endif
#ifdef HAS_I422TOABGRMATRIXROW_AVX2
ANYYUV(I422ToABGRRow_AVX2, I422ToABGRMatrixRow_AVX2, kYuvConstants)
ANYYUV(J422ToABGRRow_AVX2, I422ToABGRMatrixRow_AVX2, kYuvJConstants)
ANYYUV(H422ToABGRRow_AVX2, I422ToABGRMatrixRow_AVX2, kYuvHConstants)
#endif
// Maximum temporary width for wrappers to process at a time, in pixels.
......
......@@ -1429,6 +1429,57 @@ YuvConstants SIMD_ALIGNED(kYuvJConstants) = {
#undef BGJ
#undef BRJ
// BT.709 YUV to RGB reference
// * R = Y - V * -1.28033
// * G = Y - U * 0.21482 - V * 0.38059
// * B = Y - U * -2.12798
// Y contribution to R,G,B. Scale and bias.
// TODO(fbarchard): Consider moving constants into a common header.
#define YGH 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
#define YGBH 32 /* 64 / 2 */
// U and V contributions to R,G,B.
#define UBH -128 /* max(-128, round(-2.12798 * 64)) */
#define UGH 14 /* round(0.21482 * 64) */
#define VGH 24 /* round(0.38059 * 64) */
#define VRH -82 /* round(-1.28033 * 64) */
// Bias values to round, and subtract 128 from U and V.
#define BBH (UBH * 128 + YGBH)
#define BGH (UGH * 128 + VGH * 128 + YGBH)
#define BRH (VRH * 128 + YGBH)
// BT.709 constants for YUV to RGB.
YuvConstants SIMD_ALIGNED(kYuvHConstants) = {
{ UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0,
UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0 },
{ UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH },
{ 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH,
0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH },
{ BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH,
BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH },
{ BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH,
BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH },
{ BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH,
BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH },
{ YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH,
YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH }
};
#undef YGH
#undef YGBH
#undef UBH
#undef UGH
#undef VGH
#undef VRH
#undef BBH
#undef BGH
#undef BRH
// Read 8 UV from 411
#define READYUV444 \
"movq " MEMACCESS([u_buf]) ",%%xmm0 \n" \
......
......@@ -143,6 +143,57 @@ YuvConstants SIMD_ALIGNED(kYuvJConstants) = {
#undef BGJ
#undef BRJ
// BT.709 YUV to RGB reference
// * R = Y - V * -1.28033
// * G = Y - U * 0.21482 - V * 0.38059
// * B = Y - U * -2.12798
// Y contribution to R,G,B. Scale and bias.
// TODO(fbarchard): Consider moving constants into a common header.
#define YGH 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
#define YGBH 32 /* 64 / 2 */
// U and V contributions to R,G,B.
#define UBH -128 /* max(-128, round(-2.12798 * 64)) */
#define UGH 14 /* round(0.21482 * 64) */
#define VGH 24 /* round(0.38059 * 64) */
#define VRH -82 /* round(-1.28033 * 64) */
// Bias values to round, and subtract 128 from U and V.
#define BBH (UBH * 128 + YGBH)
#define BGH (UGH * 128 + VGH * 128 + YGBH)
#define BRH (VRH * 128 + YGBH)
// BT.709 constants for YUV to RGB.
YuvConstants SIMD_ALIGNED(kYuvHConstants) = {
{ UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0,
UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0 },
{ UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH,
UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH },
{ 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH,
0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH },
{ BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH,
BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH },
{ BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH,
BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH },
{ BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH,
BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH },
{ YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH,
YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH }
};
#undef YGH
#undef YGBH
#undef UBH
#undef UGH
#undef VGH
#undef VRH
#undef BBH
#undef BGH
#undef BRH
// 64 bit
#if defined(_M_X64)
......
......@@ -493,6 +493,8 @@ TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) { \
TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(J420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(J420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(H420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(H420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1, 2, ARGB, 4)
......@@ -504,6 +506,8 @@ TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1, 17, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(J422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(J422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(H422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(H422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1, 2, ARGB, 4)
......@@ -516,8 +520,6 @@ TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4)
TESTPLANARTOB(J420, 2, 2, J400, 1, 1, 1, 0, ARGB, 4)
#define TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
YALIGN, W1280, DIFF, N, NEG, OFF) \
TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) { \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment