react-native-vision-camera-spoof-detector 1.0.22 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +442 -442
  2. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  3. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  4. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  5. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  6. package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
  7. package/android/build/reports/problems/problems-report.html +659 -0
  8. package/android/build.gradle +12 -4
  9. package/android/src/main/cpp/CMakeLists.txt +101 -94
  10. package/android/src/main/cpp/libyuv/.clang-format +6 -6
  11. package/android/src/main/cpp/libyuv/.gn +40 -40
  12. package/android/src/main/cpp/libyuv/.vpython3 +410 -410
  13. package/android/src/main/cpp/libyuv/AUTHORS +7 -7
  14. package/android/src/main/cpp/libyuv/Android.bp +202 -202
  15. package/android/src/main/cpp/libyuv/Android.mk +106 -106
  16. package/android/src/main/cpp/libyuv/BUILD.gn +490 -490
  17. package/android/src/main/cpp/libyuv/CM_linux_packages.cmake +70 -70
  18. package/android/src/main/cpp/libyuv/CMakeLists.txt +259 -252
  19. package/android/src/main/cpp/libyuv/DEPS +935 -935
  20. package/android/src/main/cpp/libyuv/DIR_METADATA +3 -3
  21. package/android/src/main/cpp/libyuv/LICENSE +29 -29
  22. package/android/src/main/cpp/libyuv/OWNERS +11 -11
  23. package/android/src/main/cpp/libyuv/PATENTS +23 -23
  24. package/android/src/main/cpp/libyuv/PRESUBMIT.py +65 -65
  25. package/android/src/main/cpp/libyuv/README.chromium +11 -11
  26. package/android/src/main/cpp/libyuv/README.md +19 -19
  27. package/android/src/main/cpp/libyuv/build_overrides/build.gni +60 -60
  28. package/android/src/main/cpp/libyuv/build_overrides/gtest.gni +19 -19
  29. package/android/src/main/cpp/libyuv/build_overrides/partition_alloc.gni +17 -17
  30. package/android/src/main/cpp/libyuv/codereview.settings +5 -5
  31. package/android/src/main/cpp/libyuv/docs/deprecated_builds.md +409 -409
  32. package/android/src/main/cpp/libyuv/docs/environment_variables.md +64 -64
  33. package/android/src/main/cpp/libyuv/docs/feature_detection.md +108 -108
  34. package/android/src/main/cpp/libyuv/docs/filtering.md +196 -196
  35. package/android/src/main/cpp/libyuv/docs/formats.md +208 -208
  36. package/android/src/main/cpp/libyuv/docs/getting_started.md +296 -296
  37. package/android/src/main/cpp/libyuv/docs/rotation.md +107 -107
  38. package/android/src/main/cpp/libyuv/download_vs_toolchain.py +29 -29
  39. package/android/src/main/cpp/libyuv/include/libyuv/basic_types.h +68 -68
  40. package/android/src/main/cpp/libyuv/include/libyuv/compare.h +111 -111
  41. package/android/src/main/cpp/libyuv/include/libyuv/compare_row.h +112 -112
  42. package/android/src/main/cpp/libyuv/include/libyuv/convert.h +1117 -1117
  43. package/android/src/main/cpp/libyuv/include/libyuv/convert_argb.h +2335 -2335
  44. package/android/src/main/cpp/libyuv/include/libyuv/convert_from.h +203 -203
  45. package/android/src/main/cpp/libyuv/include/libyuv/convert_from_argb.h +394 -394
  46. package/android/src/main/cpp/libyuv/include/libyuv/cpu_id.h +147 -147
  47. package/android/src/main/cpp/libyuv/include/libyuv/cpu_support.h +99 -99
  48. package/android/src/main/cpp/libyuv/include/libyuv/loongson_intrinsics.h +1949 -1949
  49. package/android/src/main/cpp/libyuv/include/libyuv/mjpeg_decoder.h +195 -195
  50. package/android/src/main/cpp/libyuv/include/libyuv/planar_functions.h +1131 -1131
  51. package/android/src/main/cpp/libyuv/include/libyuv/rotate.h +296 -296
  52. package/android/src/main/cpp/libyuv/include/libyuv/rotate_argb.h +37 -37
  53. package/android/src/main/cpp/libyuv/include/libyuv/rotate_row.h +265 -265
  54. package/android/src/main/cpp/libyuv/include/libyuv/row.h +6738 -6738
  55. package/android/src/main/cpp/libyuv/include/libyuv/row_sve.h +2154 -2154
  56. package/android/src/main/cpp/libyuv/include/libyuv/scale.h +336 -336
  57. package/android/src/main/cpp/libyuv/include/libyuv/scale_argb.h +76 -76
  58. package/android/src/main/cpp/libyuv/include/libyuv/scale_rgb.h +42 -42
  59. package/android/src/main/cpp/libyuv/include/libyuv/scale_row.h +1726 -1726
  60. package/android/src/main/cpp/libyuv/include/libyuv/scale_uv.h +51 -51
  61. package/android/src/main/cpp/libyuv/include/libyuv/version.h +16 -16
  62. package/android/src/main/cpp/libyuv/include/libyuv/video_common.h +222 -222
  63. package/android/src/main/cpp/libyuv/include/libyuv.h +33 -33
  64. package/android/src/main/cpp/libyuv/infra/config/OWNERS +3 -3
  65. package/android/src/main/cpp/libyuv/infra/config/PRESUBMIT.py +17 -17
  66. package/android/src/main/cpp/libyuv/infra/config/README.md +2 -2
  67. package/android/src/main/cpp/libyuv/infra/config/codereview.settings +6 -6
  68. package/android/src/main/cpp/libyuv/infra/config/commit-queue.cfg +144 -144
  69. package/android/src/main/cpp/libyuv/infra/config/cr-buildbucket.cfg +1185 -1185
  70. package/android/src/main/cpp/libyuv/infra/config/luci-logdog.cfg +9 -9
  71. package/android/src/main/cpp/libyuv/infra/config/luci-milo.cfg +246 -246
  72. package/android/src/main/cpp/libyuv/infra/config/luci-scheduler.cfg +385 -385
  73. package/android/src/main/cpp/libyuv/infra/config/main.star +402 -402
  74. package/android/src/main/cpp/libyuv/infra/config/project.cfg +16 -16
  75. package/android/src/main/cpp/libyuv/infra/config/realms.cfg +111 -111
  76. package/android/src/main/cpp/libyuv/libyuv.gni +34 -34
  77. package/android/src/main/cpp/libyuv/libyuv.gyp +149 -149
  78. package/android/src/main/cpp/libyuv/libyuv.gypi +87 -87
  79. package/android/src/main/cpp/libyuv/linux.mk +96 -96
  80. package/android/src/main/cpp/libyuv/public.mk +13 -13
  81. package/android/src/main/cpp/libyuv/pylintrc +49 -49
  82. package/android/src/main/cpp/libyuv/riscv_script/prepare_toolchain_qemu.sh +74 -74
  83. package/android/src/main/cpp/libyuv/riscv_script/riscv-clang.cmake +56 -56
  84. package/android/src/main/cpp/libyuv/riscv_script/run_qemu.sh +15 -15
  85. package/android/src/main/cpp/libyuv/source/compare.cc +435 -435
  86. package/android/src/main/cpp/libyuv/source/compare_common.cc +74 -74
  87. package/android/src/main/cpp/libyuv/source/compare_gcc.cc +362 -362
  88. package/android/src/main/cpp/libyuv/source/compare_neon.cc +96 -96
  89. package/android/src/main/cpp/libyuv/source/compare_neon64.cc +223 -223
  90. package/android/src/main/cpp/libyuv/source/compare_win.cc +241 -241
  91. package/android/src/main/cpp/libyuv/source/convert.cc +4746 -4746
  92. package/android/src/main/cpp/libyuv/source/convert_argb.cc +9179 -9179
  93. package/android/src/main/cpp/libyuv/source/convert_from.cc +866 -866
  94. package/android/src/main/cpp/libyuv/source/convert_from_argb.cc +3671 -3671
  95. package/android/src/main/cpp/libyuv/source/convert_jpeg.cc +602 -602
  96. package/android/src/main/cpp/libyuv/source/convert_to_argb.cc +391 -391
  97. package/android/src/main/cpp/libyuv/source/convert_to_i420.cc +288 -288
  98. package/android/src/main/cpp/libyuv/source/cpu_id.cc +496 -496
  99. package/android/src/main/cpp/libyuv/source/mjpeg_decoder.cc +580 -580
  100. package/android/src/main/cpp/libyuv/source/mjpeg_validate.cc +71 -71
  101. package/android/src/main/cpp/libyuv/source/planar_functions.cc +5663 -5663
  102. package/android/src/main/cpp/libyuv/source/rotate.cc +1241 -1241
  103. package/android/src/main/cpp/libyuv/source/rotate_any.cc +76 -76
  104. package/android/src/main/cpp/libyuv/source/rotate_argb.cc +259 -259
  105. package/android/src/main/cpp/libyuv/source/rotate_common.cc +208 -208
  106. package/android/src/main/cpp/libyuv/source/rotate_gcc.cc +505 -505
  107. package/android/src/main/cpp/libyuv/source/rotate_lsx.cc +233 -233
  108. package/android/src/main/cpp/libyuv/source/rotate_neon.cc +219 -219
  109. package/android/src/main/cpp/libyuv/source/rotate_neon64.cc +273 -273
  110. package/android/src/main/cpp/libyuv/source/rotate_sme.cc +174 -174
  111. package/android/src/main/cpp/libyuv/source/rotate_win.cc +253 -253
  112. package/android/src/main/cpp/libyuv/source/row_any.cc +2519 -2519
  113. package/android/src/main/cpp/libyuv/source/row_common.cc +4461 -4461
  114. package/android/src/main/cpp/libyuv/source/row_gcc.cc +9570 -9570
  115. package/android/src/main/cpp/libyuv/source/row_lasx.cc +2343 -2343
  116. package/android/src/main/cpp/libyuv/source/row_lsx.cc +3030 -3030
  117. package/android/src/main/cpp/libyuv/source/row_neon.cc +4026 -4026
  118. package/android/src/main/cpp/libyuv/source/row_neon64.cc +5617 -5617
  119. package/android/src/main/cpp/libyuv/source/row_rvv.cc +2599 -2599
  120. package/android/src/main/cpp/libyuv/source/row_sme.cc +1183 -1183
  121. package/android/src/main/cpp/libyuv/source/row_sve.cc +1088 -1088
  122. package/android/src/main/cpp/libyuv/source/row_win.cc +6453 -6453
  123. package/android/src/main/cpp/libyuv/source/scale.cc +2710 -2710
  124. package/android/src/main/cpp/libyuv/source/scale_any.cc +991 -991
  125. package/android/src/main/cpp/libyuv/source/scale_argb.cc +1158 -1158
  126. package/android/src/main/cpp/libyuv/source/scale_common.cc +1977 -1977
  127. package/android/src/main/cpp/libyuv/source/scale_gcc.cc +2947 -2947
  128. package/android/src/main/cpp/libyuv/source/scale_lsx.cc +739 -739
  129. package/android/src/main/cpp/libyuv/source/scale_neon.cc +1449 -1449
  130. package/android/src/main/cpp/libyuv/source/scale_neon64.cc +1552 -1552
  131. package/android/src/main/cpp/libyuv/source/scale_rgb.cc +82 -82
  132. package/android/src/main/cpp/libyuv/source/scale_rvv.cc +1971 -1971
  133. package/android/src/main/cpp/libyuv/source/scale_sme.cc +555 -555
  134. package/android/src/main/cpp/libyuv/source/scale_uv.cc +1159 -1159
  135. package/android/src/main/cpp/libyuv/source/scale_win.cc +1392 -1392
  136. package/android/src/main/cpp/libyuv/source/test.sh +35 -35
  137. package/android/src/main/cpp/libyuv/source/video_common.cc +62 -62
  138. package/android/src/main/cpp/libyuv/tools_libyuv/OWNERS +4 -4
  139. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/roll_deps.py +931 -931
  140. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/roll_deps_test.py +164 -164
  141. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS +21 -21
  142. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.new +13 -13
  143. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old +13 -13
  144. package/android/src/main/cpp/libyuv/tools_libyuv/get_landmines.py +38 -38
  145. package/android/src/main/cpp/libyuv/tools_libyuv/msan/OWNERS +3 -3
  146. package/android/src/main/cpp/libyuv/tools_libyuv/msan/blacklist.txt +9 -9
  147. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/OWNERS +3 -3
  148. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/blacklist.txt +15 -15
  149. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/vptr_blacklist.txt +25 -25
  150. package/android/src/main/cpp/libyuv/unit_test/basictypes_test.cc +43 -43
  151. package/android/src/main/cpp/libyuv/unit_test/color_test.cc +848 -848
  152. package/android/src/main/cpp/libyuv/unit_test/compare_test.cc +739 -739
  153. package/android/src/main/cpp/libyuv/unit_test/convert_argb_test.cc +2867 -2867
  154. package/android/src/main/cpp/libyuv/unit_test/convert_test.cc +2133 -2133
  155. package/android/src/main/cpp/libyuv/unit_test/cpu_test.cc +427 -427
  156. package/android/src/main/cpp/libyuv/unit_test/cpu_thread_test.cc +63 -63
  157. package/android/src/main/cpp/libyuv/unit_test/math_test.cc +160 -160
  158. package/android/src/main/cpp/libyuv/unit_test/planar_test.cc +4731 -4731
  159. package/android/src/main/cpp/libyuv/unit_test/rotate_argb_test.cc +334 -334
  160. package/android/src/main/cpp/libyuv/unit_test/rotate_test.cc +962 -962
  161. package/android/src/main/cpp/libyuv/unit_test/scale_argb_test.cc +590 -590
  162. package/android/src/main/cpp/libyuv/unit_test/scale_plane_test.cc +465 -465
  163. package/android/src/main/cpp/libyuv/unit_test/scale_rgb_test.cc +280 -280
  164. package/android/src/main/cpp/libyuv/unit_test/scale_test.cc +1135 -1135
  165. package/android/src/main/cpp/libyuv/unit_test/scale_uv_test.cc +249 -249
  166. package/android/src/main/cpp/libyuv/unit_test/testdata/arm_v7.txt +12 -12
  167. package/android/src/main/cpp/libyuv/unit_test/testdata/mips.txt +7 -7
  168. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson2k.txt +5 -5
  169. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson3.txt +10 -10
  170. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson_mmi.txt +7 -7
  171. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64.txt +3 -3
  172. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv.txt +3 -3
  173. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv_zvfh.txt +3 -3
  174. package/android/src/main/cpp/libyuv/unit_test/testdata/tegra3.txt +23 -23
  175. package/android/src/main/cpp/libyuv/unit_test/unit_test.cc +581 -581
  176. package/android/src/main/cpp/libyuv/unit_test/unit_test.h +232 -232
  177. package/android/src/main/cpp/libyuv/unit_test/video_common_test.cc +112 -112
  178. package/android/src/main/cpp/libyuv/util/Makefile +9 -9
  179. package/android/src/main/cpp/libyuv/util/color.cc +120 -120
  180. package/android/src/main/cpp/libyuv/util/compare.cc +67 -67
  181. package/android/src/main/cpp/libyuv/util/cpuid.c +211 -211
  182. package/android/src/main/cpp/libyuv/util/i444tonv12_eg.cc +27 -27
  183. package/android/src/main/cpp/libyuv/util/psnr.cc +291 -291
  184. package/android/src/main/cpp/libyuv/util/psnr.h +47 -47
  185. package/android/src/main/cpp/libyuv/util/psnr_main.cc +620 -620
  186. package/android/src/main/cpp/libyuv/util/ssim.cc +364 -364
  187. package/android/src/main/cpp/libyuv/util/ssim.h +38 -38
  188. package/android/src/main/cpp/libyuv/util/yuvconstants.c +114 -114
  189. package/android/src/main/cpp/libyuv/util/yuvconvert.cc +367 -367
  190. package/android/src/main/cpp/libyuv/winarm.mk +47 -47
  191. package/index.js +17 -1
  192. package/ios/FaceAntiSpoofFrameProcessor.swift +283 -0
  193. package/ios/FaceAntiSpoofJSI.h +12 -0
  194. package/ios/FaceAntiSpoofJSI.mm +92 -0
  195. package/ios/FaceAntiSpoofManager.swift +63 -0
  196. package/ios/FaceAntiSpoofModule.m +191 -0
  197. package/ios/FaceAntiSpoofPluginRegister.m +42 -0
  198. package/ios/models/FaceAntiSpoofing.tflite +0 -0
  199. package/ios/models/model_spec.json +16 -0
  200. package/package.json +87 -86
  201. package/.gitignore +0 -27
  202. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  203. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  204. package/android/.gradle/8.9/gc.properties +0 -0
  205. /package/android/.gradle/{8.9 → 9.2.0}/fileChanges/last-build.bin +0 -0
  206. /package/android/.gradle/{8.9/dependencies-accessors → 9.2.0}/gc.properties +0 -0
