aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libyuv/convert_from.h12
-rw-r--r--source/convert_from.cc129
-rw-r--r--source/row_gcc.cc3
-rw-r--r--unit_test/convert_test.cc7
4 files changed, 142 insertions, 9 deletions
diff --git a/include/libyuv/convert_from.h b/include/libyuv/convert_from.h
index 237f68f5..8c3999bb 100644
--- a/include/libyuv/convert_from.h
+++ b/include/libyuv/convert_from.h
@@ -276,6 +276,18 @@ int I420ToARGB4444(const uint8* src_y,
int dst_stride_frame,
int width,
int height);
+// Convert I420 to AR30.
+LIBYUV_API
+int I420ToAR30(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_ar30,
+ int dst_stride_ar30,
+ int width,
+ int height);
// Convert I420 to specified format.
// "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the
diff --git a/source/convert_from.cc b/source/convert_from.cc
index 0f52f9ef..509fe232 100644
--- a/source/convert_from.cc
+++ b/source/convert_from.cc
@@ -1125,6 +1125,122 @@ int I420ToRGB565Dither(const uint8* src_y,
return 0;
}
+// Convert I420 to AR30 with matrix
+static int I420ToAR30Matrix(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_ar30,
+ int dst_stride_ar30,
+ const struct YuvConstants* yuvconstants,
+ int width,
+ int height) {
+ int y;
+ void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf,
+ const uint8* v_buf, uint8* rgb_buf,
+ const struct YuvConstants* yuvconstants, int width) =
+ I422ToARGBRow_C;
+ void (*ARGBToAR30Row)(const uint8* src_argb, uint8* dst_rgb, int width) =
+ ARGBToAR30Row_C;
+
+ if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
+ return -1;
+ }
+ // Negative height means invert the image.
+ if (height < 0) {
+ height = -height;
+ dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
+ dst_stride_ar30 = -dst_stride_ar30;
+ }
+
+#if defined(HAS_ARGBTOAR30ROW_SSSE3)
+ if (TestCpuFlag(kCpuHasSSSE3)) {
+ ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3;
+ if (IS_ALIGNED(width, 4)) {
+ ARGBToAR30Row = ARGBToAR30Row_SSSE3;
+ }
+ }
+#endif
+#if defined(HAS_ARGBTOAR30ROW_AVX2)
+ if (TestCpuFlag(kCpuHasAVX2)) {
+ ARGBToAR30Row = ARGBToAR30Row_Any_AVX2;
+ if (IS_ALIGNED(width, 8)) {
+ ARGBToAR30Row = ARGBToAR30Row_AVX2;
+ }
+ }
+#endif
+#if defined(HAS_I422TOARGBROW_SSSE3)
+ if (TestCpuFlag(kCpuHasSSSE3)) {
+ I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
+ if (IS_ALIGNED(width, 8)) {
+ I422ToARGBRow = I422ToARGBRow_SSSE3;
+ }
+ }
+#endif
+#if defined(HAS_I422TOARGBROW_AVX2)
+ if (TestCpuFlag(kCpuHasAVX2)) {
+ I422ToARGBRow = I422ToARGBRow_Any_AVX2;
+ if (IS_ALIGNED(width, 16)) {
+ I422ToARGBRow = I422ToARGBRow_AVX2;
+ }
+ }
+#endif
+#if defined(HAS_I422TOARGBROW_NEON)
+ if (TestCpuFlag(kCpuHasNEON)) {
+ I422ToARGBRow = I422ToARGBRow_Any_NEON;
+ if (IS_ALIGNED(width, 8)) {
+ I422ToARGBRow = I422ToARGBRow_NEON;
+ }
+ }
+#endif
+#if defined(HAS_I422TOARGBROW_MSA)
+ if (TestCpuFlag(kCpuHasMSA)) {
+ I422ToARGBRow = I422ToARGBRow_Any_MSA;
+ if (IS_ALIGNED(width, 8)) {
+ I422ToARGBRow = I422ToARGBRow_MSA;
+ }
+ }
+#endif
+
+ {
+ // Row buffer for ARGB.
+ align_buffer_64(row_argb, width * 4);
+
+ for (y = 0; y < height; ++y) {
+ I422ToARGBRow(src_y, src_u, src_v, row_argb, yuvconstants, width);
+ ARGBToAR30Row(row_argb, dst_ar30, width);
+ dst_ar30 += dst_stride_ar30;
+ src_y += src_stride_y;
+ if (y & 1) {
+ src_u += src_stride_u;
+ src_v += src_stride_v;
+ }
+ }
+
+ free_aligned_buffer_64(row_argb);
+ }
+ return 0;
+}
+
+// Convert I420 to AR30.
+LIBYUV_API
+int I420ToAR30(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_ar30,
+ int dst_stride_ar30,
+ int width,
+ int height) {
+ return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
+ src_stride_v, dst_ar30, dst_stride_ar30,
+ &kYuvI601Constants, width, height);
+}
+
// Convert I420 to specified format
LIBYUV_API
int ConvertFromI420(const uint8* y,
@@ -1157,8 +1273,8 @@ int ConvertFromI420(const uint8* y,
break;
case FOURCC_RGBP:
r = I420ToRGB565(y, y_stride, u, u_stride, v, v_stride, dst_sample,
- dst_sample_stride ? dst_sample_stride : width * 2, width,
- height);
+ dst_sample_stride ? dst_sample_stride : width * 2,
+ width, height);
break;
case FOURCC_RGBO:
r = I420ToARGB1555(y, y_stride, u, u_stride, v, v_stride, dst_sample,
@@ -1172,8 +1288,8 @@ int ConvertFromI420(const uint8* y,
break;
case FOURCC_24BG:
r = I420ToRGB24(y, y_stride, u, u_stride, v, v_stride, dst_sample,
- dst_sample_stride ? dst_sample_stride : width * 3, width,
- height);
+ dst_sample_stride ? dst_sample_stride : width * 3,
+ width, height);
break;
case FOURCC_RAW:
r = I420ToRAW(y, y_stride, u, u_stride, v, v_stride, dst_sample,
@@ -1200,6 +1316,11 @@ int ConvertFromI420(const uint8* y,
dst_sample_stride ? dst_sample_stride : width * 4, width,
height);
break;
+ case FOURCC_AR30:
+ r = I420ToAR30(y, y_stride, u, u_stride, v, v_stride, dst_sample,
+ dst_sample_stride ? dst_sample_stride : width * 4, width,
+ height);
+ break;
case FOURCC_I400:
r = I400Copy(y, y_stride, dst_sample,
dst_sample_stride ? dst_sample_stride : width, width,
diff --git a/source/row_gcc.cc b/source/row_gcc.cc
index 4eda0597..10781cba 100644
--- a/source/row_gcc.cc
+++ b/source/row_gcc.cc
@@ -802,8 +802,7 @@ void ARGBToAR30Row_AVX2(const uint8* src, uint8* dst, int width) {
"m"(kMaskRB10), // %5
"m"(kMaskAG10), // %6
"m"(kMulAG10) // %7
- : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
- "xmm6");
+ : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
}
#endif
diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc
index 394bb782..ec04530f 100644
--- a/unit_test/convert_test.cc
+++ b/unit_test/convert_test.cc
@@ -30,6 +30,9 @@
namespace libyuv {
+// Alias to copy pixels as is
+#define AR30ToAR30 ARGBCopy
+
#define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
#define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
@@ -597,6 +600,7 @@ TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4)
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)
+TESTPLANARTOB(I420, 2, 2, AR30, 4, 4, 1, 0, AR30, 4)
#define TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
YALIGN, W1280, DIFF, N, NEG, OFF, ATTEN) \
@@ -1967,9 +1971,6 @@ TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) {
}
#endif // HAS_ARGBTOAR30ROW_AVX2
-// Alias to copy pixels as is
-#define AR30ToAR30 ARGBToARGB
-
#define TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \
ALIGN, YALIGN, W1280, DIFF, N, NEG, SOFF, DOFF, \
FMT_C, BPP_C) \