convert_from_argb.cc 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617
  1. /*
  2. * Copyright 2012 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. #include "libyuv/convert_from_argb.h"
  11. #include "libyuv/basic_types.h"
  12. #include "libyuv/cpu_id.h"
  13. #include "libyuv/planar_functions.h"
  14. #include "libyuv/row.h"
  15. #ifdef __cplusplus
  16. namespace libyuv {
  17. extern "C" {
  18. #endif
  19. // ARGB little endian (bgra in memory) to I444
  20. LIBYUV_API
  21. int ARGBToI444(const uint8_t* src_argb,
  22. int src_stride_argb,
  23. uint8_t* dst_y,
  24. int dst_stride_y,
  25. uint8_t* dst_u,
  26. int dst_stride_u,
  27. uint8_t* dst_v,
  28. int dst_stride_v,
  29. int width,
  30. int height) {
  31. int y;
  32. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  33. ARGBToYRow_C;
  34. void (*ARGBToUV444Row)(const uint8_t* src_argb, uint8_t* dst_u,
  35. uint8_t* dst_v, int width) = ARGBToUV444Row_C;
  36. if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
  37. return -1;
  38. }
  39. if (height < 0) {
  40. height = -height;
  41. src_argb = src_argb + (height - 1) * src_stride_argb;
  42. src_stride_argb = -src_stride_argb;
  43. }
  44. // Coalesce rows.
  45. if (src_stride_argb == width * 4 && dst_stride_y == width &&
  46. dst_stride_u == width && dst_stride_v == width) {
  47. width *= height;
  48. height = 1;
  49. src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
  50. }
  51. #if defined(HAS_ARGBTOUV444ROW_SSSE3)
  52. if (TestCpuFlag(kCpuHasSSSE3)) {
  53. ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
  54. if (IS_ALIGNED(width, 16)) {
  55. ARGBToUV444Row = ARGBToUV444Row_SSSE3;
  56. }
  57. }
  58. #endif
  59. #if defined(HAS_ARGBTOUV444ROW_NEON)
  60. if (TestCpuFlag(kCpuHasNEON)) {
  61. ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
  62. if (IS_ALIGNED(width, 8)) {
  63. ARGBToUV444Row = ARGBToUV444Row_NEON;
  64. }
  65. }
  66. #endif
  67. #if defined(HAS_ARGBTOUV444ROW_MSA)
  68. if (TestCpuFlag(kCpuHasMSA)) {
  69. ARGBToUV444Row = ARGBToUV444Row_Any_MSA;
  70. if (IS_ALIGNED(width, 16)) {
  71. ARGBToUV444Row = ARGBToUV444Row_MSA;
  72. }
  73. }
  74. #endif
  75. #if defined(HAS_ARGBTOYROW_SSSE3)
  76. if (TestCpuFlag(kCpuHasSSSE3)) {
  77. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  78. if (IS_ALIGNED(width, 16)) {
  79. ARGBToYRow = ARGBToYRow_SSSE3;
  80. }
  81. }
  82. #endif
  83. #if defined(HAS_ARGBTOYROW_AVX2)
  84. if (TestCpuFlag(kCpuHasAVX2)) {
  85. ARGBToYRow = ARGBToYRow_Any_AVX2;
  86. if (IS_ALIGNED(width, 32)) {
  87. ARGBToYRow = ARGBToYRow_AVX2;
  88. }
  89. }
  90. #endif
  91. #if defined(HAS_ARGBTOYROW_NEON)
  92. if (TestCpuFlag(kCpuHasNEON)) {
  93. ARGBToYRow = ARGBToYRow_Any_NEON;
  94. if (IS_ALIGNED(width, 8)) {
  95. ARGBToYRow = ARGBToYRow_NEON;
  96. }
  97. }
  98. #endif
  99. #if defined(HAS_ARGBTOYROW_MSA)
  100. if (TestCpuFlag(kCpuHasMSA)) {
  101. ARGBToYRow = ARGBToYRow_Any_MSA;
  102. if (IS_ALIGNED(width, 16)) {
  103. ARGBToYRow = ARGBToYRow_MSA;
  104. }
  105. }
  106. #endif
  107. for (y = 0; y < height; ++y) {
  108. ARGBToUV444Row(src_argb, dst_u, dst_v, width);
  109. ARGBToYRow(src_argb, dst_y, width);
  110. src_argb += src_stride_argb;
  111. dst_y += dst_stride_y;
  112. dst_u += dst_stride_u;
  113. dst_v += dst_stride_v;
  114. }
  115. return 0;
  116. }
  117. // ARGB little endian (bgra in memory) to I422
  118. LIBYUV_API
  119. int ARGBToI422(const uint8_t* src_argb,
  120. int src_stride_argb,
  121. uint8_t* dst_y,
  122. int dst_stride_y,
  123. uint8_t* dst_u,
  124. int dst_stride_u,
  125. uint8_t* dst_v,
  126. int dst_stride_v,
  127. int width,
  128. int height) {
  129. int y;
  130. void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
  131. uint8_t* dst_u, uint8_t* dst_v, int width) =
  132. ARGBToUVRow_C;
  133. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  134. ARGBToYRow_C;
  135. if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
  136. return -1;
  137. }
  138. // Negative height means invert the image.
  139. if (height < 0) {
  140. height = -height;
  141. src_argb = src_argb + (height - 1) * src_stride_argb;
  142. src_stride_argb = -src_stride_argb;
  143. }
  144. // Coalesce rows.
  145. if (src_stride_argb == width * 4 && dst_stride_y == width &&
  146. dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
  147. width *= height;
  148. height = 1;
  149. src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
  150. }
  151. #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
  152. if (TestCpuFlag(kCpuHasSSSE3)) {
  153. ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
  154. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  155. if (IS_ALIGNED(width, 16)) {
  156. ARGBToUVRow = ARGBToUVRow_SSSE3;
  157. ARGBToYRow = ARGBToYRow_SSSE3;
  158. }
  159. }
  160. #endif
  161. #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
  162. if (TestCpuFlag(kCpuHasAVX2)) {
  163. ARGBToUVRow = ARGBToUVRow_Any_AVX2;
  164. ARGBToYRow = ARGBToYRow_Any_AVX2;
  165. if (IS_ALIGNED(width, 32)) {
  166. ARGBToUVRow = ARGBToUVRow_AVX2;
  167. ARGBToYRow = ARGBToYRow_AVX2;
  168. }
  169. }
  170. #endif
  171. #if defined(HAS_ARGBTOYROW_NEON)
  172. if (TestCpuFlag(kCpuHasNEON)) {
  173. ARGBToYRow = ARGBToYRow_Any_NEON;
  174. if (IS_ALIGNED(width, 8)) {
  175. ARGBToYRow = ARGBToYRow_NEON;
  176. }
  177. }
  178. #endif
  179. #if defined(HAS_ARGBTOUVROW_NEON)
  180. if (TestCpuFlag(kCpuHasNEON)) {
  181. ARGBToUVRow = ARGBToUVRow_Any_NEON;
  182. if (IS_ALIGNED(width, 16)) {
  183. ARGBToUVRow = ARGBToUVRow_NEON;
  184. }
  185. }
  186. #endif
  187. #if defined(HAS_ARGBTOYROW_MSA)
  188. if (TestCpuFlag(kCpuHasMSA)) {
  189. ARGBToYRow = ARGBToYRow_Any_MSA;
  190. if (IS_ALIGNED(width, 16)) {
  191. ARGBToYRow = ARGBToYRow_MSA;
  192. }
  193. }
  194. #endif
  195. #if defined(HAS_ARGBTOUVROW_MSA)
  196. if (TestCpuFlag(kCpuHasMSA)) {
  197. ARGBToUVRow = ARGBToUVRow_Any_MSA;
  198. if (IS_ALIGNED(width, 32)) {
  199. ARGBToUVRow = ARGBToUVRow_MSA;
  200. }
  201. }
  202. #endif
  203. for (y = 0; y < height; ++y) {
  204. ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
  205. ARGBToYRow(src_argb, dst_y, width);
  206. src_argb += src_stride_argb;
  207. dst_y += dst_stride_y;
  208. dst_u += dst_stride_u;
  209. dst_v += dst_stride_v;
  210. }
  211. return 0;
  212. }
  213. LIBYUV_API
  214. int ARGBToNV12(const uint8_t* src_argb,
  215. int src_stride_argb,
  216. uint8_t* dst_y,
  217. int dst_stride_y,
  218. uint8_t* dst_uv,
  219. int dst_stride_uv,
  220. int width,
  221. int height) {
  222. int y;
  223. int halfwidth = (width + 1) >> 1;
  224. void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
  225. uint8_t* dst_u, uint8_t* dst_v, int width) =
  226. ARGBToUVRow_C;
  227. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  228. ARGBToYRow_C;
  229. void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
  230. uint8_t* dst_uv, int width) = MergeUVRow_C;
  231. if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
  232. return -1;
  233. }
  234. // Negative height means invert the image.
  235. if (height < 0) {
  236. height = -height;
  237. src_argb = src_argb + (height - 1) * src_stride_argb;
  238. src_stride_argb = -src_stride_argb;
  239. }
  240. #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
  241. if (TestCpuFlag(kCpuHasSSSE3)) {
  242. ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
  243. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  244. if (IS_ALIGNED(width, 16)) {
  245. ARGBToUVRow = ARGBToUVRow_SSSE3;
  246. ARGBToYRow = ARGBToYRow_SSSE3;
  247. }
  248. }
  249. #endif
  250. #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
  251. if (TestCpuFlag(kCpuHasAVX2)) {
  252. ARGBToUVRow = ARGBToUVRow_Any_AVX2;
  253. ARGBToYRow = ARGBToYRow_Any_AVX2;
  254. if (IS_ALIGNED(width, 32)) {
  255. ARGBToUVRow = ARGBToUVRow_AVX2;
  256. ARGBToYRow = ARGBToYRow_AVX2;
  257. }
  258. }
  259. #endif
  260. #if defined(HAS_ARGBTOYROW_NEON)
  261. if (TestCpuFlag(kCpuHasNEON)) {
  262. ARGBToYRow = ARGBToYRow_Any_NEON;
  263. if (IS_ALIGNED(width, 8)) {
  264. ARGBToYRow = ARGBToYRow_NEON;
  265. }
  266. }
  267. #endif
  268. #if defined(HAS_ARGBTOUVROW_NEON)
  269. if (TestCpuFlag(kCpuHasNEON)) {
  270. ARGBToUVRow = ARGBToUVRow_Any_NEON;
  271. if (IS_ALIGNED(width, 16)) {
  272. ARGBToUVRow = ARGBToUVRow_NEON;
  273. }
  274. }
  275. #endif
  276. #if defined(HAS_ARGBTOYROW_MSA)
  277. if (TestCpuFlag(kCpuHasMSA)) {
  278. ARGBToYRow = ARGBToYRow_Any_MSA;
  279. if (IS_ALIGNED(width, 16)) {
  280. ARGBToYRow = ARGBToYRow_MSA;
  281. }
  282. }
  283. #endif
  284. #if defined(HAS_ARGBTOUVROW_MSA)
  285. if (TestCpuFlag(kCpuHasMSA)) {
  286. ARGBToUVRow = ARGBToUVRow_Any_MSA;
  287. if (IS_ALIGNED(width, 32)) {
  288. ARGBToUVRow = ARGBToUVRow_MSA;
  289. }
  290. }
  291. #endif
  292. #if defined(HAS_MERGEUVROW_SSE2)
  293. if (TestCpuFlag(kCpuHasSSE2)) {
  294. MergeUVRow_ = MergeUVRow_Any_SSE2;
  295. if (IS_ALIGNED(halfwidth, 16)) {
  296. MergeUVRow_ = MergeUVRow_SSE2;
  297. }
  298. }
  299. #endif
  300. #if defined(HAS_MERGEUVROW_AVX2)
  301. if (TestCpuFlag(kCpuHasAVX2)) {
  302. MergeUVRow_ = MergeUVRow_Any_AVX2;
  303. if (IS_ALIGNED(halfwidth, 32)) {
  304. MergeUVRow_ = MergeUVRow_AVX2;
  305. }
  306. }
  307. #endif
  308. #if defined(HAS_MERGEUVROW_NEON)
  309. if (TestCpuFlag(kCpuHasNEON)) {
  310. MergeUVRow_ = MergeUVRow_Any_NEON;
  311. if (IS_ALIGNED(halfwidth, 16)) {
  312. MergeUVRow_ = MergeUVRow_NEON;
  313. }
  314. }
  315. #endif
  316. #if defined(HAS_MERGEUVROW_MSA)
  317. if (TestCpuFlag(kCpuHasMSA)) {
  318. MergeUVRow_ = MergeUVRow_Any_MSA;
  319. if (IS_ALIGNED(halfwidth, 16)) {
  320. MergeUVRow_ = MergeUVRow_MSA;
  321. }
  322. }
  323. #endif
  324. {
  325. // Allocate a rows of uv.
  326. align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
  327. uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
  328. for (y = 0; y < height - 1; y += 2) {
  329. ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
  330. MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
  331. ARGBToYRow(src_argb, dst_y, width);
  332. ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
  333. src_argb += src_stride_argb * 2;
  334. dst_y += dst_stride_y * 2;
  335. dst_uv += dst_stride_uv;
  336. }
  337. if (height & 1) {
  338. ARGBToUVRow(src_argb, 0, row_u, row_v, width);
  339. MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
  340. ARGBToYRow(src_argb, dst_y, width);
  341. }
  342. free_aligned_buffer_64(row_u);
  343. }
  344. return 0;
  345. }
  346. // Same as NV12 but U and V swapped.
  347. LIBYUV_API
  348. int ARGBToNV21(const uint8_t* src_argb,
  349. int src_stride_argb,
  350. uint8_t* dst_y,
  351. int dst_stride_y,
  352. uint8_t* dst_vu,
  353. int dst_stride_vu,
  354. int width,
  355. int height) {
  356. int y;
  357. int halfwidth = (width + 1) >> 1;
  358. void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
  359. uint8_t* dst_u, uint8_t* dst_v, int width) =
  360. ARGBToUVRow_C;
  361. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  362. ARGBToYRow_C;
  363. void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
  364. uint8_t* dst_vu, int width) = MergeUVRow_C;
  365. if (!src_argb || !dst_y || !dst_vu || width <= 0 || height == 0) {
  366. return -1;
  367. }
  368. // Negative height means invert the image.
  369. if (height < 0) {
  370. height = -height;
  371. src_argb = src_argb + (height - 1) * src_stride_argb;
  372. src_stride_argb = -src_stride_argb;
  373. }
  374. #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
  375. if (TestCpuFlag(kCpuHasSSSE3)) {
  376. ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
  377. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  378. if (IS_ALIGNED(width, 16)) {
  379. ARGBToUVRow = ARGBToUVRow_SSSE3;
  380. ARGBToYRow = ARGBToYRow_SSSE3;
  381. }
  382. }
  383. #endif
  384. #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
  385. if (TestCpuFlag(kCpuHasAVX2)) {
  386. ARGBToUVRow = ARGBToUVRow_Any_AVX2;
  387. ARGBToYRow = ARGBToYRow_Any_AVX2;
  388. if (IS_ALIGNED(width, 32)) {
  389. ARGBToUVRow = ARGBToUVRow_AVX2;
  390. ARGBToYRow = ARGBToYRow_AVX2;
  391. }
  392. }
  393. #endif
  394. #if defined(HAS_ARGBTOYROW_NEON)
  395. if (TestCpuFlag(kCpuHasNEON)) {
  396. ARGBToYRow = ARGBToYRow_Any_NEON;
  397. if (IS_ALIGNED(width, 8)) {
  398. ARGBToYRow = ARGBToYRow_NEON;
  399. }
  400. }
  401. #endif
  402. #if defined(HAS_ARGBTOUVROW_NEON)
  403. if (TestCpuFlag(kCpuHasNEON)) {
  404. ARGBToUVRow = ARGBToUVRow_Any_NEON;
  405. if (IS_ALIGNED(width, 16)) {
  406. ARGBToUVRow = ARGBToUVRow_NEON;
  407. }
  408. }
  409. #endif
  410. #if defined(HAS_ARGBTOYROW_MSA)
  411. if (TestCpuFlag(kCpuHasMSA)) {
  412. ARGBToYRow = ARGBToYRow_Any_MSA;
  413. if (IS_ALIGNED(width, 16)) {
  414. ARGBToYRow = ARGBToYRow_MSA;
  415. }
  416. }
  417. #endif
  418. #if defined(HAS_ARGBTOUVROW_MSA)
  419. if (TestCpuFlag(kCpuHasMSA)) {
  420. ARGBToUVRow = ARGBToUVRow_Any_MSA;
  421. if (IS_ALIGNED(width, 32)) {
  422. ARGBToUVRow = ARGBToUVRow_MSA;
  423. }
  424. }
  425. #endif
  426. #if defined(HAS_MERGEUVROW_SSE2)
  427. if (TestCpuFlag(kCpuHasSSE2)) {
  428. MergeUVRow_ = MergeUVRow_Any_SSE2;
  429. if (IS_ALIGNED(halfwidth, 16)) {
  430. MergeUVRow_ = MergeUVRow_SSE2;
  431. }
  432. }
  433. #endif
  434. #if defined(HAS_MERGEUVROW_AVX2)
  435. if (TestCpuFlag(kCpuHasAVX2)) {
  436. MergeUVRow_ = MergeUVRow_Any_AVX2;
  437. if (IS_ALIGNED(halfwidth, 32)) {
  438. MergeUVRow_ = MergeUVRow_AVX2;
  439. }
  440. }
  441. #endif
  442. #if defined(HAS_MERGEUVROW_NEON)
  443. if (TestCpuFlag(kCpuHasNEON)) {
  444. MergeUVRow_ = MergeUVRow_Any_NEON;
  445. if (IS_ALIGNED(halfwidth, 16)) {
  446. MergeUVRow_ = MergeUVRow_NEON;
  447. }
  448. }
  449. #endif
  450. #if defined(HAS_MERGEUVROW_MSA)
  451. if (TestCpuFlag(kCpuHasMSA)) {
  452. MergeUVRow_ = MergeUVRow_Any_MSA;
  453. if (IS_ALIGNED(halfwidth, 16)) {
  454. MergeUVRow_ = MergeUVRow_MSA;
  455. }
  456. }
  457. #endif
  458. {
  459. // Allocate a rows of uv.
  460. align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
  461. uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
  462. for (y = 0; y < height - 1; y += 2) {
  463. ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
  464. MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
  465. ARGBToYRow(src_argb, dst_y, width);
  466. ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
  467. src_argb += src_stride_argb * 2;
  468. dst_y += dst_stride_y * 2;
  469. dst_vu += dst_stride_vu;
  470. }
  471. if (height & 1) {
  472. ARGBToUVRow(src_argb, 0, row_u, row_v, width);
  473. MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
  474. ARGBToYRow(src_argb, dst_y, width);
  475. }
  476. free_aligned_buffer_64(row_u);
  477. }
  478. return 0;
  479. }
  480. // Convert ARGB to YUY2.
  481. LIBYUV_API
  482. int ARGBToYUY2(const uint8_t* src_argb,
  483. int src_stride_argb,
  484. uint8_t* dst_yuy2,
  485. int dst_stride_yuy2,
  486. int width,
  487. int height) {
  488. int y;
  489. void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
  490. uint8_t* dst_u, uint8_t* dst_v, int width) =
  491. ARGBToUVRow_C;
  492. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  493. ARGBToYRow_C;
  494. void (*I422ToYUY2Row)(const uint8_t* src_y, const uint8_t* src_u,
  495. const uint8_t* src_v, uint8_t* dst_yuy2, int width) =
  496. I422ToYUY2Row_C;
  497. if (!src_argb || !dst_yuy2 || width <= 0 || height == 0) {
  498. return -1;
  499. }
  500. // Negative height means invert the image.
  501. if (height < 0) {
  502. height = -height;
  503. dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
  504. dst_stride_yuy2 = -dst_stride_yuy2;
  505. }
  506. // Coalesce rows.
  507. if (src_stride_argb == width * 4 && dst_stride_yuy2 == width * 2) {
  508. width *= height;
  509. height = 1;
  510. src_stride_argb = dst_stride_yuy2 = 0;
  511. }
  512. #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
  513. if (TestCpuFlag(kCpuHasSSSE3)) {
  514. ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
  515. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  516. if (IS_ALIGNED(width, 16)) {
  517. ARGBToUVRow = ARGBToUVRow_SSSE3;
  518. ARGBToYRow = ARGBToYRow_SSSE3;
  519. }
  520. }
  521. #endif
  522. #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
  523. if (TestCpuFlag(kCpuHasAVX2)) {
  524. ARGBToUVRow = ARGBToUVRow_Any_AVX2;
  525. ARGBToYRow = ARGBToYRow_Any_AVX2;
  526. if (IS_ALIGNED(width, 32)) {
  527. ARGBToUVRow = ARGBToUVRow_AVX2;
  528. ARGBToYRow = ARGBToYRow_AVX2;
  529. }
  530. }
  531. #endif
  532. #if defined(HAS_ARGBTOYROW_NEON)
  533. if (TestCpuFlag(kCpuHasNEON)) {
  534. ARGBToYRow = ARGBToYRow_Any_NEON;
  535. if (IS_ALIGNED(width, 8)) {
  536. ARGBToYRow = ARGBToYRow_NEON;
  537. }
  538. }
  539. #endif
  540. #if defined(HAS_ARGBTOUVROW_NEON)
  541. if (TestCpuFlag(kCpuHasNEON)) {
  542. ARGBToUVRow = ARGBToUVRow_Any_NEON;
  543. if (IS_ALIGNED(width, 16)) {
  544. ARGBToUVRow = ARGBToUVRow_NEON;
  545. }
  546. }
  547. #endif
  548. #if defined(HAS_ARGBTOYROW_MSA)
  549. if (TestCpuFlag(kCpuHasMSA)) {
  550. ARGBToYRow = ARGBToYRow_Any_MSA;
  551. if (IS_ALIGNED(width, 16)) {
  552. ARGBToYRow = ARGBToYRow_MSA;
  553. }
  554. }
  555. #endif
  556. #if defined(HAS_ARGBTOUVROW_MSA)
  557. if (TestCpuFlag(kCpuHasMSA)) {
  558. ARGBToUVRow = ARGBToUVRow_Any_MSA;
  559. if (IS_ALIGNED(width, 32)) {
  560. ARGBToUVRow = ARGBToUVRow_MSA;
  561. }
  562. }
  563. #endif
  564. #if defined(HAS_I422TOYUY2ROW_SSE2)
  565. if (TestCpuFlag(kCpuHasSSE2)) {
  566. I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
  567. if (IS_ALIGNED(width, 16)) {
  568. I422ToYUY2Row = I422ToYUY2Row_SSE2;
  569. }
  570. }
  571. #endif
  572. #if defined(HAS_I422TOYUY2ROW_AVX2)
  573. if (TestCpuFlag(kCpuHasAVX2)) {
  574. I422ToYUY2Row = I422ToYUY2Row_Any_AVX2;
  575. if (IS_ALIGNED(width, 32)) {
  576. I422ToYUY2Row = I422ToYUY2Row_AVX2;
  577. }
  578. }
  579. #endif
  580. #if defined(HAS_I422TOYUY2ROW_NEON)
  581. if (TestCpuFlag(kCpuHasNEON)) {
  582. I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
  583. if (IS_ALIGNED(width, 16)) {
  584. I422ToYUY2Row = I422ToYUY2Row_NEON;
  585. }
  586. }
  587. #endif
  588. #if defined(HAS_I422TOYUY2ROW_MSA)
  589. if (TestCpuFlag(kCpuHasMSA)) {
  590. I422ToYUY2Row = I422ToYUY2Row_Any_MSA;
  591. if (IS_ALIGNED(width, 32)) {
  592. I422ToYUY2Row = I422ToYUY2Row_MSA;
  593. }
  594. }
  595. #endif
  596. {
  597. // Allocate a rows of yuv.
  598. align_buffer_64(row_y, ((width + 63) & ~63) * 2);
  599. uint8_t* row_u = row_y + ((width + 63) & ~63);
  600. uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
  601. for (y = 0; y < height; ++y) {
  602. ARGBToUVRow(src_argb, 0, row_u, row_v, width);
  603. ARGBToYRow(src_argb, row_y, width);
  604. I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
  605. src_argb += src_stride_argb;
  606. dst_yuy2 += dst_stride_yuy2;
  607. }
  608. free_aligned_buffer_64(row_y);
  609. }
  610. return 0;
  611. }
  612. // Convert ARGB to UYVY.
  613. LIBYUV_API
  614. int ARGBToUYVY(const uint8_t* src_argb,
  615. int src_stride_argb,
  616. uint8_t* dst_uyvy,
  617. int dst_stride_uyvy,
  618. int width,
  619. int height) {
  620. int y;
  621. void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
  622. uint8_t* dst_u, uint8_t* dst_v, int width) =
  623. ARGBToUVRow_C;
  624. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  625. ARGBToYRow_C;
  626. void (*I422ToUYVYRow)(const uint8_t* src_y, const uint8_t* src_u,
  627. const uint8_t* src_v, uint8_t* dst_uyvy, int width) =
  628. I422ToUYVYRow_C;
  629. if (!src_argb || !dst_uyvy || width <= 0 || height == 0) {
  630. return -1;
  631. }
  632. // Negative height means invert the image.
  633. if (height < 0) {
  634. height = -height;
  635. dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
  636. dst_stride_uyvy = -dst_stride_uyvy;
  637. }
  638. // Coalesce rows.
  639. if (src_stride_argb == width * 4 && dst_stride_uyvy == width * 2) {
  640. width *= height;
  641. height = 1;
  642. src_stride_argb = dst_stride_uyvy = 0;
  643. }
  644. #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
  645. if (TestCpuFlag(kCpuHasSSSE3)) {
  646. ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
  647. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  648. if (IS_ALIGNED(width, 16)) {
  649. ARGBToUVRow = ARGBToUVRow_SSSE3;
  650. ARGBToYRow = ARGBToYRow_SSSE3;
  651. }
  652. }
  653. #endif
  654. #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
  655. if (TestCpuFlag(kCpuHasAVX2)) {
  656. ARGBToUVRow = ARGBToUVRow_Any_AVX2;
  657. ARGBToYRow = ARGBToYRow_Any_AVX2;
  658. if (IS_ALIGNED(width, 32)) {
  659. ARGBToUVRow = ARGBToUVRow_AVX2;
  660. ARGBToYRow = ARGBToYRow_AVX2;
  661. }
  662. }
  663. #endif
  664. #if defined(HAS_ARGBTOYROW_NEON)
  665. if (TestCpuFlag(kCpuHasNEON)) {
  666. ARGBToYRow = ARGBToYRow_Any_NEON;
  667. if (IS_ALIGNED(width, 8)) {
  668. ARGBToYRow = ARGBToYRow_NEON;
  669. }
  670. }
  671. #endif
  672. #if defined(HAS_ARGBTOUVROW_NEON)
  673. if (TestCpuFlag(kCpuHasNEON)) {
  674. ARGBToUVRow = ARGBToUVRow_Any_NEON;
  675. if (IS_ALIGNED(width, 16)) {
  676. ARGBToUVRow = ARGBToUVRow_NEON;
  677. }
  678. }
  679. #endif
  680. #if defined(HAS_ARGBTOYROW_MSA)
  681. if (TestCpuFlag(kCpuHasMSA)) {
  682. ARGBToYRow = ARGBToYRow_Any_MSA;
  683. if (IS_ALIGNED(width, 16)) {
  684. ARGBToYRow = ARGBToYRow_MSA;
  685. }
  686. }
  687. #endif
  688. #if defined(HAS_ARGBTOUVROW_MSA)
  689. if (TestCpuFlag(kCpuHasMSA)) {
  690. ARGBToUVRow = ARGBToUVRow_Any_MSA;
  691. if (IS_ALIGNED(width, 32)) {
  692. ARGBToUVRow = ARGBToUVRow_MSA;
  693. }
  694. }
  695. #endif
  696. #if defined(HAS_I422TOUYVYROW_SSE2)
  697. if (TestCpuFlag(kCpuHasSSE2)) {
  698. I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
  699. if (IS_ALIGNED(width, 16)) {
  700. I422ToUYVYRow = I422ToUYVYRow_SSE2;
  701. }
  702. }
  703. #endif
  704. #if defined(HAS_I422TOUYVYROW_AVX2)
  705. if (TestCpuFlag(kCpuHasAVX2)) {
  706. I422ToUYVYRow = I422ToUYVYRow_Any_AVX2;
  707. if (IS_ALIGNED(width, 32)) {
  708. I422ToUYVYRow = I422ToUYVYRow_AVX2;
  709. }
  710. }
  711. #endif
  712. #if defined(HAS_I422TOUYVYROW_NEON)
  713. if (TestCpuFlag(kCpuHasNEON)) {
  714. I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
  715. if (IS_ALIGNED(width, 16)) {
  716. I422ToUYVYRow = I422ToUYVYRow_NEON;
  717. }
  718. }
  719. #endif
  720. #if defined(HAS_I422TOUYVYROW_MSA)
  721. if (TestCpuFlag(kCpuHasMSA)) {
  722. I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
  723. if (IS_ALIGNED(width, 32)) {
  724. I422ToUYVYRow = I422ToUYVYRow_MSA;
  725. }
  726. }
  727. #endif
  728. {
  729. // Allocate a rows of yuv.
  730. align_buffer_64(row_y, ((width + 63) & ~63) * 2);
  731. uint8_t* row_u = row_y + ((width + 63) & ~63);
  732. uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
  733. for (y = 0; y < height; ++y) {
  734. ARGBToUVRow(src_argb, 0, row_u, row_v, width);
  735. ARGBToYRow(src_argb, row_y, width);
  736. I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
  737. src_argb += src_stride_argb;
  738. dst_uyvy += dst_stride_uyvy;
  739. }
  740. free_aligned_buffer_64(row_y);
  741. }
  742. return 0;
  743. }
  744. // Convert ARGB to I400.
  745. LIBYUV_API
  746. int ARGBToI400(const uint8_t* src_argb,
  747. int src_stride_argb,
  748. uint8_t* dst_y,
  749. int dst_stride_y,
  750. int width,
  751. int height) {
  752. int y;
  753. void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
  754. ARGBToYRow_C;
  755. if (!src_argb || !dst_y || width <= 0 || height == 0) {
  756. return -1;
  757. }
  758. if (height < 0) {
  759. height = -height;
  760. src_argb = src_argb + (height - 1) * src_stride_argb;
  761. src_stride_argb = -src_stride_argb;
  762. }
  763. // Coalesce rows.
  764. if (src_stride_argb == width * 4 && dst_stride_y == width) {
  765. width *= height;
  766. height = 1;
  767. src_stride_argb = dst_stride_y = 0;
  768. }
  769. #if defined(HAS_ARGBTOYROW_SSSE3)
  770. if (TestCpuFlag(kCpuHasSSSE3)) {
  771. ARGBToYRow = ARGBToYRow_Any_SSSE3;
  772. if (IS_ALIGNED(width, 16)) {
  773. ARGBToYRow = ARGBToYRow_SSSE3;
  774. }
  775. }
  776. #endif
  777. #if defined(HAS_ARGBTOYROW_AVX2)
  778. if (TestCpuFlag(kCpuHasAVX2)) {
  779. ARGBToYRow = ARGBToYRow_Any_AVX2;
  780. if (IS_ALIGNED(width, 32)) {
  781. ARGBToYRow = ARGBToYRow_AVX2;
  782. }
  783. }
  784. #endif
  785. #if defined(HAS_ARGBTOYROW_NEON)
  786. if (TestCpuFlag(kCpuHasNEON)) {
  787. ARGBToYRow = ARGBToYRow_Any_NEON;
  788. if (IS_ALIGNED(width, 8)) {
  789. ARGBToYRow = ARGBToYRow_NEON;
  790. }
  791. }
  792. #endif
  793. #if defined(HAS_ARGBTOYROW_MSA)
  794. if (TestCpuFlag(kCpuHasMSA)) {
  795. ARGBToYRow = ARGBToYRow_Any_MSA;
  796. if (IS_ALIGNED(width, 16)) {
  797. ARGBToYRow = ARGBToYRow_MSA;
  798. }
  799. }
  800. #endif
  801. for (y = 0; y < height; ++y) {
  802. ARGBToYRow(src_argb, dst_y, width);
  803. src_argb += src_stride_argb;
  804. dst_y += dst_stride_y;
  805. }
  806. return 0;
  807. }
  808. // Shuffle table for converting ARGB to RGBA.
  809. static const uvec8 kShuffleMaskARGBToRGBA = {
  810. 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u};
  811. // Convert ARGB to RGBA.
  812. LIBYUV_API
  813. int ARGBToRGBA(const uint8_t* src_argb,
  814. int src_stride_argb,
  815. uint8_t* dst_rgba,
  816. int dst_stride_rgba,
  817. int width,
  818. int height) {
  819. return ARGBShuffle(src_argb, src_stride_argb, dst_rgba, dst_stride_rgba,
  820. (const uint8_t*)(&kShuffleMaskARGBToRGBA), width, height);
  821. }
  822. // Convert ARGB To RGB24.
  823. LIBYUV_API
  824. int ARGBToRGB24(const uint8_t* src_argb,
  825. int src_stride_argb,
  826. uint8_t* dst_rgb24,
  827. int dst_stride_rgb24,
  828. int width,
  829. int height) {
  830. int y;
  831. void (*ARGBToRGB24Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
  832. ARGBToRGB24Row_C;
  833. if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
  834. return -1;
  835. }
  836. if (height < 0) {
  837. height = -height;
  838. src_argb = src_argb + (height - 1) * src_stride_argb;
  839. src_stride_argb = -src_stride_argb;
  840. }
  841. // Coalesce rows.
  842. if (src_stride_argb == width * 4 && dst_stride_rgb24 == width * 3) {
  843. width *= height;
  844. height = 1;
  845. src_stride_argb = dst_stride_rgb24 = 0;
  846. }
  847. #if defined(HAS_ARGBTORGB24ROW_SSSE3)
  848. if (TestCpuFlag(kCpuHasSSSE3)) {
  849. ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
  850. if (IS_ALIGNED(width, 16)) {
  851. ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
  852. }
  853. }
  854. #endif
  855. #if defined(HAS_ARGBTORGB24ROW_AVX2)
  856. if (TestCpuFlag(kCpuHasAVX2)) {
  857. ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX2;
  858. if (IS_ALIGNED(width, 32)) {
  859. ARGBToRGB24Row = ARGBToRGB24Row_AVX2;
  860. }
  861. }
  862. #endif
  863. #if defined(HAS_ARGBTORGB24ROW_AVX512VBMI)
  864. if (TestCpuFlag(kCpuHasAVX512VBMI)) {
  865. ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX512VBMI;
  866. if (IS_ALIGNED(width, 32)) {
  867. ARGBToRGB24Row = ARGBToRGB24Row_AVX512VBMI;
  868. }
  869. }
  870. #endif
  871. #if defined(HAS_ARGBTORGB24ROW_NEON)
  872. if (TestCpuFlag(kCpuHasNEON)) {
  873. ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
  874. if (IS_ALIGNED(width, 8)) {
  875. ARGBToRGB24Row = ARGBToRGB24Row_NEON;
  876. }
  877. }
  878. #endif
  879. #if defined(HAS_ARGBTORGB24ROW_MSA)
  880. if (TestCpuFlag(kCpuHasMSA)) {
  881. ARGBToRGB24Row = ARGBToRGB24Row_Any_MSA;
  882. if (IS_ALIGNED(width, 16)) {
  883. ARGBToRGB24Row = ARGBToRGB24Row_MSA;
  884. }
  885. }
  886. #endif
  887. for (y = 0; y < height; ++y) {
  888. ARGBToRGB24Row(src_argb, dst_rgb24, width);
  889. src_argb += src_stride_argb;
  890. dst_rgb24 += dst_stride_rgb24;
  891. }
  892. return 0;
  893. }
  894. // Convert ARGB To RAW.
  895. LIBYUV_API
  896. int ARGBToRAW(const uint8_t* src_argb,
  897. int src_stride_argb,
  898. uint8_t* dst_raw,
  899. int dst_stride_raw,
  900. int width,
  901. int height) {
  902. int y;
  903. void (*ARGBToRAWRow)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
  904. ARGBToRAWRow_C;
  905. if (!src_argb || !dst_raw || width <= 0 || height == 0) {
  906. return -1;
  907. }
  908. if (height < 0) {
  909. height = -height;
  910. src_argb = src_argb + (height - 1) * src_stride_argb;
  911. src_stride_argb = -src_stride_argb;
  912. }
  913. // Coalesce rows.
  914. if (src_stride_argb == width * 4 && dst_stride_raw == width * 3) {
  915. width *= height;
  916. height = 1;
  917. src_stride_argb = dst_stride_raw = 0;
  918. }
  919. #if defined(HAS_ARGBTORAWROW_SSSE3)
  920. if (TestCpuFlag(kCpuHasSSSE3)) {
  921. ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
  922. if (IS_ALIGNED(width, 16)) {
  923. ARGBToRAWRow = ARGBToRAWRow_SSSE3;
  924. }
  925. }
  926. #endif
  927. #if defined(HAS_ARGBTORAWROW_AVX2)
  928. if (TestCpuFlag(kCpuHasAVX2)) {
  929. ARGBToRAWRow = ARGBToRAWRow_Any_AVX2;
  930. if (IS_ALIGNED(width, 32)) {
  931. ARGBToRAWRow = ARGBToRAWRow_AVX2;
  932. }
  933. }
  934. #endif
  935. #if defined(HAS_ARGBTORAWROW_NEON)
  936. if (TestCpuFlag(kCpuHasNEON)) {
  937. ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
  938. if (IS_ALIGNED(width, 8)) {
  939. ARGBToRAWRow = ARGBToRAWRow_NEON;
  940. }
  941. }
  942. #endif
  943. #if defined(HAS_ARGBTORAWROW_MSA)
  944. if (TestCpuFlag(kCpuHasMSA)) {
  945. ARGBToRAWRow = ARGBToRAWRow_Any_MSA;
  946. if (IS_ALIGNED(width, 16)) {
  947. ARGBToRAWRow = ARGBToRAWRow_MSA;
  948. }
  949. }
  950. #endif
  951. for (y = 0; y < height; ++y) {
  952. ARGBToRAWRow(src_argb, dst_raw, width);
  953. src_argb += src_stride_argb;
  954. dst_raw += dst_stride_raw;
  955. }
  956. return 0;
  957. }
  958. // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
  959. static const uint8_t kDither565_4x4[16] = {
  960. 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
  961. };
  962. // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
  963. LIBYUV_API
  964. int ARGBToRGB565Dither(const uint8_t* src_argb,
  965. int src_stride_argb,
  966. uint8_t* dst_rgb565,
  967. int dst_stride_rgb565,
  968. const uint8_t* dither4x4,
  969. int width,
  970. int height) {
  971. int y;
  972. void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
  973. const uint32_t dither4, int width) =
  974. ARGBToRGB565DitherRow_C;
  975. if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
  976. return -1;
  977. }
  978. if (height < 0) {
  979. height = -height;
  980. src_argb = src_argb + (height - 1) * src_stride_argb;
  981. src_stride_argb = -src_stride_argb;
  982. }
  983. if (!dither4x4) {
  984. dither4x4 = kDither565_4x4;
  985. }
  986. #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
  987. if (TestCpuFlag(kCpuHasSSE2)) {
  988. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
  989. if (IS_ALIGNED(width, 4)) {
  990. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
  991. }
  992. }
  993. #endif
  994. #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
  995. if (TestCpuFlag(kCpuHasAVX2)) {
  996. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
  997. if (IS_ALIGNED(width, 8)) {
  998. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
  999. }
  1000. }
  1001. #endif
  1002. #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
  1003. if (TestCpuFlag(kCpuHasNEON)) {
  1004. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
  1005. if (IS_ALIGNED(width, 8)) {
  1006. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
  1007. }
  1008. }
  1009. #endif
  1010. #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
  1011. if (TestCpuFlag(kCpuHasMSA)) {
  1012. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
  1013. if (IS_ALIGNED(width, 8)) {
  1014. ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
  1015. }
  1016. }
  1017. #endif
  1018. for (y = 0; y < height; ++y) {
  1019. ARGBToRGB565DitherRow(src_argb, dst_rgb565,
  1020. *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
  1021. width);
  1022. src_argb += src_stride_argb;
  1023. dst_rgb565 += dst_stride_rgb565;
  1024. }
  1025. return 0;
  1026. }
  1027. // Convert ARGB To RGB565.
  1028. // TODO(fbarchard): Consider using dither function low level with zeros.
  1029. LIBYUV_API
  1030. int ARGBToRGB565(const uint8_t* src_argb,
  1031. int src_stride_argb,
  1032. uint8_t* dst_rgb565,
  1033. int dst_stride_rgb565,
  1034. int width,
  1035. int height) {
  1036. int y;
  1037. void (*ARGBToRGB565Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
  1038. int width) = ARGBToRGB565Row_C;
  1039. if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
  1040. return -1;
  1041. }
  1042. if (height < 0) {
  1043. height = -height;
  1044. src_argb = src_argb + (height - 1) * src_stride_argb;
  1045. src_stride_argb = -src_stride_argb;
  1046. }
  1047. // Coalesce rows.
  1048. if (src_stride_argb == width * 4 && dst_stride_rgb565 == width * 2) {
  1049. width *= height;
  1050. height = 1;
  1051. src_stride_argb = dst_stride_rgb565 = 0;
  1052. }
  1053. #if defined(HAS_ARGBTORGB565ROW_SSE2)
  1054. if (TestCpuFlag(kCpuHasSSE2)) {
  1055. ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
  1056. if (IS_ALIGNED(width, 4)) {
  1057. ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
  1058. }
  1059. }
  1060. #endif
  1061. #if defined(HAS_ARGBTORGB565ROW_AVX2)
  1062. if (TestCpuFlag(kCpuHasAVX2)) {
  1063. ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2;
  1064. if (IS_ALIGNED(width, 8)) {
  1065. ARGBToRGB565Row = ARGBToRGB565Row_AVX2;
  1066. }
  1067. }
  1068. #endif
  1069. #if defined(HAS_ARGBTORGB565ROW_NEON)
  1070. if (TestCpuFlag(kCpuHasNEON)) {
  1071. ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
  1072. if (IS_ALIGNED(width, 8)) {
  1073. ARGBToRGB565Row = ARGBToRGB565Row_NEON;
  1074. }
  1075. }
  1076. #endif
  1077. #if defined(HAS_ARGBTORGB565ROW_MSA)
  1078. if (TestCpuFlag(kCpuHasMSA)) {
  1079. ARGBToRGB565Row = ARGBToRGB565Row_Any_MSA;
  1080. if (IS_ALIGNED(width, 8)) {
  1081. ARGBToRGB565Row = ARGBToRGB565Row_MSA;
  1082. }
  1083. }
  1084. #endif
  1085. for (y = 0; y < height; ++y) {
  1086. ARGBToRGB565Row(src_argb, dst_rgb565, width);
  1087. src_argb += src_stride_argb;
  1088. dst_rgb565 += dst_stride_rgb565;
  1089. }
  1090. return 0;
  1091. }
  1092. // Convert ARGB To ARGB1555.
  1093. LIBYUV_API
  1094. int ARGBToARGB1555(const uint8_t* src_argb,
  1095. int src_stride_argb,
  1096. uint8_t* dst_argb1555,
  1097. int dst_stride_argb1555,
  1098. int width,
  1099. int height) {
  1100. int y;
  1101. void (*ARGBToARGB1555Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
  1102. int width) = ARGBToARGB1555Row_C;
  1103. if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
  1104. return -1;
  1105. }
  1106. if (height < 0) {
  1107. height = -height;
  1108. src_argb = src_argb + (height - 1) * src_stride_argb;
  1109. src_stride_argb = -src_stride_argb;
  1110. }
  1111. // Coalesce rows.
  1112. if (src_stride_argb == width * 4 && dst_stride_argb1555 == width * 2) {
  1113. width *= height;
  1114. height = 1;
  1115. src_stride_argb = dst_stride_argb1555 = 0;
  1116. }
  1117. #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
  1118. if (TestCpuFlag(kCpuHasSSE2)) {
  1119. ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
  1120. if (IS_ALIGNED(width, 4)) {
  1121. ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
  1122. }
  1123. }
  1124. #endif
  1125. #if defined(HAS_ARGBTOARGB1555ROW_AVX2)
  1126. if (TestCpuFlag(kCpuHasAVX2)) {
  1127. ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2;
  1128. if (IS_ALIGNED(width, 8)) {
  1129. ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2;
  1130. }
  1131. }
  1132. #endif
  1133. #if defined(HAS_ARGBTOARGB1555ROW_NEON)
  1134. if (TestCpuFlag(kCpuHasNEON)) {
  1135. ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
  1136. if (IS_ALIGNED(width, 8)) {
  1137. ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
  1138. }
  1139. }
  1140. #endif
  1141. #if defined(HAS_ARGBTOARGB1555ROW_MSA)
  1142. if (TestCpuFlag(kCpuHasMSA)) {
  1143. ARGBToARGB1555Row = ARGBToARGB1555Row_Any_MSA;
  1144. if (IS_ALIGNED(width, 8)) {
  1145. ARGBToARGB1555Row = ARGBToARGB1555Row_MSA;
  1146. }
  1147. }
  1148. #endif
  1149. for (y = 0; y < height; ++y) {
  1150. ARGBToARGB1555Row(src_argb, dst_argb1555, width);
  1151. src_argb += src_stride_argb;
  1152. dst_argb1555 += dst_stride_argb1555;
  1153. }
  1154. return 0;
  1155. }
  1156. // Convert ARGB To ARGB4444.
  1157. LIBYUV_API
  1158. int ARGBToARGB4444(const uint8_t* src_argb,
  1159. int src_stride_argb,
  1160. uint8_t* dst_argb4444,
  1161. int dst_stride_argb4444,
  1162. int width,
  1163. int height) {
  1164. int y;
  1165. void (*ARGBToARGB4444Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
  1166. int width) = ARGBToARGB4444Row_C;
  1167. if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
  1168. return -1;
  1169. }
  1170. if (height < 0) {
  1171. height = -height;
  1172. src_argb = src_argb + (height - 1) * src_stride_argb;
  1173. src_stride_argb = -src_stride_argb;
  1174. }
  1175. // Coalesce rows.
  1176. if (src_stride_argb == width * 4 && dst_stride_argb4444 == width * 2) {
  1177. width *= height;
  1178. height = 1;
  1179. src_stride_argb = dst_stride_argb4444 = 0;
  1180. }
  1181. #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
  1182. if (TestCpuFlag(kCpuHasSSE2)) {
  1183. ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
  1184. if (IS_ALIGNED(width, 4)) {
  1185. ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
  1186. }
  1187. }
  1188. #endif
  1189. #if defined(HAS_ARGBTOARGB4444ROW_AVX2)
  1190. if (TestCpuFlag(kCpuHasAVX2)) {
  1191. ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2;
  1192. if (IS_ALIGNED(width, 8)) {
  1193. ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2;
  1194. }
  1195. }
  1196. #endif
  1197. #if defined(HAS_ARGBTOARGB4444ROW_NEON)
  1198. if (TestCpuFlag(kCpuHasNEON)) {
  1199. ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
  1200. if (IS_ALIGNED(width, 8)) {
  1201. ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
  1202. }
  1203. }
  1204. #endif
  1205. #if defined(HAS_ARGBTOARGB4444ROW_MSA)
  1206. if (TestCpuFlag(kCpuHasMSA)) {
  1207. ARGBToARGB4444Row = ARGBToARGB4444Row_Any_MSA;
  1208. if (IS_ALIGNED(width, 8)) {
  1209. ARGBToARGB4444Row = ARGBToARGB4444Row_MSA;
  1210. }
  1211. }
  1212. #endif
  1213. for (y = 0; y < height; ++y) {
  1214. ARGBToARGB4444Row(src_argb, dst_argb4444, width);
  1215. src_argb += src_stride_argb;
  1216. dst_argb4444 += dst_stride_argb4444;
  1217. }
  1218. return 0;
  1219. }
  1220. // Convert ABGR To AR30.
  1221. LIBYUV_API
  1222. int ABGRToAR30(const uint8_t* src_abgr,
  1223. int src_stride_abgr,
  1224. uint8_t* dst_ar30,
  1225. int dst_stride_ar30,
  1226. int width,
  1227. int height) {
  1228. int y;
  1229. void (*ABGRToAR30Row)(const uint8_t* src_abgr, uint8_t* dst_rgb, int width) =
  1230. ABGRToAR30Row_C;
  1231. if (!src_abgr || !dst_ar30 || width <= 0 || height == 0) {
  1232. return -1;
  1233. }
  1234. if (height < 0) {
  1235. height = -height;
  1236. src_abgr = src_abgr + (height - 1) * src_stride_abgr;
  1237. src_stride_abgr = -src_stride_abgr;
  1238. }
  1239. // Coalesce rows.
  1240. if (src_stride_abgr == width * 4 && dst_stride_ar30 == width * 4) {
  1241. width *= height;
  1242. height = 1;
  1243. src_stride_abgr = dst_stride_ar30 = 0;
  1244. }
  1245. #if defined(HAS_ABGRTOAR30ROW_SSSE3)
  1246. if (TestCpuFlag(kCpuHasSSSE3)) {
  1247. ABGRToAR30Row = ABGRToAR30Row_Any_SSSE3;
  1248. if (IS_ALIGNED(width, 4)) {
  1249. ABGRToAR30Row = ABGRToAR30Row_SSSE3;
  1250. }
  1251. }
  1252. #endif
  1253. #if defined(HAS_ABGRTOAR30ROW_AVX2)
  1254. if (TestCpuFlag(kCpuHasAVX2)) {
  1255. ABGRToAR30Row = ABGRToAR30Row_Any_AVX2;
  1256. if (IS_ALIGNED(width, 8)) {
  1257. ABGRToAR30Row = ABGRToAR30Row_AVX2;
  1258. }
  1259. }
  1260. #endif
  1261. for (y = 0; y < height; ++y) {
  1262. ABGRToAR30Row(src_abgr, dst_ar30, width);
  1263. src_abgr += src_stride_abgr;
  1264. dst_ar30 += dst_stride_ar30;
  1265. }
  1266. return 0;
  1267. }
  1268. // Convert ARGB To AR30.
  1269. LIBYUV_API
  1270. int ARGBToAR30(const uint8_t* src_argb,
  1271. int src_stride_argb,
  1272. uint8_t* dst_ar30,
  1273. int dst_stride_ar30,
  1274. int width,
  1275. int height) {
  1276. int y;
  1277. void (*ARGBToAR30Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
  1278. ARGBToAR30Row_C;
  1279. if (!src_argb || !dst_ar30 || width <= 0 || height == 0) {
  1280. return -1;
  1281. }
  1282. if (height < 0) {
  1283. height = -height;
  1284. src_argb = src_argb + (height - 1) * src_stride_argb;
  1285. src_stride_argb = -src_stride_argb;
  1286. }
  1287. // Coalesce rows.
  1288. if (src_stride_argb == width * 4 && dst_stride_ar30 == width * 4) {
  1289. width *= height;
  1290. height = 1;
  1291. src_stride_argb = dst_stride_ar30 = 0;
  1292. }
  1293. #if defined(HAS_ARGBTOAR30ROW_SSSE3)
  1294. if (TestCpuFlag(kCpuHasSSSE3)) {
  1295. ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3;
  1296. if (IS_ALIGNED(width, 4)) {
  1297. ARGBToAR30Row = ARGBToAR30Row_SSSE3;
  1298. }
  1299. }
  1300. #endif
  1301. #if defined(HAS_ARGBTOAR30ROW_AVX2)
  1302. if (TestCpuFlag(kCpuHasAVX2)) {
  1303. ARGBToAR30Row = ARGBToAR30Row_Any_AVX2;
  1304. if (IS_ALIGNED(width, 8)) {
  1305. ARGBToAR30Row = ARGBToAR30Row_AVX2;
  1306. }
  1307. }
  1308. #endif
  1309. for (y = 0; y < height; ++y) {
  1310. ARGBToAR30Row(src_argb, dst_ar30, width);
  1311. src_argb += src_stride_argb;
  1312. dst_ar30 += dst_stride_ar30;
  1313. }
  1314. return 0;
  1315. }
  1316. // Convert ARGB to J420. (JPeg full range I420).
  1317. LIBYUV_API
  1318. int ARGBToJ420(const uint8_t* src_argb,
  1319. int src_stride_argb,
  1320. uint8_t* dst_yj,
  1321. int dst_stride_yj,
  1322. uint8_t* dst_u,
  1323. int dst_stride_u,
  1324. uint8_t* dst_v,
  1325. int dst_stride_v,
  1326. int width,
  1327. int height) {
  1328. int y;
  1329. void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
  1330. uint8_t* dst_u, uint8_t* dst_v, int width) =
  1331. ARGBToUVJRow_C;
  1332. void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
  1333. ARGBToYJRow_C;
  1334. if (!src_argb || !dst_yj || !dst_u || !dst_v || width <= 0 || height == 0) {
  1335. return -1;
  1336. }
  1337. // Negative height means invert the image.
  1338. if (height < 0) {
  1339. height = -height;
  1340. src_argb = src_argb + (height - 1) * src_stride_argb;
  1341. src_stride_argb = -src_stride_argb;
  1342. }
  1343. #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
  1344. if (TestCpuFlag(kCpuHasSSSE3)) {
  1345. ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
  1346. ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
  1347. if (IS_ALIGNED(width, 16)) {
  1348. ARGBToUVJRow = ARGBToUVJRow_SSSE3;
  1349. ARGBToYJRow = ARGBToYJRow_SSSE3;
  1350. }
  1351. }
  1352. #endif
  1353. #if defined(HAS_ARGBTOYJROW_AVX2)
  1354. if (TestCpuFlag(kCpuHasAVX2)) {
  1355. ARGBToYJRow = ARGBToYJRow_Any_AVX2;
  1356. if (IS_ALIGNED(width, 32)) {
  1357. ARGBToYJRow = ARGBToYJRow_AVX2;
  1358. }
  1359. }
  1360. #endif
  1361. #if defined(HAS_ARGBTOYJROW_NEON)
  1362. if (TestCpuFlag(kCpuHasNEON)) {
  1363. ARGBToYJRow = ARGBToYJRow_Any_NEON;
  1364. if (IS_ALIGNED(width, 8)) {
  1365. ARGBToYJRow = ARGBToYJRow_NEON;
  1366. }
  1367. }
  1368. #endif
  1369. #if defined(HAS_ARGBTOUVJROW_NEON)
  1370. if (TestCpuFlag(kCpuHasNEON)) {
  1371. ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
  1372. if (IS_ALIGNED(width, 16)) {
  1373. ARGBToUVJRow = ARGBToUVJRow_NEON;
  1374. }
  1375. }
  1376. #endif
  1377. #if defined(HAS_ARGBTOYJROW_MSA)
  1378. if (TestCpuFlag(kCpuHasMSA)) {
  1379. ARGBToYJRow = ARGBToYJRow_Any_MSA;
  1380. if (IS_ALIGNED(width, 16)) {
  1381. ARGBToYJRow = ARGBToYJRow_MSA;
  1382. }
  1383. }
  1384. #endif
  1385. #if defined(HAS_ARGBTOUVJROW_MSA)
  1386. if (TestCpuFlag(kCpuHasMSA)) {
  1387. ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
  1388. if (IS_ALIGNED(width, 32)) {
  1389. ARGBToUVJRow = ARGBToUVJRow_MSA;
  1390. }
  1391. }
  1392. #endif
  1393. for (y = 0; y < height - 1; y += 2) {
  1394. ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width);
  1395. ARGBToYJRow(src_argb, dst_yj, width);
  1396. ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
  1397. src_argb += src_stride_argb * 2;
  1398. dst_yj += dst_stride_yj * 2;
  1399. dst_u += dst_stride_u;
  1400. dst_v += dst_stride_v;
  1401. }
  1402. if (height & 1) {
  1403. ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
  1404. ARGBToYJRow(src_argb, dst_yj, width);
  1405. }
  1406. return 0;
  1407. }
  1408. // Convert ARGB to J422. (JPeg full range I422).
  1409. LIBYUV_API
  1410. int ARGBToJ422(const uint8_t* src_argb,
  1411. int src_stride_argb,
  1412. uint8_t* dst_yj,
  1413. int dst_stride_yj,
  1414. uint8_t* dst_u,
  1415. int dst_stride_u,
  1416. uint8_t* dst_v,
  1417. int dst_stride_v,
  1418. int width,
  1419. int height) {
  1420. int y;
  1421. void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
  1422. uint8_t* dst_u, uint8_t* dst_v, int width) =
  1423. ARGBToUVJRow_C;
  1424. void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
  1425. ARGBToYJRow_C;
  1426. if (!src_argb || !dst_yj || !dst_u || !dst_v || width <= 0 || height == 0) {
  1427. return -1;
  1428. }
  1429. // Negative height means invert the image.
  1430. if (height < 0) {
  1431. height = -height;
  1432. src_argb = src_argb + (height - 1) * src_stride_argb;
  1433. src_stride_argb = -src_stride_argb;
  1434. }
  1435. // Coalesce rows.
  1436. if (src_stride_argb == width * 4 && dst_stride_yj == width &&
  1437. dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
  1438. width *= height;
  1439. height = 1;
  1440. src_stride_argb = dst_stride_yj = dst_stride_u = dst_stride_v = 0;
  1441. }
  1442. #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
  1443. if (TestCpuFlag(kCpuHasSSSE3)) {
  1444. ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
  1445. ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
  1446. if (IS_ALIGNED(width, 16)) {
  1447. ARGBToUVJRow = ARGBToUVJRow_SSSE3;
  1448. ARGBToYJRow = ARGBToYJRow_SSSE3;
  1449. }
  1450. }
  1451. #endif
  1452. #if defined(HAS_ARGBTOYJROW_AVX2)
  1453. if (TestCpuFlag(kCpuHasAVX2)) {
  1454. ARGBToYJRow = ARGBToYJRow_Any_AVX2;
  1455. if (IS_ALIGNED(width, 32)) {
  1456. ARGBToYJRow = ARGBToYJRow_AVX2;
  1457. }
  1458. }
  1459. #endif
  1460. #if defined(HAS_ARGBTOYJROW_NEON)
  1461. if (TestCpuFlag(kCpuHasNEON)) {
  1462. ARGBToYJRow = ARGBToYJRow_Any_NEON;
  1463. if (IS_ALIGNED(width, 8)) {
  1464. ARGBToYJRow = ARGBToYJRow_NEON;
  1465. }
  1466. }
  1467. #endif
  1468. #if defined(HAS_ARGBTOUVJROW_NEON)
  1469. if (TestCpuFlag(kCpuHasNEON)) {
  1470. ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
  1471. if (IS_ALIGNED(width, 16)) {
  1472. ARGBToUVJRow = ARGBToUVJRow_NEON;
  1473. }
  1474. }
  1475. #endif
  1476. #if defined(HAS_ARGBTOYJROW_MSA)
  1477. if (TestCpuFlag(kCpuHasMSA)) {
  1478. ARGBToYJRow = ARGBToYJRow_Any_MSA;
  1479. if (IS_ALIGNED(width, 16)) {
  1480. ARGBToYJRow = ARGBToYJRow_MSA;
  1481. }
  1482. }
  1483. #endif
  1484. #if defined(HAS_ARGBTOUVJROW_MSA)
  1485. if (TestCpuFlag(kCpuHasMSA)) {
  1486. ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
  1487. if (IS_ALIGNED(width, 32)) {
  1488. ARGBToUVJRow = ARGBToUVJRow_MSA;
  1489. }
  1490. }
  1491. #endif
  1492. for (y = 0; y < height; ++y) {
  1493. ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
  1494. ARGBToYJRow(src_argb, dst_yj, width);
  1495. src_argb += src_stride_argb;
  1496. dst_yj += dst_stride_yj;
  1497. dst_u += dst_stride_u;
  1498. dst_v += dst_stride_v;
  1499. }
  1500. return 0;
  1501. }
  1502. // Convert ARGB to J400.
  1503. LIBYUV_API
  1504. int ARGBToJ400(const uint8_t* src_argb,
  1505. int src_stride_argb,
  1506. uint8_t* dst_yj,
  1507. int dst_stride_yj,
  1508. int width,
  1509. int height) {
  1510. int y;
  1511. void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
  1512. ARGBToYJRow_C;
  1513. if (!src_argb || !dst_yj || width <= 0 || height == 0) {
  1514. return -1;
  1515. }
  1516. if (height < 0) {
  1517. height = -height;
  1518. src_argb = src_argb + (height - 1) * src_stride_argb;
  1519. src_stride_argb = -src_stride_argb;
  1520. }
  1521. // Coalesce rows.
  1522. if (src_stride_argb == width * 4 && dst_stride_yj == width) {
  1523. width *= height;
  1524. height = 1;
  1525. src_stride_argb = dst_stride_yj = 0;
  1526. }
  1527. #if defined(HAS_ARGBTOYJROW_SSSE3)
  1528. if (TestCpuFlag(kCpuHasSSSE3)) {
  1529. ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
  1530. if (IS_ALIGNED(width, 16)) {
  1531. ARGBToYJRow = ARGBToYJRow_SSSE3;
  1532. }
  1533. }
  1534. #endif
  1535. #if defined(HAS_ARGBTOYJROW_AVX2)
  1536. if (TestCpuFlag(kCpuHasAVX2)) {
  1537. ARGBToYJRow = ARGBToYJRow_Any_AVX2;
  1538. if (IS_ALIGNED(width, 32)) {
  1539. ARGBToYJRow = ARGBToYJRow_AVX2;
  1540. }
  1541. }
  1542. #endif
  1543. #if defined(HAS_ARGBTOYJROW_NEON)
  1544. if (TestCpuFlag(kCpuHasNEON)) {
  1545. ARGBToYJRow = ARGBToYJRow_Any_NEON;
  1546. if (IS_ALIGNED(width, 8)) {
  1547. ARGBToYJRow = ARGBToYJRow_NEON;
  1548. }
  1549. }
  1550. #endif
  1551. #if defined(HAS_ARGBTOYJROW_MSA)
  1552. if (TestCpuFlag(kCpuHasMSA)) {
  1553. ARGBToYJRow = ARGBToYJRow_Any_MSA;
  1554. if (IS_ALIGNED(width, 16)) {
  1555. ARGBToYJRow = ARGBToYJRow_MSA;
  1556. }
  1557. }
  1558. #endif
  1559. for (y = 0; y < height; ++y) {
  1560. ARGBToYJRow(src_argb, dst_yj, width);
  1561. src_argb += src_stride_argb;
  1562. dst_yj += dst_stride_yj;
  1563. }
  1564. return 0;
  1565. }
  1566. #ifdef __cplusplus
  1567. } // extern "C"
  1568. } // namespace libyuv
  1569. #endif