@@ -1,1241 +1,1241 @@
1
- /*
2
- * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3
- *
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
6
- * tree. An additional intellectual property rights grant can be found
7
- * in the file PATENTS. All contributing project authors may
8
- * be found in the AUTHORS file in the root of the source tree.
9
- */
10
-
11
- #include <assert.h>
12
-
13
- #include "libyuv/rotate.h"
14
-
15
- #include "libyuv/convert.h"
16
- #include "libyuv/cpu_id.h"
17
- #include "libyuv/planar_functions.h"
18
- #include "libyuv/rotate_row.h"
19
- #include "libyuv/row.h"
20
-
21
- #ifdef __cplusplus
22
- namespace libyuv {
23
- extern "C" {
24
- #endif
25
-
26
- LIBYUV_API
27
- void TransposePlane(const uint8_t* src,
28
- int src_stride,
29
- uint8_t* dst,
30
- int dst_stride,
31
- int width,
32
- int height) {
33
- int i = height;
34
- #if defined(HAS_TRANSPOSEWXH_SME)
35
- void (*TransposeWxH)(const uint8_t* src, int src_stride, uint8_t* dst,
36
- int dst_stride, int width, int height) = NULL;
37
- #endif
38
- #if defined(HAS_TRANSPOSEWX16_LSX) || defined(HAS_TRANSPOSEWX16_NEON)
39
- void (*TransposeWx16)(const uint8_t* src, int src_stride, uint8_t* dst,
40
- int dst_stride, int width) = TransposeWx16_C;
41
- #else
42
- void (*TransposeWx8)(const uint8_t* src, int src_stride, uint8_t* dst,
43
- int dst_stride, int width) = TransposeWx8_C;
44
- #endif
45
-
46
- #if defined(HAS_TRANSPOSEWX8_NEON)
47
- if (TestCpuFlag(kCpuHasNEON)) {
48
- TransposeWx8 = TransposeWx8_Any_NEON;
49
- if (IS_ALIGNED(width, 8)) {
50
- TransposeWx8 = TransposeWx8_NEON;
51
- }
52
- }
53
- #endif
54
- #if defined(HAS_TRANSPOSEWX16_NEON)
55
- if (TestCpuFlag(kCpuHasNEON)) {
56
- TransposeWx16 = TransposeWx16_Any_NEON;
57
- if (IS_ALIGNED(width, 16)) {
58
- TransposeWx16 = TransposeWx16_NEON;
59
- }
60
- }
61
- #endif
62
- #if defined(HAS_TRANSPOSEWXH_SME)
63
- if (TestCpuFlag(kCpuHasSME)) {
64
- TransposeWxH = TransposeWxH_SME;
65
- }
66
- #endif
67
- #if defined(HAS_TRANSPOSEWX8_SSSE3)
68
- if (TestCpuFlag(kCpuHasSSSE3)) {
69
- TransposeWx8 = TransposeWx8_Any_SSSE3;
70
- if (IS_ALIGNED(width, 8)) {
71
- TransposeWx8 = TransposeWx8_SSSE3;
72
- }
73
- }
74
- #endif
75
- #if defined(HAS_TRANSPOSEWX8_FAST_SSSE3)
76
- if (TestCpuFlag(kCpuHasSSSE3)) {
77
- TransposeWx8 = TransposeWx8_Fast_Any_SSSE3;
78
- if (IS_ALIGNED(width, 16)) {
79
- TransposeWx8 = TransposeWx8_Fast_SSSE3;
80
- }
81
- }
82
- #endif
83
- #if defined(HAS_TRANSPOSEWX16_LSX)
84
- if (TestCpuFlag(kCpuHasLSX)) {
85
- TransposeWx16 = TransposeWx16_Any_LSX;
86
- if (IS_ALIGNED(width, 16)) {
87
- TransposeWx16 = TransposeWx16_LSX;
88
- }
89
- }
90
- #endif
91
-
92
- #if defined(HAS_TRANSPOSEWXH_SME)
93
- if (TransposeWxH) {
94
- TransposeWxH(src, src_stride, dst, dst_stride, width, height);
95
- return;
96
- }
97
- #endif
98
- #if defined(HAS_TRANSPOSEWX16_LSX) || defined(HAS_TRANSPOSEWX16_NEON)
99
- // Work across the source in 16x16 tiles
100
- while (i >= 16) {
101
- TransposeWx16(src, src_stride, dst, dst_stride, width);
102
- src += 16 * src_stride; // Go down 16 rows.
103
- dst += 16; // Move over 16 columns.
104
- i -= 16;
105
- }
106
- #else
107
- // Work across the source in 8x8 tiles
108
- while (i >= 8) {
109
- TransposeWx8(src, src_stride, dst, dst_stride, width);
110
- src += 8 * src_stride; // Go down 8 rows.
111
- dst += 8; // Move over 8 columns.
112
- i -= 8;
113
- }
114
- #endif
115
-
116
- if (i > 0) {
117
- TransposeWxH_C(src, src_stride, dst, dst_stride, width, i);
118
- }
119
- }
120
-
121
- LIBYUV_API
122
- void RotatePlane90(const uint8_t* src,
123
- int src_stride,
124
- uint8_t* dst,
125
- int dst_stride,
126
- int width,
127
- int height) {
128
- // Rotate by 90 is a transpose with the source read
129
- // from bottom to top. So set the source pointer to the end
130
- // of the buffer and flip the sign of the source stride.
131
- src += src_stride * (height - 1);
132
- src_stride = -src_stride;
133
- TransposePlane(src, src_stride, dst, dst_stride, width, height);
134
- }
135
-
136
- LIBYUV_API
137
- void RotatePlane270(const uint8_t* src,
138
- int src_stride,
139
- uint8_t* dst,
140
- int dst_stride,
141
- int width,
142
- int height) {
143
- // Rotate by 270 is a transpose with the destination written
144
- // from bottom to top. So set the destination pointer to the end
145
- // of the buffer and flip the sign of the destination stride.
146
- dst += dst_stride * (width - 1);
147
- dst_stride = -dst_stride;
148
- TransposePlane(src, src_stride, dst, dst_stride, width, height);
149
- }
150
-
151
- LIBYUV_API
152
- void RotatePlane180(const uint8_t* src,
153
- int src_stride,
154
- uint8_t* dst,
155
- int dst_stride,
156
- int width,
157
- int height) {
158
- // Swap top and bottom row and mirror the content. Uses a temporary row.
159
- align_buffer_64(row, width);
160
- assert(row);
161
- if (!row)
162
- return;
163
- const uint8_t* src_bot = src + src_stride * (height - 1);
164
- uint8_t* dst_bot = dst + dst_stride * (height - 1);
165
- int half_height = (height + 1) >> 1;
166
- int y;
167
- void (*MirrorRow)(const uint8_t* src, uint8_t* dst, int width) = MirrorRow_C;
168
- void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C;
169
- #if defined(HAS_MIRRORROW_NEON)
170
- if (TestCpuFlag(kCpuHasNEON)) {
171
- MirrorRow = MirrorRow_Any_NEON;
172
- if (IS_ALIGNED(width, 32)) {
173
- MirrorRow = MirrorRow_NEON;
174
- }
175
- }
176
- #endif
177
- #if defined(HAS_MIRRORROW_SSSE3)
178
- if (TestCpuFlag(kCpuHasSSSE3)) {
179
- MirrorRow = MirrorRow_Any_SSSE3;
180
- if (IS_ALIGNED(width, 16)) {
181
- MirrorRow = MirrorRow_SSSE3;
182
- }
183
- }
184
- #endif
185
- #if defined(HAS_MIRRORROW_AVX2)
186
- if (TestCpuFlag(kCpuHasAVX2)) {
187
- MirrorRow = MirrorRow_Any_AVX2;
188
- if (IS_ALIGNED(width, 32)) {
189
- MirrorRow = MirrorRow_AVX2;
190
- }
191
- }
192
- #endif
193
- #if defined(HAS_MIRRORROW_LSX)
194
- if (TestCpuFlag(kCpuHasLSX)) {
195
- MirrorRow = MirrorRow_Any_LSX;
196
- if (IS_ALIGNED(width, 32)) {
197
- MirrorRow = MirrorRow_LSX;
198
- }
199
- }
200
- #endif
201
- #if defined(HAS_MIRRORROW_LASX)
202
- if (TestCpuFlag(kCpuHasLASX)) {
203
- MirrorRow = MirrorRow_Any_LASX;
204
- if (IS_ALIGNED(width, 64)) {
205
- MirrorRow = MirrorRow_LASX;
206
- }
207
- }
208
- #endif
209
- #if defined(HAS_COPYROW_SSE2)
210
- if (TestCpuFlag(kCpuHasSSE2)) {
211
- CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2;
212
- }
213
- #endif
214
- #if defined(HAS_COPYROW_AVX)
215
- if (TestCpuFlag(kCpuHasAVX)) {
216
- CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX;
217
- }
218
- #endif
219
- #if defined(HAS_COPYROW_AVX512BW)
220
- if (TestCpuFlag(kCpuHasAVX512BW)) {
221
- CopyRow = IS_ALIGNED(width, 128) ? CopyRow_AVX512BW : CopyRow_Any_AVX512BW;
222
- }
223
- #endif
224
- #if defined(HAS_COPYROW_ERMS)
225
- if (TestCpuFlag(kCpuHasERMS)) {
226
- CopyRow = CopyRow_ERMS;
227
- }
228
- #endif
229
- #if defined(HAS_COPYROW_NEON)
230
- if (TestCpuFlag(kCpuHasNEON)) {
231
- CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON;
232
- }
233
- #endif
234
- #if defined(HAS_COPYROW_SME)
235
- if (TestCpuFlag(kCpuHasSME)) {
236
- CopyRow = CopyRow_SME;
237
- }
238
- #endif
239
- #if defined(HAS_COPYROW_RVV)
240
- if (TestCpuFlag(kCpuHasRVV)) {
241
- CopyRow = CopyRow_RVV;
242
- }
243
- #endif
244
-
245
- // Odd height will harmlessly mirror the middle row twice.
246
- for (y = 0; y < half_height; ++y) {
247
- CopyRow(src, row, width); // Copy top row into buffer
248
- MirrorRow(src_bot, dst, width); // Mirror bottom row into top row
249
- MirrorRow(row, dst_bot, width); // Mirror buffer into bottom row
250
- src += src_stride;
251
- dst += dst_stride;
252
- src_bot -= src_stride;
253
- dst_bot -= dst_stride;
254
- }
255
- free_aligned_buffer_64(row);
256
- }
257
-
258
- LIBYUV_API
259
- void SplitTransposeUV(const uint8_t* src,
260
- int src_stride,
261
- uint8_t* dst_a,
262
- int dst_stride_a,
263
- uint8_t* dst_b,
264
- int dst_stride_b,
265
- int width,
266
- int height) {
267
- int i = height;
268
- #if defined(HAS_TRANSPOSEUVWXH_SME)
269
- void (*TransposeUVWxH)(const uint8_t* src, int src_stride, uint8_t* dst_a,
270
- int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
271
- int width, int height) = TransposeUVWxH_C;
272
- #endif
273
- #if defined(HAS_TRANSPOSEUVWX16_LSX)
274
- void (*TransposeUVWx16)(const uint8_t* src, int src_stride, uint8_t* dst_a,
275
- int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
276
- int width) = TransposeUVWx16_C;
277
- #else
278
- void (*TransposeUVWx8)(const uint8_t* src, int src_stride, uint8_t* dst_a,
279
- int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
280
- int width) = TransposeUVWx8_C;
281
- #endif
282
-
283
- #if defined(HAS_TRANSPOSEUVWX16_LSX)
284
- if (TestCpuFlag(kCpuHasLSX)) {
285
- TransposeUVWx16 = TransposeUVWx16_Any_LSX;
286
- if (IS_ALIGNED(width, 8)) {
287
- TransposeUVWx16 = TransposeUVWx16_LSX;
288
- }
289
- }
290
- #endif
291
- #if defined(HAS_TRANSPOSEUVWX8_NEON)
292
- if (TestCpuFlag(kCpuHasNEON)) {
293
- TransposeUVWx8 = TransposeUVWx8_Any_NEON;
294
- if (IS_ALIGNED(width, 8)) {
295
- TransposeUVWx8 = TransposeUVWx8_NEON;
296
- }
297
- }
298
- #endif
299
- #if defined(HAS_TRANSPOSEUVWXH_SME)
300
- if (TestCpuFlag(kCpuHasSME)) {
301
- TransposeUVWxH = TransposeUVWxH_SME;
302
- }
303
- #endif
304
- #if defined(HAS_TRANSPOSEUVWX8_SSE2)
305
- if (TestCpuFlag(kCpuHasSSE2)) {
306
- TransposeUVWx8 = TransposeUVWx8_Any_SSE2;
307
- if (IS_ALIGNED(width, 8)) {
308
- TransposeUVWx8 = TransposeUVWx8_SSE2;
309
- }
310
- }
311
- #endif
312
-
313
- #if defined(HAS_TRANSPOSEUVWXH_SME)
314
- if (TestCpuFlag(kCpuHasSME)) {
315
- TransposeUVWxH(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
316
- width, i);
317
- return;
318
- }
319
- #endif
320
- #if defined(HAS_TRANSPOSEUVWX16_LSX)
321
- // Work through the source in 8x8 tiles.
322
- while (i >= 16) {
323
- TransposeUVWx16(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
324
- width);
325
- src += 16 * src_stride; // Go down 16 rows.
326
- dst_a += 16; // Move over 8 columns.
327
- dst_b += 16; // Move over 8 columns.
328
- i -= 16;
329
- }
330
- #else
331
- // Work through the source in 8x8 tiles.
332
- while (i >= 8) {
333
- TransposeUVWx8(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
334
- width);
335
- src += 8 * src_stride; // Go down 8 rows.
336
- dst_a += 8; // Move over 8 columns.
337
- dst_b += 8; // Move over 8 columns.
338
- i -= 8;
339
- }
340
- #endif
341
-
342
- if (i > 0) {
343
- TransposeUVWxH_C(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
344
- width, i);
345
- }
346
- }
347
-
348
- LIBYUV_API
349
- void SplitRotateUV90(const uint8_t* src,
350
- int src_stride,
351
- uint8_t* dst_a,
352
- int dst_stride_a,
353
- uint8_t* dst_b,
354
- int dst_stride_b,
355
- int width,
356
- int height) {
357
- src += src_stride * (height - 1);
358
- src_stride = -src_stride;
359
-
360
- SplitTransposeUV(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
361
- width, height);
362
- }
363
-
364
- LIBYUV_API
365
- void SplitRotateUV270(const uint8_t* src,
366
- int src_stride,
367
- uint8_t* dst_a,
368
- int dst_stride_a,
369
- uint8_t* dst_b,
370
- int dst_stride_b,
371
- int width,
372
- int height) {
373
- dst_a += dst_stride_a * (width - 1);
374
- dst_b += dst_stride_b * (width - 1);
375
- dst_stride_a = -dst_stride_a;
376
- dst_stride_b = -dst_stride_b;
377
-
378
- SplitTransposeUV(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
379
- width, height);
380
- }
381
-
382
- // Rotate 180 is a horizontal and vertical flip.
383
- LIBYUV_API
384
- void SplitRotateUV180(const uint8_t* src,
385
- int src_stride,
386
- uint8_t* dst_a,
387
- int dst_stride_a,
388
- uint8_t* dst_b,
389
- int dst_stride_b,
390
- int width,
391
- int height) {
392
- int i;
393
- void (*MirrorSplitUVRow)(const uint8_t* src, uint8_t* dst_u, uint8_t* dst_v,
394
- int width) = MirrorSplitUVRow_C;
395
- #if defined(HAS_MIRRORSPLITUVROW_NEON)
396
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
397
- MirrorSplitUVRow = MirrorSplitUVRow_NEON;
398
- }
399
- #endif
400
- #if defined(HAS_MIRRORSPLITUVROW_SSSE3)
401
- if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16)) {
402
- MirrorSplitUVRow = MirrorSplitUVRow_SSSE3;
403
- }
404
- #endif
405
- #if defined(HAS_MIRRORSPLITUVROW_LSX)
406
- if (TestCpuFlag(kCpuHasLSX) && IS_ALIGNED(width, 32)) {
407
- MirrorSplitUVRow = MirrorSplitUVRow_LSX;
408
- }
409
- #endif
410
-
411
- dst_a += dst_stride_a * (height - 1);
412
- dst_b += dst_stride_b * (height - 1);
413
-
414
- for (i = 0; i < height; ++i) {
415
- MirrorSplitUVRow(src, dst_a, dst_b, width);
416
- src += src_stride;
417
- dst_a -= dst_stride_a;
418
- dst_b -= dst_stride_b;
419
- }
420
- }
421
-
422
- // Rotate UV and split into planar.
423
- // width and height expected to be half size for NV12
424
- LIBYUV_API
425
- int SplitRotateUV(const uint8_t* src_uv,
426
- int src_stride_uv,
427
- uint8_t* dst_u,
428
- int dst_stride_u,
429
- uint8_t* dst_v,
430
- int dst_stride_v,
431
- int width,
432
- int height,
433
- enum RotationMode mode) {
434
- if (!src_uv || width <= 0 || height == 0 || !dst_u || !dst_v) {
435
- return -1;
436
- }
437
-
438
- // Negative height means invert the image.
439
- if (height < 0) {
440
- height = -height;
441
- src_uv = src_uv + (height - 1) * src_stride_uv;
442
- src_stride_uv = -src_stride_uv;
443
- }
444
-
445
- switch (mode) {
446
- case kRotate0:
447
- SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
448
- dst_stride_v, width, height);
449
- return 0;
450
- case kRotate90:
451
- SplitRotateUV90(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
452
- dst_stride_v, width, height);
453
- return 0;
454
- case kRotate270:
455
- SplitRotateUV270(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
456
- dst_stride_v, width, height);
457
- return 0;
458
- case kRotate180:
459
- SplitRotateUV180(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
460
- dst_stride_v, width, height);
461
- return 0;
462
- default:
463
- break;
464
- }
465
- return -1;
466
- }
467
-
468
- LIBYUV_API
469
- int RotatePlane(const uint8_t* src,
470
- int src_stride,
471
- uint8_t* dst,
472
- int dst_stride,
473
- int width,
474
- int height,
475
- enum RotationMode mode) {
476
- if (!src || width <= 0 || height == 0 || !dst) {
477
- return -1;
478
- }
479
-
480
- // Negative height means invert the image.
481
- if (height < 0) {
482
- height = -height;
483
- src = src + (height - 1) * src_stride;
484
- src_stride = -src_stride;
485
- }
486
-
487
- switch (mode) {
488
- case kRotate0:
489
- // copy frame
490
- CopyPlane(src, src_stride, dst, dst_stride, width, height);
491
- return 0;
492
- case kRotate90:
493
- RotatePlane90(src, src_stride, dst, dst_stride, width, height);
494
- return 0;
495
- case kRotate270:
496
- RotatePlane270(src, src_stride, dst, dst_stride, width, height);
497
- return 0;
498
- case kRotate180:
499
- RotatePlane180(src, src_stride, dst, dst_stride, width, height);
500
- return 0;
501
- default:
502
- break;
503
- }
504
- return -1;
505
- }
506
-
507
- static void TransposePlane_16(const uint16_t* src,
508
- int src_stride,
509
- uint16_t* dst,
510
- int dst_stride,
511
- int width,
512
- int height) {
513
- int i = height;
514
- // Work across the source in 8x8 tiles
515
- while (i >= 8) {
516
- TransposeWx8_16_C(src, src_stride, dst, dst_stride, width);
517
- src += 8 * src_stride; // Go down 8 rows.
518
- dst += 8; // Move over 8 columns.
519
- i -= 8;
520
- }
521
-
522
- if (i > 0) {
523
- TransposeWxH_16_C(src, src_stride, dst, dst_stride, width, i);
524
- }
525
- }
526
-
527
- static void RotatePlane90_16(const uint16_t* src,
528
- int src_stride,
529
- uint16_t* dst,
530
- int dst_stride,
531
- int width,
532
- int height) {
533
- // Rotate by 90 is a transpose with the source read
534
- // from bottom to top. So set the source pointer to the end
535
- // of the buffer and flip the sign of the source stride.
536
- src += src_stride * (height - 1);
537
- src_stride = -src_stride;
538
- TransposePlane_16(src, src_stride, dst, dst_stride, width, height);
539
- }
540
-
541
- static void RotatePlane270_16(const uint16_t* src,
542
- int src_stride,
543
- uint16_t* dst,
544
- int dst_stride,
545
- int width,
546
- int height) {
547
- // Rotate by 270 is a transpose with the destination written
548
- // from bottom to top. So set the destination pointer to the end
549
- // of the buffer and flip the sign of the destination stride.
550
- dst += dst_stride * (width - 1);
551
- dst_stride = -dst_stride;
552
- TransposePlane_16(src, src_stride, dst, dst_stride, width, height);
553
- }
554
-
555
- static void RotatePlane180_16(const uint16_t* src,
556
- int src_stride,
557
- uint16_t* dst,
558
- int dst_stride,
559
- int width,
560
- int height) {
561
- const uint16_t* src_bot = src + src_stride * (height - 1);
562
- uint16_t* dst_bot = dst + dst_stride * (height - 1);
563
- int half_height = (height + 1) >> 1;
564
- int y;
565
-
566
- // Swap top and bottom row and mirror the content. Uses a temporary row.
567
- align_buffer_64(row, width * 2);
568
- uint16_t* row_tmp = (uint16_t*)row;
569
- assert(row);
570
- if (!row)
571
- return;
572
-
573
- // Odd height will harmlessly mirror the middle row twice.
574
- for (y = 0; y < half_height; ++y) {
575
- CopyRow_16_C(src, row_tmp, width); // Copy top row into buffer
576
- MirrorRow_16_C(src_bot, dst, width); // Mirror bottom row into top row
577
- MirrorRow_16_C(row_tmp, dst_bot, width); // Mirror buffer into bottom row
578
- src += src_stride;
579
- dst += dst_stride;
580
- src_bot -= src_stride;
581
- dst_bot -= dst_stride;
582
- }
583
- free_aligned_buffer_64(row);
584
- }
585
-
586
- LIBYUV_API
587
- int RotatePlane_16(const uint16_t* src,
588
- int src_stride,
589
- uint16_t* dst,
590
- int dst_stride,
591
- int width,
592
- int height,
593
- enum RotationMode mode) {
594
- if (!src || width <= 0 || height == 0 || !dst) {
595
- return -1;
596
- }
597
-
598
- // Negative height means invert the image.
599
- if (height < 0) {
600
- height = -height;
601
- src = src + (height - 1) * src_stride;
602
- src_stride = -src_stride;
603
- }
604
-
605
- switch (mode) {
606
- case kRotate0:
607
- // copy frame
608
- CopyPlane_16(src, src_stride, dst, dst_stride, width, height);
609
- return 0;
610
- case kRotate90:
611
- RotatePlane90_16(src, src_stride, dst, dst_stride, width, height);
612
- return 0;
613
- case kRotate270:
614
- RotatePlane270_16(src, src_stride, dst, dst_stride, width, height);
615
- return 0;
616
- case kRotate180:
617
- RotatePlane180_16(src, src_stride, dst, dst_stride, width, height);
618
- return 0;
619
- default:
620
- break;
621
- }
622
- return -1;
623
- }
624
-
625
- LIBYUV_API
626
- int I420Rotate(const uint8_t* src_y,
627
- int src_stride_y,
628
- const uint8_t* src_u,
629
- int src_stride_u,
630
- const uint8_t* src_v,
631
- int src_stride_v,
632
- uint8_t* dst_y,
633
- int dst_stride_y,
634
- uint8_t* dst_u,
635
- int dst_stride_u,
636
- uint8_t* dst_v,
637
- int dst_stride_v,
638
- int width,
639
- int height,
640
- enum RotationMode mode) {
641
- int halfwidth = (width + 1) >> 1;
642
- int halfheight = (height + 1) >> 1;
643
- if ((!src_y && dst_y) || !src_u || !src_v || width <= 0 || height == 0 ||
644
- !dst_y || !dst_u || !dst_v) {
645
- return -1;
646
- }
647
-
648
- // Negative height means invert the image.
649
- if (height < 0) {
650
- height = -height;
651
- halfheight = (height + 1) >> 1;
652
- src_y = src_y + (height - 1) * src_stride_y;
653
- src_u = src_u + (halfheight - 1) * src_stride_u;
654
- src_v = src_v + (halfheight - 1) * src_stride_v;
655
- src_stride_y = -src_stride_y;
656
- src_stride_u = -src_stride_u;
657
- src_stride_v = -src_stride_v;
658
- }
659
-
660
- switch (mode) {
661
- case kRotate0:
662
- // copy frame
663
- return I420Copy(src_y, src_stride_y, src_u, src_stride_u, src_v,
664
- src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
665
- dst_v, dst_stride_v, width, height);
666
- case kRotate90:
667
- RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
668
- RotatePlane90(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
669
- halfheight);
670
- RotatePlane90(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
671
- halfheight);
672
- return 0;
673
- case kRotate270:
674
- RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
675
- RotatePlane270(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
676
- halfheight);
677
- RotatePlane270(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
678
- halfheight);
679
- return 0;
680
- case kRotate180:
681
- RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
682
- RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
683
- halfheight);
684
- RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
685
- halfheight);
686
- return 0;
687
- default:
688
- break;
689
- }
690
- return -1;
691
- }
692
-
693
- // I422 has half width x full height UV planes, so rotate by 90 and 270
694
- // require scaling to maintain 422 subsampling.
695
- LIBYUV_API
696
- int I422Rotate(const uint8_t* src_y,
697
- int src_stride_y,
698
- const uint8_t* src_u,
699
- int src_stride_u,
700
- const uint8_t* src_v,
701
- int src_stride_v,
702
- uint8_t* dst_y,
703
- int dst_stride_y,
704
- uint8_t* dst_u,
705
- int dst_stride_u,
706
- uint8_t* dst_v,
707
- int dst_stride_v,
708
- int width,
709
- int height,
710
- enum RotationMode mode) {
711
- int halfwidth = (width + 1) >> 1;
712
- int halfheight = (height + 1) >> 1;
713
- int r;
714
- if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
715
- !dst_u || !dst_v) {
716
- return -1;
717
- }
718
- // Negative height means invert the image.
719
- if (height < 0) {
720
- height = -height;
721
- src_y = src_y + (height - 1) * src_stride_y;
722
- src_u = src_u + (height - 1) * src_stride_u;
723
- src_v = src_v + (height - 1) * src_stride_v;
724
- src_stride_y = -src_stride_y;
725
- src_stride_u = -src_stride_u;
726
- src_stride_v = -src_stride_v;
727
- }
728
-
729
- switch (mode) {
730
- case kRotate0:
731
- // Copy frame
732
- CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
733
- CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
734
- CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
735
- return 0;
736
-
737
- // Note on temporary Y plane for UV.
738
- // Rotation of UV first fits within the Y destination plane rows.
739
- // Y plane is width x height
740
- // Y plane rotated is height x width
741
- // UV plane is (width / 2) x height
742
- // UV plane rotated is height x (width / 2)
743
- // UV plane rotated+scaled is (height / 2) x width.
744
- // UV plane rotated is a temporary that fits within the Y plane rotated.
745
-
746
- case kRotate90:
747
- RotatePlane90(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
748
- height);
749
- r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_u,
750
- dst_stride_u, halfheight, width, kFilterBilinear);
751
- if (r != 0) {
752
- return r;
753
- }
754
- RotatePlane90(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
755
- height);
756
- r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_v,
757
- dst_stride_v, halfheight, width, kFilterLinear);
758
- if (r != 0) {
759
- return r;
760
- }
761
- RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
762
- return 0;
763
- case kRotate270:
764
- RotatePlane270(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
765
- height);
766
- r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_u,
767
- dst_stride_u, halfheight, width, kFilterBilinear);
768
- if (r != 0) {
769
- return r;
770
- }
771
- RotatePlane270(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
772
- height);
773
- r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_v,
774
- dst_stride_v, halfheight, width, kFilterLinear);
775
- if (r != 0) {
776
- return r;
777
- }
778
- RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
779
- return 0;
780
- case kRotate180:
781
- RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
782
- RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
783
- height);
784
- RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
785
- height);
786
- return 0;
787
- default:
788
- break;
789
- }
790
- return -1;
791
- }
792
-
793
- LIBYUV_API
794
- int I444Rotate(const uint8_t* src_y,
795
- int src_stride_y,
796
- const uint8_t* src_u,
797
- int src_stride_u,
798
- const uint8_t* src_v,
799
- int src_stride_v,
800
- uint8_t* dst_y,
801
- int dst_stride_y,
802
- uint8_t* dst_u,
803
- int dst_stride_u,
804
- uint8_t* dst_v,
805
- int dst_stride_v,
806
- int width,
807
- int height,
808
- enum RotationMode mode) {
809
- if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
810
- !dst_u || !dst_v) {
811
- return -1;
812
- }
813
-
814
- // Negative height means invert the image.
815
- if (height < 0) {
816
- height = -height;
817
- src_y = src_y + (height - 1) * src_stride_y;
818
- src_u = src_u + (height - 1) * src_stride_u;
819
- src_v = src_v + (height - 1) * src_stride_v;
820
- src_stride_y = -src_stride_y;
821
- src_stride_u = -src_stride_u;
822
- src_stride_v = -src_stride_v;
823
- }
824
-
825
- switch (mode) {
826
- case kRotate0:
827
- // copy frame
828
- CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
829
- CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
830
- CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
831
- return 0;
832
- case kRotate90:
833
- RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
834
- RotatePlane90(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
835
- RotatePlane90(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
836
- return 0;
837
- case kRotate270:
838
- RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
839
- RotatePlane270(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
840
- RotatePlane270(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
841
- return 0;
842
- case kRotate180:
843
- RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
844
- RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
845
- RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
846
- return 0;
847
- default:
848
- break;
849
- }
850
- return -1;
851
- }
852
-
853
- LIBYUV_API
854
- int NV12ToI420Rotate(const uint8_t* src_y,
855
- int src_stride_y,
856
- const uint8_t* src_uv,
857
- int src_stride_uv,
858
- uint8_t* dst_y,
859
- int dst_stride_y,
860
- uint8_t* dst_u,
861
- int dst_stride_u,
862
- uint8_t* dst_v,
863
- int dst_stride_v,
864
- int width,
865
- int height,
866
- enum RotationMode mode) {
867
- int halfwidth = (width + 1) >> 1;
868
- int halfheight = (height + 1) >> 1;
869
- if (!src_y || !src_uv || width <= 0 || height == 0 || !dst_y || !dst_u ||
870
- !dst_v) {
871
- return -1;
872
- }
873
-
874
- // Negative height means invert the image.
875
- if (height < 0) {
876
- height = -height;
877
- halfheight = (height + 1) >> 1;
878
- src_y = src_y + (height - 1) * src_stride_y;
879
- src_uv = src_uv + (halfheight - 1) * src_stride_uv;
880
- src_stride_y = -src_stride_y;
881
- src_stride_uv = -src_stride_uv;
882
- }
883
-
884
- switch (mode) {
885
- case kRotate0:
886
- // copy frame
887
- return NV12ToI420(src_y, src_stride_y, src_uv, src_stride_uv, dst_y,
888
- dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
889
- width, height);
890
- case kRotate90:
891
- RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
892
- SplitRotateUV90(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
893
- dst_stride_v, halfwidth, halfheight);
894
- return 0;
895
- case kRotate270:
896
- RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
897
- SplitRotateUV270(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
898
- dst_stride_v, halfwidth, halfheight);
899
- return 0;
900
- case kRotate180:
901
- RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
902
- SplitRotateUV180(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
903
- dst_stride_v, halfwidth, halfheight);
904
- return 0;
905
- default:
906
- break;
907
- }
908
- return -1;
909
- }
910
-
911
- static void SplitPixels(const uint8_t* src_u,
912
- int src_pixel_stride_uv,
913
- uint8_t* dst_u,
914
- int width) {
915
- int i;
916
- for (i = 0; i < width; ++i) {
917
- *dst_u = *src_u;
918
- ++dst_u;
919
- src_u += src_pixel_stride_uv;
920
- }
921
- }
922
-
923
- // Convert Android420 to I420 with Rotate
924
- LIBYUV_API
925
- int Android420ToI420Rotate(const uint8_t* src_y,
926
- int src_stride_y,
927
- const uint8_t* src_u,
928
- int src_stride_u,
929
- const uint8_t* src_v,
930
- int src_stride_v,
931
- int src_pixel_stride_uv,
932
- uint8_t* dst_y,
933
- int dst_stride_y,
934
- uint8_t* dst_u,
935
- int dst_stride_u,
936
- uint8_t* dst_v,
937
- int dst_stride_v,
938
- int width,
939
- int height,
940
- enum RotationMode rotation) {
941
- int y;
942
- const ptrdiff_t vu_off = src_v - src_u;
943
- int halfwidth = (width + 1) >> 1;
944
- int halfheight = (height + 1) >> 1;
945
- if ((!src_y && dst_y) || !src_u || !src_v || !dst_u || !dst_v || width <= 0 ||
946
- height == 0) {
947
- return -1;
948
- }
949
- // Negative height means invert the image.
950
- if (height < 0) {
951
- height = -height;
952
- halfheight = (height + 1) >> 1;
953
- src_y = src_y + (height - 1) * src_stride_y;
954
- src_u = src_u + (halfheight - 1) * src_stride_u;
955
- src_v = src_v + (halfheight - 1) * src_stride_v;
956
- src_stride_y = -src_stride_y;
957
- src_stride_u = -src_stride_u;
958
- src_stride_v = -src_stride_v;
959
- }
960
-
961
- if (dst_y) {
962
- RotatePlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height,
963
- rotation);
964
- }
965
-
966
- // Copy UV planes - I420
967
- if (src_pixel_stride_uv == 1) {
968
- RotatePlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight,
969
- rotation);
970
- RotatePlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight,
971
- rotation);
972
- return 0;
973
- }
974
- // Split UV planes - NV21
975
- if (src_pixel_stride_uv == 2 && vu_off == -1 &&
976
- src_stride_u == src_stride_v) {
977
- SplitRotateUV(src_v, src_stride_v, dst_v, dst_stride_v, dst_u, dst_stride_u,
978
- halfwidth, halfheight, rotation);
979
- return 0;
980
- }
981
- // Split UV planes - NV12
982
- if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
983
- SplitRotateUV(src_u, src_stride_u, dst_u, dst_stride_u, dst_v, dst_stride_v,
984
- halfwidth, halfheight, rotation);
985
- return 0;
986
- }
987
-
988
- if (rotation == 0) {
989
- for (y = 0; y < halfheight; ++y) {
990
- SplitPixels(src_u, src_pixel_stride_uv, dst_u, halfwidth);
991
- SplitPixels(src_v, src_pixel_stride_uv, dst_v, halfwidth);
992
- src_u += src_stride_u;
993
- src_v += src_stride_v;
994
- dst_u += dst_stride_u;
995
- dst_v += dst_stride_v;
996
- }
997
- return 0;
998
- }
999
- // unsupported type and/or rotation.
1000
- return -1;
1001
- }
1002
-
1003
- LIBYUV_API
1004
- int I010Rotate(const uint16_t* src_y,
1005
- int src_stride_y,
1006
- const uint16_t* src_u,
1007
- int src_stride_u,
1008
- const uint16_t* src_v,
1009
- int src_stride_v,
1010
- uint16_t* dst_y,
1011
- int dst_stride_y,
1012
- uint16_t* dst_u,
1013
- int dst_stride_u,
1014
- uint16_t* dst_v,
1015
- int dst_stride_v,
1016
- int width,
1017
- int height,
1018
- enum RotationMode mode) {
1019
- int halfwidth = (width + 1) >> 1;
1020
- int halfheight = (height + 1) >> 1;
1021
- if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1022
- !dst_u || !dst_v || dst_stride_y < 0) {
1023
- return -1;
1024
- }
1025
- // Negative height means invert the image.
1026
- if (height < 0) {
1027
- height = -height;
1028
- src_y = src_y + (height - 1) * src_stride_y;
1029
- src_u = src_u + (height - 1) * src_stride_u;
1030
- src_v = src_v + (height - 1) * src_stride_v;
1031
- src_stride_y = -src_stride_y;
1032
- src_stride_u = -src_stride_u;
1033
- src_stride_v = -src_stride_v;
1034
- }
1035
-
1036
- switch (mode) {
1037
- case kRotate0:
1038
- // copy frame
1039
- return I010Copy(src_y, src_stride_y, src_u, src_stride_u, src_v,
1040
- src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
1041
- dst_v, dst_stride_v, width, height);
1042
- case kRotate90:
1043
- RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1044
- RotatePlane90_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1045
- halfheight);
1046
- RotatePlane90_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1047
- halfheight);
1048
- return 0;
1049
- case kRotate270:
1050
- RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1051
- height);
1052
- RotatePlane270_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1053
- halfheight);
1054
- RotatePlane270_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1055
- halfheight);
1056
- return 0;
1057
- case kRotate180:
1058
- RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1059
- height);
1060
- RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1061
- halfheight);
1062
- RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1063
- halfheight);
1064
- return 0;
1065
- default:
1066
- break;
1067
- }
1068
- return -1;
1069
- }
1070
-
1071
- // I210 has half width x full height UV planes, so rotate by 90 and 270
1072
- // require scaling to maintain 422 subsampling.
1073
- LIBYUV_API
1074
- int I210Rotate(const uint16_t* src_y,
1075
- int src_stride_y,
1076
- const uint16_t* src_u,
1077
- int src_stride_u,
1078
- const uint16_t* src_v,
1079
- int src_stride_v,
1080
- uint16_t* dst_y,
1081
- int dst_stride_y,
1082
- uint16_t* dst_u,
1083
- int dst_stride_u,
1084
- uint16_t* dst_v,
1085
- int dst_stride_v,
1086
- int width,
1087
- int height,
1088
- enum RotationMode mode) {
1089
- int halfwidth = (width + 1) >> 1;
1090
- int halfheight = (height + 1) >> 1;
1091
- int r;
1092
- if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1093
- !dst_u || !dst_v) {
1094
- return -1;
1095
- }
1096
- // Negative height means invert the image.
1097
- if (height < 0) {
1098
- height = -height;
1099
- src_y = src_y + (height - 1) * src_stride_y;
1100
- src_u = src_u + (height - 1) * src_stride_u;
1101
- src_v = src_v + (height - 1) * src_stride_v;
1102
- src_stride_y = -src_stride_y;
1103
- src_stride_u = -src_stride_u;
1104
- src_stride_v = -src_stride_v;
1105
- }
1106
-
1107
- switch (mode) {
1108
- case kRotate0:
1109
- // Copy frame
1110
- CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1111
- CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
1112
- CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
1113
- return 0;
1114
-
1115
- // Note on temporary Y plane for UV.
1116
- // Rotation of UV first fits within the Y destination plane rows.
1117
- // Y plane is width x height
1118
- // Y plane rotated is height x width
1119
- // UV plane is (width / 2) x height
1120
- // UV plane rotated is height x (width / 2)
1121
- // UV plane rotated+scaled is (height / 2) x width.
1122
- // UV plane rotated is a temporary that fits within the Y plane rotated.
1123
-
1124
- case kRotate90:
1125
- RotatePlane90_16(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
1126
- height);
1127
- r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_u,
1128
- dst_stride_u, halfheight, width, kFilterBilinear);
1129
- if (r != 0) {
1130
- return r;
1131
- }
1132
- RotatePlane90_16(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
1133
- height);
1134
- r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_v,
1135
- dst_stride_v, halfheight, width, kFilterLinear);
1136
- if (r != 0) {
1137
- return r;
1138
- }
1139
- RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1140
- return 0;
1141
- case kRotate270:
1142
- RotatePlane270_16(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
1143
- height);
1144
- r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_u,
1145
- dst_stride_u, halfheight, width, kFilterBilinear);
1146
- if (r != 0) {
1147
- return r;
1148
- }
1149
- RotatePlane270_16(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
1150
- height);
1151
- r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_v,
1152
- dst_stride_v, halfheight, width, kFilterLinear);
1153
- if (r != 0) {
1154
- return r;
1155
- }
1156
- RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1157
- height);
1158
- return 0;
1159
- case kRotate180:
1160
- RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1161
- height);
1162
- RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1163
- height);
1164
- RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1165
- height);
1166
- return 0;
1167
- default:
1168
- break;
1169
- }
1170
- return -1;
1171
- }
1172
-
1173
- LIBYUV_API
1174
- int I410Rotate(const uint16_t* src_y,
1175
- int src_stride_y,
1176
- const uint16_t* src_u,
1177
- int src_stride_u,
1178
- const uint16_t* src_v,
1179
- int src_stride_v,
1180
- uint16_t* dst_y,
1181
- int dst_stride_y,
1182
- uint16_t* dst_u,
1183
- int dst_stride_u,
1184
- uint16_t* dst_v,
1185
- int dst_stride_v,
1186
- int width,
1187
- int height,
1188
- enum RotationMode mode) {
1189
- if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1190
- !dst_u || !dst_v || dst_stride_y < 0) {
1191
- return -1;
1192
- }
1193
- // Negative height means invert the image.
1194
- if (height < 0) {
1195
- height = -height;
1196
- src_y = src_y + (height - 1) * src_stride_y;
1197
- src_u = src_u + (height - 1) * src_stride_u;
1198
- src_v = src_v + (height - 1) * src_stride_v;
1199
- src_stride_y = -src_stride_y;
1200
- src_stride_u = -src_stride_u;
1201
- src_stride_v = -src_stride_v;
1202
- }
1203
-
1204
- switch (mode) {
1205
- case kRotate0:
1206
- // copy frame
1207
- CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1208
- CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
1209
- CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
1210
- return 0;
1211
- case kRotate90:
1212
- RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1213
- RotatePlane90_16(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
1214
- RotatePlane90_16(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
1215
- return 0;
1216
- case kRotate270:
1217
- RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1218
- height);
1219
- RotatePlane270_16(src_u, src_stride_u, dst_u, dst_stride_u, width,
1220
- height);
1221
- RotatePlane270_16(src_v, src_stride_v, dst_v, dst_stride_v, width,
1222
- height);
1223
- return 0;
1224
- case kRotate180:
1225
- RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1226
- height);
1227
- RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, width,
1228
- height);
1229
- RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, width,
1230
- height);
1231
- return 0;
1232
- default:
1233
- break;
1234
- }
1235
- return -1;
1236
- }
1237
-
1238
- #ifdef __cplusplus
1239
- } // extern "C"
1240
- } // namespace libyuv
1241
- #endif
1
+ /*
2
+ * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3
+ *
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
6
+ * tree. An additional intellectual property rights grant can be found
7
+ * in the file PATENTS. All contributing project authors may
8
+ * be found in the AUTHORS file in the root of the source tree.
9
+ */
10
+
11
+ #include <assert.h>
12
+
13
+ #include "libyuv/rotate.h"
14
+
15
+ #include "libyuv/convert.h"
16
+ #include "libyuv/cpu_id.h"
17
+ #include "libyuv/planar_functions.h"
18
+ #include "libyuv/rotate_row.h"
19
+ #include "libyuv/row.h"
20
+
21
+ #ifdef __cplusplus
22
+ namespace libyuv {
23
+ extern "C" {
24
+ #endif
25
+
26
+ LIBYUV_API
27
+ void TransposePlane(const uint8_t* src,
28
+ int src_stride,
29
+ uint8_t* dst,
30
+ int dst_stride,
31
+ int width,
32
+ int height) {
33
+ int i = height;
34
+ #if defined(HAS_TRANSPOSEWXH_SME)
35
+ void (*TransposeWxH)(const uint8_t* src, int src_stride, uint8_t* dst,
36
+ int dst_stride, int width, int height) = NULL;
37
+ #endif
38
+ #if defined(HAS_TRANSPOSEWX16_LSX) || defined(HAS_TRANSPOSEWX16_NEON)
39
+ void (*TransposeWx16)(const uint8_t* src, int src_stride, uint8_t* dst,
40
+ int dst_stride, int width) = TransposeWx16_C;
41
+ #else
42
+ void (*TransposeWx8)(const uint8_t* src, int src_stride, uint8_t* dst,
43
+ int dst_stride, int width) = TransposeWx8_C;
44
+ #endif
45
+
46
+ #if defined(HAS_TRANSPOSEWX8_NEON)
47
+ if (TestCpuFlag(kCpuHasNEON)) {
48
+ TransposeWx8 = TransposeWx8_Any_NEON;
49
+ if (IS_ALIGNED(width, 8)) {
50
+ TransposeWx8 = TransposeWx8_NEON;
51
+ }
52
+ }
53
+ #endif
54
+ #if defined(HAS_TRANSPOSEWX16_NEON)
55
+ if (TestCpuFlag(kCpuHasNEON)) {
56
+ TransposeWx16 = TransposeWx16_Any_NEON;
57
+ if (IS_ALIGNED(width, 16)) {
58
+ TransposeWx16 = TransposeWx16_NEON;
59
+ }
60
+ }
61
+ #endif
62
+ #if defined(HAS_TRANSPOSEWXH_SME)
63
+ if (TestCpuFlag(kCpuHasSME)) {
64
+ TransposeWxH = TransposeWxH_SME;
65
+ }
66
+ #endif
67
+ #if defined(HAS_TRANSPOSEWX8_SSSE3)
68
+ if (TestCpuFlag(kCpuHasSSSE3)) {
69
+ TransposeWx8 = TransposeWx8_Any_SSSE3;
70
+ if (IS_ALIGNED(width, 8)) {
71
+ TransposeWx8 = TransposeWx8_SSSE3;
72
+ }
73
+ }
74
+ #endif
75
+ #if defined(HAS_TRANSPOSEWX8_FAST_SSSE3)
76
+ if (TestCpuFlag(kCpuHasSSSE3)) {
77
+ TransposeWx8 = TransposeWx8_Fast_Any_SSSE3;
78
+ if (IS_ALIGNED(width, 16)) {
79
+ TransposeWx8 = TransposeWx8_Fast_SSSE3;
80
+ }
81
+ }
82
+ #endif
83
+ #if defined(HAS_TRANSPOSEWX16_LSX)
84
+ if (TestCpuFlag(kCpuHasLSX)) {
85
+ TransposeWx16 = TransposeWx16_Any_LSX;
86
+ if (IS_ALIGNED(width, 16)) {
87
+ TransposeWx16 = TransposeWx16_LSX;
88
+ }
89
+ }
90
+ #endif
91
+
92
+ #if defined(HAS_TRANSPOSEWXH_SME)
93
+ if (TransposeWxH) {
94
+ TransposeWxH(src, src_stride, dst, dst_stride, width, height);
95
+ return;
96
+ }
97
+ #endif
98
+ #if defined(HAS_TRANSPOSEWX16_LSX) || defined(HAS_TRANSPOSEWX16_NEON)
99
+ // Work across the source in 16x16 tiles
100
+ while (i >= 16) {
101
+ TransposeWx16(src, src_stride, dst, dst_stride, width);
102
+ src += 16 * src_stride; // Go down 16 rows.
103
+ dst += 16; // Move over 16 columns.
104
+ i -= 16;
105
+ }
106
+ #else
107
+ // Work across the source in 8x8 tiles
108
+ while (i >= 8) {
109
+ TransposeWx8(src, src_stride, dst, dst_stride, width);
110
+ src += 8 * src_stride; // Go down 8 rows.
111
+ dst += 8; // Move over 8 columns.
112
+ i -= 8;
113
+ }
114
+ #endif
115
+
116
+ if (i > 0) {
117
+ TransposeWxH_C(src, src_stride, dst, dst_stride, width, i);
118
+ }
119
+ }
120
+
121
+ LIBYUV_API
122
+ void RotatePlane90(const uint8_t* src,
123
+ int src_stride,
124
+ uint8_t* dst,
125
+ int dst_stride,
126
+ int width,
127
+ int height) {
128
+ // Rotate by 90 is a transpose with the source read
129
+ // from bottom to top. So set the source pointer to the end
130
+ // of the buffer and flip the sign of the source stride.
131
+ src += src_stride * (height - 1);
132
+ src_stride = -src_stride;
133
+ TransposePlane(src, src_stride, dst, dst_stride, width, height);
134
+ }
135
+
136
+ LIBYUV_API
137
+ void RotatePlane270(const uint8_t* src,
138
+ int src_stride,
139
+ uint8_t* dst,
140
+ int dst_stride,
141
+ int width,
142
+ int height) {
143
+ // Rotate by 270 is a transpose with the destination written
144
+ // from bottom to top. So set the destination pointer to the end
145
+ // of the buffer and flip the sign of the destination stride.
146
+ dst += dst_stride * (width - 1);
147
+ dst_stride = -dst_stride;
148
+ TransposePlane(src, src_stride, dst, dst_stride, width, height);
149
+ }
150
+
151
+ LIBYUV_API
152
+ void RotatePlane180(const uint8_t* src,
153
+ int src_stride,
154
+ uint8_t* dst,
155
+ int dst_stride,
156
+ int width,
157
+ int height) {
158
+ // Swap top and bottom row and mirror the content. Uses a temporary row.
159
+ align_buffer_64(row, width);
160
+ assert(row);
161
+ if (!row)
162
+ return;
163
+ const uint8_t* src_bot = src + src_stride * (height - 1);
164
+ uint8_t* dst_bot = dst + dst_stride * (height - 1);
165
+ int half_height = (height + 1) >> 1;
166
+ int y;
167
+ void (*MirrorRow)(const uint8_t* src, uint8_t* dst, int width) = MirrorRow_C;
168
+ void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C;
169
+ #if defined(HAS_MIRRORROW_NEON)
170
+ if (TestCpuFlag(kCpuHasNEON)) {
171
+ MirrorRow = MirrorRow_Any_NEON;
172
+ if (IS_ALIGNED(width, 32)) {
173
+ MirrorRow = MirrorRow_NEON;
174
+ }
175
+ }
176
+ #endif
177
+ #if defined(HAS_MIRRORROW_SSSE3)
178
+ if (TestCpuFlag(kCpuHasSSSE3)) {
179
+ MirrorRow = MirrorRow_Any_SSSE3;
180
+ if (IS_ALIGNED(width, 16)) {
181
+ MirrorRow = MirrorRow_SSSE3;
182
+ }
183
+ }
184
+ #endif
185
+ #if defined(HAS_MIRRORROW_AVX2)
186
+ if (TestCpuFlag(kCpuHasAVX2)) {
187
+ MirrorRow = MirrorRow_Any_AVX2;
188
+ if (IS_ALIGNED(width, 32)) {
189
+ MirrorRow = MirrorRow_AVX2;
190
+ }
191
+ }
192
+ #endif
193
+ #if defined(HAS_MIRRORROW_LSX)
194
+ if (TestCpuFlag(kCpuHasLSX)) {
195
+ MirrorRow = MirrorRow_Any_LSX;
196
+ if (IS_ALIGNED(width, 32)) {
197
+ MirrorRow = MirrorRow_LSX;
198
+ }
199
+ }
200
+ #endif
201
+ #if defined(HAS_MIRRORROW_LASX)
202
+ if (TestCpuFlag(kCpuHasLASX)) {
203
+ MirrorRow = MirrorRow_Any_LASX;
204
+ if (IS_ALIGNED(width, 64)) {
205
+ MirrorRow = MirrorRow_LASX;
206
+ }
207
+ }
208
+ #endif
209
+ #if defined(HAS_COPYROW_SSE2)
210
+ if (TestCpuFlag(kCpuHasSSE2)) {
211
+ CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2;
212
+ }
213
+ #endif
214
+ #if defined(HAS_COPYROW_AVX)
215
+ if (TestCpuFlag(kCpuHasAVX)) {
216
+ CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX;
217
+ }
218
+ #endif
219
+ #if defined(HAS_COPYROW_AVX512BW)
220
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
221
+ CopyRow = IS_ALIGNED(width, 128) ? CopyRow_AVX512BW : CopyRow_Any_AVX512BW;
222
+ }
223
+ #endif
224
+ #if defined(HAS_COPYROW_ERMS)
225
+ if (TestCpuFlag(kCpuHasERMS)) {
226
+ CopyRow = CopyRow_ERMS;
227
+ }
228
+ #endif
229
+ #if defined(HAS_COPYROW_NEON)
230
+ if (TestCpuFlag(kCpuHasNEON)) {
231
+ CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON;
232
+ }
233
+ #endif
234
+ #if defined(HAS_COPYROW_SME)
235
+ if (TestCpuFlag(kCpuHasSME)) {
236
+ CopyRow = CopyRow_SME;
237
+ }
238
+ #endif
239
+ #if defined(HAS_COPYROW_RVV)
240
+ if (TestCpuFlag(kCpuHasRVV)) {
241
+ CopyRow = CopyRow_RVV;
242
+ }
243
+ #endif
244
+
245
+ // Odd height will harmlessly mirror the middle row twice.
246
+ for (y = 0; y < half_height; ++y) {
247
+ CopyRow(src, row, width); // Copy top row into buffer
248
+ MirrorRow(src_bot, dst, width); // Mirror bottom row into top row
249
+ MirrorRow(row, dst_bot, width); // Mirror buffer into bottom row
250
+ src += src_stride;
251
+ dst += dst_stride;
252
+ src_bot -= src_stride;
253
+ dst_bot -= dst_stride;
254
+ }
255
+ free_aligned_buffer_64(row);
256
+ }
257
+
258
+ LIBYUV_API
259
+ void SplitTransposeUV(const uint8_t* src,
260
+ int src_stride,
261
+ uint8_t* dst_a,
262
+ int dst_stride_a,
263
+ uint8_t* dst_b,
264
+ int dst_stride_b,
265
+ int width,
266
+ int height) {
267
+ int i = height;
268
+ #if defined(HAS_TRANSPOSEUVWXH_SME)
269
+ void (*TransposeUVWxH)(const uint8_t* src, int src_stride, uint8_t* dst_a,
270
+ int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
271
+ int width, int height) = TransposeUVWxH_C;
272
+ #endif
273
+ #if defined(HAS_TRANSPOSEUVWX16_LSX)
274
+ void (*TransposeUVWx16)(const uint8_t* src, int src_stride, uint8_t* dst_a,
275
+ int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
276
+ int width) = TransposeUVWx16_C;
277
+ #else
278
+ void (*TransposeUVWx8)(const uint8_t* src, int src_stride, uint8_t* dst_a,
279
+ int dst_stride_a, uint8_t* dst_b, int dst_stride_b,
280
+ int width) = TransposeUVWx8_C;
281
+ #endif
282
+
283
+ #if defined(HAS_TRANSPOSEUVWX16_LSX)
284
+ if (TestCpuFlag(kCpuHasLSX)) {
285
+ TransposeUVWx16 = TransposeUVWx16_Any_LSX;
286
+ if (IS_ALIGNED(width, 8)) {
287
+ TransposeUVWx16 = TransposeUVWx16_LSX;
288
+ }
289
+ }
290
+ #endif
291
+ #if defined(HAS_TRANSPOSEUVWX8_NEON)
292
+ if (TestCpuFlag(kCpuHasNEON)) {
293
+ TransposeUVWx8 = TransposeUVWx8_Any_NEON;
294
+ if (IS_ALIGNED(width, 8)) {
295
+ TransposeUVWx8 = TransposeUVWx8_NEON;
296
+ }
297
+ }
298
+ #endif
299
+ #if defined(HAS_TRANSPOSEUVWXH_SME)
300
+ if (TestCpuFlag(kCpuHasSME)) {
301
+ TransposeUVWxH = TransposeUVWxH_SME;
302
+ }
303
+ #endif
304
+ #if defined(HAS_TRANSPOSEUVWX8_SSE2)
305
+ if (TestCpuFlag(kCpuHasSSE2)) {
306
+ TransposeUVWx8 = TransposeUVWx8_Any_SSE2;
307
+ if (IS_ALIGNED(width, 8)) {
308
+ TransposeUVWx8 = TransposeUVWx8_SSE2;
309
+ }
310
+ }
311
+ #endif
312
+
313
+ #if defined(HAS_TRANSPOSEUVWXH_SME)
314
+ if (TestCpuFlag(kCpuHasSME)) {
315
+ TransposeUVWxH(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
316
+ width, i);
317
+ return;
318
+ }
319
+ #endif
320
+ #if defined(HAS_TRANSPOSEUVWX16_LSX)
321
+ // Work through the source in 8x8 tiles.
322
+ while (i >= 16) {
323
+ TransposeUVWx16(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
324
+ width);
325
+ src += 16 * src_stride; // Go down 16 rows.
326
+ dst_a += 16; // Move over 8 columns.
327
+ dst_b += 16; // Move over 8 columns.
328
+ i -= 16;
329
+ }
330
+ #else
331
+ // Work through the source in 8x8 tiles.
332
+ while (i >= 8) {
333
+ TransposeUVWx8(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
334
+ width);
335
+ src += 8 * src_stride; // Go down 8 rows.
336
+ dst_a += 8; // Move over 8 columns.
337
+ dst_b += 8; // Move over 8 columns.
338
+ i -= 8;
339
+ }
340
+ #endif
341
+
342
+ if (i > 0) {
343
+ TransposeUVWxH_C(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
344
+ width, i);
345
+ }
346
+ }
347
+
348
+ LIBYUV_API
349
+ void SplitRotateUV90(const uint8_t* src,
350
+ int src_stride,
351
+ uint8_t* dst_a,
352
+ int dst_stride_a,
353
+ uint8_t* dst_b,
354
+ int dst_stride_b,
355
+ int width,
356
+ int height) {
357
+ src += src_stride * (height - 1);
358
+ src_stride = -src_stride;
359
+
360
+ SplitTransposeUV(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
361
+ width, height);
362
+ }
363
+
364
+ LIBYUV_API
365
+ void SplitRotateUV270(const uint8_t* src,
366
+ int src_stride,
367
+ uint8_t* dst_a,
368
+ int dst_stride_a,
369
+ uint8_t* dst_b,
370
+ int dst_stride_b,
371
+ int width,
372
+ int height) {
373
+ dst_a += dst_stride_a * (width - 1);
374
+ dst_b += dst_stride_b * (width - 1);
375
+ dst_stride_a = -dst_stride_a;
376
+ dst_stride_b = -dst_stride_b;
377
+
378
+ SplitTransposeUV(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
379
+ width, height);
380
+ }
381
+
382
+ // Rotate 180 is a horizontal and vertical flip.
383
+ LIBYUV_API
384
+ void SplitRotateUV180(const uint8_t* src,
385
+ int src_stride,
386
+ uint8_t* dst_a,
387
+ int dst_stride_a,
388
+ uint8_t* dst_b,
389
+ int dst_stride_b,
390
+ int width,
391
+ int height) {
392
+ int i;
393
+ void (*MirrorSplitUVRow)(const uint8_t* src, uint8_t* dst_u, uint8_t* dst_v,
394
+ int width) = MirrorSplitUVRow_C;
395
+ #if defined(HAS_MIRRORSPLITUVROW_NEON)
396
+ if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
397
+ MirrorSplitUVRow = MirrorSplitUVRow_NEON;
398
+ }
399
+ #endif
400
+ #if defined(HAS_MIRRORSPLITUVROW_SSSE3)
401
+ if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16)) {
402
+ MirrorSplitUVRow = MirrorSplitUVRow_SSSE3;
403
+ }
404
+ #endif
405
+ #if defined(HAS_MIRRORSPLITUVROW_LSX)
406
+ if (TestCpuFlag(kCpuHasLSX) && IS_ALIGNED(width, 32)) {
407
+ MirrorSplitUVRow = MirrorSplitUVRow_LSX;
408
+ }
409
+ #endif
410
+
411
+ dst_a += dst_stride_a * (height - 1);
412
+ dst_b += dst_stride_b * (height - 1);
413
+
414
+ for (i = 0; i < height; ++i) {
415
+ MirrorSplitUVRow(src, dst_a, dst_b, width);
416
+ src += src_stride;
417
+ dst_a -= dst_stride_a;
418
+ dst_b -= dst_stride_b;
419
+ }
420
+ }
421
+
422
+ // Rotate UV and split into planar.
423
+ // width and height expected to be half size for NV12
424
+ LIBYUV_API
425
+ int SplitRotateUV(const uint8_t* src_uv,
426
+ int src_stride_uv,
427
+ uint8_t* dst_u,
428
+ int dst_stride_u,
429
+ uint8_t* dst_v,
430
+ int dst_stride_v,
431
+ int width,
432
+ int height,
433
+ enum RotationMode mode) {
434
+ if (!src_uv || width <= 0 || height == 0 || !dst_u || !dst_v) {
435
+ return -1;
436
+ }
437
+
438
+ // Negative height means invert the image.
439
+ if (height < 0) {
440
+ height = -height;
441
+ src_uv = src_uv + (height - 1) * src_stride_uv;
442
+ src_stride_uv = -src_stride_uv;
443
+ }
444
+
445
+ switch (mode) {
446
+ case kRotate0:
447
+ SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
448
+ dst_stride_v, width, height);
449
+ return 0;
450
+ case kRotate90:
451
+ SplitRotateUV90(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
452
+ dst_stride_v, width, height);
453
+ return 0;
454
+ case kRotate270:
455
+ SplitRotateUV270(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
456
+ dst_stride_v, width, height);
457
+ return 0;
458
+ case kRotate180:
459
+ SplitRotateUV180(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
460
+ dst_stride_v, width, height);
461
+ return 0;
462
+ default:
463
+ break;
464
+ }
465
+ return -1;
466
+ }
467
+
468
+ LIBYUV_API
469
+ int RotatePlane(const uint8_t* src,
470
+ int src_stride,
471
+ uint8_t* dst,
472
+ int dst_stride,
473
+ int width,
474
+ int height,
475
+ enum RotationMode mode) {
476
+ if (!src || width <= 0 || height == 0 || !dst) {
477
+ return -1;
478
+ }
479
+
480
+ // Negative height means invert the image.
481
+ if (height < 0) {
482
+ height = -height;
483
+ src = src + (height - 1) * src_stride;
484
+ src_stride = -src_stride;
485
+ }
486
+
487
+ switch (mode) {
488
+ case kRotate0:
489
+ // copy frame
490
+ CopyPlane(src, src_stride, dst, dst_stride, width, height);
491
+ return 0;
492
+ case kRotate90:
493
+ RotatePlane90(src, src_stride, dst, dst_stride, width, height);
494
+ return 0;
495
+ case kRotate270:
496
+ RotatePlane270(src, src_stride, dst, dst_stride, width, height);
497
+ return 0;
498
+ case kRotate180:
499
+ RotatePlane180(src, src_stride, dst, dst_stride, width, height);
500
+ return 0;
501
+ default:
502
+ break;
503
+ }
504
+ return -1;
505
+ }
506
+
507
+ static void TransposePlane_16(const uint16_t* src,
508
+ int src_stride,
509
+ uint16_t* dst,
510
+ int dst_stride,
511
+ int width,
512
+ int height) {
513
+ int i = height;
514
+ // Work across the source in 8x8 tiles
515
+ while (i >= 8) {
516
+ TransposeWx8_16_C(src, src_stride, dst, dst_stride, width);
517
+ src += 8 * src_stride; // Go down 8 rows.
518
+ dst += 8; // Move over 8 columns.
519
+ i -= 8;
520
+ }
521
+
522
+ if (i > 0) {
523
+ TransposeWxH_16_C(src, src_stride, dst, dst_stride, width, i);
524
+ }
525
+ }
526
+
527
+ static void RotatePlane90_16(const uint16_t* src,
528
+ int src_stride,
529
+ uint16_t* dst,
530
+ int dst_stride,
531
+ int width,
532
+ int height) {
533
+ // Rotate by 90 is a transpose with the source read
534
+ // from bottom to top. So set the source pointer to the end
535
+ // of the buffer and flip the sign of the source stride.
536
+ src += src_stride * (height - 1);
537
+ src_stride = -src_stride;
538
+ TransposePlane_16(src, src_stride, dst, dst_stride, width, height);
539
+ }
540
+
541
+ static void RotatePlane270_16(const uint16_t* src,
542
+ int src_stride,
543
+ uint16_t* dst,
544
+ int dst_stride,
545
+ int width,
546
+ int height) {
547
+ // Rotate by 270 is a transpose with the destination written
548
+ // from bottom to top. So set the destination pointer to the end
549
+ // of the buffer and flip the sign of the destination stride.
550
+ dst += dst_stride * (width - 1);
551
+ dst_stride = -dst_stride;
552
+ TransposePlane_16(src, src_stride, dst, dst_stride, width, height);
553
+ }
554
+
555
+ static void RotatePlane180_16(const uint16_t* src,
556
+ int src_stride,
557
+ uint16_t* dst,
558
+ int dst_stride,
559
+ int width,
560
+ int height) {
561
+ const uint16_t* src_bot = src + src_stride * (height - 1);
562
+ uint16_t* dst_bot = dst + dst_stride * (height - 1);
563
+ int half_height = (height + 1) >> 1;
564
+ int y;
565
+
566
+ // Swap top and bottom row and mirror the content. Uses a temporary row.
567
+ align_buffer_64(row, width * 2);
568
+ uint16_t* row_tmp = (uint16_t*)row;
569
+ assert(row);
570
+ if (!row)
571
+ return;
572
+
573
+ // Odd height will harmlessly mirror the middle row twice.
574
+ for (y = 0; y < half_height; ++y) {
575
+ CopyRow_16_C(src, row_tmp, width); // Copy top row into buffer
576
+ MirrorRow_16_C(src_bot, dst, width); // Mirror bottom row into top row
577
+ MirrorRow_16_C(row_tmp, dst_bot, width); // Mirror buffer into bottom row
578
+ src += src_stride;
579
+ dst += dst_stride;
580
+ src_bot -= src_stride;
581
+ dst_bot -= dst_stride;
582
+ }
583
+ free_aligned_buffer_64(row);
584
+ }
585
+
586
+ LIBYUV_API
587
+ int RotatePlane_16(const uint16_t* src,
588
+ int src_stride,
589
+ uint16_t* dst,
590
+ int dst_stride,
591
+ int width,
592
+ int height,
593
+ enum RotationMode mode) {
594
+ if (!src || width <= 0 || height == 0 || !dst) {
595
+ return -1;
596
+ }
597
+
598
+ // Negative height means invert the image.
599
+ if (height < 0) {
600
+ height = -height;
601
+ src = src + (height - 1) * src_stride;
602
+ src_stride = -src_stride;
603
+ }
604
+
605
+ switch (mode) {
606
+ case kRotate0:
607
+ // copy frame
608
+ CopyPlane_16(src, src_stride, dst, dst_stride, width, height);
609
+ return 0;
610
+ case kRotate90:
611
+ RotatePlane90_16(src, src_stride, dst, dst_stride, width, height);
612
+ return 0;
613
+ case kRotate270:
614
+ RotatePlane270_16(src, src_stride, dst, dst_stride, width, height);
615
+ return 0;
616
+ case kRotate180:
617
+ RotatePlane180_16(src, src_stride, dst, dst_stride, width, height);
618
+ return 0;
619
+ default:
620
+ break;
621
+ }
622
+ return -1;
623
+ }
624
+
625
+ LIBYUV_API
626
+ int I420Rotate(const uint8_t* src_y,
627
+ int src_stride_y,
628
+ const uint8_t* src_u,
629
+ int src_stride_u,
630
+ const uint8_t* src_v,
631
+ int src_stride_v,
632
+ uint8_t* dst_y,
633
+ int dst_stride_y,
634
+ uint8_t* dst_u,
635
+ int dst_stride_u,
636
+ uint8_t* dst_v,
637
+ int dst_stride_v,
638
+ int width,
639
+ int height,
640
+ enum RotationMode mode) {
641
+ int halfwidth = (width + 1) >> 1;
642
+ int halfheight = (height + 1) >> 1;
643
+ if ((!src_y && dst_y) || !src_u || !src_v || width <= 0 || height == 0 ||
644
+ !dst_y || !dst_u || !dst_v) {
645
+ return -1;
646
+ }
647
+
648
+ // Negative height means invert the image.
649
+ if (height < 0) {
650
+ height = -height;
651
+ halfheight = (height + 1) >> 1;
652
+ src_y = src_y + (height - 1) * src_stride_y;
653
+ src_u = src_u + (halfheight - 1) * src_stride_u;
654
+ src_v = src_v + (halfheight - 1) * src_stride_v;
655
+ src_stride_y = -src_stride_y;
656
+ src_stride_u = -src_stride_u;
657
+ src_stride_v = -src_stride_v;
658
+ }
659
+
660
+ switch (mode) {
661
+ case kRotate0:
662
+ // copy frame
663
+ return I420Copy(src_y, src_stride_y, src_u, src_stride_u, src_v,
664
+ src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
665
+ dst_v, dst_stride_v, width, height);
666
+ case kRotate90:
667
+ RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
668
+ RotatePlane90(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
669
+ halfheight);
670
+ RotatePlane90(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
671
+ halfheight);
672
+ return 0;
673
+ case kRotate270:
674
+ RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
675
+ RotatePlane270(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
676
+ halfheight);
677
+ RotatePlane270(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
678
+ halfheight);
679
+ return 0;
680
+ case kRotate180:
681
+ RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
682
+ RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
683
+ halfheight);
684
+ RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
685
+ halfheight);
686
+ return 0;
687
+ default:
688
+ break;
689
+ }
690
+ return -1;
691
+ }
692
+
693
+ // I422 has half width x full height UV planes, so rotate by 90 and 270
694
+ // require scaling to maintain 422 subsampling.
695
+ LIBYUV_API
696
+ int I422Rotate(const uint8_t* src_y,
697
+ int src_stride_y,
698
+ const uint8_t* src_u,
699
+ int src_stride_u,
700
+ const uint8_t* src_v,
701
+ int src_stride_v,
702
+ uint8_t* dst_y,
703
+ int dst_stride_y,
704
+ uint8_t* dst_u,
705
+ int dst_stride_u,
706
+ uint8_t* dst_v,
707
+ int dst_stride_v,
708
+ int width,
709
+ int height,
710
+ enum RotationMode mode) {
711
+ int halfwidth = (width + 1) >> 1;
712
+ int halfheight = (height + 1) >> 1;
713
+ int r;
714
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
715
+ !dst_u || !dst_v) {
716
+ return -1;
717
+ }
718
+ // Negative height means invert the image.
719
+ if (height < 0) {
720
+ height = -height;
721
+ src_y = src_y + (height - 1) * src_stride_y;
722
+ src_u = src_u + (height - 1) * src_stride_u;
723
+ src_v = src_v + (height - 1) * src_stride_v;
724
+ src_stride_y = -src_stride_y;
725
+ src_stride_u = -src_stride_u;
726
+ src_stride_v = -src_stride_v;
727
+ }
728
+
729
+ switch (mode) {
730
+ case kRotate0:
731
+ // Copy frame
732
+ CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
733
+ CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
734
+ CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
735
+ return 0;
736
+
737
+ // Note on temporary Y plane for UV.
738
+ // Rotation of UV first fits within the Y destination plane rows.
739
+ // Y plane is width x height
740
+ // Y plane rotated is height x width
741
+ // UV plane is (width / 2) x height
742
+ // UV plane rotated is height x (width / 2)
743
+ // UV plane rotated+scaled is (height / 2) x width.
744
+ // UV plane rotated is a temporary that fits within the Y plane rotated.
745
+
746
+ case kRotate90:
747
+ RotatePlane90(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
748
+ height);
749
+ r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_u,
750
+ dst_stride_u, halfheight, width, kFilterBilinear);
751
+ if (r != 0) {
752
+ return r;
753
+ }
754
+ RotatePlane90(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
755
+ height);
756
+ r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_v,
757
+ dst_stride_v, halfheight, width, kFilterLinear);
758
+ if (r != 0) {
759
+ return r;
760
+ }
761
+ RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
762
+ return 0;
763
+ case kRotate270:
764
+ RotatePlane270(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
765
+ height);
766
+ r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_u,
767
+ dst_stride_u, halfheight, width, kFilterBilinear);
768
+ if (r != 0) {
769
+ return r;
770
+ }
771
+ RotatePlane270(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
772
+ height);
773
+ r = ScalePlane(dst_y, dst_stride_y, height, halfwidth, dst_v,
774
+ dst_stride_v, halfheight, width, kFilterLinear);
775
+ if (r != 0) {
776
+ return r;
777
+ }
778
+ RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
779
+ return 0;
780
+ case kRotate180:
781
+ RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
782
+ RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
783
+ height);
784
+ RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
785
+ height);
786
+ return 0;
787
+ default:
788
+ break;
789
+ }
790
+ return -1;
791
+ }
792
+
793
+ LIBYUV_API
794
+ int I444Rotate(const uint8_t* src_y,
795
+ int src_stride_y,
796
+ const uint8_t* src_u,
797
+ int src_stride_u,
798
+ const uint8_t* src_v,
799
+ int src_stride_v,
800
+ uint8_t* dst_y,
801
+ int dst_stride_y,
802
+ uint8_t* dst_u,
803
+ int dst_stride_u,
804
+ uint8_t* dst_v,
805
+ int dst_stride_v,
806
+ int width,
807
+ int height,
808
+ enum RotationMode mode) {
809
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
810
+ !dst_u || !dst_v) {
811
+ return -1;
812
+ }
813
+
814
+ // Negative height means invert the image.
815
+ if (height < 0) {
816
+ height = -height;
817
+ src_y = src_y + (height - 1) * src_stride_y;
818
+ src_u = src_u + (height - 1) * src_stride_u;
819
+ src_v = src_v + (height - 1) * src_stride_v;
820
+ src_stride_y = -src_stride_y;
821
+ src_stride_u = -src_stride_u;
822
+ src_stride_v = -src_stride_v;
823
+ }
824
+
825
+ switch (mode) {
826
+ case kRotate0:
827
+ // copy frame
828
+ CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
829
+ CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
830
+ CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
831
+ return 0;
832
+ case kRotate90:
833
+ RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
834
+ RotatePlane90(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
835
+ RotatePlane90(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
836
+ return 0;
837
+ case kRotate270:
838
+ RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
839
+ RotatePlane270(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
840
+ RotatePlane270(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
841
+ return 0;
842
+ case kRotate180:
843
+ RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
844
+ RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
845
+ RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
846
+ return 0;
847
+ default:
848
+ break;
849
+ }
850
+ return -1;
851
+ }
852
+
853
+ LIBYUV_API
854
+ int NV12ToI420Rotate(const uint8_t* src_y,
855
+ int src_stride_y,
856
+ const uint8_t* src_uv,
857
+ int src_stride_uv,
858
+ uint8_t* dst_y,
859
+ int dst_stride_y,
860
+ uint8_t* dst_u,
861
+ int dst_stride_u,
862
+ uint8_t* dst_v,
863
+ int dst_stride_v,
864
+ int width,
865
+ int height,
866
+ enum RotationMode mode) {
867
+ int halfwidth = (width + 1) >> 1;
868
+ int halfheight = (height + 1) >> 1;
869
+ if (!src_y || !src_uv || width <= 0 || height == 0 || !dst_y || !dst_u ||
870
+ !dst_v) {
871
+ return -1;
872
+ }
873
+
874
+ // Negative height means invert the image.
875
+ if (height < 0) {
876
+ height = -height;
877
+ halfheight = (height + 1) >> 1;
878
+ src_y = src_y + (height - 1) * src_stride_y;
879
+ src_uv = src_uv + (halfheight - 1) * src_stride_uv;
880
+ src_stride_y = -src_stride_y;
881
+ src_stride_uv = -src_stride_uv;
882
+ }
883
+
884
+ switch (mode) {
885
+ case kRotate0:
886
+ // copy frame
887
+ return NV12ToI420(src_y, src_stride_y, src_uv, src_stride_uv, dst_y,
888
+ dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
889
+ width, height);
890
+ case kRotate90:
891
+ RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
892
+ SplitRotateUV90(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
893
+ dst_stride_v, halfwidth, halfheight);
894
+ return 0;
895
+ case kRotate270:
896
+ RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
897
+ SplitRotateUV270(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
898
+ dst_stride_v, halfwidth, halfheight);
899
+ return 0;
900
+ case kRotate180:
901
+ RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
902
+ SplitRotateUV180(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v,
903
+ dst_stride_v, halfwidth, halfheight);
904
+ return 0;
905
+ default:
906
+ break;
907
+ }
908
+ return -1;
909
+ }
910
+
911
+ static void SplitPixels(const uint8_t* src_u,
912
+ int src_pixel_stride_uv,
913
+ uint8_t* dst_u,
914
+ int width) {
915
+ int i;
916
+ for (i = 0; i < width; ++i) {
917
+ *dst_u = *src_u;
918
+ ++dst_u;
919
+ src_u += src_pixel_stride_uv;
920
+ }
921
+ }
922
+
923
+ // Convert Android420 to I420 with Rotate
924
+ LIBYUV_API
925
+ int Android420ToI420Rotate(const uint8_t* src_y,
926
+ int src_stride_y,
927
+ const uint8_t* src_u,
928
+ int src_stride_u,
929
+ const uint8_t* src_v,
930
+ int src_stride_v,
931
+ int src_pixel_stride_uv,
932
+ uint8_t* dst_y,
933
+ int dst_stride_y,
934
+ uint8_t* dst_u,
935
+ int dst_stride_u,
936
+ uint8_t* dst_v,
937
+ int dst_stride_v,
938
+ int width,
939
+ int height,
940
+ enum RotationMode rotation) {
941
+ int y;
942
+ const ptrdiff_t vu_off = src_v - src_u;
943
+ int halfwidth = (width + 1) >> 1;
944
+ int halfheight = (height + 1) >> 1;
945
+ if ((!src_y && dst_y) || !src_u || !src_v || !dst_u || !dst_v || width <= 0 ||
946
+ height == 0) {
947
+ return -1;
948
+ }
949
+ // Negative height means invert the image.
950
+ if (height < 0) {
951
+ height = -height;
952
+ halfheight = (height + 1) >> 1;
953
+ src_y = src_y + (height - 1) * src_stride_y;
954
+ src_u = src_u + (halfheight - 1) * src_stride_u;
955
+ src_v = src_v + (halfheight - 1) * src_stride_v;
956
+ src_stride_y = -src_stride_y;
957
+ src_stride_u = -src_stride_u;
958
+ src_stride_v = -src_stride_v;
959
+ }
960
+
961
+ if (dst_y) {
962
+ RotatePlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height,
963
+ rotation);
964
+ }
965
+
966
+ // Copy UV planes - I420
967
+ if (src_pixel_stride_uv == 1) {
968
+ RotatePlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight,
969
+ rotation);
970
+ RotatePlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight,
971
+ rotation);
972
+ return 0;
973
+ }
974
+ // Split UV planes - NV21
975
+ if (src_pixel_stride_uv == 2 && vu_off == -1 &&
976
+ src_stride_u == src_stride_v) {
977
+ SplitRotateUV(src_v, src_stride_v, dst_v, dst_stride_v, dst_u, dst_stride_u,
978
+ halfwidth, halfheight, rotation);
979
+ return 0;
980
+ }
981
+ // Split UV planes - NV12
982
+ if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
983
+ SplitRotateUV(src_u, src_stride_u, dst_u, dst_stride_u, dst_v, dst_stride_v,
984
+ halfwidth, halfheight, rotation);
985
+ return 0;
986
+ }
987
+
988
+ if (rotation == 0) {
989
+ for (y = 0; y < halfheight; ++y) {
990
+ SplitPixels(src_u, src_pixel_stride_uv, dst_u, halfwidth);
991
+ SplitPixels(src_v, src_pixel_stride_uv, dst_v, halfwidth);
992
+ src_u += src_stride_u;
993
+ src_v += src_stride_v;
994
+ dst_u += dst_stride_u;
995
+ dst_v += dst_stride_v;
996
+ }
997
+ return 0;
998
+ }
999
+ // unsupported type and/or rotation.
1000
+ return -1;
1001
+ }
1002
+
1003
+ LIBYUV_API
1004
+ int I010Rotate(const uint16_t* src_y,
1005
+ int src_stride_y,
1006
+ const uint16_t* src_u,
1007
+ int src_stride_u,
1008
+ const uint16_t* src_v,
1009
+ int src_stride_v,
1010
+ uint16_t* dst_y,
1011
+ int dst_stride_y,
1012
+ uint16_t* dst_u,
1013
+ int dst_stride_u,
1014
+ uint16_t* dst_v,
1015
+ int dst_stride_v,
1016
+ int width,
1017
+ int height,
1018
+ enum RotationMode mode) {
1019
+ int halfwidth = (width + 1) >> 1;
1020
+ int halfheight = (height + 1) >> 1;
1021
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1022
+ !dst_u || !dst_v || dst_stride_y < 0) {
1023
+ return -1;
1024
+ }
1025
+ // Negative height means invert the image.
1026
+ if (height < 0) {
1027
+ height = -height;
1028
+ src_y = src_y + (height - 1) * src_stride_y;
1029
+ src_u = src_u + (height - 1) * src_stride_u;
1030
+ src_v = src_v + (height - 1) * src_stride_v;
1031
+ src_stride_y = -src_stride_y;
1032
+ src_stride_u = -src_stride_u;
1033
+ src_stride_v = -src_stride_v;
1034
+ }
1035
+
1036
+ switch (mode) {
1037
+ case kRotate0:
1038
+ // copy frame
1039
+ return I010Copy(src_y, src_stride_y, src_u, src_stride_u, src_v,
1040
+ src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
1041
+ dst_v, dst_stride_v, width, height);
1042
+ case kRotate90:
1043
+ RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1044
+ RotatePlane90_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1045
+ halfheight);
1046
+ RotatePlane90_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1047
+ halfheight);
1048
+ return 0;
1049
+ case kRotate270:
1050
+ RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1051
+ height);
1052
+ RotatePlane270_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1053
+ halfheight);
1054
+ RotatePlane270_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1055
+ halfheight);
1056
+ return 0;
1057
+ case kRotate180:
1058
+ RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1059
+ height);
1060
+ RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1061
+ halfheight);
1062
+ RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1063
+ halfheight);
1064
+ return 0;
1065
+ default:
1066
+ break;
1067
+ }
1068
+ return -1;
1069
+ }
1070
+
1071
+ // I210 has half width x full height UV planes, so rotate by 90 and 270
1072
+ // require scaling to maintain 422 subsampling.
1073
+ LIBYUV_API
1074
+ int I210Rotate(const uint16_t* src_y,
1075
+ int src_stride_y,
1076
+ const uint16_t* src_u,
1077
+ int src_stride_u,
1078
+ const uint16_t* src_v,
1079
+ int src_stride_v,
1080
+ uint16_t* dst_y,
1081
+ int dst_stride_y,
1082
+ uint16_t* dst_u,
1083
+ int dst_stride_u,
1084
+ uint16_t* dst_v,
1085
+ int dst_stride_v,
1086
+ int width,
1087
+ int height,
1088
+ enum RotationMode mode) {
1089
+ int halfwidth = (width + 1) >> 1;
1090
+ int halfheight = (height + 1) >> 1;
1091
+ int r;
1092
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1093
+ !dst_u || !dst_v) {
1094
+ return -1;
1095
+ }
1096
+ // Negative height means invert the image.
1097
+ if (height < 0) {
1098
+ height = -height;
1099
+ src_y = src_y + (height - 1) * src_stride_y;
1100
+ src_u = src_u + (height - 1) * src_stride_u;
1101
+ src_v = src_v + (height - 1) * src_stride_v;
1102
+ src_stride_y = -src_stride_y;
1103
+ src_stride_u = -src_stride_u;
1104
+ src_stride_v = -src_stride_v;
1105
+ }
1106
+
1107
+ switch (mode) {
1108
+ case kRotate0:
1109
+ // Copy frame
1110
+ CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1111
+ CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
1112
+ CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
1113
+ return 0;
1114
+
1115
+ // Note on temporary Y plane for UV.
1116
+ // Rotation of UV first fits within the Y destination plane rows.
1117
+ // Y plane is width x height
1118
+ // Y plane rotated is height x width
1119
+ // UV plane is (width / 2) x height
1120
+ // UV plane rotated is height x (width / 2)
1121
+ // UV plane rotated+scaled is (height / 2) x width.
1122
+ // UV plane rotated is a temporary that fits within the Y plane rotated.
1123
+
1124
+ case kRotate90:
1125
+ RotatePlane90_16(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
1126
+ height);
1127
+ r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_u,
1128
+ dst_stride_u, halfheight, width, kFilterBilinear);
1129
+ if (r != 0) {
1130
+ return r;
1131
+ }
1132
+ RotatePlane90_16(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
1133
+ height);
1134
+ r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_v,
1135
+ dst_stride_v, halfheight, width, kFilterLinear);
1136
+ if (r != 0) {
1137
+ return r;
1138
+ }
1139
+ RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1140
+ return 0;
1141
+ case kRotate270:
1142
+ RotatePlane270_16(src_u, src_stride_u, dst_y, dst_stride_y, halfwidth,
1143
+ height);
1144
+ r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_u,
1145
+ dst_stride_u, halfheight, width, kFilterBilinear);
1146
+ if (r != 0) {
1147
+ return r;
1148
+ }
1149
+ RotatePlane270_16(src_v, src_stride_v, dst_y, dst_stride_y, halfwidth,
1150
+ height);
1151
+ r = ScalePlane_16(dst_y, dst_stride_y, height, halfwidth, dst_v,
1152
+ dst_stride_v, halfheight, width, kFilterLinear);
1153
+ if (r != 0) {
1154
+ return r;
1155
+ }
1156
+ RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1157
+ height);
1158
+ return 0;
1159
+ case kRotate180:
1160
+ RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1161
+ height);
1162
+ RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
1163
+ height);
1164
+ RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
1165
+ height);
1166
+ return 0;
1167
+ default:
1168
+ break;
1169
+ }
1170
+ return -1;
1171
+ }
1172
+
1173
+ LIBYUV_API
1174
+ int I410Rotate(const uint16_t* src_y,
1175
+ int src_stride_y,
1176
+ const uint16_t* src_u,
1177
+ int src_stride_u,
1178
+ const uint16_t* src_v,
1179
+ int src_stride_v,
1180
+ uint16_t* dst_y,
1181
+ int dst_stride_y,
1182
+ uint16_t* dst_u,
1183
+ int dst_stride_u,
1184
+ uint16_t* dst_v,
1185
+ int dst_stride_v,
1186
+ int width,
1187
+ int height,
1188
+ enum RotationMode mode) {
1189
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
1190
+ !dst_u || !dst_v || dst_stride_y < 0) {
1191
+ return -1;
1192
+ }
1193
+ // Negative height means invert the image.
1194
+ if (height < 0) {
1195
+ height = -height;
1196
+ src_y = src_y + (height - 1) * src_stride_y;
1197
+ src_u = src_u + (height - 1) * src_stride_u;
1198
+ src_v = src_v + (height - 1) * src_stride_v;
1199
+ src_stride_y = -src_stride_y;
1200
+ src_stride_u = -src_stride_u;
1201
+ src_stride_v = -src_stride_v;
1202
+ }
1203
+
1204
+ switch (mode) {
1205
+ case kRotate0:
1206
+ // copy frame
1207
+ CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1208
+ CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
1209
+ CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
1210
+ return 0;
1211
+ case kRotate90:
1212
+ RotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1213
+ RotatePlane90_16(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
1214
+ RotatePlane90_16(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
1215
+ return 0;
1216
+ case kRotate270:
1217
+ RotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1218
+ height);
1219
+ RotatePlane270_16(src_u, src_stride_u, dst_u, dst_stride_u, width,
1220
+ height);
1221
+ RotatePlane270_16(src_v, src_stride_v, dst_v, dst_stride_v, width,
1222
+ height);
1223
+ return 0;
1224
+ case kRotate180:
1225
+ RotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
1226
+ height);
1227
+ RotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u, width,
1228
+ height);
1229
+ RotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v, width,
1230
+ height);
1231
+ return 0;
1232
+ default:
1233
+ break;
1234
+ }
1235
+ return -1;
1236
+ }
1237
+
1238
+ #ifdef __cplusplus
1239
+ } // extern "C"
1240
+ } // namespace libyuv
1241
+ #endif