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