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.
51 LIBYUV_API
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)52 int I420ToARGBMatrix(const uint8_t* src_y,
53 int src_stride_y,
54 const uint8_t* src_u,
55 int src_stride_u,
56 const uint8_t* src_v,
57 int src_stride_v,
58 uint8_t* dst_argb,
59 int dst_stride_argb,
60 const struct YuvConstants* yuvconstants,
61 int width,
62 int height) {
63 int y;
64 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
65 const uint8_t* v_buf, uint8_t* rgb_buf,
66 const struct YuvConstants* yuvconstants, int width) =
67 I422ToARGBRow_C;
68 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
69 return -1;
70 }
71 // Negative height means invert the image.
72 if (height < 0) {
73 height = -height;
74 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
75 dst_stride_argb = -dst_stride_argb;
76 }
77 #if defined(HAS_I422TOARGBROW_SSSE3)
78 if (TestCpuFlag(kCpuHasSSSE3)) {
79 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
80 if (IS_ALIGNED(width, 8)) {
81 I422ToARGBRow = I422ToARGBRow_SSSE3;
82 }
83 }
84 #endif
85 #if defined(HAS_I422TOARGBROW_AVX2)
86 if (TestCpuFlag(kCpuHasAVX2)) {
87 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
88 if (IS_ALIGNED(width, 16)) {
89 I422ToARGBRow = I422ToARGBRow_AVX2;
90 }
91 }
92 #endif
93 #if defined(HAS_I422TOARGBROW_NEON)
94 if (TestCpuFlag(kCpuHasNEON)) {
95 I422ToARGBRow = I422ToARGBRow_Any_NEON;
96 if (IS_ALIGNED(width, 8)) {
97 I422ToARGBRow = I422ToARGBRow_NEON;
98 }
99 }
100 #endif
101 #if defined(HAS_I422TOARGBROW_MMI)
102 if (TestCpuFlag(kCpuHasMMI)) {
103 I422ToARGBRow = I422ToARGBRow_Any_MMI;
104 if (IS_ALIGNED(width, 4)) {
105 I422ToARGBRow = I422ToARGBRow_MMI;
106 }
107 }
108 #endif
109 #if defined(HAS_I422TOARGBROW_MSA)
110 if (TestCpuFlag(kCpuHasMSA)) {
111 I422ToARGBRow = I422ToARGBRow_Any_MSA;
112 if (IS_ALIGNED(width, 8)) {
113 I422ToARGBRow = I422ToARGBRow_MSA;
114 }
115 }
116 #endif
117
118 for (y = 0; y < height; ++y) {
119 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
120 dst_argb += dst_stride_argb;
121 src_y += src_stride_y;
122 if (y & 1) {
123 src_u += src_stride_u;
124 src_v += src_stride_v;
125 }
126 }
127 return 0;
128 }
129
130 // Convert I420 to ARGB.
131 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)132 int I420ToARGB(const uint8_t* src_y,
133 int src_stride_y,
134 const uint8_t* src_u,
135 int src_stride_u,
136 const uint8_t* src_v,
137 int src_stride_v,
138 uint8_t* dst_argb,
139 int dst_stride_argb,
140 int width,
141 int height) {
142 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
143 src_stride_v, dst_argb, dst_stride_argb,
144 &kYuvI601Constants, width, height);
145 }
146
147 // Convert I420 to ABGR.
148 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)149 int I420ToABGR(const uint8_t* src_y,
150 int src_stride_y,
151 const uint8_t* src_u,
152 int src_stride_u,
153 const uint8_t* src_v,
154 int src_stride_v,
155 uint8_t* dst_abgr,
156 int dst_stride_abgr,
157 int width,
158 int height) {
159 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
160 src_stride_v, // Swap U and V
161 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
162 &kYvuI601Constants, // Use Yvu matrix
163 width, height);
164 }
165
166 // Convert J420 to ARGB.
167 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)168 int J420ToARGB(const uint8_t* src_y,
169 int src_stride_y,
170 const uint8_t* src_u,
171 int src_stride_u,
172 const uint8_t* src_v,
173 int src_stride_v,
174 uint8_t* dst_argb,
175 int dst_stride_argb,
176 int width,
177 int height) {
178 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
179 src_stride_v, dst_argb, dst_stride_argb,
180 &kYuvJPEGConstants, width, height);
181 }
182
183 // Convert J420 to ABGR.
184 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)185 int J420ToABGR(const uint8_t* src_y,
186 int src_stride_y,
187 const uint8_t* src_u,
188 int src_stride_u,
189 const uint8_t* src_v,
190 int src_stride_v,
191 uint8_t* dst_abgr,
192 int dst_stride_abgr,
193 int width,
194 int height) {
195 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
196 src_stride_v, // Swap U and V
197 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
198 &kYvuJPEGConstants, // Use Yvu matrix
199 width, height);
200 }
201
202 // Convert H420 to ARGB.
203 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)204 int H420ToARGB(const uint8_t* src_y,
205 int src_stride_y,
206 const uint8_t* src_u,
207 int src_stride_u,
208 const uint8_t* src_v,
209 int src_stride_v,
210 uint8_t* dst_argb,
211 int dst_stride_argb,
212 int width,
213 int height) {
214 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
215 src_stride_v, dst_argb, dst_stride_argb,
216 &kYuvH709Constants, width, height);
217 }
218
219 // Convert H420 to ABGR.
220 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)221 int H420ToABGR(const uint8_t* src_y,
222 int src_stride_y,
223 const uint8_t* src_u,
224 int src_stride_u,
225 const uint8_t* src_v,
226 int src_stride_v,
227 uint8_t* dst_abgr,
228 int dst_stride_abgr,
229 int width,
230 int height) {
231 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
232 src_stride_v, // Swap U and V
233 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
234 &kYvuH709Constants, // Use Yvu matrix
235 width, height);
236 }
237
238 // Convert U420 to ARGB.
239 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)240 int U420ToARGB(const uint8_t* src_y,
241 int src_stride_y,
242 const uint8_t* src_u,
243 int src_stride_u,
244 const uint8_t* src_v,
245 int src_stride_v,
246 uint8_t* dst_argb,
247 int dst_stride_argb,
248 int width,
249 int height) {
250 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
251 src_stride_v, dst_argb, dst_stride_argb,
252 &kYuv2020Constants, width, height);
253 }
254
255 // Convert U420 to ABGR.
256 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)257 int U420ToABGR(const uint8_t* src_y,
258 int src_stride_y,
259 const uint8_t* src_u,
260 int src_stride_u,
261 const uint8_t* src_v,
262 int src_stride_v,
263 uint8_t* dst_abgr,
264 int dst_stride_abgr,
265 int width,
266 int height) {
267 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
268 src_stride_v, // Swap U and V
269 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
270 &kYvu2020Constants, // Use Yvu matrix
271 width, height);
272 }
273
274 // Convert I422 to ARGB with matrix.
275 LIBYUV_API
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)276 int I422ToARGBMatrix(const uint8_t* src_y,
277 int src_stride_y,
278 const uint8_t* src_u,
279 int src_stride_u,
280 const uint8_t* src_v,
281 int src_stride_v,
282 uint8_t* dst_argb,
283 int dst_stride_argb,
284 const struct YuvConstants* yuvconstants,
285 int width,
286 int height) {
287 int y;
288 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
289 const uint8_t* v_buf, uint8_t* rgb_buf,
290 const struct YuvConstants* yuvconstants, int width) =
291 I422ToARGBRow_C;
292 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
293 return -1;
294 }
295 // Negative height means invert the image.
296 if (height < 0) {
297 height = -height;
298 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
299 dst_stride_argb = -dst_stride_argb;
300 }
301 // Coalesce rows.
302 if (src_stride_y == width && src_stride_u * 2 == width &&
303 src_stride_v * 2 == width && dst_stride_argb == width * 4) {
304 width *= height;
305 height = 1;
306 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
307 }
308 #if defined(HAS_I422TOARGBROW_SSSE3)
309 if (TestCpuFlag(kCpuHasSSSE3)) {
310 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
311 if (IS_ALIGNED(width, 8)) {
312 I422ToARGBRow = I422ToARGBRow_SSSE3;
313 }
314 }
315 #endif
316 #if defined(HAS_I422TOARGBROW_AVX2)
317 if (TestCpuFlag(kCpuHasAVX2)) {
318 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
319 if (IS_ALIGNED(width, 16)) {
320 I422ToARGBRow = I422ToARGBRow_AVX2;
321 }
322 }
323 #endif
324 #if defined(HAS_I422TOARGBROW_NEON)
325 if (TestCpuFlag(kCpuHasNEON)) {
326 I422ToARGBRow = I422ToARGBRow_Any_NEON;
327 if (IS_ALIGNED(width, 8)) {
328 I422ToARGBRow = I422ToARGBRow_NEON;
329 }
330 }
331 #endif
332 #if defined(HAS_I422TOARGBROW_MMI)
333 if (TestCpuFlag(kCpuHasMMI)) {
334 I422ToARGBRow = I422ToARGBRow_Any_MMI;
335 if (IS_ALIGNED(width, 4)) {
336 I422ToARGBRow = I422ToARGBRow_MMI;
337 }
338 }
339 #endif
340 #if defined(HAS_I422TOARGBROW_MSA)
341 if (TestCpuFlag(kCpuHasMSA)) {
342 I422ToARGBRow = I422ToARGBRow_Any_MSA;
343 if (IS_ALIGNED(width, 8)) {
344 I422ToARGBRow = I422ToARGBRow_MSA;
345 }
346 }
347 #endif
348
349 for (y = 0; y < height; ++y) {
350 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
351 dst_argb += dst_stride_argb;
352 src_y += src_stride_y;
353 src_u += src_stride_u;
354 src_v += src_stride_v;
355 }
356 return 0;
357 }
358
359 // Convert I422 to ARGB.
360 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)361 int I422ToARGB(const uint8_t* src_y,
362 int src_stride_y,
363 const uint8_t* src_u,
364 int src_stride_u,
365 const uint8_t* src_v,
366 int src_stride_v,
367 uint8_t* dst_argb,
368 int dst_stride_argb,
369 int width,
370 int height) {
371 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
372 src_stride_v, dst_argb, dst_stride_argb,
373 &kYuvI601Constants, width, height);
374 }
375
376 // Convert I422 to ABGR.
377 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)378 int I422ToABGR(const uint8_t* src_y,
379 int src_stride_y,
380 const uint8_t* src_u,
381 int src_stride_u,
382 const uint8_t* src_v,
383 int src_stride_v,
384 uint8_t* dst_abgr,
385 int dst_stride_abgr,
386 int width,
387 int height) {
388 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
389 src_stride_v, // Swap U and V
390 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
391 &kYvuI601Constants, // Use Yvu matrix
392 width, height);
393 }
394
395 // Convert J422 to ARGB.
396 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)397 int J422ToARGB(const uint8_t* src_y,
398 int src_stride_y,
399 const uint8_t* src_u,
400 int src_stride_u,
401 const uint8_t* src_v,
402 int src_stride_v,
403 uint8_t* dst_argb,
404 int dst_stride_argb,
405 int width,
406 int height) {
407 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
408 src_stride_v, dst_argb, dst_stride_argb,
409 &kYuvJPEGConstants, width, height);
410 }
411
412 // Convert J422 to ABGR.
413 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)414 int J422ToABGR(const uint8_t* src_y,
415 int src_stride_y,
416 const uint8_t* src_u,
417 int src_stride_u,
418 const uint8_t* src_v,
419 int src_stride_v,
420 uint8_t* dst_abgr,
421 int dst_stride_abgr,
422 int width,
423 int height) {
424 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
425 src_stride_v, // Swap U and V
426 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
427 &kYvuJPEGConstants, // Use Yvu matrix
428 width, height);
429 }
430
431 // Convert H422 to ARGB.
432 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)433 int H422ToARGB(const uint8_t* src_y,
434 int src_stride_y,
435 const uint8_t* src_u,
436 int src_stride_u,
437 const uint8_t* src_v,
438 int src_stride_v,
439 uint8_t* dst_argb,
440 int dst_stride_argb,
441 int width,
442 int height) {
443 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
444 src_stride_v, dst_argb, dst_stride_argb,
445 &kYuvH709Constants, width, height);
446 }
447
448 // Convert H422 to ABGR.
449 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)450 int H422ToABGR(const uint8_t* src_y,
451 int src_stride_y,
452 const uint8_t* src_u,
453 int src_stride_u,
454 const uint8_t* src_v,
455 int src_stride_v,
456 uint8_t* dst_abgr,
457 int dst_stride_abgr,
458 int width,
459 int height) {
460 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
461 src_stride_v, // Swap U and V
462 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
463 &kYvuH709Constants, // Use Yvu matrix
464 width, height);
465 }
466
467 // Convert U422 to ARGB.
468 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)469 int U422ToARGB(const uint8_t* src_y,
470 int src_stride_y,
471 const uint8_t* src_u,
472 int src_stride_u,
473 const uint8_t* src_v,
474 int src_stride_v,
475 uint8_t* dst_argb,
476 int dst_stride_argb,
477 int width,
478 int height) {
479 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
480 src_stride_v, dst_argb, dst_stride_argb,
481 &kYuv2020Constants, width, height);
482 }
483
484 // Convert U422 to ABGR.
485 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)486 int U422ToABGR(const uint8_t* src_y,
487 int src_stride_y,
488 const uint8_t* src_u,
489 int src_stride_u,
490 const uint8_t* src_v,
491 int src_stride_v,
492 uint8_t* dst_abgr,
493 int dst_stride_abgr,
494 int width,
495 int height) {
496 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
497 src_stride_v, // Swap U and V
498 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
499 &kYvu2020Constants, // Use Yvu matrix
500 width, height);
501 }
502
503 // Convert I444 to ARGB with matrix.
504 LIBYUV_API
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)505 int I444ToARGBMatrix(const uint8_t* src_y,
506 int src_stride_y,
507 const uint8_t* src_u,
508 int src_stride_u,
509 const uint8_t* src_v,
510 int src_stride_v,
511 uint8_t* dst_argb,
512 int dst_stride_argb,
513 const struct YuvConstants* yuvconstants,
514 int width,
515 int height) {
516 int y;
517 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
518 const uint8_t* v_buf, uint8_t* rgb_buf,
519 const struct YuvConstants* yuvconstants, int width) =
520 I444ToARGBRow_C;
521 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
522 return -1;
523 }
524 // Negative height means invert the image.
525 if (height < 0) {
526 height = -height;
527 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
528 dst_stride_argb = -dst_stride_argb;
529 }
530 // Coalesce rows.
531 if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
532 dst_stride_argb == width * 4) {
533 width *= height;
534 height = 1;
535 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
536 }
537 #if defined(HAS_I444TOARGBROW_SSSE3)
538 if (TestCpuFlag(kCpuHasSSSE3)) {
539 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
540 if (IS_ALIGNED(width, 8)) {
541 I444ToARGBRow = I444ToARGBRow_SSSE3;
542 }
543 }
544 #endif
545 #if defined(HAS_I444TOARGBROW_AVX2)
546 if (TestCpuFlag(kCpuHasAVX2)) {
547 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
548 if (IS_ALIGNED(width, 16)) {
549 I444ToARGBRow = I444ToARGBRow_AVX2;
550 }
551 }
552 #endif
553 #if defined(HAS_I444TOARGBROW_NEON)
554 if (TestCpuFlag(kCpuHasNEON)) {
555 I444ToARGBRow = I444ToARGBRow_Any_NEON;
556 if (IS_ALIGNED(width, 8)) {
557 I444ToARGBRow = I444ToARGBRow_NEON;
558 }
559 }
560 #endif
561 #if defined(HAS_I444TOARGBROW_MMI)
562 if (TestCpuFlag(kCpuHasMMI)) {
563 I444ToARGBRow = I444ToARGBRow_Any_MMI;
564 if (IS_ALIGNED(width, 4)) {
565 I444ToARGBRow = I444ToARGBRow_MMI;
566 }
567 }
568 #endif
569 #if defined(HAS_I444TOARGBROW_MSA)
570 if (TestCpuFlag(kCpuHasMSA)) {
571 I444ToARGBRow = I444ToARGBRow_Any_MSA;
572 if (IS_ALIGNED(width, 8)) {
573 I444ToARGBRow = I444ToARGBRow_MSA;
574 }
575 }
576 #endif
577
578 for (y = 0; y < height; ++y) {
579 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
580 dst_argb += dst_stride_argb;
581 src_y += src_stride_y;
582 src_u += src_stride_u;
583 src_v += src_stride_v;
584 }
585 return 0;
586 }
587
588 // Convert I444 to ARGB.
589 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)590 int I444ToARGB(const uint8_t* src_y,
591 int src_stride_y,
592 const uint8_t* src_u,
593 int src_stride_u,
594 const uint8_t* src_v,
595 int src_stride_v,
596 uint8_t* dst_argb,
597 int dst_stride_argb,
598 int width,
599 int height) {
600 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
601 src_stride_v, dst_argb, dst_stride_argb,
602 &kYuvI601Constants, width, height);
603 }
604
605 // Convert I444 to ABGR.
606 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)607 int I444ToABGR(const uint8_t* src_y,
608 int src_stride_y,
609 const uint8_t* src_u,
610 int src_stride_u,
611 const uint8_t* src_v,
612 int src_stride_v,
613 uint8_t* dst_abgr,
614 int dst_stride_abgr,
615 int width,
616 int height) {
617 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
618 src_stride_v, // Swap U and V
619 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
620 &kYvuI601Constants, // Use Yvu matrix
621 width, height);
622 }
623
624 // Convert J444 to ARGB.
625 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)626 int J444ToARGB(const uint8_t* src_y,
627 int src_stride_y,
628 const uint8_t* src_u,
629 int src_stride_u,
630 const uint8_t* src_v,
631 int src_stride_v,
632 uint8_t* dst_argb,
633 int dst_stride_argb,
634 int width,
635 int height) {
636 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
637 src_stride_v, dst_argb, dst_stride_argb,
638 &kYuvJPEGConstants, width, height);
639 }
640
641 // Convert J444 to ABGR.
642 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)643 int J444ToABGR(const uint8_t* src_y,
644 int src_stride_y,
645 const uint8_t* src_u,
646 int src_stride_u,
647 const uint8_t* src_v,
648 int src_stride_v,
649 uint8_t* dst_abgr,
650 int dst_stride_abgr,
651 int width,
652 int height) {
653 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
654 src_stride_v, // Swap U and V
655 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
656 &kYvuJPEGConstants, // Use Yvu matrix
657 width, height);
658 }
659
660 // Convert H444 to ARGB.
661 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)662 int H444ToARGB(const uint8_t* src_y,
663 int src_stride_y,
664 const uint8_t* src_u,
665 int src_stride_u,
666 const uint8_t* src_v,
667 int src_stride_v,
668 uint8_t* dst_argb,
669 int dst_stride_argb,
670 int width,
671 int height) {
672 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
673 src_stride_v, dst_argb, dst_stride_argb,
674 &kYuvH709Constants, width, height);
675 }
676
677 // Convert H444 to ABGR.
678 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)679 int H444ToABGR(const uint8_t* src_y,
680 int src_stride_y,
681 const uint8_t* src_u,
682 int src_stride_u,
683 const uint8_t* src_v,
684 int src_stride_v,
685 uint8_t* dst_abgr,
686 int dst_stride_abgr,
687 int width,
688 int height) {
689 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
690 src_stride_v, // Swap U and V
691 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
692 &kYvuH709Constants, // Use Yvu matrix
693 width, height);
694 }
695
696 // Convert U444 to ARGB.
697 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)698 int U444ToARGB(const uint8_t* src_y,
699 int src_stride_y,
700 const uint8_t* src_u,
701 int src_stride_u,
702 const uint8_t* src_v,
703 int src_stride_v,
704 uint8_t* dst_argb,
705 int dst_stride_argb,
706 int width,
707 int height) {
708 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
709 src_stride_v, dst_argb, dst_stride_argb,
710 &kYuv2020Constants, width, height);
711 }
712
713 // Convert U444 to ABGR.
714 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)715 int U444ToABGR(const uint8_t* src_y,
716 int src_stride_y,
717 const uint8_t* src_u,
718 int src_stride_u,
719 const uint8_t* src_v,
720 int src_stride_v,
721 uint8_t* dst_abgr,
722 int dst_stride_abgr,
723 int width,
724 int height) {
725 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
726 src_stride_v, // Swap U and V
727 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
728 &kYvu2020Constants, // Use Yvu matrix
729 width, height);
730 }
731
732 // Convert 10 bit YUV to ARGB with matrix.
733 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
734 // multiply 10 bit yuv into high bits to allow any number of bits.
735 LIBYUV_API
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)736 int I010ToAR30Matrix(const uint16_t* src_y,
737 int src_stride_y,
738 const uint16_t* src_u,
739 int src_stride_u,
740 const uint16_t* src_v,
741 int src_stride_v,
742 uint8_t* dst_ar30,
743 int dst_stride_ar30,
744 const struct YuvConstants* yuvconstants,
745 int width,
746 int height) {
747 int y;
748 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
749 const uint16_t* v_buf, uint8_t* rgb_buf,
750 const struct YuvConstants* yuvconstants, int width) =
751 I210ToAR30Row_C;
752 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
753 return -1;
754 }
755 // Negative height means invert the image.
756 if (height < 0) {
757 height = -height;
758 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
759 dst_stride_ar30 = -dst_stride_ar30;
760 }
761 #if defined(HAS_I210TOAR30ROW_SSSE3)
762 if (TestCpuFlag(kCpuHasSSSE3)) {
763 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
764 if (IS_ALIGNED(width, 8)) {
765 I210ToAR30Row = I210ToAR30Row_SSSE3;
766 }
767 }
768 #endif
769 #if defined(HAS_I210TOAR30ROW_AVX2)
770 if (TestCpuFlag(kCpuHasAVX2)) {
771 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
772 if (IS_ALIGNED(width, 16)) {
773 I210ToAR30Row = I210ToAR30Row_AVX2;
774 }
775 }
776 #endif
777 for (y = 0; y < height; ++y) {
778 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
779 dst_ar30 += dst_stride_ar30;
780 src_y += src_stride_y;
781 if (y & 1) {
782 src_u += src_stride_u;
783 src_v += src_stride_v;
784 }
785 }
786 return 0;
787 }
788
789 // Convert I010 to AR30.
790 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)791 int I010ToAR30(const uint16_t* src_y,
792 int src_stride_y,
793 const uint16_t* src_u,
794 int src_stride_u,
795 const uint16_t* src_v,
796 int src_stride_v,
797 uint8_t* dst_ar30,
798 int dst_stride_ar30,
799 int width,
800 int height) {
801 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
802 src_stride_v, dst_ar30, dst_stride_ar30,
803 &kYuvI601Constants, width, height);
804 }
805
806 // Convert H010 to AR30.
807 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)808 int H010ToAR30(const uint16_t* src_y,
809 int src_stride_y,
810 const uint16_t* src_u,
811 int src_stride_u,
812 const uint16_t* src_v,
813 int src_stride_v,
814 uint8_t* dst_ar30,
815 int dst_stride_ar30,
816 int width,
817 int height) {
818 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
819 src_stride_v, dst_ar30, dst_stride_ar30,
820 &kYuvH709Constants, width, height);
821 }
822
823 // Convert U010 to AR30.
824 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)825 int U010ToAR30(const uint16_t* src_y,
826 int src_stride_y,
827 const uint16_t* src_u,
828 int src_stride_u,
829 const uint16_t* src_v,
830 int src_stride_v,
831 uint8_t* dst_ar30,
832 int dst_stride_ar30,
833 int width,
834 int height) {
835 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
836 src_stride_v, dst_ar30, dst_stride_ar30,
837 &kYuv2020Constants, width, height);
838 }
839
840 // Convert I010 to AB30.
841 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)842 int I010ToAB30(const uint16_t* src_y,
843 int src_stride_y,
844 const uint16_t* src_u,
845 int src_stride_u,
846 const uint16_t* src_v,
847 int src_stride_v,
848 uint8_t* dst_ab30,
849 int dst_stride_ab30,
850 int width,
851 int height) {
852 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
853 src_stride_u, dst_ab30, dst_stride_ab30,
854 &kYvuI601Constants, width, height);
855 }
856
857 // Convert H010 to AB30.
858 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)859 int H010ToAB30(const uint16_t* src_y,
860 int src_stride_y,
861 const uint16_t* src_u,
862 int src_stride_u,
863 const uint16_t* src_v,
864 int src_stride_v,
865 uint8_t* dst_ab30,
866 int dst_stride_ab30,
867 int width,
868 int height) {
869 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
870 src_stride_u, dst_ab30, dst_stride_ab30,
871 &kYvuH709Constants, width, height);
872 }
873
874 // Convert U010 to AB30.
875 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)876 int U010ToAB30(const uint16_t* src_y,
877 int src_stride_y,
878 const uint16_t* src_u,
879 int src_stride_u,
880 const uint16_t* src_v,
881 int src_stride_v,
882 uint8_t* dst_ab30,
883 int dst_stride_ab30,
884 int width,
885 int height) {
886 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
887 src_stride_u, dst_ab30, dst_stride_ab30,
888 &kYuv2020Constants, width, height);
889 }
890
891 // Convert 10 bit YUV to ARGB with matrix.
892 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
893 // multiply 10 bit yuv into high bits to allow any number of bits.
894 LIBYUV_API
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)895 int I210ToAR30Matrix(const uint16_t* src_y,
896 int src_stride_y,
897 const uint16_t* src_u,
898 int src_stride_u,
899 const uint16_t* src_v,
900 int src_stride_v,
901 uint8_t* dst_ar30,
902 int dst_stride_ar30,
903 const struct YuvConstants* yuvconstants,
904 int width,
905 int height) {
906 int y;
907 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
908 const uint16_t* v_buf, uint8_t* rgb_buf,
909 const struct YuvConstants* yuvconstants, int width) =
910 I210ToAR30Row_C;
911 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
912 return -1;
913 }
914 // Negative height means invert the image.
915 if (height < 0) {
916 height = -height;
917 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
918 dst_stride_ar30 = -dst_stride_ar30;
919 }
920 #if defined(HAS_I210TOAR30ROW_SSSE3)
921 if (TestCpuFlag(kCpuHasSSSE3)) {
922 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
923 if (IS_ALIGNED(width, 8)) {
924 I210ToAR30Row = I210ToAR30Row_SSSE3;
925 }
926 }
927 #endif
928 #if defined(HAS_I210TOAR30ROW_AVX2)
929 if (TestCpuFlag(kCpuHasAVX2)) {
930 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
931 if (IS_ALIGNED(width, 16)) {
932 I210ToAR30Row = I210ToAR30Row_AVX2;
933 }
934 }
935 #endif
936 for (y = 0; y < height; ++y) {
937 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
938 dst_ar30 += dst_stride_ar30;
939 src_y += src_stride_y;
940 src_u += src_stride_u;
941 src_v += src_stride_v;
942 }
943 return 0;
944 }
945
946 // Convert I210 to AR30.
947 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)948 int I210ToAR30(const uint16_t* src_y,
949 int src_stride_y,
950 const uint16_t* src_u,
951 int src_stride_u,
952 const uint16_t* src_v,
953 int src_stride_v,
954 uint8_t* dst_ar30,
955 int dst_stride_ar30,
956 int width,
957 int height) {
958 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
959 src_stride_v, dst_ar30, dst_stride_ar30,
960 &kYuvI601Constants, width, height);
961 }
962
963 // Convert H210 to AR30.
964 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)965 int H210ToAR30(const uint16_t* src_y,
966 int src_stride_y,
967 const uint16_t* src_u,
968 int src_stride_u,
969 const uint16_t* src_v,
970 int src_stride_v,
971 uint8_t* dst_ar30,
972 int dst_stride_ar30,
973 int width,
974 int height) {
975 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
976 src_stride_v, dst_ar30, dst_stride_ar30,
977 &kYuvH709Constants, width, height);
978 }
979
980 // Convert U210 to AR30.
981 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)982 int U210ToAR30(const uint16_t* src_y,
983 int src_stride_y,
984 const uint16_t* src_u,
985 int src_stride_u,
986 const uint16_t* src_v,
987 int src_stride_v,
988 uint8_t* dst_ar30,
989 int dst_stride_ar30,
990 int width,
991 int height) {
992 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
993 src_stride_v, dst_ar30, dst_stride_ar30,
994 &kYuv2020Constants, width, height);
995 }
996
997 // Convert I210 to AB30.
998 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)999 int I210ToAB30(const uint16_t* src_y,
1000 int src_stride_y,
1001 const uint16_t* src_u,
1002 int src_stride_u,
1003 const uint16_t* src_v,
1004 int src_stride_v,
1005 uint8_t* dst_ab30,
1006 int dst_stride_ab30,
1007 int width,
1008 int height) {
1009 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1010 src_stride_u, dst_ab30, dst_stride_ab30,
1011 &kYvuI601Constants, width, height);
1012 }
1013
1014 // Convert H210 to AB30.
1015 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)1016 int H210ToAB30(const uint16_t* src_y,
1017 int src_stride_y,
1018 const uint16_t* src_u,
1019 int src_stride_u,
1020 const uint16_t* src_v,
1021 int src_stride_v,
1022 uint8_t* dst_ab30,
1023 int dst_stride_ab30,
1024 int width,
1025 int height) {
1026 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1027 src_stride_u, dst_ab30, dst_stride_ab30,
1028 &kYvuH709Constants, width, height);
1029 }
1030
1031 // Convert U210 to AB30.
1032 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)1033 int U210ToAB30(const uint16_t* src_y,
1034 int src_stride_y,
1035 const uint16_t* src_u,
1036 int src_stride_u,
1037 const uint16_t* src_v,
1038 int src_stride_v,
1039 uint8_t* dst_ab30,
1040 int dst_stride_ab30,
1041 int width,
1042 int height) {
1043 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1044 src_stride_u, dst_ab30, dst_stride_ab30,
1045 &kYuv2020Constants, width, height);
1046 }
1047
1048 // Convert 10 bit YUV to ARGB with matrix.
1049 LIBYUV_API
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)1050 int I010ToARGBMatrix(const uint16_t* src_y,
1051 int src_stride_y,
1052 const uint16_t* src_u,
1053 int src_stride_u,
1054 const uint16_t* src_v,
1055 int src_stride_v,
1056 uint8_t* dst_argb,
1057 int dst_stride_argb,
1058 const struct YuvConstants* yuvconstants,
1059 int width,
1060 int height) {
1061 int y;
1062 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1063 const uint16_t* v_buf, uint8_t* rgb_buf,
1064 const struct YuvConstants* yuvconstants, int width) =
1065 I210ToARGBRow_C;
1066 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1067 return -1;
1068 }
1069 // Negative height means invert the image.
1070 if (height < 0) {
1071 height = -height;
1072 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1073 dst_stride_argb = -dst_stride_argb;
1074 }
1075 #if defined(HAS_I210TOARGBROW_SSSE3)
1076 if (TestCpuFlag(kCpuHasSSSE3)) {
1077 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1078 if (IS_ALIGNED(width, 8)) {
1079 I210ToARGBRow = I210ToARGBRow_SSSE3;
1080 }
1081 }
1082 #endif
1083 #if defined(HAS_I210TOARGBROW_AVX2)
1084 if (TestCpuFlag(kCpuHasAVX2)) {
1085 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1086 if (IS_ALIGNED(width, 16)) {
1087 I210ToARGBRow = I210ToARGBRow_AVX2;
1088 }
1089 }
1090 #endif
1091 #if defined(HAS_I210TOARGBROW_MMI)
1092 if (TestCpuFlag(kCpuHasMMI)) {
1093 I210ToARGBRow = I210ToARGBRow_Any_MMI;
1094 if (IS_ALIGNED(width, 4)) {
1095 I210ToARGBRow = I210ToARGBRow_MMI;
1096 }
1097 }
1098 #endif
1099 for (y = 0; y < height; ++y) {
1100 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1101 dst_argb += dst_stride_argb;
1102 src_y += src_stride_y;
1103 if (y & 1) {
1104 src_u += src_stride_u;
1105 src_v += src_stride_v;
1106 }
1107 }
1108 return 0;
1109 }
1110
1111 // Convert I010 to ARGB.
1112 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)1113 int I010ToARGB(const uint16_t* src_y,
1114 int src_stride_y,
1115 const uint16_t* src_u,
1116 int src_stride_u,
1117 const uint16_t* src_v,
1118 int src_stride_v,
1119 uint8_t* dst_argb,
1120 int dst_stride_argb,
1121 int width,
1122 int height) {
1123 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1124 src_stride_v, dst_argb, dst_stride_argb,
1125 &kYuvI601Constants, width, height);
1126 }
1127
1128 // Convert I010 to ABGR.
1129 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)1130 int I010ToABGR(const uint16_t* src_y,
1131 int src_stride_y,
1132 const uint16_t* src_u,
1133 int src_stride_u,
1134 const uint16_t* src_v,
1135 int src_stride_v,
1136 uint8_t* dst_abgr,
1137 int dst_stride_abgr,
1138 int width,
1139 int height) {
1140 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1141 src_stride_v, // Swap U and V
1142 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1143 &kYvuI601Constants, // Use Yvu matrix
1144 width, height);
1145 }
1146
1147 // Convert H010 to ARGB.
1148 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)1149 int H010ToARGB(const uint16_t* src_y,
1150 int src_stride_y,
1151 const uint16_t* src_u,
1152 int src_stride_u,
1153 const uint16_t* src_v,
1154 int src_stride_v,
1155 uint8_t* dst_argb,
1156 int dst_stride_argb,
1157 int width,
1158 int height) {
1159 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1160 src_stride_v, dst_argb, dst_stride_argb,
1161 &kYuvH709Constants, width, height);
1162 }
1163
1164 // Convert H010 to ABGR.
1165 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)1166 int H010ToABGR(const uint16_t* src_y,
1167 int src_stride_y,
1168 const uint16_t* src_u,
1169 int src_stride_u,
1170 const uint16_t* src_v,
1171 int src_stride_v,
1172 uint8_t* dst_abgr,
1173 int dst_stride_abgr,
1174 int width,
1175 int height) {
1176 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1177 src_stride_v, // Swap U and V
1178 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1179 &kYvuH709Constants, // Use Yvu matrix
1180 width, height);
1181 }
1182
1183 // Convert U010 to ARGB.
1184 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)1185 int U010ToARGB(const uint16_t* src_y,
1186 int src_stride_y,
1187 const uint16_t* src_u,
1188 int src_stride_u,
1189 const uint16_t* src_v,
1190 int src_stride_v,
1191 uint8_t* dst_argb,
1192 int dst_stride_argb,
1193 int width,
1194 int height) {
1195 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1196 src_stride_v, dst_argb, dst_stride_argb,
1197 &kYuv2020Constants, width, height);
1198 }
1199
1200 // Convert U010 to ABGR.
1201 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)1202 int U010ToABGR(const uint16_t* src_y,
1203 int src_stride_y,
1204 const uint16_t* src_u,
1205 int src_stride_u,
1206 const uint16_t* src_v,
1207 int src_stride_v,
1208 uint8_t* dst_abgr,
1209 int dst_stride_abgr,
1210 int width,
1211 int height) {
1212 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1213 src_stride_v, // Swap U and V
1214 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1215 &kYvu2020Constants, // Use Yvu matrix
1216 width, height);
1217 }
1218
1219 // Convert 10 bit 422 YUV to ARGB with matrix.
1220 LIBYUV_API
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)1221 int I210ToARGBMatrix(const uint16_t* src_y,
1222 int src_stride_y,
1223 const uint16_t* src_u,
1224 int src_stride_u,
1225 const uint16_t* src_v,
1226 int src_stride_v,
1227 uint8_t* dst_argb,
1228 int dst_stride_argb,
1229 const struct YuvConstants* yuvconstants,
1230 int width,
1231 int height) {
1232 int y;
1233 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1234 const uint16_t* v_buf, uint8_t* rgb_buf,
1235 const struct YuvConstants* yuvconstants, int width) =
1236 I210ToARGBRow_C;
1237 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1238 return -1;
1239 }
1240 // Negative height means invert the image.
1241 if (height < 0) {
1242 height = -height;
1243 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1244 dst_stride_argb = -dst_stride_argb;
1245 }
1246 #if defined(HAS_I210TOARGBROW_SSSE3)
1247 if (TestCpuFlag(kCpuHasSSSE3)) {
1248 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1249 if (IS_ALIGNED(width, 8)) {
1250 I210ToARGBRow = I210ToARGBRow_SSSE3;
1251 }
1252 }
1253 #endif
1254 #if defined(HAS_I210TOARGBROW_AVX2)
1255 if (TestCpuFlag(kCpuHasAVX2)) {
1256 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1257 if (IS_ALIGNED(width, 16)) {
1258 I210ToARGBRow = I210ToARGBRow_AVX2;
1259 }
1260 }
1261 #endif
1262 #if defined(HAS_I210TOARGBROW_MMI)
1263 if (TestCpuFlag(kCpuHasMMI)) {
1264 I210ToARGBRow = I210ToARGBRow_Any_MMI;
1265 if (IS_ALIGNED(width, 4)) {
1266 I210ToARGBRow = I210ToARGBRow_MMI;
1267 }
1268 }
1269 #endif
1270 for (y = 0; y < height; ++y) {
1271 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1272 dst_argb += dst_stride_argb;
1273 src_y += src_stride_y;
1274 src_u += src_stride_u;
1275 src_v += src_stride_v;
1276 }
1277 return 0;
1278 }
1279
1280 // Convert I210 to ARGB.
1281 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)1282 int I210ToARGB(const uint16_t* src_y,
1283 int src_stride_y,
1284 const uint16_t* src_u,
1285 int src_stride_u,
1286 const uint16_t* src_v,
1287 int src_stride_v,
1288 uint8_t* dst_argb,
1289 int dst_stride_argb,
1290 int width,
1291 int height) {
1292 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1293 src_stride_v, dst_argb, dst_stride_argb,
1294 &kYuvI601Constants, width, height);
1295 }
1296
1297 // Convert I210 to ABGR.
1298 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)1299 int I210ToABGR(const uint16_t* src_y,
1300 int src_stride_y,
1301 const uint16_t* src_u,
1302 int src_stride_u,
1303 const uint16_t* src_v,
1304 int src_stride_v,
1305 uint8_t* dst_abgr,
1306 int dst_stride_abgr,
1307 int width,
1308 int height) {
1309 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1310 src_stride_v, // Swap U and V
1311 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1312 &kYvuI601Constants, // Use Yvu matrix
1313 width, height);
1314 }
1315
1316 // Convert H210 to ARGB.
1317 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)1318 int H210ToARGB(const uint16_t* src_y,
1319 int src_stride_y,
1320 const uint16_t* src_u,
1321 int src_stride_u,
1322 const uint16_t* src_v,
1323 int src_stride_v,
1324 uint8_t* dst_argb,
1325 int dst_stride_argb,
1326 int width,
1327 int height) {
1328 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1329 src_stride_v, dst_argb, dst_stride_argb,
1330 &kYuvH709Constants, width, height);
1331 }
1332
1333 // Convert H210 to ABGR.
1334 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)1335 int H210ToABGR(const uint16_t* src_y,
1336 int src_stride_y,
1337 const uint16_t* src_u,
1338 int src_stride_u,
1339 const uint16_t* src_v,
1340 int src_stride_v,
1341 uint8_t* dst_abgr,
1342 int dst_stride_abgr,
1343 int width,
1344 int height) {
1345 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1346 src_stride_v, // Swap U and V
1347 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1348 &kYvuH709Constants, // Use Yvu matrix
1349 width, height);
1350 }
1351
1352 // Convert U210 to ARGB.
1353 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)1354 int U210ToARGB(const uint16_t* src_y,
1355 int src_stride_y,
1356 const uint16_t* src_u,
1357 int src_stride_u,
1358 const uint16_t* src_v,
1359 int src_stride_v,
1360 uint8_t* dst_argb,
1361 int dst_stride_argb,
1362 int width,
1363 int height) {
1364 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1365 src_stride_v, dst_argb, dst_stride_argb,
1366 &kYuv2020Constants, width, height);
1367 }
1368
1369 // Convert U210 to ABGR.
1370 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)1371 int U210ToABGR(const uint16_t* src_y,
1372 int src_stride_y,
1373 const uint16_t* src_u,
1374 int src_stride_u,
1375 const uint16_t* src_v,
1376 int src_stride_v,
1377 uint8_t* dst_abgr,
1378 int dst_stride_abgr,
1379 int width,
1380 int height) {
1381 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1382 src_stride_v, // Swap U and V
1383 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1384 &kYvu2020Constants, // Use Yvu matrix
1385 width, height);
1386 }
1387
1388 // Convert I420 with Alpha to preattenuated ARGB with matrix.
1389 LIBYUV_API
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)1390 int I420AlphaToARGBMatrix(const uint8_t* src_y,
1391 int src_stride_y,
1392 const uint8_t* src_u,
1393 int src_stride_u,
1394 const uint8_t* src_v,
1395 int src_stride_v,
1396 const uint8_t* src_a,
1397 int src_stride_a,
1398 uint8_t* dst_argb,
1399 int dst_stride_argb,
1400 const struct YuvConstants* yuvconstants,
1401 int width,
1402 int height,
1403 int attenuate) {
1404 int y;
1405 void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1406 const uint8_t* v_buf, const uint8_t* a_buf,
1407 uint8_t* dst_argb,
1408 const struct YuvConstants* yuvconstants,
1409 int width) = I422AlphaToARGBRow_C;
1410 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
1411 int width) = ARGBAttenuateRow_C;
1412 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1413 return -1;
1414 }
1415 // Negative height means invert the image.
1416 if (height < 0) {
1417 height = -height;
1418 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1419 dst_stride_argb = -dst_stride_argb;
1420 }
1421 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
1422 if (TestCpuFlag(kCpuHasSSSE3)) {
1423 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
1424 if (IS_ALIGNED(width, 8)) {
1425 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
1426 }
1427 }
1428 #endif
1429 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
1430 if (TestCpuFlag(kCpuHasAVX2)) {
1431 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
1432 if (IS_ALIGNED(width, 16)) {
1433 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
1434 }
1435 }
1436 #endif
1437 #if defined(HAS_I422ALPHATOARGBROW_NEON)
1438 if (TestCpuFlag(kCpuHasNEON)) {
1439 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
1440 if (IS_ALIGNED(width, 8)) {
1441 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
1442 }
1443 }
1444 #endif
1445 #if defined(HAS_I422ALPHATOARGBROW_MMI)
1446 if (TestCpuFlag(kCpuHasMMI)) {
1447 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MMI;
1448 if (IS_ALIGNED(width, 4)) {
1449 I422AlphaToARGBRow = I422AlphaToARGBRow_MMI;
1450 }
1451 }
1452 #endif
1453 #if defined(HAS_I422ALPHATOARGBROW_MSA)
1454 if (TestCpuFlag(kCpuHasMSA)) {
1455 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
1456 if (IS_ALIGNED(width, 8)) {
1457 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
1458 }
1459 }
1460 #endif
1461 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
1462 if (TestCpuFlag(kCpuHasSSSE3)) {
1463 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1464 if (IS_ALIGNED(width, 4)) {
1465 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1466 }
1467 }
1468 #endif
1469 #if defined(HAS_ARGBATTENUATEROW_AVX2)
1470 if (TestCpuFlag(kCpuHasAVX2)) {
1471 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1472 if (IS_ALIGNED(width, 8)) {
1473 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1474 }
1475 }
1476 #endif
1477 #if defined(HAS_ARGBATTENUATEROW_NEON)
1478 if (TestCpuFlag(kCpuHasNEON)) {
1479 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1480 if (IS_ALIGNED(width, 8)) {
1481 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1482 }
1483 }
1484 #endif
1485 #if defined(HAS_ARGBATTENUATEROW_MMI)
1486 if (TestCpuFlag(kCpuHasMMI)) {
1487 ARGBAttenuateRow = ARGBAttenuateRow_Any_MMI;
1488 if (IS_ALIGNED(width, 2)) {
1489 ARGBAttenuateRow = ARGBAttenuateRow_MMI;
1490 }
1491 }
1492 #endif
1493 #if defined(HAS_ARGBATTENUATEROW_MSA)
1494 if (TestCpuFlag(kCpuHasMSA)) {
1495 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
1496 if (IS_ALIGNED(width, 8)) {
1497 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
1498 }
1499 }
1500 #endif
1501
1502 for (y = 0; y < height; ++y) {
1503 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
1504 width);
1505 if (attenuate) {
1506 ARGBAttenuateRow(dst_argb, dst_argb, width);
1507 }
1508 dst_argb += dst_stride_argb;
1509 src_a += src_stride_a;
1510 src_y += src_stride_y;
1511 if (y & 1) {
1512 src_u += src_stride_u;
1513 src_v += src_stride_v;
1514 }
1515 }
1516 return 0;
1517 }
1518
1519 // Convert I420 with Alpha to ARGB.
1520 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)1521 int I420AlphaToARGB(const uint8_t* src_y,
1522 int src_stride_y,
1523 const uint8_t* src_u,
1524 int src_stride_u,
1525 const uint8_t* src_v,
1526 int src_stride_v,
1527 const uint8_t* src_a,
1528 int src_stride_a,
1529 uint8_t* dst_argb,
1530 int dst_stride_argb,
1531 int width,
1532 int height,
1533 int attenuate) {
1534 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1535 src_stride_v, src_a, src_stride_a, dst_argb,
1536 dst_stride_argb, &kYuvI601Constants, width,
1537 height, attenuate);
1538 }
1539
1540 // Convert I420 with Alpha to ABGR.
1541 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)1542 int I420AlphaToABGR(const uint8_t* src_y,
1543 int src_stride_y,
1544 const uint8_t* src_u,
1545 int src_stride_u,
1546 const uint8_t* src_v,
1547 int src_stride_v,
1548 const uint8_t* src_a,
1549 int src_stride_a,
1550 uint8_t* dst_abgr,
1551 int dst_stride_abgr,
1552 int width,
1553 int height,
1554 int attenuate) {
1555 return I420AlphaToARGBMatrix(
1556 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
1557 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
1558 &kYvuI601Constants, // Use Yvu matrix
1559 width, height, attenuate);
1560 }
1561
1562 // Convert I400 to ARGB with matrix.
1563 LIBYUV_API
I400ToARGBMatrix(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1564 int I400ToARGBMatrix(const uint8_t* src_y,
1565 int src_stride_y,
1566 uint8_t* dst_argb,
1567 int dst_stride_argb,
1568 const struct YuvConstants* yuvconstants,
1569 int width,
1570 int height) {
1571 int y;
1572 void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
1573 const struct YuvConstants* yuvconstants, int width) =
1574 I400ToARGBRow_C;
1575 if (!src_y || !dst_argb || width <= 0 || height == 0) {
1576 return -1;
1577 }
1578 // Negative height means invert the image.
1579 if (height < 0) {
1580 height = -height;
1581 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1582 dst_stride_argb = -dst_stride_argb;
1583 }
1584 // Coalesce rows.
1585 if (src_stride_y == width && dst_stride_argb == width * 4) {
1586 width *= height;
1587 height = 1;
1588 src_stride_y = dst_stride_argb = 0;
1589 }
1590 #if defined(HAS_I400TOARGBROW_SSE2)
1591 if (TestCpuFlag(kCpuHasSSE2)) {
1592 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
1593 if (IS_ALIGNED(width, 8)) {
1594 I400ToARGBRow = I400ToARGBRow_SSE2;
1595 }
1596 }
1597 #endif
1598 #if defined(HAS_I400TOARGBROW_AVX2)
1599 if (TestCpuFlag(kCpuHasAVX2)) {
1600 I400ToARGBRow = I400ToARGBRow_Any_AVX2;
1601 if (IS_ALIGNED(width, 16)) {
1602 I400ToARGBRow = I400ToARGBRow_AVX2;
1603 }
1604 }
1605 #endif
1606 #if defined(HAS_I400TOARGBROW_NEON)
1607 if (TestCpuFlag(kCpuHasNEON)) {
1608 I400ToARGBRow = I400ToARGBRow_Any_NEON;
1609 if (IS_ALIGNED(width, 8)) {
1610 I400ToARGBRow = I400ToARGBRow_NEON;
1611 }
1612 }
1613 #endif
1614 #if defined(HAS_I400TOARGBROW_MMI)
1615 if (TestCpuFlag(kCpuHasMMI)) {
1616 I400ToARGBRow = I400ToARGBRow_Any_MMI;
1617 if (IS_ALIGNED(width, 8)) {
1618 I400ToARGBRow = I400ToARGBRow_MMI;
1619 }
1620 }
1621 #endif
1622 #if defined(HAS_I400TOARGBROW_MSA)
1623 if (TestCpuFlag(kCpuHasMSA)) {
1624 I400ToARGBRow = I400ToARGBRow_Any_MSA;
1625 if (IS_ALIGNED(width, 16)) {
1626 I400ToARGBRow = I400ToARGBRow_MSA;
1627 }
1628 }
1629 #endif
1630
1631 for (y = 0; y < height; ++y) {
1632 I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
1633 dst_argb += dst_stride_argb;
1634 src_y += src_stride_y;
1635 }
1636 return 0;
1637 }
1638
1639 // Convert I400 to ARGB.
1640 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1641 int I400ToARGB(const uint8_t* src_y,
1642 int src_stride_y,
1643 uint8_t* dst_argb,
1644 int dst_stride_argb,
1645 int width,
1646 int height) {
1647 return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
1648 &kYuvI601Constants, width, height);
1649 }
1650
1651 // Convert J400 to ARGB.
1652 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1653 int J400ToARGB(const uint8_t* src_y,
1654 int src_stride_y,
1655 uint8_t* dst_argb,
1656 int dst_stride_argb,
1657 int width,
1658 int height) {
1659 int y;
1660 void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
1661 J400ToARGBRow_C;
1662 if (!src_y || !dst_argb || width <= 0 || height == 0) {
1663 return -1;
1664 }
1665 // Negative height means invert the image.
1666 if (height < 0) {
1667 height = -height;
1668 src_y = src_y + (height - 1) * src_stride_y;
1669 src_stride_y = -src_stride_y;
1670 }
1671 // Coalesce rows.
1672 if (src_stride_y == width && dst_stride_argb == width * 4) {
1673 width *= height;
1674 height = 1;
1675 src_stride_y = dst_stride_argb = 0;
1676 }
1677 #if defined(HAS_J400TOARGBROW_SSE2)
1678 if (TestCpuFlag(kCpuHasSSE2)) {
1679 J400ToARGBRow = J400ToARGBRow_Any_SSE2;
1680 if (IS_ALIGNED(width, 8)) {
1681 J400ToARGBRow = J400ToARGBRow_SSE2;
1682 }
1683 }
1684 #endif
1685 #if defined(HAS_J400TOARGBROW_AVX2)
1686 if (TestCpuFlag(kCpuHasAVX2)) {
1687 J400ToARGBRow = J400ToARGBRow_Any_AVX2;
1688 if (IS_ALIGNED(width, 16)) {
1689 J400ToARGBRow = J400ToARGBRow_AVX2;
1690 }
1691 }
1692 #endif
1693 #if defined(HAS_J400TOARGBROW_NEON)
1694 if (TestCpuFlag(kCpuHasNEON)) {
1695 J400ToARGBRow = J400ToARGBRow_Any_NEON;
1696 if (IS_ALIGNED(width, 8)) {
1697 J400ToARGBRow = J400ToARGBRow_NEON;
1698 }
1699 }
1700 #endif
1701 #if defined(HAS_J400TOARGBROW_MMI)
1702 if (TestCpuFlag(kCpuHasMMI)) {
1703 J400ToARGBRow = J400ToARGBRow_Any_MMI;
1704 if (IS_ALIGNED(width, 4)) {
1705 J400ToARGBRow = J400ToARGBRow_MMI;
1706 }
1707 }
1708 #endif
1709 #if defined(HAS_J400TOARGBROW_MSA)
1710 if (TestCpuFlag(kCpuHasMSA)) {
1711 J400ToARGBRow = J400ToARGBRow_Any_MSA;
1712 if (IS_ALIGNED(width, 16)) {
1713 J400ToARGBRow = J400ToARGBRow_MSA;
1714 }
1715 }
1716 #endif
1717 for (y = 0; y < height; ++y) {
1718 J400ToARGBRow(src_y, dst_argb, width);
1719 src_y += src_stride_y;
1720 dst_argb += dst_stride_argb;
1721 }
1722 return 0;
1723 }
1724
1725 // Shuffle table for converting BGRA to ARGB.
1726 static const uvec8 kShuffleMaskBGRAToARGB = {
1727 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
1728
1729 // Shuffle table for converting ABGR to ARGB.
1730 static const uvec8 kShuffleMaskABGRToARGB = {
1731 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
1732
1733 // Shuffle table for converting RGBA to ARGB.
1734 static const uvec8 kShuffleMaskRGBAToARGB = {
1735 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
1736
1737 // Convert BGRA to ARGB.
1738 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1739 int BGRAToARGB(const uint8_t* src_bgra,
1740 int src_stride_bgra,
1741 uint8_t* dst_argb,
1742 int dst_stride_argb,
1743 int width,
1744 int height) {
1745 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1746 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1747 }
1748
1749 // Convert ARGB to BGRA (same as BGRAToARGB).
1750 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1751 int ARGBToBGRA(const uint8_t* src_bgra,
1752 int src_stride_bgra,
1753 uint8_t* dst_argb,
1754 int dst_stride_argb,
1755 int width,
1756 int height) {
1757 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1758 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1759 }
1760
1761 // Convert ABGR to ARGB.
1762 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1763 int ABGRToARGB(const uint8_t* src_abgr,
1764 int src_stride_abgr,
1765 uint8_t* dst_argb,
1766 int dst_stride_argb,
1767 int width,
1768 int height) {
1769 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1770 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1771 }
1772
1773 // Convert ARGB to ABGR to (same as ABGRToARGB).
1774 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1775 int ARGBToABGR(const uint8_t* src_abgr,
1776 int src_stride_abgr,
1777 uint8_t* dst_argb,
1778 int dst_stride_argb,
1779 int width,
1780 int height) {
1781 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1782 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1783 }
1784
1785 // Convert RGBA to ARGB.
1786 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1787 int RGBAToARGB(const uint8_t* src_rgba,
1788 int src_stride_rgba,
1789 uint8_t* dst_argb,
1790 int dst_stride_argb,
1791 int width,
1792 int height) {
1793 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
1794 (const uint8_t*)(&kShuffleMaskRGBAToARGB), width, height);
1795 }
1796
1797 // Convert RGB24 to ARGB.
1798 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1799 int RGB24ToARGB(const uint8_t* src_rgb24,
1800 int src_stride_rgb24,
1801 uint8_t* dst_argb,
1802 int dst_stride_argb,
1803 int width,
1804 int height) {
1805 int y;
1806 void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1807 RGB24ToARGBRow_C;
1808 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
1809 return -1;
1810 }
1811 // Negative height means invert the image.
1812 if (height < 0) {
1813 height = -height;
1814 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
1815 src_stride_rgb24 = -src_stride_rgb24;
1816 }
1817 // Coalesce rows.
1818 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
1819 width *= height;
1820 height = 1;
1821 src_stride_rgb24 = dst_stride_argb = 0;
1822 }
1823 #if defined(HAS_RGB24TOARGBROW_SSSE3)
1824 if (TestCpuFlag(kCpuHasSSSE3)) {
1825 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
1826 if (IS_ALIGNED(width, 16)) {
1827 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
1828 }
1829 }
1830 #endif
1831 #if defined(HAS_RGB24TOARGBROW_NEON)
1832 if (TestCpuFlag(kCpuHasNEON)) {
1833 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
1834 if (IS_ALIGNED(width, 8)) {
1835 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
1836 }
1837 }
1838 #endif
1839 #if defined(HAS_RGB24TOARGBROW_MMI)
1840 if (TestCpuFlag(kCpuHasMMI)) {
1841 RGB24ToARGBRow = RGB24ToARGBRow_Any_MMI;
1842 if (IS_ALIGNED(width, 4)) {
1843 RGB24ToARGBRow = RGB24ToARGBRow_MMI;
1844 }
1845 }
1846 #endif
1847 #if defined(HAS_RGB24TOARGBROW_MSA)
1848 if (TestCpuFlag(kCpuHasMSA)) {
1849 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
1850 if (IS_ALIGNED(width, 16)) {
1851 RGB24ToARGBRow = RGB24ToARGBRow_MSA;
1852 }
1853 }
1854 #endif
1855
1856 for (y = 0; y < height; ++y) {
1857 RGB24ToARGBRow(src_rgb24, dst_argb, width);
1858 src_rgb24 += src_stride_rgb24;
1859 dst_argb += dst_stride_argb;
1860 }
1861 return 0;
1862 }
1863
1864 // Convert RAW to ARGB.
1865 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1866 int RAWToARGB(const uint8_t* src_raw,
1867 int src_stride_raw,
1868 uint8_t* dst_argb,
1869 int dst_stride_argb,
1870 int width,
1871 int height) {
1872 int y;
1873 void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1874 RAWToARGBRow_C;
1875 if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1876 return -1;
1877 }
1878 // Negative height means invert the image.
1879 if (height < 0) {
1880 height = -height;
1881 src_raw = src_raw + (height - 1) * src_stride_raw;
1882 src_stride_raw = -src_stride_raw;
1883 }
1884 // Coalesce rows.
1885 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1886 width *= height;
1887 height = 1;
1888 src_stride_raw = dst_stride_argb = 0;
1889 }
1890 #if defined(HAS_RAWTOARGBROW_SSSE3)
1891 if (TestCpuFlag(kCpuHasSSSE3)) {
1892 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1893 if (IS_ALIGNED(width, 16)) {
1894 RAWToARGBRow = RAWToARGBRow_SSSE3;
1895 }
1896 }
1897 #endif
1898 #if defined(HAS_RAWTOARGBROW_NEON)
1899 if (TestCpuFlag(kCpuHasNEON)) {
1900 RAWToARGBRow = RAWToARGBRow_Any_NEON;
1901 if (IS_ALIGNED(width, 8)) {
1902 RAWToARGBRow = RAWToARGBRow_NEON;
1903 }
1904 }
1905 #endif
1906 #if defined(HAS_RAWTOARGBROW_MMI)
1907 if (TestCpuFlag(kCpuHasMMI)) {
1908 RAWToARGBRow = RAWToARGBRow_Any_MMI;
1909 if (IS_ALIGNED(width, 4)) {
1910 RAWToARGBRow = RAWToARGBRow_MMI;
1911 }
1912 }
1913 #endif
1914 #if defined(HAS_RAWTOARGBROW_MSA)
1915 if (TestCpuFlag(kCpuHasMSA)) {
1916 RAWToARGBRow = RAWToARGBRow_Any_MSA;
1917 if (IS_ALIGNED(width, 16)) {
1918 RAWToARGBRow = RAWToARGBRow_MSA;
1919 }
1920 }
1921 #endif
1922
1923 for (y = 0; y < height; ++y) {
1924 RAWToARGBRow(src_raw, dst_argb, width);
1925 src_raw += src_stride_raw;
1926 dst_argb += dst_stride_argb;
1927 }
1928 return 0;
1929 }
1930
1931 // Convert RAW to RGBA.
1932 LIBYUV_API
RAWToRGBA(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1933 int RAWToRGBA(const uint8_t* src_raw,
1934 int src_stride_raw,
1935 uint8_t* dst_rgba,
1936 int dst_stride_rgba,
1937 int width,
1938 int height) {
1939 int y;
1940 void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
1941 RAWToRGBARow_C;
1942 if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
1943 return -1;
1944 }
1945 // Negative height means invert the image.
1946 if (height < 0) {
1947 height = -height;
1948 src_raw = src_raw + (height - 1) * src_stride_raw;
1949 src_stride_raw = -src_stride_raw;
1950 }
1951 // Coalesce rows.
1952 if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
1953 width *= height;
1954 height = 1;
1955 src_stride_raw = dst_stride_rgba = 0;
1956 }
1957 #if defined(HAS_RAWTORGBAROW_SSSE3)
1958 if (TestCpuFlag(kCpuHasSSSE3)) {
1959 RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
1960 if (IS_ALIGNED(width, 16)) {
1961 RAWToRGBARow = RAWToRGBARow_SSSE3;
1962 }
1963 }
1964 #endif
1965 #if defined(HAS_RAWTORGBAROW_NEON)
1966 if (TestCpuFlag(kCpuHasNEON)) {
1967 RAWToRGBARow = RAWToRGBARow_Any_NEON;
1968 if (IS_ALIGNED(width, 8)) {
1969 RAWToRGBARow = RAWToRGBARow_NEON;
1970 }
1971 }
1972 #endif
1973
1974 for (y = 0; y < height; ++y) {
1975 RAWToRGBARow(src_raw, dst_rgba, width);
1976 src_raw += src_stride_raw;
1977 dst_rgba += dst_stride_rgba;
1978 }
1979 return 0;
1980 }
1981
1982 // Convert RGB565 to ARGB.
1983 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1984 int RGB565ToARGB(const uint8_t* src_rgb565,
1985 int src_stride_rgb565,
1986 uint8_t* dst_argb,
1987 int dst_stride_argb,
1988 int width,
1989 int height) {
1990 int y;
1991 void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
1992 int width) = RGB565ToARGBRow_C;
1993 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1994 return -1;
1995 }
1996 // Negative height means invert the image.
1997 if (height < 0) {
1998 height = -height;
1999 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
2000 src_stride_rgb565 = -src_stride_rgb565;
2001 }
2002 // Coalesce rows.
2003 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
2004 width *= height;
2005 height = 1;
2006 src_stride_rgb565 = dst_stride_argb = 0;
2007 }
2008 #if defined(HAS_RGB565TOARGBROW_SSE2)
2009 if (TestCpuFlag(kCpuHasSSE2)) {
2010 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
2011 if (IS_ALIGNED(width, 8)) {
2012 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
2013 }
2014 }
2015 #endif
2016 #if defined(HAS_RGB565TOARGBROW_AVX2)
2017 if (TestCpuFlag(kCpuHasAVX2)) {
2018 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
2019 if (IS_ALIGNED(width, 16)) {
2020 RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
2021 }
2022 }
2023 #endif
2024 #if defined(HAS_RGB565TOARGBROW_NEON)
2025 if (TestCpuFlag(kCpuHasNEON)) {
2026 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
2027 if (IS_ALIGNED(width, 8)) {
2028 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
2029 }
2030 }
2031 #endif
2032 #if defined(HAS_RGB565TOARGBROW_MMI)
2033 if (TestCpuFlag(kCpuHasMMI)) {
2034 RGB565ToARGBRow = RGB565ToARGBRow_Any_MMI;
2035 if (IS_ALIGNED(width, 4)) {
2036 RGB565ToARGBRow = RGB565ToARGBRow_MMI;
2037 }
2038 }
2039 #endif
2040 #if defined(HAS_RGB565TOARGBROW_MSA)
2041 if (TestCpuFlag(kCpuHasMSA)) {
2042 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
2043 if (IS_ALIGNED(width, 16)) {
2044 RGB565ToARGBRow = RGB565ToARGBRow_MSA;
2045 }
2046 }
2047 #endif
2048
2049 for (y = 0; y < height; ++y) {
2050 RGB565ToARGBRow(src_rgb565, dst_argb, width);
2051 src_rgb565 += src_stride_rgb565;
2052 dst_argb += dst_stride_argb;
2053 }
2054 return 0;
2055 }
2056
2057 // Convert ARGB1555 to ARGB.
2058 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2059 int ARGB1555ToARGB(const uint8_t* src_argb1555,
2060 int src_stride_argb1555,
2061 uint8_t* dst_argb,
2062 int dst_stride_argb,
2063 int width,
2064 int height) {
2065 int y;
2066 void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
2067 int width) = ARGB1555ToARGBRow_C;
2068 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
2069 return -1;
2070 }
2071 // Negative height means invert the image.
2072 if (height < 0) {
2073 height = -height;
2074 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
2075 src_stride_argb1555 = -src_stride_argb1555;
2076 }
2077 // Coalesce rows.
2078 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
2079 width *= height;
2080 height = 1;
2081 src_stride_argb1555 = dst_stride_argb = 0;
2082 }
2083 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
2084 if (TestCpuFlag(kCpuHasSSE2)) {
2085 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
2086 if (IS_ALIGNED(width, 8)) {
2087 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
2088 }
2089 }
2090 #endif
2091 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
2092 if (TestCpuFlag(kCpuHasAVX2)) {
2093 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
2094 if (IS_ALIGNED(width, 16)) {
2095 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
2096 }
2097 }
2098 #endif
2099 #if defined(HAS_ARGB1555TOARGBROW_NEON)
2100 if (TestCpuFlag(kCpuHasNEON)) {
2101 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
2102 if (IS_ALIGNED(width, 8)) {
2103 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
2104 }
2105 }
2106 #endif
2107 #if defined(HAS_ARGB1555TOARGBROW_MMI)
2108 if (TestCpuFlag(kCpuHasMMI)) {
2109 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MMI;
2110 if (IS_ALIGNED(width, 4)) {
2111 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MMI;
2112 }
2113 }
2114 #endif
2115 #if defined(HAS_ARGB1555TOARGBROW_MSA)
2116 if (TestCpuFlag(kCpuHasMSA)) {
2117 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
2118 if (IS_ALIGNED(width, 16)) {
2119 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
2120 }
2121 }
2122 #endif
2123
2124 for (y = 0; y < height; ++y) {
2125 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
2126 src_argb1555 += src_stride_argb1555;
2127 dst_argb += dst_stride_argb;
2128 }
2129 return 0;
2130 }
2131
2132 // Convert ARGB4444 to ARGB.
2133 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2134 int ARGB4444ToARGB(const uint8_t* src_argb4444,
2135 int src_stride_argb4444,
2136 uint8_t* dst_argb,
2137 int dst_stride_argb,
2138 int width,
2139 int height) {
2140 int y;
2141 void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
2142 int width) = ARGB4444ToARGBRow_C;
2143 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
2144 return -1;
2145 }
2146 // Negative height means invert the image.
2147 if (height < 0) {
2148 height = -height;
2149 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
2150 src_stride_argb4444 = -src_stride_argb4444;
2151 }
2152 // Coalesce rows.
2153 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
2154 width *= height;
2155 height = 1;
2156 src_stride_argb4444 = dst_stride_argb = 0;
2157 }
2158 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
2159 if (TestCpuFlag(kCpuHasSSE2)) {
2160 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
2161 if (IS_ALIGNED(width, 8)) {
2162 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
2163 }
2164 }
2165 #endif
2166 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
2167 if (TestCpuFlag(kCpuHasAVX2)) {
2168 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
2169 if (IS_ALIGNED(width, 16)) {
2170 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
2171 }
2172 }
2173 #endif
2174 #if defined(HAS_ARGB4444TOARGBROW_NEON)
2175 if (TestCpuFlag(kCpuHasNEON)) {
2176 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
2177 if (IS_ALIGNED(width, 8)) {
2178 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
2179 }
2180 }
2181 #endif
2182 #if defined(HAS_ARGB4444TOARGBROW_MMI)
2183 if (TestCpuFlag(kCpuHasMMI)) {
2184 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MMI;
2185 if (IS_ALIGNED(width, 4)) {
2186 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MMI;
2187 }
2188 }
2189 #endif
2190 #if defined(HAS_ARGB4444TOARGBROW_MSA)
2191 if (TestCpuFlag(kCpuHasMSA)) {
2192 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
2193 if (IS_ALIGNED(width, 16)) {
2194 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
2195 }
2196 }
2197 #endif
2198
2199 for (y = 0; y < height; ++y) {
2200 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
2201 src_argb4444 += src_stride_argb4444;
2202 dst_argb += dst_stride_argb;
2203 }
2204 return 0;
2205 }
2206
2207 // Convert AR30 to ARGB.
2208 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2209 int AR30ToARGB(const uint8_t* src_ar30,
2210 int src_stride_ar30,
2211 uint8_t* dst_argb,
2212 int dst_stride_argb,
2213 int width,
2214 int height) {
2215 int y;
2216 if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
2217 return -1;
2218 }
2219 // Negative height means invert the image.
2220 if (height < 0) {
2221 height = -height;
2222 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2223 src_stride_ar30 = -src_stride_ar30;
2224 }
2225 // Coalesce rows.
2226 if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
2227 width *= height;
2228 height = 1;
2229 src_stride_ar30 = dst_stride_argb = 0;
2230 }
2231 for (y = 0; y < height; ++y) {
2232 AR30ToARGBRow_C(src_ar30, dst_argb, width);
2233 src_ar30 += src_stride_ar30;
2234 dst_argb += dst_stride_argb;
2235 }
2236 return 0;
2237 }
2238
2239 // Convert AR30 to ABGR.
2240 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2241 int AR30ToABGR(const uint8_t* src_ar30,
2242 int src_stride_ar30,
2243 uint8_t* dst_abgr,
2244 int dst_stride_abgr,
2245 int width,
2246 int height) {
2247 int y;
2248 if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
2249 return -1;
2250 }
2251 // Negative height means invert the image.
2252 if (height < 0) {
2253 height = -height;
2254 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2255 src_stride_ar30 = -src_stride_ar30;
2256 }
2257 // Coalesce rows.
2258 if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
2259 width *= height;
2260 height = 1;
2261 src_stride_ar30 = dst_stride_abgr = 0;
2262 }
2263 for (y = 0; y < height; ++y) {
2264 AR30ToABGRRow_C(src_ar30, dst_abgr, width);
2265 src_ar30 += src_stride_ar30;
2266 dst_abgr += dst_stride_abgr;
2267 }
2268 return 0;
2269 }
2270
2271 // Convert AR30 to AB30.
2272 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)2273 int AR30ToAB30(const uint8_t* src_ar30,
2274 int src_stride_ar30,
2275 uint8_t* dst_ab30,
2276 int dst_stride_ab30,
2277 int width,
2278 int height) {
2279 int y;
2280 if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
2281 return -1;
2282 }
2283 // Negative height means invert the image.
2284 if (height < 0) {
2285 height = -height;
2286 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2287 src_stride_ar30 = -src_stride_ar30;
2288 }
2289 // Coalesce rows.
2290 if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
2291 width *= height;
2292 height = 1;
2293 src_stride_ar30 = dst_stride_ab30 = 0;
2294 }
2295 for (y = 0; y < height; ++y) {
2296 AR30ToAB30Row_C(src_ar30, dst_ab30, width);
2297 src_ar30 += src_stride_ar30;
2298 dst_ab30 += dst_stride_ab30;
2299 }
2300 return 0;
2301 }
2302
2303 // Convert NV12 to ARGB with matrix.
2304 LIBYUV_API
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)2305 int NV12ToARGBMatrix(const uint8_t* src_y,
2306 int src_stride_y,
2307 const uint8_t* src_uv,
2308 int src_stride_uv,
2309 uint8_t* dst_argb,
2310 int dst_stride_argb,
2311 const struct YuvConstants* yuvconstants,
2312 int width,
2313 int height) {
2314 int y;
2315 void (*NV12ToARGBRow)(
2316 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2317 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
2318 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
2319 return -1;
2320 }
2321 // Negative height means invert the image.
2322 if (height < 0) {
2323 height = -height;
2324 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2325 dst_stride_argb = -dst_stride_argb;
2326 }
2327 #if defined(HAS_NV12TOARGBROW_SSSE3)
2328 if (TestCpuFlag(kCpuHasSSSE3)) {
2329 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
2330 if (IS_ALIGNED(width, 8)) {
2331 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
2332 }
2333 }
2334 #endif
2335 #if defined(HAS_NV12TOARGBROW_AVX2)
2336 if (TestCpuFlag(kCpuHasAVX2)) {
2337 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
2338 if (IS_ALIGNED(width, 16)) {
2339 NV12ToARGBRow = NV12ToARGBRow_AVX2;
2340 }
2341 }
2342 #endif
2343 #if defined(HAS_NV12TOARGBROW_NEON)
2344 if (TestCpuFlag(kCpuHasNEON)) {
2345 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
2346 if (IS_ALIGNED(width, 8)) {
2347 NV12ToARGBRow = NV12ToARGBRow_NEON;
2348 }
2349 }
2350 #endif
2351 #if defined(HAS_NV12TOARGBROW_MMI)
2352 if (TestCpuFlag(kCpuHasMMI)) {
2353 NV12ToARGBRow = NV12ToARGBRow_Any_MMI;
2354 if (IS_ALIGNED(width, 4)) {
2355 NV12ToARGBRow = NV12ToARGBRow_MMI;
2356 }
2357 }
2358 #endif
2359 #if defined(HAS_NV12TOARGBROW_MSA)
2360 if (TestCpuFlag(kCpuHasMSA)) {
2361 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
2362 if (IS_ALIGNED(width, 8)) {
2363 NV12ToARGBRow = NV12ToARGBRow_MSA;
2364 }
2365 }
2366 #endif
2367
2368 for (y = 0; y < height; ++y) {
2369 NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
2370 dst_argb += dst_stride_argb;
2371 src_y += src_stride_y;
2372 if (y & 1) {
2373 src_uv += src_stride_uv;
2374 }
2375 }
2376 return 0;
2377 }
2378
2379 // Convert NV21 to ARGB with matrix.
2380 LIBYUV_API
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)2381 int NV21ToARGBMatrix(const uint8_t* src_y,
2382 int src_stride_y,
2383 const uint8_t* src_vu,
2384 int src_stride_vu,
2385 uint8_t* dst_argb,
2386 int dst_stride_argb,
2387 const struct YuvConstants* yuvconstants,
2388 int width,
2389 int height) {
2390 int y;
2391 void (*NV21ToARGBRow)(
2392 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2393 const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
2394 if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
2395 return -1;
2396 }
2397 // Negative height means invert the image.
2398 if (height < 0) {
2399 height = -height;
2400 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2401 dst_stride_argb = -dst_stride_argb;
2402 }
2403 #if defined(HAS_NV21TOARGBROW_SSSE3)
2404 if (TestCpuFlag(kCpuHasSSSE3)) {
2405 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
2406 if (IS_ALIGNED(width, 8)) {
2407 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
2408 }
2409 }
2410 #endif
2411 #if defined(HAS_NV21TOARGBROW_AVX2)
2412 if (TestCpuFlag(kCpuHasAVX2)) {
2413 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
2414 if (IS_ALIGNED(width, 16)) {
2415 NV21ToARGBRow = NV21ToARGBRow_AVX2;
2416 }
2417 }
2418 #endif
2419 #if defined(HAS_NV21TOARGBROW_NEON)
2420 if (TestCpuFlag(kCpuHasNEON)) {
2421 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
2422 if (IS_ALIGNED(width, 8)) {
2423 NV21ToARGBRow = NV21ToARGBRow_NEON;
2424 }
2425 }
2426 #endif
2427 #if defined(HAS_NV21TOARGBROW_MMI)
2428 if (TestCpuFlag(kCpuHasMMI)) {
2429 NV21ToARGBRow = NV21ToARGBRow_Any_MMI;
2430 if (IS_ALIGNED(width, 4)) {
2431 NV21ToARGBRow = NV21ToARGBRow_MMI;
2432 }
2433 }
2434 #endif
2435 #if defined(HAS_NV21TOARGBROW_MSA)
2436 if (TestCpuFlag(kCpuHasMSA)) {
2437 NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
2438 if (IS_ALIGNED(width, 8)) {
2439 NV21ToARGBRow = NV21ToARGBRow_MSA;
2440 }
2441 }
2442 #endif
2443
2444 for (y = 0; y < height; ++y) {
2445 NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
2446 dst_argb += dst_stride_argb;
2447 src_y += src_stride_y;
2448 if (y & 1) {
2449 src_vu += src_stride_vu;
2450 }
2451 }
2452 return 0;
2453 }
2454
2455 // Convert NV12 to ARGB.
2456 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)2457 int NV12ToARGB(const uint8_t* src_y,
2458 int src_stride_y,
2459 const uint8_t* src_uv,
2460 int src_stride_uv,
2461 uint8_t* dst_argb,
2462 int dst_stride_argb,
2463 int width,
2464 int height) {
2465 return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
2466 dst_stride_argb, &kYuvI601Constants, width, height);
2467 }
2468
2469 // Convert NV21 to ARGB.
2470 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)2471 int NV21ToARGB(const uint8_t* src_y,
2472 int src_stride_y,
2473 const uint8_t* src_vu,
2474 int src_stride_vu,
2475 uint8_t* dst_argb,
2476 int dst_stride_argb,
2477 int width,
2478 int height) {
2479 return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
2480 dst_stride_argb, &kYuvI601Constants, width, height);
2481 }
2482
2483 // Convert NV12 to ABGR.
2484 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
2485 // To swap the UV use NV12 instead of NV21.LIBYUV_API
2486 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)2487 int NV12ToABGR(const uint8_t* src_y,
2488 int src_stride_y,
2489 const uint8_t* src_uv,
2490 int src_stride_uv,
2491 uint8_t* dst_abgr,
2492 int dst_stride_abgr,
2493 int width,
2494 int height) {
2495 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
2496 dst_stride_abgr, &kYvuI601Constants, width, height);
2497 }
2498
2499 // Convert NV21 to ABGR.
2500 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)2501 int NV21ToABGR(const uint8_t* src_y,
2502 int src_stride_y,
2503 const uint8_t* src_vu,
2504 int src_stride_vu,
2505 uint8_t* dst_abgr,
2506 int dst_stride_abgr,
2507 int width,
2508 int height) {
2509 return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
2510 dst_stride_abgr, &kYvuI601Constants, width, height);
2511 }
2512
2513 // TODO(fbarchard): Consider SSSE3 2 step conversion.
2514 // Convert NV12 to RGB24 with matrix.
2515 LIBYUV_API
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)2516 int NV12ToRGB24Matrix(const uint8_t* src_y,
2517 int src_stride_y,
2518 const uint8_t* src_uv,
2519 int src_stride_uv,
2520 uint8_t* dst_rgb24,
2521 int dst_stride_rgb24,
2522 const struct YuvConstants* yuvconstants,
2523 int width,
2524 int height) {
2525 int y;
2526 void (*NV12ToRGB24Row)(
2527 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2528 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
2529 if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
2530 return -1;
2531 }
2532 // Negative height means invert the image.
2533 if (height < 0) {
2534 height = -height;
2535 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2536 dst_stride_rgb24 = -dst_stride_rgb24;
2537 }
2538 #if defined(HAS_NV12TORGB24ROW_NEON)
2539 if (TestCpuFlag(kCpuHasNEON)) {
2540 NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
2541 if (IS_ALIGNED(width, 8)) {
2542 NV12ToRGB24Row = NV12ToRGB24Row_NEON;
2543 }
2544 }
2545 #endif
2546 #if defined(HAS_NV12TORGB24ROW_SSSE3)
2547 if (TestCpuFlag(kCpuHasSSSE3)) {
2548 NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
2549 if (IS_ALIGNED(width, 16)) {
2550 NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
2551 }
2552 }
2553 #endif
2554 #if defined(HAS_NV12TORGB24ROW_AVX2)
2555 if (TestCpuFlag(kCpuHasAVX2)) {
2556 NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
2557 if (IS_ALIGNED(width, 32)) {
2558 NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
2559 }
2560 }
2561 #endif
2562 #if defined(HAS_NV12TORGB24ROW_MMI)
2563 if (TestCpuFlag(kCpuHasMMI)) {
2564 NV12ToRGB24Row = NV12ToRGB24Row_Any_MMI;
2565 if (IS_ALIGNED(width, 8)) {
2566 NV12ToRGB24Row = NV12ToRGB24Row_MMI;
2567 }
2568 }
2569 #endif
2570
2571 for (y = 0; y < height; ++y) {
2572 NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
2573 dst_rgb24 += dst_stride_rgb24;
2574 src_y += src_stride_y;
2575 if (y & 1) {
2576 src_uv += src_stride_uv;
2577 }
2578 }
2579 return 0;
2580 }
2581
2582 // Convert NV21 to RGB24 with matrix.
2583 LIBYUV_API
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)2584 int NV21ToRGB24Matrix(const uint8_t* src_y,
2585 int src_stride_y,
2586 const uint8_t* src_vu,
2587 int src_stride_vu,
2588 uint8_t* dst_rgb24,
2589 int dst_stride_rgb24,
2590 const struct YuvConstants* yuvconstants,
2591 int width,
2592 int height) {
2593 int y;
2594 void (*NV21ToRGB24Row)(
2595 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2596 const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
2597 if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
2598 return -1;
2599 }
2600 // Negative height means invert the image.
2601 if (height < 0) {
2602 height = -height;
2603 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2604 dst_stride_rgb24 = -dst_stride_rgb24;
2605 }
2606 #if defined(HAS_NV21TORGB24ROW_NEON)
2607 if (TestCpuFlag(kCpuHasNEON)) {
2608 NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
2609 if (IS_ALIGNED(width, 8)) {
2610 NV21ToRGB24Row = NV21ToRGB24Row_NEON;
2611 }
2612 }
2613 #endif
2614 #if defined(HAS_NV21TORGB24ROW_SSSE3)
2615 if (TestCpuFlag(kCpuHasSSSE3)) {
2616 NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
2617 if (IS_ALIGNED(width, 16)) {
2618 NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
2619 }
2620 }
2621 #endif
2622 #if defined(HAS_NV21TORGB24ROW_AVX2)
2623 if (TestCpuFlag(kCpuHasAVX2)) {
2624 NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
2625 if (IS_ALIGNED(width, 32)) {
2626 NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
2627 }
2628 }
2629 #endif
2630 #if defined(HAS_NV21TORGB24ROW_MMI)
2631 if (TestCpuFlag(kCpuHasMMI)) {
2632 NV21ToRGB24Row = NV21ToRGB24Row_Any_MMI;
2633 if (IS_ALIGNED(width, 8)) {
2634 NV21ToRGB24Row = NV21ToRGB24Row_MMI;
2635 }
2636 }
2637 #endif
2638
2639 for (y = 0; y < height; ++y) {
2640 NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
2641 dst_rgb24 += dst_stride_rgb24;
2642 src_y += src_stride_y;
2643 if (y & 1) {
2644 src_vu += src_stride_vu;
2645 }
2646 }
2647 return 0;
2648 }
2649
2650 // Convert NV12 to RGB24.
2651 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)2652 int NV12ToRGB24(const uint8_t* src_y,
2653 int src_stride_y,
2654 const uint8_t* src_uv,
2655 int src_stride_uv,
2656 uint8_t* dst_rgb24,
2657 int dst_stride_rgb24,
2658 int width,
2659 int height) {
2660 return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
2661 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2662 width, height);
2663 }
2664
2665 // Convert NV21 to RGB24.
2666 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)2667 int NV21ToRGB24(const uint8_t* src_y,
2668 int src_stride_y,
2669 const uint8_t* src_vu,
2670 int src_stride_vu,
2671 uint8_t* dst_rgb24,
2672 int dst_stride_rgb24,
2673 int width,
2674 int height) {
2675 return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
2676 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2677 width, height);
2678 }
2679
2680 // Convert NV12 to RAW.
2681 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)2682 int NV12ToRAW(const uint8_t* src_y,
2683 int src_stride_y,
2684 const uint8_t* src_uv,
2685 int src_stride_uv,
2686 uint8_t* dst_raw,
2687 int dst_stride_raw,
2688 int width,
2689 int height) {
2690 return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
2691 dst_stride_raw, &kYvuI601Constants, width, height);
2692 }
2693
2694 // Convert NV21 to RAW.
2695 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)2696 int NV21ToRAW(const uint8_t* src_y,
2697 int src_stride_y,
2698 const uint8_t* src_vu,
2699 int src_stride_vu,
2700 uint8_t* dst_raw,
2701 int dst_stride_raw,
2702 int width,
2703 int height) {
2704 return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
2705 dst_stride_raw, &kYvuI601Constants, width, height);
2706 }
2707
2708 // 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)2709 int NV21ToYUV24(const uint8_t* src_y,
2710 int src_stride_y,
2711 const uint8_t* src_vu,
2712 int src_stride_vu,
2713 uint8_t* dst_yuv24,
2714 int dst_stride_yuv24,
2715 int width,
2716 int height) {
2717 int y;
2718 void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
2719 uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
2720 if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
2721 return -1;
2722 }
2723 // Negative height means invert the image.
2724 if (height < 0) {
2725 height = -height;
2726 dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
2727 dst_stride_yuv24 = -dst_stride_yuv24;
2728 }
2729 #if defined(HAS_NV21TOYUV24ROW_NEON)
2730 if (TestCpuFlag(kCpuHasNEON)) {
2731 NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
2732 if (IS_ALIGNED(width, 16)) {
2733 NV21ToYUV24Row = NV21ToYUV24Row_NEON;
2734 }
2735 }
2736 #endif
2737 #if defined(HAS_NV21TOYUV24ROW_AVX2)
2738 if (TestCpuFlag(kCpuHasAVX2)) {
2739 NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
2740 if (IS_ALIGNED(width, 32)) {
2741 NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
2742 }
2743 }
2744 #endif
2745 for (y = 0; y < height; ++y) {
2746 NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
2747 dst_yuv24 += dst_stride_yuv24;
2748 src_y += src_stride_y;
2749 if (y & 1) {
2750 src_vu += src_stride_vu;
2751 }
2752 }
2753 return 0;
2754 }
2755
2756 // Convert YUY2 to ARGB.
2757 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2758 int YUY2ToARGB(const uint8_t* src_yuy2,
2759 int src_stride_yuy2,
2760 uint8_t* dst_argb,
2761 int dst_stride_argb,
2762 int width,
2763 int height) {
2764 int y;
2765 void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
2766 const struct YuvConstants* yuvconstants, int width) =
2767 YUY2ToARGBRow_C;
2768 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
2769 return -1;
2770 }
2771 // Negative height means invert the image.
2772 if (height < 0) {
2773 height = -height;
2774 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
2775 src_stride_yuy2 = -src_stride_yuy2;
2776 }
2777 // Coalesce rows.
2778 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
2779 width *= height;
2780 height = 1;
2781 src_stride_yuy2 = dst_stride_argb = 0;
2782 }
2783 #if defined(HAS_YUY2TOARGBROW_SSSE3)
2784 if (TestCpuFlag(kCpuHasSSSE3)) {
2785 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
2786 if (IS_ALIGNED(width, 16)) {
2787 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
2788 }
2789 }
2790 #endif
2791 #if defined(HAS_YUY2TOARGBROW_AVX2)
2792 if (TestCpuFlag(kCpuHasAVX2)) {
2793 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
2794 if (IS_ALIGNED(width, 32)) {
2795 YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
2796 }
2797 }
2798 #endif
2799 #if defined(HAS_YUY2TOARGBROW_NEON)
2800 if (TestCpuFlag(kCpuHasNEON)) {
2801 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
2802 if (IS_ALIGNED(width, 8)) {
2803 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
2804 }
2805 }
2806 #endif
2807 #if defined(HAS_YUY2TOARGBROW_MMI)
2808 if (TestCpuFlag(kCpuHasMMI)) {
2809 YUY2ToARGBRow = YUY2ToARGBRow_Any_MMI;
2810 if (IS_ALIGNED(width, 4)) {
2811 YUY2ToARGBRow = YUY2ToARGBRow_MMI;
2812 }
2813 }
2814 #endif
2815 #if defined(HAS_YUY2TOARGBROW_MSA)
2816 if (TestCpuFlag(kCpuHasMSA)) {
2817 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
2818 if (IS_ALIGNED(width, 8)) {
2819 YUY2ToARGBRow = YUY2ToARGBRow_MSA;
2820 }
2821 }
2822 #endif
2823 for (y = 0; y < height; ++y) {
2824 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
2825 src_yuy2 += src_stride_yuy2;
2826 dst_argb += dst_stride_argb;
2827 }
2828 return 0;
2829 }
2830
2831 // Convert UYVY to ARGB.
2832 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2833 int UYVYToARGB(const uint8_t* src_uyvy,
2834 int src_stride_uyvy,
2835 uint8_t* dst_argb,
2836 int dst_stride_argb,
2837 int width,
2838 int height) {
2839 int y;
2840 void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
2841 const struct YuvConstants* yuvconstants, int width) =
2842 UYVYToARGBRow_C;
2843 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
2844 return -1;
2845 }
2846 // Negative height means invert the image.
2847 if (height < 0) {
2848 height = -height;
2849 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
2850 src_stride_uyvy = -src_stride_uyvy;
2851 }
2852 // Coalesce rows.
2853 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
2854 width *= height;
2855 height = 1;
2856 src_stride_uyvy = dst_stride_argb = 0;
2857 }
2858 #if defined(HAS_UYVYTOARGBROW_SSSE3)
2859 if (TestCpuFlag(kCpuHasSSSE3)) {
2860 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
2861 if (IS_ALIGNED(width, 16)) {
2862 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
2863 }
2864 }
2865 #endif
2866 #if defined(HAS_UYVYTOARGBROW_AVX2)
2867 if (TestCpuFlag(kCpuHasAVX2)) {
2868 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
2869 if (IS_ALIGNED(width, 32)) {
2870 UYVYToARGBRow = UYVYToARGBRow_AVX2;
2871 }
2872 }
2873 #endif
2874 #if defined(HAS_UYVYTOARGBROW_NEON)
2875 if (TestCpuFlag(kCpuHasNEON)) {
2876 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
2877 if (IS_ALIGNED(width, 8)) {
2878 UYVYToARGBRow = UYVYToARGBRow_NEON;
2879 }
2880 }
2881 #endif
2882 #if defined(HAS_UYVYTOARGBROW_MMI)
2883 if (TestCpuFlag(kCpuHasMMI)) {
2884 UYVYToARGBRow = UYVYToARGBRow_Any_MMI;
2885 if (IS_ALIGNED(width, 4)) {
2886 UYVYToARGBRow = UYVYToARGBRow_MMI;
2887 }
2888 }
2889 #endif
2890 #if defined(HAS_UYVYTOARGBROW_MSA)
2891 if (TestCpuFlag(kCpuHasMSA)) {
2892 UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
2893 if (IS_ALIGNED(width, 8)) {
2894 UYVYToARGBRow = UYVYToARGBRow_MSA;
2895 }
2896 }
2897 #endif
2898 for (y = 0; y < height; ++y) {
2899 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
2900 src_uyvy += src_stride_uyvy;
2901 dst_argb += dst_stride_argb;
2902 }
2903 return 0;
2904 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)2905 static void WeavePixels(const uint8_t* src_u,
2906 const uint8_t* src_v,
2907 int src_pixel_stride_uv,
2908 uint8_t* dst_uv,
2909 int width) {
2910 int i;
2911 for (i = 0; i < width; ++i) {
2912 dst_uv[0] = *src_u;
2913 dst_uv[1] = *src_v;
2914 dst_uv += 2;
2915 src_u += src_pixel_stride_uv;
2916 src_v += src_pixel_stride_uv;
2917 }
2918 }
2919
2920 // Convert Android420 to ARGB with matrix.
2921 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)2922 int Android420ToARGBMatrix(const uint8_t* src_y,
2923 int src_stride_y,
2924 const uint8_t* src_u,
2925 int src_stride_u,
2926 const uint8_t* src_v,
2927 int src_stride_v,
2928 int src_pixel_stride_uv,
2929 uint8_t* dst_argb,
2930 int dst_stride_argb,
2931 const struct YuvConstants* yuvconstants,
2932 int width,
2933 int height) {
2934 int y;
2935 uint8_t* dst_uv;
2936 const ptrdiff_t vu_off = src_v - src_u;
2937 int halfwidth = (width + 1) >> 1;
2938 int halfheight = (height + 1) >> 1;
2939 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
2940 return -1;
2941 }
2942 // Negative height means invert the image.
2943 if (height < 0) {
2944 height = -height;
2945 halfheight = (height + 1) >> 1;
2946 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2947 dst_stride_argb = -dst_stride_argb;
2948 }
2949
2950 // I420
2951 if (src_pixel_stride_uv == 1) {
2952 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2953 src_stride_v, dst_argb, dst_stride_argb,
2954 yuvconstants, width, height);
2955 // NV21
2956 }
2957 if (src_pixel_stride_uv == 2 && vu_off == -1 &&
2958 src_stride_u == src_stride_v) {
2959 return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
2960 dst_stride_argb, yuvconstants, width, height);
2961 // NV12
2962 }
2963 if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
2964 return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
2965 dst_stride_argb, yuvconstants, width, height);
2966 }
2967
2968 // General case fallback creates NV12
2969 align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
2970 dst_uv = plane_uv;
2971 for (y = 0; y < halfheight; ++y) {
2972 WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
2973 src_u += src_stride_u;
2974 src_v += src_stride_v;
2975 dst_uv += halfwidth * 2;
2976 }
2977 NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
2978 dst_stride_argb, yuvconstants, width, height);
2979 free_aligned_buffer_64(plane_uv);
2980 return 0;
2981 }
2982
2983 // Convert Android420 to ARGB.
2984 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)2985 int Android420ToARGB(const uint8_t* src_y,
2986 int src_stride_y,
2987 const uint8_t* src_u,
2988 int src_stride_u,
2989 const uint8_t* src_v,
2990 int src_stride_v,
2991 int src_pixel_stride_uv,
2992 uint8_t* dst_argb,
2993 int dst_stride_argb,
2994 int width,
2995 int height) {
2996 return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2997 src_stride_v, src_pixel_stride_uv, dst_argb,
2998 dst_stride_argb, &kYuvI601Constants, width,
2999 height);
3000 }
3001
3002 // Convert Android420 to ABGR.
3003 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)3004 int Android420ToABGR(const uint8_t* src_y,
3005 int src_stride_y,
3006 const uint8_t* src_u,
3007 int src_stride_u,
3008 const uint8_t* src_v,
3009 int src_stride_v,
3010 int src_pixel_stride_uv,
3011 uint8_t* dst_abgr,
3012 int dst_stride_abgr,
3013 int width,
3014 int height) {
3015 return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
3016 src_stride_u, src_pixel_stride_uv, dst_abgr,
3017 dst_stride_abgr, &kYvuI601Constants, width,
3018 height);
3019 }
3020
3021 // Convert I422 to RGBA with matrix.
3022 LIBYUV_API
I422ToRGBAMatrix(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_rgba,int dst_stride_rgba,const struct YuvConstants * yuvconstants,int width,int height)3023 int I422ToRGBAMatrix(const uint8_t* src_y,
3024 int src_stride_y,
3025 const uint8_t* src_u,
3026 int src_stride_u,
3027 const uint8_t* src_v,
3028 int src_stride_v,
3029 uint8_t* dst_rgba,
3030 int dst_stride_rgba,
3031 const struct YuvConstants* yuvconstants,
3032 int width,
3033 int height) {
3034 int y;
3035 void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
3036 const uint8_t* v_buf, uint8_t* rgb_buf,
3037 const struct YuvConstants* yuvconstants, int width) =
3038 I422ToRGBARow_C;
3039 if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
3040 return -1;
3041 }
3042 // Negative height means invert the image.
3043 if (height < 0) {
3044 height = -height;
3045 dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
3046 dst_stride_rgba = -dst_stride_rgba;
3047 }
3048 #if defined(HAS_I422TORGBAROW_SSSE3)
3049 if (TestCpuFlag(kCpuHasSSSE3)) {
3050 I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
3051 if (IS_ALIGNED(width, 8)) {
3052 I422ToRGBARow = I422ToRGBARow_SSSE3;
3053 }
3054 }
3055 #endif
3056 #if defined(HAS_I422TORGBAROW_AVX2)
3057 if (TestCpuFlag(kCpuHasAVX2)) {
3058 I422ToRGBARow = I422ToRGBARow_Any_AVX2;
3059 if (IS_ALIGNED(width, 16)) {
3060 I422ToRGBARow = I422ToRGBARow_AVX2;
3061 }
3062 }
3063 #endif
3064 #if defined(HAS_I422TORGBAROW_NEON)
3065 if (TestCpuFlag(kCpuHasNEON)) {
3066 I422ToRGBARow = I422ToRGBARow_Any_NEON;
3067 if (IS_ALIGNED(width, 8)) {
3068 I422ToRGBARow = I422ToRGBARow_NEON;
3069 }
3070 }
3071 #endif
3072 #if defined(HAS_I422TORGBAROW_MMI)
3073 if (TestCpuFlag(kCpuHasMMI)) {
3074 I422ToRGBARow = I422ToRGBARow_Any_MMI;
3075 if (IS_ALIGNED(width, 4)) {
3076 I422ToRGBARow = I422ToRGBARow_MMI;
3077 }
3078 }
3079 #endif
3080 #if defined(HAS_I422TORGBAROW_MSA)
3081 if (TestCpuFlag(kCpuHasMSA)) {
3082 I422ToRGBARow = I422ToRGBARow_Any_MSA;
3083 if (IS_ALIGNED(width, 8)) {
3084 I422ToRGBARow = I422ToRGBARow_MSA;
3085 }
3086 }
3087 #endif
3088
3089 for (y = 0; y < height; ++y) {
3090 I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
3091 dst_rgba += dst_stride_rgba;
3092 src_y += src_stride_y;
3093 src_u += src_stride_u;
3094 src_v += src_stride_v;
3095 }
3096 return 0;
3097 }
3098
3099 // Convert I422 to RGBA.
3100 LIBYUV_API
I422ToRGBA(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_rgba,int dst_stride_rgba,int width,int height)3101 int I422ToRGBA(const uint8_t* src_y,
3102 int src_stride_y,
3103 const uint8_t* src_u,
3104 int src_stride_u,
3105 const uint8_t* src_v,
3106 int src_stride_v,
3107 uint8_t* dst_rgba,
3108 int dst_stride_rgba,
3109 int width,
3110 int height) {
3111 return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3112 src_stride_v, dst_rgba, dst_stride_rgba,
3113 &kYuvI601Constants, width, height);
3114 }
3115
3116 // Convert I422 to BGRA.
3117 LIBYUV_API
I422ToBGRA(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_bgra,int dst_stride_bgra,int width,int height)3118 int I422ToBGRA(const uint8_t* src_y,
3119 int src_stride_y,
3120 const uint8_t* src_u,
3121 int src_stride_u,
3122 const uint8_t* src_v,
3123 int src_stride_v,
3124 uint8_t* dst_bgra,
3125 int dst_stride_bgra,
3126 int width,
3127 int height) {
3128 return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
3129 src_stride_v, // Swap U and V
3130 src_u, src_stride_u, dst_bgra, dst_stride_bgra,
3131 &kYvuI601Constants, // Use Yvu matrix
3132 width, height);
3133 }
3134
3135 // Convert NV12 to RGB565 with matrix.
3136 LIBYUV_API
NV12ToRGB565Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb565,int dst_stride_rgb565,const struct YuvConstants * yuvconstants,int width,int height)3137 int NV12ToRGB565Matrix(const uint8_t* src_y,
3138 int src_stride_y,
3139 const uint8_t* src_uv,
3140 int src_stride_uv,
3141 uint8_t* dst_rgb565,
3142 int dst_stride_rgb565,
3143 const struct YuvConstants* yuvconstants,
3144 int width,
3145 int height) {
3146 int y;
3147 void (*NV12ToRGB565Row)(
3148 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3149 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
3150 if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
3151 return -1;
3152 }
3153 // Negative height means invert the image.
3154 if (height < 0) {
3155 height = -height;
3156 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3157 dst_stride_rgb565 = -dst_stride_rgb565;
3158 }
3159 #if defined(HAS_NV12TORGB565ROW_SSSE3)
3160 if (TestCpuFlag(kCpuHasSSSE3)) {
3161 NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
3162 if (IS_ALIGNED(width, 8)) {
3163 NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
3164 }
3165 }
3166 #endif
3167 #if defined(HAS_NV12TORGB565ROW_AVX2)
3168 if (TestCpuFlag(kCpuHasAVX2)) {
3169 NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
3170 if (IS_ALIGNED(width, 16)) {
3171 NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
3172 }
3173 }
3174 #endif
3175 #if defined(HAS_NV12TORGB565ROW_NEON)
3176 if (TestCpuFlag(kCpuHasNEON)) {
3177 NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
3178 if (IS_ALIGNED(width, 8)) {
3179 NV12ToRGB565Row = NV12ToRGB565Row_NEON;
3180 }
3181 }
3182 #endif
3183 #if defined(HAS_NV12TORGB565ROW_MMI)
3184 if (TestCpuFlag(kCpuHasMMI)) {
3185 NV12ToRGB565Row = NV12ToRGB565Row_Any_MMI;
3186 if (IS_ALIGNED(width, 4)) {
3187 NV12ToRGB565Row = NV12ToRGB565Row_MMI;
3188 }
3189 }
3190 #endif
3191 #if defined(HAS_NV12TORGB565ROW_MSA)
3192 if (TestCpuFlag(kCpuHasMSA)) {
3193 NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
3194 if (IS_ALIGNED(width, 8)) {
3195 NV12ToRGB565Row = NV12ToRGB565Row_MSA;
3196 }
3197 }
3198 #endif
3199
3200 for (y = 0; y < height; ++y) {
3201 NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
3202 dst_rgb565 += dst_stride_rgb565;
3203 src_y += src_stride_y;
3204 if (y & 1) {
3205 src_uv += src_stride_uv;
3206 }
3207 }
3208 return 0;
3209 }
3210
3211 // Convert NV12 to RGB565.
3212 LIBYUV_API
NV12ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)3213 int NV12ToRGB565(const uint8_t* src_y,
3214 int src_stride_y,
3215 const uint8_t* src_uv,
3216 int src_stride_uv,
3217 uint8_t* dst_rgb565,
3218 int dst_stride_rgb565,
3219 int width,
3220 int height) {
3221 return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
3222 dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
3223 width, height);
3224 }
3225
3226 // Convert I422 to RGBA with matrix.
3227 LIBYUV_API
I420ToRGBAMatrix(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_rgba,int dst_stride_rgba,const struct YuvConstants * yuvconstants,int width,int height)3228 int I420ToRGBAMatrix(const uint8_t* src_y,
3229 int src_stride_y,
3230 const uint8_t* src_u,
3231 int src_stride_u,
3232 const uint8_t* src_v,
3233 int src_stride_v,
3234 uint8_t* dst_rgba,
3235 int dst_stride_rgba,
3236 const struct YuvConstants* yuvconstants,
3237 int width,
3238 int height) {
3239 int y;
3240 void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
3241 const uint8_t* v_buf, uint8_t* rgb_buf,
3242 const struct YuvConstants* yuvconstants, int width) =
3243 I422ToRGBARow_C;
3244 if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
3245 return -1;
3246 }
3247 // Negative height means invert the image.
3248 if (height < 0) {
3249 height = -height;
3250 dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
3251 dst_stride_rgba = -dst_stride_rgba;
3252 }
3253 #if defined(HAS_I422TORGBAROW_SSSE3)
3254 if (TestCpuFlag(kCpuHasSSSE3)) {
3255 I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
3256 if (IS_ALIGNED(width, 8)) {
3257 I422ToRGBARow = I422ToRGBARow_SSSE3;
3258 }
3259 }
3260 #endif
3261 #if defined(HAS_I422TORGBAROW_AVX2)
3262 if (TestCpuFlag(kCpuHasAVX2)) {
3263 I422ToRGBARow = I422ToRGBARow_Any_AVX2;
3264 if (IS_ALIGNED(width, 16)) {
3265 I422ToRGBARow = I422ToRGBARow_AVX2;
3266 }
3267 }
3268 #endif
3269 #if defined(HAS_I422TORGBAROW_NEON)
3270 if (TestCpuFlag(kCpuHasNEON)) {
3271 I422ToRGBARow = I422ToRGBARow_Any_NEON;
3272 if (IS_ALIGNED(width, 8)) {
3273 I422ToRGBARow = I422ToRGBARow_NEON;
3274 }
3275 }
3276 #endif
3277 #if defined(HAS_I422TORGBAROW_MMI)
3278 if (TestCpuFlag(kCpuHasMMI)) {
3279 I422ToRGBARow = I422ToRGBARow_Any_MMI;
3280 if (IS_ALIGNED(width, 4)) {
3281 I422ToRGBARow = I422ToRGBARow_MMI;
3282 }
3283 }
3284 #endif
3285 #if defined(HAS_I422TORGBAROW_MSA)
3286 if (TestCpuFlag(kCpuHasMSA)) {
3287 I422ToRGBARow = I422ToRGBARow_Any_MSA;
3288 if (IS_ALIGNED(width, 8)) {
3289 I422ToRGBARow = I422ToRGBARow_MSA;
3290 }
3291 }
3292 #endif
3293
3294 for (y = 0; y < height; ++y) {
3295 I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
3296 dst_rgba += dst_stride_rgba;
3297 src_y += src_stride_y;
3298 if (y & 1) {
3299 src_u += src_stride_u;
3300 src_v += src_stride_v;
3301 }
3302 }
3303 return 0;
3304 }
3305
3306 // Convert I420 to RGBA.
3307 LIBYUV_API
I420ToRGBA(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_rgba,int dst_stride_rgba,int width,int height)3308 int I420ToRGBA(const uint8_t* src_y,
3309 int src_stride_y,
3310 const uint8_t* src_u,
3311 int src_stride_u,
3312 const uint8_t* src_v,
3313 int src_stride_v,
3314 uint8_t* dst_rgba,
3315 int dst_stride_rgba,
3316 int width,
3317 int height) {
3318 return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3319 src_stride_v, dst_rgba, dst_stride_rgba,
3320 &kYuvI601Constants, width, height);
3321 }
3322
3323 // Convert I420 to BGRA.
3324 LIBYUV_API
I420ToBGRA(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_bgra,int dst_stride_bgra,int width,int height)3325 int I420ToBGRA(const uint8_t* src_y,
3326 int src_stride_y,
3327 const uint8_t* src_u,
3328 int src_stride_u,
3329 const uint8_t* src_v,
3330 int src_stride_v,
3331 uint8_t* dst_bgra,
3332 int dst_stride_bgra,
3333 int width,
3334 int height) {
3335 return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
3336 src_stride_v, // Swap U and V
3337 src_u, src_stride_u, dst_bgra, dst_stride_bgra,
3338 &kYvuI601Constants, // Use Yvu matrix
3339 width, height);
3340 }
3341
3342 // Convert I420 to RGB24 with matrix.
3343 LIBYUV_API
I420ToRGB24Matrix(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_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)3344 int I420ToRGB24Matrix(const uint8_t* src_y,
3345 int src_stride_y,
3346 const uint8_t* src_u,
3347 int src_stride_u,
3348 const uint8_t* src_v,
3349 int src_stride_v,
3350 uint8_t* dst_rgb24,
3351 int dst_stride_rgb24,
3352 const struct YuvConstants* yuvconstants,
3353 int width,
3354 int height) {
3355 int y;
3356 void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3357 const uint8_t* v_buf, uint8_t* rgb_buf,
3358 const struct YuvConstants* yuvconstants, int width) =
3359 I422ToRGB24Row_C;
3360 if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
3361 return -1;
3362 }
3363 // Negative height means invert the image.
3364 if (height < 0) {
3365 height = -height;
3366 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
3367 dst_stride_rgb24 = -dst_stride_rgb24;
3368 }
3369 #if defined(HAS_I422TORGB24ROW_SSSE3)
3370 if (TestCpuFlag(kCpuHasSSSE3)) {
3371 I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
3372 if (IS_ALIGNED(width, 16)) {
3373 I422ToRGB24Row = I422ToRGB24Row_SSSE3;
3374 }
3375 }
3376 #endif
3377 #if defined(HAS_I422TORGB24ROW_AVX2)
3378 if (TestCpuFlag(kCpuHasAVX2)) {
3379 I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
3380 if (IS_ALIGNED(width, 32)) {
3381 I422ToRGB24Row = I422ToRGB24Row_AVX2;
3382 }
3383 }
3384 #endif
3385 #if defined(HAS_I422TORGB24ROW_NEON)
3386 if (TestCpuFlag(kCpuHasNEON)) {
3387 I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
3388 if (IS_ALIGNED(width, 8)) {
3389 I422ToRGB24Row = I422ToRGB24Row_NEON;
3390 }
3391 }
3392 #endif
3393 #if defined(HAS_I422TORGB24ROW_MMI)
3394 if (TestCpuFlag(kCpuHasMMI)) {
3395 I422ToRGB24Row = I422ToRGB24Row_Any_MMI;
3396 if (IS_ALIGNED(width, 4)) {
3397 I422ToRGB24Row = I422ToRGB24Row_MMI;
3398 }
3399 }
3400 #endif
3401 #if defined(HAS_I422TORGB24ROW_MSA)
3402 if (TestCpuFlag(kCpuHasMSA)) {
3403 I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
3404 if (IS_ALIGNED(width, 16)) {
3405 I422ToRGB24Row = I422ToRGB24Row_MSA;
3406 }
3407 }
3408 #endif
3409
3410 for (y = 0; y < height; ++y) {
3411 I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
3412 dst_rgb24 += dst_stride_rgb24;
3413 src_y += src_stride_y;
3414 if (y & 1) {
3415 src_u += src_stride_u;
3416 src_v += src_stride_v;
3417 }
3418 }
3419 return 0;
3420 }
3421
3422 // Convert I420 to RGB24.
3423 LIBYUV_API
I420ToRGB24(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_rgb24,int dst_stride_rgb24,int width,int height)3424 int I420ToRGB24(const uint8_t* src_y,
3425 int src_stride_y,
3426 const uint8_t* src_u,
3427 int src_stride_u,
3428 const uint8_t* src_v,
3429 int src_stride_v,
3430 uint8_t* dst_rgb24,
3431 int dst_stride_rgb24,
3432 int width,
3433 int height) {
3434 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3435 src_stride_v, dst_rgb24, dst_stride_rgb24,
3436 &kYuvI601Constants, width, height);
3437 }
3438
3439 // Convert I420 to RAW.
3440 LIBYUV_API
I420ToRAW(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_raw,int dst_stride_raw,int width,int height)3441 int I420ToRAW(const uint8_t* src_y,
3442 int src_stride_y,
3443 const uint8_t* src_u,
3444 int src_stride_u,
3445 const uint8_t* src_v,
3446 int src_stride_v,
3447 uint8_t* dst_raw,
3448 int dst_stride_raw,
3449 int width,
3450 int height) {
3451 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3452 src_stride_v, // Swap U and V
3453 src_u, src_stride_u, dst_raw, dst_stride_raw,
3454 &kYvuI601Constants, // Use Yvu matrix
3455 width, height);
3456 }
3457
3458 // Convert J420 to RGB24.
3459 LIBYUV_API
J420ToRGB24(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_rgb24,int dst_stride_rgb24,int width,int height)3460 int J420ToRGB24(const uint8_t* src_y,
3461 int src_stride_y,
3462 const uint8_t* src_u,
3463 int src_stride_u,
3464 const uint8_t* src_v,
3465 int src_stride_v,
3466 uint8_t* dst_rgb24,
3467 int dst_stride_rgb24,
3468 int width,
3469 int height) {
3470 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3471 src_stride_v, dst_rgb24, dst_stride_rgb24,
3472 &kYuvJPEGConstants, width, height);
3473 }
3474
3475 // Convert J420 to RAW.
3476 LIBYUV_API
J420ToRAW(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_raw,int dst_stride_raw,int width,int height)3477 int J420ToRAW(const uint8_t* src_y,
3478 int src_stride_y,
3479 const uint8_t* src_u,
3480 int src_stride_u,
3481 const uint8_t* src_v,
3482 int src_stride_v,
3483 uint8_t* dst_raw,
3484 int dst_stride_raw,
3485 int width,
3486 int height) {
3487 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3488 src_stride_v, // Swap U and V
3489 src_u, src_stride_u, dst_raw, dst_stride_raw,
3490 &kYvuJPEGConstants, // Use Yvu matrix
3491 width, height);
3492 }
3493
3494 // Convert H420 to RGB24.
3495 LIBYUV_API
H420ToRGB24(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_rgb24,int dst_stride_rgb24,int width,int height)3496 int H420ToRGB24(const uint8_t* src_y,
3497 int src_stride_y,
3498 const uint8_t* src_u,
3499 int src_stride_u,
3500 const uint8_t* src_v,
3501 int src_stride_v,
3502 uint8_t* dst_rgb24,
3503 int dst_stride_rgb24,
3504 int width,
3505 int height) {
3506 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3507 src_stride_v, dst_rgb24, dst_stride_rgb24,
3508 &kYuvH709Constants, width, height);
3509 }
3510
3511 // Convert H420 to RAW.
3512 LIBYUV_API
H420ToRAW(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_raw,int dst_stride_raw,int width,int height)3513 int H420ToRAW(const uint8_t* src_y,
3514 int src_stride_y,
3515 const uint8_t* src_u,
3516 int src_stride_u,
3517 const uint8_t* src_v,
3518 int src_stride_v,
3519 uint8_t* dst_raw,
3520 int dst_stride_raw,
3521 int width,
3522 int height) {
3523 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3524 src_stride_v, // Swap U and V
3525 src_u, src_stride_u, dst_raw, dst_stride_raw,
3526 &kYvuH709Constants, // Use Yvu matrix
3527 width, height);
3528 }
3529
3530 // Convert I420 to ARGB1555.
3531 LIBYUV_API
I420ToARGB1555(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_argb1555,int dst_stride_argb1555,int width,int height)3532 int I420ToARGB1555(const uint8_t* src_y,
3533 int src_stride_y,
3534 const uint8_t* src_u,
3535 int src_stride_u,
3536 const uint8_t* src_v,
3537 int src_stride_v,
3538 uint8_t* dst_argb1555,
3539 int dst_stride_argb1555,
3540 int width,
3541 int height) {
3542 int y;
3543 void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3544 const uint8_t* v_buf, uint8_t* rgb_buf,
3545 const struct YuvConstants* yuvconstants,
3546 int width) = I422ToARGB1555Row_C;
3547 if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
3548 height == 0) {
3549 return -1;
3550 }
3551 // Negative height means invert the image.
3552 if (height < 0) {
3553 height = -height;
3554 dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
3555 dst_stride_argb1555 = -dst_stride_argb1555;
3556 }
3557 #if defined(HAS_I422TOARGB1555ROW_SSSE3)
3558 if (TestCpuFlag(kCpuHasSSSE3)) {
3559 I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
3560 if (IS_ALIGNED(width, 8)) {
3561 I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
3562 }
3563 }
3564 #endif
3565 #if defined(HAS_I422TOARGB1555ROW_AVX2)
3566 if (TestCpuFlag(kCpuHasAVX2)) {
3567 I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
3568 if (IS_ALIGNED(width, 16)) {
3569 I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
3570 }
3571 }
3572 #endif
3573 #if defined(HAS_I422TOARGB1555ROW_NEON)
3574 if (TestCpuFlag(kCpuHasNEON)) {
3575 I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
3576 if (IS_ALIGNED(width, 8)) {
3577 I422ToARGB1555Row = I422ToARGB1555Row_NEON;
3578 }
3579 }
3580 #endif
3581 #if defined(HAS_I422TOARGB1555ROW_MMI)
3582 if (TestCpuFlag(kCpuHasMMI)) {
3583 I422ToARGB1555Row = I422ToARGB1555Row_Any_MMI;
3584 if (IS_ALIGNED(width, 4)) {
3585 I422ToARGB1555Row = I422ToARGB1555Row_MMI;
3586 }
3587 }
3588 #endif
3589 #if defined(HAS_I422TOARGB1555ROW_MSA)
3590 if (TestCpuFlag(kCpuHasMSA)) {
3591 I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
3592 if (IS_ALIGNED(width, 8)) {
3593 I422ToARGB1555Row = I422ToARGB1555Row_MSA;
3594 }
3595 }
3596 #endif
3597
3598 for (y = 0; y < height; ++y) {
3599 I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
3600 width);
3601 dst_argb1555 += dst_stride_argb1555;
3602 src_y += src_stride_y;
3603 if (y & 1) {
3604 src_u += src_stride_u;
3605 src_v += src_stride_v;
3606 }
3607 }
3608 return 0;
3609 }
3610
3611 // Convert I420 to ARGB4444.
3612 LIBYUV_API
I420ToARGB4444(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_argb4444,int dst_stride_argb4444,int width,int height)3613 int I420ToARGB4444(const uint8_t* src_y,
3614 int src_stride_y,
3615 const uint8_t* src_u,
3616 int src_stride_u,
3617 const uint8_t* src_v,
3618 int src_stride_v,
3619 uint8_t* dst_argb4444,
3620 int dst_stride_argb4444,
3621 int width,
3622 int height) {
3623 int y;
3624 void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3625 const uint8_t* v_buf, uint8_t* rgb_buf,
3626 const struct YuvConstants* yuvconstants,
3627 int width) = I422ToARGB4444Row_C;
3628 if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
3629 height == 0) {
3630 return -1;
3631 }
3632 // Negative height means invert the image.
3633 if (height < 0) {
3634 height = -height;
3635 dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
3636 dst_stride_argb4444 = -dst_stride_argb4444;
3637 }
3638 #if defined(HAS_I422TOARGB4444ROW_SSSE3)
3639 if (TestCpuFlag(kCpuHasSSSE3)) {
3640 I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
3641 if (IS_ALIGNED(width, 8)) {
3642 I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
3643 }
3644 }
3645 #endif
3646 #if defined(HAS_I422TOARGB4444ROW_AVX2)
3647 if (TestCpuFlag(kCpuHasAVX2)) {
3648 I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
3649 if (IS_ALIGNED(width, 16)) {
3650 I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
3651 }
3652 }
3653 #endif
3654 #if defined(HAS_I422TOARGB4444ROW_NEON)
3655 if (TestCpuFlag(kCpuHasNEON)) {
3656 I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
3657 if (IS_ALIGNED(width, 8)) {
3658 I422ToARGB4444Row = I422ToARGB4444Row_NEON;
3659 }
3660 }
3661 #endif
3662 #if defined(HAS_I422TOARGB4444ROW_MMI)
3663 if (TestCpuFlag(kCpuHasMMI)) {
3664 I422ToARGB4444Row = I422ToARGB4444Row_Any_MMI;
3665 if (IS_ALIGNED(width, 4)) {
3666 I422ToARGB4444Row = I422ToARGB4444Row_MMI;
3667 }
3668 }
3669 #endif
3670 #if defined(HAS_I422TOARGB4444ROW_MSA)
3671 if (TestCpuFlag(kCpuHasMSA)) {
3672 I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
3673 if (IS_ALIGNED(width, 8)) {
3674 I422ToARGB4444Row = I422ToARGB4444Row_MSA;
3675 }
3676 }
3677 #endif
3678
3679 for (y = 0; y < height; ++y) {
3680 I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
3681 width);
3682 dst_argb4444 += dst_stride_argb4444;
3683 src_y += src_stride_y;
3684 if (y & 1) {
3685 src_u += src_stride_u;
3686 src_v += src_stride_v;
3687 }
3688 }
3689 return 0;
3690 }
3691
3692 // Convert I420 to RGB565 with specified color matrix.
3693 LIBYUV_API
I420ToRGB565Matrix(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_rgb565,int dst_stride_rgb565,const struct YuvConstants * yuvconstants,int width,int height)3694 int I420ToRGB565Matrix(const uint8_t* src_y,
3695 int src_stride_y,
3696 const uint8_t* src_u,
3697 int src_stride_u,
3698 const uint8_t* src_v,
3699 int src_stride_v,
3700 uint8_t* dst_rgb565,
3701 int dst_stride_rgb565,
3702 const struct YuvConstants* yuvconstants,
3703 int width,
3704 int height) {
3705 int y;
3706 void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3707 const uint8_t* v_buf, uint8_t* rgb_buf,
3708 const struct YuvConstants* yuvconstants, int width) =
3709 I422ToRGB565Row_C;
3710 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3711 return -1;
3712 }
3713 // Negative height means invert the image.
3714 if (height < 0) {
3715 height = -height;
3716 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3717 dst_stride_rgb565 = -dst_stride_rgb565;
3718 }
3719 #if defined(HAS_I422TORGB565ROW_SSSE3)
3720 if (TestCpuFlag(kCpuHasSSSE3)) {
3721 I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
3722 if (IS_ALIGNED(width, 8)) {
3723 I422ToRGB565Row = I422ToRGB565Row_SSSE3;
3724 }
3725 }
3726 #endif
3727 #if defined(HAS_I422TORGB565ROW_AVX2)
3728 if (TestCpuFlag(kCpuHasAVX2)) {
3729 I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
3730 if (IS_ALIGNED(width, 16)) {
3731 I422ToRGB565Row = I422ToRGB565Row_AVX2;
3732 }
3733 }
3734 #endif
3735 #if defined(HAS_I422TORGB565ROW_NEON)
3736 if (TestCpuFlag(kCpuHasNEON)) {
3737 I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
3738 if (IS_ALIGNED(width, 8)) {
3739 I422ToRGB565Row = I422ToRGB565Row_NEON;
3740 }
3741 }
3742 #endif
3743 #if defined(HAS_I422TORGB565ROW_MMI)
3744 if (TestCpuFlag(kCpuHasMMI)) {
3745 I422ToRGB565Row = I422ToRGB565Row_Any_MMI;
3746 if (IS_ALIGNED(width, 4)) {
3747 I422ToRGB565Row = I422ToRGB565Row_MMI;
3748 }
3749 }
3750 #endif
3751 #if defined(HAS_I422TORGB565ROW_MSA)
3752 if (TestCpuFlag(kCpuHasMSA)) {
3753 I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
3754 if (IS_ALIGNED(width, 8)) {
3755 I422ToRGB565Row = I422ToRGB565Row_MSA;
3756 }
3757 }
3758 #endif
3759
3760 for (y = 0; y < height; ++y) {
3761 I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
3762 dst_rgb565 += dst_stride_rgb565;
3763 src_y += src_stride_y;
3764 if (y & 1) {
3765 src_u += src_stride_u;
3766 src_v += src_stride_v;
3767 }
3768 }
3769 return 0;
3770 }
3771
3772 // Convert I420 to RGB565.
3773 LIBYUV_API
I420ToRGB565(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_rgb565,int dst_stride_rgb565,int width,int height)3774 int I420ToRGB565(const uint8_t* src_y,
3775 int src_stride_y,
3776 const uint8_t* src_u,
3777 int src_stride_u,
3778 const uint8_t* src_v,
3779 int src_stride_v,
3780 uint8_t* dst_rgb565,
3781 int dst_stride_rgb565,
3782 int width,
3783 int height) {
3784 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3785 src_stride_v, dst_rgb565, dst_stride_rgb565,
3786 &kYuvI601Constants, width, height);
3787 }
3788
3789 // Convert J420 to RGB565.
3790 LIBYUV_API
J420ToRGB565(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_rgb565,int dst_stride_rgb565,int width,int height)3791 int J420ToRGB565(const uint8_t* src_y,
3792 int src_stride_y,
3793 const uint8_t* src_u,
3794 int src_stride_u,
3795 const uint8_t* src_v,
3796 int src_stride_v,
3797 uint8_t* dst_rgb565,
3798 int dst_stride_rgb565,
3799 int width,
3800 int height) {
3801 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3802 src_stride_v, dst_rgb565, dst_stride_rgb565,
3803 &kYuvJPEGConstants, width, height);
3804 }
3805
3806 // Convert H420 to RGB565.
3807 LIBYUV_API
H420ToRGB565(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_rgb565,int dst_stride_rgb565,int width,int height)3808 int H420ToRGB565(const uint8_t* src_y,
3809 int src_stride_y,
3810 const uint8_t* src_u,
3811 int src_stride_u,
3812 const uint8_t* src_v,
3813 int src_stride_v,
3814 uint8_t* dst_rgb565,
3815 int dst_stride_rgb565,
3816 int width,
3817 int height) {
3818 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3819 src_stride_v, dst_rgb565, dst_stride_rgb565,
3820 &kYuvH709Constants, width, height);
3821 }
3822
3823 // Convert I422 to RGB565.
3824 LIBYUV_API
I422ToRGB565(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_rgb565,int dst_stride_rgb565,int width,int height)3825 int I422ToRGB565(const uint8_t* src_y,
3826 int src_stride_y,
3827 const uint8_t* src_u,
3828 int src_stride_u,
3829 const uint8_t* src_v,
3830 int src_stride_v,
3831 uint8_t* dst_rgb565,
3832 int dst_stride_rgb565,
3833 int width,
3834 int height) {
3835 int y;
3836 void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3837 const uint8_t* v_buf, uint8_t* rgb_buf,
3838 const struct YuvConstants* yuvconstants, int width) =
3839 I422ToRGB565Row_C;
3840 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3841 return -1;
3842 }
3843 // Negative height means invert the image.
3844 if (height < 0) {
3845 height = -height;
3846 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3847 dst_stride_rgb565 = -dst_stride_rgb565;
3848 }
3849 #if defined(HAS_I422TORGB565ROW_SSSE3)
3850 if (TestCpuFlag(kCpuHasSSSE3)) {
3851 I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
3852 if (IS_ALIGNED(width, 8)) {
3853 I422ToRGB565Row = I422ToRGB565Row_SSSE3;
3854 }
3855 }
3856 #endif
3857 #if defined(HAS_I422TORGB565ROW_AVX2)
3858 if (TestCpuFlag(kCpuHasAVX2)) {
3859 I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
3860 if (IS_ALIGNED(width, 16)) {
3861 I422ToRGB565Row = I422ToRGB565Row_AVX2;
3862 }
3863 }
3864 #endif
3865 #if defined(HAS_I422TORGB565ROW_NEON)
3866 if (TestCpuFlag(kCpuHasNEON)) {
3867 I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
3868 if (IS_ALIGNED(width, 8)) {
3869 I422ToRGB565Row = I422ToRGB565Row_NEON;
3870 }
3871 }
3872 #endif
3873 #if defined(HAS_I422TORGB565ROW_MSA)
3874 if (TestCpuFlag(kCpuHasMSA)) {
3875 I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
3876 if (IS_ALIGNED(width, 8)) {
3877 I422ToRGB565Row = I422ToRGB565Row_MSA;
3878 }
3879 }
3880 #endif
3881
3882 for (y = 0; y < height; ++y) {
3883 I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, &kYuvI601Constants, width);
3884 dst_rgb565 += dst_stride_rgb565;
3885 src_y += src_stride_y;
3886 src_u += src_stride_u;
3887 src_v += src_stride_v;
3888 }
3889 return 0;
3890 }
3891
3892 // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
3893 static const uint8_t kDither565_4x4[16] = {
3894 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
3895 };
3896
3897 // Convert I420 to RGB565 with dithering.
3898 LIBYUV_API
I420ToRGB565Dither(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_rgb565,int dst_stride_rgb565,const uint8_t * dither4x4,int width,int height)3899 int I420ToRGB565Dither(const uint8_t* src_y,
3900 int src_stride_y,
3901 const uint8_t* src_u,
3902 int src_stride_u,
3903 const uint8_t* src_v,
3904 int src_stride_v,
3905 uint8_t* dst_rgb565,
3906 int dst_stride_rgb565,
3907 const uint8_t* dither4x4,
3908 int width,
3909 int height) {
3910 int y;
3911 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
3912 const uint8_t* v_buf, uint8_t* rgb_buf,
3913 const struct YuvConstants* yuvconstants, int width) =
3914 I422ToARGBRow_C;
3915 void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
3916 const uint32_t dither4, int width) =
3917 ARGBToRGB565DitherRow_C;
3918 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3919 return -1;
3920 }
3921 // Negative height means invert the image.
3922 if (height < 0) {
3923 height = -height;
3924 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3925 dst_stride_rgb565 = -dst_stride_rgb565;
3926 }
3927 if (!dither4x4) {
3928 dither4x4 = kDither565_4x4;
3929 }
3930 #if defined(HAS_I422TOARGBROW_SSSE3)
3931 if (TestCpuFlag(kCpuHasSSSE3)) {
3932 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
3933 if (IS_ALIGNED(width, 8)) {
3934 I422ToARGBRow = I422ToARGBRow_SSSE3;
3935 }
3936 }
3937 #endif
3938 #if defined(HAS_I422TOARGBROW_AVX2)
3939 if (TestCpuFlag(kCpuHasAVX2)) {
3940 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
3941 if (IS_ALIGNED(width, 16)) {
3942 I422ToARGBRow = I422ToARGBRow_AVX2;
3943 }
3944 }
3945 #endif
3946 #if defined(HAS_I422TOARGBROW_NEON)
3947 if (TestCpuFlag(kCpuHasNEON)) {
3948 I422ToARGBRow = I422ToARGBRow_Any_NEON;
3949 if (IS_ALIGNED(width, 8)) {
3950 I422ToARGBRow = I422ToARGBRow_NEON;
3951 }
3952 }
3953 #endif
3954 #if defined(HAS_I422TOARGBROW_MMI)
3955 if (TestCpuFlag(kCpuHasMMI)) {
3956 I422ToARGBRow = I422ToARGBRow_Any_MMI;
3957 if (IS_ALIGNED(width, 4)) {
3958 I422ToARGBRow = I422ToARGBRow_MMI;
3959 }
3960 }
3961 #endif
3962 #if defined(HAS_I422TOARGBROW_MSA)
3963 if (TestCpuFlag(kCpuHasMSA)) {
3964 I422ToARGBRow = I422ToARGBRow_Any_MSA;
3965 if (IS_ALIGNED(width, 8)) {
3966 I422ToARGBRow = I422ToARGBRow_MSA;
3967 }
3968 }
3969 #endif
3970 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
3971 if (TestCpuFlag(kCpuHasSSE2)) {
3972 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
3973 if (IS_ALIGNED(width, 4)) {
3974 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
3975 }
3976 }
3977 #endif
3978 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
3979 if (TestCpuFlag(kCpuHasAVX2)) {
3980 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
3981 if (IS_ALIGNED(width, 8)) {
3982 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
3983 }
3984 }
3985 #endif
3986 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
3987 if (TestCpuFlag(kCpuHasNEON)) {
3988 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
3989 if (IS_ALIGNED(width, 8)) {
3990 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
3991 }
3992 }
3993 #endif
3994 #if defined(HAS_ARGBTORGB565DITHERROW_MMI)
3995 if (TestCpuFlag(kCpuHasMMI)) {
3996 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MMI;
3997 if (IS_ALIGNED(width, 4)) {
3998 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MMI;
3999 }
4000 }
4001 #endif
4002 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
4003 if (TestCpuFlag(kCpuHasMSA)) {
4004 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
4005 if (IS_ALIGNED(width, 8)) {
4006 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
4007 }
4008 }
4009 #endif
4010 {
4011 // Allocate a row of argb.
4012 align_buffer_64(row_argb, width * 4);
4013 for (y = 0; y < height; ++y) {
4014 I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
4015 ARGBToRGB565DitherRow(row_argb, dst_rgb565,
4016 *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
4017 width);
4018 dst_rgb565 += dst_stride_rgb565;
4019 src_y += src_stride_y;
4020 if (y & 1) {
4021 src_u += src_stride_u;
4022 src_v += src_stride_v;
4023 }
4024 }
4025 free_aligned_buffer_64(row_argb);
4026 }
4027 return 0;
4028 }
4029
4030 // Convert I420 to AR30 with matrix.
4031 LIBYUV_API
I420ToAR30Matrix(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_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)4032 int I420ToAR30Matrix(const uint8_t* src_y,
4033 int src_stride_y,
4034 const uint8_t* src_u,
4035 int src_stride_u,
4036 const uint8_t* src_v,
4037 int src_stride_v,
4038 uint8_t* dst_ar30,
4039 int dst_stride_ar30,
4040 const struct YuvConstants* yuvconstants,
4041 int width,
4042 int height) {
4043 int y;
4044 void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4045 const uint8_t* v_buf, uint8_t* rgb_buf,
4046 const struct YuvConstants* yuvconstants, int width) =
4047 I422ToAR30Row_C;
4048
4049 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
4050 return -1;
4051 }
4052 // Negative height means invert the image.
4053 if (height < 0) {
4054 height = -height;
4055 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
4056 dst_stride_ar30 = -dst_stride_ar30;
4057 }
4058
4059 #if defined(HAS_I422TOAR30ROW_SSSE3)
4060 if (TestCpuFlag(kCpuHasSSSE3)) {
4061 I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
4062 if (IS_ALIGNED(width, 8)) {
4063 I422ToAR30Row = I422ToAR30Row_SSSE3;
4064 }
4065 }
4066 #endif
4067 #if defined(HAS_I422TOAR30ROW_AVX2)
4068 if (TestCpuFlag(kCpuHasAVX2)) {
4069 I422ToAR30Row = I422ToAR30Row_Any_AVX2;
4070 if (IS_ALIGNED(width, 16)) {
4071 I422ToAR30Row = I422ToAR30Row_AVX2;
4072 }
4073 }
4074 #endif
4075
4076 for (y = 0; y < height; ++y) {
4077 I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
4078 dst_ar30 += dst_stride_ar30;
4079 src_y += src_stride_y;
4080 if (y & 1) {
4081 src_u += src_stride_u;
4082 src_v += src_stride_v;
4083 }
4084 }
4085 return 0;
4086 }
4087
4088 // Convert I420 to AR30.
4089 LIBYUV_API
I420ToAR30(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_ar30,int dst_stride_ar30,int width,int height)4090 int I420ToAR30(const uint8_t* src_y,
4091 int src_stride_y,
4092 const uint8_t* src_u,
4093 int src_stride_u,
4094 const uint8_t* src_v,
4095 int src_stride_v,
4096 uint8_t* dst_ar30,
4097 int dst_stride_ar30,
4098 int width,
4099 int height) {
4100 return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4101 src_stride_v, dst_ar30, dst_stride_ar30,
4102 &kYuvI601Constants, width, height);
4103 }
4104
4105 // Convert H420 to AR30.
4106 LIBYUV_API
H420ToAR30(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_ar30,int dst_stride_ar30,int width,int height)4107 int H420ToAR30(const uint8_t* src_y,
4108 int src_stride_y,
4109 const uint8_t* src_u,
4110 int src_stride_u,
4111 const uint8_t* src_v,
4112 int src_stride_v,
4113 uint8_t* dst_ar30,
4114 int dst_stride_ar30,
4115 int width,
4116 int height) {
4117 return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4118 src_stride_v, dst_ar30, dst_stride_ar30,
4119 &kYvuH709Constants, width, height);
4120 }
4121
4122 #ifdef __cplusplus
4123 } // extern "C"
4124 } // namespace libyuv
4125 #endif
4126