OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. | 2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 | 521 |
522 // Mirror plane | 522 // Mirror plane |
523 for (y = 0; y < height; ++y) { | 523 for (y = 0; y < height; ++y) { |
524 ARGBMirrorRow(src_argb, dst_argb, width); | 524 ARGBMirrorRow(src_argb, dst_argb, width); |
525 src_argb += src_stride_argb; | 525 src_argb += src_stride_argb; |
526 dst_argb += dst_stride_argb; | 526 dst_argb += dst_stride_argb; |
527 } | 527 } |
528 return 0; | 528 return 0; |
529 } | 529 } |
530 | 530 |
531 // Get a blender that optimized for the CPU, alignment and pixel count. | 531 // Get a blender that optimized for the CPU and pixel count. |
532 // As there are 6 blenders to choose from, the caller should try to use | 532 // As there are 6 blenders to choose from, the caller should try to use |
533 // the same blend function for all pixels if possible. | 533 // the same blend function for all pixels if possible. |
534 LIBYUV_API | 534 LIBYUV_API |
535 ARGBBlendRow GetARGBBlend() { | 535 ARGBBlendRow GetARGBBlend() { |
536 void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1, | 536 void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1, |
537 uint8* dst_argb, int width) = ARGBBlendRow_C; | 537 uint8* dst_argb, int width) = ARGBBlendRow_C; |
538 #if defined(HAS_ARGBBLENDROW_SSSE3) | 538 #if defined(HAS_ARGBBLENDROW_SSSE3) |
539 if (TestCpuFlag(kCpuHasSSSE3)) { | 539 if (TestCpuFlag(kCpuHasSSSE3)) { |
540 ARGBBlendRow = ARGBBlendRow_SSSE3; | 540 ARGBBlendRow = ARGBBlendRow_SSSE3; |
541 return ARGBBlendRow; | 541 return ARGBBlendRow; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 dst_stride_argb = -dst_stride_argb; | 670 dst_stride_argb = -dst_stride_argb; |
671 } | 671 } |
672 // Coalesce rows. | 672 // Coalesce rows. |
673 if (src_stride_argb0 == width * 4 && | 673 if (src_stride_argb0 == width * 4 && |
674 src_stride_argb1 == width * 4 && | 674 src_stride_argb1 == width * 4 && |
675 dst_stride_argb == width * 4) { | 675 dst_stride_argb == width * 4) { |
676 width *= height; | 676 width *= height; |
677 height = 1; | 677 height = 1; |
678 src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; | 678 src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; |
679 } | 679 } |
680 #if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER) | 680 #if defined(HAS_ARGBADDROW_SSE2) && (defined(_MSC_VER) && !defined(__clang__)) |
681 if (TestCpuFlag(kCpuHasSSE2)) { | 681 if (TestCpuFlag(kCpuHasSSE2)) { |
682 ARGBAddRow = ARGBAddRow_SSE2; | 682 ARGBAddRow = ARGBAddRow_SSE2; |
683 } | 683 } |
684 #endif | 684 #endif |
685 #if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER) | 685 #if defined(HAS_ARGBADDROW_SSE2) && !(defined(_MSC_VER) && !defined(__clang__)) |
686 if (TestCpuFlag(kCpuHasSSE2)) { | 686 if (TestCpuFlag(kCpuHasSSE2)) { |
687 ARGBAddRow = ARGBAddRow_Any_SSE2; | 687 ARGBAddRow = ARGBAddRow_Any_SSE2; |
688 if (IS_ALIGNED(width, 4)) { | 688 if (IS_ALIGNED(width, 4)) { |
689 ARGBAddRow = ARGBAddRow_SSE2; | 689 ARGBAddRow = ARGBAddRow_SSE2; |
690 } | 690 } |
691 } | 691 } |
692 #endif | 692 #endif |
693 #if defined(HAS_ARGBADDROW_AVX2) | 693 #if defined(HAS_ARGBADDROW_AVX2) |
694 if (TestCpuFlag(kCpuHasAVX2)) { | 694 if (TestCpuFlag(kCpuHasAVX2)) { |
695 ARGBAddRow = ARGBAddRow_Any_AVX2; | 695 ARGBAddRow = ARGBAddRow_Any_AVX2; |
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 } | 1969 } |
1970 | 1970 |
1971 // Sobel ARGB effect. | 1971 // Sobel ARGB effect. |
1972 static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, | 1972 static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, |
1973 uint8* dst_argb, int dst_stride_argb, | 1973 uint8* dst_argb, int dst_stride_argb, |
1974 int width, int height, | 1974 int width, int height, |
1975 void (*SobelRow)(const uint8* src_sobelx, | 1975 void (*SobelRow)(const uint8* src_sobelx, |
1976 const uint8* src_sobely, | 1976 const uint8* src_sobely, |
1977 uint8* dst, int width)) { | 1977 uint8* dst, int width)) { |
1978 int y; | 1978 int y; |
1979 void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, | 1979 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_g, int pix) = |
1980 uint32 selector, int pix) = ARGBToBayerGGRow_C; | 1980 ARGBToYJRow_C; |
1981 void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1, | 1981 void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1, |
1982 uint8* dst_sobely, int width) = SobelYRow_C; | 1982 uint8* dst_sobely, int width) = SobelYRow_C; |
1983 void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1, | 1983 void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1, |
1984 const uint8* src_y2, uint8* dst_sobely, int width) = | 1984 const uint8* src_y2, uint8* dst_sobely, int width) = |
1985 SobelXRow_C; | 1985 SobelXRow_C; |
1986 const int kEdge = 16; // Extra pixels at start of row for extrude/align. | 1986 const int kEdge = 16; // Extra pixels at start of row for extrude/align. |
1987 if (!src_argb || !dst_argb || width <= 0 || height == 0) { | 1987 if (!src_argb || !dst_argb || width <= 0 || height == 0) { |
1988 return -1; | 1988 return -1; |
1989 } | 1989 } |
1990 // Negative height means invert the image. | 1990 // Negative height means invert the image. |
1991 if (height < 0) { | 1991 if (height < 0) { |
1992 height = -height; | 1992 height = -height; |
1993 src_argb = src_argb + (height - 1) * src_stride_argb; | 1993 src_argb = src_argb + (height - 1) * src_stride_argb; |
1994 src_stride_argb = -src_stride_argb; | 1994 src_stride_argb = -src_stride_argb; |
1995 } | 1995 } |
1996 // ARGBToBayer used to select G channel from ARGB. | 1996 |
1997 #if defined(HAS_ARGBTOBAYERGGROW_SSE2) | 1997 #if defined(HAS_ARGBTOYJROW_SSSE3) |
1998 if (TestCpuFlag(kCpuHasSSE2)) { | 1998 if (TestCpuFlag(kCpuHasSSSE3)) { |
1999 ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2; | 1999 ARGBToYJRow = ARGBToYJRow_Any_SSSE3; |
2000 if (IS_ALIGNED(width, 8)) { | 2000 if (IS_ALIGNED(width, 16)) { |
2001 ARGBToBayerRow = ARGBToBayerGGRow_SSE2; | 2001 ARGBToYJRow = ARGBToYJRow_SSSE3; |
2002 } | 2002 } |
2003 } | 2003 } |
2004 #endif | 2004 #endif |
2005 #if defined(HAS_ARGBTOBAYERROW_SSSE3) | 2005 #if defined(HAS_ARGBTOYJROW_AVX2) |
2006 if (TestCpuFlag(kCpuHasSSSE3)) { | 2006 if (TestCpuFlag(kCpuHasAVX2)) { |
2007 ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; | 2007 ARGBToYJRow = ARGBToYJRow_Any_AVX2; |
2008 if (IS_ALIGNED(width, 8)) { | 2008 if (IS_ALIGNED(width, 32)) { |
2009 ARGBToBayerRow = ARGBToBayerRow_SSSE3; | 2009 ARGBToYJRow = ARGBToYJRow_AVX2; |
2010 } | 2010 } |
2011 } | 2011 } |
2012 #endif | 2012 #endif |
2013 #if defined(HAS_ARGBTOBAYERGGROW_NEON) | 2013 #if defined(HAS_ARGBTOYJROW_NEON) |
2014 if (TestCpuFlag(kCpuHasNEON)) { | 2014 if (TestCpuFlag(kCpuHasNEON)) { |
2015 ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON; | 2015 ARGBToYJRow = ARGBToYJRow_Any_NEON; |
2016 if (IS_ALIGNED(width, 8)) { | 2016 if (IS_ALIGNED(width, 8)) { |
2017 ARGBToBayerRow = ARGBToBayerGGRow_NEON; | 2017 ARGBToYJRow = ARGBToYJRow_NEON; |
2018 } | 2018 } |
2019 } | 2019 } |
2020 #endif | 2020 #endif |
| 2021 |
2021 #if defined(HAS_SOBELYROW_SSE2) | 2022 #if defined(HAS_SOBELYROW_SSE2) |
2022 if (TestCpuFlag(kCpuHasSSE2)) { | 2023 if (TestCpuFlag(kCpuHasSSE2)) { |
2023 SobelYRow = SobelYRow_SSE2; | 2024 SobelYRow = SobelYRow_SSE2; |
2024 } | 2025 } |
2025 #endif | 2026 #endif |
2026 #if defined(HAS_SOBELYROW_NEON) | 2027 #if defined(HAS_SOBELYROW_NEON) |
2027 if (TestCpuFlag(kCpuHasNEON)) { | 2028 if (TestCpuFlag(kCpuHasNEON)) { |
2028 SobelYRow = SobelYRow_NEON; | 2029 SobelYRow = SobelYRow_NEON; |
2029 } | 2030 } |
2030 #endif | 2031 #endif |
2031 #if defined(HAS_SOBELXROW_SSE2) | 2032 #if defined(HAS_SOBELXROW_SSE2) |
2032 if (TestCpuFlag(kCpuHasSSE2)) { | 2033 if (TestCpuFlag(kCpuHasSSE2)) { |
2033 SobelXRow = SobelXRow_SSE2; | 2034 SobelXRow = SobelXRow_SSE2; |
2034 } | 2035 } |
2035 #endif | 2036 #endif |
2036 #if defined(HAS_SOBELXROW_NEON) | 2037 #if defined(HAS_SOBELXROW_NEON) |
2037 if (TestCpuFlag(kCpuHasNEON)) { | 2038 if (TestCpuFlag(kCpuHasNEON)) { |
2038 SobelXRow = SobelXRow_NEON; | 2039 SobelXRow = SobelXRow_NEON; |
2039 } | 2040 } |
2040 #endif | 2041 #endif |
2041 { | 2042 { |
2042 // 3 rows with edges before/after. | 2043 // 3 rows with edges before/after. |
2043 const int kRowSize = (width + kEdge + 15) & ~15; | 2044 const int kRowSize = (width + kEdge + 31) & ~31; |
2044 align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge)); | 2045 align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge)); |
2045 uint8* row_sobelx = rows; | 2046 uint8* row_sobelx = rows; |
2046 uint8* row_sobely = rows + kRowSize; | 2047 uint8* row_sobely = rows + kRowSize; |
2047 uint8* row_y = rows + kRowSize * 2; | 2048 uint8* row_y = rows + kRowSize * 2; |
2048 | 2049 |
2049 // Convert first row. | 2050 // Convert first row. |
2050 uint8* row_y0 = row_y + kEdge; | 2051 uint8* row_y0 = row_y + kEdge; |
2051 uint8* row_y1 = row_y0 + kRowSize; | 2052 uint8* row_y1 = row_y0 + kRowSize; |
2052 uint8* row_y2 = row_y1 + kRowSize; | 2053 uint8* row_y2 = row_y1 + kRowSize; |
2053 ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width); | 2054 ARGBToYJRow(src_argb, row_y0, width); |
2054 row_y0[-1] = row_y0[0]; | 2055 row_y0[-1] = row_y0[0]; |
2055 memset(row_y0 + width, row_y0[width - 1], 16); // Extrude 16 for valgrind. | 2056 memset(row_y0 + width, row_y0[width - 1], 16); // Extrude 16 for valgrind. |
2056 ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width); | 2057 ARGBToYJRow(src_argb, row_y1, width); |
2057 row_y1[-1] = row_y1[0]; | 2058 row_y1[-1] = row_y1[0]; |
2058 memset(row_y1 + width, row_y1[width - 1], 16); | 2059 memset(row_y1 + width, row_y1[width - 1], 16); |
2059 memset(row_y2 + width, 0, 16); | 2060 memset(row_y2 + width, 0, 16); |
2060 | 2061 |
2061 for (y = 0; y < height; ++y) { | 2062 for (y = 0; y < height; ++y) { |
2062 // Convert next row of ARGB to Y. | 2063 // Convert next row of ARGB to G. |
2063 if (y < (height - 1)) { | 2064 if (y < (height - 1)) { |
2064 src_argb += src_stride_argb; | 2065 src_argb += src_stride_argb; |
2065 } | 2066 } |
2066 ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width); | 2067 ARGBToYJRow(src_argb, row_y2, width); |
2067 row_y2[-1] = row_y2[0]; | 2068 row_y2[-1] = row_y2[0]; |
2068 row_y2[width] = row_y2[width - 1]; | 2069 row_y2[width] = row_y2[width - 1]; |
2069 | 2070 |
2070 SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width); | 2071 SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width); |
2071 SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width); | 2072 SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width); |
2072 SobelRow(row_sobelx, row_sobely, dst_argb, width); | 2073 SobelRow(row_sobelx, row_sobely, dst_argb, width); |
2073 | 2074 |
2074 // Cycle thru circular queue of 3 row_y buffers. | 2075 // Cycle thru circular queue of 3 row_y buffers. |
2075 { | 2076 { |
2076 uint8* row_yt = row_y0; | 2077 uint8* row_yt = row_y0; |
(...skipping 10 matching lines...) Expand all Loading... |
2087 } | 2088 } |
2088 | 2089 |
2089 // Sobel ARGB effect. | 2090 // Sobel ARGB effect. |
2090 LIBYUV_API | 2091 LIBYUV_API |
2091 int ARGBSobel(const uint8* src_argb, int src_stride_argb, | 2092 int ARGBSobel(const uint8* src_argb, int src_stride_argb, |
2092 uint8* dst_argb, int dst_stride_argb, | 2093 uint8* dst_argb, int dst_stride_argb, |
2093 int width, int height) { | 2094 int width, int height) { |
2094 void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely, | 2095 void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely, |
2095 uint8* dst_argb, int width) = SobelRow_C; | 2096 uint8* dst_argb, int width) = SobelRow_C; |
2096 #if defined(HAS_SOBELROW_SSE2) | 2097 #if defined(HAS_SOBELROW_SSE2) |
2097 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { | 2098 if (TestCpuFlag(kCpuHasSSE2)) { |
2098 SobelRow = SobelRow_SSE2; | 2099 SobelRow = SobelRow_Any_SSE2; |
| 2100 if (IS_ALIGNED(width, 16)) { |
| 2101 SobelRow = SobelRow_SSE2; |
| 2102 } |
2099 } | 2103 } |
2100 #endif | 2104 #endif |
2101 #if defined(HAS_SOBELROW_NEON) | 2105 #if defined(HAS_SOBELROW_NEON) |
2102 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { | 2106 if (TestCpuFlag(kCpuHasNEON)) { |
2103 SobelRow = SobelRow_NEON; | 2107 SobelRow = SobelRow_Any_NEON; |
| 2108 if (IS_ALIGNED(width, 8)) { |
| 2109 SobelRow = SobelRow_NEON; |
| 2110 } |
2104 } | 2111 } |
2105 #endif | 2112 #endif |
2106 return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, | 2113 return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, |
2107 width, height, SobelRow); | 2114 width, height, SobelRow); |
2108 } | 2115 } |
2109 | 2116 |
2110 // Sobel ARGB effect with planar output. | 2117 // Sobel ARGB effect with planar output. |
2111 LIBYUV_API | 2118 LIBYUV_API |
2112 int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, | 2119 int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, |
2113 uint8* dst_y, int dst_stride_y, | 2120 uint8* dst_y, int dst_stride_y, |
2114 int width, int height) { | 2121 int width, int height) { |
2115 void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely, | 2122 void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely, |
2116 uint8* dst_, int width) = SobelToPlaneRow_C; | 2123 uint8* dst_, int width) = SobelToPlaneRow_C; |
2117 #if defined(HAS_SOBELTOPLANEROW_SSE2) | 2124 #if defined(HAS_SOBELTOPLANEROW_SSE2) |
2118 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { | 2125 if (TestCpuFlag(kCpuHasSSE2)) { |
2119 SobelToPlaneRow = SobelToPlaneRow_SSE2; | 2126 SobelToPlaneRow = SobelToPlaneRow_Any_SSE2; |
| 2127 if (IS_ALIGNED(width, 16)) { |
| 2128 SobelToPlaneRow = SobelToPlaneRow_SSE2; |
| 2129 } |
2120 } | 2130 } |
2121 #endif | 2131 #endif |
2122 #if defined(HAS_SOBELTOPLANEROW_NEON) | 2132 #if defined(HAS_SOBELTOPLANEROW_NEON) |
2123 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { | 2133 if (TestCpuFlag(kCpuHasNEON)) { |
2124 SobelToPlaneRow = SobelToPlaneRow_NEON; | 2134 SobelToPlaneRow = SobelToPlaneRow_Any_NEON; |
| 2135 if (IS_ALIGNED(width, 16)) { |
| 2136 SobelToPlaneRow = SobelToPlaneRow_NEON; |
| 2137 } |
2125 } | 2138 } |
2126 #endif | 2139 #endif |
2127 return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y, | 2140 return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y, |
2128 width, height, SobelToPlaneRow); | 2141 width, height, SobelToPlaneRow); |
2129 } | 2142 } |
2130 | 2143 |
2131 // SobelXY ARGB effect. | 2144 // SobelXY ARGB effect. |
2132 // Similar to Sobel, but also stores Sobel X in R and Sobel Y in B. G = Sobel. | 2145 // Similar to Sobel, but also stores Sobel X in R and Sobel Y in B. G = Sobel. |
2133 LIBYUV_API | 2146 LIBYUV_API |
2134 int ARGBSobelXY(const uint8* src_argb, int src_stride_argb, | 2147 int ARGBSobelXY(const uint8* src_argb, int src_stride_argb, |
2135 uint8* dst_argb, int dst_stride_argb, | 2148 uint8* dst_argb, int dst_stride_argb, |
2136 int width, int height) { | 2149 int width, int height) { |
2137 void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely, | 2150 void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely, |
2138 uint8* dst_argb, int width) = SobelXYRow_C; | 2151 uint8* dst_argb, int width) = SobelXYRow_C; |
2139 #if defined(HAS_SOBELXYROW_SSE2) | 2152 #if defined(HAS_SOBELXYROW_SSE2) |
2140 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { | 2153 if (TestCpuFlag(kCpuHasSSE2)) { |
2141 SobelXYRow = SobelXYRow_SSE2; | 2154 SobelXYRow = SobelXYRow_Any_SSE2; |
| 2155 if (IS_ALIGNED(width, 16)) { |
| 2156 SobelXYRow = SobelXYRow_SSE2; |
| 2157 } |
2142 } | 2158 } |
2143 #endif | 2159 #endif |
2144 #if defined(HAS_SOBELXYROW_NEON) | 2160 #if defined(HAS_SOBELXYROW_NEON) |
2145 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { | 2161 if (TestCpuFlag(kCpuHasNEON)) { |
2146 SobelXYRow = SobelXYRow_NEON; | 2162 SobelXYRow = SobelXYRow_Any_NEON; |
| 2163 if (IS_ALIGNED(width, 8)) { |
| 2164 SobelXYRow = SobelXYRow_NEON; |
| 2165 } |
2147 } | 2166 } |
2148 #endif | 2167 #endif |
2149 return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, | 2168 return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, |
2150 width, height, SobelXYRow); | 2169 width, height, SobelXYRow); |
2151 } | 2170 } |
2152 | 2171 |
2153 // Apply a 4x4 polynomial to each ARGB pixel. | 2172 // Apply a 4x4 polynomial to each ARGB pixel. |
2154 LIBYUV_API | 2173 LIBYUV_API |
2155 int ARGBPolynomial(const uint8* src_argb, int src_stride_argb, | 2174 int ARGBPolynomial(const uint8* src_argb, int src_stride_argb, |
2156 uint8* dst_argb, int dst_stride_argb, | 2175 uint8* dst_argb, int dst_stride_argb, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2315 #endif | 2334 #endif |
2316 | 2335 |
2317 for (y = 0; y < height; ++y) { | 2336 for (y = 0; y < height; ++y) { |
2318 ARGBCopyYToAlphaRow(src_y, dst_argb, width); | 2337 ARGBCopyYToAlphaRow(src_y, dst_argb, width); |
2319 src_y += src_stride_y; | 2338 src_y += src_stride_y; |
2320 dst_argb += dst_stride_argb; | 2339 dst_argb += dst_stride_argb; |
2321 } | 2340 } |
2322 return 0; | 2341 return 0; |
2323 } | 2342 } |
2324 | 2343 |
| 2344 LIBYUV_API |
| 2345 int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2, |
| 2346 uint8* dst_y, int dst_stride_y, |
| 2347 uint8* dst_uv, int dst_stride_uv, |
| 2348 int width, int height) { |
| 2349 int y; |
| 2350 int halfwidth = (width + 1) >> 1; |
| 2351 void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) = |
| 2352 SplitUVRow_C; |
| 2353 void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, |
| 2354 ptrdiff_t src_stride, int dst_width, |
| 2355 int source_y_fraction) = InterpolateRow_C; |
| 2356 if (!src_yuy2 || |
| 2357 !dst_y || !dst_uv || |
| 2358 width <= 0 || height == 0) { |
| 2359 return -1; |
| 2360 } |
| 2361 // Negative height means invert the image. |
| 2362 if (height < 0) { |
| 2363 height = -height; |
| 2364 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; |
| 2365 src_stride_yuy2 = -src_stride_yuy2; |
| 2366 } |
| 2367 #if defined(HAS_SPLITUVROW_SSE2) |
| 2368 if (TestCpuFlag(kCpuHasSSE2)) { |
| 2369 SplitUVRow = SplitUVRow_Any_SSE2; |
| 2370 if (IS_ALIGNED(width, 16)) { |
| 2371 SplitUVRow = SplitUVRow_SSE2; |
| 2372 } |
| 2373 } |
| 2374 #endif |
| 2375 #if defined(HAS_SPLITUVROW_AVX2) |
| 2376 if (TestCpuFlag(kCpuHasAVX2)) { |
| 2377 SplitUVRow = SplitUVRow_Any_AVX2; |
| 2378 if (IS_ALIGNED(width, 32)) { |
| 2379 SplitUVRow = SplitUVRow_AVX2; |
| 2380 } |
| 2381 } |
| 2382 #endif |
| 2383 #if defined(HAS_SPLITUVROW_NEON) |
| 2384 if (TestCpuFlag(kCpuHasNEON)) { |
| 2385 SplitUVRow = SplitUVRow_Any_NEON; |
| 2386 if (IS_ALIGNED(width, 16)) { |
| 2387 SplitUVRow = SplitUVRow_NEON; |
| 2388 } |
| 2389 } |
| 2390 #endif |
| 2391 #if defined(HAS_INTERPOLATEROW_SSE2) |
| 2392 if (TestCpuFlag(kCpuHasSSE2)) { |
| 2393 InterpolateRow = InterpolateRow_Any_SSE2; |
| 2394 if (IS_ALIGNED(width, 16)) { |
| 2395 InterpolateRow = InterpolateRow_SSE2; |
| 2396 } |
| 2397 } |
| 2398 #endif |
| 2399 #if defined(HAS_INTERPOLATEROW_SSSE3) |
| 2400 if (TestCpuFlag(kCpuHasSSSE3)) { |
| 2401 InterpolateRow = InterpolateRow_Any_SSSE3; |
| 2402 if (IS_ALIGNED(width, 16)) { |
| 2403 InterpolateRow = InterpolateRow_SSSE3; |
| 2404 } |
| 2405 } |
| 2406 #endif |
| 2407 #if defined(HAS_INTERPOLATEROW_AVX2) |
| 2408 if (TestCpuFlag(kCpuHasAVX2)) { |
| 2409 InterpolateRow = InterpolateRow_Any_AVX2; |
| 2410 if (IS_ALIGNED(width, 32)) { |
| 2411 InterpolateRow = InterpolateRow_AVX2; |
| 2412 } |
| 2413 } |
| 2414 #endif |
| 2415 #if defined(HAS_INTERPOLATEROW_NEON) |
| 2416 if (TestCpuFlag(kCpuHasNEON)) { |
| 2417 InterpolateRow = InterpolateRow_Any_NEON; |
| 2418 if (IS_ALIGNED(width, 16)) { |
| 2419 InterpolateRow = InterpolateRow_NEON; |
| 2420 } |
| 2421 } |
| 2422 #endif |
| 2423 |
| 2424 { |
| 2425 int awidth = halfwidth * 2; |
| 2426 // 2 rows of uv |
| 2427 align_buffer_64(rows, awidth * 2); |
| 2428 |
| 2429 for (y = 0; y < height - 1; y += 2) { |
| 2430 // Split Y from UV. |
| 2431 SplitUVRow(src_yuy2, dst_y, rows, awidth); |
| 2432 SplitUVRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, |
| 2433 rows + awidth, awidth); |
| 2434 InterpolateRow(dst_uv, rows, awidth, awidth, 128); |
| 2435 src_yuy2 += src_stride_yuy2 * 2; |
| 2436 dst_y += dst_stride_y * 2; |
| 2437 dst_uv += dst_stride_uv; |
| 2438 } |
| 2439 if (height & 1) { |
| 2440 // Split Y from UV. |
| 2441 SplitUVRow(src_yuy2, dst_y, dst_uv, width); |
| 2442 } |
| 2443 free_aligned_buffer_64(rows); |
| 2444 } |
| 2445 return 0; |
| 2446 } |
| 2447 |
| 2448 LIBYUV_API |
| 2449 int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, |
| 2450 uint8* dst_y, int dst_stride_y, |
| 2451 uint8* dst_uv, int dst_stride_uv, |
| 2452 int width, int height) { |
| 2453 int y; |
| 2454 int halfwidth = (width + 1) >> 1; |
| 2455 void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) = |
| 2456 SplitUVRow_C; |
| 2457 void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, |
| 2458 ptrdiff_t src_stride, int dst_width, |
| 2459 int source_y_fraction) = InterpolateRow_C; |
| 2460 if (!src_uyvy || |
| 2461 !dst_y || !dst_uv || |
| 2462 width <= 0 || height == 0) { |
| 2463 return -1; |
| 2464 } |
| 2465 // Negative height means invert the image. |
| 2466 if (height < 0) { |
| 2467 height = -height; |
| 2468 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; |
| 2469 src_stride_uyvy = -src_stride_uyvy; |
| 2470 } |
| 2471 #if defined(HAS_SPLITUVROW_SSE2) |
| 2472 if (TestCpuFlag(kCpuHasSSE2)) { |
| 2473 SplitUVRow = SplitUVRow_Any_SSE2; |
| 2474 if (IS_ALIGNED(width, 16)) { |
| 2475 SplitUVRow = SplitUVRow_SSE2; |
| 2476 } |
| 2477 } |
| 2478 #endif |
| 2479 #if defined(HAS_SPLITUVROW_AVX2) |
| 2480 if (TestCpuFlag(kCpuHasAVX2)) { |
| 2481 SplitUVRow = SplitUVRow_Any_AVX2; |
| 2482 if (IS_ALIGNED(width, 32)) { |
| 2483 SplitUVRow = SplitUVRow_AVX2; |
| 2484 } |
| 2485 } |
| 2486 #endif |
| 2487 #if defined(HAS_SPLITUVROW_NEON) |
| 2488 if (TestCpuFlag(kCpuHasNEON)) { |
| 2489 SplitUVRow = SplitUVRow_Any_NEON; |
| 2490 if (IS_ALIGNED(width, 16)) { |
| 2491 SplitUVRow = SplitUVRow_NEON; |
| 2492 } |
| 2493 } |
| 2494 #endif |
| 2495 #if defined(HAS_INTERPOLATEROW_SSE2) |
| 2496 if (TestCpuFlag(kCpuHasSSE2)) { |
| 2497 InterpolateRow = InterpolateRow_Any_SSE2; |
| 2498 if (IS_ALIGNED(width, 16)) { |
| 2499 InterpolateRow = InterpolateRow_SSE2; |
| 2500 } |
| 2501 } |
| 2502 #endif |
| 2503 #if defined(HAS_INTERPOLATEROW_SSSE3) |
| 2504 if (TestCpuFlag(kCpuHasSSSE3)) { |
| 2505 InterpolateRow = InterpolateRow_Any_SSSE3; |
| 2506 if (IS_ALIGNED(width, 16)) { |
| 2507 InterpolateRow = InterpolateRow_SSSE3; |
| 2508 } |
| 2509 } |
| 2510 #endif |
| 2511 #if defined(HAS_INTERPOLATEROW_AVX2) |
| 2512 if (TestCpuFlag(kCpuHasAVX2)) { |
| 2513 InterpolateRow = InterpolateRow_Any_AVX2; |
| 2514 if (IS_ALIGNED(width, 32)) { |
| 2515 InterpolateRow = InterpolateRow_AVX2; |
| 2516 } |
| 2517 } |
| 2518 #endif |
| 2519 #if defined(HAS_INTERPOLATEROW_NEON) |
| 2520 if (TestCpuFlag(kCpuHasNEON)) { |
| 2521 InterpolateRow = InterpolateRow_Any_NEON; |
| 2522 if (IS_ALIGNED(width, 16)) { |
| 2523 InterpolateRow = InterpolateRow_NEON; |
| 2524 } |
| 2525 } |
| 2526 #endif |
| 2527 |
| 2528 { |
| 2529 int awidth = halfwidth * 2; |
| 2530 // 2 rows of uv |
| 2531 align_buffer_64(rows, awidth * 2); |
| 2532 |
| 2533 for (y = 0; y < height - 1; y += 2) { |
| 2534 // Split Y from UV. |
| 2535 SplitUVRow(src_uyvy, rows, dst_y, awidth); |
| 2536 SplitUVRow(src_uyvy + src_stride_uyvy, rows + awidth, |
| 2537 dst_y + dst_stride_y, awidth); |
| 2538 InterpolateRow(dst_uv, rows, awidth, awidth, 128); |
| 2539 src_uyvy += src_stride_uyvy * 2; |
| 2540 dst_y += dst_stride_y * 2; |
| 2541 dst_uv += dst_stride_uv; |
| 2542 } |
| 2543 if (height & 1) { |
| 2544 // Split Y from UV. |
| 2545 SplitUVRow(src_uyvy, dst_y, dst_uv, width); |
| 2546 } |
| 2547 free_aligned_buffer_64(rows); |
| 2548 } |
| 2549 return 0; |
| 2550 } |
| 2551 |
2325 #ifdef __cplusplus | 2552 #ifdef __cplusplus |
2326 } // extern "C" | 2553 } // extern "C" |
2327 } // namespace libyuv | 2554 } // namespace libyuv |
2328 #endif | 2555 #endif |
OLD | NEW |