diff --git a/README.chromium b/README.chromium index 5030755f3..e93aa1ac7 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1207 +Version: 1211 License: BSD License File: LICENSE diff --git a/include/libyuv/convert_argb.h b/include/libyuv/convert_argb.h index a18014ca2..e12b4e88f 100644 --- a/include/libyuv/convert_argb.h +++ b/include/libyuv/convert_argb.h @@ -123,6 +123,14 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_argb, int dst_stride_argb, int width, int height); +// Convert J420 to ARGB. +LIBYUV_API +int J420ToARGB(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); + // BGRA little endian (argb in memory) to ARGB. LIBYUV_API int BGRAToARGB(const uint8* src_frame, int src_stride_frame, diff --git a/include/libyuv/row.h b/include/libyuv/row.h index 5b17cf426..cc4344f41 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -96,6 +96,8 @@ extern "C" { #define HAS_I422TOUYVYROW_SSE2 #define HAS_I422TOYUY2ROW_SSE2 #define HAS_I444TOARGBROW_SSSE3 +// TODO(fbarchard): Implement SSSE3 version of J422ToARGB +//#define HAS_J422TOARGBROW_SSSE3 #define HAS_MERGEUVROW_SSE2 #define HAS_MIRRORROW_SSE2 #define HAS_MIRRORROW_SSSE3 @@ -928,6 +930,11 @@ void YUY2ToARGBRow_C(const uint8* src_yuy2, void UYVYToARGBRow_C(const uint8* src_uyvy, uint8* dst_argb, int width); +void J422ToARGBRow_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, @@ -1028,6 +1035,11 @@ void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2, void UYVYToARGBRow_SSSE3(const uint8* src_uyvy, uint8* dst_argb, int width); +void J422ToARGBRow_SSSE3(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, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 7ff0d73b5..be22e201f 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1207 +#define LIBYUV_VERSION 1211 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/convert_argb.cc b/source/convert_argb.cc index 690636464..c8a4bb569 100644 --- a/source/convert_argb.cc +++ b/source/convert_argb.cc @@ -910,6 +910,75 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, return 0; } +// Convert J420 to ARGB. +LIBYUV_API +int J420ToARGB(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 (*J422ToARGBRow)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* rgb_buf, + int width) = J422ToARGBRow_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_J422TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + J422ToARGBRow = J422ToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + J422ToARGBRow = J422ToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_J422TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + J422ToARGBRow = J422ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + J422ToARGBRow = J422ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_J422TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + J422ToARGBRow = J422ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + J422ToARGBRow = J422ToARGBRow_NEON; + } + } +#endif +#if defined(HAS_J422TOARGBROW_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)) { + J422ToARGBRow = J422ToARGBRow_MIPS_DSPR2; + } +#endif + + for (y = 0; y < height; ++y) { + J422ToARGBRow(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; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/source/convert_to_argb.cc b/source/convert_to_argb.cc index 1b228a7b4..86480719f 100644 --- a/source/convert_to_argb.cc +++ b/source/convert_to_argb.cc @@ -241,6 +241,25 @@ int ConvertToARGB(const uint8* sample, size_t sample_size, crop_width, inv_crop_height); break; } + + case FOURCC_J420: { + const uint8* src_y = sample + (src_width * crop_y + crop_x); + const uint8* src_u; + const uint8* src_v; + int halfwidth = (src_width + 1) / 2; + int halfheight = (abs_src_height + 1) / 2; + src_u = sample + src_width * abs_src_height + + (halfwidth * crop_y + crop_x) / 2; + src_v = sample + src_width * abs_src_height + + halfwidth * (halfheight + crop_y / 2) + crop_x / 2; + r = J420ToARGB(src_y, src_width, + src_u, halfwidth, + src_v, halfwidth, + crop_argb, argb_stride, + crop_width, inv_crop_height); + break; + } + case FOURCC_I422: case FOURCC_YV16: { const uint8* src_y = sample + src_width * crop_y + crop_x; diff --git a/source/row_any.cc b/source/row_any.cc index f7c5cf766..253436993 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -62,6 +62,10 @@ YANY(I422ToRAWRow_Any_SSSE3, I422ToRAWRow_SSSE3, I422ToRAWRow_C, 1, 3, 7) YANY(I422ToYUY2Row_Any_SSE2, I422ToYUY2Row_SSE2, I422ToYUY2Row_C, 1, 2, 15) YANY(I422ToUYVYRow_Any_SSE2, I422ToUYVYRow_SSE2, I422ToUYVYRow_C, 1, 2, 15) #endif // HAS_I444TOARGBROW_SSSE3 +#ifdef HAS_J422TOARGBROW_SSSE3 +YANY(J422ToARGBRow_Any_SSSE3, J422ToARGBRow_SSSE3, J422ToARGBRow_C, + 1, 4, 7) +#endif // HAS_I422TOARGBROW_SSSE3 #ifdef HAS_I422TOARGBROW_AVX2 YANY(I422ToARGBRow_Any_AVX2, I422ToARGBRow_AVX2, I422ToARGBRow_C, 1, 4, 15) #endif // HAS_I422TOARGBROW_AVX2 diff --git a/source/row_common.cc b/source/row_common.cc index afc74c05c..489d62416 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -1008,6 +1008,7 @@ void I444ToARGBRow_C(const uint8* src_y, } } #endif + // Also used for 420 void I422ToARGBRow_C(const uint8* src_y, const uint8* src_u, @@ -1034,6 +1035,59 @@ void I422ToARGBRow_C(const uint8* src_y, } } +// C reference code that mimics the YUV assembly. +// * R = Y + 1.40200 * Cr +// * G = Y - 0.34414 * Cb - 0.71414 * Cr +// * B = Y + 1.77200 * Cb + +#define YGJ 64 /* (int8)(1.000 * 64) */ + +#define UBJ 113 /* (int8)(1.772 * 64) */ +#define UGJ -22 /* (int8)(-0.34414 * 64) */ +#define URJ 0 + +#define VBJ 0 +#define VGJ -46 /* (int8)(-0.71414 * 64) */ +#define VRJ 90 /* (int8)(1.402 * 64) */ + +// Bias +#define BBJ UBJ * 128 + VBJ * 128 +#define BGJ UGJ * 128 + VGJ * 128 +#define BRJ URJ * 128 + VRJ * 128 + +static __inline void YuvJPixel(uint8 y, uint8 u, uint8 v, + uint8* b, uint8* g, uint8* r) { + int32 y1 = ((int32)(y)) * YGJ; + *b = Clamp((int32)((u * UBJ + v * VBJ) - (BBJ) + y1) >> 6); + *g = Clamp((int32)((u * UGJ + v * VGJ) - (BGJ) + y1) >> 6); + *r = Clamp((int32)((u * URJ + v * VRJ) - (BRJ) + y1) >> 6); +} + +void J422ToARGBRow_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) { + YuvJPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf[3] = 255; + YuvJPixel(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) { + YuvJPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf[3] = 255; + } +} + void I422ToRGB24Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 86dd08867..8fd9c123e 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -499,6 +499,7 @@ TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) { \ // TODO(fbarchard): Make vertical alignment unnecessary on bayer. TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4) +TESTPLANARTOB(J420, 2, 2, ARGB, 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)