1 /*
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "libyuv/convert_argb.h"
11
12 #include "libyuv/cpu_id.h"
13 #ifdef HAVE_JPEG
14 #include "libyuv/mjpeg_decoder.h"
15 #endif
16 #include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle.
17 #include "libyuv/rotate_argb.h"
18 #include "libyuv/row.h"
19 #include "libyuv/scale_row.h" // For ScaleRowUp2_Linear and ScaleRowUp2_Bilinear
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_AVX512BW)
94 if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
95 (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
96 I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
97 if (IS_ALIGNED(width, 32)) {
98 I422ToARGBRow = I422ToARGBRow_AVX512BW;
99 }
100 }
101 #endif
102 #if defined(HAS_I422TOARGBROW_NEON)
103 if (TestCpuFlag(kCpuHasNEON)) {
104 I422ToARGBRow = I422ToARGBRow_Any_NEON;
105 if (IS_ALIGNED(width, 8)) {
106 I422ToARGBRow = I422ToARGBRow_NEON;
107 }
108 }
109 #endif
110 #if defined(HAS_I422TOARGBROW_MSA)
111 if (TestCpuFlag(kCpuHasMSA)) {
112 I422ToARGBRow = I422ToARGBRow_Any_MSA;
113 if (IS_ALIGNED(width, 8)) {
114 I422ToARGBRow = I422ToARGBRow_MSA;
115 }
116 }
117 #endif
118 #if defined(HAS_I422TOARGBROW_LASX)
119 if (TestCpuFlag(kCpuHasLASX)) {
120 I422ToARGBRow = I422ToARGBRow_Any_LASX;
121 if (IS_ALIGNED(width, 32)) {
122 I422ToARGBRow = I422ToARGBRow_LASX;
123 }
124 }
125 #endif
126
127 for (y = 0; y < height; ++y) {
128 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
129 dst_argb += dst_stride_argb;
130 src_y += src_stride_y;
131 if (y & 1) {
132 src_u += src_stride_u;
133 src_v += src_stride_v;
134 }
135 }
136 return 0;
137 }
138
139 // Convert I420 to ARGB.
140 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)141 int I420ToARGB(const uint8_t* src_y,
142 int src_stride_y,
143 const uint8_t* src_u,
144 int src_stride_u,
145 const uint8_t* src_v,
146 int src_stride_v,
147 uint8_t* dst_argb,
148 int dst_stride_argb,
149 int width,
150 int height) {
151 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
152 src_stride_v, dst_argb, dst_stride_argb,
153 &kYuvI601Constants, width, height);
154 }
155
156 // Convert I420 to ABGR.
157 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)158 int I420ToABGR(const uint8_t* src_y,
159 int src_stride_y,
160 const uint8_t* src_u,
161 int src_stride_u,
162 const uint8_t* src_v,
163 int src_stride_v,
164 uint8_t* dst_abgr,
165 int dst_stride_abgr,
166 int width,
167 int height) {
168 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
169 src_stride_v, // Swap U and V
170 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
171 &kYvuI601Constants, // Use Yvu matrix
172 width, height);
173 }
174
175 // Convert J420 to ARGB.
176 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)177 int J420ToARGB(const uint8_t* src_y,
178 int src_stride_y,
179 const uint8_t* src_u,
180 int src_stride_u,
181 const uint8_t* src_v,
182 int src_stride_v,
183 uint8_t* dst_argb,
184 int dst_stride_argb,
185 int width,
186 int height) {
187 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
188 src_stride_v, dst_argb, dst_stride_argb,
189 &kYuvJPEGConstants, width, height);
190 }
191
192 // Convert J420 to ABGR.
193 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)194 int J420ToABGR(const uint8_t* src_y,
195 int src_stride_y,
196 const uint8_t* src_u,
197 int src_stride_u,
198 const uint8_t* src_v,
199 int src_stride_v,
200 uint8_t* dst_abgr,
201 int dst_stride_abgr,
202 int width,
203 int height) {
204 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
205 src_stride_v, // Swap U and V
206 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
207 &kYvuJPEGConstants, // Use Yvu matrix
208 width, height);
209 }
210
211 // Convert H420 to ARGB.
212 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)213 int H420ToARGB(const uint8_t* src_y,
214 int src_stride_y,
215 const uint8_t* src_u,
216 int src_stride_u,
217 const uint8_t* src_v,
218 int src_stride_v,
219 uint8_t* dst_argb,
220 int dst_stride_argb,
221 int width,
222 int height) {
223 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
224 src_stride_v, dst_argb, dst_stride_argb,
225 &kYuvH709Constants, width, height);
226 }
227
228 // Convert H420 to ABGR.
229 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)230 int H420ToABGR(const uint8_t* src_y,
231 int src_stride_y,
232 const uint8_t* src_u,
233 int src_stride_u,
234 const uint8_t* src_v,
235 int src_stride_v,
236 uint8_t* dst_abgr,
237 int dst_stride_abgr,
238 int width,
239 int height) {
240 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
241 src_stride_v, // Swap U and V
242 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
243 &kYvuH709Constants, // Use Yvu matrix
244 width, height);
245 }
246
247 // Convert U420 to ARGB.
248 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)249 int U420ToARGB(const uint8_t* src_y,
250 int src_stride_y,
251 const uint8_t* src_u,
252 int src_stride_u,
253 const uint8_t* src_v,
254 int src_stride_v,
255 uint8_t* dst_argb,
256 int dst_stride_argb,
257 int width,
258 int height) {
259 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
260 src_stride_v, dst_argb, dst_stride_argb,
261 &kYuv2020Constants, width, height);
262 }
263
264 // Convert U420 to ABGR.
265 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)266 int U420ToABGR(const uint8_t* src_y,
267 int src_stride_y,
268 const uint8_t* src_u,
269 int src_stride_u,
270 const uint8_t* src_v,
271 int src_stride_v,
272 uint8_t* dst_abgr,
273 int dst_stride_abgr,
274 int width,
275 int height) {
276 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
277 src_stride_v, // Swap U and V
278 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
279 &kYvu2020Constants, // Use Yvu matrix
280 width, height);
281 }
282
283 // Convert I422 to ARGB with matrix.
284 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)285 int I422ToARGBMatrix(const uint8_t* src_y,
286 int src_stride_y,
287 const uint8_t* src_u,
288 int src_stride_u,
289 const uint8_t* src_v,
290 int src_stride_v,
291 uint8_t* dst_argb,
292 int dst_stride_argb,
293 const struct YuvConstants* yuvconstants,
294 int width,
295 int height) {
296 int y;
297 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
298 const uint8_t* v_buf, uint8_t* rgb_buf,
299 const struct YuvConstants* yuvconstants, int width) =
300 I422ToARGBRow_C;
301 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
302 return -1;
303 }
304 // Negative height means invert the image.
305 if (height < 0) {
306 height = -height;
307 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
308 dst_stride_argb = -dst_stride_argb;
309 }
310 // Coalesce rows.
311 if (src_stride_y == width && src_stride_u * 2 == width &&
312 src_stride_v * 2 == width && dst_stride_argb == width * 4) {
313 width *= height;
314 height = 1;
315 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
316 }
317 #if defined(HAS_I422TOARGBROW_SSSE3)
318 if (TestCpuFlag(kCpuHasSSSE3)) {
319 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
320 if (IS_ALIGNED(width, 8)) {
321 I422ToARGBRow = I422ToARGBRow_SSSE3;
322 }
323 }
324 #endif
325 #if defined(HAS_I422TOARGBROW_AVX2)
326 if (TestCpuFlag(kCpuHasAVX2)) {
327 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
328 if (IS_ALIGNED(width, 16)) {
329 I422ToARGBRow = I422ToARGBRow_AVX2;
330 }
331 }
332 #endif
333 #if defined(HAS_I422TOARGBROW_AVX512BW)
334 if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
335 (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
336 I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
337 if (IS_ALIGNED(width, 32)) {
338 I422ToARGBRow = I422ToARGBRow_AVX512BW;
339 }
340 }
341 #endif
342 #if defined(HAS_I422TOARGBROW_NEON)
343 if (TestCpuFlag(kCpuHasNEON)) {
344 I422ToARGBRow = I422ToARGBRow_Any_NEON;
345 if (IS_ALIGNED(width, 8)) {
346 I422ToARGBRow = I422ToARGBRow_NEON;
347 }
348 }
349 #endif
350 #if defined(HAS_I422TOARGBROW_MSA)
351 if (TestCpuFlag(kCpuHasMSA)) {
352 I422ToARGBRow = I422ToARGBRow_Any_MSA;
353 if (IS_ALIGNED(width, 8)) {
354 I422ToARGBRow = I422ToARGBRow_MSA;
355 }
356 }
357 #endif
358 #if defined(HAS_I422TOARGBROW_LASX)
359 if (TestCpuFlag(kCpuHasLASX)) {
360 I422ToARGBRow = I422ToARGBRow_Any_LASX;
361 if (IS_ALIGNED(width, 32)) {
362 I422ToARGBRow = I422ToARGBRow_LASX;
363 }
364 }
365 #endif
366
367 for (y = 0; y < height; ++y) {
368 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
369 dst_argb += dst_stride_argb;
370 src_y += src_stride_y;
371 src_u += src_stride_u;
372 src_v += src_stride_v;
373 }
374 return 0;
375 }
376
377 // Convert I422 to ARGB.
378 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)379 int I422ToARGB(const uint8_t* src_y,
380 int src_stride_y,
381 const uint8_t* src_u,
382 int src_stride_u,
383 const uint8_t* src_v,
384 int src_stride_v,
385 uint8_t* dst_argb,
386 int dst_stride_argb,
387 int width,
388 int height) {
389 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
390 src_stride_v, dst_argb, dst_stride_argb,
391 &kYuvI601Constants, width, height);
392 }
393
394 // Convert I422 to ABGR.
395 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)396 int I422ToABGR(const uint8_t* src_y,
397 int src_stride_y,
398 const uint8_t* src_u,
399 int src_stride_u,
400 const uint8_t* src_v,
401 int src_stride_v,
402 uint8_t* dst_abgr,
403 int dst_stride_abgr,
404 int width,
405 int height) {
406 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
407 src_stride_v, // Swap U and V
408 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
409 &kYvuI601Constants, // Use Yvu matrix
410 width, height);
411 }
412
413 // Convert J422 to ARGB.
414 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)415 int J422ToARGB(const uint8_t* src_y,
416 int src_stride_y,
417 const uint8_t* src_u,
418 int src_stride_u,
419 const uint8_t* src_v,
420 int src_stride_v,
421 uint8_t* dst_argb,
422 int dst_stride_argb,
423 int width,
424 int height) {
425 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
426 src_stride_v, dst_argb, dst_stride_argb,
427 &kYuvJPEGConstants, width, height);
428 }
429
430 // Convert J422 to ABGR.
431 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)432 int J422ToABGR(const uint8_t* src_y,
433 int src_stride_y,
434 const uint8_t* src_u,
435 int src_stride_u,
436 const uint8_t* src_v,
437 int src_stride_v,
438 uint8_t* dst_abgr,
439 int dst_stride_abgr,
440 int width,
441 int height) {
442 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
443 src_stride_v, // Swap U and V
444 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
445 &kYvuJPEGConstants, // Use Yvu matrix
446 width, height);
447 }
448
449 // Convert H422 to ARGB.
450 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)451 int H422ToARGB(const uint8_t* src_y,
452 int src_stride_y,
453 const uint8_t* src_u,
454 int src_stride_u,
455 const uint8_t* src_v,
456 int src_stride_v,
457 uint8_t* dst_argb,
458 int dst_stride_argb,
459 int width,
460 int height) {
461 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
462 src_stride_v, dst_argb, dst_stride_argb,
463 &kYuvH709Constants, width, height);
464 }
465
466 // Convert H422 to ABGR.
467 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)468 int H422ToABGR(const uint8_t* src_y,
469 int src_stride_y,
470 const uint8_t* src_u,
471 int src_stride_u,
472 const uint8_t* src_v,
473 int src_stride_v,
474 uint8_t* dst_abgr,
475 int dst_stride_abgr,
476 int width,
477 int height) {
478 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
479 src_stride_v, // Swap U and V
480 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
481 &kYvuH709Constants, // Use Yvu matrix
482 width, height);
483 }
484
485 // Convert U422 to ARGB.
486 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)487 int U422ToARGB(const uint8_t* src_y,
488 int src_stride_y,
489 const uint8_t* src_u,
490 int src_stride_u,
491 const uint8_t* src_v,
492 int src_stride_v,
493 uint8_t* dst_argb,
494 int dst_stride_argb,
495 int width,
496 int height) {
497 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
498 src_stride_v, dst_argb, dst_stride_argb,
499 &kYuv2020Constants, width, height);
500 }
501
502 // Convert U422 to ABGR.
503 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)504 int U422ToABGR(const uint8_t* src_y,
505 int src_stride_y,
506 const uint8_t* src_u,
507 int src_stride_u,
508 const uint8_t* src_v,
509 int src_stride_v,
510 uint8_t* dst_abgr,
511 int dst_stride_abgr,
512 int width,
513 int height) {
514 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
515 src_stride_v, // Swap U and V
516 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
517 &kYvu2020Constants, // Use Yvu matrix
518 width, height);
519 }
520
521 // Convert I444 to ARGB with matrix.
522 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)523 int I444ToARGBMatrix(const uint8_t* src_y,
524 int src_stride_y,
525 const uint8_t* src_u,
526 int src_stride_u,
527 const uint8_t* src_v,
528 int src_stride_v,
529 uint8_t* dst_argb,
530 int dst_stride_argb,
531 const struct YuvConstants* yuvconstants,
532 int width,
533 int height) {
534 int y;
535 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
536 const uint8_t* v_buf, uint8_t* rgb_buf,
537 const struct YuvConstants* yuvconstants, int width) =
538 I444ToARGBRow_C;
539 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
540 return -1;
541 }
542 // Negative height means invert the image.
543 if (height < 0) {
544 height = -height;
545 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
546 dst_stride_argb = -dst_stride_argb;
547 }
548 // Coalesce rows.
549 if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
550 dst_stride_argb == width * 4) {
551 width *= height;
552 height = 1;
553 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
554 }
555 #if defined(HAS_I444TOARGBROW_SSSE3)
556 if (TestCpuFlag(kCpuHasSSSE3)) {
557 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
558 if (IS_ALIGNED(width, 8)) {
559 I444ToARGBRow = I444ToARGBRow_SSSE3;
560 }
561 }
562 #endif
563 #if defined(HAS_I444TOARGBROW_AVX2)
564 if (TestCpuFlag(kCpuHasAVX2)) {
565 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
566 if (IS_ALIGNED(width, 16)) {
567 I444ToARGBRow = I444ToARGBRow_AVX2;
568 }
569 }
570 #endif
571 #if defined(HAS_I444TOARGBROW_NEON)
572 if (TestCpuFlag(kCpuHasNEON)) {
573 I444ToARGBRow = I444ToARGBRow_Any_NEON;
574 if (IS_ALIGNED(width, 8)) {
575 I444ToARGBRow = I444ToARGBRow_NEON;
576 }
577 }
578 #endif
579 #if defined(HAS_I444TOARGBROW_MSA)
580 if (TestCpuFlag(kCpuHasMSA)) {
581 I444ToARGBRow = I444ToARGBRow_Any_MSA;
582 if (IS_ALIGNED(width, 8)) {
583 I444ToARGBRow = I444ToARGBRow_MSA;
584 }
585 }
586 #endif
587 #if defined(HAS_I444TOARGBROW_LSX)
588 if (TestCpuFlag(kCpuHasLSX)) {
589 I444ToARGBRow = I444ToARGBRow_Any_LSX;
590 if (IS_ALIGNED(width, 16)) {
591 I444ToARGBRow = I444ToARGBRow_LSX;
592 }
593 }
594 #endif
595
596 for (y = 0; y < height; ++y) {
597 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
598 dst_argb += dst_stride_argb;
599 src_y += src_stride_y;
600 src_u += src_stride_u;
601 src_v += src_stride_v;
602 }
603 return 0;
604 }
605
606 // Convert I444 to ARGB.
607 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)608 int I444ToARGB(const uint8_t* src_y,
609 int src_stride_y,
610 const uint8_t* src_u,
611 int src_stride_u,
612 const uint8_t* src_v,
613 int src_stride_v,
614 uint8_t* dst_argb,
615 int dst_stride_argb,
616 int width,
617 int height) {
618 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
619 src_stride_v, dst_argb, dst_stride_argb,
620 &kYuvI601Constants, width, height);
621 }
622
623 // Convert I444 to ABGR.
624 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)625 int I444ToABGR(const uint8_t* src_y,
626 int src_stride_y,
627 const uint8_t* src_u,
628 int src_stride_u,
629 const uint8_t* src_v,
630 int src_stride_v,
631 uint8_t* dst_abgr,
632 int dst_stride_abgr,
633 int width,
634 int height) {
635 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
636 src_stride_v, // Swap U and V
637 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
638 &kYvuI601Constants, // Use Yvu matrix
639 width, height);
640 }
641
642 // Convert J444 to ARGB.
643 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)644 int J444ToARGB(const uint8_t* src_y,
645 int src_stride_y,
646 const uint8_t* src_u,
647 int src_stride_u,
648 const uint8_t* src_v,
649 int src_stride_v,
650 uint8_t* dst_argb,
651 int dst_stride_argb,
652 int width,
653 int height) {
654 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
655 src_stride_v, dst_argb, dst_stride_argb,
656 &kYuvJPEGConstants, width, height);
657 }
658
659 // Convert J444 to ABGR.
660 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)661 int J444ToABGR(const uint8_t* src_y,
662 int src_stride_y,
663 const uint8_t* src_u,
664 int src_stride_u,
665 const uint8_t* src_v,
666 int src_stride_v,
667 uint8_t* dst_abgr,
668 int dst_stride_abgr,
669 int width,
670 int height) {
671 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
672 src_stride_v, // Swap U and V
673 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
674 &kYvuJPEGConstants, // Use Yvu matrix
675 width, height);
676 }
677
678 // Convert H444 to ARGB.
679 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)680 int H444ToARGB(const uint8_t* src_y,
681 int src_stride_y,
682 const uint8_t* src_u,
683 int src_stride_u,
684 const uint8_t* src_v,
685 int src_stride_v,
686 uint8_t* dst_argb,
687 int dst_stride_argb,
688 int width,
689 int height) {
690 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
691 src_stride_v, dst_argb, dst_stride_argb,
692 &kYuvH709Constants, width, height);
693 }
694
695 // Convert H444 to ABGR.
696 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)697 int H444ToABGR(const uint8_t* src_y,
698 int src_stride_y,
699 const uint8_t* src_u,
700 int src_stride_u,
701 const uint8_t* src_v,
702 int src_stride_v,
703 uint8_t* dst_abgr,
704 int dst_stride_abgr,
705 int width,
706 int height) {
707 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
708 src_stride_v, // Swap U and V
709 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
710 &kYvuH709Constants, // Use Yvu matrix
711 width, height);
712 }
713
714 // Convert U444 to ARGB.
715 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)716 int U444ToARGB(const uint8_t* src_y,
717 int src_stride_y,
718 const uint8_t* src_u,
719 int src_stride_u,
720 const uint8_t* src_v,
721 int src_stride_v,
722 uint8_t* dst_argb,
723 int dst_stride_argb,
724 int width,
725 int height) {
726 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
727 src_stride_v, dst_argb, dst_stride_argb,
728 &kYuv2020Constants, width, height);
729 }
730
731 // Convert U444 to ABGR.
732 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)733 int U444ToABGR(const uint8_t* src_y,
734 int src_stride_y,
735 const uint8_t* src_u,
736 int src_stride_u,
737 const uint8_t* src_v,
738 int src_stride_v,
739 uint8_t* dst_abgr,
740 int dst_stride_abgr,
741 int width,
742 int height) {
743 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
744 src_stride_v, // Swap U and V
745 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
746 &kYvu2020Constants, // Use Yvu matrix
747 width, height);
748 }
749
750 // Convert 10 bit YUV to ARGB with matrix.
751 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
752 // multiply 10 bit yuv into high bits to allow any number of bits.
753 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)754 int I010ToAR30Matrix(const uint16_t* src_y,
755 int src_stride_y,
756 const uint16_t* src_u,
757 int src_stride_u,
758 const uint16_t* src_v,
759 int src_stride_v,
760 uint8_t* dst_ar30,
761 int dst_stride_ar30,
762 const struct YuvConstants* yuvconstants,
763 int width,
764 int height) {
765 int y;
766 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
767 const uint16_t* v_buf, uint8_t* rgb_buf,
768 const struct YuvConstants* yuvconstants, int width) =
769 I210ToAR30Row_C;
770 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
771 return -1;
772 }
773 // Negative height means invert the image.
774 if (height < 0) {
775 height = -height;
776 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
777 dst_stride_ar30 = -dst_stride_ar30;
778 }
779 #if defined(HAS_I210TOAR30ROW_SSSE3)
780 if (TestCpuFlag(kCpuHasSSSE3)) {
781 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
782 if (IS_ALIGNED(width, 8)) {
783 I210ToAR30Row = I210ToAR30Row_SSSE3;
784 }
785 }
786 #endif
787 #if defined(HAS_I210TOAR30ROW_AVX2)
788 if (TestCpuFlag(kCpuHasAVX2)) {
789 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
790 if (IS_ALIGNED(width, 16)) {
791 I210ToAR30Row = I210ToAR30Row_AVX2;
792 }
793 }
794 #endif
795 for (y = 0; y < height; ++y) {
796 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
797 dst_ar30 += dst_stride_ar30;
798 src_y += src_stride_y;
799 if (y & 1) {
800 src_u += src_stride_u;
801 src_v += src_stride_v;
802 }
803 }
804 return 0;
805 }
806
807 // Convert I010 to AR30.
808 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)809 int I010ToAR30(const uint16_t* src_y,
810 int src_stride_y,
811 const uint16_t* src_u,
812 int src_stride_u,
813 const uint16_t* src_v,
814 int src_stride_v,
815 uint8_t* dst_ar30,
816 int dst_stride_ar30,
817 int width,
818 int height) {
819 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
820 src_stride_v, dst_ar30, dst_stride_ar30,
821 &kYuvI601Constants, width, height);
822 }
823
824 // Convert H010 to AR30.
825 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)826 int H010ToAR30(const uint16_t* src_y,
827 int src_stride_y,
828 const uint16_t* src_u,
829 int src_stride_u,
830 const uint16_t* src_v,
831 int src_stride_v,
832 uint8_t* dst_ar30,
833 int dst_stride_ar30,
834 int width,
835 int height) {
836 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
837 src_stride_v, dst_ar30, dst_stride_ar30,
838 &kYuvH709Constants, width, height);
839 }
840
841 // Convert U010 to AR30.
842 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)843 int U010ToAR30(const uint16_t* src_y,
844 int src_stride_y,
845 const uint16_t* src_u,
846 int src_stride_u,
847 const uint16_t* src_v,
848 int src_stride_v,
849 uint8_t* dst_ar30,
850 int dst_stride_ar30,
851 int width,
852 int height) {
853 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
854 src_stride_v, dst_ar30, dst_stride_ar30,
855 &kYuv2020Constants, width, height);
856 }
857
858 // Convert I010 to AB30.
859 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)860 int I010ToAB30(const uint16_t* src_y,
861 int src_stride_y,
862 const uint16_t* src_u,
863 int src_stride_u,
864 const uint16_t* src_v,
865 int src_stride_v,
866 uint8_t* dst_ab30,
867 int dst_stride_ab30,
868 int width,
869 int height) {
870 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
871 src_stride_u, dst_ab30, dst_stride_ab30,
872 &kYvuI601Constants, width, height);
873 }
874
875 // Convert H010 to AB30.
876 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)877 int H010ToAB30(const uint16_t* src_y,
878 int src_stride_y,
879 const uint16_t* src_u,
880 int src_stride_u,
881 const uint16_t* src_v,
882 int src_stride_v,
883 uint8_t* dst_ab30,
884 int dst_stride_ab30,
885 int width,
886 int height) {
887 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
888 src_stride_u, dst_ab30, dst_stride_ab30,
889 &kYvuH709Constants, width, height);
890 }
891
892 // Convert U010 to AB30.
893 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)894 int U010ToAB30(const uint16_t* src_y,
895 int src_stride_y,
896 const uint16_t* src_u,
897 int src_stride_u,
898 const uint16_t* src_v,
899 int src_stride_v,
900 uint8_t* dst_ab30,
901 int dst_stride_ab30,
902 int width,
903 int height) {
904 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
905 src_stride_u, dst_ab30, dst_stride_ab30,
906 &kYuv2020Constants, width, height);
907 }
908
909 // Convert 12 bit YUV to ARGB with matrix.
910 // TODO(fbarchard): Consider passing scale multiplier to I212ToARGB to
911 // multiply 12 bit yuv into high bits to allow any number of bits.
912 LIBYUV_API
I012ToAR30Matrix(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)913 int I012ToAR30Matrix(const uint16_t* src_y,
914 int src_stride_y,
915 const uint16_t* src_u,
916 int src_stride_u,
917 const uint16_t* src_v,
918 int src_stride_v,
919 uint8_t* dst_ar30,
920 int dst_stride_ar30,
921 const struct YuvConstants* yuvconstants,
922 int width,
923 int height) {
924 int y;
925 void (*I212ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
926 const uint16_t* v_buf, uint8_t* rgb_buf,
927 const struct YuvConstants* yuvconstants, int width) =
928 I212ToAR30Row_C;
929 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
930 return -1;
931 }
932 // Negative height means invert the image.
933 if (height < 0) {
934 height = -height;
935 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
936 dst_stride_ar30 = -dst_stride_ar30;
937 }
938 #if defined(HAS_I212TOAR30ROW_SSSE3)
939 if (TestCpuFlag(kCpuHasSSSE3)) {
940 I212ToAR30Row = I212ToAR30Row_Any_SSSE3;
941 if (IS_ALIGNED(width, 8)) {
942 I212ToAR30Row = I212ToAR30Row_SSSE3;
943 }
944 }
945 #endif
946 #if defined(HAS_I212TOAR30ROW_AVX2)
947 if (TestCpuFlag(kCpuHasAVX2)) {
948 I212ToAR30Row = I212ToAR30Row_Any_AVX2;
949 if (IS_ALIGNED(width, 16)) {
950 I212ToAR30Row = I212ToAR30Row_AVX2;
951 }
952 }
953 #endif
954 for (y = 0; y < height; ++y) {
955 I212ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
956 dst_ar30 += dst_stride_ar30;
957 src_y += src_stride_y;
958 if (y & 1) {
959 src_u += src_stride_u;
960 src_v += src_stride_v;
961 }
962 }
963 return 0;
964 }
965
966 // Convert 10 bit YUV to ARGB with matrix.
967 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
968 // multiply 10 bit yuv into high bits to allow any number of bits.
969 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)970 int I210ToAR30Matrix(const uint16_t* src_y,
971 int src_stride_y,
972 const uint16_t* src_u,
973 int src_stride_u,
974 const uint16_t* src_v,
975 int src_stride_v,
976 uint8_t* dst_ar30,
977 int dst_stride_ar30,
978 const struct YuvConstants* yuvconstants,
979 int width,
980 int height) {
981 int y;
982 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
983 const uint16_t* v_buf, uint8_t* rgb_buf,
984 const struct YuvConstants* yuvconstants, int width) =
985 I210ToAR30Row_C;
986 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
987 return -1;
988 }
989 // Negative height means invert the image.
990 if (height < 0) {
991 height = -height;
992 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
993 dst_stride_ar30 = -dst_stride_ar30;
994 }
995 #if defined(HAS_I210TOAR30ROW_SSSE3)
996 if (TestCpuFlag(kCpuHasSSSE3)) {
997 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
998 if (IS_ALIGNED(width, 8)) {
999 I210ToAR30Row = I210ToAR30Row_SSSE3;
1000 }
1001 }
1002 #endif
1003 #if defined(HAS_I210TOAR30ROW_AVX2)
1004 if (TestCpuFlag(kCpuHasAVX2)) {
1005 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
1006 if (IS_ALIGNED(width, 16)) {
1007 I210ToAR30Row = I210ToAR30Row_AVX2;
1008 }
1009 }
1010 #endif
1011 for (y = 0; y < height; ++y) {
1012 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1013 dst_ar30 += dst_stride_ar30;
1014 src_y += src_stride_y;
1015 src_u += src_stride_u;
1016 src_v += src_stride_v;
1017 }
1018 return 0;
1019 }
1020
1021 // Convert I210 to AR30.
1022 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)1023 int I210ToAR30(const uint16_t* src_y,
1024 int src_stride_y,
1025 const uint16_t* src_u,
1026 int src_stride_u,
1027 const uint16_t* src_v,
1028 int src_stride_v,
1029 uint8_t* dst_ar30,
1030 int dst_stride_ar30,
1031 int width,
1032 int height) {
1033 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1034 src_stride_v, dst_ar30, dst_stride_ar30,
1035 &kYuvI601Constants, width, height);
1036 }
1037
1038 // Convert H210 to AR30.
1039 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)1040 int H210ToAR30(const uint16_t* src_y,
1041 int src_stride_y,
1042 const uint16_t* src_u,
1043 int src_stride_u,
1044 const uint16_t* src_v,
1045 int src_stride_v,
1046 uint8_t* dst_ar30,
1047 int dst_stride_ar30,
1048 int width,
1049 int height) {
1050 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1051 src_stride_v, dst_ar30, dst_stride_ar30,
1052 &kYuvH709Constants, width, height);
1053 }
1054
1055 // Convert U210 to AR30.
1056 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)1057 int U210ToAR30(const uint16_t* src_y,
1058 int src_stride_y,
1059 const uint16_t* src_u,
1060 int src_stride_u,
1061 const uint16_t* src_v,
1062 int src_stride_v,
1063 uint8_t* dst_ar30,
1064 int dst_stride_ar30,
1065 int width,
1066 int height) {
1067 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1068 src_stride_v, dst_ar30, dst_stride_ar30,
1069 &kYuv2020Constants, width, height);
1070 }
1071
1072 // Convert I210 to AB30.
1073 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)1074 int I210ToAB30(const uint16_t* src_y,
1075 int src_stride_y,
1076 const uint16_t* src_u,
1077 int src_stride_u,
1078 const uint16_t* src_v,
1079 int src_stride_v,
1080 uint8_t* dst_ab30,
1081 int dst_stride_ab30,
1082 int width,
1083 int height) {
1084 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1085 src_stride_u, dst_ab30, dst_stride_ab30,
1086 &kYvuI601Constants, width, height);
1087 }
1088
1089 // Convert H210 to AB30.
1090 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)1091 int H210ToAB30(const uint16_t* src_y,
1092 int src_stride_y,
1093 const uint16_t* src_u,
1094 int src_stride_u,
1095 const uint16_t* src_v,
1096 int src_stride_v,
1097 uint8_t* dst_ab30,
1098 int dst_stride_ab30,
1099 int width,
1100 int height) {
1101 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1102 src_stride_u, dst_ab30, dst_stride_ab30,
1103 &kYvuH709Constants, width, height);
1104 }
1105
1106 // Convert U210 to AB30.
1107 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)1108 int U210ToAB30(const uint16_t* src_y,
1109 int src_stride_y,
1110 const uint16_t* src_u,
1111 int src_stride_u,
1112 const uint16_t* src_v,
1113 int src_stride_v,
1114 uint8_t* dst_ab30,
1115 int dst_stride_ab30,
1116 int width,
1117 int height) {
1118 return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1119 src_stride_u, dst_ab30, dst_stride_ab30,
1120 &kYuv2020Constants, width, height);
1121 }
1122
1123 LIBYUV_API
I410ToAR30Matrix(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)1124 int I410ToAR30Matrix(const uint16_t* src_y,
1125 int src_stride_y,
1126 const uint16_t* src_u,
1127 int src_stride_u,
1128 const uint16_t* src_v,
1129 int src_stride_v,
1130 uint8_t* dst_ar30,
1131 int dst_stride_ar30,
1132 const struct YuvConstants* yuvconstants,
1133 int width,
1134 int height) {
1135 int y;
1136 void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1137 const uint16_t* v_buf, uint8_t* rgb_buf,
1138 const struct YuvConstants* yuvconstants, int width) =
1139 I410ToAR30Row_C;
1140 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1141 return -1;
1142 }
1143 // Negative height means invert the image.
1144 if (height < 0) {
1145 height = -height;
1146 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1147 dst_stride_ar30 = -dst_stride_ar30;
1148 }
1149 #if defined(HAS_I410TOAR30ROW_SSSE3)
1150 if (TestCpuFlag(kCpuHasSSSE3)) {
1151 I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
1152 if (IS_ALIGNED(width, 8)) {
1153 I410ToAR30Row = I410ToAR30Row_SSSE3;
1154 }
1155 }
1156 #endif
1157 #if defined(HAS_I410TOAR30ROW_AVX2)
1158 if (TestCpuFlag(kCpuHasAVX2)) {
1159 I410ToAR30Row = I410ToAR30Row_Any_AVX2;
1160 if (IS_ALIGNED(width, 16)) {
1161 I410ToAR30Row = I410ToAR30Row_AVX2;
1162 }
1163 }
1164 #endif
1165 for (y = 0; y < height; ++y) {
1166 I410ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1167 dst_ar30 += dst_stride_ar30;
1168 src_y += src_stride_y;
1169 src_u += src_stride_u;
1170 src_v += src_stride_v;
1171 }
1172 return 0;
1173 }
1174
1175 // Convert 10 bit YUV to ARGB with matrix.
1176 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)1177 int I010ToARGBMatrix(const uint16_t* src_y,
1178 int src_stride_y,
1179 const uint16_t* src_u,
1180 int src_stride_u,
1181 const uint16_t* src_v,
1182 int src_stride_v,
1183 uint8_t* dst_argb,
1184 int dst_stride_argb,
1185 const struct YuvConstants* yuvconstants,
1186 int width,
1187 int height) {
1188 int y;
1189 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1190 const uint16_t* v_buf, uint8_t* rgb_buf,
1191 const struct YuvConstants* yuvconstants, int width) =
1192 I210ToARGBRow_C;
1193 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1194 return -1;
1195 }
1196 // Negative height means invert the image.
1197 if (height < 0) {
1198 height = -height;
1199 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1200 dst_stride_argb = -dst_stride_argb;
1201 }
1202 #if defined(HAS_I210TOARGBROW_SSSE3)
1203 if (TestCpuFlag(kCpuHasSSSE3)) {
1204 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1205 if (IS_ALIGNED(width, 8)) {
1206 I210ToARGBRow = I210ToARGBRow_SSSE3;
1207 }
1208 }
1209 #endif
1210 #if defined(HAS_I210TOARGBROW_AVX2)
1211 if (TestCpuFlag(kCpuHasAVX2)) {
1212 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1213 if (IS_ALIGNED(width, 16)) {
1214 I210ToARGBRow = I210ToARGBRow_AVX2;
1215 }
1216 }
1217 #endif
1218 for (y = 0; y < height; ++y) {
1219 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1220 dst_argb += dst_stride_argb;
1221 src_y += src_stride_y;
1222 if (y & 1) {
1223 src_u += src_stride_u;
1224 src_v += src_stride_v;
1225 }
1226 }
1227 return 0;
1228 }
1229
1230 // Convert I010 to ARGB.
1231 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)1232 int I010ToARGB(const uint16_t* src_y,
1233 int src_stride_y,
1234 const uint16_t* src_u,
1235 int src_stride_u,
1236 const uint16_t* src_v,
1237 int src_stride_v,
1238 uint8_t* dst_argb,
1239 int dst_stride_argb,
1240 int width,
1241 int height) {
1242 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1243 src_stride_v, dst_argb, dst_stride_argb,
1244 &kYuvI601Constants, width, height);
1245 }
1246
1247 // Convert I010 to ABGR.
1248 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)1249 int I010ToABGR(const uint16_t* src_y,
1250 int src_stride_y,
1251 const uint16_t* src_u,
1252 int src_stride_u,
1253 const uint16_t* src_v,
1254 int src_stride_v,
1255 uint8_t* dst_abgr,
1256 int dst_stride_abgr,
1257 int width,
1258 int height) {
1259 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1260 src_stride_v, // Swap U and V
1261 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1262 &kYvuI601Constants, // Use Yvu matrix
1263 width, height);
1264 }
1265
1266 // Convert H010 to ARGB.
1267 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)1268 int H010ToARGB(const uint16_t* src_y,
1269 int src_stride_y,
1270 const uint16_t* src_u,
1271 int src_stride_u,
1272 const uint16_t* src_v,
1273 int src_stride_v,
1274 uint8_t* dst_argb,
1275 int dst_stride_argb,
1276 int width,
1277 int height) {
1278 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1279 src_stride_v, dst_argb, dst_stride_argb,
1280 &kYuvH709Constants, width, height);
1281 }
1282
1283 // Convert H010 to ABGR.
1284 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)1285 int H010ToABGR(const uint16_t* src_y,
1286 int src_stride_y,
1287 const uint16_t* src_u,
1288 int src_stride_u,
1289 const uint16_t* src_v,
1290 int src_stride_v,
1291 uint8_t* dst_abgr,
1292 int dst_stride_abgr,
1293 int width,
1294 int height) {
1295 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1296 src_stride_v, // Swap U and V
1297 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1298 &kYvuH709Constants, // Use Yvu matrix
1299 width, height);
1300 }
1301
1302 // Convert U010 to ARGB.
1303 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)1304 int U010ToARGB(const uint16_t* src_y,
1305 int src_stride_y,
1306 const uint16_t* src_u,
1307 int src_stride_u,
1308 const uint16_t* src_v,
1309 int src_stride_v,
1310 uint8_t* dst_argb,
1311 int dst_stride_argb,
1312 int width,
1313 int height) {
1314 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1315 src_stride_v, dst_argb, dst_stride_argb,
1316 &kYuv2020Constants, width, height);
1317 }
1318
1319 // Convert U010 to ABGR.
1320 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)1321 int U010ToABGR(const uint16_t* src_y,
1322 int src_stride_y,
1323 const uint16_t* src_u,
1324 int src_stride_u,
1325 const uint16_t* src_v,
1326 int src_stride_v,
1327 uint8_t* dst_abgr,
1328 int dst_stride_abgr,
1329 int width,
1330 int height) {
1331 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1332 src_stride_v, // Swap U and V
1333 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1334 &kYvu2020Constants, // Use Yvu matrix
1335 width, height);
1336 }
1337
1338 // Convert 12 bit YUV to ARGB with matrix.
1339 LIBYUV_API
I012ToARGBMatrix(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)1340 int I012ToARGBMatrix(const uint16_t* src_y,
1341 int src_stride_y,
1342 const uint16_t* src_u,
1343 int src_stride_u,
1344 const uint16_t* src_v,
1345 int src_stride_v,
1346 uint8_t* dst_argb,
1347 int dst_stride_argb,
1348 const struct YuvConstants* yuvconstants,
1349 int width,
1350 int height) {
1351 int y;
1352 void (*I212ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1353 const uint16_t* v_buf, uint8_t* rgb_buf,
1354 const struct YuvConstants* yuvconstants, int width) =
1355 I212ToARGBRow_C;
1356 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1357 return -1;
1358 }
1359 // Negative height means invert the image.
1360 if (height < 0) {
1361 height = -height;
1362 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1363 dst_stride_argb = -dst_stride_argb;
1364 }
1365 #if defined(HAS_I212TOARGBROW_SSSE3)
1366 if (TestCpuFlag(kCpuHasSSSE3)) {
1367 I212ToARGBRow = I212ToARGBRow_Any_SSSE3;
1368 if (IS_ALIGNED(width, 8)) {
1369 I212ToARGBRow = I212ToARGBRow_SSSE3;
1370 }
1371 }
1372 #endif
1373 #if defined(HAS_I212TOARGBROW_AVX2)
1374 if (TestCpuFlag(kCpuHasAVX2)) {
1375 I212ToARGBRow = I212ToARGBRow_Any_AVX2;
1376 if (IS_ALIGNED(width, 16)) {
1377 I212ToARGBRow = I212ToARGBRow_AVX2;
1378 }
1379 }
1380 #endif
1381 for (y = 0; y < height; ++y) {
1382 I212ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1383 dst_argb += dst_stride_argb;
1384 src_y += src_stride_y;
1385 if (y & 1) {
1386 src_u += src_stride_u;
1387 src_v += src_stride_v;
1388 }
1389 }
1390 return 0;
1391 }
1392
1393 // Convert 10 bit 422 YUV to ARGB with matrix.
1394 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)1395 int I210ToARGBMatrix(const uint16_t* src_y,
1396 int src_stride_y,
1397 const uint16_t* src_u,
1398 int src_stride_u,
1399 const uint16_t* src_v,
1400 int src_stride_v,
1401 uint8_t* dst_argb,
1402 int dst_stride_argb,
1403 const struct YuvConstants* yuvconstants,
1404 int width,
1405 int height) {
1406 int y;
1407 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1408 const uint16_t* v_buf, uint8_t* rgb_buf,
1409 const struct YuvConstants* yuvconstants, int width) =
1410 I210ToARGBRow_C;
1411 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1412 return -1;
1413 }
1414 // Negative height means invert the image.
1415 if (height < 0) {
1416 height = -height;
1417 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1418 dst_stride_argb = -dst_stride_argb;
1419 }
1420 #if defined(HAS_I210TOARGBROW_SSSE3)
1421 if (TestCpuFlag(kCpuHasSSSE3)) {
1422 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1423 if (IS_ALIGNED(width, 8)) {
1424 I210ToARGBRow = I210ToARGBRow_SSSE3;
1425 }
1426 }
1427 #endif
1428 #if defined(HAS_I210TOARGBROW_AVX2)
1429 if (TestCpuFlag(kCpuHasAVX2)) {
1430 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1431 if (IS_ALIGNED(width, 16)) {
1432 I210ToARGBRow = I210ToARGBRow_AVX2;
1433 }
1434 }
1435 #endif
1436 for (y = 0; y < height; ++y) {
1437 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1438 dst_argb += dst_stride_argb;
1439 src_y += src_stride_y;
1440 src_u += src_stride_u;
1441 src_v += src_stride_v;
1442 }
1443 return 0;
1444 }
1445
1446 // Convert I210 to ARGB.
1447 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)1448 int I210ToARGB(const uint16_t* src_y,
1449 int src_stride_y,
1450 const uint16_t* src_u,
1451 int src_stride_u,
1452 const uint16_t* src_v,
1453 int src_stride_v,
1454 uint8_t* dst_argb,
1455 int dst_stride_argb,
1456 int width,
1457 int height) {
1458 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1459 src_stride_v, dst_argb, dst_stride_argb,
1460 &kYuvI601Constants, width, height);
1461 }
1462
1463 // Convert I210 to ABGR.
1464 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)1465 int I210ToABGR(const uint16_t* src_y,
1466 int src_stride_y,
1467 const uint16_t* src_u,
1468 int src_stride_u,
1469 const uint16_t* src_v,
1470 int src_stride_v,
1471 uint8_t* dst_abgr,
1472 int dst_stride_abgr,
1473 int width,
1474 int height) {
1475 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1476 src_stride_v, // Swap U and V
1477 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1478 &kYvuI601Constants, // Use Yvu matrix
1479 width, height);
1480 }
1481
1482 // Convert H210 to ARGB.
1483 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)1484 int H210ToARGB(const uint16_t* src_y,
1485 int src_stride_y,
1486 const uint16_t* src_u,
1487 int src_stride_u,
1488 const uint16_t* src_v,
1489 int src_stride_v,
1490 uint8_t* dst_argb,
1491 int dst_stride_argb,
1492 int width,
1493 int height) {
1494 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1495 src_stride_v, dst_argb, dst_stride_argb,
1496 &kYuvH709Constants, width, height);
1497 }
1498
1499 // Convert H210 to ABGR.
1500 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)1501 int H210ToABGR(const uint16_t* src_y,
1502 int src_stride_y,
1503 const uint16_t* src_u,
1504 int src_stride_u,
1505 const uint16_t* src_v,
1506 int src_stride_v,
1507 uint8_t* dst_abgr,
1508 int dst_stride_abgr,
1509 int width,
1510 int height) {
1511 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1512 src_stride_v, // Swap U and V
1513 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1514 &kYvuH709Constants, // Use Yvu matrix
1515 width, height);
1516 }
1517
1518 // Convert U210 to ARGB.
1519 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)1520 int U210ToARGB(const uint16_t* src_y,
1521 int src_stride_y,
1522 const uint16_t* src_u,
1523 int src_stride_u,
1524 const uint16_t* src_v,
1525 int src_stride_v,
1526 uint8_t* dst_argb,
1527 int dst_stride_argb,
1528 int width,
1529 int height) {
1530 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1531 src_stride_v, dst_argb, dst_stride_argb,
1532 &kYuv2020Constants, width, height);
1533 }
1534
1535 // Convert U210 to ABGR.
1536 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)1537 int U210ToABGR(const uint16_t* src_y,
1538 int src_stride_y,
1539 const uint16_t* src_u,
1540 int src_stride_u,
1541 const uint16_t* src_v,
1542 int src_stride_v,
1543 uint8_t* dst_abgr,
1544 int dst_stride_abgr,
1545 int width,
1546 int height) {
1547 return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1548 src_stride_v, // Swap U and V
1549 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1550 &kYvu2020Constants, // Use Yvu matrix
1551 width, height);
1552 }
1553
1554 LIBYUV_API
I410ToARGBMatrix(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)1555 int I410ToARGBMatrix(const uint16_t* src_y,
1556 int src_stride_y,
1557 const uint16_t* src_u,
1558 int src_stride_u,
1559 const uint16_t* src_v,
1560 int src_stride_v,
1561 uint8_t* dst_argb,
1562 int dst_stride_argb,
1563 const struct YuvConstants* yuvconstants,
1564 int width,
1565 int height) {
1566 int y;
1567 void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1568 const uint16_t* v_buf, uint8_t* rgb_buf,
1569 const struct YuvConstants* yuvconstants, int width) =
1570 I410ToARGBRow_C;
1571 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1572 return -1;
1573 }
1574 // Negative height means invert the image.
1575 if (height < 0) {
1576 height = -height;
1577 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1578 dst_stride_argb = -dst_stride_argb;
1579 }
1580 #if defined(HAS_I410TOARGBROW_SSSE3)
1581 if (TestCpuFlag(kCpuHasSSSE3)) {
1582 I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
1583 if (IS_ALIGNED(width, 8)) {
1584 I410ToARGBRow = I410ToARGBRow_SSSE3;
1585 }
1586 }
1587 #endif
1588 #if defined(HAS_I410TOARGBROW_AVX2)
1589 if (TestCpuFlag(kCpuHasAVX2)) {
1590 I410ToARGBRow = I410ToARGBRow_Any_AVX2;
1591 if (IS_ALIGNED(width, 16)) {
1592 I410ToARGBRow = I410ToARGBRow_AVX2;
1593 }
1594 }
1595 #endif
1596 for (y = 0; y < height; ++y) {
1597 I410ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1598 dst_argb += dst_stride_argb;
1599 src_y += src_stride_y;
1600 src_u += src_stride_u;
1601 src_v += src_stride_v;
1602 }
1603 return 0;
1604 }
1605
1606 LIBYUV_API
P010ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1607 int P010ToARGBMatrix(const uint16_t* src_y,
1608 int src_stride_y,
1609 const uint16_t* src_uv,
1610 int src_stride_uv,
1611 uint8_t* dst_argb,
1612 int dst_stride_argb,
1613 const struct YuvConstants* yuvconstants,
1614 int width,
1615 int height) {
1616 int y;
1617 void (*P210ToARGBRow)(
1618 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1619 const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
1620 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1621 return -1;
1622 }
1623 // Negative height means invert the image.
1624 if (height < 0) {
1625 height = -height;
1626 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1627 dst_stride_argb = -dst_stride_argb;
1628 }
1629 #if defined(HAS_P210TOARGBROW_SSSE3)
1630 if (TestCpuFlag(kCpuHasSSSE3)) {
1631 P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
1632 if (IS_ALIGNED(width, 8)) {
1633 P210ToARGBRow = P210ToARGBRow_SSSE3;
1634 }
1635 }
1636 #endif
1637 #if defined(HAS_P210TOARGBROW_AVX2)
1638 if (TestCpuFlag(kCpuHasAVX2)) {
1639 P210ToARGBRow = P210ToARGBRow_Any_AVX2;
1640 if (IS_ALIGNED(width, 16)) {
1641 P210ToARGBRow = P210ToARGBRow_AVX2;
1642 }
1643 }
1644 #endif
1645 for (y = 0; y < height; ++y) {
1646 P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
1647 dst_argb += dst_stride_argb;
1648 src_y += src_stride_y;
1649 if (y & 1) {
1650 src_uv += src_stride_uv;
1651 }
1652 }
1653 return 0;
1654 }
1655
1656 LIBYUV_API
P210ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1657 int P210ToARGBMatrix(const uint16_t* src_y,
1658 int src_stride_y,
1659 const uint16_t* src_uv,
1660 int src_stride_uv,
1661 uint8_t* dst_argb,
1662 int dst_stride_argb,
1663 const struct YuvConstants* yuvconstants,
1664 int width,
1665 int height) {
1666 int y;
1667 void (*P210ToARGBRow)(
1668 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1669 const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
1670 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1671 return -1;
1672 }
1673 // Negative height means invert the image.
1674 if (height < 0) {
1675 height = -height;
1676 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1677 dst_stride_argb = -dst_stride_argb;
1678 }
1679 #if defined(HAS_P210TOARGBROW_SSSE3)
1680 if (TestCpuFlag(kCpuHasSSSE3)) {
1681 P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
1682 if (IS_ALIGNED(width, 8)) {
1683 P210ToARGBRow = P210ToARGBRow_SSSE3;
1684 }
1685 }
1686 #endif
1687 #if defined(HAS_P210TOARGBROW_AVX2)
1688 if (TestCpuFlag(kCpuHasAVX2)) {
1689 P210ToARGBRow = P210ToARGBRow_Any_AVX2;
1690 if (IS_ALIGNED(width, 16)) {
1691 P210ToARGBRow = P210ToARGBRow_AVX2;
1692 }
1693 }
1694 #endif
1695 for (y = 0; y < height; ++y) {
1696 P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
1697 dst_argb += dst_stride_argb;
1698 src_y += src_stride_y;
1699 src_uv += src_stride_uv;
1700 }
1701 return 0;
1702 }
1703
1704 LIBYUV_API
P010ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1705 int P010ToAR30Matrix(const uint16_t* src_y,
1706 int src_stride_y,
1707 const uint16_t* src_uv,
1708 int src_stride_uv,
1709 uint8_t* dst_ar30,
1710 int dst_stride_ar30,
1711 const struct YuvConstants* yuvconstants,
1712 int width,
1713 int height) {
1714 int y;
1715 void (*P210ToAR30Row)(
1716 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1717 const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
1718 if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
1719 return -1;
1720 }
1721 // Negative height means invert the image.
1722 if (height < 0) {
1723 height = -height;
1724 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1725 dst_stride_ar30 = -dst_stride_ar30;
1726 }
1727 #if defined(HAS_P210TOAR30ROW_SSSE3)
1728 if (TestCpuFlag(kCpuHasSSSE3)) {
1729 P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
1730 if (IS_ALIGNED(width, 8)) {
1731 P210ToAR30Row = P210ToAR30Row_SSSE3;
1732 }
1733 }
1734 #endif
1735 #if defined(HAS_P210TOAR30ROW_AVX2)
1736 if (TestCpuFlag(kCpuHasAVX2)) {
1737 P210ToAR30Row = P210ToAR30Row_Any_AVX2;
1738 if (IS_ALIGNED(width, 16)) {
1739 P210ToAR30Row = P210ToAR30Row_AVX2;
1740 }
1741 }
1742 #endif
1743 for (y = 0; y < height; ++y) {
1744 P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
1745 dst_ar30 += dst_stride_ar30;
1746 src_y += src_stride_y;
1747 if (y & 1) {
1748 src_uv += src_stride_uv;
1749 }
1750 }
1751 return 0;
1752 }
1753
1754 LIBYUV_API
P210ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1755 int P210ToAR30Matrix(const uint16_t* src_y,
1756 int src_stride_y,
1757 const uint16_t* src_uv,
1758 int src_stride_uv,
1759 uint8_t* dst_ar30,
1760 int dst_stride_ar30,
1761 const struct YuvConstants* yuvconstants,
1762 int width,
1763 int height) {
1764 int y;
1765 void (*P210ToAR30Row)(
1766 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1767 const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
1768 if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
1769 return -1;
1770 }
1771 // Negative height means invert the image.
1772 if (height < 0) {
1773 height = -height;
1774 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1775 dst_stride_ar30 = -dst_stride_ar30;
1776 }
1777 #if defined(HAS_P210TOAR30ROW_SSSE3)
1778 if (TestCpuFlag(kCpuHasSSSE3)) {
1779 P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
1780 if (IS_ALIGNED(width, 8)) {
1781 P210ToAR30Row = P210ToAR30Row_SSSE3;
1782 }
1783 }
1784 #endif
1785 #if defined(HAS_P210TOAR30ROW_AVX2)
1786 if (TestCpuFlag(kCpuHasAVX2)) {
1787 P210ToAR30Row = P210ToAR30Row_Any_AVX2;
1788 if (IS_ALIGNED(width, 16)) {
1789 P210ToAR30Row = P210ToAR30Row_AVX2;
1790 }
1791 }
1792 #endif
1793 for (y = 0; y < height; ++y) {
1794 P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
1795 dst_ar30 += dst_stride_ar30;
1796 src_y += src_stride_y;
1797 src_uv += src_stride_uv;
1798 }
1799 return 0;
1800 }
1801
1802 // Convert I420 with Alpha to preattenuated ARGB with matrix.
1803 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)1804 int I420AlphaToARGBMatrix(const uint8_t* src_y,
1805 int src_stride_y,
1806 const uint8_t* src_u,
1807 int src_stride_u,
1808 const uint8_t* src_v,
1809 int src_stride_v,
1810 const uint8_t* src_a,
1811 int src_stride_a,
1812 uint8_t* dst_argb,
1813 int dst_stride_argb,
1814 const struct YuvConstants* yuvconstants,
1815 int width,
1816 int height,
1817 int attenuate) {
1818 int y;
1819 void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1820 const uint8_t* v_buf, const uint8_t* a_buf,
1821 uint8_t* dst_argb,
1822 const struct YuvConstants* yuvconstants,
1823 int width) = I422AlphaToARGBRow_C;
1824 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
1825 int width) = ARGBAttenuateRow_C;
1826 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
1827 height == 0) {
1828 return -1;
1829 }
1830 // Negative height means invert the image.
1831 if (height < 0) {
1832 height = -height;
1833 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1834 dst_stride_argb = -dst_stride_argb;
1835 }
1836 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
1837 if (TestCpuFlag(kCpuHasSSSE3)) {
1838 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
1839 if (IS_ALIGNED(width, 8)) {
1840 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
1841 }
1842 }
1843 #endif
1844 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
1845 if (TestCpuFlag(kCpuHasAVX2)) {
1846 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
1847 if (IS_ALIGNED(width, 16)) {
1848 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
1849 }
1850 }
1851 #endif
1852 #if defined(HAS_I422ALPHATOARGBROW_NEON)
1853 if (TestCpuFlag(kCpuHasNEON)) {
1854 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
1855 if (IS_ALIGNED(width, 8)) {
1856 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
1857 }
1858 }
1859 #endif
1860 #if defined(HAS_I422ALPHATOARGBROW_MSA)
1861 if (TestCpuFlag(kCpuHasMSA)) {
1862 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
1863 if (IS_ALIGNED(width, 8)) {
1864 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
1865 }
1866 }
1867 #endif
1868 #if defined(HAS_I422ALPHATOARGBROW_LASX)
1869 if (TestCpuFlag(kCpuHasLASX)) {
1870 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
1871 if (IS_ALIGNED(width, 16)) {
1872 I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
1873 }
1874 }
1875 #endif
1876 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
1877 if (TestCpuFlag(kCpuHasSSSE3)) {
1878 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1879 if (IS_ALIGNED(width, 4)) {
1880 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1881 }
1882 }
1883 #endif
1884 #if defined(HAS_ARGBATTENUATEROW_AVX2)
1885 if (TestCpuFlag(kCpuHasAVX2)) {
1886 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1887 if (IS_ALIGNED(width, 8)) {
1888 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1889 }
1890 }
1891 #endif
1892 #if defined(HAS_ARGBATTENUATEROW_NEON)
1893 if (TestCpuFlag(kCpuHasNEON)) {
1894 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1895 if (IS_ALIGNED(width, 8)) {
1896 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1897 }
1898 }
1899 #endif
1900 #if defined(HAS_ARGBATTENUATEROW_MSA)
1901 if (TestCpuFlag(kCpuHasMSA)) {
1902 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
1903 if (IS_ALIGNED(width, 8)) {
1904 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
1905 }
1906 }
1907 #endif
1908
1909 for (y = 0; y < height; ++y) {
1910 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
1911 width);
1912 if (attenuate) {
1913 ARGBAttenuateRow(dst_argb, dst_argb, width);
1914 }
1915 dst_argb += dst_stride_argb;
1916 src_a += src_stride_a;
1917 src_y += src_stride_y;
1918 if (y & 1) {
1919 src_u += src_stride_u;
1920 src_v += src_stride_v;
1921 }
1922 }
1923 return 0;
1924 }
1925
1926 // Convert I422 with Alpha to preattenuated ARGB with matrix.
1927 LIBYUV_API
I422AlphaToARGBMatrix(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)1928 int I422AlphaToARGBMatrix(const uint8_t* src_y,
1929 int src_stride_y,
1930 const uint8_t* src_u,
1931 int src_stride_u,
1932 const uint8_t* src_v,
1933 int src_stride_v,
1934 const uint8_t* src_a,
1935 int src_stride_a,
1936 uint8_t* dst_argb,
1937 int dst_stride_argb,
1938 const struct YuvConstants* yuvconstants,
1939 int width,
1940 int height,
1941 int attenuate) {
1942 int y;
1943 void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1944 const uint8_t* v_buf, const uint8_t* a_buf,
1945 uint8_t* dst_argb,
1946 const struct YuvConstants* yuvconstants,
1947 int width) = I422AlphaToARGBRow_C;
1948 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
1949 int width) = ARGBAttenuateRow_C;
1950 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
1951 height == 0) {
1952 return -1;
1953 }
1954 // Negative height means invert the image.
1955 if (height < 0) {
1956 height = -height;
1957 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1958 dst_stride_argb = -dst_stride_argb;
1959 }
1960 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
1961 if (TestCpuFlag(kCpuHasSSSE3)) {
1962 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
1963 if (IS_ALIGNED(width, 8)) {
1964 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
1965 }
1966 }
1967 #endif
1968 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
1969 if (TestCpuFlag(kCpuHasAVX2)) {
1970 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
1971 if (IS_ALIGNED(width, 16)) {
1972 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
1973 }
1974 }
1975 #endif
1976 #if defined(HAS_I422ALPHATOARGBROW_NEON)
1977 if (TestCpuFlag(kCpuHasNEON)) {
1978 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
1979 if (IS_ALIGNED(width, 8)) {
1980 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
1981 }
1982 }
1983 #endif
1984 #if defined(HAS_I422ALPHATOARGBROW_MSA)
1985 if (TestCpuFlag(kCpuHasMSA)) {
1986 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
1987 if (IS_ALIGNED(width, 8)) {
1988 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
1989 }
1990 }
1991 #endif
1992 #if defined(HAS_I422ALPHATOARGBROW_LASX)
1993 if (TestCpuFlag(kCpuHasLASX)) {
1994 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
1995 if (IS_ALIGNED(width, 16)) {
1996 I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
1997 }
1998 }
1999 #endif
2000 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2001 if (TestCpuFlag(kCpuHasSSSE3)) {
2002 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2003 if (IS_ALIGNED(width, 4)) {
2004 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2005 }
2006 }
2007 #endif
2008 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2009 if (TestCpuFlag(kCpuHasAVX2)) {
2010 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2011 if (IS_ALIGNED(width, 8)) {
2012 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2013 }
2014 }
2015 #endif
2016 #if defined(HAS_ARGBATTENUATEROW_NEON)
2017 if (TestCpuFlag(kCpuHasNEON)) {
2018 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2019 if (IS_ALIGNED(width, 8)) {
2020 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2021 }
2022 }
2023 #endif
2024 #if defined(HAS_ARGBATTENUATEROW_MSA)
2025 if (TestCpuFlag(kCpuHasMSA)) {
2026 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2027 if (IS_ALIGNED(width, 8)) {
2028 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2029 }
2030 }
2031 #endif
2032
2033 for (y = 0; y < height; ++y) {
2034 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2035 width);
2036 if (attenuate) {
2037 ARGBAttenuateRow(dst_argb, dst_argb, width);
2038 }
2039 dst_argb += dst_stride_argb;
2040 src_a += src_stride_a;
2041 src_y += src_stride_y;
2042 src_u += src_stride_u;
2043 src_v += src_stride_v;
2044 }
2045 return 0;
2046 }
2047
2048 // Convert I444 with Alpha to preattenuated ARGB with matrix.
2049 LIBYUV_API
I444AlphaToARGBMatrix(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)2050 int I444AlphaToARGBMatrix(const uint8_t* src_y,
2051 int src_stride_y,
2052 const uint8_t* src_u,
2053 int src_stride_u,
2054 const uint8_t* src_v,
2055 int src_stride_v,
2056 const uint8_t* src_a,
2057 int src_stride_a,
2058 uint8_t* dst_argb,
2059 int dst_stride_argb,
2060 const struct YuvConstants* yuvconstants,
2061 int width,
2062 int height,
2063 int attenuate) {
2064 int y;
2065 void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2066 const uint8_t* v_buf, const uint8_t* a_buf,
2067 uint8_t* dst_argb,
2068 const struct YuvConstants* yuvconstants,
2069 int width) = I444AlphaToARGBRow_C;
2070 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2071 int width) = ARGBAttenuateRow_C;
2072 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2073 height == 0) {
2074 return -1;
2075 }
2076 // Negative height means invert the image.
2077 if (height < 0) {
2078 height = -height;
2079 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2080 dst_stride_argb = -dst_stride_argb;
2081 }
2082 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
2083 if (TestCpuFlag(kCpuHasSSSE3)) {
2084 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
2085 if (IS_ALIGNED(width, 8)) {
2086 I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
2087 }
2088 }
2089 #endif
2090 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
2091 if (TestCpuFlag(kCpuHasAVX2)) {
2092 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
2093 if (IS_ALIGNED(width, 16)) {
2094 I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
2095 }
2096 }
2097 #endif
2098 #if defined(HAS_I444ALPHATOARGBROW_NEON)
2099 if (TestCpuFlag(kCpuHasNEON)) {
2100 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
2101 if (IS_ALIGNED(width, 8)) {
2102 I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
2103 }
2104 }
2105 #endif
2106 #if defined(HAS_I444ALPHATOARGBROW_MSA)
2107 if (TestCpuFlag(kCpuHasMSA)) {
2108 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
2109 if (IS_ALIGNED(width, 8)) {
2110 I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
2111 }
2112 }
2113 #endif
2114 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2115 if (TestCpuFlag(kCpuHasSSSE3)) {
2116 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2117 if (IS_ALIGNED(width, 4)) {
2118 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2119 }
2120 }
2121 #endif
2122 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2123 if (TestCpuFlag(kCpuHasAVX2)) {
2124 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2125 if (IS_ALIGNED(width, 8)) {
2126 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2127 }
2128 }
2129 #endif
2130 #if defined(HAS_ARGBATTENUATEROW_NEON)
2131 if (TestCpuFlag(kCpuHasNEON)) {
2132 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2133 if (IS_ALIGNED(width, 8)) {
2134 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2135 }
2136 }
2137 #endif
2138 #if defined(HAS_ARGBATTENUATEROW_MSA)
2139 if (TestCpuFlag(kCpuHasMSA)) {
2140 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2141 if (IS_ALIGNED(width, 8)) {
2142 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2143 }
2144 }
2145 #endif
2146
2147 for (y = 0; y < height; ++y) {
2148 I444AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2149 width);
2150 if (attenuate) {
2151 ARGBAttenuateRow(dst_argb, dst_argb, width);
2152 }
2153 dst_argb += dst_stride_argb;
2154 src_a += src_stride_a;
2155 src_y += src_stride_y;
2156 src_u += src_stride_u;
2157 src_v += src_stride_v;
2158 }
2159 return 0;
2160 }
2161
2162 // Convert I420 with Alpha to ARGB.
2163 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)2164 int I420AlphaToARGB(const uint8_t* src_y,
2165 int src_stride_y,
2166 const uint8_t* src_u,
2167 int src_stride_u,
2168 const uint8_t* src_v,
2169 int src_stride_v,
2170 const uint8_t* src_a,
2171 int src_stride_a,
2172 uint8_t* dst_argb,
2173 int dst_stride_argb,
2174 int width,
2175 int height,
2176 int attenuate) {
2177 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2178 src_stride_v, src_a, src_stride_a, dst_argb,
2179 dst_stride_argb, &kYuvI601Constants, width,
2180 height, attenuate);
2181 }
2182
2183 // Convert I420 with Alpha to ABGR.
2184 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)2185 int I420AlphaToABGR(const uint8_t* src_y,
2186 int src_stride_y,
2187 const uint8_t* src_u,
2188 int src_stride_u,
2189 const uint8_t* src_v,
2190 int src_stride_v,
2191 const uint8_t* src_a,
2192 int src_stride_a,
2193 uint8_t* dst_abgr,
2194 int dst_stride_abgr,
2195 int width,
2196 int height,
2197 int attenuate) {
2198 return I420AlphaToARGBMatrix(
2199 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
2200 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2201 &kYvuI601Constants, // Use Yvu matrix
2202 width, height, attenuate);
2203 }
2204
2205 // Convert I422 with Alpha to ARGB.
2206 LIBYUV_API
I422AlphaToARGB(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)2207 int I422AlphaToARGB(const uint8_t* src_y,
2208 int src_stride_y,
2209 const uint8_t* src_u,
2210 int src_stride_u,
2211 const uint8_t* src_v,
2212 int src_stride_v,
2213 const uint8_t* src_a,
2214 int src_stride_a,
2215 uint8_t* dst_argb,
2216 int dst_stride_argb,
2217 int width,
2218 int height,
2219 int attenuate) {
2220 return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2221 src_stride_v, src_a, src_stride_a, dst_argb,
2222 dst_stride_argb, &kYuvI601Constants, width,
2223 height, attenuate);
2224 }
2225
2226 // Convert I422 with Alpha to ABGR.
2227 LIBYUV_API
I422AlphaToABGR(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)2228 int I422AlphaToABGR(const uint8_t* src_y,
2229 int src_stride_y,
2230 const uint8_t* src_u,
2231 int src_stride_u,
2232 const uint8_t* src_v,
2233 int src_stride_v,
2234 const uint8_t* src_a,
2235 int src_stride_a,
2236 uint8_t* dst_abgr,
2237 int dst_stride_abgr,
2238 int width,
2239 int height,
2240 int attenuate) {
2241 return I422AlphaToARGBMatrix(
2242 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
2243 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2244 &kYvuI601Constants, // Use Yvu matrix
2245 width, height, attenuate);
2246 }
2247
2248 // Convert I444 with Alpha to ARGB.
2249 LIBYUV_API
I444AlphaToARGB(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)2250 int I444AlphaToARGB(const uint8_t* src_y,
2251 int src_stride_y,
2252 const uint8_t* src_u,
2253 int src_stride_u,
2254 const uint8_t* src_v,
2255 int src_stride_v,
2256 const uint8_t* src_a,
2257 int src_stride_a,
2258 uint8_t* dst_argb,
2259 int dst_stride_argb,
2260 int width,
2261 int height,
2262 int attenuate) {
2263 return I444AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2264 src_stride_v, src_a, src_stride_a, dst_argb,
2265 dst_stride_argb, &kYuvI601Constants, width,
2266 height, attenuate);
2267 }
2268
2269 // Convert I444 with Alpha to ABGR.
2270 LIBYUV_API
I444AlphaToABGR(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)2271 int I444AlphaToABGR(const uint8_t* src_y,
2272 int src_stride_y,
2273 const uint8_t* src_u,
2274 int src_stride_u,
2275 const uint8_t* src_v,
2276 int src_stride_v,
2277 const uint8_t* src_a,
2278 int src_stride_a,
2279 uint8_t* dst_abgr,
2280 int dst_stride_abgr,
2281 int width,
2282 int height,
2283 int attenuate) {
2284 return I444AlphaToARGBMatrix(
2285 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
2286 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2287 &kYvuI601Constants, // Use Yvu matrix
2288 width, height, attenuate);
2289 }
2290
2291 // Convert I010 with Alpha to preattenuated ARGB with matrix.
2292 LIBYUV_API
I010AlphaToARGBMatrix(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,const uint16_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)2293 int I010AlphaToARGBMatrix(const uint16_t* src_y,
2294 int src_stride_y,
2295 const uint16_t* src_u,
2296 int src_stride_u,
2297 const uint16_t* src_v,
2298 int src_stride_v,
2299 const uint16_t* src_a,
2300 int src_stride_a,
2301 uint8_t* dst_argb,
2302 int dst_stride_argb,
2303 const struct YuvConstants* yuvconstants,
2304 int width,
2305 int height,
2306 int attenuate) {
2307 int y;
2308 void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2309 const uint16_t* v_buf, const uint16_t* a_buf,
2310 uint8_t* dst_argb,
2311 const struct YuvConstants* yuvconstants,
2312 int width) = I210AlphaToARGBRow_C;
2313 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2314 int width) = ARGBAttenuateRow_C;
2315 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2316 height == 0) {
2317 return -1;
2318 }
2319 // Negative height means invert the image.
2320 if (height < 0) {
2321 height = -height;
2322 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2323 dst_stride_argb = -dst_stride_argb;
2324 }
2325 #if defined(HAS_I210ALPHATOARGBROW_SSSE3)
2326 if (TestCpuFlag(kCpuHasSSSE3)) {
2327 I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
2328 if (IS_ALIGNED(width, 8)) {
2329 I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
2330 }
2331 }
2332 #endif
2333 #if defined(HAS_I210ALPHATOARGBROW_AVX2)
2334 if (TestCpuFlag(kCpuHasAVX2)) {
2335 I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
2336 if (IS_ALIGNED(width, 16)) {
2337 I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
2338 }
2339 }
2340 #endif
2341 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2342 if (TestCpuFlag(kCpuHasSSSE3)) {
2343 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2344 if (IS_ALIGNED(width, 4)) {
2345 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2346 }
2347 }
2348 #endif
2349 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2350 if (TestCpuFlag(kCpuHasAVX2)) {
2351 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2352 if (IS_ALIGNED(width, 8)) {
2353 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2354 }
2355 }
2356 #endif
2357 #if defined(HAS_ARGBATTENUATEROW_NEON)
2358 if (TestCpuFlag(kCpuHasNEON)) {
2359 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2360 if (IS_ALIGNED(width, 8)) {
2361 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2362 }
2363 }
2364 #endif
2365 #if defined(HAS_ARGBATTENUATEROW_MSA)
2366 if (TestCpuFlag(kCpuHasMSA)) {
2367 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2368 if (IS_ALIGNED(width, 8)) {
2369 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2370 }
2371 }
2372 #endif
2373
2374 for (y = 0; y < height; ++y) {
2375 I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2376 width);
2377 if (attenuate) {
2378 ARGBAttenuateRow(dst_argb, dst_argb, width);
2379 }
2380 dst_argb += dst_stride_argb;
2381 src_a += src_stride_a;
2382 src_y += src_stride_y;
2383 if (y & 1) {
2384 src_u += src_stride_u;
2385 src_v += src_stride_v;
2386 }
2387 }
2388 return 0;
2389 }
2390
2391 // Convert I210 with Alpha to preattenuated ARGB with matrix.
2392 LIBYUV_API
I210AlphaToARGBMatrix(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,const uint16_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)2393 int I210AlphaToARGBMatrix(const uint16_t* src_y,
2394 int src_stride_y,
2395 const uint16_t* src_u,
2396 int src_stride_u,
2397 const uint16_t* src_v,
2398 int src_stride_v,
2399 const uint16_t* src_a,
2400 int src_stride_a,
2401 uint8_t* dst_argb,
2402 int dst_stride_argb,
2403 const struct YuvConstants* yuvconstants,
2404 int width,
2405 int height,
2406 int attenuate) {
2407 int y;
2408 void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2409 const uint16_t* v_buf, const uint16_t* a_buf,
2410 uint8_t* dst_argb,
2411 const struct YuvConstants* yuvconstants,
2412 int width) = I210AlphaToARGBRow_C;
2413 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2414 int width) = ARGBAttenuateRow_C;
2415 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2416 height == 0) {
2417 return -1;
2418 }
2419 // Negative height means invert the image.
2420 if (height < 0) {
2421 height = -height;
2422 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2423 dst_stride_argb = -dst_stride_argb;
2424 }
2425 #if defined(HAS_I210ALPHATOARGBROW_SSSE3)
2426 if (TestCpuFlag(kCpuHasSSSE3)) {
2427 I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
2428 if (IS_ALIGNED(width, 8)) {
2429 I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
2430 }
2431 }
2432 #endif
2433 #if defined(HAS_I210ALPHATOARGBROW_AVX2)
2434 if (TestCpuFlag(kCpuHasAVX2)) {
2435 I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
2436 if (IS_ALIGNED(width, 16)) {
2437 I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
2438 }
2439 }
2440 #endif
2441 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2442 if (TestCpuFlag(kCpuHasSSSE3)) {
2443 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2444 if (IS_ALIGNED(width, 4)) {
2445 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2446 }
2447 }
2448 #endif
2449 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2450 if (TestCpuFlag(kCpuHasAVX2)) {
2451 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2452 if (IS_ALIGNED(width, 8)) {
2453 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2454 }
2455 }
2456 #endif
2457 #if defined(HAS_ARGBATTENUATEROW_NEON)
2458 if (TestCpuFlag(kCpuHasNEON)) {
2459 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2460 if (IS_ALIGNED(width, 8)) {
2461 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2462 }
2463 }
2464 #endif
2465 #if defined(HAS_ARGBATTENUATEROW_MSA)
2466 if (TestCpuFlag(kCpuHasMSA)) {
2467 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2468 if (IS_ALIGNED(width, 8)) {
2469 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2470 }
2471 }
2472 #endif
2473
2474 for (y = 0; y < height; ++y) {
2475 I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2476 width);
2477 if (attenuate) {
2478 ARGBAttenuateRow(dst_argb, dst_argb, width);
2479 }
2480 dst_argb += dst_stride_argb;
2481 src_a += src_stride_a;
2482 src_y += src_stride_y;
2483 src_u += src_stride_u;
2484 src_v += src_stride_v;
2485 }
2486 return 0;
2487 }
2488
2489 // Convert I410 with Alpha to preattenuated ARGB with matrix.
2490 LIBYUV_API
I410AlphaToARGBMatrix(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,const uint16_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)2491 int I410AlphaToARGBMatrix(const uint16_t* src_y,
2492 int src_stride_y,
2493 const uint16_t* src_u,
2494 int src_stride_u,
2495 const uint16_t* src_v,
2496 int src_stride_v,
2497 const uint16_t* src_a,
2498 int src_stride_a,
2499 uint8_t* dst_argb,
2500 int dst_stride_argb,
2501 const struct YuvConstants* yuvconstants,
2502 int width,
2503 int height,
2504 int attenuate) {
2505 int y;
2506 void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2507 const uint16_t* v_buf, const uint16_t* a_buf,
2508 uint8_t* dst_argb,
2509 const struct YuvConstants* yuvconstants,
2510 int width) = I410AlphaToARGBRow_C;
2511 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2512 int width) = ARGBAttenuateRow_C;
2513 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2514 height == 0) {
2515 return -1;
2516 }
2517 // Negative height means invert the image.
2518 if (height < 0) {
2519 height = -height;
2520 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2521 dst_stride_argb = -dst_stride_argb;
2522 }
2523 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
2524 if (TestCpuFlag(kCpuHasSSSE3)) {
2525 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
2526 if (IS_ALIGNED(width, 8)) {
2527 I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
2528 }
2529 }
2530 #endif
2531 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
2532 if (TestCpuFlag(kCpuHasAVX2)) {
2533 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
2534 if (IS_ALIGNED(width, 16)) {
2535 I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
2536 }
2537 }
2538 #endif
2539 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2540 if (TestCpuFlag(kCpuHasSSSE3)) {
2541 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2542 if (IS_ALIGNED(width, 4)) {
2543 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2544 }
2545 }
2546 #endif
2547 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2548 if (TestCpuFlag(kCpuHasAVX2)) {
2549 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2550 if (IS_ALIGNED(width, 8)) {
2551 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2552 }
2553 }
2554 #endif
2555 #if defined(HAS_ARGBATTENUATEROW_NEON)
2556 if (TestCpuFlag(kCpuHasNEON)) {
2557 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2558 if (IS_ALIGNED(width, 8)) {
2559 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2560 }
2561 }
2562 #endif
2563 #if defined(HAS_ARGBATTENUATEROW_MSA)
2564 if (TestCpuFlag(kCpuHasMSA)) {
2565 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2566 if (IS_ALIGNED(width, 8)) {
2567 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2568 }
2569 }
2570 #endif
2571
2572 for (y = 0; y < height; ++y) {
2573 I410AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2574 width);
2575 if (attenuate) {
2576 ARGBAttenuateRow(dst_argb, dst_argb, width);
2577 }
2578 dst_argb += dst_stride_argb;
2579 src_a += src_stride_a;
2580 src_y += src_stride_y;
2581 src_u += src_stride_u;
2582 src_v += src_stride_v;
2583 }
2584 return 0;
2585 }
2586
2587 // Convert I400 to ARGB with matrix.
2588 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)2589 int I400ToARGBMatrix(const uint8_t* src_y,
2590 int src_stride_y,
2591 uint8_t* dst_argb,
2592 int dst_stride_argb,
2593 const struct YuvConstants* yuvconstants,
2594 int width,
2595 int height) {
2596 int y;
2597 void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
2598 const struct YuvConstants* yuvconstants, int width) =
2599 I400ToARGBRow_C;
2600 if (!src_y || !dst_argb || width <= 0 || height == 0) {
2601 return -1;
2602 }
2603 // Negative height means invert the image.
2604 if (height < 0) {
2605 height = -height;
2606 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2607 dst_stride_argb = -dst_stride_argb;
2608 }
2609 // Coalesce rows.
2610 if (src_stride_y == width && dst_stride_argb == width * 4) {
2611 width *= height;
2612 height = 1;
2613 src_stride_y = dst_stride_argb = 0;
2614 }
2615 #if defined(HAS_I400TOARGBROW_SSE2)
2616 if (TestCpuFlag(kCpuHasSSE2)) {
2617 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
2618 if (IS_ALIGNED(width, 8)) {
2619 I400ToARGBRow = I400ToARGBRow_SSE2;
2620 }
2621 }
2622 #endif
2623 #if defined(HAS_I400TOARGBROW_AVX2)
2624 if (TestCpuFlag(kCpuHasAVX2)) {
2625 I400ToARGBRow = I400ToARGBRow_Any_AVX2;
2626 if (IS_ALIGNED(width, 16)) {
2627 I400ToARGBRow = I400ToARGBRow_AVX2;
2628 }
2629 }
2630 #endif
2631 #if defined(HAS_I400TOARGBROW_NEON)
2632 if (TestCpuFlag(kCpuHasNEON)) {
2633 I400ToARGBRow = I400ToARGBRow_Any_NEON;
2634 if (IS_ALIGNED(width, 8)) {
2635 I400ToARGBRow = I400ToARGBRow_NEON;
2636 }
2637 }
2638 #endif
2639 #if defined(HAS_I400TOARGBROW_MSA)
2640 if (TestCpuFlag(kCpuHasMSA)) {
2641 I400ToARGBRow = I400ToARGBRow_Any_MSA;
2642 if (IS_ALIGNED(width, 16)) {
2643 I400ToARGBRow = I400ToARGBRow_MSA;
2644 }
2645 }
2646 #endif
2647 #if defined(HAS_I400TOARGBROW_LSX)
2648 if (TestCpuFlag(kCpuHasLSX)) {
2649 I400ToARGBRow = I400ToARGBRow_Any_LSX;
2650 if (IS_ALIGNED(width, 16)) {
2651 I400ToARGBRow = I400ToARGBRow_LSX;
2652 }
2653 }
2654 #endif
2655
2656 for (y = 0; y < height; ++y) {
2657 I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
2658 dst_argb += dst_stride_argb;
2659 src_y += src_stride_y;
2660 }
2661 return 0;
2662 }
2663
2664 // Convert I400 to ARGB.
2665 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2666 int I400ToARGB(const uint8_t* src_y,
2667 int src_stride_y,
2668 uint8_t* dst_argb,
2669 int dst_stride_argb,
2670 int width,
2671 int height) {
2672 return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
2673 &kYuvI601Constants, width, height);
2674 }
2675
2676 // Convert J400 to ARGB.
2677 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2678 int J400ToARGB(const uint8_t* src_y,
2679 int src_stride_y,
2680 uint8_t* dst_argb,
2681 int dst_stride_argb,
2682 int width,
2683 int height) {
2684 int y;
2685 void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
2686 J400ToARGBRow_C;
2687 if (!src_y || !dst_argb || width <= 0 || height == 0) {
2688 return -1;
2689 }
2690 // Negative height means invert the image.
2691 if (height < 0) {
2692 height = -height;
2693 src_y = src_y + (height - 1) * src_stride_y;
2694 src_stride_y = -src_stride_y;
2695 }
2696 // Coalesce rows.
2697 if (src_stride_y == width && dst_stride_argb == width * 4) {
2698 width *= height;
2699 height = 1;
2700 src_stride_y = dst_stride_argb = 0;
2701 }
2702 #if defined(HAS_J400TOARGBROW_SSE2)
2703 if (TestCpuFlag(kCpuHasSSE2)) {
2704 J400ToARGBRow = J400ToARGBRow_Any_SSE2;
2705 if (IS_ALIGNED(width, 8)) {
2706 J400ToARGBRow = J400ToARGBRow_SSE2;
2707 }
2708 }
2709 #endif
2710 #if defined(HAS_J400TOARGBROW_AVX2)
2711 if (TestCpuFlag(kCpuHasAVX2)) {
2712 J400ToARGBRow = J400ToARGBRow_Any_AVX2;
2713 if (IS_ALIGNED(width, 16)) {
2714 J400ToARGBRow = J400ToARGBRow_AVX2;
2715 }
2716 }
2717 #endif
2718 #if defined(HAS_J400TOARGBROW_NEON)
2719 if (TestCpuFlag(kCpuHasNEON)) {
2720 J400ToARGBRow = J400ToARGBRow_Any_NEON;
2721 if (IS_ALIGNED(width, 8)) {
2722 J400ToARGBRow = J400ToARGBRow_NEON;
2723 }
2724 }
2725 #endif
2726 #if defined(HAS_J400TOARGBROW_MSA)
2727 if (TestCpuFlag(kCpuHasMSA)) {
2728 J400ToARGBRow = J400ToARGBRow_Any_MSA;
2729 if (IS_ALIGNED(width, 16)) {
2730 J400ToARGBRow = J400ToARGBRow_MSA;
2731 }
2732 }
2733 #endif
2734 #if defined(HAS_J400TOARGBROW_LSX)
2735 if (TestCpuFlag(kCpuHasLSX)) {
2736 J400ToARGBRow = J400ToARGBRow_Any_LSX;
2737 if (IS_ALIGNED(width, 16)) {
2738 J400ToARGBRow = J400ToARGBRow_LSX;
2739 }
2740 }
2741 #endif
2742 for (y = 0; y < height; ++y) {
2743 J400ToARGBRow(src_y, dst_argb, width);
2744 src_y += src_stride_y;
2745 dst_argb += dst_stride_argb;
2746 }
2747 return 0;
2748 }
2749
2750 // Shuffle table for converting BGRA to ARGB.
2751 static const uvec8 kShuffleMaskBGRAToARGB = {
2752 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
2753
2754 // Shuffle table for converting ABGR to ARGB.
2755 static const uvec8 kShuffleMaskABGRToARGB = {
2756 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
2757
2758 // Shuffle table for converting RGBA to ARGB.
2759 static const uvec8 kShuffleMaskRGBAToARGB = {
2760 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
2761
2762 // Shuffle table for converting AR64 to AB64.
2763 static const uvec8 kShuffleMaskAR64ToAB64 = {
2764 4u, 5u, 2u, 3u, 0u, 1u, 6u, 7u, 12u, 13u, 10u, 11u, 8u, 9u, 14u, 15u};
2765
2766 // Convert BGRA to ARGB.
2767 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2768 int BGRAToARGB(const uint8_t* src_bgra,
2769 int src_stride_bgra,
2770 uint8_t* dst_argb,
2771 int dst_stride_argb,
2772 int width,
2773 int height) {
2774 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
2775 (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
2776 }
2777
2778 // Convert ARGB to BGRA (same as BGRAToARGB).
2779 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2780 int ARGBToBGRA(const uint8_t* src_bgra,
2781 int src_stride_bgra,
2782 uint8_t* dst_argb,
2783 int dst_stride_argb,
2784 int width,
2785 int height) {
2786 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
2787 (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
2788 }
2789
2790 // Convert ABGR to ARGB.
2791 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2792 int ABGRToARGB(const uint8_t* src_abgr,
2793 int src_stride_abgr,
2794 uint8_t* dst_argb,
2795 int dst_stride_argb,
2796 int width,
2797 int height) {
2798 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
2799 (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
2800 }
2801
2802 // Convert ARGB to ABGR to (same as ABGRToARGB).
2803 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2804 int ARGBToABGR(const uint8_t* src_abgr,
2805 int src_stride_abgr,
2806 uint8_t* dst_argb,
2807 int dst_stride_argb,
2808 int width,
2809 int height) {
2810 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
2811 (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
2812 }
2813
2814 // Convert RGBA to ARGB.
2815 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2816 int RGBAToARGB(const uint8_t* src_rgba,
2817 int src_stride_rgba,
2818 uint8_t* dst_argb,
2819 int dst_stride_argb,
2820 int width,
2821 int height) {
2822 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
2823 (const uint8_t*)&kShuffleMaskRGBAToARGB, width, height);
2824 }
2825
2826 // Convert AR64 To AB64.
2827 LIBYUV_API
AR64ToAB64(const uint16_t * src_ar64,int src_stride_ar64,uint16_t * dst_ab64,int dst_stride_ab64,int width,int height)2828 int AR64ToAB64(const uint16_t* src_ar64,
2829 int src_stride_ar64,
2830 uint16_t* dst_ab64,
2831 int dst_stride_ab64,
2832 int width,
2833 int height) {
2834 return AR64Shuffle(src_ar64, src_stride_ar64, dst_ab64, dst_stride_ab64,
2835 (const uint8_t*)&kShuffleMaskAR64ToAB64, width, height);
2836 }
2837
2838 // Convert RGB24 to ARGB.
2839 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2840 int RGB24ToARGB(const uint8_t* src_rgb24,
2841 int src_stride_rgb24,
2842 uint8_t* dst_argb,
2843 int dst_stride_argb,
2844 int width,
2845 int height) {
2846 int y;
2847 void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
2848 RGB24ToARGBRow_C;
2849 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
2850 return -1;
2851 }
2852 // Negative height means invert the image.
2853 if (height < 0) {
2854 height = -height;
2855 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
2856 src_stride_rgb24 = -src_stride_rgb24;
2857 }
2858 // Coalesce rows.
2859 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
2860 width *= height;
2861 height = 1;
2862 src_stride_rgb24 = dst_stride_argb = 0;
2863 }
2864 #if defined(HAS_RGB24TOARGBROW_SSSE3)
2865 if (TestCpuFlag(kCpuHasSSSE3)) {
2866 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
2867 if (IS_ALIGNED(width, 16)) {
2868 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
2869 }
2870 }
2871 #endif
2872 #if defined(HAS_RGB24TOARGBROW_NEON)
2873 if (TestCpuFlag(kCpuHasNEON)) {
2874 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
2875 if (IS_ALIGNED(width, 8)) {
2876 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
2877 }
2878 }
2879 #endif
2880 #if defined(HAS_RGB24TOARGBROW_MSA)
2881 if (TestCpuFlag(kCpuHasMSA)) {
2882 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
2883 if (IS_ALIGNED(width, 16)) {
2884 RGB24ToARGBRow = RGB24ToARGBRow_MSA;
2885 }
2886 }
2887 #endif
2888 #if defined(HAS_RGB24TOARGBROW_LSX)
2889 if (TestCpuFlag(kCpuHasLSX)) {
2890 RGB24ToARGBRow = RGB24ToARGBRow_Any_LSX;
2891 if (IS_ALIGNED(width, 16)) {
2892 RGB24ToARGBRow = RGB24ToARGBRow_LSX;
2893 }
2894 }
2895 #endif
2896 #if defined(HAS_RGB24TOARGBROW_LASX)
2897 if (TestCpuFlag(kCpuHasLASX)) {
2898 RGB24ToARGBRow = RGB24ToARGBRow_Any_LASX;
2899 if (IS_ALIGNED(width, 32)) {
2900 RGB24ToARGBRow = RGB24ToARGBRow_LASX;
2901 }
2902 }
2903 #endif
2904
2905 for (y = 0; y < height; ++y) {
2906 RGB24ToARGBRow(src_rgb24, dst_argb, width);
2907 src_rgb24 += src_stride_rgb24;
2908 dst_argb += dst_stride_argb;
2909 }
2910 return 0;
2911 }
2912
2913 // Convert RAW to ARGB.
2914 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2915 int RAWToARGB(const uint8_t* src_raw,
2916 int src_stride_raw,
2917 uint8_t* dst_argb,
2918 int dst_stride_argb,
2919 int width,
2920 int height) {
2921 int y;
2922 void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
2923 RAWToARGBRow_C;
2924 if (!src_raw || !dst_argb || width <= 0 || height == 0) {
2925 return -1;
2926 }
2927 // Negative height means invert the image.
2928 if (height < 0) {
2929 height = -height;
2930 src_raw = src_raw + (height - 1) * src_stride_raw;
2931 src_stride_raw = -src_stride_raw;
2932 }
2933 // Coalesce rows.
2934 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
2935 width *= height;
2936 height = 1;
2937 src_stride_raw = dst_stride_argb = 0;
2938 }
2939 #if defined(HAS_RAWTOARGBROW_SSSE3)
2940 if (TestCpuFlag(kCpuHasSSSE3)) {
2941 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
2942 if (IS_ALIGNED(width, 16)) {
2943 RAWToARGBRow = RAWToARGBRow_SSSE3;
2944 }
2945 }
2946 #endif
2947 #if defined(HAS_RAWTOARGBROW_NEON)
2948 if (TestCpuFlag(kCpuHasNEON)) {
2949 RAWToARGBRow = RAWToARGBRow_Any_NEON;
2950 if (IS_ALIGNED(width, 8)) {
2951 RAWToARGBRow = RAWToARGBRow_NEON;
2952 }
2953 }
2954 #endif
2955 #if defined(HAS_RAWTOARGBROW_MSA)
2956 if (TestCpuFlag(kCpuHasMSA)) {
2957 RAWToARGBRow = RAWToARGBRow_Any_MSA;
2958 if (IS_ALIGNED(width, 16)) {
2959 RAWToARGBRow = RAWToARGBRow_MSA;
2960 }
2961 }
2962 #endif
2963 #if defined(HAS_RAWTOARGBROW_LSX)
2964 if (TestCpuFlag(kCpuHasLSX)) {
2965 RAWToARGBRow = RAWToARGBRow_Any_LSX;
2966 if (IS_ALIGNED(width, 16)) {
2967 RAWToARGBRow = RAWToARGBRow_LSX;
2968 }
2969 }
2970 #endif
2971 #if defined(HAS_RAWTOARGBROW_LASX)
2972 if (TestCpuFlag(kCpuHasLASX)) {
2973 RAWToARGBRow = RAWToARGBRow_Any_LASX;
2974 if (IS_ALIGNED(width, 32)) {
2975 RAWToARGBRow = RAWToARGBRow_LASX;
2976 }
2977 }
2978 #endif
2979
2980 for (y = 0; y < height; ++y) {
2981 RAWToARGBRow(src_raw, dst_argb, width);
2982 src_raw += src_stride_raw;
2983 dst_argb += dst_stride_argb;
2984 }
2985 return 0;
2986 }
2987
2988 // Convert RAW to RGBA.
2989 LIBYUV_API
RAWToRGBA(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)2990 int RAWToRGBA(const uint8_t* src_raw,
2991 int src_stride_raw,
2992 uint8_t* dst_rgba,
2993 int dst_stride_rgba,
2994 int width,
2995 int height) {
2996 int y;
2997 void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
2998 RAWToRGBARow_C;
2999 if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
3000 return -1;
3001 }
3002 // Negative height means invert the image.
3003 if (height < 0) {
3004 height = -height;
3005 src_raw = src_raw + (height - 1) * src_stride_raw;
3006 src_stride_raw = -src_stride_raw;
3007 }
3008 // Coalesce rows.
3009 if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
3010 width *= height;
3011 height = 1;
3012 src_stride_raw = dst_stride_rgba = 0;
3013 }
3014 #if defined(HAS_RAWTORGBAROW_SSSE3)
3015 if (TestCpuFlag(kCpuHasSSSE3)) {
3016 RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
3017 if (IS_ALIGNED(width, 16)) {
3018 RAWToRGBARow = RAWToRGBARow_SSSE3;
3019 }
3020 }
3021 #endif
3022 #if defined(HAS_RAWTORGBAROW_NEON)
3023 if (TestCpuFlag(kCpuHasNEON)) {
3024 RAWToRGBARow = RAWToRGBARow_Any_NEON;
3025 if (IS_ALIGNED(width, 8)) {
3026 RAWToRGBARow = RAWToRGBARow_NEON;
3027 }
3028 }
3029 #endif
3030
3031 for (y = 0; y < height; ++y) {
3032 RAWToRGBARow(src_raw, dst_rgba, width);
3033 src_raw += src_stride_raw;
3034 dst_rgba += dst_stride_rgba;
3035 }
3036 return 0;
3037 }
3038
3039 // Convert RGB565 to ARGB.
3040 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3041 int RGB565ToARGB(const uint8_t* src_rgb565,
3042 int src_stride_rgb565,
3043 uint8_t* dst_argb,
3044 int dst_stride_argb,
3045 int width,
3046 int height) {
3047 int y;
3048 void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
3049 int width) = RGB565ToARGBRow_C;
3050 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
3051 return -1;
3052 }
3053 // Negative height means invert the image.
3054 if (height < 0) {
3055 height = -height;
3056 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
3057 src_stride_rgb565 = -src_stride_rgb565;
3058 }
3059 // Coalesce rows.
3060 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
3061 width *= height;
3062 height = 1;
3063 src_stride_rgb565 = dst_stride_argb = 0;
3064 }
3065 #if defined(HAS_RGB565TOARGBROW_SSE2)
3066 if (TestCpuFlag(kCpuHasSSE2)) {
3067 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
3068 if (IS_ALIGNED(width, 8)) {
3069 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
3070 }
3071 }
3072 #endif
3073 #if defined(HAS_RGB565TOARGBROW_AVX2)
3074 if (TestCpuFlag(kCpuHasAVX2)) {
3075 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
3076 if (IS_ALIGNED(width, 16)) {
3077 RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
3078 }
3079 }
3080 #endif
3081 #if defined(HAS_RGB565TOARGBROW_NEON)
3082 if (TestCpuFlag(kCpuHasNEON)) {
3083 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
3084 if (IS_ALIGNED(width, 8)) {
3085 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
3086 }
3087 }
3088 #endif
3089 #if defined(HAS_RGB565TOARGBROW_MSA)
3090 if (TestCpuFlag(kCpuHasMSA)) {
3091 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
3092 if (IS_ALIGNED(width, 16)) {
3093 RGB565ToARGBRow = RGB565ToARGBRow_MSA;
3094 }
3095 }
3096 #endif
3097 #if defined(HAS_RGB565TOARGBROW_LSX)
3098 if (TestCpuFlag(kCpuHasLSX)) {
3099 RGB565ToARGBRow = RGB565ToARGBRow_Any_LSX;
3100 if (IS_ALIGNED(width, 16)) {
3101 RGB565ToARGBRow = RGB565ToARGBRow_LSX;
3102 }
3103 }
3104 #endif
3105 #if defined(HAS_RGB565TOARGBROW_LASX)
3106 if (TestCpuFlag(kCpuHasLASX)) {
3107 RGB565ToARGBRow = RGB565ToARGBRow_Any_LASX;
3108 if (IS_ALIGNED(width, 32)) {
3109 RGB565ToARGBRow = RGB565ToARGBRow_LASX;
3110 }
3111 }
3112 #endif
3113
3114 for (y = 0; y < height; ++y) {
3115 RGB565ToARGBRow(src_rgb565, dst_argb, width);
3116 src_rgb565 += src_stride_rgb565;
3117 dst_argb += dst_stride_argb;
3118 }
3119 return 0;
3120 }
3121
3122 // Convert ARGB1555 to ARGB.
3123 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3124 int ARGB1555ToARGB(const uint8_t* src_argb1555,
3125 int src_stride_argb1555,
3126 uint8_t* dst_argb,
3127 int dst_stride_argb,
3128 int width,
3129 int height) {
3130 int y;
3131 void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
3132 int width) = ARGB1555ToARGBRow_C;
3133 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
3134 return -1;
3135 }
3136 // Negative height means invert the image.
3137 if (height < 0) {
3138 height = -height;
3139 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
3140 src_stride_argb1555 = -src_stride_argb1555;
3141 }
3142 // Coalesce rows.
3143 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
3144 width *= height;
3145 height = 1;
3146 src_stride_argb1555 = dst_stride_argb = 0;
3147 }
3148 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
3149 if (TestCpuFlag(kCpuHasSSE2)) {
3150 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
3151 if (IS_ALIGNED(width, 8)) {
3152 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
3153 }
3154 }
3155 #endif
3156 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
3157 if (TestCpuFlag(kCpuHasAVX2)) {
3158 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
3159 if (IS_ALIGNED(width, 16)) {
3160 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
3161 }
3162 }
3163 #endif
3164 #if defined(HAS_ARGB1555TOARGBROW_NEON)
3165 if (TestCpuFlag(kCpuHasNEON)) {
3166 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
3167 if (IS_ALIGNED(width, 8)) {
3168 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
3169 }
3170 }
3171 #endif
3172 #if defined(HAS_ARGB1555TOARGBROW_MSA)
3173 if (TestCpuFlag(kCpuHasMSA)) {
3174 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
3175 if (IS_ALIGNED(width, 16)) {
3176 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
3177 }
3178 }
3179 #endif
3180 #if defined(HAS_ARGB1555TOARGBROW_LSX)
3181 if (TestCpuFlag(kCpuHasLSX)) {
3182 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LSX;
3183 if (IS_ALIGNED(width, 16)) {
3184 ARGB1555ToARGBRow = ARGB1555ToARGBRow_LSX;
3185 }
3186 }
3187 #endif
3188 #if defined(HAS_ARGB1555TOARGBROW_LASX)
3189 if (TestCpuFlag(kCpuHasLASX)) {
3190 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LASX;
3191 if (IS_ALIGNED(width, 32)) {
3192 ARGB1555ToARGBRow = ARGB1555ToARGBRow_LASX;
3193 }
3194 }
3195 #endif
3196
3197 for (y = 0; y < height; ++y) {
3198 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
3199 src_argb1555 += src_stride_argb1555;
3200 dst_argb += dst_stride_argb;
3201 }
3202 return 0;
3203 }
3204
3205 // Convert ARGB4444 to ARGB.
3206 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3207 int ARGB4444ToARGB(const uint8_t* src_argb4444,
3208 int src_stride_argb4444,
3209 uint8_t* dst_argb,
3210 int dst_stride_argb,
3211 int width,
3212 int height) {
3213 int y;
3214 void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
3215 int width) = ARGB4444ToARGBRow_C;
3216 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
3217 return -1;
3218 }
3219 // Negative height means invert the image.
3220 if (height < 0) {
3221 height = -height;
3222 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
3223 src_stride_argb4444 = -src_stride_argb4444;
3224 }
3225 // Coalesce rows.
3226 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
3227 width *= height;
3228 height = 1;
3229 src_stride_argb4444 = dst_stride_argb = 0;
3230 }
3231 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
3232 if (TestCpuFlag(kCpuHasSSE2)) {
3233 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
3234 if (IS_ALIGNED(width, 8)) {
3235 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
3236 }
3237 }
3238 #endif
3239 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
3240 if (TestCpuFlag(kCpuHasAVX2)) {
3241 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
3242 if (IS_ALIGNED(width, 16)) {
3243 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
3244 }
3245 }
3246 #endif
3247 #if defined(HAS_ARGB4444TOARGBROW_NEON)
3248 if (TestCpuFlag(kCpuHasNEON)) {
3249 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
3250 if (IS_ALIGNED(width, 8)) {
3251 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
3252 }
3253 }
3254 #endif
3255 #if defined(HAS_ARGB4444TOARGBROW_MSA)
3256 if (TestCpuFlag(kCpuHasMSA)) {
3257 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
3258 if (IS_ALIGNED(width, 16)) {
3259 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
3260 }
3261 }
3262 #endif
3263 #if defined(HAS_ARGB4444TOARGBROW_LSX)
3264 if (TestCpuFlag(kCpuHasLSX)) {
3265 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LSX;
3266 if (IS_ALIGNED(width, 16)) {
3267 ARGB4444ToARGBRow = ARGB4444ToARGBRow_LSX;
3268 }
3269 }
3270 #endif
3271 #if defined(HAS_ARGB4444TOARGBROW_LASX)
3272 if (TestCpuFlag(kCpuHasLASX)) {
3273 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LASX;
3274 if (IS_ALIGNED(width, 32)) {
3275 ARGB4444ToARGBRow = ARGB4444ToARGBRow_LASX;
3276 }
3277 }
3278 #endif
3279
3280 for (y = 0; y < height; ++y) {
3281 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
3282 src_argb4444 += src_stride_argb4444;
3283 dst_argb += dst_stride_argb;
3284 }
3285 return 0;
3286 }
3287
3288 // Convert AR30 to ARGB.
3289 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3290 int AR30ToARGB(const uint8_t* src_ar30,
3291 int src_stride_ar30,
3292 uint8_t* dst_argb,
3293 int dst_stride_argb,
3294 int width,
3295 int height) {
3296 int y;
3297 if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
3298 return -1;
3299 }
3300 // Negative height means invert the image.
3301 if (height < 0) {
3302 height = -height;
3303 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3304 src_stride_ar30 = -src_stride_ar30;
3305 }
3306 // Coalesce rows.
3307 if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
3308 width *= height;
3309 height = 1;
3310 src_stride_ar30 = dst_stride_argb = 0;
3311 }
3312 for (y = 0; y < height; ++y) {
3313 AR30ToARGBRow_C(src_ar30, dst_argb, width);
3314 src_ar30 += src_stride_ar30;
3315 dst_argb += dst_stride_argb;
3316 }
3317 return 0;
3318 }
3319
3320 // Convert AR30 to ABGR.
3321 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)3322 int AR30ToABGR(const uint8_t* src_ar30,
3323 int src_stride_ar30,
3324 uint8_t* dst_abgr,
3325 int dst_stride_abgr,
3326 int width,
3327 int height) {
3328 int y;
3329 if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
3330 return -1;
3331 }
3332 // Negative height means invert the image.
3333 if (height < 0) {
3334 height = -height;
3335 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3336 src_stride_ar30 = -src_stride_ar30;
3337 }
3338 // Coalesce rows.
3339 if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
3340 width *= height;
3341 height = 1;
3342 src_stride_ar30 = dst_stride_abgr = 0;
3343 }
3344 for (y = 0; y < height; ++y) {
3345 AR30ToABGRRow_C(src_ar30, dst_abgr, width);
3346 src_ar30 += src_stride_ar30;
3347 dst_abgr += dst_stride_abgr;
3348 }
3349 return 0;
3350 }
3351
3352 // Convert AR30 to AB30.
3353 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)3354 int AR30ToAB30(const uint8_t* src_ar30,
3355 int src_stride_ar30,
3356 uint8_t* dst_ab30,
3357 int dst_stride_ab30,
3358 int width,
3359 int height) {
3360 int y;
3361 if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
3362 return -1;
3363 }
3364 // Negative height means invert the image.
3365 if (height < 0) {
3366 height = -height;
3367 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3368 src_stride_ar30 = -src_stride_ar30;
3369 }
3370 // Coalesce rows.
3371 if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
3372 width *= height;
3373 height = 1;
3374 src_stride_ar30 = dst_stride_ab30 = 0;
3375 }
3376 for (y = 0; y < height; ++y) {
3377 AR30ToAB30Row_C(src_ar30, dst_ab30, width);
3378 src_ar30 += src_stride_ar30;
3379 dst_ab30 += dst_stride_ab30;
3380 }
3381 return 0;
3382 }
3383
3384 // Convert AR64 to ARGB.
3385 LIBYUV_API
AR64ToARGB(const uint16_t * src_ar64,int src_stride_ar64,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3386 int AR64ToARGB(const uint16_t* src_ar64,
3387 int src_stride_ar64,
3388 uint8_t* dst_argb,
3389 int dst_stride_argb,
3390 int width,
3391 int height) {
3392 int y;
3393 void (*AR64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
3394 int width) = AR64ToARGBRow_C;
3395 if (!src_ar64 || !dst_argb || width <= 0 || height == 0) {
3396 return -1;
3397 }
3398 // Negative height means invert the image.
3399 if (height < 0) {
3400 height = -height;
3401 src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
3402 src_stride_ar64 = -src_stride_ar64;
3403 }
3404 // Coalesce rows.
3405 if (src_stride_ar64 == width * 4 && dst_stride_argb == width * 4) {
3406 width *= height;
3407 height = 1;
3408 src_stride_ar64 = dst_stride_argb = 0;
3409 }
3410 #if defined(HAS_AR64TOARGBROW_SSSE3)
3411 if (TestCpuFlag(kCpuHasSSSE3)) {
3412 AR64ToARGBRow = AR64ToARGBRow_Any_SSSE3;
3413 if (IS_ALIGNED(width, 4)) {
3414 AR64ToARGBRow = AR64ToARGBRow_SSSE3;
3415 }
3416 }
3417 #endif
3418 #if defined(HAS_AR64TOARGBROW_AVX2)
3419 if (TestCpuFlag(kCpuHasAVX2)) {
3420 AR64ToARGBRow = AR64ToARGBRow_Any_AVX2;
3421 if (IS_ALIGNED(width, 8)) {
3422 AR64ToARGBRow = AR64ToARGBRow_AVX2;
3423 }
3424 }
3425 #endif
3426 #if defined(HAS_AR64TOARGBROW_NEON)
3427 if (TestCpuFlag(kCpuHasNEON)) {
3428 AR64ToARGBRow = AR64ToARGBRow_Any_NEON;
3429 if (IS_ALIGNED(width, 8)) {
3430 AR64ToARGBRow = AR64ToARGBRow_NEON;
3431 }
3432 }
3433 #endif
3434
3435 for (y = 0; y < height; ++y) {
3436 AR64ToARGBRow(src_ar64, dst_argb, width);
3437 src_ar64 += src_stride_ar64;
3438 dst_argb += dst_stride_argb;
3439 }
3440 return 0;
3441 }
3442
3443 // Convert AB64 to ARGB.
3444 LIBYUV_API
AB64ToARGB(const uint16_t * src_ab64,int src_stride_ab64,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3445 int AB64ToARGB(const uint16_t* src_ab64,
3446 int src_stride_ab64,
3447 uint8_t* dst_argb,
3448 int dst_stride_argb,
3449 int width,
3450 int height) {
3451 int y;
3452 void (*AB64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
3453 int width) = AB64ToARGBRow_C;
3454 if (!src_ab64 || !dst_argb || width <= 0 || height == 0) {
3455 return -1;
3456 }
3457 // Negative height means invert the image.
3458 if (height < 0) {
3459 height = -height;
3460 src_ab64 = src_ab64 + (height - 1) * src_stride_ab64;
3461 src_stride_ab64 = -src_stride_ab64;
3462 }
3463 // Coalesce rows.
3464 if (src_stride_ab64 == width * 4 && dst_stride_argb == width * 4) {
3465 width *= height;
3466 height = 1;
3467 src_stride_ab64 = dst_stride_argb = 0;
3468 }
3469 #if defined(HAS_AB64TOARGBROW_SSSE3)
3470 if (TestCpuFlag(kCpuHasSSSE3)) {
3471 AB64ToARGBRow = AB64ToARGBRow_Any_SSSE3;
3472 if (IS_ALIGNED(width, 4)) {
3473 AB64ToARGBRow = AB64ToARGBRow_SSSE3;
3474 }
3475 }
3476 #endif
3477 #if defined(HAS_AB64TOARGBROW_AVX2)
3478 if (TestCpuFlag(kCpuHasAVX2)) {
3479 AB64ToARGBRow = AB64ToARGBRow_Any_AVX2;
3480 if (IS_ALIGNED(width, 8)) {
3481 AB64ToARGBRow = AB64ToARGBRow_AVX2;
3482 }
3483 }
3484 #endif
3485 #if defined(HAS_AB64TOARGBROW_NEON)
3486 if (TestCpuFlag(kCpuHasNEON)) {
3487 AB64ToARGBRow = AB64ToARGBRow_Any_NEON;
3488 if (IS_ALIGNED(width, 8)) {
3489 AB64ToARGBRow = AB64ToARGBRow_NEON;
3490 }
3491 }
3492 #endif
3493
3494 for (y = 0; y < height; ++y) {
3495 AB64ToARGBRow(src_ab64, dst_argb, width);
3496 src_ab64 += src_stride_ab64;
3497 dst_argb += dst_stride_argb;
3498 }
3499 return 0;
3500 }
3501
3502 // Convert NV12 to ARGB with matrix.
3503 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)3504 int NV12ToARGBMatrix(const uint8_t* src_y,
3505 int src_stride_y,
3506 const uint8_t* src_uv,
3507 int src_stride_uv,
3508 uint8_t* dst_argb,
3509 int dst_stride_argb,
3510 const struct YuvConstants* yuvconstants,
3511 int width,
3512 int height) {
3513 int y;
3514 void (*NV12ToARGBRow)(
3515 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3516 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
3517 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
3518 return -1;
3519 }
3520 // Negative height means invert the image.
3521 if (height < 0) {
3522 height = -height;
3523 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3524 dst_stride_argb = -dst_stride_argb;
3525 }
3526 #if defined(HAS_NV12TOARGBROW_SSSE3)
3527 if (TestCpuFlag(kCpuHasSSSE3)) {
3528 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
3529 if (IS_ALIGNED(width, 8)) {
3530 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
3531 }
3532 }
3533 #endif
3534 #if defined(HAS_NV12TOARGBROW_AVX2)
3535 if (TestCpuFlag(kCpuHasAVX2)) {
3536 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
3537 if (IS_ALIGNED(width, 16)) {
3538 NV12ToARGBRow = NV12ToARGBRow_AVX2;
3539 }
3540 }
3541 #endif
3542 #if defined(HAS_NV12TOARGBROW_NEON)
3543 if (TestCpuFlag(kCpuHasNEON)) {
3544 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
3545 if (IS_ALIGNED(width, 8)) {
3546 NV12ToARGBRow = NV12ToARGBRow_NEON;
3547 }
3548 }
3549 #endif
3550 #if defined(HAS_NV12TOARGBROW_MSA)
3551 if (TestCpuFlag(kCpuHasMSA)) {
3552 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
3553 if (IS_ALIGNED(width, 8)) {
3554 NV12ToARGBRow = NV12ToARGBRow_MSA;
3555 }
3556 }
3557 #endif
3558 #if defined(HAS_NV12TOARGBROW_LSX)
3559 if (TestCpuFlag(kCpuHasLSX)) {
3560 NV12ToARGBRow = NV12ToARGBRow_Any_LSX;
3561 if (IS_ALIGNED(width, 8)) {
3562 NV12ToARGBRow = NV12ToARGBRow_LSX;
3563 }
3564 }
3565 #endif
3566 #if defined(HAS_NV12TOARGBROW_LASX)
3567 if (TestCpuFlag(kCpuHasLASX)) {
3568 NV12ToARGBRow = NV12ToARGBRow_Any_LASX;
3569 if (IS_ALIGNED(width, 16)) {
3570 NV12ToARGBRow = NV12ToARGBRow_LASX;
3571 }
3572 }
3573 #endif
3574
3575 for (y = 0; y < height; ++y) {
3576 NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
3577 dst_argb += dst_stride_argb;
3578 src_y += src_stride_y;
3579 if (y & 1) {
3580 src_uv += src_stride_uv;
3581 }
3582 }
3583 return 0;
3584 }
3585
3586 // Convert NV21 to ARGB with matrix.
3587 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)3588 int NV21ToARGBMatrix(const uint8_t* src_y,
3589 int src_stride_y,
3590 const uint8_t* src_vu,
3591 int src_stride_vu,
3592 uint8_t* dst_argb,
3593 int dst_stride_argb,
3594 const struct YuvConstants* yuvconstants,
3595 int width,
3596 int height) {
3597 int y;
3598 void (*NV21ToARGBRow)(
3599 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3600 const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
3601 if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
3602 return -1;
3603 }
3604 // Negative height means invert the image.
3605 if (height < 0) {
3606 height = -height;
3607 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3608 dst_stride_argb = -dst_stride_argb;
3609 }
3610 #if defined(HAS_NV21TOARGBROW_SSSE3)
3611 if (TestCpuFlag(kCpuHasSSSE3)) {
3612 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
3613 if (IS_ALIGNED(width, 8)) {
3614 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
3615 }
3616 }
3617 #endif
3618 #if defined(HAS_NV21TOARGBROW_AVX2)
3619 if (TestCpuFlag(kCpuHasAVX2)) {
3620 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
3621 if (IS_ALIGNED(width, 16)) {
3622 NV21ToARGBRow = NV21ToARGBRow_AVX2;
3623 }
3624 }
3625 #endif
3626 #if defined(HAS_NV21TOARGBROW_NEON)
3627 if (TestCpuFlag(kCpuHasNEON)) {
3628 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
3629 if (IS_ALIGNED(width, 8)) {
3630 NV21ToARGBRow = NV21ToARGBRow_NEON;
3631 }
3632 }
3633 #endif
3634 #if defined(HAS_NV21TOARGBROW_MSA)
3635 if (TestCpuFlag(kCpuHasMSA)) {
3636 NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
3637 if (IS_ALIGNED(width, 8)) {
3638 NV21ToARGBRow = NV21ToARGBRow_MSA;
3639 }
3640 }
3641 #endif
3642 #if defined(HAS_NV21TOARGBROW_LSX)
3643 if (TestCpuFlag(kCpuHasLSX)) {
3644 NV21ToARGBRow = NV21ToARGBRow_Any_LSX;
3645 if (IS_ALIGNED(width, 8)) {
3646 NV21ToARGBRow = NV21ToARGBRow_LSX;
3647 }
3648 }
3649 #endif
3650 #if defined(HAS_NV21TOARGBROW_LASX)
3651 if (TestCpuFlag(kCpuHasLASX)) {
3652 NV21ToARGBRow = NV21ToARGBRow_Any_LASX;
3653 if (IS_ALIGNED(width, 16)) {
3654 NV21ToARGBRow = NV21ToARGBRow_LASX;
3655 }
3656 }
3657 #endif
3658
3659 for (y = 0; y < height; ++y) {
3660 NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
3661 dst_argb += dst_stride_argb;
3662 src_y += src_stride_y;
3663 if (y & 1) {
3664 src_vu += src_stride_vu;
3665 }
3666 }
3667 return 0;
3668 }
3669
3670 // Convert NV12 to ARGB.
3671 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)3672 int NV12ToARGB(const uint8_t* src_y,
3673 int src_stride_y,
3674 const uint8_t* src_uv,
3675 int src_stride_uv,
3676 uint8_t* dst_argb,
3677 int dst_stride_argb,
3678 int width,
3679 int height) {
3680 return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
3681 dst_stride_argb, &kYuvI601Constants, width, height);
3682 }
3683
3684 // Convert NV21 to ARGB.
3685 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)3686 int NV21ToARGB(const uint8_t* src_y,
3687 int src_stride_y,
3688 const uint8_t* src_vu,
3689 int src_stride_vu,
3690 uint8_t* dst_argb,
3691 int dst_stride_argb,
3692 int width,
3693 int height) {
3694 return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
3695 dst_stride_argb, &kYuvI601Constants, width, height);
3696 }
3697
3698 // Convert NV12 to ABGR.
3699 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
3700 // To swap the UV use NV12 instead of NV21.LIBYUV_API
3701 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)3702 int NV12ToABGR(const uint8_t* src_y,
3703 int src_stride_y,
3704 const uint8_t* src_uv,
3705 int src_stride_uv,
3706 uint8_t* dst_abgr,
3707 int dst_stride_abgr,
3708 int width,
3709 int height) {
3710 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
3711 dst_stride_abgr, &kYvuI601Constants, width, height);
3712 }
3713
3714 // Convert NV21 to ABGR.
3715 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)3716 int NV21ToABGR(const uint8_t* src_y,
3717 int src_stride_y,
3718 const uint8_t* src_vu,
3719 int src_stride_vu,
3720 uint8_t* dst_abgr,
3721 int dst_stride_abgr,
3722 int width,
3723 int height) {
3724 return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
3725 dst_stride_abgr, &kYvuI601Constants, width, height);
3726 }
3727
3728 // TODO(fbarchard): Consider SSSE3 2 step conversion.
3729 // Convert NV12 to RGB24 with matrix.
3730 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)3731 int NV12ToRGB24Matrix(const uint8_t* src_y,
3732 int src_stride_y,
3733 const uint8_t* src_uv,
3734 int src_stride_uv,
3735 uint8_t* dst_rgb24,
3736 int dst_stride_rgb24,
3737 const struct YuvConstants* yuvconstants,
3738 int width,
3739 int height) {
3740 int y;
3741 void (*NV12ToRGB24Row)(
3742 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3743 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
3744 if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
3745 return -1;
3746 }
3747 // Negative height means invert the image.
3748 if (height < 0) {
3749 height = -height;
3750 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
3751 dst_stride_rgb24 = -dst_stride_rgb24;
3752 }
3753 #if defined(HAS_NV12TORGB24ROW_NEON)
3754 if (TestCpuFlag(kCpuHasNEON)) {
3755 NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
3756 if (IS_ALIGNED(width, 8)) {
3757 NV12ToRGB24Row = NV12ToRGB24Row_NEON;
3758 }
3759 }
3760 #endif
3761 #if defined(HAS_NV12TORGB24ROW_SSSE3)
3762 if (TestCpuFlag(kCpuHasSSSE3)) {
3763 NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
3764 if (IS_ALIGNED(width, 16)) {
3765 NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
3766 }
3767 }
3768 #endif
3769 #if defined(HAS_NV12TORGB24ROW_AVX2)
3770 if (TestCpuFlag(kCpuHasAVX2)) {
3771 NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
3772 if (IS_ALIGNED(width, 32)) {
3773 NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
3774 }
3775 }
3776 #endif
3777
3778 for (y = 0; y < height; ++y) {
3779 NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
3780 dst_rgb24 += dst_stride_rgb24;
3781 src_y += src_stride_y;
3782 if (y & 1) {
3783 src_uv += src_stride_uv;
3784 }
3785 }
3786 return 0;
3787 }
3788
3789 // Convert NV21 to RGB24 with matrix.
3790 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)3791 int NV21ToRGB24Matrix(const uint8_t* src_y,
3792 int src_stride_y,
3793 const uint8_t* src_vu,
3794 int src_stride_vu,
3795 uint8_t* dst_rgb24,
3796 int dst_stride_rgb24,
3797 const struct YuvConstants* yuvconstants,
3798 int width,
3799 int height) {
3800 int y;
3801 void (*NV21ToRGB24Row)(
3802 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3803 const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
3804 if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
3805 return -1;
3806 }
3807 // Negative height means invert the image.
3808 if (height < 0) {
3809 height = -height;
3810 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
3811 dst_stride_rgb24 = -dst_stride_rgb24;
3812 }
3813 #if defined(HAS_NV21TORGB24ROW_NEON)
3814 if (TestCpuFlag(kCpuHasNEON)) {
3815 NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
3816 if (IS_ALIGNED(width, 8)) {
3817 NV21ToRGB24Row = NV21ToRGB24Row_NEON;
3818 }
3819 }
3820 #endif
3821 #if defined(HAS_NV21TORGB24ROW_SSSE3)
3822 if (TestCpuFlag(kCpuHasSSSE3)) {
3823 NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
3824 if (IS_ALIGNED(width, 16)) {
3825 NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
3826 }
3827 }
3828 #endif
3829 #if defined(HAS_NV21TORGB24ROW_AVX2)
3830 if (TestCpuFlag(kCpuHasAVX2)) {
3831 NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
3832 if (IS_ALIGNED(width, 32)) {
3833 NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
3834 }
3835 }
3836 #endif
3837
3838 for (y = 0; y < height; ++y) {
3839 NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
3840 dst_rgb24 += dst_stride_rgb24;
3841 src_y += src_stride_y;
3842 if (y & 1) {
3843 src_vu += src_stride_vu;
3844 }
3845 }
3846 return 0;
3847 }
3848
3849 // Convert NV12 to RGB24.
3850 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)3851 int NV12ToRGB24(const uint8_t* src_y,
3852 int src_stride_y,
3853 const uint8_t* src_uv,
3854 int src_stride_uv,
3855 uint8_t* dst_rgb24,
3856 int dst_stride_rgb24,
3857 int width,
3858 int height) {
3859 return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
3860 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
3861 width, height);
3862 }
3863
3864 // Convert NV21 to RGB24.
3865 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)3866 int NV21ToRGB24(const uint8_t* src_y,
3867 int src_stride_y,
3868 const uint8_t* src_vu,
3869 int src_stride_vu,
3870 uint8_t* dst_rgb24,
3871 int dst_stride_rgb24,
3872 int width,
3873 int height) {
3874 return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
3875 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
3876 width, height);
3877 }
3878
3879 // Convert NV12 to RAW.
3880 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)3881 int NV12ToRAW(const uint8_t* src_y,
3882 int src_stride_y,
3883 const uint8_t* src_uv,
3884 int src_stride_uv,
3885 uint8_t* dst_raw,
3886 int dst_stride_raw,
3887 int width,
3888 int height) {
3889 return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
3890 dst_stride_raw, &kYvuI601Constants, width, height);
3891 }
3892
3893 // Convert NV21 to RAW.
3894 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)3895 int NV21ToRAW(const uint8_t* src_y,
3896 int src_stride_y,
3897 const uint8_t* src_vu,
3898 int src_stride_vu,
3899 uint8_t* dst_raw,
3900 int dst_stride_raw,
3901 int width,
3902 int height) {
3903 return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
3904 dst_stride_raw, &kYvuI601Constants, width, height);
3905 }
3906
3907 // 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)3908 int NV21ToYUV24(const uint8_t* src_y,
3909 int src_stride_y,
3910 const uint8_t* src_vu,
3911 int src_stride_vu,
3912 uint8_t* dst_yuv24,
3913 int dst_stride_yuv24,
3914 int width,
3915 int height) {
3916 int y;
3917 void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
3918 uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
3919 if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
3920 return -1;
3921 }
3922 // Negative height means invert the image.
3923 if (height < 0) {
3924 height = -height;
3925 dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
3926 dst_stride_yuv24 = -dst_stride_yuv24;
3927 }
3928 #if defined(HAS_NV21TOYUV24ROW_NEON)
3929 if (TestCpuFlag(kCpuHasNEON)) {
3930 NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
3931 if (IS_ALIGNED(width, 16)) {
3932 NV21ToYUV24Row = NV21ToYUV24Row_NEON;
3933 }
3934 }
3935 #endif
3936 #if defined(HAS_NV21TOYUV24ROW_SSSE3)
3937 if (TestCpuFlag(kCpuHasSSSE3)) {
3938 NV21ToYUV24Row = NV21ToYUV24Row_Any_SSSE3;
3939 if (IS_ALIGNED(width, 16)) {
3940 NV21ToYUV24Row = NV21ToYUV24Row_SSSE3;
3941 }
3942 }
3943 #endif
3944 #if defined(HAS_NV21TOYUV24ROW_AVX2)
3945 if (TestCpuFlag(kCpuHasAVX2)) {
3946 NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
3947 if (IS_ALIGNED(width, 32)) {
3948 NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
3949 }
3950 }
3951 #endif
3952 for (y = 0; y < height; ++y) {
3953 NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
3954 dst_yuv24 += dst_stride_yuv24;
3955 src_y += src_stride_y;
3956 if (y & 1) {
3957 src_vu += src_stride_vu;
3958 }
3959 }
3960 return 0;
3961 }
3962
3963 // Convert YUY2 to ARGB.
3964 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3965 int YUY2ToARGB(const uint8_t* src_yuy2,
3966 int src_stride_yuy2,
3967 uint8_t* dst_argb,
3968 int dst_stride_argb,
3969 int width,
3970 int height) {
3971 int y;
3972 void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
3973 const struct YuvConstants* yuvconstants, int width) =
3974 YUY2ToARGBRow_C;
3975 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
3976 return -1;
3977 }
3978 // Negative height means invert the image.
3979 if (height < 0) {
3980 height = -height;
3981 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
3982 src_stride_yuy2 = -src_stride_yuy2;
3983 }
3984 // Coalesce rows.
3985 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
3986 width *= height;
3987 height = 1;
3988 src_stride_yuy2 = dst_stride_argb = 0;
3989 }
3990 #if defined(HAS_YUY2TOARGBROW_SSSE3)
3991 if (TestCpuFlag(kCpuHasSSSE3)) {
3992 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
3993 if (IS_ALIGNED(width, 16)) {
3994 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
3995 }
3996 }
3997 #endif
3998 #if defined(HAS_YUY2TOARGBROW_AVX2)
3999 if (TestCpuFlag(kCpuHasAVX2)) {
4000 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
4001 if (IS_ALIGNED(width, 32)) {
4002 YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
4003 }
4004 }
4005 #endif
4006 #if defined(HAS_YUY2TOARGBROW_NEON)
4007 if (TestCpuFlag(kCpuHasNEON)) {
4008 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
4009 if (IS_ALIGNED(width, 8)) {
4010 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
4011 }
4012 }
4013 #endif
4014 #if defined(HAS_YUY2TOARGBROW_MSA)
4015 if (TestCpuFlag(kCpuHasMSA)) {
4016 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
4017 if (IS_ALIGNED(width, 8)) {
4018 YUY2ToARGBRow = YUY2ToARGBRow_MSA;
4019 }
4020 }
4021 #endif
4022 #if defined(HAS_YUY2TOARGBROW_LSX)
4023 if (TestCpuFlag(kCpuHasLSX)) {
4024 YUY2ToARGBRow = YUY2ToARGBRow_Any_LSX;
4025 if (IS_ALIGNED(width, 8)) {
4026 YUY2ToARGBRow = YUY2ToARGBRow_LSX;
4027 }
4028 }
4029 #endif
4030 for (y = 0; y < height; ++y) {
4031 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
4032 src_yuy2 += src_stride_yuy2;
4033 dst_argb += dst_stride_argb;
4034 }
4035 return 0;
4036 }
4037
4038 // Convert UYVY to ARGB.
4039 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4040 int UYVYToARGB(const uint8_t* src_uyvy,
4041 int src_stride_uyvy,
4042 uint8_t* dst_argb,
4043 int dst_stride_argb,
4044 int width,
4045 int height) {
4046 int y;
4047 void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
4048 const struct YuvConstants* yuvconstants, int width) =
4049 UYVYToARGBRow_C;
4050 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
4051 return -1;
4052 }
4053 // Negative height means invert the image.
4054 if (height < 0) {
4055 height = -height;
4056 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
4057 src_stride_uyvy = -src_stride_uyvy;
4058 }
4059 // Coalesce rows.
4060 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
4061 width *= height;
4062 height = 1;
4063 src_stride_uyvy = dst_stride_argb = 0;
4064 }
4065 #if defined(HAS_UYVYTOARGBROW_SSSE3)
4066 if (TestCpuFlag(kCpuHasSSSE3)) {
4067 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
4068 if (IS_ALIGNED(width, 16)) {
4069 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
4070 }
4071 }
4072 #endif
4073 #if defined(HAS_UYVYTOARGBROW_AVX2)
4074 if (TestCpuFlag(kCpuHasAVX2)) {
4075 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
4076 if (IS_ALIGNED(width, 32)) {
4077 UYVYToARGBRow = UYVYToARGBRow_AVX2;
4078 }
4079 }
4080 #endif
4081 #if defined(HAS_UYVYTOARGBROW_NEON)
4082 if (TestCpuFlag(kCpuHasNEON)) {
4083 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
4084 if (IS_ALIGNED(width, 8)) {
4085 UYVYToARGBRow = UYVYToARGBRow_NEON;
4086 }
4087 }
4088 #endif
4089 #if defined(HAS_UYVYTOARGBROW_MSA)
4090 if (TestCpuFlag(kCpuHasMSA)) {
4091 UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
4092 if (IS_ALIGNED(width, 8)) {
4093 UYVYToARGBRow = UYVYToARGBRow_MSA;
4094 }
4095 }
4096 #endif
4097 #if defined(HAS_UYVYTOARGBROW_LSX)
4098 if (TestCpuFlag(kCpuHasLSX)) {
4099 UYVYToARGBRow = UYVYToARGBRow_Any_LSX;
4100 if (IS_ALIGNED(width, 8)) {
4101 UYVYToARGBRow = UYVYToARGBRow_LSX;
4102 }
4103 }
4104 #endif
4105 for (y = 0; y < height; ++y) {
4106 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
4107 src_uyvy += src_stride_uyvy;
4108 dst_argb += dst_stride_argb;
4109 }
4110 return 0;
4111 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)4112 static void WeavePixels(const uint8_t* src_u,
4113 const uint8_t* src_v,
4114 int src_pixel_stride_uv,
4115 uint8_t* dst_uv,
4116 int width) {
4117 int i;
4118 for (i = 0; i < width; ++i) {
4119 dst_uv[0] = *src_u;
4120 dst_uv[1] = *src_v;
4121 dst_uv += 2;
4122 src_u += src_pixel_stride_uv;
4123 src_v += src_pixel_stride_uv;
4124 }
4125 }
4126
4127 // Convert Android420 to ARGB with matrix.
4128 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)4129 int Android420ToARGBMatrix(const uint8_t* src_y,
4130 int src_stride_y,
4131 const uint8_t* src_u,
4132 int src_stride_u,
4133 const uint8_t* src_v,
4134 int src_stride_v,
4135 int src_pixel_stride_uv,
4136 uint8_t* dst_argb,
4137 int dst_stride_argb,
4138 const struct YuvConstants* yuvconstants,
4139 int width,
4140 int height) {
4141 int y;
4142 uint8_t* dst_uv;
4143 const ptrdiff_t vu_off = src_v - src_u;
4144 int halfwidth = (width + 1) >> 1;
4145 int halfheight = (height + 1) >> 1;
4146 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
4147 return -1;
4148 }
4149 // Negative height means invert the image.
4150 if (height < 0) {
4151 height = -height;
4152 halfheight = (height + 1) >> 1;
4153 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
4154 dst_stride_argb = -dst_stride_argb;
4155 }
4156
4157 // I420
4158 if (src_pixel_stride_uv == 1) {
4159 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4160 src_stride_v, dst_argb, dst_stride_argb,
4161 yuvconstants, width, height);
4162 // NV21
4163 }
4164 if (src_pixel_stride_uv == 2 && vu_off == -1 &&
4165 src_stride_u == src_stride_v) {
4166 return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
4167 dst_stride_argb, yuvconstants, width, height);
4168 // NV12
4169 }
4170 if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
4171 return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
4172 dst_stride_argb, yuvconstants, width, height);
4173 }
4174
4175 // General case fallback creates NV12
4176 align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
4177 dst_uv = plane_uv;
4178 for (y = 0; y < halfheight; ++y) {
4179 WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
4180 src_u += src_stride_u;
4181 src_v += src_stride_v;
4182 dst_uv += halfwidth * 2;
4183 }
4184 NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
4185 dst_stride_argb, yuvconstants, width, height);
4186 free_aligned_buffer_64(plane_uv);
4187 return 0;
4188 }
4189
4190 // Convert Android420 to ARGB.
4191 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)4192 int Android420ToARGB(const uint8_t* src_y,
4193 int src_stride_y,
4194 const uint8_t* src_u,
4195 int src_stride_u,
4196 const uint8_t* src_v,
4197 int src_stride_v,
4198 int src_pixel_stride_uv,
4199 uint8_t* dst_argb,
4200 int dst_stride_argb,
4201 int width,
4202 int height) {
4203 return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4204 src_stride_v, src_pixel_stride_uv, dst_argb,
4205 dst_stride_argb, &kYuvI601Constants, width,
4206 height);
4207 }
4208
4209 // Convert Android420 to ABGR.
4210 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)4211 int Android420ToABGR(const uint8_t* src_y,
4212 int src_stride_y,
4213 const uint8_t* src_u,
4214 int src_stride_u,
4215 const uint8_t* src_v,
4216 int src_stride_v,
4217 int src_pixel_stride_uv,
4218 uint8_t* dst_abgr,
4219 int dst_stride_abgr,
4220 int width,
4221 int height) {
4222 return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
4223 src_stride_u, src_pixel_stride_uv, dst_abgr,
4224 dst_stride_abgr, &kYvuI601Constants, width,
4225 height);
4226 }
4227
4228 // Convert I422 to RGBA with matrix.
4229 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)4230 int I422ToRGBAMatrix(const uint8_t* src_y,
4231 int src_stride_y,
4232 const uint8_t* src_u,
4233 int src_stride_u,
4234 const uint8_t* src_v,
4235 int src_stride_v,
4236 uint8_t* dst_rgba,
4237 int dst_stride_rgba,
4238 const struct YuvConstants* yuvconstants,
4239 int width,
4240 int height) {
4241 int y;
4242 void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
4243 const uint8_t* v_buf, uint8_t* rgb_buf,
4244 const struct YuvConstants* yuvconstants, int width) =
4245 I422ToRGBARow_C;
4246 if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
4247 return -1;
4248 }
4249 // Negative height means invert the image.
4250 if (height < 0) {
4251 height = -height;
4252 dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
4253 dst_stride_rgba = -dst_stride_rgba;
4254 }
4255 #if defined(HAS_I422TORGBAROW_SSSE3)
4256 if (TestCpuFlag(kCpuHasSSSE3)) {
4257 I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
4258 if (IS_ALIGNED(width, 8)) {
4259 I422ToRGBARow = I422ToRGBARow_SSSE3;
4260 }
4261 }
4262 #endif
4263 #if defined(HAS_I422TORGBAROW_AVX2)
4264 if (TestCpuFlag(kCpuHasAVX2)) {
4265 I422ToRGBARow = I422ToRGBARow_Any_AVX2;
4266 if (IS_ALIGNED(width, 16)) {
4267 I422ToRGBARow = I422ToRGBARow_AVX2;
4268 }
4269 }
4270 #endif
4271 #if defined(HAS_I422TORGBAROW_NEON)
4272 if (TestCpuFlag(kCpuHasNEON)) {
4273 I422ToRGBARow = I422ToRGBARow_Any_NEON;
4274 if (IS_ALIGNED(width, 8)) {
4275 I422ToRGBARow = I422ToRGBARow_NEON;
4276 }
4277 }
4278 #endif
4279 #if defined(HAS_I422TORGBAROW_MSA)
4280 if (TestCpuFlag(kCpuHasMSA)) {
4281 I422ToRGBARow = I422ToRGBARow_Any_MSA;
4282 if (IS_ALIGNED(width, 8)) {
4283 I422ToRGBARow = I422ToRGBARow_MSA;
4284 }
4285 }
4286 #endif
4287 #if defined(HAS_I422TORGBAROW_LASX)
4288 if (TestCpuFlag(kCpuHasLASX)) {
4289 I422ToRGBARow = I422ToRGBARow_Any_LASX;
4290 if (IS_ALIGNED(width, 32)) {
4291 I422ToRGBARow = I422ToRGBARow_LASX;
4292 }
4293 }
4294 #endif
4295
4296 for (y = 0; y < height; ++y) {
4297 I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
4298 dst_rgba += dst_stride_rgba;
4299 src_y += src_stride_y;
4300 src_u += src_stride_u;
4301 src_v += src_stride_v;
4302 }
4303 return 0;
4304 }
4305
4306 // Convert I422 to RGBA.
4307 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)4308 int I422ToRGBA(const uint8_t* src_y,
4309 int src_stride_y,
4310 const uint8_t* src_u,
4311 int src_stride_u,
4312 const uint8_t* src_v,
4313 int src_stride_v,
4314 uint8_t* dst_rgba,
4315 int dst_stride_rgba,
4316 int width,
4317 int height) {
4318 return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4319 src_stride_v, dst_rgba, dst_stride_rgba,
4320 &kYuvI601Constants, width, height);
4321 }
4322
4323 // Convert I422 to BGRA.
4324 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)4325 int I422ToBGRA(const uint8_t* src_y,
4326 int src_stride_y,
4327 const uint8_t* src_u,
4328 int src_stride_u,
4329 const uint8_t* src_v,
4330 int src_stride_v,
4331 uint8_t* dst_bgra,
4332 int dst_stride_bgra,
4333 int width,
4334 int height) {
4335 return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
4336 src_stride_v, // Swap U and V
4337 src_u, src_stride_u, dst_bgra, dst_stride_bgra,
4338 &kYvuI601Constants, // Use Yvu matrix
4339 width, height);
4340 }
4341
4342 // Convert NV12 to RGB565 with matrix.
4343 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)4344 int NV12ToRGB565Matrix(const uint8_t* src_y,
4345 int src_stride_y,
4346 const uint8_t* src_uv,
4347 int src_stride_uv,
4348 uint8_t* dst_rgb565,
4349 int dst_stride_rgb565,
4350 const struct YuvConstants* yuvconstants,
4351 int width,
4352 int height) {
4353 int y;
4354 void (*NV12ToRGB565Row)(
4355 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4356 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
4357 if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
4358 return -1;
4359 }
4360 // Negative height means invert the image.
4361 if (height < 0) {
4362 height = -height;
4363 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
4364 dst_stride_rgb565 = -dst_stride_rgb565;
4365 }
4366 #if defined(HAS_NV12TORGB565ROW_SSSE3)
4367 if (TestCpuFlag(kCpuHasSSSE3)) {
4368 NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
4369 if (IS_ALIGNED(width, 8)) {
4370 NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
4371 }
4372 }
4373 #endif
4374 #if defined(HAS_NV12TORGB565ROW_AVX2)
4375 if (TestCpuFlag(kCpuHasAVX2)) {
4376 NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
4377 if (IS_ALIGNED(width, 16)) {
4378 NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
4379 }
4380 }
4381 #endif
4382 #if defined(HAS_NV12TORGB565ROW_NEON)
4383 if (TestCpuFlag(kCpuHasNEON)) {
4384 NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
4385 if (IS_ALIGNED(width, 8)) {
4386 NV12ToRGB565Row = NV12ToRGB565Row_NEON;
4387 }
4388 }
4389 #endif
4390 #if defined(HAS_NV12TORGB565ROW_MSA)
4391 if (TestCpuFlag(kCpuHasMSA)) {
4392 NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
4393 if (IS_ALIGNED(width, 8)) {
4394 NV12ToRGB565Row = NV12ToRGB565Row_MSA;
4395 }
4396 }
4397 #endif
4398 #if defined(HAS_NV12TORGB565ROW_LSX)
4399 if (TestCpuFlag(kCpuHasLSX)) {
4400 NV12ToRGB565Row = NV12ToRGB565Row_Any_LSX;
4401 if (IS_ALIGNED(width, 8)) {
4402 NV12ToRGB565Row = NV12ToRGB565Row_LSX;
4403 }
4404 }
4405 #endif
4406 #if defined(HAS_NV12TORGB565ROW_LASX)
4407 if (TestCpuFlag(kCpuHasLASX)) {
4408 NV12ToRGB565Row = NV12ToRGB565Row_Any_LASX;
4409 if (IS_ALIGNED(width, 16)) {
4410 NV12ToRGB565Row = NV12ToRGB565Row_LASX;
4411 }
4412 }
4413 #endif
4414
4415 for (y = 0; y < height; ++y) {
4416 NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
4417 dst_rgb565 += dst_stride_rgb565;
4418 src_y += src_stride_y;
4419 if (y & 1) {
4420 src_uv += src_stride_uv;
4421 }
4422 }
4423 return 0;
4424 }
4425
4426 // Convert NV12 to RGB565.
4427 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)4428 int NV12ToRGB565(const uint8_t* src_y,
4429 int src_stride_y,
4430 const uint8_t* src_uv,
4431 int src_stride_uv,
4432 uint8_t* dst_rgb565,
4433 int dst_stride_rgb565,
4434 int width,
4435 int height) {
4436 return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
4437 dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
4438 width, height);
4439 }
4440
4441 // Convert I422 to RGBA with matrix.
4442 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)4443 int I420ToRGBAMatrix(const uint8_t* src_y,
4444 int src_stride_y,
4445 const uint8_t* src_u,
4446 int src_stride_u,
4447 const uint8_t* src_v,
4448 int src_stride_v,
4449 uint8_t* dst_rgba,
4450 int dst_stride_rgba,
4451 const struct YuvConstants* yuvconstants,
4452 int width,
4453 int height) {
4454 int y;
4455 void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
4456 const uint8_t* v_buf, uint8_t* rgb_buf,
4457 const struct YuvConstants* yuvconstants, int width) =
4458 I422ToRGBARow_C;
4459 if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
4460 return -1;
4461 }
4462 // Negative height means invert the image.
4463 if (height < 0) {
4464 height = -height;
4465 dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
4466 dst_stride_rgba = -dst_stride_rgba;
4467 }
4468 #if defined(HAS_I422TORGBAROW_SSSE3)
4469 if (TestCpuFlag(kCpuHasSSSE3)) {
4470 I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
4471 if (IS_ALIGNED(width, 8)) {
4472 I422ToRGBARow = I422ToRGBARow_SSSE3;
4473 }
4474 }
4475 #endif
4476 #if defined(HAS_I422TORGBAROW_AVX2)
4477 if (TestCpuFlag(kCpuHasAVX2)) {
4478 I422ToRGBARow = I422ToRGBARow_Any_AVX2;
4479 if (IS_ALIGNED(width, 16)) {
4480 I422ToRGBARow = I422ToRGBARow_AVX2;
4481 }
4482 }
4483 #endif
4484 #if defined(HAS_I422TORGBAROW_NEON)
4485 if (TestCpuFlag(kCpuHasNEON)) {
4486 I422ToRGBARow = I422ToRGBARow_Any_NEON;
4487 if (IS_ALIGNED(width, 8)) {
4488 I422ToRGBARow = I422ToRGBARow_NEON;
4489 }
4490 }
4491 #endif
4492 #if defined(HAS_I422TORGBAROW_MSA)
4493 if (TestCpuFlag(kCpuHasMSA)) {
4494 I422ToRGBARow = I422ToRGBARow_Any_MSA;
4495 if (IS_ALIGNED(width, 8)) {
4496 I422ToRGBARow = I422ToRGBARow_MSA;
4497 }
4498 }
4499 #endif
4500 #if defined(HAS_I422TORGBAROW_LASX)
4501 if (TestCpuFlag(kCpuHasLASX)) {
4502 I422ToRGBARow = I422ToRGBARow_Any_LASX;
4503 if (IS_ALIGNED(width, 32)) {
4504 I422ToRGBARow = I422ToRGBARow_LASX;
4505 }
4506 }
4507 #endif
4508
4509 for (y = 0; y < height; ++y) {
4510 I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
4511 dst_rgba += dst_stride_rgba;
4512 src_y += src_stride_y;
4513 if (y & 1) {
4514 src_u += src_stride_u;
4515 src_v += src_stride_v;
4516 }
4517 }
4518 return 0;
4519 }
4520
4521 // Convert I420 to RGBA.
4522 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)4523 int I420ToRGBA(const uint8_t* src_y,
4524 int src_stride_y,
4525 const uint8_t* src_u,
4526 int src_stride_u,
4527 const uint8_t* src_v,
4528 int src_stride_v,
4529 uint8_t* dst_rgba,
4530 int dst_stride_rgba,
4531 int width,
4532 int height) {
4533 return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4534 src_stride_v, dst_rgba, dst_stride_rgba,
4535 &kYuvI601Constants, width, height);
4536 }
4537
4538 // Convert I420 to BGRA.
4539 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)4540 int I420ToBGRA(const uint8_t* src_y,
4541 int src_stride_y,
4542 const uint8_t* src_u,
4543 int src_stride_u,
4544 const uint8_t* src_v,
4545 int src_stride_v,
4546 uint8_t* dst_bgra,
4547 int dst_stride_bgra,
4548 int width,
4549 int height) {
4550 return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
4551 src_stride_v, // Swap U and V
4552 src_u, src_stride_u, dst_bgra, dst_stride_bgra,
4553 &kYvuI601Constants, // Use Yvu matrix
4554 width, height);
4555 }
4556
4557 // Convert I420 to RGB24 with matrix.
4558 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)4559 int I420ToRGB24Matrix(const uint8_t* src_y,
4560 int src_stride_y,
4561 const uint8_t* src_u,
4562 int src_stride_u,
4563 const uint8_t* src_v,
4564 int src_stride_v,
4565 uint8_t* dst_rgb24,
4566 int dst_stride_rgb24,
4567 const struct YuvConstants* yuvconstants,
4568 int width,
4569 int height) {
4570 int y;
4571 void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4572 const uint8_t* v_buf, uint8_t* rgb_buf,
4573 const struct YuvConstants* yuvconstants, int width) =
4574 I422ToRGB24Row_C;
4575 if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
4576 return -1;
4577 }
4578 // Negative height means invert the image.
4579 if (height < 0) {
4580 height = -height;
4581 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
4582 dst_stride_rgb24 = -dst_stride_rgb24;
4583 }
4584 #if defined(HAS_I422TORGB24ROW_SSSE3)
4585 if (TestCpuFlag(kCpuHasSSSE3)) {
4586 I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
4587 if (IS_ALIGNED(width, 16)) {
4588 I422ToRGB24Row = I422ToRGB24Row_SSSE3;
4589 }
4590 }
4591 #endif
4592 #if defined(HAS_I422TORGB24ROW_AVX2)
4593 if (TestCpuFlag(kCpuHasAVX2)) {
4594 I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
4595 if (IS_ALIGNED(width, 32)) {
4596 I422ToRGB24Row = I422ToRGB24Row_AVX2;
4597 }
4598 }
4599 #endif
4600 #if defined(HAS_I422TORGB24ROW_NEON)
4601 if (TestCpuFlag(kCpuHasNEON)) {
4602 I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
4603 if (IS_ALIGNED(width, 8)) {
4604 I422ToRGB24Row = I422ToRGB24Row_NEON;
4605 }
4606 }
4607 #endif
4608 #if defined(HAS_I422TORGB24ROW_MSA)
4609 if (TestCpuFlag(kCpuHasMSA)) {
4610 I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
4611 if (IS_ALIGNED(width, 16)) {
4612 I422ToRGB24Row = I422ToRGB24Row_MSA;
4613 }
4614 }
4615 #endif
4616 #if defined(HAS_I422TORGB24ROW_LASX)
4617 if (TestCpuFlag(kCpuHasLASX)) {
4618 I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
4619 if (IS_ALIGNED(width, 32)) {
4620 I422ToRGB24Row = I422ToRGB24Row_LASX;
4621 }
4622 }
4623 #endif
4624
4625 for (y = 0; y < height; ++y) {
4626 I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
4627 dst_rgb24 += dst_stride_rgb24;
4628 src_y += src_stride_y;
4629 if (y & 1) {
4630 src_u += src_stride_u;
4631 src_v += src_stride_v;
4632 }
4633 }
4634 return 0;
4635 }
4636
4637 // Convert I420 to RGB24.
4638 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)4639 int I420ToRGB24(const uint8_t* src_y,
4640 int src_stride_y,
4641 const uint8_t* src_u,
4642 int src_stride_u,
4643 const uint8_t* src_v,
4644 int src_stride_v,
4645 uint8_t* dst_rgb24,
4646 int dst_stride_rgb24,
4647 int width,
4648 int height) {
4649 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4650 src_stride_v, dst_rgb24, dst_stride_rgb24,
4651 &kYuvI601Constants, width, height);
4652 }
4653
4654 // Convert I420 to RAW.
4655 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)4656 int I420ToRAW(const uint8_t* src_y,
4657 int src_stride_y,
4658 const uint8_t* src_u,
4659 int src_stride_u,
4660 const uint8_t* src_v,
4661 int src_stride_v,
4662 uint8_t* dst_raw,
4663 int dst_stride_raw,
4664 int width,
4665 int height) {
4666 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
4667 src_stride_v, // Swap U and V
4668 src_u, src_stride_u, dst_raw, dst_stride_raw,
4669 &kYvuI601Constants, // Use Yvu matrix
4670 width, height);
4671 }
4672
4673 // Convert J420 to RGB24.
4674 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)4675 int J420ToRGB24(const uint8_t* src_y,
4676 int src_stride_y,
4677 const uint8_t* src_u,
4678 int src_stride_u,
4679 const uint8_t* src_v,
4680 int src_stride_v,
4681 uint8_t* dst_rgb24,
4682 int dst_stride_rgb24,
4683 int width,
4684 int height) {
4685 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4686 src_stride_v, dst_rgb24, dst_stride_rgb24,
4687 &kYuvJPEGConstants, width, height);
4688 }
4689
4690 // Convert J420 to RAW.
4691 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)4692 int J420ToRAW(const uint8_t* src_y,
4693 int src_stride_y,
4694 const uint8_t* src_u,
4695 int src_stride_u,
4696 const uint8_t* src_v,
4697 int src_stride_v,
4698 uint8_t* dst_raw,
4699 int dst_stride_raw,
4700 int width,
4701 int height) {
4702 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
4703 src_stride_v, // Swap U and V
4704 src_u, src_stride_u, dst_raw, dst_stride_raw,
4705 &kYvuJPEGConstants, // Use Yvu matrix
4706 width, height);
4707 }
4708
4709 // Convert H420 to RGB24.
4710 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)4711 int H420ToRGB24(const uint8_t* src_y,
4712 int src_stride_y,
4713 const uint8_t* src_u,
4714 int src_stride_u,
4715 const uint8_t* src_v,
4716 int src_stride_v,
4717 uint8_t* dst_rgb24,
4718 int dst_stride_rgb24,
4719 int width,
4720 int height) {
4721 return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4722 src_stride_v, dst_rgb24, dst_stride_rgb24,
4723 &kYuvH709Constants, width, height);
4724 }
4725
4726 // Convert H420 to RAW.
4727 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)4728 int H420ToRAW(const uint8_t* src_y,
4729 int src_stride_y,
4730 const uint8_t* src_u,
4731 int src_stride_u,
4732 const uint8_t* src_v,
4733 int src_stride_v,
4734 uint8_t* dst_raw,
4735 int dst_stride_raw,
4736 int width,
4737 int height) {
4738 return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
4739 src_stride_v, // Swap U and V
4740 src_u, src_stride_u, dst_raw, dst_stride_raw,
4741 &kYvuH709Constants, // Use Yvu matrix
4742 width, height);
4743 }
4744
4745 // Convert I420 to ARGB1555.
4746 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)4747 int I420ToARGB1555(const uint8_t* src_y,
4748 int src_stride_y,
4749 const uint8_t* src_u,
4750 int src_stride_u,
4751 const uint8_t* src_v,
4752 int src_stride_v,
4753 uint8_t* dst_argb1555,
4754 int dst_stride_argb1555,
4755 int width,
4756 int height) {
4757 int y;
4758 void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4759 const uint8_t* v_buf, uint8_t* rgb_buf,
4760 const struct YuvConstants* yuvconstants,
4761 int width) = I422ToARGB1555Row_C;
4762 if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
4763 height == 0) {
4764 return -1;
4765 }
4766 // Negative height means invert the image.
4767 if (height < 0) {
4768 height = -height;
4769 dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
4770 dst_stride_argb1555 = -dst_stride_argb1555;
4771 }
4772 #if defined(HAS_I422TOARGB1555ROW_SSSE3)
4773 if (TestCpuFlag(kCpuHasSSSE3)) {
4774 I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
4775 if (IS_ALIGNED(width, 8)) {
4776 I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
4777 }
4778 }
4779 #endif
4780 #if defined(HAS_I422TOARGB1555ROW_AVX2)
4781 if (TestCpuFlag(kCpuHasAVX2)) {
4782 I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
4783 if (IS_ALIGNED(width, 16)) {
4784 I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
4785 }
4786 }
4787 #endif
4788 #if defined(HAS_I422TOARGB1555ROW_NEON)
4789 if (TestCpuFlag(kCpuHasNEON)) {
4790 I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
4791 if (IS_ALIGNED(width, 8)) {
4792 I422ToARGB1555Row = I422ToARGB1555Row_NEON;
4793 }
4794 }
4795 #endif
4796 #if defined(HAS_I422TOARGB1555ROW_MSA)
4797 if (TestCpuFlag(kCpuHasMSA)) {
4798 I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
4799 if (IS_ALIGNED(width, 8)) {
4800 I422ToARGB1555Row = I422ToARGB1555Row_MSA;
4801 }
4802 }
4803 #endif
4804 #if defined(HAS_I422TOARGB1555ROW_LASX)
4805 if (TestCpuFlag(kCpuHasLASX)) {
4806 I422ToARGB1555Row = I422ToARGB1555Row_Any_LASX;
4807 if (IS_ALIGNED(width, 8)) {
4808 I422ToARGB1555Row = I422ToARGB1555Row_LASX;
4809 }
4810 }
4811 #endif
4812
4813 for (y = 0; y < height; ++y) {
4814 I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
4815 width);
4816 dst_argb1555 += dst_stride_argb1555;
4817 src_y += src_stride_y;
4818 if (y & 1) {
4819 src_u += src_stride_u;
4820 src_v += src_stride_v;
4821 }
4822 }
4823 return 0;
4824 }
4825
4826 // Convert I420 to ARGB4444.
4827 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)4828 int I420ToARGB4444(const uint8_t* src_y,
4829 int src_stride_y,
4830 const uint8_t* src_u,
4831 int src_stride_u,
4832 const uint8_t* src_v,
4833 int src_stride_v,
4834 uint8_t* dst_argb4444,
4835 int dst_stride_argb4444,
4836 int width,
4837 int height) {
4838 int y;
4839 void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4840 const uint8_t* v_buf, uint8_t* rgb_buf,
4841 const struct YuvConstants* yuvconstants,
4842 int width) = I422ToARGB4444Row_C;
4843 if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
4844 height == 0) {
4845 return -1;
4846 }
4847 // Negative height means invert the image.
4848 if (height < 0) {
4849 height = -height;
4850 dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
4851 dst_stride_argb4444 = -dst_stride_argb4444;
4852 }
4853 #if defined(HAS_I422TOARGB4444ROW_SSSE3)
4854 if (TestCpuFlag(kCpuHasSSSE3)) {
4855 I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
4856 if (IS_ALIGNED(width, 8)) {
4857 I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
4858 }
4859 }
4860 #endif
4861 #if defined(HAS_I422TOARGB4444ROW_AVX2)
4862 if (TestCpuFlag(kCpuHasAVX2)) {
4863 I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
4864 if (IS_ALIGNED(width, 16)) {
4865 I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
4866 }
4867 }
4868 #endif
4869 #if defined(HAS_I422TOARGB4444ROW_NEON)
4870 if (TestCpuFlag(kCpuHasNEON)) {
4871 I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
4872 if (IS_ALIGNED(width, 8)) {
4873 I422ToARGB4444Row = I422ToARGB4444Row_NEON;
4874 }
4875 }
4876 #endif
4877 #if defined(HAS_I422TOARGB4444ROW_MSA)
4878 if (TestCpuFlag(kCpuHasMSA)) {
4879 I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
4880 if (IS_ALIGNED(width, 8)) {
4881 I422ToARGB4444Row = I422ToARGB4444Row_MSA;
4882 }
4883 }
4884 #endif
4885 #if defined(HAS_I422TOARGB4444ROW_LASX)
4886 if (TestCpuFlag(kCpuHasLASX)) {
4887 I422ToARGB4444Row = I422ToARGB4444Row_Any_LASX;
4888 if (IS_ALIGNED(width, 8)) {
4889 I422ToARGB4444Row = I422ToARGB4444Row_LASX;
4890 }
4891 }
4892 #endif
4893
4894 for (y = 0; y < height; ++y) {
4895 I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
4896 width);
4897 dst_argb4444 += dst_stride_argb4444;
4898 src_y += src_stride_y;
4899 if (y & 1) {
4900 src_u += src_stride_u;
4901 src_v += src_stride_v;
4902 }
4903 }
4904 return 0;
4905 }
4906
4907 // Convert I420 to RGB565 with specified color matrix.
4908 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)4909 int I420ToRGB565Matrix(const uint8_t* src_y,
4910 int src_stride_y,
4911 const uint8_t* src_u,
4912 int src_stride_u,
4913 const uint8_t* src_v,
4914 int src_stride_v,
4915 uint8_t* dst_rgb565,
4916 int dst_stride_rgb565,
4917 const struct YuvConstants* yuvconstants,
4918 int width,
4919 int height) {
4920 int y;
4921 void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4922 const uint8_t* v_buf, uint8_t* rgb_buf,
4923 const struct YuvConstants* yuvconstants, int width) =
4924 I422ToRGB565Row_C;
4925 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
4926 return -1;
4927 }
4928 // Negative height means invert the image.
4929 if (height < 0) {
4930 height = -height;
4931 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
4932 dst_stride_rgb565 = -dst_stride_rgb565;
4933 }
4934 #if defined(HAS_I422TORGB565ROW_SSSE3)
4935 if (TestCpuFlag(kCpuHasSSSE3)) {
4936 I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
4937 if (IS_ALIGNED(width, 8)) {
4938 I422ToRGB565Row = I422ToRGB565Row_SSSE3;
4939 }
4940 }
4941 #endif
4942 #if defined(HAS_I422TORGB565ROW_AVX2)
4943 if (TestCpuFlag(kCpuHasAVX2)) {
4944 I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
4945 if (IS_ALIGNED(width, 16)) {
4946 I422ToRGB565Row = I422ToRGB565Row_AVX2;
4947 }
4948 }
4949 #endif
4950 #if defined(HAS_I422TORGB565ROW_NEON)
4951 if (TestCpuFlag(kCpuHasNEON)) {
4952 I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
4953 if (IS_ALIGNED(width, 8)) {
4954 I422ToRGB565Row = I422ToRGB565Row_NEON;
4955 }
4956 }
4957 #endif
4958 #if defined(HAS_I422TORGB565ROW_MSA)
4959 if (TestCpuFlag(kCpuHasMSA)) {
4960 I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
4961 if (IS_ALIGNED(width, 8)) {
4962 I422ToRGB565Row = I422ToRGB565Row_MSA;
4963 }
4964 }
4965 #endif
4966 #if defined(HAS_I422TORGB565ROW_LASX)
4967 if (TestCpuFlag(kCpuHasLASX)) {
4968 I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
4969 if (IS_ALIGNED(width, 32)) {
4970 I422ToRGB565Row = I422ToRGB565Row_LASX;
4971 }
4972 }
4973 #endif
4974
4975 for (y = 0; y < height; ++y) {
4976 I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
4977 dst_rgb565 += dst_stride_rgb565;
4978 src_y += src_stride_y;
4979 if (y & 1) {
4980 src_u += src_stride_u;
4981 src_v += src_stride_v;
4982 }
4983 }
4984 return 0;
4985 }
4986
4987 // Convert I420 to RGB565.
4988 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)4989 int I420ToRGB565(const uint8_t* src_y,
4990 int src_stride_y,
4991 const uint8_t* src_u,
4992 int src_stride_u,
4993 const uint8_t* src_v,
4994 int src_stride_v,
4995 uint8_t* dst_rgb565,
4996 int dst_stride_rgb565,
4997 int width,
4998 int height) {
4999 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5000 src_stride_v, dst_rgb565, dst_stride_rgb565,
5001 &kYuvI601Constants, width, height);
5002 }
5003
5004 // Convert J420 to RGB565.
5005 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)5006 int J420ToRGB565(const uint8_t* src_y,
5007 int src_stride_y,
5008 const uint8_t* src_u,
5009 int src_stride_u,
5010 const uint8_t* src_v,
5011 int src_stride_v,
5012 uint8_t* dst_rgb565,
5013 int dst_stride_rgb565,
5014 int width,
5015 int height) {
5016 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5017 src_stride_v, dst_rgb565, dst_stride_rgb565,
5018 &kYuvJPEGConstants, width, height);
5019 }
5020
5021 // Convert H420 to RGB565.
5022 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)5023 int H420ToRGB565(const uint8_t* src_y,
5024 int src_stride_y,
5025 const uint8_t* src_u,
5026 int src_stride_u,
5027 const uint8_t* src_v,
5028 int src_stride_v,
5029 uint8_t* dst_rgb565,
5030 int dst_stride_rgb565,
5031 int width,
5032 int height) {
5033 return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5034 src_stride_v, dst_rgb565, dst_stride_rgb565,
5035 &kYuvH709Constants, width, height);
5036 }
5037
5038 // Convert I422 to RGB565.
5039 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)5040 int I422ToRGB565(const uint8_t* src_y,
5041 int src_stride_y,
5042 const uint8_t* src_u,
5043 int src_stride_u,
5044 const uint8_t* src_v,
5045 int src_stride_v,
5046 uint8_t* dst_rgb565,
5047 int dst_stride_rgb565,
5048 int width,
5049 int height) {
5050 int y;
5051 void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5052 const uint8_t* v_buf, uint8_t* rgb_buf,
5053 const struct YuvConstants* yuvconstants, int width) =
5054 I422ToRGB565Row_C;
5055 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
5056 return -1;
5057 }
5058 // Negative height means invert the image.
5059 if (height < 0) {
5060 height = -height;
5061 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5062 dst_stride_rgb565 = -dst_stride_rgb565;
5063 }
5064 #if defined(HAS_I422TORGB565ROW_SSSE3)
5065 if (TestCpuFlag(kCpuHasSSSE3)) {
5066 I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
5067 if (IS_ALIGNED(width, 8)) {
5068 I422ToRGB565Row = I422ToRGB565Row_SSSE3;
5069 }
5070 }
5071 #endif
5072 #if defined(HAS_I422TORGB565ROW_AVX2)
5073 if (TestCpuFlag(kCpuHasAVX2)) {
5074 I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
5075 if (IS_ALIGNED(width, 16)) {
5076 I422ToRGB565Row = I422ToRGB565Row_AVX2;
5077 }
5078 }
5079 #endif
5080 #if defined(HAS_I422TORGB565ROW_NEON)
5081 if (TestCpuFlag(kCpuHasNEON)) {
5082 I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
5083 if (IS_ALIGNED(width, 8)) {
5084 I422ToRGB565Row = I422ToRGB565Row_NEON;
5085 }
5086 }
5087 #endif
5088 #if defined(HAS_I422TORGB565ROW_MSA)
5089 if (TestCpuFlag(kCpuHasMSA)) {
5090 I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
5091 if (IS_ALIGNED(width, 8)) {
5092 I422ToRGB565Row = I422ToRGB565Row_MSA;
5093 }
5094 }
5095 #endif
5096 #if defined(HAS_I422TORGB565ROW_LASX)
5097 if (TestCpuFlag(kCpuHasLASX)) {
5098 I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
5099 if (IS_ALIGNED(width, 32)) {
5100 I422ToRGB565Row = I422ToRGB565Row_LASX;
5101 }
5102 }
5103 #endif
5104
5105 for (y = 0; y < height; ++y) {
5106 I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, &kYuvI601Constants, width);
5107 dst_rgb565 += dst_stride_rgb565;
5108 src_y += src_stride_y;
5109 src_u += src_stride_u;
5110 src_v += src_stride_v;
5111 }
5112 return 0;
5113 }
5114
5115 // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
5116 static const uint8_t kDither565_4x4[16] = {
5117 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
5118 };
5119
5120 // Convert I420 to RGB565 with dithering.
5121 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)5122 int I420ToRGB565Dither(const uint8_t* src_y,
5123 int src_stride_y,
5124 const uint8_t* src_u,
5125 int src_stride_u,
5126 const uint8_t* src_v,
5127 int src_stride_v,
5128 uint8_t* dst_rgb565,
5129 int dst_stride_rgb565,
5130 const uint8_t* dither4x4,
5131 int width,
5132 int height) {
5133 int y;
5134 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
5135 const uint8_t* v_buf, uint8_t* rgb_buf,
5136 const struct YuvConstants* yuvconstants, int width) =
5137 I422ToARGBRow_C;
5138 void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
5139 const uint32_t dither4, int width) =
5140 ARGBToRGB565DitherRow_C;
5141 if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
5142 return -1;
5143 }
5144 // Negative height means invert the image.
5145 if (height < 0) {
5146 height = -height;
5147 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5148 dst_stride_rgb565 = -dst_stride_rgb565;
5149 }
5150 if (!dither4x4) {
5151 dither4x4 = kDither565_4x4;
5152 }
5153 #if defined(HAS_I422TOARGBROW_SSSE3)
5154 if (TestCpuFlag(kCpuHasSSSE3)) {
5155 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
5156 if (IS_ALIGNED(width, 8)) {
5157 I422ToARGBRow = I422ToARGBRow_SSSE3;
5158 }
5159 }
5160 #endif
5161 #if defined(HAS_I422TOARGBROW_AVX2)
5162 if (TestCpuFlag(kCpuHasAVX2)) {
5163 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
5164 if (IS_ALIGNED(width, 16)) {
5165 I422ToARGBRow = I422ToARGBRow_AVX2;
5166 }
5167 }
5168 #endif
5169 #if defined(HAS_I422TOARGBROW_AVX512BW)
5170 if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
5171 (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
5172 I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
5173 if (IS_ALIGNED(width, 32)) {
5174 I422ToARGBRow = I422ToARGBRow_AVX512BW;
5175 }
5176 }
5177 #endif
5178 #if defined(HAS_I422TOARGBROW_NEON)
5179 if (TestCpuFlag(kCpuHasNEON)) {
5180 I422ToARGBRow = I422ToARGBRow_Any_NEON;
5181 if (IS_ALIGNED(width, 8)) {
5182 I422ToARGBRow = I422ToARGBRow_NEON;
5183 }
5184 }
5185 #endif
5186 #if defined(HAS_I422TOARGBROW_MSA)
5187 if (TestCpuFlag(kCpuHasMSA)) {
5188 I422ToARGBRow = I422ToARGBRow_Any_MSA;
5189 if (IS_ALIGNED(width, 8)) {
5190 I422ToARGBRow = I422ToARGBRow_MSA;
5191 }
5192 }
5193 #endif
5194 #if defined(HAS_I422TOARGBROW_LASX)
5195 if (TestCpuFlag(kCpuHasLASX)) {
5196 I422ToARGBRow = I422ToARGBRow_Any_LASX;
5197 if (IS_ALIGNED(width, 32)) {
5198 I422ToARGBRow = I422ToARGBRow_LASX;
5199 }
5200 }
5201 #endif
5202 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
5203 if (TestCpuFlag(kCpuHasSSE2)) {
5204 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
5205 if (IS_ALIGNED(width, 4)) {
5206 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
5207 }
5208 }
5209 #endif
5210 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
5211 if (TestCpuFlag(kCpuHasAVX2)) {
5212 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
5213 if (IS_ALIGNED(width, 8)) {
5214 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
5215 }
5216 }
5217 #endif
5218 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
5219 if (TestCpuFlag(kCpuHasNEON)) {
5220 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
5221 if (IS_ALIGNED(width, 8)) {
5222 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
5223 }
5224 }
5225 #endif
5226 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
5227 if (TestCpuFlag(kCpuHasMSA)) {
5228 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
5229 if (IS_ALIGNED(width, 8)) {
5230 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
5231 }
5232 }
5233 #endif
5234 #if defined(HAS_ARGBTORGB565DITHERROW_LASX)
5235 if (TestCpuFlag(kCpuHasLASX)) {
5236 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
5237 if (IS_ALIGNED(width, 16)) {
5238 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
5239 }
5240 }
5241 #endif
5242 {
5243 // Allocate a row of argb.
5244 align_buffer_64(row_argb, width * 4);
5245 for (y = 0; y < height; ++y) {
5246 I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
5247 ARGBToRGB565DitherRow(row_argb, dst_rgb565,
5248 *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
5249 width);
5250 dst_rgb565 += dst_stride_rgb565;
5251 src_y += src_stride_y;
5252 if (y & 1) {
5253 src_u += src_stride_u;
5254 src_v += src_stride_v;
5255 }
5256 }
5257 free_aligned_buffer_64(row_argb);
5258 }
5259 return 0;
5260 }
5261
5262 // Convert I420 to AR30 with matrix.
5263 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)5264 int I420ToAR30Matrix(const uint8_t* src_y,
5265 int src_stride_y,
5266 const uint8_t* src_u,
5267 int src_stride_u,
5268 const uint8_t* src_v,
5269 int src_stride_v,
5270 uint8_t* dst_ar30,
5271 int dst_stride_ar30,
5272 const struct YuvConstants* yuvconstants,
5273 int width,
5274 int height) {
5275 int y;
5276 void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5277 const uint8_t* v_buf, uint8_t* rgb_buf,
5278 const struct YuvConstants* yuvconstants, int width) =
5279 I422ToAR30Row_C;
5280
5281 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
5282 return -1;
5283 }
5284 // Negative height means invert the image.
5285 if (height < 0) {
5286 height = -height;
5287 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
5288 dst_stride_ar30 = -dst_stride_ar30;
5289 }
5290
5291 #if defined(HAS_I422TOAR30ROW_SSSE3)
5292 if (TestCpuFlag(kCpuHasSSSE3)) {
5293 I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
5294 if (IS_ALIGNED(width, 8)) {
5295 I422ToAR30Row = I422ToAR30Row_SSSE3;
5296 }
5297 }
5298 #endif
5299 #if defined(HAS_I422TOAR30ROW_AVX2)
5300 if (TestCpuFlag(kCpuHasAVX2)) {
5301 I422ToAR30Row = I422ToAR30Row_Any_AVX2;
5302 if (IS_ALIGNED(width, 16)) {
5303 I422ToAR30Row = I422ToAR30Row_AVX2;
5304 }
5305 }
5306 #endif
5307
5308 for (y = 0; y < height; ++y) {
5309 I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
5310 dst_ar30 += dst_stride_ar30;
5311 src_y += src_stride_y;
5312 if (y & 1) {
5313 src_u += src_stride_u;
5314 src_v += src_stride_v;
5315 }
5316 }
5317 return 0;
5318 }
5319
5320 // Convert I420 to AR30.
5321 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)5322 int I420ToAR30(const uint8_t* src_y,
5323 int src_stride_y,
5324 const uint8_t* src_u,
5325 int src_stride_u,
5326 const uint8_t* src_v,
5327 int src_stride_v,
5328 uint8_t* dst_ar30,
5329 int dst_stride_ar30,
5330 int width,
5331 int height) {
5332 return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5333 src_stride_v, dst_ar30, dst_stride_ar30,
5334 &kYuvI601Constants, width, height);
5335 }
5336
5337 // Convert H420 to AR30.
5338 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)5339 int H420ToAR30(const uint8_t* src_y,
5340 int src_stride_y,
5341 const uint8_t* src_u,
5342 int src_stride_u,
5343 const uint8_t* src_v,
5344 int src_stride_v,
5345 uint8_t* dst_ar30,
5346 int dst_stride_ar30,
5347 int width,
5348 int height) {
5349 return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5350 src_stride_v, dst_ar30, dst_stride_ar30,
5351 &kYvuH709Constants, width, height);
5352 }
5353
5354 // Convert I420 to AB30.
5355 LIBYUV_API
I420ToAB30(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_ab30,int dst_stride_ab30,int width,int height)5356 int I420ToAB30(const uint8_t* src_y,
5357 int src_stride_y,
5358 const uint8_t* src_u,
5359 int src_stride_u,
5360 const uint8_t* src_v,
5361 int src_stride_v,
5362 uint8_t* dst_ab30,
5363 int dst_stride_ab30,
5364 int width,
5365 int height) {
5366 return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
5367 src_stride_u, dst_ab30, dst_stride_ab30,
5368 &kYvuI601Constants, width, height);
5369 }
5370
5371 // Convert H420 to AB30.
5372 LIBYUV_API
H420ToAB30(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_ab30,int dst_stride_ab30,int width,int height)5373 int H420ToAB30(const uint8_t* src_y,
5374 int src_stride_y,
5375 const uint8_t* src_u,
5376 int src_stride_u,
5377 const uint8_t* src_v,
5378 int src_stride_v,
5379 uint8_t* dst_ab30,
5380 int dst_stride_ab30,
5381 int width,
5382 int height) {
5383 return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
5384 src_stride_u, dst_ab30, dst_stride_ab30,
5385 &kYvuH709Constants, width, height);
5386 }
5387
I420ToARGBMatrixBilinear(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)5388 static int I420ToARGBMatrixBilinear(const uint8_t* src_y,
5389 int src_stride_y,
5390 const uint8_t* src_u,
5391 int src_stride_u,
5392 const uint8_t* src_v,
5393 int src_stride_v,
5394 uint8_t* dst_argb,
5395 int dst_stride_argb,
5396 const struct YuvConstants* yuvconstants,
5397 int width,
5398 int height) {
5399 int y;
5400 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
5401 const uint8_t* v_buf, uint8_t* rgb_buf,
5402 const struct YuvConstants* yuvconstants, int width) =
5403 I444ToARGBRow_C;
5404 void (*Scale2RowUp)(const uint8_t* src_ptr, ptrdiff_t src_stride,
5405 uint8_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
5406 ScaleRowUp2_Bilinear_Any_C;
5407 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
5408 return -1;
5409 }
5410 // Negative height means invert the image.
5411 if (height < 0) {
5412 height = -height;
5413 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
5414 dst_stride_argb = -dst_stride_argb;
5415 }
5416 #if defined(HAS_I444TOARGBROW_SSSE3)
5417 if (TestCpuFlag(kCpuHasSSSE3)) {
5418 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
5419 if (IS_ALIGNED(width, 8)) {
5420 I444ToARGBRow = I444ToARGBRow_SSSE3;
5421 }
5422 }
5423 #endif
5424 #if defined(HAS_I444TOARGBROW_AVX2)
5425 if (TestCpuFlag(kCpuHasAVX2)) {
5426 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
5427 if (IS_ALIGNED(width, 16)) {
5428 I444ToARGBRow = I444ToARGBRow_AVX2;
5429 }
5430 }
5431 #endif
5432 #if defined(HAS_I444TOARGBROW_NEON)
5433 if (TestCpuFlag(kCpuHasNEON)) {
5434 I444ToARGBRow = I444ToARGBRow_Any_NEON;
5435 if (IS_ALIGNED(width, 8)) {
5436 I444ToARGBRow = I444ToARGBRow_NEON;
5437 }
5438 }
5439 #endif
5440 #if defined(HAS_I444TOARGBROW_MSA)
5441 if (TestCpuFlag(kCpuHasMSA)) {
5442 I444ToARGBRow = I444ToARGBRow_Any_MSA;
5443 if (IS_ALIGNED(width, 8)) {
5444 I444ToARGBRow = I444ToARGBRow_MSA;
5445 }
5446 }
5447 #endif
5448 #if defined(HAS_I444TOARGBROW_LASX)
5449 if (TestCpuFlag(kCpuHasLASX)) {
5450 I444ToARGBRow = I444ToARGBRow_Any_LASX;
5451 if (IS_ALIGNED(width, 32)) {
5452 I444ToARGBRow = I444ToARGBRow_LASX;
5453 }
5454 }
5455 #endif
5456
5457 #if defined(HAS_SCALEROWUP2LINEAR_SSE2)
5458 if (TestCpuFlag(kCpuHasSSE2)) {
5459 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSE2;
5460 }
5461 #endif
5462
5463 #if defined(HAS_SCALEROWUP2LINEAR_SSSE3)
5464 if (TestCpuFlag(kCpuHasSSSE3)) {
5465 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSSE3;
5466 }
5467 #endif
5468
5469 #if defined(HAS_SCALEROWUP2LINEAR_AVX2)
5470 if (TestCpuFlag(kCpuHasAVX2)) {
5471 Scale2RowUp = ScaleRowUp2_Bilinear_Any_AVX2;
5472 }
5473 #endif
5474
5475 #if defined(HAS_SCALEROWUP2LINEAR_NEON)
5476 if (TestCpuFlag(kCpuHasNEON)) {
5477 Scale2RowUp = ScaleRowUp2_Bilinear_Any_NEON;
5478 }
5479 #endif
5480
5481 // alloc 4 lines temp
5482 const int kRowSize = (width + 31) & ~31;
5483 align_buffer_64(row, kRowSize * 4);
5484 uint8_t* temp_u_1 = row;
5485 uint8_t* temp_u_2 = row + kRowSize;
5486 uint8_t* temp_v_1 = row + kRowSize * 2;
5487 uint8_t* temp_v_2 = row + kRowSize * 3;
5488
5489 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5490 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5491 I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5492 dst_argb += dst_stride_argb;
5493 src_y += src_stride_y;
5494
5495 for (y = 0; y < height - 2; y += 2) {
5496 Scale2RowUp(src_u, src_stride_u, temp_u_1, kRowSize, width);
5497 Scale2RowUp(src_v, src_stride_v, temp_v_1, kRowSize, width);
5498 I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5499 dst_argb += dst_stride_argb;
5500 src_y += src_stride_y;
5501 I444ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
5502 dst_argb += dst_stride_argb;
5503 src_y += src_stride_y;
5504 src_u += src_stride_u;
5505 src_v += src_stride_v;
5506 }
5507
5508 if (!(height & 1)) {
5509 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5510 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5511 I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5512 }
5513
5514 free_aligned_buffer_64(row);
5515 return 0;
5516 }
5517
I422ToARGBMatrixLinear(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)5518 static int I422ToARGBMatrixLinear(const uint8_t* src_y,
5519 int src_stride_y,
5520 const uint8_t* src_u,
5521 int src_stride_u,
5522 const uint8_t* src_v,
5523 int src_stride_v,
5524 uint8_t* dst_argb,
5525 int dst_stride_argb,
5526 const struct YuvConstants* yuvconstants,
5527 int width,
5528 int height) {
5529 int y;
5530 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
5531 const uint8_t* v_buf, uint8_t* rgb_buf,
5532 const struct YuvConstants* yuvconstants, int width) =
5533 I444ToARGBRow_C;
5534 void (*ScaleRowUp)(const uint8_t* src_ptr, uint8_t* dst_ptr, int dst_width) =
5535 ScaleRowUp2_Linear_Any_C;
5536 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
5537 return -1;
5538 }
5539 // Negative height means invert the image.
5540 if (height < 0) {
5541 height = -height;
5542 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
5543 dst_stride_argb = -dst_stride_argb;
5544 }
5545 #if defined(HAS_I444TOARGBROW_SSSE3)
5546 if (TestCpuFlag(kCpuHasSSSE3)) {
5547 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
5548 if (IS_ALIGNED(width, 8)) {
5549 I444ToARGBRow = I444ToARGBRow_SSSE3;
5550 }
5551 }
5552 #endif
5553 #if defined(HAS_I444TOARGBROW_AVX2)
5554 if (TestCpuFlag(kCpuHasAVX2)) {
5555 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
5556 if (IS_ALIGNED(width, 16)) {
5557 I444ToARGBRow = I444ToARGBRow_AVX2;
5558 }
5559 }
5560 #endif
5561 #if defined(HAS_I444TOARGBROW_NEON)
5562 if (TestCpuFlag(kCpuHasNEON)) {
5563 I444ToARGBRow = I444ToARGBRow_Any_NEON;
5564 if (IS_ALIGNED(width, 8)) {
5565 I444ToARGBRow = I444ToARGBRow_NEON;
5566 }
5567 }
5568 #endif
5569 #if defined(HAS_I444TOARGBROW_MSA)
5570 if (TestCpuFlag(kCpuHasMSA)) {
5571 I444ToARGBRow = I444ToARGBRow_Any_MSA;
5572 if (IS_ALIGNED(width, 8)) {
5573 I444ToARGBRow = I444ToARGBRow_MSA;
5574 }
5575 }
5576 #endif
5577 #if defined(HAS_I444TOARGBROW_LASX)
5578 if (TestCpuFlag(kCpuHasLASX)) {
5579 I444ToARGBRow = I444ToARGBRow_Any_LASX;
5580 if (IS_ALIGNED(width, 32)) {
5581 I444ToARGBRow = I444ToARGBRow_LASX;
5582 }
5583 }
5584 #endif
5585 #if defined(HAS_SCALEROWUP2LINEAR_SSE2)
5586 if (TestCpuFlag(kCpuHasSSE2)) {
5587 ScaleRowUp = ScaleRowUp2_Linear_Any_SSE2;
5588 }
5589 #endif
5590 #if defined(HAS_SCALEROWUP2LINEAR_SSSE3)
5591 if (TestCpuFlag(kCpuHasSSSE3)) {
5592 ScaleRowUp = ScaleRowUp2_Linear_Any_SSSE3;
5593 }
5594 #endif
5595 #if defined(HAS_SCALEROWUP2LINEAR_AVX2)
5596 if (TestCpuFlag(kCpuHasAVX2)) {
5597 ScaleRowUp = ScaleRowUp2_Linear_Any_AVX2;
5598 }
5599 #endif
5600 #if defined(HAS_SCALEROWUP2LINEAR_NEON)
5601 if (TestCpuFlag(kCpuHasNEON)) {
5602 ScaleRowUp = ScaleRowUp2_Linear_Any_NEON;
5603 }
5604 #endif
5605
5606 // alloc 2 lines temp
5607 const int kRowSize = (width + 31) & ~31;
5608 align_buffer_64(row, kRowSize * 2);
5609 uint8_t* temp_u = row;
5610 uint8_t* temp_v = row + kRowSize;
5611
5612 for (y = 0; y < height; ++y) {
5613 ScaleRowUp(src_u, temp_u, width);
5614 ScaleRowUp(src_v, temp_v, width);
5615 I444ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
5616 dst_argb += dst_stride_argb;
5617 src_y += src_stride_y;
5618 src_u += src_stride_u;
5619 src_v += src_stride_v;
5620 }
5621
5622 free_aligned_buffer_64(row);
5623 return 0;
5624 }
5625
I010ToAR30MatrixBilinear(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)5626 static int I010ToAR30MatrixBilinear(const uint16_t* src_y,
5627 int src_stride_y,
5628 const uint16_t* src_u,
5629 int src_stride_u,
5630 const uint16_t* src_v,
5631 int src_stride_v,
5632 uint8_t* dst_ar30,
5633 int dst_stride_ar30,
5634 const struct YuvConstants* yuvconstants,
5635 int width,
5636 int height) {
5637 int y;
5638 void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
5639 const uint16_t* v_buf, uint8_t* rgb_buf,
5640 const struct YuvConstants* yuvconstants, int width) =
5641 I410ToAR30Row_C;
5642 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
5643 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
5644 ScaleRowUp2_Bilinear_16_Any_C;
5645 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
5646 return -1;
5647 }
5648 // Negative height means invert the image.
5649 if (height < 0) {
5650 height = -height;
5651 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
5652 dst_stride_ar30 = -dst_stride_ar30;
5653 }
5654 #if defined(HAS_I410TOAR30ROW_SSSE3)
5655 if (TestCpuFlag(kCpuHasSSSE3)) {
5656 I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
5657 if (IS_ALIGNED(width, 8)) {
5658 I410ToAR30Row = I410ToAR30Row_SSSE3;
5659 }
5660 }
5661 #endif
5662 #if defined(HAS_I410TOAR30ROW_AVX2)
5663 if (TestCpuFlag(kCpuHasAVX2)) {
5664 I410ToAR30Row = I410ToAR30Row_Any_AVX2;
5665 if (IS_ALIGNED(width, 16)) {
5666 I410ToAR30Row = I410ToAR30Row_AVX2;
5667 }
5668 }
5669 #endif
5670
5671 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
5672 if (TestCpuFlag(kCpuHasSSSE3)) {
5673 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_SSSE3;
5674 }
5675 #endif
5676
5677 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
5678 if (TestCpuFlag(kCpuHasAVX2)) {
5679 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_AVX2;
5680 }
5681 #endif
5682
5683 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
5684 if (TestCpuFlag(kCpuHasNEON)) {
5685 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_NEON;
5686 }
5687 #endif
5688
5689 // alloc 4 lines temp
5690 const int kRowSize = (width + 31) & ~31;
5691 align_buffer_64(row, kRowSize * 4 * sizeof(uint16_t));
5692 uint16_t* temp_u_1 = (uint16_t*)(row);
5693 uint16_t* temp_u_2 = (uint16_t*)(row) + kRowSize;
5694 uint16_t* temp_v_1 = (uint16_t*)(row) + kRowSize * 2;
5695 uint16_t* temp_v_2 = (uint16_t*)(row) + kRowSize * 3;
5696
5697 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5698 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5699 I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
5700 dst_ar30 += dst_stride_ar30;
5701 src_y += src_stride_y;
5702
5703 for (y = 0; y < height - 2; y += 2) {
5704 Scale2RowUp(src_u, src_stride_u, temp_u_1, kRowSize, width);
5705 Scale2RowUp(src_v, src_stride_v, temp_v_1, kRowSize, width);
5706 I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
5707 dst_ar30 += dst_stride_ar30;
5708 src_y += src_stride_y;
5709 I410ToAR30Row(src_y, temp_u_2, temp_v_2, dst_ar30, yuvconstants, width);
5710 dst_ar30 += dst_stride_ar30;
5711 src_y += src_stride_y;
5712 src_u += src_stride_u;
5713 src_v += src_stride_v;
5714 }
5715
5716 if (!(height & 1)) {
5717 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5718 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5719 I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
5720 }
5721
5722 free_aligned_buffer_64(row);
5723
5724 return 0;
5725 }
5726
I210ToAR30MatrixLinear(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)5727 static int I210ToAR30MatrixLinear(const uint16_t* src_y,
5728 int src_stride_y,
5729 const uint16_t* src_u,
5730 int src_stride_u,
5731 const uint16_t* src_v,
5732 int src_stride_v,
5733 uint8_t* dst_ar30,
5734 int dst_stride_ar30,
5735 const struct YuvConstants* yuvconstants,
5736 int width,
5737 int height) {
5738 int y;
5739 void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
5740 const uint16_t* v_buf, uint8_t* rgb_buf,
5741 const struct YuvConstants* yuvconstants, int width) =
5742 I410ToAR30Row_C;
5743 void (*ScaleRowUp)(const uint16_t* src_ptr, uint16_t* dst_ptr,
5744 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
5745 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
5746 return -1;
5747 }
5748 // Negative height means invert the image.
5749 if (height < 0) {
5750 height = -height;
5751 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
5752 dst_stride_ar30 = -dst_stride_ar30;
5753 }
5754 #if defined(HAS_I410TOAR30ROW_SSSE3)
5755 if (TestCpuFlag(kCpuHasSSSE3)) {
5756 I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
5757 if (IS_ALIGNED(width, 8)) {
5758 I410ToAR30Row = I410ToAR30Row_SSSE3;
5759 }
5760 }
5761 #endif
5762 #if defined(HAS_I410TOAR30ROW_AVX2)
5763 if (TestCpuFlag(kCpuHasAVX2)) {
5764 I410ToAR30Row = I410ToAR30Row_Any_AVX2;
5765 if (IS_ALIGNED(width, 16)) {
5766 I410ToAR30Row = I410ToAR30Row_AVX2;
5767 }
5768 }
5769 #endif
5770
5771 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
5772 if (TestCpuFlag(kCpuHasSSSE3)) {
5773 ScaleRowUp = ScaleRowUp2_Linear_12_Any_SSSE3;
5774 }
5775 #endif
5776 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
5777 if (TestCpuFlag(kCpuHasAVX2)) {
5778 ScaleRowUp = ScaleRowUp2_Linear_12_Any_AVX2;
5779 }
5780 #endif
5781 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
5782 if (TestCpuFlag(kCpuHasNEON)) {
5783 ScaleRowUp = ScaleRowUp2_Linear_12_Any_NEON;
5784 }
5785 #endif
5786
5787 // alloc 2 lines temp
5788 const int kRowSize = (width + 31) & ~31;
5789 align_buffer_64(row, kRowSize * 2 * sizeof(uint16_t));
5790 uint16_t* temp_u = (uint16_t*)(row);
5791 uint16_t* temp_v = (uint16_t*)(row) + kRowSize;
5792
5793 for (y = 0; y < height; ++y) {
5794 ScaleRowUp(src_u, temp_u, width);
5795 ScaleRowUp(src_v, temp_v, width);
5796 I410ToAR30Row(src_y, temp_u, temp_v, dst_ar30, yuvconstants, width);
5797 dst_ar30 += dst_stride_ar30;
5798 src_y += src_stride_y;
5799 src_u += src_stride_u;
5800 src_v += src_stride_v;
5801 }
5802 free_aligned_buffer_64(row);
5803 return 0;
5804 }
5805
I010ToARGBMatrixBilinear(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)5806 static int I010ToARGBMatrixBilinear(const uint16_t* src_y,
5807 int src_stride_y,
5808 const uint16_t* src_u,
5809 int src_stride_u,
5810 const uint16_t* src_v,
5811 int src_stride_v,
5812 uint8_t* dst_argb,
5813 int dst_stride_argb,
5814 const struct YuvConstants* yuvconstants,
5815 int width,
5816 int height) {
5817 int y;
5818 void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
5819 const uint16_t* v_buf, uint8_t* rgb_buf,
5820 const struct YuvConstants* yuvconstants, int width) =
5821 I410ToARGBRow_C;
5822 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
5823 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
5824 ScaleRowUp2_Bilinear_16_Any_C;
5825 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
5826 return -1;
5827 }
5828 // Negative height means invert the image.
5829 if (height < 0) {
5830 height = -height;
5831 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
5832 dst_stride_argb = -dst_stride_argb;
5833 }
5834 #if defined(HAS_I410TOARGBROW_SSSE3)
5835 if (TestCpuFlag(kCpuHasSSSE3)) {
5836 I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
5837 if (IS_ALIGNED(width, 8)) {
5838 I410ToARGBRow = I410ToARGBRow_SSSE3;
5839 }
5840 }
5841 #endif
5842 #if defined(HAS_I410TOARGBROW_AVX2)
5843 if (TestCpuFlag(kCpuHasAVX2)) {
5844 I410ToARGBRow = I410ToARGBRow_Any_AVX2;
5845 if (IS_ALIGNED(width, 16)) {
5846 I410ToARGBRow = I410ToARGBRow_AVX2;
5847 }
5848 }
5849 #endif
5850
5851 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
5852 if (TestCpuFlag(kCpuHasSSSE3)) {
5853 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_SSSE3;
5854 }
5855 #endif
5856
5857 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
5858 if (TestCpuFlag(kCpuHasAVX2)) {
5859 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_AVX2;
5860 }
5861 #endif
5862
5863 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
5864 if (TestCpuFlag(kCpuHasNEON)) {
5865 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_NEON;
5866 }
5867 #endif
5868
5869 // alloc 4 lines temp
5870 const int kRowSize = (width + 31) & ~31;
5871 align_buffer_64(row, kRowSize * 4 * sizeof(uint16_t));
5872 uint16_t* temp_u_1 = (uint16_t*)(row);
5873 uint16_t* temp_u_2 = (uint16_t*)(row) + kRowSize;
5874 uint16_t* temp_v_1 = (uint16_t*)(row) + kRowSize * 2;
5875 uint16_t* temp_v_2 = (uint16_t*)(row) + kRowSize * 3;
5876
5877 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5878 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5879 I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5880 dst_argb += dst_stride_argb;
5881 src_y += src_stride_y;
5882
5883 for (y = 0; y < height - 2; y += 2) {
5884 Scale2RowUp(src_u, src_stride_u, temp_u_1, kRowSize, width);
5885 Scale2RowUp(src_v, src_stride_v, temp_v_1, kRowSize, width);
5886 I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5887 dst_argb += dst_stride_argb;
5888 src_y += src_stride_y;
5889 I410ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
5890 dst_argb += dst_stride_argb;
5891 src_y += src_stride_y;
5892 src_u += src_stride_u;
5893 src_v += src_stride_v;
5894 }
5895
5896 if (!(height & 1)) {
5897 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
5898 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
5899 I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
5900 }
5901
5902 free_aligned_buffer_64(row);
5903 return 0;
5904 }
5905
I210ToARGBMatrixLinear(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)5906 static int I210ToARGBMatrixLinear(const uint16_t* src_y,
5907 int src_stride_y,
5908 const uint16_t* src_u,
5909 int src_stride_u,
5910 const uint16_t* src_v,
5911 int src_stride_v,
5912 uint8_t* dst_argb,
5913 int dst_stride_argb,
5914 const struct YuvConstants* yuvconstants,
5915 int width,
5916 int height) {
5917 int y;
5918 void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
5919 const uint16_t* v_buf, uint8_t* rgb_buf,
5920 const struct YuvConstants* yuvconstants, int width) =
5921 I410ToARGBRow_C;
5922 void (*ScaleRowUp)(const uint16_t* src_ptr, uint16_t* dst_ptr,
5923 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
5924 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
5925 return -1;
5926 }
5927 // Negative height means invert the image.
5928 if (height < 0) {
5929 height = -height;
5930 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
5931 dst_stride_argb = -dst_stride_argb;
5932 }
5933 #if defined(HAS_I410TOARGBROW_SSSE3)
5934 if (TestCpuFlag(kCpuHasSSSE3)) {
5935 I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
5936 if (IS_ALIGNED(width, 8)) {
5937 I410ToARGBRow = I410ToARGBRow_SSSE3;
5938 }
5939 }
5940 #endif
5941 #if defined(HAS_I410TOARGBROW_AVX2)
5942 if (TestCpuFlag(kCpuHasAVX2)) {
5943 I410ToARGBRow = I410ToARGBRow_Any_AVX2;
5944 if (IS_ALIGNED(width, 16)) {
5945 I410ToARGBRow = I410ToARGBRow_AVX2;
5946 }
5947 }
5948 #endif
5949
5950 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
5951 if (TestCpuFlag(kCpuHasSSSE3)) {
5952 ScaleRowUp = ScaleRowUp2_Linear_12_Any_SSSE3;
5953 }
5954 #endif
5955 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
5956 if (TestCpuFlag(kCpuHasAVX2)) {
5957 ScaleRowUp = ScaleRowUp2_Linear_12_Any_AVX2;
5958 }
5959 #endif
5960 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
5961 if (TestCpuFlag(kCpuHasNEON)) {
5962 ScaleRowUp = ScaleRowUp2_Linear_12_Any_NEON;
5963 }
5964 #endif
5965
5966 // alloc 2 lines temp
5967 const int kRowSize = (width + 31) & ~31;
5968 align_buffer_64(row, kRowSize * 2 * sizeof(uint16_t));
5969 uint16_t* temp_u = (uint16_t*)(row);
5970 uint16_t* temp_v = (uint16_t*)(row) + kRowSize;
5971
5972 for (y = 0; y < height; ++y) {
5973 ScaleRowUp(src_u, temp_u, width);
5974 ScaleRowUp(src_v, temp_v, width);
5975 I410ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
5976 dst_argb += dst_stride_argb;
5977 src_y += src_stride_y;
5978 src_u += src_stride_u;
5979 src_v += src_stride_v;
5980 }
5981
5982 free_aligned_buffer_64(row);
5983 return 0;
5984 }
5985
I420AlphaToARGBMatrixBilinear(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)5986 static int I420AlphaToARGBMatrixBilinear(
5987 const uint8_t* src_y,
5988 int src_stride_y,
5989 const uint8_t* src_u,
5990 int src_stride_u,
5991 const uint8_t* src_v,
5992 int src_stride_v,
5993 const uint8_t* src_a,
5994 int src_stride_a,
5995 uint8_t* dst_argb,
5996 int dst_stride_argb,
5997 const struct YuvConstants* yuvconstants,
5998 int width,
5999 int height,
6000 int attenuate) {
6001 int y;
6002 void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6003 const uint8_t* v_buf, const uint8_t* a_buf,
6004 uint8_t* dst_argb,
6005 const struct YuvConstants* yuvconstants,
6006 int width) = I444AlphaToARGBRow_C;
6007 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
6008 int width) = ARGBAttenuateRow_C;
6009 void (*Scale2RowUp)(const uint8_t* src_ptr, ptrdiff_t src_stride,
6010 uint8_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
6011 ScaleRowUp2_Bilinear_Any_C;
6012 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
6013 height == 0) {
6014 return -1;
6015 }
6016 // Negative height means invert the image.
6017 if (height < 0) {
6018 height = -height;
6019 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6020 dst_stride_argb = -dst_stride_argb;
6021 }
6022 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
6023 if (TestCpuFlag(kCpuHasSSSE3)) {
6024 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
6025 if (IS_ALIGNED(width, 8)) {
6026 I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
6027 }
6028 }
6029 #endif
6030 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
6031 if (TestCpuFlag(kCpuHasAVX2)) {
6032 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
6033 if (IS_ALIGNED(width, 16)) {
6034 I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
6035 }
6036 }
6037 #endif
6038 #if defined(HAS_I444ALPHATOARGBROW_NEON)
6039 if (TestCpuFlag(kCpuHasNEON)) {
6040 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
6041 if (IS_ALIGNED(width, 8)) {
6042 I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
6043 }
6044 }
6045 #endif
6046 #if defined(HAS_I444ALPHATOARGBROW_MSA)
6047 if (TestCpuFlag(kCpuHasMSA)) {
6048 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
6049 if (IS_ALIGNED(width, 8)) {
6050 I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
6051 }
6052 }
6053 #endif
6054 #if defined(HAS_I444ALPHATOARGBROW_LASX)
6055 if (TestCpuFlag(kCpuHasLASX)) {
6056 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
6057 if (IS_ALIGNED(width, 16)) {
6058 I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
6059 }
6060 }
6061 #endif
6062 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
6063 if (TestCpuFlag(kCpuHasSSSE3)) {
6064 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
6065 if (IS_ALIGNED(width, 4)) {
6066 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
6067 }
6068 }
6069 #endif
6070 #if defined(HAS_ARGBATTENUATEROW_AVX2)
6071 if (TestCpuFlag(kCpuHasAVX2)) {
6072 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
6073 if (IS_ALIGNED(width, 8)) {
6074 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
6075 }
6076 }
6077 #endif
6078 #if defined(HAS_ARGBATTENUATEROW_NEON)
6079 if (TestCpuFlag(kCpuHasNEON)) {
6080 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
6081 if (IS_ALIGNED(width, 8)) {
6082 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
6083 }
6084 }
6085 #endif
6086 #if defined(HAS_ARGBATTENUATEROW_MSA)
6087 if (TestCpuFlag(kCpuHasMSA)) {
6088 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
6089 if (IS_ALIGNED(width, 8)) {
6090 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
6091 }
6092 }
6093 #endif
6094 #if defined(HAS_SCALEROWUP2LINEAR_SSE2)
6095 if (TestCpuFlag(kCpuHasSSE2)) {
6096 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSE2;
6097 }
6098 #endif
6099
6100 #if defined(HAS_SCALEROWUP2LINEAR_SSSE3)
6101 if (TestCpuFlag(kCpuHasSSSE3)) {
6102 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSSE3;
6103 }
6104 #endif
6105
6106 #if defined(HAS_SCALEROWUP2LINEAR_AVX2)
6107 if (TestCpuFlag(kCpuHasAVX2)) {
6108 Scale2RowUp = ScaleRowUp2_Bilinear_Any_AVX2;
6109 }
6110 #endif
6111
6112 #if defined(HAS_SCALEROWUP2LINEAR_NEON)
6113 if (TestCpuFlag(kCpuHasNEON)) {
6114 Scale2RowUp = ScaleRowUp2_Bilinear_Any_NEON;
6115 }
6116 #endif
6117
6118 // alloc 4 lines temp
6119 const int kRowSize = (width + 31) & ~31;
6120 align_buffer_64(row, kRowSize * 4);
6121 uint8_t* temp_u_1 = row;
6122 uint8_t* temp_u_2 = row + kRowSize;
6123 uint8_t* temp_v_1 = row + kRowSize * 2;
6124 uint8_t* temp_v_2 = row + kRowSize * 3;
6125
6126 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
6127 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
6128 I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6129 width);
6130 if (attenuate) {
6131 ARGBAttenuateRow(dst_argb, dst_argb, width);
6132 }
6133 dst_argb += dst_stride_argb;
6134 src_y += src_stride_y;
6135 src_a += src_stride_a;
6136
6137 for (y = 0; y < height - 2; y += 2) {
6138 Scale2RowUp(src_u, src_stride_u, temp_u_1, kRowSize, width);
6139 Scale2RowUp(src_v, src_stride_v, temp_v_1, kRowSize, width);
6140 I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6141 width);
6142 if (attenuate) {
6143 ARGBAttenuateRow(dst_argb, dst_argb, width);
6144 }
6145 dst_argb += dst_stride_argb;
6146 src_y += src_stride_y;
6147 src_a += src_stride_a;
6148 I444AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
6149 width);
6150 if (attenuate) {
6151 ARGBAttenuateRow(dst_argb, dst_argb, width);
6152 }
6153 dst_argb += dst_stride_argb;
6154 src_y += src_stride_y;
6155 src_u += src_stride_u;
6156 src_v += src_stride_v;
6157 src_a += src_stride_a;
6158 }
6159
6160 if (!(height & 1)) {
6161 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
6162 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
6163 I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6164 width);
6165 if (attenuate) {
6166 ARGBAttenuateRow(dst_argb, dst_argb, width);
6167 }
6168 }
6169
6170 free_aligned_buffer_64(row);
6171 return 0;
6172 }
6173
I422AlphaToARGBMatrixLinear(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)6174 static int I422AlphaToARGBMatrixLinear(const uint8_t* src_y,
6175 int src_stride_y,
6176 const uint8_t* src_u,
6177 int src_stride_u,
6178 const uint8_t* src_v,
6179 int src_stride_v,
6180 const uint8_t* src_a,
6181 int src_stride_a,
6182 uint8_t* dst_argb,
6183 int dst_stride_argb,
6184 const struct YuvConstants* yuvconstants,
6185 int width,
6186 int height,
6187 int attenuate) {
6188 int y;
6189 void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6190 const uint8_t* v_buf, const uint8_t* a_buf,
6191 uint8_t* dst_argb,
6192 const struct YuvConstants* yuvconstants,
6193 int width) = I444AlphaToARGBRow_C;
6194 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
6195 int width) = ARGBAttenuateRow_C;
6196 void (*ScaleRowUp)(const uint8_t* src_ptr, uint8_t* dst_ptr, int dst_width) =
6197 ScaleRowUp2_Linear_Any_C;
6198 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
6199 height == 0) {
6200 return -1;
6201 }
6202 // Negative height means invert the image.
6203 if (height < 0) {
6204 height = -height;
6205 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6206 dst_stride_argb = -dst_stride_argb;
6207 }
6208 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
6209 if (TestCpuFlag(kCpuHasSSSE3)) {
6210 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
6211 if (IS_ALIGNED(width, 8)) {
6212 I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
6213 }
6214 }
6215 #endif
6216 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
6217 if (TestCpuFlag(kCpuHasAVX2)) {
6218 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
6219 if (IS_ALIGNED(width, 16)) {
6220 I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
6221 }
6222 }
6223 #endif
6224 #if defined(HAS_I444ALPHATOARGBROW_NEON)
6225 if (TestCpuFlag(kCpuHasNEON)) {
6226 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
6227 if (IS_ALIGNED(width, 8)) {
6228 I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
6229 }
6230 }
6231 #endif
6232 #if defined(HAS_I444ALPHATOARGBROW_MSA)
6233 if (TestCpuFlag(kCpuHasMSA)) {
6234 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
6235 if (IS_ALIGNED(width, 8)) {
6236 I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
6237 }
6238 }
6239 #endif
6240 #if defined(HAS_I444ALPHATOARGBROW_LASX)
6241 if (TestCpuFlag(kCpuHasLASX)) {
6242 I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
6243 if (IS_ALIGNED(width, 16)) {
6244 I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
6245 }
6246 }
6247 #endif
6248 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
6249 if (TestCpuFlag(kCpuHasSSSE3)) {
6250 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
6251 if (IS_ALIGNED(width, 4)) {
6252 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
6253 }
6254 }
6255 #endif
6256 #if defined(HAS_ARGBATTENUATEROW_AVX2)
6257 if (TestCpuFlag(kCpuHasAVX2)) {
6258 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
6259 if (IS_ALIGNED(width, 8)) {
6260 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
6261 }
6262 }
6263 #endif
6264 #if defined(HAS_ARGBATTENUATEROW_NEON)
6265 if (TestCpuFlag(kCpuHasNEON)) {
6266 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
6267 if (IS_ALIGNED(width, 8)) {
6268 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
6269 }
6270 }
6271 #endif
6272 #if defined(HAS_ARGBATTENUATEROW_MSA)
6273 if (TestCpuFlag(kCpuHasMSA)) {
6274 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
6275 if (IS_ALIGNED(width, 8)) {
6276 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
6277 }
6278 }
6279 #endif
6280 #if defined(HAS_SCALEROWUP2LINEAR_SSE2)
6281 if (TestCpuFlag(kCpuHasSSE2)) {
6282 ScaleRowUp = ScaleRowUp2_Linear_Any_SSE2;
6283 }
6284 #endif
6285 #if defined(HAS_SCALEROWUP2LINEAR_SSSE3)
6286 if (TestCpuFlag(kCpuHasSSSE3)) {
6287 ScaleRowUp = ScaleRowUp2_Linear_Any_SSSE3;
6288 }
6289 #endif
6290 #if defined(HAS_SCALEROWUP2LINEAR_AVX2)
6291 if (TestCpuFlag(kCpuHasAVX2)) {
6292 ScaleRowUp = ScaleRowUp2_Linear_Any_AVX2;
6293 }
6294 #endif
6295 #if defined(HAS_SCALEROWUP2LINEAR_NEON)
6296 if (TestCpuFlag(kCpuHasNEON)) {
6297 ScaleRowUp = ScaleRowUp2_Linear_Any_NEON;
6298 }
6299 #endif
6300
6301 // alloc 2 lines temp
6302 const int kRowSize = (width + 31) & ~31;
6303 align_buffer_64(row, kRowSize * 2);
6304 uint8_t* temp_u = row;
6305 uint8_t* temp_v = row + kRowSize;
6306
6307 for (y = 0; y < height; ++y) {
6308 ScaleRowUp(src_u, temp_u, width);
6309 ScaleRowUp(src_v, temp_v, width);
6310 I444AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
6311 width);
6312 if (attenuate) {
6313 ARGBAttenuateRow(dst_argb, dst_argb, width);
6314 }
6315 dst_argb += dst_stride_argb;
6316 src_a += src_stride_a;
6317 src_y += src_stride_y;
6318 src_u += src_stride_u;
6319 src_v += src_stride_v;
6320 }
6321
6322 free_aligned_buffer_64(row);
6323 return 0;
6324 }
6325
I010AlphaToARGBMatrixBilinear(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,const uint16_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)6326 static int I010AlphaToARGBMatrixBilinear(
6327 const uint16_t* src_y,
6328 int src_stride_y,
6329 const uint16_t* src_u,
6330 int src_stride_u,
6331 const uint16_t* src_v,
6332 int src_stride_v,
6333 const uint16_t* src_a,
6334 int src_stride_a,
6335 uint8_t* dst_argb,
6336 int dst_stride_argb,
6337 const struct YuvConstants* yuvconstants,
6338 int width,
6339 int height,
6340 int attenuate) {
6341 int y;
6342 void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
6343 const uint16_t* v_buf, const uint16_t* a_buf,
6344 uint8_t* dst_argb,
6345 const struct YuvConstants* yuvconstants,
6346 int width) = I410AlphaToARGBRow_C;
6347 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
6348 int width) = ARGBAttenuateRow_C;
6349 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
6350 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
6351 ScaleRowUp2_Bilinear_16_Any_C;
6352 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
6353 height == 0) {
6354 return -1;
6355 }
6356 // Negative height means invert the image.
6357 if (height < 0) {
6358 height = -height;
6359 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6360 dst_stride_argb = -dst_stride_argb;
6361 }
6362 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
6363 if (TestCpuFlag(kCpuHasSSSE3)) {
6364 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
6365 if (IS_ALIGNED(width, 8)) {
6366 I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
6367 }
6368 }
6369 #endif
6370 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
6371 if (TestCpuFlag(kCpuHasAVX2)) {
6372 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
6373 if (IS_ALIGNED(width, 16)) {
6374 I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
6375 }
6376 }
6377 #endif
6378 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
6379 if (TestCpuFlag(kCpuHasSSSE3)) {
6380 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
6381 if (IS_ALIGNED(width, 4)) {
6382 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
6383 }
6384 }
6385 #endif
6386 #if defined(HAS_ARGBATTENUATEROW_AVX2)
6387 if (TestCpuFlag(kCpuHasAVX2)) {
6388 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
6389 if (IS_ALIGNED(width, 8)) {
6390 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
6391 }
6392 }
6393 #endif
6394 #if defined(HAS_ARGBATTENUATEROW_NEON)
6395 if (TestCpuFlag(kCpuHasNEON)) {
6396 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
6397 if (IS_ALIGNED(width, 8)) {
6398 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
6399 }
6400 }
6401 #endif
6402 #if defined(HAS_ARGBATTENUATEROW_MSA)
6403 if (TestCpuFlag(kCpuHasMSA)) {
6404 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
6405 if (IS_ALIGNED(width, 8)) {
6406 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
6407 }
6408 }
6409 #endif
6410
6411 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
6412 if (TestCpuFlag(kCpuHasSSSE3)) {
6413 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_SSSE3;
6414 }
6415 #endif
6416
6417 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
6418 if (TestCpuFlag(kCpuHasAVX2)) {
6419 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_AVX2;
6420 }
6421 #endif
6422
6423 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
6424 if (TestCpuFlag(kCpuHasNEON)) {
6425 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_NEON;
6426 }
6427 #endif
6428
6429 // alloc 4 lines temp
6430 const int kRowSize = (width + 31) & ~31;
6431 align_buffer_64(row, kRowSize * 4 * sizeof(uint16_t));
6432 uint16_t* temp_u_1 = (uint16_t*)(row);
6433 uint16_t* temp_u_2 = (uint16_t*)(row) + kRowSize;
6434 uint16_t* temp_v_1 = (uint16_t*)(row) + kRowSize * 2;
6435 uint16_t* temp_v_2 = (uint16_t*)(row) + kRowSize * 3;
6436
6437 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
6438 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
6439 I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6440 width);
6441 if (attenuate) {
6442 ARGBAttenuateRow(dst_argb, dst_argb, width);
6443 }
6444 dst_argb += dst_stride_argb;
6445 src_y += src_stride_y;
6446 src_a += src_stride_a;
6447
6448 for (y = 0; y < height - 2; y += 2) {
6449 Scale2RowUp(src_u, src_stride_u, temp_u_1, kRowSize, width);
6450 Scale2RowUp(src_v, src_stride_v, temp_v_1, kRowSize, width);
6451 I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6452 width);
6453 if (attenuate) {
6454 ARGBAttenuateRow(dst_argb, dst_argb, width);
6455 }
6456 dst_argb += dst_stride_argb;
6457 src_y += src_stride_y;
6458 src_a += src_stride_a;
6459 I410AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
6460 width);
6461 if (attenuate) {
6462 ARGBAttenuateRow(dst_argb, dst_argb, width);
6463 }
6464 dst_argb += dst_stride_argb;
6465 src_y += src_stride_y;
6466 src_a += src_stride_a;
6467 src_u += src_stride_u;
6468 src_v += src_stride_v;
6469 }
6470
6471 if (!(height & 1)) {
6472 Scale2RowUp(src_u, 0, temp_u_1, kRowSize, width);
6473 Scale2RowUp(src_v, 0, temp_v_1, kRowSize, width);
6474 I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
6475 width);
6476 if (attenuate) {
6477 ARGBAttenuateRow(dst_argb, dst_argb, width);
6478 }
6479 }
6480
6481 free_aligned_buffer_64(row);
6482 return 0;
6483 }
6484
I210AlphaToARGBMatrixLinear(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,const uint16_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)6485 static int I210AlphaToARGBMatrixLinear(const uint16_t* src_y,
6486 int src_stride_y,
6487 const uint16_t* src_u,
6488 int src_stride_u,
6489 const uint16_t* src_v,
6490 int src_stride_v,
6491 const uint16_t* src_a,
6492 int src_stride_a,
6493 uint8_t* dst_argb,
6494 int dst_stride_argb,
6495 const struct YuvConstants* yuvconstants,
6496 int width,
6497 int height,
6498 int attenuate) {
6499 int y;
6500 void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
6501 const uint16_t* v_buf, const uint16_t* a_buf,
6502 uint8_t* dst_argb,
6503 const struct YuvConstants* yuvconstants,
6504 int width) = I410AlphaToARGBRow_C;
6505 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
6506 int width) = ARGBAttenuateRow_C;
6507 void (*ScaleRowUp)(const uint16_t* src_ptr, uint16_t* dst_ptr,
6508 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
6509 if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
6510 height == 0) {
6511 return -1;
6512 }
6513 // Negative height means invert the image.
6514 if (height < 0) {
6515 height = -height;
6516 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6517 dst_stride_argb = -dst_stride_argb;
6518 }
6519 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
6520 if (TestCpuFlag(kCpuHasSSSE3)) {
6521 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
6522 if (IS_ALIGNED(width, 8)) {
6523 I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
6524 }
6525 }
6526 #endif
6527 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
6528 if (TestCpuFlag(kCpuHasAVX2)) {
6529 I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
6530 if (IS_ALIGNED(width, 16)) {
6531 I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
6532 }
6533 }
6534 #endif
6535 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
6536 if (TestCpuFlag(kCpuHasSSSE3)) {
6537 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
6538 if (IS_ALIGNED(width, 4)) {
6539 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
6540 }
6541 }
6542 #endif
6543 #if defined(HAS_ARGBATTENUATEROW_AVX2)
6544 if (TestCpuFlag(kCpuHasAVX2)) {
6545 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
6546 if (IS_ALIGNED(width, 8)) {
6547 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
6548 }
6549 }
6550 #endif
6551 #if defined(HAS_ARGBATTENUATEROW_NEON)
6552 if (TestCpuFlag(kCpuHasNEON)) {
6553 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
6554 if (IS_ALIGNED(width, 8)) {
6555 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
6556 }
6557 }
6558 #endif
6559 #if defined(HAS_ARGBATTENUATEROW_MSA)
6560 if (TestCpuFlag(kCpuHasMSA)) {
6561 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
6562 if (IS_ALIGNED(width, 8)) {
6563 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
6564 }
6565 }
6566 #endif
6567
6568 #if defined(HAS_SCALEROWUP2LINEAR_12_SSSE3)
6569 if (TestCpuFlag(kCpuHasSSSE3)) {
6570 ScaleRowUp = ScaleRowUp2_Linear_12_Any_SSSE3;
6571 }
6572 #endif
6573 #if defined(HAS_SCALEROWUP2LINEAR_12_AVX2)
6574 if (TestCpuFlag(kCpuHasAVX2)) {
6575 ScaleRowUp = ScaleRowUp2_Linear_12_Any_AVX2;
6576 }
6577 #endif
6578 #if defined(HAS_SCALEROWUP2LINEAR_12_NEON)
6579 if (TestCpuFlag(kCpuHasNEON)) {
6580 ScaleRowUp = ScaleRowUp2_Linear_12_Any_NEON;
6581 }
6582 #endif
6583
6584 // alloc 2 lines temp
6585 const int kRowSize = (width + 31) & ~31;
6586 align_buffer_64(row, kRowSize * 2 * sizeof(uint16_t));
6587 uint16_t* temp_u = (uint16_t*)(row);
6588 uint16_t* temp_v = (uint16_t*)(row) + kRowSize;
6589
6590 for (y = 0; y < height; ++y) {
6591 ScaleRowUp(src_u, temp_u, width);
6592 ScaleRowUp(src_v, temp_v, width);
6593 I410AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
6594 width);
6595 if (attenuate) {
6596 ARGBAttenuateRow(dst_argb, dst_argb, width);
6597 }
6598 dst_argb += dst_stride_argb;
6599 src_a += src_stride_a;
6600 src_y += src_stride_y;
6601 src_u += src_stride_u;
6602 src_v += src_stride_v;
6603 }
6604 free_aligned_buffer_64(row);
6605 return 0;
6606 }
6607
P010ToARGBMatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6608 static int P010ToARGBMatrixBilinear(const uint16_t* src_y,
6609 int src_stride_y,
6610 const uint16_t* src_uv,
6611 int src_stride_uv,
6612 uint8_t* dst_argb,
6613 int dst_stride_argb,
6614 const struct YuvConstants* yuvconstants,
6615 int width,
6616 int height) {
6617 int y;
6618 void (*P410ToARGBRow)(
6619 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
6620 const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
6621 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
6622 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
6623 ScaleUVRowUp2_Bilinear_16_Any_C;
6624 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
6625 return -1;
6626 }
6627 // Negative height means invert the image.
6628 if (height < 0) {
6629 height = -height;
6630 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6631 dst_stride_argb = -dst_stride_argb;
6632 }
6633 #if defined(HAS_P410TOARGBROW_SSSE3)
6634 if (TestCpuFlag(kCpuHasSSSE3)) {
6635 P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
6636 if (IS_ALIGNED(width, 8)) {
6637 P410ToARGBRow = P410ToARGBRow_SSSE3;
6638 }
6639 }
6640 #endif
6641 #if defined(HAS_P410TOARGBROW_AVX2)
6642 if (TestCpuFlag(kCpuHasAVX2)) {
6643 P410ToARGBRow = P410ToARGBRow_Any_AVX2;
6644 if (IS_ALIGNED(width, 16)) {
6645 P410ToARGBRow = P410ToARGBRow_AVX2;
6646 }
6647 }
6648 #endif
6649
6650 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_SSE41
6651 if (TestCpuFlag(kCpuHasSSE41)) {
6652 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
6653 }
6654 #endif
6655
6656 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_AVX2
6657 if (TestCpuFlag(kCpuHasAVX2)) {
6658 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
6659 }
6660 #endif
6661
6662 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_NEON
6663 if (TestCpuFlag(kCpuHasNEON)) {
6664 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_NEON;
6665 }
6666 #endif
6667
6668 // alloc 2 lines temp
6669 const int kRowSize = (2 * width + 31) & ~31;
6670 align_buffer_64(row, kRowSize * 2 * sizeof(uint16_t));
6671 uint16_t* temp_uv_1 = (uint16_t*)(row);
6672 uint16_t* temp_uv_2 = (uint16_t*)(row) + kRowSize;
6673
6674 Scale2RowUp(src_uv, 0, temp_uv_1, kRowSize, width);
6675 P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
6676 dst_argb += dst_stride_argb;
6677 src_y += src_stride_y;
6678
6679 for (y = 0; y < height - 2; y += 2) {
6680 Scale2RowUp(src_uv, src_stride_uv, temp_uv_1, kRowSize, width);
6681 P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
6682 dst_argb += dst_stride_argb;
6683 src_y += src_stride_y;
6684 P410ToARGBRow(src_y, temp_uv_2, dst_argb, yuvconstants, width);
6685 dst_argb += dst_stride_argb;
6686 src_y += src_stride_y;
6687 src_uv += src_stride_uv;
6688 }
6689
6690 if (!(height & 1)) {
6691 Scale2RowUp(src_uv, 0, temp_uv_1, kRowSize, width);
6692 P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
6693 }
6694
6695 free_aligned_buffer_64(row);
6696 return 0;
6697 }
6698
P210ToARGBMatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6699 static int P210ToARGBMatrixLinear(const uint16_t* src_y,
6700 int src_stride_y,
6701 const uint16_t* src_uv,
6702 int src_stride_uv,
6703 uint8_t* dst_argb,
6704 int dst_stride_argb,
6705 const struct YuvConstants* yuvconstants,
6706 int width,
6707 int height) {
6708 int y;
6709 void (*P410ToARGBRow)(
6710 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
6711 const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
6712 void (*ScaleRowUp)(const uint16_t* src_uv, uint16_t* dst_uv, int dst_width) =
6713 ScaleUVRowUp2_Linear_16_Any_C;
6714 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
6715 return -1;
6716 }
6717 // Negative height means invert the image.
6718 if (height < 0) {
6719 height = -height;
6720 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6721 dst_stride_argb = -dst_stride_argb;
6722 }
6723 #if defined(HAS_P410TOARGBROW_SSSE3)
6724 if (TestCpuFlag(kCpuHasSSSE3)) {
6725 P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
6726 if (IS_ALIGNED(width, 8)) {
6727 P410ToARGBRow = P410ToARGBRow_SSSE3;
6728 }
6729 }
6730 #endif
6731 #if defined(HAS_P410TOARGBROW_AVX2)
6732 if (TestCpuFlag(kCpuHasAVX2)) {
6733 P410ToARGBRow = P410ToARGBRow_Any_AVX2;
6734 if (IS_ALIGNED(width, 16)) {
6735 P410ToARGBRow = P410ToARGBRow_AVX2;
6736 }
6737 }
6738 #endif
6739
6740 #ifdef HAS_SCALEUVROWUP2LINEAR_16_SSE41
6741 if (TestCpuFlag(kCpuHasSSE41)) {
6742 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_SSE41;
6743 }
6744 #endif
6745
6746 #ifdef HAS_SCALEUVROWUP2LINEAR_16_AVX2
6747 if (TestCpuFlag(kCpuHasAVX2)) {
6748 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_AVX2;
6749 }
6750 #endif
6751
6752 #ifdef HAS_SCALEUVROWUP2LINEAR_16_NEON
6753 if (TestCpuFlag(kCpuHasNEON)) {
6754 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_NEON;
6755 }
6756 #endif
6757
6758 const int kRowSize = (2 * width + 31) & ~31;
6759 align_buffer_64(row, kRowSize * sizeof(uint16_t));
6760 uint16_t* temp_uv = (uint16_t*)(row);
6761
6762 for (y = 0; y < height; ++y) {
6763 ScaleRowUp(src_uv, temp_uv, width);
6764 P410ToARGBRow(src_y, temp_uv, dst_argb, yuvconstants, width);
6765 dst_argb += dst_stride_argb;
6766 src_y += src_stride_y;
6767 src_uv += src_stride_uv;
6768 }
6769
6770 free_aligned_buffer_64(row);
6771 return 0;
6772 }
6773
P010ToAR30MatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)6774 static int P010ToAR30MatrixBilinear(const uint16_t* src_y,
6775 int src_stride_y,
6776 const uint16_t* src_uv,
6777 int src_stride_uv,
6778 uint8_t* dst_ar30,
6779 int dst_stride_ar30,
6780 const struct YuvConstants* yuvconstants,
6781 int width,
6782 int height) {
6783 int y;
6784 void (*P410ToAR30Row)(
6785 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
6786 const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
6787 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
6788 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
6789 ScaleUVRowUp2_Bilinear_16_Any_C;
6790 if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
6791 return -1;
6792 }
6793 // Negative height means invert the image.
6794 if (height < 0) {
6795 height = -height;
6796 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6797 dst_stride_ar30 = -dst_stride_ar30;
6798 }
6799 #if defined(HAS_P410TOAR30ROW_SSSE3)
6800 if (TestCpuFlag(kCpuHasSSSE3)) {
6801 P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
6802 if (IS_ALIGNED(width, 8)) {
6803 P410ToAR30Row = P410ToAR30Row_SSSE3;
6804 }
6805 }
6806 #endif
6807 #if defined(HAS_P410TOAR30ROW_AVX2)
6808 if (TestCpuFlag(kCpuHasAVX2)) {
6809 P410ToAR30Row = P410ToAR30Row_Any_AVX2;
6810 if (IS_ALIGNED(width, 16)) {
6811 P410ToAR30Row = P410ToAR30Row_AVX2;
6812 }
6813 }
6814 #endif
6815
6816 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_SSE41
6817 if (TestCpuFlag(kCpuHasSSE41)) {
6818 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
6819 }
6820 #endif
6821
6822 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_AVX2
6823 if (TestCpuFlag(kCpuHasAVX2)) {
6824 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
6825 }
6826 #endif
6827
6828 #ifdef HAS_SCALEUVROWUP2BILINEAR_16_NEON
6829 if (TestCpuFlag(kCpuHasNEON)) {
6830 Scale2RowUp = ScaleUVRowUp2_Bilinear_16_Any_NEON;
6831 }
6832 #endif
6833
6834 // alloc 2 lines temp
6835 const int kRowSize = (2 * width + 31) & ~31;
6836 align_buffer_64(row, kRowSize * 2 * sizeof(uint16_t));
6837 uint16_t* temp_uv_1 = (uint16_t*)(row);
6838 uint16_t* temp_uv_2 = (uint16_t*)(row) + kRowSize;
6839
6840 Scale2RowUp(src_uv, 0, temp_uv_1, kRowSize, width);
6841 P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
6842 dst_ar30 += dst_stride_ar30;
6843 src_y += src_stride_y;
6844
6845 for (y = 0; y < height - 2; y += 2) {
6846 Scale2RowUp(src_uv, src_stride_uv, temp_uv_1, kRowSize, width);
6847 P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
6848 dst_ar30 += dst_stride_ar30;
6849 src_y += src_stride_y;
6850 P410ToAR30Row(src_y, temp_uv_2, dst_ar30, yuvconstants, width);
6851 dst_ar30 += dst_stride_ar30;
6852 src_y += src_stride_y;
6853 src_uv += src_stride_uv;
6854 }
6855
6856 if (!(height & 1)) {
6857 Scale2RowUp(src_uv, 0, temp_uv_1, kRowSize, width);
6858 P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
6859 }
6860
6861 free_aligned_buffer_64(row);
6862 return 0;
6863 }
6864
P210ToAR30MatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)6865 static int P210ToAR30MatrixLinear(const uint16_t* src_y,
6866 int src_stride_y,
6867 const uint16_t* src_uv,
6868 int src_stride_uv,
6869 uint8_t* dst_ar30,
6870 int dst_stride_ar30,
6871 const struct YuvConstants* yuvconstants,
6872 int width,
6873 int height) {
6874 int y;
6875 void (*P410ToAR30Row)(
6876 const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
6877 const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
6878 void (*ScaleRowUp)(const uint16_t* src_uv, uint16_t* dst_uv, int dst_width) =
6879 ScaleUVRowUp2_Linear_16_Any_C;
6880 if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
6881 return -1;
6882 }
6883 // Negative height means invert the image.
6884 if (height < 0) {
6885 height = -height;
6886 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6887 dst_stride_ar30 = -dst_stride_ar30;
6888 }
6889 #if defined(HAS_P410TOAR30ROW_SSSE3)
6890 if (TestCpuFlag(kCpuHasSSSE3)) {
6891 P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
6892 if (IS_ALIGNED(width, 8)) {
6893 P410ToAR30Row = P410ToAR30Row_SSSE3;
6894 }
6895 }
6896 #endif
6897 #if defined(HAS_P410TOAR30ROW_AVX2)
6898 if (TestCpuFlag(kCpuHasAVX2)) {
6899 P410ToAR30Row = P410ToAR30Row_Any_AVX2;
6900 if (IS_ALIGNED(width, 16)) {
6901 P410ToAR30Row = P410ToAR30Row_AVX2;
6902 }
6903 }
6904 #endif
6905
6906 #ifdef HAS_SCALEUVROWUP2LINEAR_16_SSE41
6907 if (TestCpuFlag(kCpuHasSSE41)) {
6908 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_SSE41;
6909 }
6910 #endif
6911
6912 #ifdef HAS_SCALEUVROWUP2LINEAR_16_AVX2
6913 if (TestCpuFlag(kCpuHasAVX2)) {
6914 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_AVX2;
6915 }
6916 #endif
6917
6918 #ifdef HAS_SCALEUVROWUP2LINEAR_16_NEON
6919 if (TestCpuFlag(kCpuHasNEON)) {
6920 ScaleRowUp = ScaleUVRowUp2_Linear_16_Any_NEON;
6921 }
6922 #endif
6923
6924 const int kRowSize = (2 * width + 31) & ~31;
6925 align_buffer_64(row, kRowSize * sizeof(uint16_t));
6926 uint16_t* temp_uv = (uint16_t*)(row);
6927
6928 for (y = 0; y < height; ++y) {
6929 ScaleRowUp(src_uv, temp_uv, width);
6930 P410ToAR30Row(src_y, temp_uv, dst_ar30, yuvconstants, width);
6931 dst_ar30 += dst_stride_ar30;
6932 src_y += src_stride_y;
6933 src_uv += src_stride_uv;
6934 }
6935
6936 free_aligned_buffer_64(row);
6937 return 0;
6938 }
6939
6940 LIBYUV_API
I420ToARGBMatrixFilter(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,enum FilterMode filter)6941 int I420ToARGBMatrixFilter(const uint8_t* src_y,
6942 int src_stride_y,
6943 const uint8_t* src_u,
6944 int src_stride_u,
6945 const uint8_t* src_v,
6946 int src_stride_v,
6947 uint8_t* dst_argb,
6948 int dst_stride_argb,
6949 const struct YuvConstants* yuvconstants,
6950 int width,
6951 int height,
6952 enum FilterMode filter) {
6953 switch (filter) {
6954 case kFilterNone:
6955 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6956 src_stride_v, dst_argb, dst_stride_argb,
6957 yuvconstants, width, height);
6958 case kFilterBilinear:
6959 case kFilterBox:
6960 return I420ToARGBMatrixBilinear(
6961 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
6962 dst_argb, dst_stride_argb, yuvconstants, width, height);
6963 case kFilterLinear:
6964 // Actually we can do this, but probably there's no usage.
6965 return -1;
6966 }
6967
6968 return -1;
6969 }
6970
6971 LIBYUV_API
I422ToARGBMatrixFilter(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,enum FilterMode filter)6972 int I422ToARGBMatrixFilter(const uint8_t* src_y,
6973 int src_stride_y,
6974 const uint8_t* src_u,
6975 int src_stride_u,
6976 const uint8_t* src_v,
6977 int src_stride_v,
6978 uint8_t* dst_argb,
6979 int dst_stride_argb,
6980 const struct YuvConstants* yuvconstants,
6981 int width,
6982 int height,
6983 enum FilterMode filter) {
6984 switch (filter) {
6985 case kFilterNone:
6986 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6987 src_stride_v, dst_argb, dst_stride_argb,
6988 yuvconstants, width, height);
6989 case kFilterBilinear:
6990 case kFilterBox:
6991 case kFilterLinear:
6992 return I422ToARGBMatrixLinear(
6993 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
6994 dst_argb, dst_stride_argb, yuvconstants, width, height);
6995 }
6996
6997 return -1;
6998 }
6999
7000 LIBYUV_API
I010ToAR30MatrixFilter(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,enum FilterMode filter)7001 int I010ToAR30MatrixFilter(const uint16_t* src_y,
7002 int src_stride_y,
7003 const uint16_t* src_u,
7004 int src_stride_u,
7005 const uint16_t* src_v,
7006 int src_stride_v,
7007 uint8_t* dst_ar30,
7008 int dst_stride_ar30,
7009 const struct YuvConstants* yuvconstants,
7010 int width,
7011 int height,
7012 enum FilterMode filter) {
7013 switch (filter) {
7014 case kFilterNone:
7015 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
7016 src_stride_v, dst_ar30, dst_stride_ar30,
7017 yuvconstants, width, height);
7018 case kFilterBilinear:
7019 case kFilterBox:
7020 return I010ToAR30MatrixBilinear(
7021 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
7022 dst_ar30, dst_stride_ar30, yuvconstants, width, height);
7023 case kFilterLinear:
7024 return -1;
7025 }
7026
7027 return -1;
7028 }
7029
7030 LIBYUV_API
I210ToAR30MatrixFilter(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,enum FilterMode filter)7031 int I210ToAR30MatrixFilter(const uint16_t* src_y,
7032 int src_stride_y,
7033 const uint16_t* src_u,
7034 int src_stride_u,
7035 const uint16_t* src_v,
7036 int src_stride_v,
7037 uint8_t* dst_ar30,
7038 int dst_stride_ar30,
7039 const struct YuvConstants* yuvconstants,
7040 int width,
7041 int height,
7042 enum FilterMode filter) {
7043 switch (filter) {
7044 case kFilterNone:
7045 return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
7046 src_stride_v, dst_ar30, dst_stride_ar30,
7047 yuvconstants, width, height);
7048 case kFilterBilinear:
7049 case kFilterBox:
7050 case kFilterLinear:
7051 return I210ToAR30MatrixLinear(
7052 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
7053 dst_ar30, dst_stride_ar30, yuvconstants, width, height);
7054 }
7055
7056 return -1;
7057 }
7058
7059 LIBYUV_API
I010ToARGBMatrixFilter(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,enum FilterMode filter)7060 int I010ToARGBMatrixFilter(const uint16_t* src_y,
7061 int src_stride_y,
7062 const uint16_t* src_u,
7063 int src_stride_u,
7064 const uint16_t* src_v,
7065 int src_stride_v,
7066 uint8_t* dst_argb,
7067 int dst_stride_argb,
7068 const struct YuvConstants* yuvconstants,
7069 int width,
7070 int height,
7071 enum FilterMode filter) {
7072 switch (filter) {
7073 case kFilterNone:
7074 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
7075 src_stride_v, dst_argb, dst_stride_argb,
7076 yuvconstants, width, height);
7077 case kFilterBilinear:
7078 case kFilterBox:
7079 return I010ToARGBMatrixBilinear(
7080 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
7081 dst_argb, dst_stride_argb, yuvconstants, width, height);
7082 case kFilterLinear:
7083 return -1;
7084 }
7085
7086 return -1;
7087 }
7088
7089 LIBYUV_API
I210ToARGBMatrixFilter(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,enum FilterMode filter)7090 int I210ToARGBMatrixFilter(const uint16_t* src_y,
7091 int src_stride_y,
7092 const uint16_t* src_u,
7093 int src_stride_u,
7094 const uint16_t* src_v,
7095 int src_stride_v,
7096 uint8_t* dst_argb,
7097 int dst_stride_argb,
7098 const struct YuvConstants* yuvconstants,
7099 int width,
7100 int height,
7101 enum FilterMode filter) {
7102 switch (filter) {
7103 case kFilterNone:
7104 return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
7105 src_stride_v, dst_argb, dst_stride_argb,
7106 yuvconstants, width, height);
7107 case kFilterBilinear:
7108 case kFilterBox:
7109 case kFilterLinear:
7110 return I210ToARGBMatrixLinear(
7111 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
7112 dst_argb, dst_stride_argb, yuvconstants, width, height);
7113 }
7114
7115 return -1;
7116 }
7117
7118 LIBYUV_API
I420AlphaToARGBMatrixFilter(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,enum FilterMode filter)7119 int I420AlphaToARGBMatrixFilter(const uint8_t* src_y,
7120 int src_stride_y,
7121 const uint8_t* src_u,
7122 int src_stride_u,
7123 const uint8_t* src_v,
7124 int src_stride_v,
7125 const uint8_t* src_a,
7126 int src_stride_a,
7127 uint8_t* dst_argb,
7128 int dst_stride_argb,
7129 const struct YuvConstants* yuvconstants,
7130 int width,
7131 int height,
7132 int attenuate,
7133 enum FilterMode filter) {
7134 switch (filter) {
7135 case kFilterNone:
7136 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
7137 src_v, src_stride_v, src_a, src_stride_a,
7138 dst_argb, dst_stride_argb, yuvconstants,
7139 width, height, attenuate);
7140 case kFilterBilinear:
7141 case kFilterBox:
7142 return I420AlphaToARGBMatrixBilinear(
7143 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
7144 src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
7145 attenuate);
7146 case kFilterLinear:
7147 return -1;
7148 }
7149
7150 return -1;
7151 }
7152
7153 LIBYUV_API
I422AlphaToARGBMatrixFilter(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,enum FilterMode filter)7154 int I422AlphaToARGBMatrixFilter(const uint8_t* src_y,
7155 int src_stride_y,
7156 const uint8_t* src_u,
7157 int src_stride_u,
7158 const uint8_t* src_v,
7159 int src_stride_v,
7160 const uint8_t* src_a,
7161 int src_stride_a,
7162 uint8_t* dst_argb,
7163 int dst_stride_argb,
7164 const struct YuvConstants* yuvconstants,
7165 int width,
7166 int height,
7167 int attenuate,
7168 enum FilterMode filter) {
7169 switch (filter) {
7170 case kFilterNone:
7171 return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
7172 src_v, src_stride_v, src_a, src_stride_a,
7173 dst_argb, dst_stride_argb, yuvconstants,
7174 width, height, attenuate);
7175 case kFilterBilinear:
7176 case kFilterBox:
7177 case kFilterLinear:
7178 return I422AlphaToARGBMatrixLinear(
7179 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
7180 src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
7181 attenuate);
7182 }
7183
7184 return -1;
7185 }
7186
7187 LIBYUV_API
I010AlphaToARGBMatrixFilter(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,const uint16_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,enum FilterMode filter)7188 int I010AlphaToARGBMatrixFilter(const uint16_t* src_y,
7189 int src_stride_y,
7190 const uint16_t* src_u,
7191 int src_stride_u,
7192 const uint16_t* src_v,
7193 int src_stride_v,
7194 const uint16_t* src_a,
7195 int src_stride_a,
7196 uint8_t* dst_argb,
7197 int dst_stride_argb,
7198 const struct YuvConstants* yuvconstants,
7199 int width,
7200 int height,
7201 int attenuate,
7202 enum FilterMode filter) {
7203 switch (filter) {
7204 case kFilterNone:
7205 return I010AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
7206 src_v, src_stride_v, src_a, src_stride_a,
7207 dst_argb, dst_stride_argb, yuvconstants,
7208 width, height, attenuate);
7209 case kFilterBilinear:
7210 case kFilterBox:
7211 return I010AlphaToARGBMatrixBilinear(
7212 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
7213 src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
7214 attenuate);
7215 case kFilterLinear:
7216 return -1;
7217 }
7218
7219 return -1;
7220 }
7221
7222 LIBYUV_API
I210AlphaToARGBMatrixFilter(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,const uint16_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,enum FilterMode filter)7223 int I210AlphaToARGBMatrixFilter(const uint16_t* src_y,
7224 int src_stride_y,
7225 const uint16_t* src_u,
7226 int src_stride_u,
7227 const uint16_t* src_v,
7228 int src_stride_v,
7229 const uint16_t* src_a,
7230 int src_stride_a,
7231 uint8_t* dst_argb,
7232 int dst_stride_argb,
7233 const struct YuvConstants* yuvconstants,
7234 int width,
7235 int height,
7236 int attenuate,
7237 enum FilterMode filter) {
7238 switch (filter) {
7239 case kFilterNone:
7240 return I210AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
7241 src_v, src_stride_v, src_a, src_stride_a,
7242 dst_argb, dst_stride_argb, yuvconstants,
7243 width, height, attenuate);
7244 case kFilterBilinear:
7245 case kFilterBox:
7246 case kFilterLinear:
7247 return I210AlphaToARGBMatrixLinear(
7248 src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
7249 src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
7250 attenuate);
7251 }
7252
7253 return -1;
7254 }
7255
7256 LIBYUV_API
P010ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)7257 int P010ToARGBMatrixFilter(const uint16_t* src_y,
7258 int src_stride_y,
7259 const uint16_t* src_uv,
7260 int src_stride_uv,
7261 uint8_t* dst_argb,
7262 int dst_stride_argb,
7263 const struct YuvConstants* yuvconstants,
7264 int width,
7265 int height,
7266 enum FilterMode filter) {
7267 switch (filter) {
7268 case kFilterNone:
7269 return P010ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
7270 dst_argb, dst_stride_argb, yuvconstants, width,
7271 height);
7272 case kFilterBilinear:
7273 case kFilterBox:
7274 return P010ToARGBMatrixBilinear(src_y, src_stride_y, src_uv,
7275 src_stride_uv, dst_argb, dst_stride_argb,
7276 yuvconstants, width, height);
7277 case kFilterLinear:
7278 return -1;
7279 }
7280
7281 return -1;
7282 }
7283
7284 LIBYUV_API
P210ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)7285 int P210ToARGBMatrixFilter(const uint16_t* src_y,
7286 int src_stride_y,
7287 const uint16_t* src_uv,
7288 int src_stride_uv,
7289 uint8_t* dst_argb,
7290 int dst_stride_argb,
7291 const struct YuvConstants* yuvconstants,
7292 int width,
7293 int height,
7294 enum FilterMode filter) {
7295 switch (filter) {
7296 case kFilterNone:
7297 return P210ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
7298 dst_argb, dst_stride_argb, yuvconstants, width,
7299 height);
7300 case kFilterBilinear:
7301 case kFilterBox:
7302 case kFilterLinear:
7303 return P210ToARGBMatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
7304 dst_argb, dst_stride_argb, yuvconstants,
7305 width, height);
7306 }
7307
7308 return -1;
7309 }
7310
7311 LIBYUV_API
P010ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)7312 int P010ToAR30MatrixFilter(const uint16_t* src_y,
7313 int src_stride_y,
7314 const uint16_t* src_uv,
7315 int src_stride_uv,
7316 uint8_t* dst_ar30,
7317 int dst_stride_ar30,
7318 const struct YuvConstants* yuvconstants,
7319 int width,
7320 int height,
7321 enum FilterMode filter) {
7322 switch (filter) {
7323 case kFilterNone:
7324 return P010ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
7325 dst_ar30, dst_stride_ar30, yuvconstants, width,
7326 height);
7327 case kFilterBilinear:
7328 case kFilterBox:
7329 return P010ToAR30MatrixBilinear(src_y, src_stride_y, src_uv,
7330 src_stride_uv, dst_ar30, dst_stride_ar30,
7331 yuvconstants, width, height);
7332 case kFilterLinear:
7333 return -1;
7334 }
7335
7336 return -1;
7337 }
7338
7339 LIBYUV_API
P210ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)7340 int P210ToAR30MatrixFilter(const uint16_t* src_y,
7341 int src_stride_y,
7342 const uint16_t* src_uv,
7343 int src_stride_uv,
7344 uint8_t* dst_ar30,
7345 int dst_stride_ar30,
7346 const struct YuvConstants* yuvconstants,
7347 int width,
7348 int height,
7349 enum FilterMode filter) {
7350 switch (filter) {
7351 case kFilterNone:
7352 return P210ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
7353 dst_ar30, dst_stride_ar30, yuvconstants, width,
7354 height);
7355 case kFilterBilinear:
7356 case kFilterBox:
7357 case kFilterLinear:
7358 return P210ToAR30MatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
7359 dst_ar30, dst_stride_ar30, yuvconstants,
7360 width, height);
7361 }
7362
7363 return -1;
7364 }
7365
7366 #ifdef __cplusplus
7367 } // extern "C"
7368 } // namespace libyuv
7369 #endif
7370