convert_argb.cc 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456
  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. #include "libyuv/convert_argb.h"
  11. #include "libyuv/cpu_id.h"
  12. #ifdef HAVE_JPEG
  13. #include "libyuv/mjpeg_decoder.h"
  14. #endif
  15. #include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle.
  16. #include "libyuv/rotate_argb.h"
  17. #include "libyuv/row.h"
  18. #include "libyuv/video_common.h"
  19. #ifdef __cplusplus
  20. namespace libyuv {
  21. extern "C" {
  22. #endif
  23. // Copy ARGB with optional flipping
  24. LIBYUV_API
  25. int ARGBCopy(const uint8* src_argb, int src_stride_argb,
  26. uint8* dst_argb, int dst_stride_argb,
  27. int width, int height) {
  28. if (!src_argb || !dst_argb ||
  29. width <= 0 || height == 0) {
  30. return -1;
  31. }
  32. // Negative height means invert the image.
  33. if (height < 0) {
  34. height = -height;
  35. src_argb = src_argb + (height - 1) * src_stride_argb;
  36. src_stride_argb = -src_stride_argb;
  37. }
  38. CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
  39. width * 4, height);
  40. return 0;
  41. }
  42. // Convert I422 to ARGB with matrix
  43. static int I420ToARGBMatrix(const uint8* src_y, int src_stride_y,
  44. const uint8* src_u, int src_stride_u,
  45. const uint8* src_v, int src_stride_v,
  46. uint8* dst_argb, int dst_stride_argb,
  47. const struct YuvConstants* yuvconstants,
  48. int width, int height) {
  49. int y;
  50. void (*I422ToARGBRow)(const uint8* y_buf,
  51. const uint8* u_buf,
  52. const uint8* v_buf,
  53. uint8* rgb_buf,
  54. const struct YuvConstants* yuvconstants,
  55. int width) = I422ToARGBRow_C;
  56. if (!src_y || !src_u || !src_v || !dst_argb ||
  57. width <= 0 || height == 0) {
  58. return -1;
  59. }
  60. // Negative height means invert the image.
  61. if (height < 0) {
  62. height = -height;
  63. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  64. dst_stride_argb = -dst_stride_argb;
  65. }
  66. #if defined(HAS_I422TOARGBROW_SSSE3)
  67. if (TestCpuFlag(kCpuHasSSSE3)) {
  68. I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
  69. if (IS_ALIGNED(width, 8)) {
  70. I422ToARGBRow = I422ToARGBRow_SSSE3;
  71. }
  72. }
  73. #endif
  74. #if defined(HAS_I422TOARGBROW_AVX2)
  75. if (TestCpuFlag(kCpuHasAVX2)) {
  76. I422ToARGBRow = I422ToARGBRow_Any_AVX2;
  77. if (IS_ALIGNED(width, 16)) {
  78. I422ToARGBRow = I422ToARGBRow_AVX2;
  79. }
  80. }
  81. #endif
  82. #if defined(HAS_I422TOARGBROW_NEON)
  83. if (TestCpuFlag(kCpuHasNEON)) {
  84. I422ToARGBRow = I422ToARGBRow_Any_NEON;
  85. if (IS_ALIGNED(width, 8)) {
  86. I422ToARGBRow = I422ToARGBRow_NEON;
  87. }
  88. }
  89. #endif
  90. #if defined(HAS_I422TOARGBROW_DSPR2)
  91. if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
  92. IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
  93. IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
  94. IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
  95. IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
  96. I422ToARGBRow = I422ToARGBRow_DSPR2;
  97. }
  98. #endif
  99. for (y = 0; y < height; ++y) {
  100. I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
  101. dst_argb += dst_stride_argb;
  102. src_y += src_stride_y;
  103. if (y & 1) {
  104. src_u += src_stride_u;
  105. src_v += src_stride_v;
  106. }
  107. }
  108. return 0;
  109. }
  110. // Convert I420 to ARGB.
  111. LIBYUV_API
  112. int I420ToARGB(const uint8* src_y, int src_stride_y,
  113. const uint8* src_u, int src_stride_u,
  114. const uint8* src_v, int src_stride_v,
  115. uint8* dst_argb, int dst_stride_argb,
  116. int width, int height) {
  117. return I420ToARGBMatrix(src_y, src_stride_y,
  118. src_u, src_stride_u,
  119. src_v, src_stride_v,
  120. dst_argb, dst_stride_argb,
  121. &kYuvI601Constants,
  122. width, height);
  123. }
  124. // Convert I420 to ABGR.
  125. LIBYUV_API
  126. int I420ToABGR(const uint8* src_y, int src_stride_y,
  127. const uint8* src_u, int src_stride_u,
  128. const uint8* src_v, int src_stride_v,
  129. uint8* dst_abgr, int dst_stride_abgr,
  130. int width, int height) {
  131. return I420ToARGBMatrix(src_y, src_stride_y,
  132. src_v, src_stride_v, // Swap U and V
  133. src_u, src_stride_u,
  134. dst_abgr, dst_stride_abgr,
  135. &kYvuI601Constants, // Use Yvu matrix
  136. width, height);
  137. }
  138. // Convert J420 to ARGB.
  139. LIBYUV_API
  140. int J420ToARGB(const uint8* src_y, int src_stride_y,
  141. const uint8* src_u, int src_stride_u,
  142. const uint8* src_v, int src_stride_v,
  143. uint8* dst_argb, int dst_stride_argb,
  144. int width, int height) {
  145. return I420ToARGBMatrix(src_y, src_stride_y,
  146. src_u, src_stride_u,
  147. src_v, src_stride_v,
  148. dst_argb, dst_stride_argb,
  149. &kYuvJPEGConstants,
  150. width, height);
  151. }
  152. // Convert J420 to ABGR.
  153. LIBYUV_API
  154. int J420ToABGR(const uint8* src_y, int src_stride_y,
  155. const uint8* src_u, int src_stride_u,
  156. const uint8* src_v, int src_stride_v,
  157. uint8* dst_abgr, int dst_stride_abgr,
  158. int width, int height) {
  159. return I420ToARGBMatrix(src_y, src_stride_y,
  160. src_v, src_stride_v, // Swap U and V
  161. src_u, src_stride_u,
  162. dst_abgr, dst_stride_abgr,
  163. &kYvuJPEGConstants, // Use Yvu matrix
  164. width, height);
  165. }
  166. // Convert H420 to ARGB.
  167. LIBYUV_API
  168. int H420ToARGB(const uint8* src_y, int src_stride_y,
  169. const uint8* src_u, int src_stride_u,
  170. const uint8* src_v, int src_stride_v,
  171. uint8* dst_argb, int dst_stride_argb,
  172. int width, int height) {
  173. return I420ToARGBMatrix(src_y, src_stride_y,
  174. src_u, src_stride_u,
  175. src_v, src_stride_v,
  176. dst_argb, dst_stride_argb,
  177. &kYuvH709Constants,
  178. width, height);
  179. }
  180. // Convert H420 to ABGR.
  181. LIBYUV_API
  182. int H420ToABGR(const uint8* src_y, int src_stride_y,
  183. const uint8* src_u, int src_stride_u,
  184. const uint8* src_v, int src_stride_v,
  185. uint8* dst_abgr, int dst_stride_abgr,
  186. int width, int height) {
  187. return I420ToARGBMatrix(src_y, src_stride_y,
  188. src_v, src_stride_v, // Swap U and V
  189. src_u, src_stride_u,
  190. dst_abgr, dst_stride_abgr,
  191. &kYvuH709Constants, // Use Yvu matrix
  192. width, height);
  193. }
  194. // Convert I422 to ARGB with matrix
  195. static int I422ToARGBMatrix(const uint8* src_y, int src_stride_y,
  196. const uint8* src_u, int src_stride_u,
  197. const uint8* src_v, int src_stride_v,
  198. uint8* dst_argb, int dst_stride_argb,
  199. const struct YuvConstants* yuvconstants,
  200. int width, int height) {
  201. int y;
  202. void (*I422ToARGBRow)(const uint8* y_buf,
  203. const uint8* u_buf,
  204. const uint8* v_buf,
  205. uint8* rgb_buf,
  206. const struct YuvConstants* yuvconstants,
  207. int width) = I422ToARGBRow_C;
  208. if (!src_y || !src_u || !src_v ||
  209. !dst_argb ||
  210. width <= 0 || height == 0) {
  211. return -1;
  212. }
  213. // Negative height means invert the image.
  214. if (height < 0) {
  215. height = -height;
  216. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  217. dst_stride_argb = -dst_stride_argb;
  218. }
  219. // Coalesce rows.
  220. if (src_stride_y == width &&
  221. src_stride_u * 2 == width &&
  222. src_stride_v * 2 == width &&
  223. dst_stride_argb == width * 4) {
  224. width *= height;
  225. height = 1;
  226. src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
  227. }
  228. #if defined(HAS_I422TOARGBROW_SSSE3)
  229. if (TestCpuFlag(kCpuHasSSSE3)) {
  230. I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
  231. if (IS_ALIGNED(width, 8)) {
  232. I422ToARGBRow = I422ToARGBRow_SSSE3;
  233. }
  234. }
  235. #endif
  236. #if defined(HAS_I422TOARGBROW_AVX2)
  237. if (TestCpuFlag(kCpuHasAVX2)) {
  238. I422ToARGBRow = I422ToARGBRow_Any_AVX2;
  239. if (IS_ALIGNED(width, 16)) {
  240. I422ToARGBRow = I422ToARGBRow_AVX2;
  241. }
  242. }
  243. #endif
  244. #if defined(HAS_I422TOARGBROW_NEON)
  245. if (TestCpuFlag(kCpuHasNEON)) {
  246. I422ToARGBRow = I422ToARGBRow_Any_NEON;
  247. if (IS_ALIGNED(width, 8)) {
  248. I422ToARGBRow = I422ToARGBRow_NEON;
  249. }
  250. }
  251. #endif
  252. #if defined(HAS_I422TOARGBROW_DSPR2)
  253. if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
  254. IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
  255. IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
  256. IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
  257. IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
  258. I422ToARGBRow = I422ToARGBRow_DSPR2;
  259. }
  260. #endif
  261. for (y = 0; y < height; ++y) {
  262. I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
  263. dst_argb += dst_stride_argb;
  264. src_y += src_stride_y;
  265. src_u += src_stride_u;
  266. src_v += src_stride_v;
  267. }
  268. return 0;
  269. }
  270. // Convert I422 to ARGB.
  271. LIBYUV_API
  272. int I422ToARGB(const uint8* src_y, int src_stride_y,
  273. const uint8* src_u, int src_stride_u,
  274. const uint8* src_v, int src_stride_v,
  275. uint8* dst_argb, int dst_stride_argb,
  276. int width, int height) {
  277. return I422ToARGBMatrix(src_y, src_stride_y,
  278. src_u, src_stride_u,
  279. src_v, src_stride_v,
  280. dst_argb, dst_stride_argb,
  281. &kYuvI601Constants,
  282. width, height);
  283. }
  284. // Convert I422 to ABGR.
  285. LIBYUV_API
  286. int I422ToABGR(const uint8* src_y, int src_stride_y,
  287. const uint8* src_u, int src_stride_u,
  288. const uint8* src_v, int src_stride_v,
  289. uint8* dst_abgr, int dst_stride_abgr,
  290. int width, int height) {
  291. return I422ToARGBMatrix(src_y, src_stride_y,
  292. src_v, src_stride_v, // Swap U and V
  293. src_u, src_stride_u,
  294. dst_abgr, dst_stride_abgr,
  295. &kYvuI601Constants, // Use Yvu matrix
  296. width, height);
  297. }
  298. // Convert J422 to ARGB.
  299. LIBYUV_API
  300. int J422ToARGB(const uint8* src_y, int src_stride_y,
  301. const uint8* src_u, int src_stride_u,
  302. const uint8* src_v, int src_stride_v,
  303. uint8* dst_argb, int dst_stride_argb,
  304. int width, int height) {
  305. return I422ToARGBMatrix(src_y, src_stride_y,
  306. src_u, src_stride_u,
  307. src_v, src_stride_v,
  308. dst_argb, dst_stride_argb,
  309. &kYuvJPEGConstants,
  310. width, height);
  311. }
  312. // Convert J422 to ABGR.
  313. LIBYUV_API
  314. int J422ToABGR(const uint8* src_y, int src_stride_y,
  315. const uint8* src_u, int src_stride_u,
  316. const uint8* src_v, int src_stride_v,
  317. uint8* dst_abgr, int dst_stride_abgr,
  318. int width, int height) {
  319. return I422ToARGBMatrix(src_y, src_stride_y,
  320. src_v, src_stride_v, // Swap U and V
  321. src_u, src_stride_u,
  322. dst_abgr, dst_stride_abgr,
  323. &kYvuJPEGConstants, // Use Yvu matrix
  324. width, height);
  325. }
  326. // Convert H422 to ARGB.
  327. LIBYUV_API
  328. int H422ToARGB(const uint8* src_y, int src_stride_y,
  329. const uint8* src_u, int src_stride_u,
  330. const uint8* src_v, int src_stride_v,
  331. uint8* dst_argb, int dst_stride_argb,
  332. int width, int height) {
  333. return I422ToARGBMatrix(src_y, src_stride_y,
  334. src_u, src_stride_u,
  335. src_v, src_stride_v,
  336. dst_argb, dst_stride_argb,
  337. &kYuvH709Constants,
  338. width, height);
  339. }
  340. // Convert H422 to ABGR.
  341. LIBYUV_API
  342. int H422ToABGR(const uint8* src_y, int src_stride_y,
  343. const uint8* src_u, int src_stride_u,
  344. const uint8* src_v, int src_stride_v,
  345. uint8* dst_abgr, int dst_stride_abgr,
  346. int width, int height) {
  347. return I422ToARGBMatrix(src_y, src_stride_y,
  348. src_v, src_stride_v, // Swap U and V
  349. src_u, src_stride_u,
  350. dst_abgr, dst_stride_abgr,
  351. &kYvuH709Constants, // Use Yvu matrix
  352. width, height);
  353. }
  354. // Convert I444 to ARGB with matrix
  355. static int I444ToARGBMatrix(const uint8* src_y, int src_stride_y,
  356. const uint8* src_u, int src_stride_u,
  357. const uint8* src_v, int src_stride_v,
  358. uint8* dst_argb, int dst_stride_argb,
  359. const struct YuvConstants* yuvconstants,
  360. int width, int height) {
  361. int y;
  362. void (*I444ToARGBRow)(const uint8* y_buf,
  363. const uint8* u_buf,
  364. const uint8* v_buf,
  365. uint8* rgb_buf,
  366. const struct YuvConstants* yuvconstants,
  367. int width) = I444ToARGBRow_C;
  368. if (!src_y || !src_u || !src_v ||
  369. !dst_argb ||
  370. width <= 0 || height == 0) {
  371. return -1;
  372. }
  373. // Negative height means invert the image.
  374. if (height < 0) {
  375. height = -height;
  376. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  377. dst_stride_argb = -dst_stride_argb;
  378. }
  379. // Coalesce rows.
  380. if (src_stride_y == width &&
  381. src_stride_u == width &&
  382. src_stride_v == width &&
  383. dst_stride_argb == width * 4) {
  384. width *= height;
  385. height = 1;
  386. src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
  387. }
  388. #if defined(HAS_I444TOARGBROW_SSSE3)
  389. if (TestCpuFlag(kCpuHasSSSE3)) {
  390. I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
  391. if (IS_ALIGNED(width, 8)) {
  392. I444ToARGBRow = I444ToARGBRow_SSSE3;
  393. }
  394. }
  395. #endif
  396. #if defined(HAS_I444TOARGBROW_AVX2)
  397. if (TestCpuFlag(kCpuHasAVX2)) {
  398. I444ToARGBRow = I444ToARGBRow_Any_AVX2;
  399. if (IS_ALIGNED(width, 16)) {
  400. I444ToARGBRow = I444ToARGBRow_AVX2;
  401. }
  402. }
  403. #endif
  404. #if defined(HAS_I444TOARGBROW_NEON)
  405. if (TestCpuFlag(kCpuHasNEON)) {
  406. I444ToARGBRow = I444ToARGBRow_Any_NEON;
  407. if (IS_ALIGNED(width, 8)) {
  408. I444ToARGBRow = I444ToARGBRow_NEON;
  409. }
  410. }
  411. #endif
  412. for (y = 0; y < height; ++y) {
  413. I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
  414. dst_argb += dst_stride_argb;
  415. src_y += src_stride_y;
  416. src_u += src_stride_u;
  417. src_v += src_stride_v;
  418. }
  419. return 0;
  420. }
  421. // Convert I444 to ARGB.
  422. LIBYUV_API
  423. int I444ToARGB(const uint8* src_y, int src_stride_y,
  424. const uint8* src_u, int src_stride_u,
  425. const uint8* src_v, int src_stride_v,
  426. uint8* dst_argb, int dst_stride_argb,
  427. int width, int height) {
  428. return I444ToARGBMatrix(src_y, src_stride_y,
  429. src_u, src_stride_u,
  430. src_v, src_stride_v,
  431. dst_argb, dst_stride_argb,
  432. &kYuvI601Constants,
  433. width, height);
  434. }
  435. // Convert I444 to ABGR.
  436. LIBYUV_API
  437. int I444ToABGR(const uint8* src_y, int src_stride_y,
  438. const uint8* src_u, int src_stride_u,
  439. const uint8* src_v, int src_stride_v,
  440. uint8* dst_abgr, int dst_stride_abgr,
  441. int width, int height) {
  442. return I444ToARGBMatrix(src_y, src_stride_y,
  443. src_v, src_stride_v, // Swap U and V
  444. src_u, src_stride_u,
  445. dst_abgr, dst_stride_abgr,
  446. &kYvuI601Constants, // Use Yvu matrix
  447. width, height);
  448. }
  449. // Convert J444 to ARGB.
  450. LIBYUV_API
  451. int J444ToARGB(const uint8* src_y, int src_stride_y,
  452. const uint8* src_u, int src_stride_u,
  453. const uint8* src_v, int src_stride_v,
  454. uint8* dst_argb, int dst_stride_argb,
  455. int width, int height) {
  456. return I444ToARGBMatrix(src_y, src_stride_y,
  457. src_u, src_stride_u,
  458. src_v, src_stride_v,
  459. dst_argb, dst_stride_argb,
  460. &kYuvJPEGConstants,
  461. width, height);
  462. }
  463. // Convert I411 to ARGB.
  464. LIBYUV_API
  465. int I411ToARGB(const uint8* src_y, int src_stride_y,
  466. const uint8* src_u, int src_stride_u,
  467. const uint8* src_v, int src_stride_v,
  468. uint8* dst_argb, int dst_stride_argb,
  469. int width, int height) {
  470. int y;
  471. void (*I411ToARGBRow)(const uint8* y_buf,
  472. const uint8* u_buf,
  473. const uint8* v_buf,
  474. uint8* rgb_buf,
  475. const struct YuvConstants* yuvconstants,
  476. int width) = I411ToARGBRow_C;
  477. if (!src_y || !src_u || !src_v ||
  478. !dst_argb ||
  479. width <= 0 || height == 0) {
  480. return -1;
  481. }
  482. // Negative height means invert the image.
  483. if (height < 0) {
  484. height = -height;
  485. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  486. dst_stride_argb = -dst_stride_argb;
  487. }
  488. // Coalesce rows.
  489. if (src_stride_y == width &&
  490. src_stride_u * 4 == width &&
  491. src_stride_v * 4 == width &&
  492. dst_stride_argb == width * 4) {
  493. width *= height;
  494. height = 1;
  495. src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
  496. }
  497. #if defined(HAS_I411TOARGBROW_SSSE3)
  498. if (TestCpuFlag(kCpuHasSSSE3)) {
  499. I411ToARGBRow = I411ToARGBRow_Any_SSSE3;
  500. if (IS_ALIGNED(width, 8)) {
  501. I411ToARGBRow = I411ToARGBRow_SSSE3;
  502. }
  503. }
  504. #endif
  505. #if defined(HAS_I411TOARGBROW_AVX2)
  506. if (TestCpuFlag(kCpuHasAVX2)) {
  507. I411ToARGBRow = I411ToARGBRow_Any_AVX2;
  508. if (IS_ALIGNED(width, 16)) {
  509. I411ToARGBRow = I411ToARGBRow_AVX2;
  510. }
  511. }
  512. #endif
  513. #if defined(HAS_I411TOARGBROW_NEON)
  514. if (TestCpuFlag(kCpuHasNEON)) {
  515. I411ToARGBRow = I411ToARGBRow_Any_NEON;
  516. if (IS_ALIGNED(width, 8)) {
  517. I411ToARGBRow = I411ToARGBRow_NEON;
  518. }
  519. }
  520. #endif
  521. for (y = 0; y < height; ++y) {
  522. I411ToARGBRow(src_y, src_u, src_v, dst_argb, &kYuvI601Constants, width);
  523. dst_argb += dst_stride_argb;
  524. src_y += src_stride_y;
  525. src_u += src_stride_u;
  526. src_v += src_stride_v;
  527. }
  528. return 0;
  529. }
  530. // Convert I420 with Alpha to preattenuated ARGB.
  531. static int I420AlphaToARGBMatrix(const uint8* src_y, int src_stride_y,
  532. const uint8* src_u, int src_stride_u,
  533. const uint8* src_v, int src_stride_v,
  534. const uint8* src_a, int src_stride_a,
  535. uint8* dst_argb, int dst_stride_argb,
  536. const struct YuvConstants* yuvconstants,
  537. int width, int height, int attenuate) {
  538. int y;
  539. void (*I422AlphaToARGBRow)(const uint8* y_buf,
  540. const uint8* u_buf,
  541. const uint8* v_buf,
  542. const uint8* a_buf,
  543. uint8* dst_argb,
  544. const struct YuvConstants* yuvconstants,
  545. int width) = I422AlphaToARGBRow_C;
  546. void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb,
  547. int width) = ARGBAttenuateRow_C;
  548. if (!src_y || !src_u || !src_v || !dst_argb ||
  549. width <= 0 || height == 0) {
  550. return -1;
  551. }
  552. // Negative height means invert the image.
  553. if (height < 0) {
  554. height = -height;
  555. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  556. dst_stride_argb = -dst_stride_argb;
  557. }
  558. #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
  559. if (TestCpuFlag(kCpuHasSSSE3)) {
  560. I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
  561. if (IS_ALIGNED(width, 8)) {
  562. I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
  563. }
  564. }
  565. #endif
  566. #if defined(HAS_I422ALPHATOARGBROW_AVX2)
  567. if (TestCpuFlag(kCpuHasAVX2)) {
  568. I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
  569. if (IS_ALIGNED(width, 16)) {
  570. I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
  571. }
  572. }
  573. #endif
  574. #if defined(HAS_I422ALPHATOARGBROW_NEON)
  575. if (TestCpuFlag(kCpuHasNEON)) {
  576. I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
  577. if (IS_ALIGNED(width, 8)) {
  578. I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
  579. }
  580. }
  581. #endif
  582. #if defined(HAS_I422ALPHATOARGBROW_DSPR2)
  583. if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
  584. IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
  585. IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
  586. IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
  587. IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
  588. I422AlphaToARGBRow = I422AlphaToARGBRow_DSPR2;
  589. }
  590. #endif
  591. #if defined(HAS_ARGBATTENUATEROW_SSSE3)
  592. if (TestCpuFlag(kCpuHasSSSE3)) {
  593. ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
  594. if (IS_ALIGNED(width, 4)) {
  595. ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
  596. }
  597. }
  598. #endif
  599. #if defined(HAS_ARGBATTENUATEROW_AVX2)
  600. if (TestCpuFlag(kCpuHasAVX2)) {
  601. ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
  602. if (IS_ALIGNED(width, 8)) {
  603. ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
  604. }
  605. }
  606. #endif
  607. #if defined(HAS_ARGBATTENUATEROW_NEON)
  608. if (TestCpuFlag(kCpuHasNEON)) {
  609. ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
  610. if (IS_ALIGNED(width, 8)) {
  611. ARGBAttenuateRow = ARGBAttenuateRow_NEON;
  612. }
  613. }
  614. #endif
  615. for (y = 0; y < height; ++y) {
  616. I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
  617. width);
  618. if (attenuate) {
  619. ARGBAttenuateRow(dst_argb, dst_argb, width);
  620. }
  621. dst_argb += dst_stride_argb;
  622. src_a += src_stride_a;
  623. src_y += src_stride_y;
  624. if (y & 1) {
  625. src_u += src_stride_u;
  626. src_v += src_stride_v;
  627. }
  628. }
  629. return 0;
  630. }
  631. // Convert I420 with Alpha to ARGB.
  632. LIBYUV_API
  633. int I420AlphaToARGB(const uint8* src_y, int src_stride_y,
  634. const uint8* src_u, int src_stride_u,
  635. const uint8* src_v, int src_stride_v,
  636. const uint8* src_a, int src_stride_a,
  637. uint8* dst_argb, int dst_stride_argb,
  638. int width, int height, int attenuate) {
  639. return I420AlphaToARGBMatrix(src_y, src_stride_y,
  640. src_u, src_stride_u,
  641. src_v, src_stride_v,
  642. src_a, src_stride_a,
  643. dst_argb, dst_stride_argb,
  644. &kYuvI601Constants,
  645. width, height, attenuate);
  646. }
  647. // Convert I420 with Alpha to ABGR.
  648. LIBYUV_API
  649. int I420AlphaToABGR(const uint8* src_y, int src_stride_y,
  650. const uint8* src_u, int src_stride_u,
  651. const uint8* src_v, int src_stride_v,
  652. const uint8* src_a, int src_stride_a,
  653. uint8* dst_abgr, int dst_stride_abgr,
  654. int width, int height, int attenuate) {
  655. return I420AlphaToARGBMatrix(src_y, src_stride_y,
  656. src_v, src_stride_v, // Swap U and V
  657. src_u, src_stride_u,
  658. src_a, src_stride_a,
  659. dst_abgr, dst_stride_abgr,
  660. &kYvuI601Constants, // Use Yvu matrix
  661. width, height, attenuate);
  662. }
  663. // Convert I400 to ARGB.
  664. LIBYUV_API
  665. int I400ToARGB(const uint8* src_y, int src_stride_y,
  666. uint8* dst_argb, int dst_stride_argb,
  667. int width, int height) {
  668. int y;
  669. void (*I400ToARGBRow)(const uint8* y_buf,
  670. uint8* rgb_buf,
  671. int width) = I400ToARGBRow_C;
  672. if (!src_y || !dst_argb ||
  673. width <= 0 || height == 0) {
  674. return -1;
  675. }
  676. // Negative height means invert the image.
  677. if (height < 0) {
  678. height = -height;
  679. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  680. dst_stride_argb = -dst_stride_argb;
  681. }
  682. // Coalesce rows.
  683. if (src_stride_y == width &&
  684. dst_stride_argb == width * 4) {
  685. width *= height;
  686. height = 1;
  687. src_stride_y = dst_stride_argb = 0;
  688. }
  689. #if defined(HAS_I400TOARGBROW_SSE2)
  690. if (TestCpuFlag(kCpuHasSSE2)) {
  691. I400ToARGBRow = I400ToARGBRow_Any_SSE2;
  692. if (IS_ALIGNED(width, 8)) {
  693. I400ToARGBRow = I400ToARGBRow_SSE2;
  694. }
  695. }
  696. #endif
  697. #if defined(HAS_I400TOARGBROW_AVX2)
  698. if (TestCpuFlag(kCpuHasAVX2)) {
  699. I400ToARGBRow = I400ToARGBRow_Any_AVX2;
  700. if (IS_ALIGNED(width, 16)) {
  701. I400ToARGBRow = I400ToARGBRow_AVX2;
  702. }
  703. }
  704. #endif
  705. #if defined(HAS_I400TOARGBROW_NEON)
  706. if (TestCpuFlag(kCpuHasNEON)) {
  707. I400ToARGBRow = I400ToARGBRow_Any_NEON;
  708. if (IS_ALIGNED(width, 8)) {
  709. I400ToARGBRow = I400ToARGBRow_NEON;
  710. }
  711. }
  712. #endif
  713. for (y = 0; y < height; ++y) {
  714. I400ToARGBRow(src_y, dst_argb, width);
  715. dst_argb += dst_stride_argb;
  716. src_y += src_stride_y;
  717. }
  718. return 0;
  719. }
  720. // Convert J400 to ARGB.
  721. LIBYUV_API
  722. int J400ToARGB(const uint8* src_y, int src_stride_y,
  723. uint8* dst_argb, int dst_stride_argb,
  724. int width, int height) {
  725. int y;
  726. void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int width) =
  727. J400ToARGBRow_C;
  728. if (!src_y || !dst_argb ||
  729. width <= 0 || height == 0) {
  730. return -1;
  731. }
  732. // Negative height means invert the image.
  733. if (height < 0) {
  734. height = -height;
  735. src_y = src_y + (height - 1) * src_stride_y;
  736. src_stride_y = -src_stride_y;
  737. }
  738. // Coalesce rows.
  739. if (src_stride_y == width &&
  740. dst_stride_argb == width * 4) {
  741. width *= height;
  742. height = 1;
  743. src_stride_y = dst_stride_argb = 0;
  744. }
  745. #if defined(HAS_J400TOARGBROW_SSE2)
  746. if (TestCpuFlag(kCpuHasSSE2)) {
  747. J400ToARGBRow = J400ToARGBRow_Any_SSE2;
  748. if (IS_ALIGNED(width, 8)) {
  749. J400ToARGBRow = J400ToARGBRow_SSE2;
  750. }
  751. }
  752. #endif
  753. #if defined(HAS_J400TOARGBROW_AVX2)
  754. if (TestCpuFlag(kCpuHasAVX2)) {
  755. J400ToARGBRow = J400ToARGBRow_Any_AVX2;
  756. if (IS_ALIGNED(width, 16)) {
  757. J400ToARGBRow = J400ToARGBRow_AVX2;
  758. }
  759. }
  760. #endif
  761. #if defined(HAS_J400TOARGBROW_NEON)
  762. if (TestCpuFlag(kCpuHasNEON)) {
  763. J400ToARGBRow = J400ToARGBRow_Any_NEON;
  764. if (IS_ALIGNED(width, 8)) {
  765. J400ToARGBRow = J400ToARGBRow_NEON;
  766. }
  767. }
  768. #endif
  769. for (y = 0; y < height; ++y) {
  770. J400ToARGBRow(src_y, dst_argb, width);
  771. src_y += src_stride_y;
  772. dst_argb += dst_stride_argb;
  773. }
  774. return 0;
  775. }
  776. // Shuffle table for converting BGRA to ARGB.
  777. static uvec8 kShuffleMaskBGRAToARGB = {
  778. 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u
  779. };
  780. // Shuffle table for converting ABGR to ARGB.
  781. static uvec8 kShuffleMaskABGRToARGB = {
  782. 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u
  783. };
  784. // Shuffle table for converting RGBA to ARGB.
  785. static uvec8 kShuffleMaskRGBAToARGB = {
  786. 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u
  787. };
  788. // Convert BGRA to ARGB.
  789. LIBYUV_API
  790. int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
  791. uint8* dst_argb, int dst_stride_argb,
  792. int width, int height) {
  793. return ARGBShuffle(src_bgra, src_stride_bgra,
  794. dst_argb, dst_stride_argb,
  795. (const uint8*)(&kShuffleMaskBGRAToARGB),
  796. width, height);
  797. }
  798. // Convert ARGB to BGRA (same as BGRAToARGB).
  799. LIBYUV_API
  800. int ARGBToBGRA(const uint8* src_bgra, int src_stride_bgra,
  801. uint8* dst_argb, int dst_stride_argb,
  802. int width, int height) {
  803. return ARGBShuffle(src_bgra, src_stride_bgra,
  804. dst_argb, dst_stride_argb,
  805. (const uint8*)(&kShuffleMaskBGRAToARGB),
  806. width, height);
  807. }
  808. // Convert ABGR to ARGB.
  809. LIBYUV_API
  810. int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
  811. uint8* dst_argb, int dst_stride_argb,
  812. int width, int height) {
  813. return ARGBShuffle(src_abgr, src_stride_abgr,
  814. dst_argb, dst_stride_argb,
  815. (const uint8*)(&kShuffleMaskABGRToARGB),
  816. width, height);
  817. }
  818. // Convert ARGB to ABGR to (same as ABGRToARGB).
  819. LIBYUV_API
  820. int ARGBToABGR(const uint8* src_abgr, int src_stride_abgr,
  821. uint8* dst_argb, int dst_stride_argb,
  822. int width, int height) {
  823. return ARGBShuffle(src_abgr, src_stride_abgr,
  824. dst_argb, dst_stride_argb,
  825. (const uint8*)(&kShuffleMaskABGRToARGB),
  826. width, height);
  827. }
  828. // Convert RGBA to ARGB.
  829. LIBYUV_API
  830. int RGBAToARGB(const uint8* src_rgba, int src_stride_rgba,
  831. uint8* dst_argb, int dst_stride_argb,
  832. int width, int height) {
  833. return ARGBShuffle(src_rgba, src_stride_rgba,
  834. dst_argb, dst_stride_argb,
  835. (const uint8*)(&kShuffleMaskRGBAToARGB),
  836. width, height);
  837. }
  838. // Convert RGB24 to ARGB.
  839. LIBYUV_API
  840. int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
  841. uint8* dst_argb, int dst_stride_argb,
  842. int width, int height) {
  843. int y;
  844. void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
  845. RGB24ToARGBRow_C;
  846. if (!src_rgb24 || !dst_argb ||
  847. width <= 0 || height == 0) {
  848. return -1;
  849. }
  850. // Negative height means invert the image.
  851. if (height < 0) {
  852. height = -height;
  853. src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
  854. src_stride_rgb24 = -src_stride_rgb24;
  855. }
  856. // Coalesce rows.
  857. if (src_stride_rgb24 == width * 3 &&
  858. dst_stride_argb == width * 4) {
  859. width *= height;
  860. height = 1;
  861. src_stride_rgb24 = dst_stride_argb = 0;
  862. }
  863. #if defined(HAS_RGB24TOARGBROW_SSSE3)
  864. if (TestCpuFlag(kCpuHasSSSE3)) {
  865. RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
  866. if (IS_ALIGNED(width, 16)) {
  867. RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
  868. }
  869. }
  870. #endif
  871. #if defined(HAS_RGB24TOARGBROW_NEON)
  872. if (TestCpuFlag(kCpuHasNEON)) {
  873. RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
  874. if (IS_ALIGNED(width, 8)) {
  875. RGB24ToARGBRow = RGB24ToARGBRow_NEON;
  876. }
  877. }
  878. #endif
  879. for (y = 0; y < height; ++y) {
  880. RGB24ToARGBRow(src_rgb24, dst_argb, width);
  881. src_rgb24 += src_stride_rgb24;
  882. dst_argb += dst_stride_argb;
  883. }
  884. return 0;
  885. }
  886. // Convert RAW to ARGB.
  887. LIBYUV_API
  888. int RAWToARGB(const uint8* src_raw, int src_stride_raw,
  889. uint8* dst_argb, int dst_stride_argb,
  890. int width, int height) {
  891. int y;
  892. void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
  893. RAWToARGBRow_C;
  894. if (!src_raw || !dst_argb ||
  895. width <= 0 || height == 0) {
  896. return -1;
  897. }
  898. // Negative height means invert the image.
  899. if (height < 0) {
  900. height = -height;
  901. src_raw = src_raw + (height - 1) * src_stride_raw;
  902. src_stride_raw = -src_stride_raw;
  903. }
  904. // Coalesce rows.
  905. if (src_stride_raw == width * 3 &&
  906. dst_stride_argb == width * 4) {
  907. width *= height;
  908. height = 1;
  909. src_stride_raw = dst_stride_argb = 0;
  910. }
  911. #if defined(HAS_RAWTOARGBROW_SSSE3)
  912. if (TestCpuFlag(kCpuHasSSSE3)) {
  913. RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
  914. if (IS_ALIGNED(width, 16)) {
  915. RAWToARGBRow = RAWToARGBRow_SSSE3;
  916. }
  917. }
  918. #endif
  919. #if defined(HAS_RAWTOARGBROW_NEON)
  920. if (TestCpuFlag(kCpuHasNEON)) {
  921. RAWToARGBRow = RAWToARGBRow_Any_NEON;
  922. if (IS_ALIGNED(width, 8)) {
  923. RAWToARGBRow = RAWToARGBRow_NEON;
  924. }
  925. }
  926. #endif
  927. for (y = 0; y < height; ++y) {
  928. RAWToARGBRow(src_raw, dst_argb, width);
  929. src_raw += src_stride_raw;
  930. dst_argb += dst_stride_argb;
  931. }
  932. return 0;
  933. }
  934. // Convert RGB565 to ARGB.
  935. LIBYUV_API
  936. int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
  937. uint8* dst_argb, int dst_stride_argb,
  938. int width, int height) {
  939. int y;
  940. void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int width) =
  941. RGB565ToARGBRow_C;
  942. if (!src_rgb565 || !dst_argb ||
  943. width <= 0 || height == 0) {
  944. return -1;
  945. }
  946. // Negative height means invert the image.
  947. if (height < 0) {
  948. height = -height;
  949. src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
  950. src_stride_rgb565 = -src_stride_rgb565;
  951. }
  952. // Coalesce rows.
  953. if (src_stride_rgb565 == width * 2 &&
  954. dst_stride_argb == width * 4) {
  955. width *= height;
  956. height = 1;
  957. src_stride_rgb565 = dst_stride_argb = 0;
  958. }
  959. #if defined(HAS_RGB565TOARGBROW_SSE2)
  960. if (TestCpuFlag(kCpuHasSSE2)) {
  961. RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
  962. if (IS_ALIGNED(width, 8)) {
  963. RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
  964. }
  965. }
  966. #endif
  967. #if defined(HAS_RGB565TOARGBROW_AVX2)
  968. if (TestCpuFlag(kCpuHasAVX2)) {
  969. RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
  970. if (IS_ALIGNED(width, 16)) {
  971. RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
  972. }
  973. }
  974. #endif
  975. #if defined(HAS_RGB565TOARGBROW_NEON)
  976. if (TestCpuFlag(kCpuHasNEON)) {
  977. RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
  978. if (IS_ALIGNED(width, 8)) {
  979. RGB565ToARGBRow = RGB565ToARGBRow_NEON;
  980. }
  981. }
  982. #endif
  983. for (y = 0; y < height; ++y) {
  984. RGB565ToARGBRow(src_rgb565, dst_argb, width);
  985. src_rgb565 += src_stride_rgb565;
  986. dst_argb += dst_stride_argb;
  987. }
  988. return 0;
  989. }
  990. // Convert ARGB1555 to ARGB.
  991. LIBYUV_API
  992. int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
  993. uint8* dst_argb, int dst_stride_argb,
  994. int width, int height) {
  995. int y;
  996. void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
  997. int width) = ARGB1555ToARGBRow_C;
  998. if (!src_argb1555 || !dst_argb ||
  999. width <= 0 || height == 0) {
  1000. return -1;
  1001. }
  1002. // Negative height means invert the image.
  1003. if (height < 0) {
  1004. height = -height;
  1005. src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
  1006. src_stride_argb1555 = -src_stride_argb1555;
  1007. }
  1008. // Coalesce rows.
  1009. if (src_stride_argb1555 == width * 2 &&
  1010. dst_stride_argb == width * 4) {
  1011. width *= height;
  1012. height = 1;
  1013. src_stride_argb1555 = dst_stride_argb = 0;
  1014. }
  1015. #if defined(HAS_ARGB1555TOARGBROW_SSE2)
  1016. if (TestCpuFlag(kCpuHasSSE2)) {
  1017. ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
  1018. if (IS_ALIGNED(width, 8)) {
  1019. ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
  1020. }
  1021. }
  1022. #endif
  1023. #if defined(HAS_ARGB1555TOARGBROW_AVX2)
  1024. if (TestCpuFlag(kCpuHasAVX2)) {
  1025. ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
  1026. if (IS_ALIGNED(width, 16)) {
  1027. ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
  1028. }
  1029. }
  1030. #endif
  1031. #if defined(HAS_ARGB1555TOARGBROW_NEON)
  1032. if (TestCpuFlag(kCpuHasNEON)) {
  1033. ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
  1034. if (IS_ALIGNED(width, 8)) {
  1035. ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
  1036. }
  1037. }
  1038. #endif
  1039. for (y = 0; y < height; ++y) {
  1040. ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
  1041. src_argb1555 += src_stride_argb1555;
  1042. dst_argb += dst_stride_argb;
  1043. }
  1044. return 0;
  1045. }
  1046. // Convert ARGB4444 to ARGB.
  1047. LIBYUV_API
  1048. int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
  1049. uint8* dst_argb, int dst_stride_argb,
  1050. int width, int height) {
  1051. int y;
  1052. void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
  1053. int width) = ARGB4444ToARGBRow_C;
  1054. if (!src_argb4444 || !dst_argb ||
  1055. width <= 0 || height == 0) {
  1056. return -1;
  1057. }
  1058. // Negative height means invert the image.
  1059. if (height < 0) {
  1060. height = -height;
  1061. src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
  1062. src_stride_argb4444 = -src_stride_argb4444;
  1063. }
  1064. // Coalesce rows.
  1065. if (src_stride_argb4444 == width * 2 &&
  1066. dst_stride_argb == width * 4) {
  1067. width *= height;
  1068. height = 1;
  1069. src_stride_argb4444 = dst_stride_argb = 0;
  1070. }
  1071. #if defined(HAS_ARGB4444TOARGBROW_SSE2)
  1072. if (TestCpuFlag(kCpuHasSSE2)) {
  1073. ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
  1074. if (IS_ALIGNED(width, 8)) {
  1075. ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
  1076. }
  1077. }
  1078. #endif
  1079. #if defined(HAS_ARGB4444TOARGBROW_AVX2)
  1080. if (TestCpuFlag(kCpuHasAVX2)) {
  1081. ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
  1082. if (IS_ALIGNED(width, 16)) {
  1083. ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
  1084. }
  1085. }
  1086. #endif
  1087. #if defined(HAS_ARGB4444TOARGBROW_NEON)
  1088. if (TestCpuFlag(kCpuHasNEON)) {
  1089. ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
  1090. if (IS_ALIGNED(width, 8)) {
  1091. ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
  1092. }
  1093. }
  1094. #endif
  1095. for (y = 0; y < height; ++y) {
  1096. ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
  1097. src_argb4444 += src_stride_argb4444;
  1098. dst_argb += dst_stride_argb;
  1099. }
  1100. return 0;
  1101. }
  1102. // Convert NV12 to ARGB.
  1103. LIBYUV_API
  1104. int NV12ToARGB(const uint8* src_y, int src_stride_y,
  1105. const uint8* src_uv, int src_stride_uv,
  1106. uint8* dst_argb, int dst_stride_argb,
  1107. int width, int height) {
  1108. int y;
  1109. void (*NV12ToARGBRow)(const uint8* y_buf,
  1110. const uint8* uv_buf,
  1111. uint8* rgb_buf,
  1112. const struct YuvConstants* yuvconstants,
  1113. int width) = NV12ToARGBRow_C;
  1114. if (!src_y || !src_uv || !dst_argb ||
  1115. width <= 0 || height == 0) {
  1116. return -1;
  1117. }
  1118. // Negative height means invert the image.
  1119. if (height < 0) {
  1120. height = -height;
  1121. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  1122. dst_stride_argb = -dst_stride_argb;
  1123. }
  1124. #if defined(HAS_NV12TOARGBROW_SSSE3)
  1125. if (TestCpuFlag(kCpuHasSSSE3)) {
  1126. NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
  1127. if (IS_ALIGNED(width, 8)) {
  1128. NV12ToARGBRow = NV12ToARGBRow_SSSE3;
  1129. }
  1130. }
  1131. #endif
  1132. #if defined(HAS_NV12TOARGBROW_AVX2)
  1133. if (TestCpuFlag(kCpuHasAVX2)) {
  1134. NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
  1135. if (IS_ALIGNED(width, 16)) {
  1136. NV12ToARGBRow = NV12ToARGBRow_AVX2;
  1137. }
  1138. }
  1139. #endif
  1140. #if defined(HAS_NV12TOARGBROW_NEON)
  1141. if (TestCpuFlag(kCpuHasNEON)) {
  1142. NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
  1143. if (IS_ALIGNED(width, 8)) {
  1144. NV12ToARGBRow = NV12ToARGBRow_NEON;
  1145. }
  1146. }
  1147. #endif
  1148. for (y = 0; y < height; ++y) {
  1149. NV12ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
  1150. dst_argb += dst_stride_argb;
  1151. src_y += src_stride_y;
  1152. if (y & 1) {
  1153. src_uv += src_stride_uv;
  1154. }
  1155. }
  1156. return 0;
  1157. }
  1158. // Convert NV21 to ARGB.
  1159. LIBYUV_API
  1160. int NV21ToARGB(const uint8* src_y, int src_stride_y,
  1161. const uint8* src_uv, int src_stride_uv,
  1162. uint8* dst_argb, int dst_stride_argb,
  1163. int width, int height) {
  1164. int y;
  1165. void (*NV21ToARGBRow)(const uint8* y_buf,
  1166. const uint8* uv_buf,
  1167. uint8* rgb_buf,
  1168. const struct YuvConstants* yuvconstants,
  1169. int width) = NV21ToARGBRow_C;
  1170. if (!src_y || !src_uv || !dst_argb ||
  1171. width <= 0 || height == 0) {
  1172. return -1;
  1173. }
  1174. // Negative height means invert the image.
  1175. if (height < 0) {
  1176. height = -height;
  1177. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  1178. dst_stride_argb = -dst_stride_argb;
  1179. }
  1180. #if defined(HAS_NV21TOARGBROW_SSSE3)
  1181. if (TestCpuFlag(kCpuHasSSSE3)) {
  1182. NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
  1183. if (IS_ALIGNED(width, 8)) {
  1184. NV21ToARGBRow = NV21ToARGBRow_SSSE3;
  1185. }
  1186. }
  1187. #endif
  1188. #if defined(HAS_NV21TOARGBROW_AVX2)
  1189. if (TestCpuFlag(kCpuHasAVX2)) {
  1190. NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
  1191. if (IS_ALIGNED(width, 16)) {
  1192. NV21ToARGBRow = NV21ToARGBRow_AVX2;
  1193. }
  1194. }
  1195. #endif
  1196. #if defined(HAS_NV21TOARGBROW_NEON)
  1197. if (TestCpuFlag(kCpuHasNEON)) {
  1198. NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
  1199. if (IS_ALIGNED(width, 8)) {
  1200. NV21ToARGBRow = NV21ToARGBRow_NEON;
  1201. }
  1202. }
  1203. #endif
  1204. for (y = 0; y < height; ++y) {
  1205. NV21ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
  1206. dst_argb += dst_stride_argb;
  1207. src_y += src_stride_y;
  1208. if (y & 1) {
  1209. src_uv += src_stride_uv;
  1210. }
  1211. }
  1212. return 0;
  1213. }
  1214. // Convert M420 to ARGB.
  1215. LIBYUV_API
  1216. int M420ToARGB(const uint8* src_m420, int src_stride_m420,
  1217. uint8* dst_argb, int dst_stride_argb,
  1218. int width, int height) {
  1219. int y;
  1220. void (*NV12ToARGBRow)(const uint8* y_buf,
  1221. const uint8* uv_buf,
  1222. uint8* rgb_buf,
  1223. const struct YuvConstants* yuvconstants,
  1224. int width) = NV12ToARGBRow_C;
  1225. if (!src_m420 || !dst_argb ||
  1226. width <= 0 || height == 0) {
  1227. return -1;
  1228. }
  1229. // Negative height means invert the image.
  1230. if (height < 0) {
  1231. height = -height;
  1232. dst_argb = dst_argb + (height - 1) * dst_stride_argb;
  1233. dst_stride_argb = -dst_stride_argb;
  1234. }
  1235. #if defined(HAS_NV12TOARGBROW_SSSE3)
  1236. if (TestCpuFlag(kCpuHasSSSE3)) {
  1237. NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
  1238. if (IS_ALIGNED(width, 8)) {
  1239. NV12ToARGBRow = NV12ToARGBRow_SSSE3;
  1240. }
  1241. }
  1242. #endif
  1243. #if defined(HAS_NV12TOARGBROW_AVX2)
  1244. if (TestCpuFlag(kCpuHasAVX2)) {
  1245. NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
  1246. if (IS_ALIGNED(width, 16)) {
  1247. NV12ToARGBRow = NV12ToARGBRow_AVX2;
  1248. }
  1249. }
  1250. #endif
  1251. #if defined(HAS_NV12TOARGBROW_NEON)
  1252. if (TestCpuFlag(kCpuHasNEON)) {
  1253. NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
  1254. if (IS_ALIGNED(width, 8)) {
  1255. NV12ToARGBRow = NV12ToARGBRow_NEON;
  1256. }
  1257. }
  1258. #endif
  1259. for (y = 0; y < height - 1; y += 2) {
  1260. NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
  1261. &kYuvI601Constants, width);
  1262. NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
  1263. dst_argb + dst_stride_argb, &kYuvI601Constants, width);
  1264. dst_argb += dst_stride_argb * 2;
  1265. src_m420 += src_stride_m420 * 3;
  1266. }
  1267. if (height & 1) {
  1268. NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
  1269. &kYuvI601Constants, width);
  1270. }
  1271. return 0;
  1272. }
  1273. // Convert YUY2 to ARGB.
  1274. LIBYUV_API
  1275. int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
  1276. uint8* dst_argb, int dst_stride_argb,
  1277. int width, int height) {
  1278. int y;
  1279. void (*YUY2ToARGBRow)(const uint8* src_yuy2,
  1280. uint8* dst_argb,
  1281. const struct YuvConstants* yuvconstants,
  1282. int width) =
  1283. YUY2ToARGBRow_C;
  1284. if (!src_yuy2 || !dst_argb ||
  1285. width <= 0 || height == 0) {
  1286. return -1;
  1287. }
  1288. // Negative height means invert the image.
  1289. if (height < 0) {
  1290. height = -height;
  1291. src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
  1292. src_stride_yuy2 = -src_stride_yuy2;
  1293. }
  1294. // Coalesce rows.
  1295. if (src_stride_yuy2 == width * 2 &&
  1296. dst_stride_argb == width * 4) {
  1297. width *= height;
  1298. height = 1;
  1299. src_stride_yuy2 = dst_stride_argb = 0;
  1300. }
  1301. #if defined(HAS_YUY2TOARGBROW_SSSE3)
  1302. if (TestCpuFlag(kCpuHasSSSE3)) {
  1303. YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
  1304. if (IS_ALIGNED(width, 16)) {
  1305. YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
  1306. }
  1307. }
  1308. #endif
  1309. #if defined(HAS_YUY2TOARGBROW_AVX2)
  1310. if (TestCpuFlag(kCpuHasAVX2)) {
  1311. YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
  1312. if (IS_ALIGNED(width, 32)) {
  1313. YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
  1314. }
  1315. }
  1316. #endif
  1317. #if defined(HAS_YUY2TOARGBROW_NEON)
  1318. if (TestCpuFlag(kCpuHasNEON)) {
  1319. YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
  1320. if (IS_ALIGNED(width, 8)) {
  1321. YUY2ToARGBRow = YUY2ToARGBRow_NEON;
  1322. }
  1323. }
  1324. #endif
  1325. for (y = 0; y < height; ++y) {
  1326. YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
  1327. src_yuy2 += src_stride_yuy2;
  1328. dst_argb += dst_stride_argb;
  1329. }
  1330. return 0;
  1331. }
  1332. // Convert UYVY to ARGB.
  1333. LIBYUV_API
  1334. int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
  1335. uint8* dst_argb, int dst_stride_argb,
  1336. int width, int height) {
  1337. int y;
  1338. void (*UYVYToARGBRow)(const uint8* src_uyvy,
  1339. uint8* dst_argb,
  1340. const struct YuvConstants* yuvconstants,
  1341. int width) =
  1342. UYVYToARGBRow_C;
  1343. if (!src_uyvy || !dst_argb ||
  1344. width <= 0 || height == 0) {
  1345. return -1;
  1346. }
  1347. // Negative height means invert the image.
  1348. if (height < 0) {
  1349. height = -height;
  1350. src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
  1351. src_stride_uyvy = -src_stride_uyvy;
  1352. }
  1353. // Coalesce rows.
  1354. if (src_stride_uyvy == width * 2 &&
  1355. dst_stride_argb == width * 4) {
  1356. width *= height;
  1357. height = 1;
  1358. src_stride_uyvy = dst_stride_argb = 0;
  1359. }
  1360. #if defined(HAS_UYVYTOARGBROW_SSSE3)
  1361. if (TestCpuFlag(kCpuHasSSSE3)) {
  1362. UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
  1363. if (IS_ALIGNED(width, 16)) {
  1364. UYVYToARGBRow = UYVYToARGBRow_SSSE3;
  1365. }
  1366. }
  1367. #endif
  1368. #if defined(HAS_UYVYTOARGBROW_AVX2)
  1369. if (TestCpuFlag(kCpuHasAVX2)) {
  1370. UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
  1371. if (IS_ALIGNED(width, 32)) {
  1372. UYVYToARGBRow = UYVYToARGBRow_AVX2;
  1373. }
  1374. }
  1375. #endif
  1376. #if defined(HAS_UYVYTOARGBROW_NEON)
  1377. if (TestCpuFlag(kCpuHasNEON)) {
  1378. UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
  1379. if (IS_ALIGNED(width, 8)) {
  1380. UYVYToARGBRow = UYVYToARGBRow_NEON;
  1381. }
  1382. }
  1383. #endif
  1384. for (y = 0; y < height; ++y) {
  1385. UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
  1386. src_uyvy += src_stride_uyvy;
  1387. dst_argb += dst_stride_argb;
  1388. }
  1389. return 0;
  1390. }
  1391. #ifdef __cplusplus
  1392. } // extern "C"
  1393. } // namespace libyuv
  1394. #endif