Index: source/libvpx/third_party/libyuv/source/planar_functions.cc |
diff --git a/source/libvpx/third_party/libyuv/source/planar_functions.cc b/source/libvpx/third_party/libyuv/source/planar_functions.cc |
index 75ef775dde8c359f848b0a527324f3ee4b5ebd58..b96bd502062408875798d9d382054ebeddbb0ad0 100644 |
--- a/source/libvpx/third_party/libyuv/source/planar_functions.cc |
+++ b/source/libvpx/third_party/libyuv/source/planar_functions.cc |
@@ -528,7 +528,7 @@ int ARGBMirror(const uint8* src_argb, int src_stride_argb, |
return 0; |
} |
-// Get a blender that optimized for the CPU, alignment and pixel count. |
+// Get a blender that optimized for the CPU and pixel count. |
// As there are 6 blenders to choose from, the caller should try to use |
// the same blend function for all pixels if possible. |
LIBYUV_API |
@@ -677,12 +677,12 @@ int ARGBAdd(const uint8* src_argb0, int src_stride_argb0, |
height = 1; |
src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; |
} |
-#if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER) |
+#if defined(HAS_ARGBADDROW_SSE2) && (defined(_MSC_VER) && !defined(__clang__)) |
if (TestCpuFlag(kCpuHasSSE2)) { |
ARGBAddRow = ARGBAddRow_SSE2; |
} |
#endif |
-#if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER) |
+#if defined(HAS_ARGBADDROW_SSE2) && !(defined(_MSC_VER) && !defined(__clang__)) |
if (TestCpuFlag(kCpuHasSSE2)) { |
ARGBAddRow = ARGBAddRow_Any_SSE2; |
if (IS_ALIGNED(width, 4)) { |
@@ -1976,8 +1976,8 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, |
const uint8* src_sobely, |
uint8* dst, int width)) { |
int y; |
- void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, |
- uint32 selector, int pix) = ARGBToBayerGGRow_C; |
+ void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_g, int pix) = |
+ ARGBToYJRow_C; |
void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1, |
uint8* dst_sobely, int width) = SobelYRow_C; |
void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1, |
@@ -1993,31 +1993,32 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, |
src_argb = src_argb + (height - 1) * src_stride_argb; |
src_stride_argb = -src_stride_argb; |
} |
- // ARGBToBayer used to select G channel from ARGB. |
-#if defined(HAS_ARGBTOBAYERGGROW_SSE2) |
- if (TestCpuFlag(kCpuHasSSE2)) { |
- ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2; |
- if (IS_ALIGNED(width, 8)) { |
- ARGBToBayerRow = ARGBToBayerGGRow_SSE2; |
+ |
+#if defined(HAS_ARGBTOYJROW_SSSE3) |
+ if (TestCpuFlag(kCpuHasSSSE3)) { |
+ ARGBToYJRow = ARGBToYJRow_Any_SSSE3; |
+ if (IS_ALIGNED(width, 16)) { |
+ ARGBToYJRow = ARGBToYJRow_SSSE3; |
} |
} |
#endif |
-#if defined(HAS_ARGBTOBAYERROW_SSSE3) |
- if (TestCpuFlag(kCpuHasSSSE3)) { |
- ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; |
- if (IS_ALIGNED(width, 8)) { |
- ARGBToBayerRow = ARGBToBayerRow_SSSE3; |
+#if defined(HAS_ARGBTOYJROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ ARGBToYJRow = ARGBToYJRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 32)) { |
+ ARGBToYJRow = ARGBToYJRow_AVX2; |
} |
} |
#endif |
-#if defined(HAS_ARGBTOBAYERGGROW_NEON) |
+#if defined(HAS_ARGBTOYJROW_NEON) |
if (TestCpuFlag(kCpuHasNEON)) { |
- ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON; |
+ ARGBToYJRow = ARGBToYJRow_Any_NEON; |
if (IS_ALIGNED(width, 8)) { |
- ARGBToBayerRow = ARGBToBayerGGRow_NEON; |
+ ARGBToYJRow = ARGBToYJRow_NEON; |
} |
} |
#endif |
+ |
#if defined(HAS_SOBELYROW_SSE2) |
if (TestCpuFlag(kCpuHasSSE2)) { |
SobelYRow = SobelYRow_SSE2; |
@@ -2040,7 +2041,7 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, |
#endif |
{ |
// 3 rows with edges before/after. |
- const int kRowSize = (width + kEdge + 15) & ~15; |
+ const int kRowSize = (width + kEdge + 31) & ~31; |
align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge)); |
uint8* row_sobelx = rows; |
uint8* row_sobely = rows + kRowSize; |
@@ -2050,20 +2051,20 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, |
uint8* row_y0 = row_y + kEdge; |
uint8* row_y1 = row_y0 + kRowSize; |
uint8* row_y2 = row_y1 + kRowSize; |
- ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width); |
+ ARGBToYJRow(src_argb, row_y0, width); |
row_y0[-1] = row_y0[0]; |
memset(row_y0 + width, row_y0[width - 1], 16); // Extrude 16 for valgrind. |
- ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width); |
+ ARGBToYJRow(src_argb, row_y1, width); |
row_y1[-1] = row_y1[0]; |
memset(row_y1 + width, row_y1[width - 1], 16); |
memset(row_y2 + width, 0, 16); |
for (y = 0; y < height; ++y) { |
- // Convert next row of ARGB to Y. |
+ // Convert next row of ARGB to G. |
if (y < (height - 1)) { |
src_argb += src_stride_argb; |
} |
- ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width); |
+ ARGBToYJRow(src_argb, row_y2, width); |
row_y2[-1] = row_y2[0]; |
row_y2[width] = row_y2[width - 1]; |
@@ -2094,13 +2095,19 @@ int ARGBSobel(const uint8* src_argb, int src_stride_argb, |
void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely, |
uint8* dst_argb, int width) = SobelRow_C; |
#if defined(HAS_SOBELROW_SSE2) |
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { |
- SobelRow = SobelRow_SSE2; |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ SobelRow = SobelRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ SobelRow = SobelRow_SSE2; |
+ } |
} |
#endif |
#if defined(HAS_SOBELROW_NEON) |
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { |
- SobelRow = SobelRow_NEON; |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ SobelRow = SobelRow_Any_NEON; |
+ if (IS_ALIGNED(width, 8)) { |
+ SobelRow = SobelRow_NEON; |
+ } |
} |
#endif |
return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, |
@@ -2115,13 +2122,19 @@ int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, |
void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely, |
uint8* dst_, int width) = SobelToPlaneRow_C; |
#if defined(HAS_SOBELTOPLANEROW_SSE2) |
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { |
- SobelToPlaneRow = SobelToPlaneRow_SSE2; |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ SobelToPlaneRow = SobelToPlaneRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ SobelToPlaneRow = SobelToPlaneRow_SSE2; |
+ } |
} |
#endif |
#if defined(HAS_SOBELTOPLANEROW_NEON) |
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { |
- SobelToPlaneRow = SobelToPlaneRow_NEON; |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ SobelToPlaneRow = SobelToPlaneRow_Any_NEON; |
+ if (IS_ALIGNED(width, 16)) { |
+ SobelToPlaneRow = SobelToPlaneRow_NEON; |
+ } |
} |
#endif |
return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y, |
@@ -2137,13 +2150,19 @@ int ARGBSobelXY(const uint8* src_argb, int src_stride_argb, |
void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely, |
uint8* dst_argb, int width) = SobelXYRow_C; |
#if defined(HAS_SOBELXYROW_SSE2) |
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { |
- SobelXYRow = SobelXYRow_SSE2; |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ SobelXYRow = SobelXYRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ SobelXYRow = SobelXYRow_SSE2; |
+ } |
} |
#endif |
#if defined(HAS_SOBELXYROW_NEON) |
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { |
- SobelXYRow = SobelXYRow_NEON; |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ SobelXYRow = SobelXYRow_Any_NEON; |
+ if (IS_ALIGNED(width, 8)) { |
+ SobelXYRow = SobelXYRow_NEON; |
+ } |
} |
#endif |
return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, |
@@ -2322,6 +2341,214 @@ int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, |
return 0; |
} |
+LIBYUV_API |
+int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2, |
+ uint8* dst_y, int dst_stride_y, |
+ uint8* dst_uv, int dst_stride_uv, |
+ int width, int height) { |
+ int y; |
+ int halfwidth = (width + 1) >> 1; |
+ void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) = |
+ SplitUVRow_C; |
+ void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, |
+ ptrdiff_t src_stride, int dst_width, |
+ int source_y_fraction) = InterpolateRow_C; |
+ if (!src_yuy2 || |
+ !dst_y || !dst_uv || |
+ width <= 0 || height == 0) { |
+ return -1; |
+ } |
+ // Negative height means invert the image. |
+ if (height < 0) { |
+ height = -height; |
+ src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; |
+ src_stride_yuy2 = -src_stride_yuy2; |
+ } |
+#if defined(HAS_SPLITUVROW_SSE2) |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ SplitUVRow = SplitUVRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ SplitUVRow = SplitUVRow_SSE2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_SPLITUVROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ SplitUVRow = SplitUVRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 32)) { |
+ SplitUVRow = SplitUVRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_SPLITUVROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ SplitUVRow = SplitUVRow_Any_NEON; |
+ if (IS_ALIGNED(width, 16)) { |
+ SplitUVRow = SplitUVRow_NEON; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_SSE2) |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ InterpolateRow = InterpolateRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_SSE2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_SSSE3) |
+ if (TestCpuFlag(kCpuHasSSSE3)) { |
+ InterpolateRow = InterpolateRow_Any_SSSE3; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_SSSE3; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ InterpolateRow = InterpolateRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 32)) { |
+ InterpolateRow = InterpolateRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ InterpolateRow = InterpolateRow_Any_NEON; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_NEON; |
+ } |
+ } |
+#endif |
+ |
+ { |
+ int awidth = halfwidth * 2; |
+ // 2 rows of uv |
+ align_buffer_64(rows, awidth * 2); |
+ |
+ for (y = 0; y < height - 1; y += 2) { |
+ // Split Y from UV. |
+ SplitUVRow(src_yuy2, dst_y, rows, awidth); |
+ SplitUVRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, |
+ rows + awidth, awidth); |
+ InterpolateRow(dst_uv, rows, awidth, awidth, 128); |
+ src_yuy2 += src_stride_yuy2 * 2; |
+ dst_y += dst_stride_y * 2; |
+ dst_uv += dst_stride_uv; |
+ } |
+ if (height & 1) { |
+ // Split Y from UV. |
+ SplitUVRow(src_yuy2, dst_y, dst_uv, width); |
+ } |
+ free_aligned_buffer_64(rows); |
+ } |
+ return 0; |
+} |
+ |
+LIBYUV_API |
+int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, |
+ uint8* dst_y, int dst_stride_y, |
+ uint8* dst_uv, int dst_stride_uv, |
+ int width, int height) { |
+ int y; |
+ int halfwidth = (width + 1) >> 1; |
+ void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) = |
+ SplitUVRow_C; |
+ void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, |
+ ptrdiff_t src_stride, int dst_width, |
+ int source_y_fraction) = InterpolateRow_C; |
+ if (!src_uyvy || |
+ !dst_y || !dst_uv || |
+ width <= 0 || height == 0) { |
+ return -1; |
+ } |
+ // Negative height means invert the image. |
+ if (height < 0) { |
+ height = -height; |
+ src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; |
+ src_stride_uyvy = -src_stride_uyvy; |
+ } |
+#if defined(HAS_SPLITUVROW_SSE2) |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ SplitUVRow = SplitUVRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ SplitUVRow = SplitUVRow_SSE2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_SPLITUVROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ SplitUVRow = SplitUVRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 32)) { |
+ SplitUVRow = SplitUVRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_SPLITUVROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ SplitUVRow = SplitUVRow_Any_NEON; |
+ if (IS_ALIGNED(width, 16)) { |
+ SplitUVRow = SplitUVRow_NEON; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_SSE2) |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ InterpolateRow = InterpolateRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_SSE2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_SSSE3) |
+ if (TestCpuFlag(kCpuHasSSSE3)) { |
+ InterpolateRow = InterpolateRow_Any_SSSE3; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_SSSE3; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ InterpolateRow = InterpolateRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 32)) { |
+ InterpolateRow = InterpolateRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_INTERPOLATEROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ InterpolateRow = InterpolateRow_Any_NEON; |
+ if (IS_ALIGNED(width, 16)) { |
+ InterpolateRow = InterpolateRow_NEON; |
+ } |
+ } |
+#endif |
+ |
+ { |
+ int awidth = halfwidth * 2; |
+ // 2 rows of uv |
+ align_buffer_64(rows, awidth * 2); |
+ |
+ for (y = 0; y < height - 1; y += 2) { |
+ // Split Y from UV. |
+ SplitUVRow(src_uyvy, rows, dst_y, awidth); |
+ SplitUVRow(src_uyvy + src_stride_uyvy, rows + awidth, |
+ dst_y + dst_stride_y, awidth); |
+ InterpolateRow(dst_uv, rows, awidth, awidth, 128); |
+ src_uyvy += src_stride_uyvy * 2; |
+ dst_y += dst_stride_y * 2; |
+ dst_uv += dst_stride_uv; |
+ } |
+ if (height & 1) { |
+ // Split Y from UV. |
+ SplitUVRow(src_uyvy, dst_y, dst_uv, width); |
+ } |
+ free_aligned_buffer_64(rows); |
+ } |
+ return 0; |
+} |
+ |
#ifdef __cplusplus |
} // extern "C" |
} // namespace libyuv |