1 /*
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "libyuv/convert_argb.h"
12
13 #include "libyuv/cpu_id.h"
14 #ifdef HAVE_JPEG
15 #include "libyuv/mjpeg_decoder.h"
16 #endif
17 #include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle.
18 #include "libyuv/rotate_argb.h"
19 #include "libyuv/row.h"
20 #include "libyuv/video_common.h"
21
22 #ifdef __cplusplus
23 namespace libyuv {
24 extern "C" {
25 #endif
26
27 // Copy ARGB with optional flipping
28 LIBYUV_API
ARGBCopy(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb,int dst_stride_argb,int width,int height)29 int ARGBCopy(const uint8_t* src_argb,
30 int src_stride_argb,
31 uint8_t* dst_argb,
32 int dst_stride_argb,
33 int width,
34 int height) {
35 if (!src_argb || !dst_argb || width <= 0 || height == 0) {
36 return -1;
37 }
38 // Negative height means invert the image.
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
45 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4,
46 height);
47 return 0;
48 }
49
50 // Convert I420 to ARGB with matrix
I420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)51 static int I420ToARGBMatrix(const uint8_t* src_y,
52 int src_stride_y,
53 const uint8_t* src_u,
54 int src_stride_u,
55 const uint8_t* src_v,
56 int src_stride_v,
57 uint8_t* dst_argb,
58 int dst_stride_argb,
59 const struct YuvConstants* yuvconstants,
60 int width,
61 int height) {
62 int y;
63 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
64 const uint8_t* v_buf, uint8_t* rgb_buf,
65 const struct YuvConstants* yuvconstants, int width) =
66 I422ToARGBRow_C;
67 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
68 return -1;
69 }
70 // Negative height means invert the image.
71 if (height < 0) {
72 height = -height;
73 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
74 dst_stride_argb = -dst_stride_argb;
75 }
76 #if defined(HAS_I422TOARGBROW_SSSE3)
77 if (TestCpuFlag(kCpuHasSSSE3)) {
78 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
79 if (IS_ALIGNED(width, 8)) {
80 I422ToARGBRow = I422ToARGBRow_SSSE3;
81 }
82 }
83 #endif
84 #if defined(HAS_I422TOARGBROW_AVX2)
85 if (TestCpuFlag(kCpuHasAVX2)) {
86 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
87 if (IS_ALIGNED(width, 16)) {
88 I422ToARGBRow = I422ToARGBRow_AVX2;
89 }
90 }
91 #endif
92 #if defined(HAS_I422TOARGBROW_NEON)
93 if (TestCpuFlag(kCpuHasNEON)) {
94 I422ToARGBRow = I422ToARGBRow_Any_NEON;
95 if (IS_ALIGNED(width, 8)) {
96 I422ToARGBRow = I422ToARGBRow_NEON;
97 }
98 }
99 #endif
100 #if defined(HAS_I422TOARGBROW_MSA)
101 if (TestCpuFlag(kCpuHasMSA)) {
102 I422ToARGBRow = I422ToARGBRow_Any_MSA;
103 if (IS_ALIGNED(width, 8)) {
104 I422ToARGBRow = I422ToARGBRow_MSA;
105 }
106 }
107 #endif
108 #if defined(HAS_I422TOARGBROW_MMI)
109 if (TestCpuFlag(kCpuHasMMI)) {
110 I422ToARGBRow = I422ToARGBRow_Any_MMI;
111 if (IS_ALIGNED(width, 4)) {
112 I422ToARGBRow = I422ToARGBRow_MMI;
113 }
114 }
115 #endif
116
117 for (y = 0; y < height; ++y) {
118 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
119 dst_argb += dst_stride_argb;
120 src_y += src_stride_y;
121 if (y & 1) {
122 src_u += src_stride_u;
123 src_v += src_stride_v;
124 }
125 }
126 return 0;
127 }
128
129 // Convert I420 to ARGB.
130 LIBYUV_API
I420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)131 int I420ToARGB(const uint8_t* src_y,
132 int src_stride_y,
133 const uint8_t* src_u,
134 int src_stride_u,
135 const uint8_t* src_v,
136 int src_stride_v,
137 uint8_t* dst_argb,
138 int dst_stride_argb,
139 int width,
140 int height) {
141 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
142 src_stride_v, dst_argb, dst_stride_argb,
143 &kYuvI601Constants, width, height);
144 }
145
146 // Convert I420 to ABGR.
147 LIBYUV_API
I420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)148 int I420ToABGR(const uint8_t* src_y,
149 int src_stride_y,
150 const uint8_t* src_u,
151 int src_stride_u,
152 const uint8_t* src_v,
153 int src_stride_v,
154 uint8_t* dst_abgr,
155 int dst_stride_abgr,
156 int width,
157 int height) {
158 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
159 src_stride_v, // Swap U and V
160 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
161 &kYvuI601Constants, // Use Yvu matrix
162 width, height);
163 }
164
165 // Convert J420 to ARGB.
166 LIBYUV_API
J420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)167 int J420ToARGB(const uint8_t* src_y,
168 int src_stride_y,
169 const uint8_t* src_u,
170 int src_stride_u,
171 const uint8_t* src_v,
172 int src_stride_v,
173 uint8_t* dst_argb,
174 int dst_stride_argb,
175 int width,
176 int height) {
177 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
178 src_stride_v, dst_argb, dst_stride_argb,
179 &kYuvJPEGConstants, width, height);
180 }
181
182 // Convert J420 to ABGR.
183 LIBYUV_API
J420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)184 int J420ToABGR(const uint8_t* src_y,
185 int src_stride_y,
186 const uint8_t* src_u,
187 int src_stride_u,
188 const uint8_t* src_v,
189 int src_stride_v,
190 uint8_t* dst_abgr,
191 int dst_stride_abgr,
192 int width,
193 int height) {
194 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
195 src_stride_v, // Swap U and V
196 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
197 &kYvuJPEGConstants, // Use Yvu matrix
198 width, height);
199 }
200
201 // Convert H420 to ARGB.
202 LIBYUV_API
H420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)203 int H420ToARGB(const uint8_t* src_y,
204 int src_stride_y,
205 const uint8_t* src_u,
206 int src_stride_u,
207 const uint8_t* src_v,
208 int src_stride_v,
209 uint8_t* dst_argb,
210 int dst_stride_argb,
211 int width,
212 int height) {
213 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
214 src_stride_v, dst_argb, dst_stride_argb,
215 &kYuvH709Constants, width, height);
216 }
217
218 // Convert H420 to ABGR.
219 LIBYUV_API
H420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)220 int H420ToABGR(const uint8_t* src_y,
221 int src_stride_y,
222 const uint8_t* src_u,
223 int src_stride_u,
224 const uint8_t* src_v,
225 int src_stride_v,
226 uint8_t* dst_abgr,
227 int dst_stride_abgr,
228 int width,
229 int height) {
230 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
231 src_stride_v, // Swap U and V
232 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
233 &kYvuH709Constants, // Use Yvu matrix
234 width, height);
235 }
236
237 // Convert U420 to ARGB.
238 LIBYUV_API
U420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)239 int U420ToARGB(const uint8_t* src_y,
240 int src_stride_y,
241 const uint8_t* src_u,
242 int src_stride_u,
243 const uint8_t* src_v,
244 int src_stride_v,
245 uint8_t* dst_argb,
246 int dst_stride_argb,
247 int width,
248 int height) {
249 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
250 src_stride_v, dst_argb, dst_stride_argb,
251 &kYuv2020Constants, width, height);
252 }
253
254 // Convert U420 to ABGR.
255 LIBYUV_API
U420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)256 int U420ToABGR(const uint8_t* src_y,
257 int src_stride_y,
258 const uint8_t* src_u,
259 int src_stride_u,
260 const uint8_t* src_v,
261 int src_stride_v,
262 uint8_t* dst_abgr,
263 int dst_stride_abgr,
264 int width,
265 int height) {
266 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
267 src_stride_v, // Swap U and V
268 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
269 &kYvu2020Constants, // Use Yvu matrix
270 width, height);
271 }
272
273 // Convert I422 to ARGB with matrix
I422ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)274 static int I422ToARGBMatrix(const uint8_t* src_y,
275 int src_stride_y,
276 const uint8_t* src_u,
277 int src_stride_u,
278 const uint8_t* src_v,
279 int src_stride_v,
280 uint8_t* dst_argb,
281 int dst_stride_argb,
282 const struct YuvConstants* yuvconstants,
283 int width,
284 int height) {
285 int y;
286 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
287 const uint8_t* v_buf, uint8_t* rgb_buf,
288 const struct YuvConstants* yuvconstants, int width) =
289 I422ToARGBRow_C;
290 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
291 return -1;
292 }
293 // Negative height means invert the image.
294 if (height < 0) {
295 height = -height;
296 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
297 dst_stride_argb = -dst_stride_argb;
298 }
299 // Coalesce rows.
300 if (src_stride_y == width && src_stride_u * 2 == width &&
301 src_stride_v * 2 == width && dst_stride_argb == width * 4) {
302 width *= height;
303 height = 1;
304 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
305 }
306 #if defined(HAS_I422TOARGBROW_SSSE3)
307 if (TestCpuFlag(kCpuHasSSSE3)) {
308 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
309 if (IS_ALIGNED(width, 8)) {
310 I422ToARGBRow = I422ToARGBRow_SSSE3;
311 }
312 }
313 #endif
314 #if defined(HAS_I422TOARGBROW_AVX2)
315 if (TestCpuFlag(kCpuHasAVX2)) {
316 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
317 if (IS_ALIGNED(width, 16)) {
318 I422ToARGBRow = I422ToARGBRow_AVX2;
319 }
320 }
321 #endif
322 #if defined(HAS_I422TOARGBROW_NEON)
323 if (TestCpuFlag(kCpuHasNEON)) {
324 I422ToARGBRow = I422ToARGBRow_Any_NEON;
325 if (IS_ALIGNED(width, 8)) {
326 I422ToARGBRow = I422ToARGBRow_NEON;
327 }
328 }
329 #endif
330 #if defined(HAS_I422TOARGBROW_MSA)
331 if (TestCpuFlag(kCpuHasMSA)) {
332 I422ToARGBRow = I422ToARGBRow_Any_MSA;
333 if (IS_ALIGNED(width, 8)) {
334 I422ToARGBRow = I422ToARGBRow_MSA;
335 }
336 }
337 #endif
338 #if defined(HAS_I422TOARGBROW_MMI)
339 if (TestCpuFlag(kCpuHasMMI)) {
340 I422ToARGBRow = I422ToARGBRow_Any_MMI;
341 if (IS_ALIGNED(width, 4)) {
342 I422ToARGBRow = I422ToARGBRow_MMI;
343 }
344 }
345 #endif
346
347 for (y = 0; y < height; ++y) {
348 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
349 dst_argb += dst_stride_argb;
350 src_y += src_stride_y;
351 src_u += src_stride_u;
352 src_v += src_stride_v;
353 }
354 return 0;
355 }
356
357 // Convert I422 to ARGB.
358 LIBYUV_API
I422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)359 int I422ToARGB(const uint8_t* src_y,
360 int src_stride_y,
361 const uint8_t* src_u,
362 int src_stride_u,
363 const uint8_t* src_v,
364 int src_stride_v,
365 uint8_t* dst_argb,
366 int dst_stride_argb,
367 int width,
368 int height) {
369 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
370 src_stride_v, dst_argb, dst_stride_argb,
371 &kYuvI601Constants, width, height);
372 }
373
374 // Convert I422 to ABGR.
375 LIBYUV_API
I422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)376 int I422ToABGR(const uint8_t* src_y,
377 int src_stride_y,
378 const uint8_t* src_u,
379 int src_stride_u,
380 const uint8_t* src_v,
381 int src_stride_v,
382 uint8_t* dst_abgr,
383 int dst_stride_abgr,
384 int width,
385 int height) {
386 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
387 src_stride_v, // Swap U and V
388 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
389 &kYvuI601Constants, // Use Yvu matrix
390 width, height);
391 }
392
393 // Convert J422 to ARGB.
394 LIBYUV_API
J422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)395 int J422ToARGB(const uint8_t* src_y,
396 int src_stride_y,
397 const uint8_t* src_u,
398 int src_stride_u,
399 const uint8_t* src_v,
400 int src_stride_v,
401 uint8_t* dst_argb,
402 int dst_stride_argb,
403 int width,
404 int height) {
405 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
406 src_stride_v, dst_argb, dst_stride_argb,
407 &kYuvJPEGConstants, width, height);
408 }
409
410 // Convert J422 to ABGR.
411 LIBYUV_API
J422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)412 int J422ToABGR(const uint8_t* src_y,
413 int src_stride_y,
414 const uint8_t* src_u,
415 int src_stride_u,
416 const uint8_t* src_v,
417 int src_stride_v,
418 uint8_t* dst_abgr,
419 int dst_stride_abgr,
420 int width,
421 int height) {
422 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
423 src_stride_v, // Swap U and V
424 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
425 &kYvuJPEGConstants, // Use Yvu matrix
426 width, height);
427 }
428
429 // Convert H422 to ARGB.
430 LIBYUV_API
H422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)431 int H422ToARGB(const uint8_t* src_y,
432 int src_stride_y,
433 const uint8_t* src_u,
434 int src_stride_u,
435 const uint8_t* src_v,
436 int src_stride_v,
437 uint8_t* dst_argb,
438 int dst_stride_argb,
439 int width,
440 int height) {
441 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
442 src_stride_v, dst_argb, dst_stride_argb,
443 &kYuvH709Constants, width, height);
444 }
445
446 // Convert H422 to ABGR.
447 LIBYUV_API
H422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)448 int H422ToABGR(const uint8_t* src_y,
449 int src_stride_y,
450 const uint8_t* src_u,
451 int src_stride_u,
452 const uint8_t* src_v,
453 int src_stride_v,
454 uint8_t* dst_abgr,
455 int dst_stride_abgr,
456 int width,
457 int height) {
458 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
459 src_stride_v, // Swap U and V
460 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
461 &kYvuH709Constants, // Use Yvu matrix
462 width, height);
463 }
464
465 // Convert U422 to ARGB.
466 LIBYUV_API
U422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)467 int U422ToARGB(const uint8_t* src_y,
468 int src_stride_y,
469 const uint8_t* src_u,
470 int src_stride_u,
471 const uint8_t* src_v,
472 int src_stride_v,
473 uint8_t* dst_argb,
474 int dst_stride_argb,
475 int width,
476 int height) {
477 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
478 src_stride_v, dst_argb, dst_stride_argb,
479 &kYuv2020Constants, width, height);
480 }
481
482 // Convert U422 to ABGR.
483 LIBYUV_API
U422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)484 int U422ToABGR(const uint8_t* src_y,
485 int src_stride_y,
486 const uint8_t* src_u,
487 int src_stride_u,
488 const uint8_t* src_v,
489 int src_stride_v,
490 uint8_t* dst_abgr,
491 int dst_stride_abgr,
492 int width,
493 int height) {
494 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
495 src_stride_v, // Swap U and V
496 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
497 &kYvu2020Constants, // Use Yvu matrix
498 width, height);
499 }
500
501 // Convert I444 to ARGB with matrix
I444ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)502 static int I444ToARGBMatrix(const uint8_t* src_y,
503 int src_stride_y,
504 const uint8_t* src_u,
505 int src_stride_u,
506 const uint8_t* src_v,
507 int src_stride_v,
508 uint8_t* dst_argb,
509 int dst_stride_argb,
510 const struct YuvConstants* yuvconstants,
511 int width,
512 int height) {
513 int y;
514 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
515 const uint8_t* v_buf, uint8_t* rgb_buf,
516 const struct YuvConstants* yuvconstants, int width) =
517 I444ToARGBRow_C;
518 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
519 return -1;
520 }
521 // Negative height means invert the image.
522 if (height < 0) {
523 height = -height;
524 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
525 dst_stride_argb = -dst_stride_argb;
526 }
527 // Coalesce rows.
528 if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
529 dst_stride_argb == width * 4) {
530 width *= height;
531 height = 1;
532 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
533 }
534 #if defined(HAS_I444TOARGBROW_SSSE3)
535 if (TestCpuFlag(kCpuHasSSSE3)) {
536 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
537 if (IS_ALIGNED(width, 8)) {
538 I444ToARGBRow = I444ToARGBRow_SSSE3;
539 }
540 }
541 #endif
542 #if defined(HAS_I444TOARGBROW_AVX2)
543 if (TestCpuFlag(kCpuHasAVX2)) {
544 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
545 if (IS_ALIGNED(width, 16)) {
546 I444ToARGBRow = I444ToARGBRow_AVX2;
547 }
548 }
549 #endif
550 #if defined(HAS_I444TOARGBROW_NEON)
551 if (TestCpuFlag(kCpuHasNEON)) {
552 I444ToARGBRow = I444ToARGBRow_Any_NEON;
553 if (IS_ALIGNED(width, 8)) {
554 I444ToARGBRow = I444ToARGBRow_NEON;
555 }
556 }
557 #endif
558 #if defined(HAS_I444TOARGBROW_MSA)
559 if (TestCpuFlag(kCpuHasMSA)) {
560 I444ToARGBRow = I444ToARGBRow_Any_MSA;
561 if (IS_ALIGNED(width, 8)) {
562 I444ToARGBRow = I444ToARGBRow_MSA;
563 }
564 }
565 #endif
566 #if defined(HAS_I444TOARGBROW_MMI)
567 if (TestCpuFlag(kCpuHasMMI)) {
568 I444ToARGBRow = I444ToARGBRow_Any_MMI;
569 if (IS_ALIGNED(width, 4)) {
570 I444ToARGBRow = I444ToARGBRow_MMI;
571 }
572 }
573 #endif
574
575 for (y = 0; y < height; ++y) {
576 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
577 dst_argb += dst_stride_argb;
578 src_y += src_stride_y;
579 src_u += src_stride_u;
580 src_v += src_stride_v;
581 }
582 return 0;
583 }
584
585 // Convert I444 to ARGB.
586 LIBYUV_API
I444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)587 int I444ToARGB(const uint8_t* src_y,
588 int src_stride_y,
589 const uint8_t* src_u,
590 int src_stride_u,
591 const uint8_t* src_v,
592 int src_stride_v,
593 uint8_t* dst_argb,
594 int dst_stride_argb,
595 int width,
596 int height) {
597 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
598 src_stride_v, dst_argb, dst_stride_argb,
599 &kYuvI601Constants, width, height);
600 }
601
602 // Convert I444 to ABGR.
603 LIBYUV_API
I444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)604 int I444ToABGR(const uint8_t* src_y,
605 int src_stride_y,
606 const uint8_t* src_u,
607 int src_stride_u,
608 const uint8_t* src_v,
609 int src_stride_v,
610 uint8_t* dst_abgr,
611 int dst_stride_abgr,
612 int width,
613 int height) {
614 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
615 src_stride_v, // Swap U and V
616 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
617 &kYvuI601Constants, // Use Yvu matrix
618 width, height);
619 }
620
621 // Convert J444 to ARGB.
622 LIBYUV_API
J444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)623 int J444ToARGB(const uint8_t* src_y,
624 int src_stride_y,
625 const uint8_t* src_u,
626 int src_stride_u,
627 const uint8_t* src_v,
628 int src_stride_v,
629 uint8_t* dst_argb,
630 int dst_stride_argb,
631 int width,
632 int height) {
633 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
634 src_stride_v, dst_argb, dst_stride_argb,
635 &kYuvJPEGConstants, width, height);
636 }
637
638 // Convert J444 to ABGR.
639 LIBYUV_API
J444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)640 int J444ToABGR(const uint8_t* src_y,
641 int src_stride_y,
642 const uint8_t* src_u,
643 int src_stride_u,
644 const uint8_t* src_v,
645 int src_stride_v,
646 uint8_t* dst_abgr,
647 int dst_stride_abgr,
648 int width,
649 int height) {
650 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
651 src_stride_v, // Swap U and V
652 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
653 &kYvuJPEGConstants, // Use Yvu matrix
654 width, height);
655 }
656
657 // Convert H444 to ARGB.
658 LIBYUV_API
H444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)659 int H444ToARGB(const uint8_t* src_y,
660 int src_stride_y,
661 const uint8_t* src_u,
662 int src_stride_u,
663 const uint8_t* src_v,
664 int src_stride_v,
665 uint8_t* dst_argb,
666 int dst_stride_argb,
667 int width,
668 int height) {
669 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
670 src_stride_v, dst_argb, dst_stride_argb,
671 &kYuvH709Constants, width, height);
672 }
673
674 // Convert H444 to ABGR.
675 LIBYUV_API
H444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)676 int H444ToABGR(const uint8_t* src_y,
677 int src_stride_y,
678 const uint8_t* src_u,
679 int src_stride_u,
680 const uint8_t* src_v,
681 int src_stride_v,
682 uint8_t* dst_abgr,
683 int dst_stride_abgr,
684 int width,
685 int height) {
686 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
687 src_stride_v, // Swap U and V
688 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
689 &kYvuH709Constants, // Use Yvu matrix
690 width, height);
691 }
692
693 // Convert U444 to ARGB.
694 LIBYUV_API
U444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)695 int U444ToARGB(const uint8_t* src_y,
696 int src_stride_y,
697 const uint8_t* src_u,
698 int src_stride_u,
699 const uint8_t* src_v,
700 int src_stride_v,
701 uint8_t* dst_argb,
702 int dst_stride_argb,
703 int width,
704 int height) {
705 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
706 src_stride_v, dst_argb, dst_stride_argb,
707 &kYuv2020Constants, width, height);
708 }
709
710 // Convert U444 to ABGR.
711 LIBYUV_API
U444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)712 int U444ToABGR(const uint8_t* src_y,
713 int src_stride_y,
714 const uint8_t* src_u,
715 int src_stride_u,
716 const uint8_t* src_v,
717 int src_stride_v,
718 uint8_t* dst_abgr,
719 int dst_stride_abgr,
720 int width,
721 int height) {
722 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
723 src_stride_v, // Swap U and V
724 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
725 &kYvu2020Constants, // Use Yvu matrix
726 width, height);
727 }
728
729 // Convert 10 bit YUV to ARGB with matrix
730 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
731 // multiply 10 bit yuv into high bits to allow any number of bits.
I010ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)732 static int I010ToAR30Matrix(const uint16_t* src_y,
733 int src_stride_y,
734 const uint16_t* src_u,
735 int src_stride_u,
736 const uint16_t* src_v,
737 int src_stride_v,
738 uint8_t* dst_ar30,
739 int dst_stride_ar30,
740 const struct YuvConstants* yuvconstants,
741 int width,
742 int height) {
743 int y;
744 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
745 const uint16_t* v_buf, uint8_t* rgb_buf,
746 const struct YuvConstants* yuvconstants, int width) =
747 I210ToAR30Row_C;
748 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
749 return -1;
750 }
751 // Negative height means invert the image.
752 if (height < 0) {
753 height = -height;
754 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
755 dst_stride_ar30 = -dst_stride_ar30;
756 }
757 #if defined(HAS_I210TOAR30ROW_SSSE3)
758 if (TestCpuFlag(kCpuHasSSSE3)) {
759 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
760 if (IS_ALIGNED(width, 8)) {
761 I210ToAR30Row = I210ToAR30Row_SSSE3;
762 }
763 }
764 #endif
765 #if defined(HAS_I210TOAR30ROW_AVX2)
766 if (TestCpuFlag(kCpuHasAVX2)) {
767 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
768 if (IS_ALIGNED(width, 16)) {
769 I210ToAR30Row = I210ToAR30Row_AVX2;
770 }
771 }
772 #endif
773 for (y = 0; y < height; ++y) {
774 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
775 dst_ar30 += dst_stride_ar30;
776 src_y += src_stride_y;
777 if (y & 1) {
778 src_u += src_stride_u;
779 src_v += src_stride_v;
780 }
781 }
782 return 0;
783 }
784
785 // Convert I010 to AR30.
786 LIBYUV_API
I010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)787 int I010ToAR30(const uint16_t* src_y,
788 int src_stride_y,
789 const uint16_t* src_u,
790 int src_stride_u,
791 const uint16_t* src_v,
792 int src_stride_v,
793 uint8_t* dst_ar30,
794 int dst_stride_ar30,
795 int width,
796 int height) {
797 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
798 src_stride_v, dst_ar30, dst_stride_ar30,
799 &kYuvI601Constants, width, height);
800 }
801
802 // Convert H010 to AR30.
803 LIBYUV_API
H010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)804 int H010ToAR30(const uint16_t* src_y,
805 int src_stride_y,
806 const uint16_t* src_u,
807 int src_stride_u,
808 const uint16_t* src_v,
809 int src_stride_v,
810 uint8_t* dst_ar30,
811 int dst_stride_ar30,
812 int width,
813 int height) {
814 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
815 src_stride_v, dst_ar30, dst_stride_ar30,
816 &kYuvH709Constants, width, height);
817 }
818
819 // Convert U010 to AR30.
820 LIBYUV_API
U010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)821 int U010ToAR30(const uint16_t* src_y,
822 int src_stride_y,
823 const uint16_t* src_u,
824 int src_stride_u,
825 const uint16_t* src_v,
826 int src_stride_v,
827 uint8_t* dst_ar30,
828 int dst_stride_ar30,
829 int width,
830 int height) {
831 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
832 src_stride_v, dst_ar30, dst_stride_ar30,
833 &kYuv2020Constants, width, height);
834 }
835
836 // Convert I010 to AB30.
837 LIBYUV_API
I010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)838 int I010ToAB30(const uint16_t* src_y,
839 int src_stride_y,
840 const uint16_t* src_u,
841 int src_stride_u,
842 const uint16_t* src_v,
843 int src_stride_v,
844 uint8_t* dst_ab30,
845 int dst_stride_ab30,
846 int width,
847 int height) {
848 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
849 src_stride_u, dst_ab30, dst_stride_ab30,
850 &kYvuI601Constants, width, height);
851 }
852
853 // Convert H010 to AB30.
854 LIBYUV_API
H010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)855 int H010ToAB30(const uint16_t* src_y,
856 int src_stride_y,
857 const uint16_t* src_u,
858 int src_stride_u,
859 const uint16_t* src_v,
860 int src_stride_v,
861 uint8_t* dst_ab30,
862 int dst_stride_ab30,
863 int width,
864 int height) {
865 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
866 src_stride_u, dst_ab30, dst_stride_ab30,
867 &kYvuH709Constants, width, height);
868 }
869
870 // Convert U010 to AB30.
871 LIBYUV_API
U010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)872 int U010ToAB30(const uint16_t* src_y,
873 int src_stride_y,
874 const uint16_t* src_u,
875 int src_stride_u,
876 const uint16_t* src_v,
877 int src_stride_v,
878 uint8_t* dst_ab30,
879 int dst_stride_ab30,
880 int width,
881 int height) {
882 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
883 src_stride_u, dst_ab30, dst_stride_ab30,
884 &kYuv2020Constants, width, height);
885 }
886
887 // Convert 10 bit YUV to ARGB with matrix
888 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
889 // multiply 10 bit yuv into high bits to allow any number of bits.
I210ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)890 static int I210ToAR30Matrix(const uint16_t* src_y,
891 int src_stride_y,
892 const uint16_t* src_u,
893 int src_stride_u,
894 const uint16_t* src_v,
895 int src_stride_v,
896 uint8_t* dst_ar30,
897 int dst_stride_ar30,
898 const struct YuvConstants* yuvconstants,
899 int width,
900 int height) {
901 int y;
902 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
903 const uint16_t* v_buf, uint8_t* rgb_buf,
904 const struct YuvConstants* yuvconstants, int width) =
905 I210ToAR30Row_C;
906 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
907 return -1;
908 }
909 // Negative height means invert the image.
910 if (height < 0) {
911 height = -height;
912 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
913 dst_stride_ar30 = -dst_stride_ar30;
914 }
915 #if defined(HAS_I210TOAR30ROW_SSSE3)
916 if (TestCpuFlag(kCpuHasSSSE3)) {
917 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
918 if (IS_ALIGNED(width, 8)) {
919 I210ToAR30Row = I210ToAR30Row_SSSE3;
920 }
921 }
922 #endif
923 #if defined(HAS_I210TOAR30ROW_AVX2)
924 if (TestCpuFlag(kCpuHasAVX2)) {
925 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
926 if (IS_ALIGNED(width, 16)) {
927 I210ToAR30Row = I210ToAR30Row_AVX2;
928 }
929 }
930 #endif
931 for (y = 0; y < height; ++y) {
932 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
933 dst_ar30 += dst_stride_ar30;
934 src_y += src_stride_y;
935 src_u += src_stride_u;
936 src_v += src_stride_v;
937 }
938 return 0;
939 }
940
941 // Convert I210 to AR30.
942 LIBYUV_API
I210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)943 int I210ToAR30(const uint16_t* src_y,
944 int src_stride_y,
945 const uint16_t* src_u,
946 int src_stride_u,
947 const uint16_t* src_v,
948 int src_stride_v,
949 uint8_t* dst_ar30,
950 int dst_stride_ar30,
951 int width,
952 int height) {
953 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
954 src_stride_v, dst_ar30, dst_stride_ar30,
955 &kYuvI601Constants, width, height);
956 }
957
958 // Convert H210 to AR30.
959 LIBYUV_API
H210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)960 int H210ToAR30(const uint16_t* src_y,
961 int src_stride_y,
962 const uint16_t* src_u,
963 int src_stride_u,
964 const uint16_t* src_v,
965 int src_stride_v,
966 uint8_t* dst_ar30,
967 int dst_stride_ar30,
968 int width,
969 int height) {
970 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
971 src_stride_v, dst_ar30, dst_stride_ar30,
972 &kYuvH709Constants, width, height);
973 }
974
975 // Convert U210 to AR30.
976 LIBYUV_API
U210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)977 int U210ToAR30(const uint16_t* src_y,
978 int src_stride_y,
979 const uint16_t* src_u,
980 int src_stride_u,
981 const uint16_t* src_v,
982 int src_stride_v,
983 uint8_t* dst_ar30,
984 int dst_stride_ar30,
985 int width,
986 int height) {
987 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
988 src_stride_v, dst_ar30, dst_stride_ar30,
989 &kYuv2020Constants, width, height);
990 }
991
992 // Convert I210 to AB30.
993 LIBYUV_API
I210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)994 int I210ToAB30(const uint16_t* src_y,
995 int src_stride_y,
996 const uint16_t* src_u,
997 int src_stride_u,
998 const uint16_t* src_v,
999 int src_stride_v,
1000 uint8_t* dst_ab30,
1001 int dst_stride_ab30,
1002 int width,
1003 int height) {
1004 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1005 src_stride_u, dst_ab30, dst_stride_ab30,
1006 &kYvuI601Constants, width, height);
1007 }
1008
1009 // Convert H210 to AB30.
1010 LIBYUV_API
H210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1011 int H210ToAB30(const uint16_t* src_y,
1012 int src_stride_y,
1013 const uint16_t* src_u,
1014 int src_stride_u,
1015 const uint16_t* src_v,
1016 int src_stride_v,
1017 uint8_t* dst_ab30,
1018 int dst_stride_ab30,
1019 int width,
1020 int height) {
1021 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1022 src_stride_u, dst_ab30, dst_stride_ab30,
1023 &kYvuH709Constants, width, height);
1024 }
1025
1026 // Convert U210 to AB30.
1027 LIBYUV_API
U210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1028 int U210ToAB30(const uint16_t* src_y,
1029 int src_stride_y,
1030 const uint16_t* src_u,
1031 int src_stride_u,
1032 const uint16_t* src_v,
1033 int src_stride_v,
1034 uint8_t* dst_ab30,
1035 int dst_stride_ab30,
1036 int width,
1037 int height) {
1038 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1039 src_stride_u, dst_ab30, dst_stride_ab30,
1040 &kYuv2020Constants, width, height);
1041 }
1042
1043 // Convert 10 bit YUV to ARGB with matrix
I010ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1044 static int I010ToARGBMatrix(const uint16_t* src_y,
1045 int src_stride_y,
1046 const uint16_t* src_u,
1047 int src_stride_u,
1048 const uint16_t* src_v,
1049 int src_stride_v,
1050 uint8_t* dst_argb,
1051 int dst_stride_argb,
1052 const struct YuvConstants* yuvconstants,
1053 int width,
1054 int height) {
1055 int y;
1056 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1057 const uint16_t* v_buf, uint8_t* rgb_buf,
1058 const struct YuvConstants* yuvconstants, int width) =
1059 I210ToARGBRow_C;
1060 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1061 return -1;
1062 }
1063 // Negative height means invert the image.
1064 if (height < 0) {
1065 height = -height;
1066 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1067 dst_stride_argb = -dst_stride_argb;
1068 }
1069 #if defined(HAS_I210TOARGBROW_SSSE3)
1070 if (TestCpuFlag(kCpuHasSSSE3)) {
1071 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1072 if (IS_ALIGNED(width, 8)) {
1073 I210ToARGBRow = I210ToARGBRow_SSSE3;
1074 }
1075 }
1076 #endif
1077 #if defined(HAS_I210TOARGBROW_AVX2)
1078 if (TestCpuFlag(kCpuHasAVX2)) {
1079 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1080 if (IS_ALIGNED(width, 16)) {
1081 I210ToARGBRow = I210ToARGBRow_AVX2;
1082 }
1083 }
1084 #endif
1085 #if defined(HAS_I210TOARGBROW_MMI)
1086 if (TestCpuFlag(kCpuHasMMI)) {
1087 I210ToARGBRow = I210ToARGBRow_Any_MMI;
1088 if (IS_ALIGNED(width, 4)) {
1089 I210ToARGBRow = I210ToARGBRow_MMI;
1090 }
1091 }
1092 #endif
1093 for (y = 0; y < height; ++y) {
1094 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1095 dst_argb += dst_stride_argb;
1096 src_y += src_stride_y;
1097 if (y & 1) {
1098 src_u += src_stride_u;
1099 src_v += src_stride_v;
1100 }
1101 }
1102 return 0;
1103 }
1104
1105 // Convert I010 to ARGB.
1106 LIBYUV_API
I010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1107 int I010ToARGB(const uint16_t* src_y,
1108 int src_stride_y,
1109 const uint16_t* src_u,
1110 int src_stride_u,
1111 const uint16_t* src_v,
1112 int src_stride_v,
1113 uint8_t* dst_argb,
1114 int dst_stride_argb,
1115 int width,
1116 int height) {
1117 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1118 src_stride_v, dst_argb, dst_stride_argb,
1119 &kYuvI601Constants, width, height);
1120 }
1121
1122 // Convert I010 to ABGR.
1123 LIBYUV_API
I010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1124 int I010ToABGR(const uint16_t* src_y,
1125 int src_stride_y,
1126 const uint16_t* src_u,
1127 int src_stride_u,
1128 const uint16_t* src_v,
1129 int src_stride_v,
1130 uint8_t* dst_abgr,
1131 int dst_stride_abgr,
1132 int width,
1133 int height) {
1134 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1135 src_stride_v, // Swap U and V
1136 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1137 &kYvuI601Constants, // Use Yvu matrix
1138 width, height);
1139 }
1140
1141 // Convert H010 to ARGB.
1142 LIBYUV_API
H010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1143 int H010ToARGB(const uint16_t* src_y,
1144 int src_stride_y,
1145 const uint16_t* src_u,
1146 int src_stride_u,
1147 const uint16_t* src_v,
1148 int src_stride_v,
1149 uint8_t* dst_argb,
1150 int dst_stride_argb,
1151 int width,
1152 int height) {
1153 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1154 src_stride_v, dst_argb, dst_stride_argb,
1155 &kYuvH709Constants, width, height);
1156 }
1157
1158 // Convert H010 to ABGR.
1159 LIBYUV_API
H010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1160 int H010ToABGR(const uint16_t* src_y,
1161 int src_stride_y,
1162 const uint16_t* src_u,
1163 int src_stride_u,
1164 const uint16_t* src_v,
1165 int src_stride_v,
1166 uint8_t* dst_abgr,
1167 int dst_stride_abgr,
1168 int width,
1169 int height) {
1170 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1171 src_stride_v, // Swap U and V
1172 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1173 &kYvuH709Constants, // Use Yvu matrix
1174 width, height);
1175 }
1176
1177 // Convert U010 to ARGB.
1178 LIBYUV_API
U010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1179 int U010ToARGB(const uint16_t* src_y,
1180 int src_stride_y,
1181 const uint16_t* src_u,
1182 int src_stride_u,
1183 const uint16_t* src_v,
1184 int src_stride_v,
1185 uint8_t* dst_argb,
1186 int dst_stride_argb,
1187 int width,
1188 int height) {
1189 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1190 src_stride_v, dst_argb, dst_stride_argb,
1191 &kYuv2020Constants, width, height);
1192 }
1193
1194 // Convert U010 to ABGR.
1195 LIBYUV_API
U010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1196 int U010ToABGR(const uint16_t* src_y,
1197 int src_stride_y,
1198 const uint16_t* src_u,
1199 int src_stride_u,
1200 const uint16_t* src_v,
1201 int src_stride_v,
1202 uint8_t* dst_abgr,
1203 int dst_stride_abgr,
1204 int width,
1205 int height) {
1206 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1207 src_stride_v, // Swap U and V
1208 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1209 &kYvu2020Constants, // Use Yvu matrix
1210 width, height);
1211 }
1212
1213 // Convert 10 bit 422 YUV to ARGB with matrix
I210ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1214 static int I210ToARGBMatrix(const uint16_t* src_y,
1215 int src_stride_y,
1216 const uint16_t* src_u,
1217 int src_stride_u,
1218 const uint16_t* src_v,
1219 int src_stride_v,
1220 uint8_t* dst_argb,
1221 int dst_stride_argb,
1222 const struct YuvConstants* yuvconstants,
1223 int width,
1224 int height) {
1225 int y;
1226 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1227 const uint16_t* v_buf, uint8_t* rgb_buf,
1228 const struct YuvConstants* yuvconstants, int width) =
1229 I210ToARGBRow_C;
1230 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1231 return -1;
1232 }
1233 // Negative height means invert the image.
1234 if (height < 0) {
1235 height = -height;
1236 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1237 dst_stride_argb = -dst_stride_argb;
1238 }
1239 #if defined(HAS_I210TOARGBROW_SSSE3)
1240 if (TestCpuFlag(kCpuHasSSSE3)) {
1241 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1242 if (IS_ALIGNED(width, 8)) {
1243 I210ToARGBRow = I210ToARGBRow_SSSE3;
1244 }
1245 }
1246 #endif
1247 #if defined(HAS_I210TOARGBROW_AVX2)
1248 if (TestCpuFlag(kCpuHasAVX2)) {
1249 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1250 if (IS_ALIGNED(width, 16)) {
1251 I210ToARGBRow = I210ToARGBRow_AVX2;
1252 }
1253 }
1254 #endif
1255 #if defined(HAS_I210TOARGBROW_MMI)
1256 if (TestCpuFlag(kCpuHasMMI)) {
1257 I210ToARGBRow = I210ToARGBRow_Any_MMI;
1258 if (IS_ALIGNED(width, 4)) {
1259 I210ToARGBRow = I210ToARGBRow_MMI;
1260 }
1261 }
1262 #endif
1263 for (y = 0; y < height; ++y) {
1264 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1265 dst_argb += dst_stride_argb;
1266 src_y += src_stride_y;
1267 src_u += src_stride_u;
1268 src_v += src_stride_v;
1269 }
1270 return 0;
1271 }
1272
1273
1274
1275
1276 // Convert I210 to ARGB.
1277 LIBYUV_API
I210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1278 int I210ToARGB(const uint16_t* src_y,
1279 int src_stride_y,
1280 const uint16_t* src_u,
1281 int src_stride_u,
1282 const uint16_t* src_v,
1283 int src_stride_v,
1284 uint8_t* dst_argb,
1285 int dst_stride_argb,
1286 int width,
1287 int height) {
1288 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1289 src_stride_v, dst_argb, dst_stride_argb,
1290 &kYuvI601Constants, width, height);
1291 }
1292
1293 // Convert I210 to ABGR.
1294 LIBYUV_API
I210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1295 int I210ToABGR(const uint16_t* src_y,
1296 int src_stride_y,
1297 const uint16_t* src_u,
1298 int src_stride_u,
1299 const uint16_t* src_v,
1300 int src_stride_v,
1301 uint8_t* dst_abgr,
1302 int dst_stride_abgr,
1303 int width,
1304 int height) {
1305 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1306 src_stride_v, // Swap U and V
1307 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1308 &kYvuI601Constants, // Use Yvu matrix
1309 width, height);
1310 }
1311
1312 // Convert H210 to ARGB.
1313 LIBYUV_API
H210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1314 int H210ToARGB(const uint16_t* src_y,
1315 int src_stride_y,
1316 const uint16_t* src_u,
1317 int src_stride_u,
1318 const uint16_t* src_v,
1319 int src_stride_v,
1320 uint8_t* dst_argb,
1321 int dst_stride_argb,
1322 int width,
1323 int height) {
1324 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1325 src_stride_v, dst_argb, dst_stride_argb,
1326 &kYuvH709Constants, width, height);
1327 }
1328
1329 // Convert H210 to ABGR.
1330 LIBYUV_API
H210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1331 int H210ToABGR(const uint16_t* src_y,
1332 int src_stride_y,
1333 const uint16_t* src_u,
1334 int src_stride_u,
1335 const uint16_t* src_v,
1336 int src_stride_v,
1337 uint8_t* dst_abgr,
1338 int dst_stride_abgr,
1339 int width,
1340 int height) {
1341 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1342 src_stride_v, // Swap U and V
1343 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1344 &kYvuH709Constants, // Use Yvu matrix
1345 width, height);
1346 }
1347
1348 // Convert U210 to ARGB.
1349 LIBYUV_API
U210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1350 int U210ToARGB(const uint16_t* src_y,
1351 int src_stride_y,
1352 const uint16_t* src_u,
1353 int src_stride_u,
1354 const uint16_t* src_v,
1355 int src_stride_v,
1356 uint8_t* dst_argb,
1357 int dst_stride_argb,
1358 int width,
1359 int height) {
1360 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1361 src_stride_v, dst_argb, dst_stride_argb,
1362 &kYuv2020Constants, width, height);
1363 }
1364
1365 // Convert U210 to ABGR.
1366 LIBYUV_API
U210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1367 int U210ToABGR(const uint16_t* src_y,
1368 int src_stride_y,
1369 const uint16_t* src_u,
1370 int src_stride_u,
1371 const uint16_t* src_v,
1372 int src_stride_v,
1373 uint8_t* dst_abgr,
1374 int dst_stride_abgr,
1375 int width,
1376 int height) {
1377 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1378 src_stride_v, // Swap U and V
1379 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1380 &kYvu2020Constants, // Use Yvu matrix
1381 width, height);
1382 }
1383
1384 // Convert I420 with Alpha to preattenuated ARGB.
I420AlphaToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)1385 static int I420AlphaToARGBMatrix(const uint8_t* src_y,
1386 int src_stride_y,
1387 const uint8_t* src_u,
1388 int src_stride_u,
1389 const uint8_t* src_v,
1390 int src_stride_v,
1391 const uint8_t* src_a,
1392 int src_stride_a,
1393 uint8_t* dst_argb,
1394 int dst_stride_argb,
1395 const struct YuvConstants* yuvconstants,
1396 int width,
1397 int height,
1398 int attenuate) {
1399 int y;
1400 void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1401 const uint8_t* v_buf, const uint8_t* a_buf,
1402 uint8_t* dst_argb,
1403 const struct YuvConstants* yuvconstants,
1404 int width) = I422AlphaToARGBRow_C;
1405 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
1406 int width) = ARGBAttenuateRow_C;
1407 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1408 return -1;
1409 }
1410 // Negative height means invert the image.
1411 if (height < 0) {
1412 height = -height;
1413 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1414 dst_stride_argb = -dst_stride_argb;
1415 }
1416 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
1417 if (TestCpuFlag(kCpuHasSSSE3)) {
1418 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
1419 if (IS_ALIGNED(width, 8)) {
1420 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
1421 }
1422 }
1423 #endif
1424 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
1425 if (TestCpuFlag(kCpuHasAVX2)) {
1426 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
1427 if (IS_ALIGNED(width, 16)) {
1428 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
1429 }
1430 }
1431 #endif
1432 #if defined(HAS_I422ALPHATOARGBROW_NEON)
1433 if (TestCpuFlag(kCpuHasNEON)) {
1434 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
1435 if (IS_ALIGNED(width, 8)) {
1436 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
1437 }
1438 }
1439 #endif
1440 #if defined(HAS_I422ALPHATOARGBROW_MSA)
1441 if (TestCpuFlag(kCpuHasMSA)) {
1442 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
1443 if (IS_ALIGNED(width, 8)) {
1444 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
1445 }
1446 }
1447 #endif
1448 #if defined(HAS_I422ALPHATOARGBROW_MMI)
1449 if (TestCpuFlag(kCpuHasMMI)) {
1450 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MMI;
1451 if (IS_ALIGNED(width, 4)) {
1452 I422AlphaToARGBRow = I422AlphaToARGBRow_MMI;
1453 }
1454 }
1455 #endif
1456 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
1457 if (TestCpuFlag(kCpuHasSSSE3)) {
1458 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1459 if (IS_ALIGNED(width, 4)) {
1460 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1461 }
1462 }
1463 #endif
1464 #if defined(HAS_ARGBATTENUATEROW_AVX2)
1465 if (TestCpuFlag(kCpuHasAVX2)) {
1466 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1467 if (IS_ALIGNED(width, 8)) {
1468 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1469 }
1470 }
1471 #endif
1472 #if defined(HAS_ARGBATTENUATEROW_NEON)
1473 if (TestCpuFlag(kCpuHasNEON)) {
1474 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1475 if (IS_ALIGNED(width, 8)) {
1476 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1477 }
1478 }
1479 #endif
1480 #if defined(HAS_ARGBATTENUATEROW_MSA)
1481 if (TestCpuFlag(kCpuHasMSA)) {
1482 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
1483 if (IS_ALIGNED(width, 8)) {
1484 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
1485 }
1486 }
1487 #endif
1488 #if defined(HAS_ARGBATTENUATEROW_MMI)
1489 if (TestCpuFlag(kCpuHasMMI)) {
1490 ARGBAttenuateRow = ARGBAttenuateRow_Any_MMI;
1491 if (IS_ALIGNED(width, 2)) {
1492 ARGBAttenuateRow = ARGBAttenuateRow_MMI;
1493 }
1494 }
1495 #endif
1496
1497 for (y = 0; y < height; ++y) {
1498 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
1499 width);
1500 if (attenuate) {
1501 ARGBAttenuateRow(dst_argb, dst_argb, width);
1502 }
1503 dst_argb += dst_stride_argb;
1504 src_a += src_stride_a;
1505 src_y += src_stride_y;
1506 if (y & 1) {
1507 src_u += src_stride_u;
1508 src_v += src_stride_v;
1509 }
1510 }
1511 return 0;
1512 }
1513
1514 // Convert I420 with Alpha to ARGB.
1515 LIBYUV_API
I420AlphaToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,int width,int height,int attenuate)1516 int I420AlphaToARGB(const uint8_t* src_y,
1517 int src_stride_y,
1518 const uint8_t* src_u,
1519 int src_stride_u,
1520 const uint8_t* src_v,
1521 int src_stride_v,
1522 const uint8_t* src_a,
1523 int src_stride_a,
1524 uint8_t* dst_argb,
1525 int dst_stride_argb,
1526 int width,
1527 int height,
1528 int attenuate) {
1529 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1530 src_stride_v, src_a, src_stride_a, dst_argb,
1531 dst_stride_argb, &kYuvI601Constants, width,
1532 height, attenuate);
1533 }
1534
1535 // Convert I420 with Alpha to ABGR.
1536 LIBYUV_API
I420AlphaToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)1537 int I420AlphaToABGR(const uint8_t* src_y,
1538 int src_stride_y,
1539 const uint8_t* src_u,
1540 int src_stride_u,
1541 const uint8_t* src_v,
1542 int src_stride_v,
1543 const uint8_t* src_a,
1544 int src_stride_a,
1545 uint8_t* dst_abgr,
1546 int dst_stride_abgr,
1547 int width,
1548 int height,
1549 int attenuate) {
1550 return I420AlphaToARGBMatrix(
1551 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
1552 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
1553 &kYvuI601Constants, // Use Yvu matrix
1554 width, height, attenuate);
1555 }
1556
1557 // Convert I400 to ARGB.
1558 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1559 int I400ToARGB(const uint8_t* src_y,
1560 int src_stride_y,
1561 uint8_t* dst_argb,
1562 int dst_stride_argb,
1563 int width,
1564 int height) {
1565 int y;
1566 void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf, int width) =
1567 I400ToARGBRow_C;
1568 if (!src_y || !dst_argb || width <= 0 || height == 0) {
1569 return -1;
1570 }
1571 // Negative height means invert the image.
1572 if (height < 0) {
1573 height = -height;
1574 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1575 dst_stride_argb = -dst_stride_argb;
1576 }
1577 // Coalesce rows.
1578 if (src_stride_y == width && dst_stride_argb == width * 4) {
1579 width *= height;
1580 height = 1;
1581 src_stride_y = dst_stride_argb = 0;
1582 }
1583 #if defined(HAS_I400TOARGBROW_SSE2)
1584 if (TestCpuFlag(kCpuHasSSE2)) {
1585 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
1586 if (IS_ALIGNED(width, 8)) {
1587 I400ToARGBRow = I400ToARGBRow_SSE2;
1588 }
1589 }
1590 #endif
1591 #if defined(HAS_I400TOARGBROW_AVX2)
1592 if (TestCpuFlag(kCpuHasAVX2)) {
1593 I400ToARGBRow = I400ToARGBRow_Any_AVX2;
1594 if (IS_ALIGNED(width, 16)) {
1595 I400ToARGBRow = I400ToARGBRow_AVX2;
1596 }
1597 }
1598 #endif
1599 #if defined(HAS_I400TOARGBROW_NEON)
1600 if (TestCpuFlag(kCpuHasNEON)) {
1601 I400ToARGBRow = I400ToARGBRow_Any_NEON;
1602 if (IS_ALIGNED(width, 8)) {
1603 I400ToARGBRow = I400ToARGBRow_NEON;
1604 }
1605 }
1606 #endif
1607 #if defined(HAS_I400TOARGBROW_MSA)
1608 if (TestCpuFlag(kCpuHasMSA)) {
1609 I400ToARGBRow = I400ToARGBRow_Any_MSA;
1610 if (IS_ALIGNED(width, 16)) {
1611 I400ToARGBRow = I400ToARGBRow_MSA;
1612 }
1613 }
1614 #endif
1615 #if defined(HAS_I400TOARGBROW_MMI)
1616 if (TestCpuFlag(kCpuHasMMI)) {
1617 I400ToARGBRow = I400ToARGBRow_Any_MMI;
1618 if (IS_ALIGNED(width, 8)) {
1619 I400ToARGBRow = I400ToARGBRow_MMI;
1620 }
1621 }
1622 #endif
1623
1624 for (y = 0; y < height; ++y) {
1625 I400ToARGBRow(src_y, dst_argb, width);
1626 dst_argb += dst_stride_argb;
1627 src_y += src_stride_y;
1628 }
1629 return 0;
1630 }
1631
1632 // Convert J400 to ARGB.
1633 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1634 int J400ToARGB(const uint8_t* src_y,
1635 int src_stride_y,
1636 uint8_t* dst_argb,
1637 int dst_stride_argb,
1638 int width,
1639 int height) {
1640 int y;
1641 void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
1642 J400ToARGBRow_C;
1643 if (!src_y || !dst_argb || width <= 0 || height == 0) {
1644 return -1;
1645 }
1646 // Negative height means invert the image.
1647 if (height < 0) {
1648 height = -height;
1649 src_y = src_y + (height - 1) * src_stride_y;
1650 src_stride_y = -src_stride_y;
1651 }
1652 // Coalesce rows.
1653 if (src_stride_y == width && dst_stride_argb == width * 4) {
1654 width *= height;
1655 height = 1;
1656 src_stride_y = dst_stride_argb = 0;
1657 }
1658 #if defined(HAS_J400TOARGBROW_SSE2)
1659 if (TestCpuFlag(kCpuHasSSE2)) {
1660 J400ToARGBRow = J400ToARGBRow_Any_SSE2;
1661 if (IS_ALIGNED(width, 8)) {
1662 J400ToARGBRow = J400ToARGBRow_SSE2;
1663 }
1664 }
1665 #endif
1666 #if defined(HAS_J400TOARGBROW_AVX2)
1667 if (TestCpuFlag(kCpuHasAVX2)) {
1668 J400ToARGBRow = J400ToARGBRow_Any_AVX2;
1669 if (IS_ALIGNED(width, 16)) {
1670 J400ToARGBRow = J400ToARGBRow_AVX2;
1671 }
1672 }
1673 #endif
1674 #if defined(HAS_J400TOARGBROW_NEON)
1675 if (TestCpuFlag(kCpuHasNEON)) {
1676 J400ToARGBRow = J400ToARGBRow_Any_NEON;
1677 if (IS_ALIGNED(width, 8)) {
1678 J400ToARGBRow = J400ToARGBRow_NEON;
1679 }
1680 }
1681 #endif
1682 #if defined(HAS_J400TOARGBROW_MSA)
1683 if (TestCpuFlag(kCpuHasMSA)) {
1684 J400ToARGBRow = J400ToARGBRow_Any_MSA;
1685 if (IS_ALIGNED(width, 16)) {
1686 J400ToARGBRow = J400ToARGBRow_MSA;
1687 }
1688 }
1689 #endif
1690 #if defined(HAS_J400TOARGBROW_MMI)
1691 if (TestCpuFlag(kCpuHasMMI)) {
1692 J400ToARGBRow = J400ToARGBRow_Any_MMI;
1693 if (IS_ALIGNED(width, 4)) {
1694 J400ToARGBRow = J400ToARGBRow_MMI;
1695 }
1696 }
1697 #endif
1698 for (y = 0; y < height; ++y) {
1699 J400ToARGBRow(src_y, dst_argb, width);
1700 src_y += src_stride_y;
1701 dst_argb += dst_stride_argb;
1702 }
1703 return 0;
1704 }
1705
1706 // Shuffle table for converting BGRA to ARGB.
1707 static const uvec8 kShuffleMaskBGRAToARGB = {
1708 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
1709
1710 // Shuffle table for converting ABGR to ARGB.
1711 static const uvec8 kShuffleMaskABGRToARGB = {
1712 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
1713
1714 // Shuffle table for converting RGBA to ARGB.
1715 static const uvec8 kShuffleMaskRGBAToARGB = {
1716 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
1717
1718 // Convert BGRA to ARGB.
1719 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1720 int BGRAToARGB(const uint8_t* src_bgra,
1721 int src_stride_bgra,
1722 uint8_t* dst_argb,
1723 int dst_stride_argb,
1724 int width,
1725 int height) {
1726 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1727 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1728 }
1729
1730 // Convert ARGB to BGRA (same as BGRAToARGB).
1731 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1732 int ARGBToBGRA(const uint8_t* src_bgra,
1733 int src_stride_bgra,
1734 uint8_t* dst_argb,
1735 int dst_stride_argb,
1736 int width,
1737 int height) {
1738 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1739 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1740 }
1741
1742 // Convert ABGR to ARGB.
1743 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1744 int ABGRToARGB(const uint8_t* src_abgr,
1745 int src_stride_abgr,
1746 uint8_t* dst_argb,
1747 int dst_stride_argb,
1748 int width,
1749 int height) {
1750 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1751 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1752 }
1753
1754 // Convert ARGB to ABGR to (same as ABGRToARGB).
1755 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1756 int ARGBToABGR(const uint8_t* src_abgr,
1757 int src_stride_abgr,
1758 uint8_t* dst_argb,
1759 int dst_stride_argb,
1760 int width,
1761 int height) {
1762 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1763 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1764 }
1765
1766 // Convert RGBA to ARGB.
1767 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1768 int RGBAToARGB(const uint8_t* src_rgba,
1769 int src_stride_rgba,
1770 uint8_t* dst_argb,
1771 int dst_stride_argb,
1772 int width,
1773 int height) {
1774 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
1775 (const uint8_t*)(&kShuffleMaskRGBAToARGB), width, height);
1776 }
1777
1778 // Convert RGB24 to ARGB.
1779 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1780 int RGB24ToARGB(const uint8_t* src_rgb24,
1781 int src_stride_rgb24,
1782 uint8_t* dst_argb,
1783 int dst_stride_argb,
1784 int width,
1785 int height) {
1786 int y;
1787 void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1788 RGB24ToARGBRow_C;
1789 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
1790 return -1;
1791 }
1792 // Negative height means invert the image.
1793 if (height < 0) {
1794 height = -height;
1795 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
1796 src_stride_rgb24 = -src_stride_rgb24;
1797 }
1798 // Coalesce rows.
1799 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
1800 width *= height;
1801 height = 1;
1802 src_stride_rgb24 = dst_stride_argb = 0;
1803 }
1804 #if defined(HAS_RGB24TOARGBROW_SSSE3)
1805 if (TestCpuFlag(kCpuHasSSSE3)) {
1806 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
1807 if (IS_ALIGNED(width, 16)) {
1808 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
1809 }
1810 }
1811 #endif
1812 #if defined(HAS_RGB24TOARGBROW_NEON)
1813 if (TestCpuFlag(kCpuHasNEON)) {
1814 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
1815 if (IS_ALIGNED(width, 8)) {
1816 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
1817 }
1818 }
1819 #endif
1820 #if defined(HAS_RGB24TOARGBROW_MSA)
1821 if (TestCpuFlag(kCpuHasMSA)) {
1822 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
1823 if (IS_ALIGNED(width, 16)) {
1824 RGB24ToARGBRow = RGB24ToARGBRow_MSA;
1825 }
1826 }
1827 #endif
1828 #if defined(HAS_RGB24TOARGBROW_MMI)
1829 if (TestCpuFlag(kCpuHasMMI)) {
1830 RGB24ToARGBRow = RGB24ToARGBRow_Any_MMI;
1831 if (IS_ALIGNED(width, 4)) {
1832 RGB24ToARGBRow = RGB24ToARGBRow_MMI;
1833 }
1834 }
1835 #endif
1836
1837 for (y = 0; y < height; ++y) {
1838 RGB24ToARGBRow(src_rgb24, dst_argb, width);
1839 src_rgb24 += src_stride_rgb24;
1840 dst_argb += dst_stride_argb;
1841 }
1842 return 0;
1843 }
1844
1845 // Convert RAW to ARGB.
1846 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1847 int RAWToARGB(const uint8_t* src_raw,
1848 int src_stride_raw,
1849 uint8_t* dst_argb,
1850 int dst_stride_argb,
1851 int width,
1852 int height) {
1853 int y;
1854 void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1855 RAWToARGBRow_C;
1856 if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1857 return -1;
1858 }
1859 // Negative height means invert the image.
1860 if (height < 0) {
1861 height = -height;
1862 src_raw = src_raw + (height - 1) * src_stride_raw;
1863 src_stride_raw = -src_stride_raw;
1864 }
1865 // Coalesce rows.
1866 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1867 width *= height;
1868 height = 1;
1869 src_stride_raw = dst_stride_argb = 0;
1870 }
1871 #if defined(HAS_RAWTOARGBROW_SSSE3)
1872 if (TestCpuFlag(kCpuHasSSSE3)) {
1873 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1874 if (IS_ALIGNED(width, 16)) {
1875 RAWToARGBRow = RAWToARGBRow_SSSE3;
1876 }
1877 }
1878 #endif
1879 #if defined(HAS_RAWTOARGBROW_NEON)
1880 if (TestCpuFlag(kCpuHasNEON)) {
1881 RAWToARGBRow = RAWToARGBRow_Any_NEON;
1882 if (IS_ALIGNED(width, 8)) {
1883 RAWToARGBRow = RAWToARGBRow_NEON;
1884 }
1885 }
1886 #endif
1887 #if defined(HAS_RAWTOARGBROW_MSA)
1888 if (TestCpuFlag(kCpuHasMSA)) {
1889 RAWToARGBRow = RAWToARGBRow_Any_MSA;
1890 if (IS_ALIGNED(width, 16)) {
1891 RAWToARGBRow = RAWToARGBRow_MSA;
1892 }
1893 }
1894 #endif
1895 #if defined(HAS_RAWTOARGBROW_MMI)
1896 if (TestCpuFlag(kCpuHasMMI)) {
1897 RAWToARGBRow = RAWToARGBRow_Any_MMI;
1898 if (IS_ALIGNED(width, 4)) {
1899 RAWToARGBRow = RAWToARGBRow_MMI;
1900 }
1901 }
1902 #endif
1903
1904 for (y = 0; y < height; ++y) {
1905 RAWToARGBRow(src_raw, dst_argb, width);
1906 src_raw += src_stride_raw;
1907 dst_argb += dst_stride_argb;
1908 }
1909 return 0;
1910 }
1911
1912 // Convert RAW to RGBA.
1913 LIBYUV_API
RAWToRGBA(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1914 int RAWToRGBA(const uint8_t* src_raw,
1915 int src_stride_raw,
1916 uint8_t* dst_rgba,
1917 int dst_stride_rgba,
1918 int width,
1919 int height) {
1920 int y;
1921 void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
1922 RAWToRGBARow_C;
1923 if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
1924 return -1;
1925 }
1926 // Negative height means invert the image.
1927 if (height < 0) {
1928 height = -height;
1929 src_raw = src_raw + (height - 1) * src_stride_raw;
1930 src_stride_raw = -src_stride_raw;
1931 }
1932 // Coalesce rows.
1933 if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
1934 width *= height;
1935 height = 1;
1936 src_stride_raw = dst_stride_rgba = 0;
1937 }
1938 #if defined(HAS_RAWTORGBAROW_SSSE3)
1939 if (TestCpuFlag(kCpuHasSSSE3)) {
1940 RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
1941 if (IS_ALIGNED(width, 16)) {
1942 RAWToRGBARow = RAWToRGBARow_SSSE3;
1943 }
1944 }
1945 #endif
1946 #if defined(HAS_RAWTORGBAROW_NEON)
1947 if (TestCpuFlag(kCpuHasNEON)) {
1948 RAWToRGBARow = RAWToRGBARow_Any_NEON;
1949 if (IS_ALIGNED(width, 8)) {
1950 RAWToRGBARow = RAWToRGBARow_NEON;
1951 }
1952 }
1953 #endif
1954
1955 for (y = 0; y < height; ++y) {
1956 RAWToRGBARow(src_raw, dst_rgba, width);
1957 src_raw += src_stride_raw;
1958 dst_rgba += dst_stride_rgba;
1959 }
1960 return 0;
1961 }
1962
1963 // Convert RGB565 to ARGB.
1964 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1965 int RGB565ToARGB(const uint8_t* src_rgb565,
1966 int src_stride_rgb565,
1967 uint8_t* dst_argb,
1968 int dst_stride_argb,
1969 int width,
1970 int height) {
1971 int y;
1972 void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
1973 int width) = RGB565ToARGBRow_C;
1974 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1975 return -1;
1976 }
1977 // Negative height means invert the image.
1978 if (height < 0) {
1979 height = -height;
1980 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
1981 src_stride_rgb565 = -src_stride_rgb565;
1982 }
1983 // Coalesce rows.
1984 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
1985 width *= height;
1986 height = 1;
1987 src_stride_rgb565 = dst_stride_argb = 0;
1988 }
1989 #if defined(HAS_RGB565TOARGBROW_SSE2)
1990 if (TestCpuFlag(kCpuHasSSE2)) {
1991 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
1992 if (IS_ALIGNED(width, 8)) {
1993 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
1994 }
1995 }
1996 #endif
1997 #if defined(HAS_RGB565TOARGBROW_AVX2)
1998 if (TestCpuFlag(kCpuHasAVX2)) {
1999 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
2000 if (IS_ALIGNED(width, 16)) {
2001 RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
2002 }
2003 }
2004 #endif
2005 #if defined(HAS_RGB565TOARGBROW_NEON)
2006 if (TestCpuFlag(kCpuHasNEON)) {
2007 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
2008 if (IS_ALIGNED(width, 8)) {
2009 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
2010 }
2011 }
2012 #endif
2013 #if defined(HAS_RGB565TOARGBROW_MSA)
2014 if (TestCpuFlag(kCpuHasMSA)) {
2015 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
2016 if (IS_ALIGNED(width, 16)) {
2017 RGB565ToARGBRow = RGB565ToARGBRow_MSA;
2018 }
2019 }
2020 #endif
2021 #if defined(HAS_RGB565TOARGBROW_MMI)
2022 if (TestCpuFlag(kCpuHasMMI)) {
2023 RGB565ToARGBRow = RGB565ToARGBRow_Any_MMI;
2024 if (IS_ALIGNED(width, 4)) {
2025 RGB565ToARGBRow = RGB565ToARGBRow_MMI;
2026 }
2027 }
2028 #endif
2029
2030 for (y = 0; y < height; ++y) {
2031 RGB565ToARGBRow(src_rgb565, dst_argb, width);
2032 src_rgb565 += src_stride_rgb565;
2033 dst_argb += dst_stride_argb;
2034 }
2035 return 0;
2036 }
2037
2038 // Convert ARGB1555 to ARGB.
2039 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2040 int ARGB1555ToARGB(const uint8_t* src_argb1555,
2041 int src_stride_argb1555,
2042 uint8_t* dst_argb,
2043 int dst_stride_argb,
2044 int width,
2045 int height) {
2046 int y;
2047 void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
2048 int width) = ARGB1555ToARGBRow_C;
2049 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
2050 return -1;
2051 }
2052 // Negative height means invert the image.
2053 if (height < 0) {
2054 height = -height;
2055 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
2056 src_stride_argb1555 = -src_stride_argb1555;
2057 }
2058 // Coalesce rows.
2059 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
2060 width *= height;
2061 height = 1;
2062 src_stride_argb1555 = dst_stride_argb = 0;
2063 }
2064 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
2065 if (TestCpuFlag(kCpuHasSSE2)) {
2066 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
2067 if (IS_ALIGNED(width, 8)) {
2068 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
2069 }
2070 }
2071 #endif
2072 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
2073 if (TestCpuFlag(kCpuHasAVX2)) {
2074 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
2075 if (IS_ALIGNED(width, 16)) {
2076 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
2077 }
2078 }
2079 #endif
2080 #if defined(HAS_ARGB1555TOARGBROW_NEON)
2081 if (TestCpuFlag(kCpuHasNEON)) {
2082 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
2083 if (IS_ALIGNED(width, 8)) {
2084 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
2085 }
2086 }
2087 #endif
2088 #if defined(HAS_ARGB1555TOARGBROW_MSA)
2089 if (TestCpuFlag(kCpuHasMSA)) {
2090 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
2091 if (IS_ALIGNED(width, 16)) {
2092 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
2093 }
2094 }
2095 #endif
2096 #if defined(HAS_ARGB1555TOARGBROW_MMI)
2097 if (TestCpuFlag(kCpuHasMMI)) {
2098 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MMI;
2099 if (IS_ALIGNED(width, 4)) {
2100 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MMI;
2101 }
2102 }
2103 #endif
2104
2105 for (y = 0; y < height; ++y) {
2106 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
2107 src_argb1555 += src_stride_argb1555;
2108 dst_argb += dst_stride_argb;
2109 }
2110 return 0;
2111 }
2112
2113 // Convert ARGB4444 to ARGB.
2114 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2115 int ARGB4444ToARGB(const uint8_t* src_argb4444,
2116 int src_stride_argb4444,
2117 uint8_t* dst_argb,
2118 int dst_stride_argb,
2119 int width,
2120 int height) {
2121 int y;
2122 void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
2123 int width) = ARGB4444ToARGBRow_C;
2124 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
2125 return -1;
2126 }
2127 // Negative height means invert the image.
2128 if (height < 0) {
2129 height = -height;
2130 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
2131 src_stride_argb4444 = -src_stride_argb4444;
2132 }
2133 // Coalesce rows.
2134 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
2135 width *= height;
2136 height = 1;
2137 src_stride_argb4444 = dst_stride_argb = 0;
2138 }
2139 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
2140 if (TestCpuFlag(kCpuHasSSE2)) {
2141 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
2142 if (IS_ALIGNED(width, 8)) {
2143 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
2144 }
2145 }
2146 #endif
2147 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
2148 if (TestCpuFlag(kCpuHasAVX2)) {
2149 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
2150 if (IS_ALIGNED(width, 16)) {
2151 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
2152 }
2153 }
2154 #endif
2155 #if defined(HAS_ARGB4444TOARGBROW_NEON)
2156 if (TestCpuFlag(kCpuHasNEON)) {
2157 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
2158 if (IS_ALIGNED(width, 8)) {
2159 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
2160 }
2161 }
2162 #endif
2163 #if defined(HAS_ARGB4444TOARGBROW_MSA)
2164 if (TestCpuFlag(kCpuHasMSA)) {
2165 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
2166 if (IS_ALIGNED(width, 16)) {
2167 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
2168 }
2169 }
2170 #endif
2171 #if defined(HAS_ARGB4444TOARGBROW_MMI)
2172 if (TestCpuFlag(kCpuHasMMI)) {
2173 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MMI;
2174 if (IS_ALIGNED(width, 4)) {
2175 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MMI;
2176 }
2177 }
2178 #endif
2179
2180 for (y = 0; y < height; ++y) {
2181 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
2182 src_argb4444 += src_stride_argb4444;
2183 dst_argb += dst_stride_argb;
2184 }
2185 return 0;
2186 }
2187
2188 // Convert AR30 to ARGB.
2189 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2190 int AR30ToARGB(const uint8_t* src_ar30,
2191 int src_stride_ar30,
2192 uint8_t* dst_argb,
2193 int dst_stride_argb,
2194 int width,
2195 int height) {
2196 int y;
2197 if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
2198 return -1;
2199 }
2200 // Negative height means invert the image.
2201 if (height < 0) {
2202 height = -height;
2203 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2204 src_stride_ar30 = -src_stride_ar30;
2205 }
2206 // Coalesce rows.
2207 if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
2208 width *= height;
2209 height = 1;
2210 src_stride_ar30 = dst_stride_argb = 0;
2211 }
2212 for (y = 0; y < height; ++y) {
2213 AR30ToARGBRow_C(src_ar30, dst_argb, width);
2214 src_ar30 += src_stride_ar30;
2215 dst_argb += dst_stride_argb;
2216 }
2217 return 0;
2218 }
2219
2220 // Convert AR30 to ABGR.
2221 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2222 int AR30ToABGR(const uint8_t* src_ar30,
2223 int src_stride_ar30,
2224 uint8_t* dst_abgr,
2225 int dst_stride_abgr,
2226 int width,
2227 int height) {
2228 int y;
2229 if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
2230 return -1;
2231 }
2232 // Negative height means invert the image.
2233 if (height < 0) {
2234 height = -height;
2235 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2236 src_stride_ar30 = -src_stride_ar30;
2237 }
2238 // Coalesce rows.
2239 if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
2240 width *= height;
2241 height = 1;
2242 src_stride_ar30 = dst_stride_abgr = 0;
2243 }
2244 for (y = 0; y < height; ++y) {
2245 AR30ToABGRRow_C(src_ar30, dst_abgr, width);
2246 src_ar30 += src_stride_ar30;
2247 dst_abgr += dst_stride_abgr;
2248 }
2249 return 0;
2250 }
2251
2252 // Convert AR30 to AB30.
2253 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)2254 int AR30ToAB30(const uint8_t* src_ar30,
2255 int src_stride_ar30,
2256 uint8_t* dst_ab30,
2257 int dst_stride_ab30,
2258 int width,
2259 int height) {
2260 int y;
2261 if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
2262 return -1;
2263 }
2264 // Negative height means invert the image.
2265 if (height < 0) {
2266 height = -height;
2267 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2268 src_stride_ar30 = -src_stride_ar30;
2269 }
2270 // Coalesce rows.
2271 if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
2272 width *= height;
2273 height = 1;
2274 src_stride_ar30 = dst_stride_ab30 = 0;
2275 }
2276 for (y = 0; y < height; ++y) {
2277 AR30ToAB30Row_C(src_ar30, dst_ab30, width);
2278 src_ar30 += src_stride_ar30;
2279 dst_ab30 += dst_stride_ab30;
2280 }
2281 return 0;
2282 }
2283
2284 // Convert NV12 to ARGB with matrix
NV12ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)2285 static int NV12ToARGBMatrix(const uint8_t* src_y,
2286 int src_stride_y,
2287 const uint8_t* src_uv,
2288 int src_stride_uv,
2289 uint8_t* dst_argb,
2290 int dst_stride_argb,
2291 const struct YuvConstants* yuvconstants,
2292 int width,
2293 int height) {
2294 int y;
2295 void (*NV12ToARGBRow)(
2296 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2297 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
2298 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
2299 return -1;
2300 }
2301 // Negative height means invert the image.
2302 if (height < 0) {
2303 height = -height;
2304 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2305 dst_stride_argb = -dst_stride_argb;
2306 }
2307 #if defined(HAS_NV12TOARGBROW_SSSE3)
2308 if (TestCpuFlag(kCpuHasSSSE3)) {
2309 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
2310 if (IS_ALIGNED(width, 8)) {
2311 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
2312 }
2313 }
2314 #endif
2315 #if defined(HAS_NV12TOARGBROW_AVX2)
2316 if (TestCpuFlag(kCpuHasAVX2)) {
2317 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
2318 if (IS_ALIGNED(width, 16)) {
2319 NV12ToARGBRow = NV12ToARGBRow_AVX2;
2320 }
2321 }
2322 #endif
2323 #if defined(HAS_NV12TOARGBROW_NEON)
2324 if (TestCpuFlag(kCpuHasNEON)) {
2325 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
2326 if (IS_ALIGNED(width, 8)) {
2327 NV12ToARGBRow = NV12ToARGBRow_NEON;
2328 }
2329 }
2330 #endif
2331 #if defined(HAS_NV12TOARGBROW_MSA)
2332 if (TestCpuFlag(kCpuHasMSA)) {
2333 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
2334 if (IS_ALIGNED(width, 8)) {
2335 NV12ToARGBRow = NV12ToARGBRow_MSA;
2336 }
2337 }
2338 #endif
2339 #if defined(HAS_NV12TOARGBROW_MMI)
2340 if (TestCpuFlag(kCpuHasMMI)) {
2341 NV12ToARGBRow = NV12ToARGBRow_Any_MMI;
2342 if (IS_ALIGNED(width, 4)) {
2343 NV12ToARGBRow = NV12ToARGBRow_MMI;
2344 }
2345 }
2346 #endif
2347
2348 for (y = 0; y < height; ++y) {
2349 NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
2350 dst_argb += dst_stride_argb;
2351 src_y += src_stride_y;
2352 if (y & 1) {
2353 src_uv += src_stride_uv;
2354 }
2355 }
2356 return 0;
2357 }
2358
2359 // Convert NV21 to ARGB with matrix
NV21ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)2360 static int NV21ToARGBMatrix(const uint8_t* src_y,
2361 int src_stride_y,
2362 const uint8_t* src_vu,
2363 int src_stride_vu,
2364 uint8_t* dst_argb,
2365 int dst_stride_argb,
2366 const struct YuvConstants* yuvconstants,
2367 int width,
2368 int height) {
2369 int y;
2370 void (*NV21ToARGBRow)(
2371 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2372 const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
2373 if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
2374 return -1;
2375 }
2376 // Negative height means invert the image.
2377 if (height < 0) {
2378 height = -height;
2379 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2380 dst_stride_argb = -dst_stride_argb;
2381 }
2382 #if defined(HAS_NV21TOARGBROW_SSSE3)
2383 if (TestCpuFlag(kCpuHasSSSE3)) {
2384 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
2385 if (IS_ALIGNED(width, 8)) {
2386 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
2387 }
2388 }
2389 #endif
2390 #if defined(HAS_NV21TOARGBROW_AVX2)
2391 if (TestCpuFlag(kCpuHasAVX2)) {
2392 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
2393 if (IS_ALIGNED(width, 16)) {
2394 NV21ToARGBRow = NV21ToARGBRow_AVX2;
2395 }
2396 }
2397 #endif
2398 #if defined(HAS_NV21TOARGBROW_NEON)
2399 if (TestCpuFlag(kCpuHasNEON)) {
2400 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
2401 if (IS_ALIGNED(width, 8)) {
2402 NV21ToARGBRow = NV21ToARGBRow_NEON;
2403 }
2404 }
2405 #endif
2406 #if defined(HAS_NV21TOARGBROW_MSA)
2407 if (TestCpuFlag(kCpuHasMSA)) {
2408 NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
2409 if (IS_ALIGNED(width, 8)) {
2410 NV21ToARGBRow = NV21ToARGBRow_MSA;
2411 }
2412 }
2413 #endif
2414 #if defined(HAS_NV21TOARGBROW_MMI)
2415 if (TestCpuFlag(kCpuHasMMI)) {
2416 NV21ToARGBRow = NV21ToARGBRow_Any_MMI;
2417 if (IS_ALIGNED(width, 4)) {
2418 NV21ToARGBRow = NV21ToARGBRow_MMI;
2419 }
2420 }
2421 #endif
2422
2423 for (y = 0; y < height; ++y) {
2424 NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
2425 dst_argb += dst_stride_argb;
2426 src_y += src_stride_y;
2427 if (y & 1) {
2428 src_vu += src_stride_vu;
2429 }
2430 }
2431 return 0;
2432 }
2433
2434 // Convert NV12 to ARGB.
2435 LIBYUV_API
NV12ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2436 int NV12ToARGB(const uint8_t* src_y,
2437 int src_stride_y,
2438 const uint8_t* src_uv,
2439 int src_stride_uv,
2440 uint8_t* dst_argb,
2441 int dst_stride_argb,
2442 int width,
2443 int height) {
2444 return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
2445 dst_stride_argb, &kYuvI601Constants, width, height);
2446 }
2447
2448 // Convert NV21 to ARGB.
2449 LIBYUV_API
NV21ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2450 int NV21ToARGB(const uint8_t* src_y,
2451 int src_stride_y,
2452 const uint8_t* src_vu,
2453 int src_stride_vu,
2454 uint8_t* dst_argb,
2455 int dst_stride_argb,
2456 int width,
2457 int height) {
2458 return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
2459 dst_stride_argb, &kYuvI601Constants, width, height);
2460 }
2461
2462 // Convert NV12 to ABGR.
2463 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
2464 // To swap the UV use NV12 instead of NV21.LIBYUV_API
2465 LIBYUV_API
NV12ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2466 int NV12ToABGR(const uint8_t* src_y,
2467 int src_stride_y,
2468 const uint8_t* src_uv,
2469 int src_stride_uv,
2470 uint8_t* dst_abgr,
2471 int dst_stride_abgr,
2472 int width,
2473 int height) {
2474 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
2475 dst_stride_abgr, &kYvuI601Constants, width, height);
2476 }
2477
2478 // Convert NV21 to ABGR.
2479 LIBYUV_API
NV21ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2480 int NV21ToABGR(const uint8_t* src_y,
2481 int src_stride_y,
2482 const uint8_t* src_vu,
2483 int src_stride_vu,
2484 uint8_t* dst_abgr,
2485 int dst_stride_abgr,
2486 int width,
2487 int height) {
2488 return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
2489 dst_stride_abgr, &kYvuI601Constants, width, height);
2490 }
2491
2492 // TODO(fbarchard): Consider SSSE3 2 step conversion.
2493 // Convert NV12 to RGB24 with matrix
NV12ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)2494 static int NV12ToRGB24Matrix(const uint8_t* src_y,
2495 int src_stride_y,
2496 const uint8_t* src_uv,
2497 int src_stride_uv,
2498 uint8_t* dst_rgb24,
2499 int dst_stride_rgb24,
2500 const struct YuvConstants* yuvconstants,
2501 int width,
2502 int height) {
2503 int y;
2504 void (*NV12ToRGB24Row)(
2505 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2506 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
2507 if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
2508 return -1;
2509 }
2510 // Negative height means invert the image.
2511 if (height < 0) {
2512 height = -height;
2513 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2514 dst_stride_rgb24 = -dst_stride_rgb24;
2515 }
2516 #if defined(HAS_NV12TORGB24ROW_NEON)
2517 if (TestCpuFlag(kCpuHasNEON)) {
2518 NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
2519 if (IS_ALIGNED(width, 8)) {
2520 NV12ToRGB24Row = NV12ToRGB24Row_NEON;
2521 }
2522 }
2523 #endif
2524 #if defined(HAS_NV12TORGB24ROW_SSSE3)
2525 if (TestCpuFlag(kCpuHasSSSE3)) {
2526 NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
2527 if (IS_ALIGNED(width, 16)) {
2528 NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
2529 }
2530 }
2531 #endif
2532 #if defined(HAS_NV12TORGB24ROW_AVX2)
2533 if (TestCpuFlag(kCpuHasAVX2)) {
2534 NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
2535 if (IS_ALIGNED(width, 32)) {
2536 NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
2537 }
2538 }
2539 #endif
2540 #if defined(HAS_NV12TORGB24ROW_MMI)
2541 if (TestCpuFlag(kCpuHasMMI)) {
2542 NV12ToRGB24Row = NV12ToRGB24Row_Any_MMI;
2543 if (IS_ALIGNED(width, 8)) {
2544 NV12ToRGB24Row = NV12ToRGB24Row_MMI;
2545 }
2546 }
2547 #endif
2548
2549 for (y = 0; y < height; ++y) {
2550 NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
2551 dst_rgb24 += dst_stride_rgb24;
2552 src_y += src_stride_y;
2553 if (y & 1) {
2554 src_uv += src_stride_uv;
2555 }
2556 }
2557 return 0;
2558 }
2559
2560 // Convert NV21 to RGB24 with matrix
NV21ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)2561 static int NV21ToRGB24Matrix(const uint8_t* src_y,
2562 int src_stride_y,
2563 const uint8_t* src_vu,
2564 int src_stride_vu,
2565 uint8_t* dst_rgb24,
2566 int dst_stride_rgb24,
2567 const struct YuvConstants* yuvconstants,
2568 int width,
2569 int height) {
2570 int y;
2571 void (*NV21ToRGB24Row)(
2572 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2573 const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
2574 if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
2575 return -1;
2576 }
2577 // Negative height means invert the image.
2578 if (height < 0) {
2579 height = -height;
2580 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2581 dst_stride_rgb24 = -dst_stride_rgb24;
2582 }
2583 #if defined(HAS_NV21TORGB24ROW_NEON)
2584 if (TestCpuFlag(kCpuHasNEON)) {
2585 NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
2586 if (IS_ALIGNED(width, 8)) {
2587 NV21ToRGB24Row = NV21ToRGB24Row_NEON;
2588 }
2589 }
2590 #endif
2591 #if defined(HAS_NV21TORGB24ROW_SSSE3)
2592 if (TestCpuFlag(kCpuHasSSSE3)) {
2593 NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
2594 if (IS_ALIGNED(width, 16)) {
2595 NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
2596 }
2597 }
2598 #endif
2599 #if defined(HAS_NV21TORGB24ROW_AVX2)
2600 if (TestCpuFlag(kCpuHasAVX2)) {
2601 NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
2602 if (IS_ALIGNED(width, 32)) {
2603 NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
2604 }
2605 }
2606 #endif
2607 #if defined(HAS_NV21TORGB24ROW_MMI)
2608 if (TestCpuFlag(kCpuHasMMI)) {
2609 NV21ToRGB24Row = NV21ToRGB24Row_Any_MMI;
2610 if (IS_ALIGNED(width, 8)) {
2611 NV21ToRGB24Row = NV21ToRGB24Row_MMI;
2612 }
2613 }
2614 #endif
2615
2616 for (y = 0; y < height; ++y) {
2617 NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
2618 dst_rgb24 += dst_stride_rgb24;
2619 src_y += src_stride_y;
2620 if (y & 1) {
2621 src_vu += src_stride_vu;
2622 }
2623 }
2624 return 0;
2625 }
2626
2627 // Convert NV12 to RGB24.
2628 LIBYUV_API
NV12ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)2629 int NV12ToRGB24(const uint8_t* src_y,
2630 int src_stride_y,
2631 const uint8_t* src_uv,
2632 int src_stride_uv,
2633 uint8_t* dst_rgb24,
2634 int dst_stride_rgb24,
2635 int width,
2636 int height) {
2637 return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
2638 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2639 width, height);
2640 }
2641
2642 // Convert NV21 to RGB24.
2643 LIBYUV_API
NV21ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)2644 int NV21ToRGB24(const uint8_t* src_y,
2645 int src_stride_y,
2646 const uint8_t* src_vu,
2647 int src_stride_vu,
2648 uint8_t* dst_rgb24,
2649 int dst_stride_rgb24,
2650 int width,
2651 int height) {
2652 return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
2653 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2654 width, height);
2655 }
2656
2657 // Convert NV12 to RAW.
2658 LIBYUV_API
NV12ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_raw,int dst_stride_raw,int width,int height)2659 int NV12ToRAW(const uint8_t* src_y,
2660 int src_stride_y,
2661 const uint8_t* src_uv,
2662 int src_stride_uv,
2663 uint8_t* dst_raw,
2664 int dst_stride_raw,
2665 int width,
2666 int height) {
2667 return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
2668 dst_stride_raw, &kYvuI601Constants, width, height);
2669 }
2670
2671 // Convert NV21 to RAW.
2672 LIBYUV_API
NV21ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_raw,int dst_stride_raw,int width,int height)2673 int NV21ToRAW(const uint8_t* src_y,
2674 int src_stride_y,
2675 const uint8_t* src_vu,
2676 int src_stride_vu,
2677 uint8_t* dst_raw,
2678 int dst_stride_raw,
2679 int width,
2680 int height) {
2681 return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
2682 dst_stride_raw, &kYvuI601Constants, width, height);
2683 }
2684
2685 // Convert NV21 to YUV24
NV21ToYUV24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_yuv24,int dst_stride_yuv24,int width,int height)2686 int NV21ToYUV24(const uint8_t* src_y,
2687 int src_stride_y,
2688 const uint8_t* src_vu,
2689 int src_stride_vu,
2690 uint8_t* dst_yuv24,
2691 int dst_stride_yuv24,
2692 int width,
2693 int height) {
2694 int y;
2695 void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
2696 uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
2697 if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
2698 return -1;
2699 }
2700 // Negative height means invert the image.
2701 if (height < 0) {
2702 height = -height;
2703 dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
2704 dst_stride_yuv24 = -dst_stride_yuv24;
2705 }
2706 #if defined(HAS_NV21TOYUV24ROW_NEON)
2707 if (TestCpuFlag(kCpuHasNEON)) {
2708 NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
2709 if (IS_ALIGNED(width, 16)) {
2710 NV21ToYUV24Row = NV21ToYUV24Row_NEON;
2711 }
2712 }
2713 #endif
2714 #if defined(HAS_NV21TOYUV24ROW_AVX2)
2715 if (TestCpuFlag(kCpuHasAVX2)) {
2716 NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
2717 if (IS_ALIGNED(width, 32)) {
2718 NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
2719 }
2720 }
2721 #endif
2722 for (y = 0; y < height; ++y) {
2723 NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
2724 dst_yuv24 += dst_stride_yuv24;
2725 src_y += src_stride_y;
2726 if (y & 1) {
2727 src_vu += src_stride_vu;
2728 }
2729 }
2730 return 0;
2731 }
2732
2733 // Convert M420 to ARGB.
2734 LIBYUV_API
M420ToARGB(const uint8_t * src_m420,int src_stride_m420,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2735 int M420ToARGB(const uint8_t* src_m420,
2736 int src_stride_m420,
2737 uint8_t* dst_argb,
2738 int dst_stride_argb,
2739 int width,
2740 int height) {
2741 int y;
2742 void (*NV12ToARGBRow)(
2743 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2744 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
2745 if (!src_m420 || !dst_argb || width <= 0 || height == 0) {
2746 return -1;
2747 }
2748 // Negative height means invert the image.
2749 if (height < 0) {
2750 height = -height;
2751 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2752 dst_stride_argb = -dst_stride_argb;
2753 }
2754 #if defined(HAS_NV12TOARGBROW_SSSE3)
2755 if (TestCpuFlag(kCpuHasSSSE3)) {
2756 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
2757 if (IS_ALIGNED(width, 8)) {
2758 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
2759 }
2760 }
2761 #endif
2762 #if defined(HAS_NV12TOARGBROW_AVX2)
2763 if (TestCpuFlag(kCpuHasAVX2)) {
2764 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
2765 if (IS_ALIGNED(width, 16)) {
2766 NV12ToARGBRow = NV12ToARGBRow_AVX2;
2767 }
2768 }
2769 #endif
2770 #if defined(HAS_NV12TOARGBROW_NEON)
2771 if (TestCpuFlag(kCpuHasNEON)) {
2772 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
2773 if (IS_ALIGNED(width, 8)) {
2774 NV12ToARGBRow = NV12ToARGBRow_NEON;
2775 }
2776 }
2777 #endif
2778 #if defined(HAS_NV12TOARGBROW_MSA)
2779 if (TestCpuFlag(kCpuHasMSA)) {
2780 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
2781 if (IS_ALIGNED(width, 8)) {
2782 NV12ToARGBRow = NV12ToARGBRow_MSA;
2783 }
2784 }
2785 #endif
2786 #if defined(HAS_NV12TOARGBROW_MMI)
2787 if (TestCpuFlag(kCpuHasMMI)) {
2788 NV12ToARGBRow = NV12ToARGBRow_Any_MMI;
2789 if (IS_ALIGNED(width, 4)) {
2790 NV12ToARGBRow = NV12ToARGBRow_MMI;
2791 }
2792 }
2793 #endif
2794
2795 for (y = 0; y < height - 1; y += 2) {
2796 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
2797 &kYuvI601Constants, width);
2798 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
2799 dst_argb + dst_stride_argb, &kYuvI601Constants, width);
2800 dst_argb += dst_stride_argb * 2;
2801 src_m420 += src_stride_m420 * 3;
2802 }
2803 if (height & 1) {
2804 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
2805 &kYuvI601Constants, width);
2806 }
2807 return 0;
2808 }
2809
2810 // Convert YUY2 to ARGB.
2811 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2812 int YUY2ToARGB(const uint8_t* src_yuy2,
2813 int src_stride_yuy2,
2814 uint8_t* dst_argb,
2815 int dst_stride_argb,
2816 int width,
2817 int height) {
2818 int y;
2819 void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
2820 const struct YuvConstants* yuvconstants, int width) =
2821 YUY2ToARGBRow_C;
2822 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
2823 return -1;
2824 }
2825 // Negative height means invert the image.
2826 if (height < 0) {
2827 height = -height;
2828 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
2829 src_stride_yuy2 = -src_stride_yuy2;
2830 }
2831 // Coalesce rows.
2832 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
2833 width *= height;
2834 height = 1;
2835 src_stride_yuy2 = dst_stride_argb = 0;
2836 }
2837 #if defined(HAS_YUY2TOARGBROW_SSSE3)
2838 if (TestCpuFlag(kCpuHasSSSE3)) {
2839 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
2840 if (IS_ALIGNED(width, 16)) {
2841 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
2842 }
2843 }
2844 #endif
2845 #if defined(HAS_YUY2TOARGBROW_AVX2)
2846 if (TestCpuFlag(kCpuHasAVX2)) {
2847 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
2848 if (IS_ALIGNED(width, 32)) {
2849 YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
2850 }
2851 }
2852 #endif
2853 #if defined(HAS_YUY2TOARGBROW_NEON)
2854 if (TestCpuFlag(kCpuHasNEON)) {
2855 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
2856 if (IS_ALIGNED(width, 8)) {
2857 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
2858 }
2859 }
2860 #endif
2861 #if defined(HAS_YUY2TOARGBROW_MSA)
2862 if (TestCpuFlag(kCpuHasMSA)) {
2863 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
2864 if (IS_ALIGNED(width, 8)) {
2865 YUY2ToARGBRow = YUY2ToARGBRow_MSA;
2866 }
2867 }
2868 #endif
2869 #if defined(HAS_YUY2TOARGBROW_MMI)
2870 if (TestCpuFlag(kCpuHasMMI)) {
2871 YUY2ToARGBRow = YUY2ToARGBRow_Any_MMI;
2872 if (IS_ALIGNED(width, 4)) {
2873 YUY2ToARGBRow = YUY2ToARGBRow_MMI;
2874 }
2875 }
2876 #endif
2877 for (y = 0; y < height; ++y) {
2878 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
2879 src_yuy2 += src_stride_yuy2;
2880 dst_argb += dst_stride_argb;
2881 }
2882 return 0;
2883 }
2884
2885 // Convert UYVY to ARGB.
2886 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2887 int UYVYToARGB(const uint8_t* src_uyvy,
2888 int src_stride_uyvy,
2889 uint8_t* dst_argb,
2890 int dst_stride_argb,
2891 int width,
2892 int height) {
2893 int y;
2894 void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
2895 const struct YuvConstants* yuvconstants, int width) =
2896 UYVYToARGBRow_C;
2897 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
2898 return -1;
2899 }
2900 // Negative height means invert the image.
2901 if (height < 0) {
2902 height = -height;
2903 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
2904 src_stride_uyvy = -src_stride_uyvy;
2905 }
2906 // Coalesce rows.
2907 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
2908 width *= height;
2909 height = 1;
2910 src_stride_uyvy = dst_stride_argb = 0;
2911 }
2912 #if defined(HAS_UYVYTOARGBROW_SSSE3)
2913 if (TestCpuFlag(kCpuHasSSSE3)) {
2914 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
2915 if (IS_ALIGNED(width, 16)) {
2916 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
2917 }
2918 }
2919 #endif
2920 #if defined(HAS_UYVYTOARGBROW_AVX2)
2921 if (TestCpuFlag(kCpuHasAVX2)) {
2922 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
2923 if (IS_ALIGNED(width, 32)) {
2924 UYVYToARGBRow = UYVYToARGBRow_AVX2;
2925 }
2926 }
2927 #endif
2928 #if defined(HAS_UYVYTOARGBROW_NEON)
2929 if (TestCpuFlag(kCpuHasNEON)) {
2930 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
2931 if (IS_ALIGNED(width, 8)) {
2932 UYVYToARGBRow = UYVYToARGBRow_NEON;
2933 }
2934 }
2935 #endif
2936 #if defined(HAS_UYVYTOARGBROW_MSA)
2937 if (TestCpuFlag(kCpuHasMSA)) {
2938 UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
2939 if (IS_ALIGNED(width, 8)) {
2940 UYVYToARGBRow = UYVYToARGBRow_MSA;
2941 }
2942 }
2943 #endif
2944 #if defined(HAS_UYVYTOARGBROW_MMI)
2945 if (TestCpuFlag(kCpuHasMMI)) {
2946 UYVYToARGBRow = UYVYToARGBRow_Any_MMI;
2947 if (IS_ALIGNED(width, 4)) {
2948 UYVYToARGBRow = UYVYToARGBRow_MMI;
2949 }
2950 }
2951 #endif
2952 for (y = 0; y < height; ++y) {
2953 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
2954 src_uyvy += src_stride_uyvy;
2955 dst_argb += dst_stride_argb;
2956 }
2957 return 0;
2958 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)2959 static void WeavePixels(const uint8_t* src_u,
2960 const uint8_t* src_v,
2961 int src_pixel_stride_uv,
2962 uint8_t* dst_uv,
2963 int width) {
2964 int i;
2965 for (i = 0; i < width; ++i) {
2966 dst_uv[0] = *src_u;
2967 dst_uv[1] = *src_v;
2968 dst_uv += 2;
2969 src_u += src_pixel_stride_uv;
2970 src_v += src_pixel_stride_uv;
2971 }
2972 }
2973
2974 // Convert Android420 to ARGB.
2975 LIBYUV_API
Android420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)2976 int Android420ToARGBMatrix(const uint8_t* src_y,
2977 int src_stride_y,
2978 const uint8_t* src_u,
2979 int src_stride_u,
2980 const uint8_t* src_v,
2981 int src_stride_v,
2982 int src_pixel_stride_uv,
2983 uint8_t* dst_argb,
2984 int dst_stride_argb,
2985 const struct YuvConstants* yuvconstants,
2986 int width,
2987 int height) {
2988 int y;
2989 uint8_t* dst_uv;
2990 const ptrdiff_t vu_off = src_v - src_u;
2991 int halfwidth = (width + 1) >> 1;
2992 int halfheight = (height + 1) >> 1;
2993 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
2994 return -1;
2995 }
2996 // Negative height means invert the image.
2997 if (height < 0) {
2998 height = -height;
2999 halfheight = (height + 1) >> 1;
3000 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3001 dst_stride_argb = -dst_stride_argb;
3002 }
3003
3004 // I420
3005 if (src_pixel_stride_uv == 1) {
3006 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3007 src_stride_v, dst_argb, dst_stride_argb,
3008 yuvconstants, width, height);
3009 // NV21
3010 }
3011 if (src_pixel_stride_uv == 2 && vu_off == -1 &&
3012 src_stride_u == src_stride_v) {
3013 return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
3014 dst_stride_argb, yuvconstants, width, height);
3015 // NV12
3016 }
3017 if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
3018 return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
3019 dst_stride_argb, yuvconstants, width, height);
3020 }
3021
3022 // General case fallback creates NV12
3023 align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
3024 dst_uv = plane_uv;
3025 for (y = 0; y < halfheight; ++y) {
3026 WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
3027 src_u += src_stride_u;
3028 src_v += src_stride_v;
3029 dst_uv += halfwidth * 2;
3030 }
3031 NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
3032 dst_stride_argb, yuvconstants, width, height);
3033 free_aligned_buffer_64(plane_uv);
3034 return 0;
3035 }
3036
3037 // Convert Android420 to ARGB.
3038 LIBYUV_API
Android420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3039 int Android420ToARGB(const uint8_t* src_y,
3040 int src_stride_y,
3041 const uint8_t* src_u,
3042 int src_stride_u,
3043 const uint8_t* src_v,
3044 int src_stride_v,
3045 int src_pixel_stride_uv,
3046 uint8_t* dst_argb,
3047 int dst_stride_argb,
3048 int width,
3049 int height) {
3050 return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3051 src_stride_v, src_pixel_stride_uv, dst_argb,
3052 dst_stride_argb, &kYuvI601Constants, width,
3053 height);
3054 }
3055
3056 // Convert Android420 to ABGR.
3057 LIBYUV_API
Android420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)3058 int Android420ToABGR(const uint8_t* src_y,
3059 int src_stride_y,
3060 const uint8_t* src_u,
3061 int src_stride_u,
3062 const uint8_t* src_v,
3063 int src_stride_v,
3064 int src_pixel_stride_uv,
3065 uint8_t* dst_abgr,
3066 int dst_stride_abgr,
3067 int width,
3068 int height) {
3069 return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
3070 src_stride_u, src_pixel_stride_uv, dst_abgr,
3071 dst_stride_abgr, &kYvuI601Constants, width,
3072 height);
3073 }
3074
3075 #ifdef __cplusplus
3076 } // extern "C"
3077 } // namespace libyuv
3078 #endif
3079