1 /*
2 * Copyright 2012 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_from_argb.h"
12
13 #include "libyuv/basic_types.h"
14 #include "libyuv/cpu_id.h"
15 #include "libyuv/planar_functions.h"
16 #include "libyuv/row.h"
17
18 #ifdef __cplusplus
19 namespace libyuv {
20 extern "C" {
21 #endif
22
23 // ARGB little endian (bgra in memory) to I444
24 LIBYUV_API
ARGBToI444(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_u,int dst_stride_u,uint8_t * dst_v,int dst_stride_v,int width,int height)25 int ARGBToI444(const uint8_t* src_argb,
26 int src_stride_argb,
27 uint8_t* dst_y,
28 int dst_stride_y,
29 uint8_t* dst_u,
30 int dst_stride_u,
31 uint8_t* dst_v,
32 int dst_stride_v,
33 int width,
34 int height) {
35 int y;
36 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
37 ARGBToYRow_C;
38 void (*ARGBToUV444Row)(const uint8_t* src_argb, uint8_t* dst_u,
39 uint8_t* dst_v, int width) = ARGBToUV444Row_C;
40 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
41 return -1;
42 }
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 // Coalesce rows.
49 if (src_stride_argb == width * 4 && dst_stride_y == width &&
50 dst_stride_u == width && dst_stride_v == width) {
51 width *= height;
52 height = 1;
53 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
54 }
55 #if defined(HAS_ARGBTOUV444ROW_SSSE3)
56 if (TestCpuFlag(kCpuHasSSSE3)) {
57 ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
58 if (IS_ALIGNED(width, 16)) {
59 ARGBToUV444Row = ARGBToUV444Row_SSSE3;
60 }
61 }
62 #endif
63 #if defined(HAS_ARGBTOUV444ROW_NEON)
64 if (TestCpuFlag(kCpuHasNEON)) {
65 ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
66 if (IS_ALIGNED(width, 8)) {
67 ARGBToUV444Row = ARGBToUV444Row_NEON;
68 }
69 }
70 #endif
71 #if defined(HAS_ARGBTOUV444ROW_MSA)
72 if (TestCpuFlag(kCpuHasMSA)) {
73 ARGBToUV444Row = ARGBToUV444Row_Any_MSA;
74 if (IS_ALIGNED(width, 16)) {
75 ARGBToUV444Row = ARGBToUV444Row_MSA;
76 }
77 }
78 #endif
79 #if defined(HAS_ARGBTOUV444ROW_LSX)
80 if (TestCpuFlag(kCpuHasLSX)) {
81 ARGBToUV444Row = ARGBToUV444Row_Any_LSX;
82 if (IS_ALIGNED(width, 16)) {
83 ARGBToUV444Row = ARGBToUV444Row_LSX;
84 }
85 }
86 #endif
87 #if defined(HAS_ARGBTOUV444ROW_LASX)
88 if (TestCpuFlag(kCpuHasLASX)) {
89 ARGBToUV444Row = ARGBToUV444Row_Any_LASX;
90 if (IS_ALIGNED(width, 32)) {
91 ARGBToUV444Row = ARGBToUV444Row_LASX;
92 }
93 }
94 #endif
95 #if defined(HAS_ARGBTOYROW_SSSE3)
96 if (TestCpuFlag(kCpuHasSSSE3)) {
97 ARGBToYRow = ARGBToYRow_Any_SSSE3;
98 if (IS_ALIGNED(width, 16)) {
99 ARGBToYRow = ARGBToYRow_SSSE3;
100 }
101 }
102 #endif
103 #if defined(HAS_ARGBTOYROW_AVX2)
104 if (TestCpuFlag(kCpuHasAVX2)) {
105 ARGBToYRow = ARGBToYRow_Any_AVX2;
106 if (IS_ALIGNED(width, 32)) {
107 ARGBToYRow = ARGBToYRow_AVX2;
108 }
109 }
110 #endif
111 #if defined(HAS_ARGBTOYROW_NEON)
112 if (TestCpuFlag(kCpuHasNEON)) {
113 ARGBToYRow = ARGBToYRow_Any_NEON;
114 if (IS_ALIGNED(width, 16)) {
115 ARGBToYRow = ARGBToYRow_NEON;
116 }
117 }
118 #endif
119 #if defined(HAS_ARGBTOYROW_MSA)
120 if (TestCpuFlag(kCpuHasMSA)) {
121 ARGBToYRow = ARGBToYRow_Any_MSA;
122 if (IS_ALIGNED(width, 16)) {
123 ARGBToYRow = ARGBToYRow_MSA;
124 }
125 }
126 #endif
127 #if defined(HAS_ARGBTOYROW_LSX)
128 if (TestCpuFlag(kCpuHasLSX)) {
129 ARGBToYRow = ARGBToYRow_Any_LSX;
130 if (IS_ALIGNED(width, 16)) {
131 ARGBToYRow = ARGBToYRow_LSX;
132 }
133 }
134 #endif
135 #if defined(HAS_ARGBTOYROW_LASX)
136 if (TestCpuFlag(kCpuHasLASX)) {
137 ARGBToYRow = ARGBToYRow_Any_LASX;
138 if (IS_ALIGNED(width, 32)) {
139 ARGBToYRow = ARGBToYRow_LASX;
140 }
141 }
142 #endif
143 #if defined(HAS_ARGBTOYROW_RVV)
144 if (TestCpuFlag(kCpuHasRVV)) {
145 ARGBToYRow = ARGBToYRow_RVV;
146 }
147 #endif
148
149 for (y = 0; y < height; ++y) {
150 ARGBToUV444Row(src_argb, dst_u, dst_v, width);
151 ARGBToYRow(src_argb, dst_y, width);
152 src_argb += src_stride_argb;
153 dst_y += dst_stride_y;
154 dst_u += dst_stride_u;
155 dst_v += dst_stride_v;
156 }
157 return 0;
158 }
159
160 // ARGB little endian (bgra in memory) to I422
161 LIBYUV_API
ARGBToI422(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_u,int dst_stride_u,uint8_t * dst_v,int dst_stride_v,int width,int height)162 int ARGBToI422(const uint8_t* src_argb,
163 int src_stride_argb,
164 uint8_t* dst_y,
165 int dst_stride_y,
166 uint8_t* dst_u,
167 int dst_stride_u,
168 uint8_t* dst_v,
169 int dst_stride_v,
170 int width,
171 int height) {
172 int y;
173 void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
174 uint8_t* dst_u, uint8_t* dst_v, int width) =
175 ARGBToUVRow_C;
176 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
177 ARGBToYRow_C;
178 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
179 return -1;
180 }
181 // Negative height means invert the image.
182 if (height < 0) {
183 height = -height;
184 src_argb = src_argb + (height - 1) * src_stride_argb;
185 src_stride_argb = -src_stride_argb;
186 }
187 // Coalesce rows.
188 if (src_stride_argb == width * 4 && dst_stride_y == width &&
189 dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
190 width *= height;
191 height = 1;
192 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
193 }
194 #if defined(HAS_ARGBTOYROW_SSSE3)
195 if (TestCpuFlag(kCpuHasSSSE3)) {
196 ARGBToYRow = ARGBToYRow_Any_SSSE3;
197 if (IS_ALIGNED(width, 16)) {
198 ARGBToYRow = ARGBToYRow_SSSE3;
199 }
200 }
201 #endif
202 #if defined(HAS_ARGBTOUVROW_SSSE3)
203 if (TestCpuFlag(kCpuHasSSSE3)) {
204 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
205 if (IS_ALIGNED(width, 16)) {
206 ARGBToUVRow = ARGBToUVRow_SSSE3;
207 }
208 }
209 #endif
210 #if defined(HAS_ARGBTOYROW_AVX2)
211 if (TestCpuFlag(kCpuHasAVX2)) {
212 ARGBToYRow = ARGBToYRow_Any_AVX2;
213 if (IS_ALIGNED(width, 32)) {
214 ARGBToYRow = ARGBToYRow_AVX2;
215 }
216 }
217 #endif
218 #if defined(HAS_ARGBTOUVROW_AVX2)
219 if (TestCpuFlag(kCpuHasAVX2)) {
220 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
221 if (IS_ALIGNED(width, 32)) {
222 ARGBToUVRow = ARGBToUVRow_AVX2;
223 }
224 }
225 #endif
226 #if defined(HAS_ARGBTOYROW_NEON)
227 if (TestCpuFlag(kCpuHasNEON)) {
228 ARGBToYRow = ARGBToYRow_Any_NEON;
229 if (IS_ALIGNED(width, 16)) {
230 ARGBToYRow = ARGBToYRow_NEON;
231 }
232 }
233 #endif
234 #if defined(HAS_ARGBTOUVROW_NEON)
235 if (TestCpuFlag(kCpuHasNEON)) {
236 ARGBToUVRow = ARGBToUVRow_Any_NEON;
237 if (IS_ALIGNED(width, 16)) {
238 ARGBToUVRow = ARGBToUVRow_NEON;
239 }
240 }
241 #endif
242 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
243 if (TestCpuFlag(kCpuHasMSA)) {
244 ARGBToYRow = ARGBToYRow_Any_MSA;
245 ARGBToUVRow = ARGBToUVRow_Any_MSA;
246 if (IS_ALIGNED(width, 16)) {
247 ARGBToYRow = ARGBToYRow_MSA;
248 }
249 if (IS_ALIGNED(width, 32)) {
250 ARGBToUVRow = ARGBToUVRow_MSA;
251 }
252 }
253 #endif
254 #if defined(HAS_ARGBTOYROW_LSX)
255 if (TestCpuFlag(kCpuHasLSX)) {
256 ARGBToYRow = ARGBToYRow_Any_LSX;
257 if (IS_ALIGNED(width, 16)) {
258 ARGBToYRow = ARGBToYRow_LSX;
259 }
260 }
261 #endif
262 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
263 if (TestCpuFlag(kCpuHasLSX)) {
264 ARGBToYRow = ARGBToYRow_Any_LSX;
265 ARGBToUVRow = ARGBToUVRow_Any_LSX;
266 if (IS_ALIGNED(width, 16)) {
267 ARGBToYRow = ARGBToYRow_LSX;
268 ARGBToUVRow = ARGBToUVRow_LSX;
269 }
270 }
271 #endif
272 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
273 if (TestCpuFlag(kCpuHasLASX)) {
274 ARGBToYRow = ARGBToYRow_Any_LASX;
275 ARGBToUVRow = ARGBToUVRow_Any_LASX;
276 if (IS_ALIGNED(width, 32)) {
277 ARGBToYRow = ARGBToYRow_LASX;
278 ARGBToUVRow = ARGBToUVRow_LASX;
279 }
280 }
281 #endif
282 #if defined(HAS_ARGBTOYROW_RVV)
283 if (TestCpuFlag(kCpuHasRVV)) {
284 ARGBToYRow = ARGBToYRow_RVV;
285 }
286 #endif
287
288 for (y = 0; y < height; ++y) {
289 ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
290 ARGBToYRow(src_argb, dst_y, width);
291 src_argb += src_stride_argb;
292 dst_y += dst_stride_y;
293 dst_u += dst_stride_u;
294 dst_v += dst_stride_v;
295 }
296 return 0;
297 }
298
299 LIBYUV_API
ARGBToNV12(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_uv,int dst_stride_uv,int width,int height)300 int ARGBToNV12(const uint8_t* src_argb,
301 int src_stride_argb,
302 uint8_t* dst_y,
303 int dst_stride_y,
304 uint8_t* dst_uv,
305 int dst_stride_uv,
306 int width,
307 int height) {
308 int y;
309 int halfwidth = (width + 1) >> 1;
310 void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
311 uint8_t* dst_u, uint8_t* dst_v, int width) =
312 ARGBToUVRow_C;
313 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
314 ARGBToYRow_C;
315 void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
316 uint8_t* dst_uv, int width) = MergeUVRow_C;
317 if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
318 return -1;
319 }
320 // Negative height means invert the image.
321 if (height < 0) {
322 height = -height;
323 src_argb = src_argb + (height - 1) * src_stride_argb;
324 src_stride_argb = -src_stride_argb;
325 }
326 #if defined(HAS_ARGBTOYROW_NEON)
327 if (TestCpuFlag(kCpuHasNEON)) {
328 ARGBToYRow = ARGBToYRow_Any_NEON;
329 if (IS_ALIGNED(width, 16)) {
330 ARGBToYRow = ARGBToYRow_NEON;
331 }
332 }
333 #endif
334 #if defined(HAS_ARGBTOUVROW_NEON)
335 if (TestCpuFlag(kCpuHasNEON)) {
336 ARGBToUVRow = ARGBToUVRow_Any_NEON;
337 if (IS_ALIGNED(width, 16)) {
338 ARGBToUVRow = ARGBToUVRow_NEON;
339 }
340 }
341 #endif
342 #if defined(HAS_ARGBTOYROW_SSSE3)
343 if (TestCpuFlag(kCpuHasSSSE3)) {
344 ARGBToYRow = ARGBToYRow_Any_SSSE3;
345 if (IS_ALIGNED(width, 16)) {
346 ARGBToYRow = ARGBToYRow_SSSE3;
347 }
348 }
349 #endif
350 #if defined(HAS_ARGBTOUVROW_SSSE3)
351 if (TestCpuFlag(kCpuHasSSSE3)) {
352 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
353 if (IS_ALIGNED(width, 16)) {
354 ARGBToUVRow = ARGBToUVRow_SSSE3;
355 }
356 }
357 #endif
358 #if defined(HAS_ARGBTOYROW_AVX2)
359 if (TestCpuFlag(kCpuHasAVX2)) {
360 ARGBToYRow = ARGBToYRow_Any_AVX2;
361 if (IS_ALIGNED(width, 32)) {
362 ARGBToYRow = ARGBToYRow_AVX2;
363 }
364 }
365 #endif
366 #if defined(HAS_ARGBTOUVROW_AVX2)
367 if (TestCpuFlag(kCpuHasAVX2)) {
368 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
369 if (IS_ALIGNED(width, 32)) {
370 ARGBToUVRow = ARGBToUVRow_AVX2;
371 }
372 }
373 #endif
374 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
375 if (TestCpuFlag(kCpuHasMSA)) {
376 ARGBToYRow = ARGBToYRow_Any_MSA;
377 ARGBToUVRow = ARGBToUVRow_Any_MSA;
378 if (IS_ALIGNED(width, 16)) {
379 ARGBToYRow = ARGBToYRow_MSA;
380 }
381 if (IS_ALIGNED(width, 32)) {
382 ARGBToUVRow = ARGBToUVRow_MSA;
383 }
384 }
385 #endif
386 #if defined(HAS_ARGBTOYROW_LSX)
387 if (TestCpuFlag(kCpuHasLSX)) {
388 ARGBToYRow = ARGBToYRow_Any_LSX;
389 if (IS_ALIGNED(width, 16)) {
390 ARGBToYRow = ARGBToYRow_LSX;
391 }
392 }
393 #endif
394 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
395 if (TestCpuFlag(kCpuHasLASX)) {
396 ARGBToYRow = ARGBToYRow_Any_LASX;
397 ARGBToUVRow = ARGBToUVRow_Any_LASX;
398 if (IS_ALIGNED(width, 32)) {
399 ARGBToYRow = ARGBToYRow_LASX;
400 ARGBToUVRow = ARGBToUVRow_LASX;
401 }
402 }
403 #endif
404 #if defined(HAS_ARGBTOYROW_RVV)
405 if (TestCpuFlag(kCpuHasRVV)) {
406 ARGBToYRow = ARGBToYRow_RVV;
407 }
408 #endif
409 #if defined(HAS_MERGEUVROW_SSE2)
410 if (TestCpuFlag(kCpuHasSSE2)) {
411 MergeUVRow_ = MergeUVRow_Any_SSE2;
412 if (IS_ALIGNED(halfwidth, 16)) {
413 MergeUVRow_ = MergeUVRow_SSE2;
414 }
415 }
416 #endif
417 #if defined(HAS_MERGEUVROW_AVX2)
418 if (TestCpuFlag(kCpuHasAVX2)) {
419 MergeUVRow_ = MergeUVRow_Any_AVX2;
420 if (IS_ALIGNED(halfwidth, 16)) {
421 MergeUVRow_ = MergeUVRow_AVX2;
422 }
423 }
424 #endif
425 #if defined(HAS_MERGEUVROW_AVX512BW)
426 if (TestCpuFlag(kCpuHasAVX512BW)) {
427 MergeUVRow_ = MergeUVRow_Any_AVX512BW;
428 if (IS_ALIGNED(halfwidth, 32)) {
429 MergeUVRow_ = MergeUVRow_AVX512BW;
430 }
431 }
432 #endif
433 #if defined(HAS_MERGEUVROW_NEON)
434 if (TestCpuFlag(kCpuHasNEON)) {
435 MergeUVRow_ = MergeUVRow_Any_NEON;
436 if (IS_ALIGNED(halfwidth, 16)) {
437 MergeUVRow_ = MergeUVRow_NEON;
438 }
439 }
440 #endif
441 #if defined(HAS_MERGEUVROW_MSA)
442 if (TestCpuFlag(kCpuHasMSA)) {
443 MergeUVRow_ = MergeUVRow_Any_MSA;
444 if (IS_ALIGNED(halfwidth, 16)) {
445 MergeUVRow_ = MergeUVRow_MSA;
446 }
447 }
448 #endif
449 #if defined(HAS_MERGEUVROW_LSX)
450 if (TestCpuFlag(kCpuHasLSX)) {
451 MergeUVRow_ = MergeUVRow_Any_LSX;
452 if (IS_ALIGNED(halfwidth, 16)) {
453 MergeUVRow_ = MergeUVRow_LSX;
454 }
455 }
456 #endif
457 #if defined(HAS_MERGEUVROW_RVV)
458 if (TestCpuFlag(kCpuHasRVV)) {
459 MergeUVRow_ = MergeUVRow_RVV;
460 }
461 #endif
462 {
463 // Allocate a rows of uv.
464 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
465 uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
466 if (!row_u)
467 return 1;
468
469 for (y = 0; y < height - 1; y += 2) {
470 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
471 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
472 ARGBToYRow(src_argb, dst_y, width);
473 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
474 src_argb += src_stride_argb * 2;
475 dst_y += dst_stride_y * 2;
476 dst_uv += dst_stride_uv;
477 }
478 if (height & 1) {
479 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
480 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
481 ARGBToYRow(src_argb, dst_y, width);
482 }
483 free_aligned_buffer_64(row_u);
484 }
485 return 0;
486 }
487
488 // Same as NV12 but U and V swapped.
489 LIBYUV_API
ARGBToNV21(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)490 int ARGBToNV21(const uint8_t* src_argb,
491 int src_stride_argb,
492 uint8_t* dst_y,
493 int dst_stride_y,
494 uint8_t* dst_vu,
495 int dst_stride_vu,
496 int width,
497 int height) {
498 int y;
499 int halfwidth = (width + 1) >> 1;
500 void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
501 uint8_t* dst_u, uint8_t* dst_v, int width) =
502 ARGBToUVRow_C;
503 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
504 ARGBToYRow_C;
505 void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
506 uint8_t* dst_vu, int width) = MergeUVRow_C;
507 if (!src_argb || !dst_y || !dst_vu || width <= 0 || height == 0) {
508 return -1;
509 }
510 // Negative height means invert the image.
511 if (height < 0) {
512 height = -height;
513 src_argb = src_argb + (height - 1) * src_stride_argb;
514 src_stride_argb = -src_stride_argb;
515 }
516 #if defined(HAS_ARGBTOYROW_SSSE3)
517 if (TestCpuFlag(kCpuHasSSSE3)) {
518 ARGBToYRow = ARGBToYRow_Any_SSSE3;
519 if (IS_ALIGNED(width, 16)) {
520 ARGBToYRow = ARGBToYRow_SSSE3;
521 }
522 }
523 #endif
524 #if defined(HAS_ARGBTOUVROW_SSSE3)
525 if (TestCpuFlag(kCpuHasSSSE3)) {
526 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
527 if (IS_ALIGNED(width, 16)) {
528 ARGBToUVRow = ARGBToUVRow_SSSE3;
529 }
530 }
531 #endif
532 #if defined(HAS_ARGBTOYROW_AVX2)
533 if (TestCpuFlag(kCpuHasAVX2)) {
534 ARGBToYRow = ARGBToYRow_Any_AVX2;
535 if (IS_ALIGNED(width, 32)) {
536 ARGBToYRow = ARGBToYRow_AVX2;
537 }
538 }
539 #endif
540 #if defined(HAS_ARGBTOUVROW_AVX2)
541 if (TestCpuFlag(kCpuHasAVX2)) {
542 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
543 if (IS_ALIGNED(width, 32)) {
544 ARGBToUVRow = ARGBToUVRow_AVX2;
545 }
546 }
547 #endif
548 #if defined(HAS_ARGBTOYROW_NEON)
549 if (TestCpuFlag(kCpuHasNEON)) {
550 ARGBToYRow = ARGBToYRow_Any_NEON;
551 if (IS_ALIGNED(width, 16)) {
552 ARGBToYRow = ARGBToYRow_NEON;
553 }
554 }
555 #endif
556 #if defined(HAS_ARGBTOUVROW_NEON)
557 if (TestCpuFlag(kCpuHasNEON)) {
558 ARGBToUVRow = ARGBToUVRow_Any_NEON;
559 if (IS_ALIGNED(width, 16)) {
560 ARGBToUVRow = ARGBToUVRow_NEON;
561 }
562 }
563 #endif
564 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
565 if (TestCpuFlag(kCpuHasMSA)) {
566 ARGBToYRow = ARGBToYRow_Any_MSA;
567 ARGBToUVRow = ARGBToUVRow_Any_MSA;
568 if (IS_ALIGNED(width, 16)) {
569 ARGBToYRow = ARGBToYRow_MSA;
570 }
571 if (IS_ALIGNED(width, 32)) {
572 ARGBToUVRow = ARGBToUVRow_MSA;
573 }
574 }
575 #endif
576 #if defined(HAS_ARGBTOYROW_LSX)
577 if (TestCpuFlag(kCpuHasLSX)) {
578 ARGBToYRow = ARGBToYRow_Any_LSX;
579 if (IS_ALIGNED(width, 16)) {
580 ARGBToYRow = ARGBToYRow_LSX;
581 }
582 }
583 #endif
584 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
585 if (TestCpuFlag(kCpuHasLSX)) {
586 ARGBToYRow = ARGBToYRow_Any_LSX;
587 ARGBToUVRow = ARGBToUVRow_Any_LSX;
588 if (IS_ALIGNED(width, 16)) {
589 ARGBToYRow = ARGBToYRow_LSX;
590 ARGBToUVRow = ARGBToUVRow_LSX;
591 }
592 }
593 #endif
594 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
595 if (TestCpuFlag(kCpuHasLASX)) {
596 ARGBToYRow = ARGBToYRow_Any_LASX;
597 ARGBToUVRow = ARGBToUVRow_Any_LASX;
598 if (IS_ALIGNED(width, 32)) {
599 ARGBToYRow = ARGBToYRow_LASX;
600 ARGBToUVRow = ARGBToUVRow_LASX;
601 }
602 }
603 #endif
604 #if defined(HAS_ARGBTOYROW_RVV)
605 if (TestCpuFlag(kCpuHasRVV)) {
606 ARGBToYRow = ARGBToYRow_RVV;
607 }
608 #endif
609 #if defined(HAS_MERGEUVROW_SSE2)
610 if (TestCpuFlag(kCpuHasSSE2)) {
611 MergeUVRow_ = MergeUVRow_Any_SSE2;
612 if (IS_ALIGNED(halfwidth, 16)) {
613 MergeUVRow_ = MergeUVRow_SSE2;
614 }
615 }
616 #endif
617 #if defined(HAS_MERGEUVROW_AVX2)
618 if (TestCpuFlag(kCpuHasAVX2)) {
619 MergeUVRow_ = MergeUVRow_Any_AVX2;
620 if (IS_ALIGNED(halfwidth, 16)) {
621 MergeUVRow_ = MergeUVRow_AVX2;
622 }
623 }
624 #endif
625 #if defined(HAS_MERGEUVROW_AVX512BW)
626 if (TestCpuFlag(kCpuHasAVX512BW)) {
627 MergeUVRow_ = MergeUVRow_Any_AVX512BW;
628 if (IS_ALIGNED(halfwidth, 64)) {
629 MergeUVRow_ = MergeUVRow_AVX512BW;
630 }
631 }
632 #endif
633 #if defined(HAS_MERGEUVROW_NEON)
634 if (TestCpuFlag(kCpuHasNEON)) {
635 MergeUVRow_ = MergeUVRow_Any_NEON;
636 if (IS_ALIGNED(halfwidth, 16)) {
637 MergeUVRow_ = MergeUVRow_NEON;
638 }
639 }
640 #endif
641 #if defined(HAS_MERGEUVROW_MSA)
642 if (TestCpuFlag(kCpuHasMSA)) {
643 MergeUVRow_ = MergeUVRow_Any_MSA;
644 if (IS_ALIGNED(halfwidth, 16)) {
645 MergeUVRow_ = MergeUVRow_MSA;
646 }
647 }
648 #endif
649 #if defined(HAS_MERGEUVROW_LSX)
650 if (TestCpuFlag(kCpuHasLSX)) {
651 MergeUVRow_ = MergeUVRow_Any_LSX;
652 if (IS_ALIGNED(halfwidth, 16)) {
653 MergeUVRow_ = MergeUVRow_LSX;
654 }
655 }
656 #endif
657 #if defined(HAS_MERGEUVROW_RVV)
658 if (TestCpuFlag(kCpuHasRVV)) {
659 MergeUVRow_ = MergeUVRow_RVV;
660 }
661 #endif
662 {
663 // Allocate a rows of uv.
664 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
665 uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
666 if (!row_u)
667 return 1;
668
669 for (y = 0; y < height - 1; y += 2) {
670 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
671 MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
672 ARGBToYRow(src_argb, dst_y, width);
673 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
674 src_argb += src_stride_argb * 2;
675 dst_y += dst_stride_y * 2;
676 dst_vu += dst_stride_vu;
677 }
678 if (height & 1) {
679 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
680 MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
681 ARGBToYRow(src_argb, dst_y, width);
682 }
683 free_aligned_buffer_64(row_u);
684 }
685 return 0;
686 }
687
688 LIBYUV_API
ABGRToNV12(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_uv,int dst_stride_uv,int width,int height)689 int ABGRToNV12(const uint8_t* src_abgr,
690 int src_stride_abgr,
691 uint8_t* dst_y,
692 int dst_stride_y,
693 uint8_t* dst_uv,
694 int dst_stride_uv,
695 int width,
696 int height) {
697 int y;
698 int halfwidth = (width + 1) >> 1;
699 void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
700 uint8_t* dst_u, uint8_t* dst_v, int width) =
701 ABGRToUVRow_C;
702 void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
703 ABGRToYRow_C;
704 void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
705 uint8_t* dst_uv, int width) = MergeUVRow_C;
706 if (!src_abgr || !dst_y || !dst_uv || width <= 0 || height == 0) {
707 return -1;
708 }
709 // Negative height means invert the image.
710 if (height < 0) {
711 height = -height;
712 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
713 src_stride_abgr = -src_stride_abgr;
714 }
715 #if defined(HAS_ABGRTOYROW_SSSE3)
716 if (TestCpuFlag(kCpuHasSSSE3)) {
717 ABGRToYRow = ABGRToYRow_Any_SSSE3;
718 if (IS_ALIGNED(width, 16)) {
719 ABGRToYRow = ABGRToYRow_SSSE3;
720 }
721 }
722 #endif
723 #if defined(HAS_ABGRTOUVROW_SSSE3)
724 if (TestCpuFlag(kCpuHasSSSE3)) {
725 ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
726 if (IS_ALIGNED(width, 16)) {
727 ABGRToUVRow = ABGRToUVRow_SSSE3;
728 }
729 }
730 #endif
731 #if defined(HAS_ABGRTOYROW_AVX2)
732 if (TestCpuFlag(kCpuHasAVX2)) {
733 ABGRToYRow = ABGRToYRow_Any_AVX2;
734 if (IS_ALIGNED(width, 32)) {
735 ABGRToYRow = ABGRToYRow_AVX2;
736 }
737 }
738 #endif
739 #if defined(HAS_ABGRTOUVROW_AVX2)
740 if (TestCpuFlag(kCpuHasAVX2)) {
741 ABGRToUVRow = ABGRToUVRow_Any_AVX2;
742 if (IS_ALIGNED(width, 32)) {
743 ABGRToUVRow = ABGRToUVRow_AVX2;
744 }
745 }
746 #endif
747 #if defined(HAS_ABGRTOYROW_NEON)
748 if (TestCpuFlag(kCpuHasNEON)) {
749 ABGRToYRow = ABGRToYRow_Any_NEON;
750 if (IS_ALIGNED(width, 16)) {
751 ABGRToYRow = ABGRToYRow_NEON;
752 }
753 }
754 #endif
755 #if defined(HAS_ABGRTOUVROW_NEON)
756 if (TestCpuFlag(kCpuHasNEON)) {
757 ABGRToUVRow = ABGRToUVRow_Any_NEON;
758 if (IS_ALIGNED(width, 16)) {
759 ABGRToUVRow = ABGRToUVRow_NEON;
760 }
761 }
762 #endif
763 #if defined(HAS_ABGRTOYROW_MSA) && defined(HAS_ABGRTOUVROW_MSA)
764 if (TestCpuFlag(kCpuHasMSA)) {
765 ABGRToYRow = ABGRToYRow_Any_MSA;
766 ABGRToUVRow = ABGRToUVRow_Any_MSA;
767 if (IS_ALIGNED(width, 16)) {
768 ABGRToYRow = ABGRToYRow_MSA;
769 }
770 if (IS_ALIGNED(width, 32)) {
771 ABGRToUVRow = ABGRToUVRow_MSA;
772 }
773 }
774 #endif
775 #if defined(HAS_ABGRTOYROW_LSX)
776 if (TestCpuFlag(kCpuHasLSX)) {
777 ABGRToYRow = ABGRToYRow_Any_LSX;
778 if (IS_ALIGNED(width, 16)) {
779 ABGRToYRow = ABGRToYRow_LSX;
780 }
781 }
782 #endif
783 #if defined(HAS_ABGRTOYROW_LASX)
784 if (TestCpuFlag(kCpuHasLASX)) {
785 ABGRToYRow = ABGRToYRow_Any_LASX;
786 if (IS_ALIGNED(width, 32)) {
787 ABGRToYRow = ABGRToYRow_LASX;
788 }
789 }
790 #endif
791 #if defined(HAS_ABGRTOYROW_RVV)
792 if (TestCpuFlag(kCpuHasRVV)) {
793 ABGRToYRow = ABGRToYRow_RVV;
794 }
795 #endif
796 #if defined(HAS_MERGEUVROW_SSE2)
797 if (TestCpuFlag(kCpuHasSSE2)) {
798 MergeUVRow_ = MergeUVRow_Any_SSE2;
799 if (IS_ALIGNED(halfwidth, 16)) {
800 MergeUVRow_ = MergeUVRow_SSE2;
801 }
802 }
803 #endif
804 #if defined(HAS_MERGEUVROW_AVX2)
805 if (TestCpuFlag(kCpuHasAVX2)) {
806 MergeUVRow_ = MergeUVRow_Any_AVX2;
807 if (IS_ALIGNED(halfwidth, 16)) {
808 MergeUVRow_ = MergeUVRow_AVX2;
809 }
810 }
811 #endif
812 #if defined(HAS_MERGEUVROW_AVX512BW)
813 if (TestCpuFlag(kCpuHasAVX512BW)) {
814 MergeUVRow_ = MergeUVRow_Any_AVX512BW;
815 if (IS_ALIGNED(halfwidth, 64)) {
816 MergeUVRow_ = MergeUVRow_AVX512BW;
817 }
818 }
819 #endif
820 #if defined(HAS_MERGEUVROW_NEON)
821 if (TestCpuFlag(kCpuHasNEON)) {
822 MergeUVRow_ = MergeUVRow_Any_NEON;
823 if (IS_ALIGNED(halfwidth, 16)) {
824 MergeUVRow_ = MergeUVRow_NEON;
825 }
826 }
827 #endif
828 #if defined(HAS_MERGEUVROW_MSA)
829 if (TestCpuFlag(kCpuHasMSA)) {
830 MergeUVRow_ = MergeUVRow_Any_MSA;
831 if (IS_ALIGNED(halfwidth, 16)) {
832 MergeUVRow_ = MergeUVRow_MSA;
833 }
834 }
835 #endif
836 #if defined(HAS_MERGEUVROW_LSX)
837 if (TestCpuFlag(kCpuHasLSX)) {
838 MergeUVRow_ = MergeUVRow_Any_LSX;
839 if (IS_ALIGNED(halfwidth, 16)) {
840 MergeUVRow_ = MergeUVRow_LSX;
841 }
842 }
843 #endif
844 #if defined(HAS_MERGEUVROW_RVV)
845 if (TestCpuFlag(kCpuHasRVV)) {
846 MergeUVRow_ = MergeUVRow_RVV;
847 }
848 #endif
849 {
850 // Allocate a rows of uv.
851 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
852 uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
853 if (!row_u)
854 return 1;
855
856 for (y = 0; y < height - 1; y += 2) {
857 ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
858 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
859 ABGRToYRow(src_abgr, dst_y, width);
860 ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
861 src_abgr += src_stride_abgr * 2;
862 dst_y += dst_stride_y * 2;
863 dst_uv += dst_stride_uv;
864 }
865 if (height & 1) {
866 ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
867 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
868 ABGRToYRow(src_abgr, dst_y, width);
869 }
870 free_aligned_buffer_64(row_u);
871 }
872 return 0;
873 }
874
875 // Same as NV12 but U and V swapped.
876 LIBYUV_API
ABGRToNV21(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)877 int ABGRToNV21(const uint8_t* src_abgr,
878 int src_stride_abgr,
879 uint8_t* dst_y,
880 int dst_stride_y,
881 uint8_t* dst_vu,
882 int dst_stride_vu,
883 int width,
884 int height) {
885 int y;
886 int halfwidth = (width + 1) >> 1;
887 void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
888 uint8_t* dst_u, uint8_t* dst_v, int width) =
889 ABGRToUVRow_C;
890 void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
891 ABGRToYRow_C;
892 void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
893 uint8_t* dst_vu, int width) = MergeUVRow_C;
894 if (!src_abgr || !dst_y || !dst_vu || width <= 0 || height == 0) {
895 return -1;
896 }
897 // Negative height means invert the image.
898 if (height < 0) {
899 height = -height;
900 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
901 src_stride_abgr = -src_stride_abgr;
902 }
903 #if defined(HAS_ABGRTOYROW_SSSE3)
904 if (TestCpuFlag(kCpuHasSSSE3)) {
905 ABGRToYRow = ABGRToYRow_Any_SSSE3;
906 if (IS_ALIGNED(width, 16)) {
907 ABGRToYRow = ABGRToYRow_SSSE3;
908 }
909 }
910 #endif
911 #if defined(HAS_ABGRTOUVROW_SSSE3)
912 if (TestCpuFlag(kCpuHasSSSE3)) {
913 ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
914 if (IS_ALIGNED(width, 16)) {
915 ABGRToUVRow = ABGRToUVRow_SSSE3;
916 }
917 }
918 #endif
919 #if defined(HAS_ABGRTOYROW_AVX2)
920 if (TestCpuFlag(kCpuHasAVX2)) {
921 ABGRToYRow = ABGRToYRow_Any_AVX2;
922 if (IS_ALIGNED(width, 32)) {
923 ABGRToYRow = ABGRToYRow_AVX2;
924 }
925 }
926 #endif
927 #if defined(HAS_ABGRTOUVROW_AVX2)
928 if (TestCpuFlag(kCpuHasAVX2)) {
929 ABGRToUVRow = ABGRToUVRow_Any_AVX2;
930 if (IS_ALIGNED(width, 32)) {
931 ABGRToUVRow = ABGRToUVRow_AVX2;
932 }
933 }
934 #endif
935 #if defined(HAS_ABGRTOYROW_NEON)
936 if (TestCpuFlag(kCpuHasNEON)) {
937 ABGRToYRow = ABGRToYRow_Any_NEON;
938 if (IS_ALIGNED(width, 16)) {
939 ABGRToYRow = ABGRToYRow_NEON;
940 }
941 }
942 #endif
943 #if defined(HAS_ABGRTOUVROW_NEON)
944 if (TestCpuFlag(kCpuHasNEON)) {
945 ABGRToUVRow = ABGRToUVRow_Any_NEON;
946 if (IS_ALIGNED(width, 16)) {
947 ABGRToUVRow = ABGRToUVRow_NEON;
948 }
949 }
950 #endif
951 #if defined(HAS_ABGRTOYROW_MSA) && defined(HAS_ABGRTOUVROW_MSA)
952 if (TestCpuFlag(kCpuHasMSA)) {
953 ABGRToYRow = ABGRToYRow_Any_MSA;
954 ABGRToUVRow = ABGRToUVRow_Any_MSA;
955 if (IS_ALIGNED(width, 16)) {
956 ABGRToYRow = ABGRToYRow_MSA;
957 }
958 if (IS_ALIGNED(width, 32)) {
959 ABGRToUVRow = ABGRToUVRow_MSA;
960 }
961 }
962 #endif
963 #if defined(HAS_ABGRTOYROW_LSX)
964 if (TestCpuFlag(kCpuHasLSX)) {
965 ABGRToYRow = ABGRToYRow_Any_LSX;
966 if (IS_ALIGNED(width, 16)) {
967 ABGRToYRow = ABGRToYRow_LSX;
968 }
969 }
970 #endif
971 #if defined(HAS_ABGRTOYROW_LASX)
972 if (TestCpuFlag(kCpuHasLASX)) {
973 ABGRToYRow = ABGRToYRow_Any_LASX;
974 if (IS_ALIGNED(width, 32)) {
975 ABGRToYRow = ABGRToYRow_LASX;
976 }
977 }
978 #endif
979 #if defined(HAS_ABGRTOYROW_RVV)
980 if (TestCpuFlag(kCpuHasRVV)) {
981 ABGRToYRow = ABGRToYRow_RVV;
982 }
983 #endif
984 #if defined(HAS_MERGEUVROW_SSE2)
985 if (TestCpuFlag(kCpuHasSSE2)) {
986 MergeUVRow_ = MergeUVRow_Any_SSE2;
987 if (IS_ALIGNED(halfwidth, 16)) {
988 MergeUVRow_ = MergeUVRow_SSE2;
989 }
990 }
991 #endif
992 #if defined(HAS_MERGEUVROW_AVX2)
993 if (TestCpuFlag(kCpuHasAVX2)) {
994 MergeUVRow_ = MergeUVRow_Any_AVX2;
995 if (IS_ALIGNED(halfwidth, 16)) {
996 MergeUVRow_ = MergeUVRow_AVX2;
997 }
998 }
999 #endif
1000 #if defined(HAS_MERGEUVROW_AVX512BW)
1001 if (TestCpuFlag(kCpuHasAVX512BW)) {
1002 MergeUVRow_ = MergeUVRow_Any_AVX512BW;
1003 if (IS_ALIGNED(halfwidth, 64)) {
1004 MergeUVRow_ = MergeUVRow_AVX512BW;
1005 }
1006 }
1007 #endif
1008 #if defined(HAS_MERGEUVROW_NEON)
1009 if (TestCpuFlag(kCpuHasNEON)) {
1010 MergeUVRow_ = MergeUVRow_Any_NEON;
1011 if (IS_ALIGNED(halfwidth, 16)) {
1012 MergeUVRow_ = MergeUVRow_NEON;
1013 }
1014 }
1015 #endif
1016 #if defined(HAS_MERGEUVROW_MSA)
1017 if (TestCpuFlag(kCpuHasMSA)) {
1018 MergeUVRow_ = MergeUVRow_Any_MSA;
1019 if (IS_ALIGNED(halfwidth, 16)) {
1020 MergeUVRow_ = MergeUVRow_MSA;
1021 }
1022 }
1023 #endif
1024 #if defined(HAS_MERGEUVROW_LSX)
1025 if (TestCpuFlag(kCpuHasLSX)) {
1026 MergeUVRow_ = MergeUVRow_Any_LSX;
1027 if (IS_ALIGNED(halfwidth, 16)) {
1028 MergeUVRow_ = MergeUVRow_LSX;
1029 }
1030 }
1031 #endif
1032 #if defined(HAS_MERGEUVROW_RVV)
1033 if (TestCpuFlag(kCpuHasRVV)) {
1034 MergeUVRow_ = MergeUVRow_RVV;
1035 }
1036 #endif
1037 {
1038 // Allocate a rows of uv.
1039 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
1040 uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
1041 if (!row_u)
1042 return 1;
1043
1044 for (y = 0; y < height - 1; y += 2) {
1045 ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
1046 MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1047 ABGRToYRow(src_abgr, dst_y, width);
1048 ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
1049 src_abgr += src_stride_abgr * 2;
1050 dst_y += dst_stride_y * 2;
1051 dst_vu += dst_stride_vu;
1052 }
1053 if (height & 1) {
1054 ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
1055 MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1056 ABGRToYRow(src_abgr, dst_y, width);
1057 }
1058 free_aligned_buffer_64(row_u);
1059 }
1060 return 0;
1061 }
1062
1063 // Convert ARGB to YUY2.
1064 LIBYUV_API
ARGBToYUY2(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yuy2,int dst_stride_yuy2,int width,int height)1065 int ARGBToYUY2(const uint8_t* src_argb,
1066 int src_stride_argb,
1067 uint8_t* dst_yuy2,
1068 int dst_stride_yuy2,
1069 int width,
1070 int height) {
1071 int y;
1072 void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1073 uint8_t* dst_u, uint8_t* dst_v, int width) =
1074 ARGBToUVRow_C;
1075 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1076 ARGBToYRow_C;
1077 void (*I422ToYUY2Row)(const uint8_t* src_y, const uint8_t* src_u,
1078 const uint8_t* src_v, uint8_t* dst_yuy2, int width) =
1079 I422ToYUY2Row_C;
1080
1081 if (!src_argb || !dst_yuy2 || width <= 0 || height == 0) {
1082 return -1;
1083 }
1084 // Negative height means invert the image.
1085 if (height < 0) {
1086 height = -height;
1087 dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
1088 dst_stride_yuy2 = -dst_stride_yuy2;
1089 }
1090 // Coalesce rows.
1091 if (src_stride_argb == width * 4 && dst_stride_yuy2 == width * 2) {
1092 width *= height;
1093 height = 1;
1094 src_stride_argb = dst_stride_yuy2 = 0;
1095 }
1096 #if defined(HAS_ARGBTOYROW_SSSE3)
1097 if (TestCpuFlag(kCpuHasSSSE3)) {
1098 ARGBToYRow = ARGBToYRow_Any_SSSE3;
1099 if (IS_ALIGNED(width, 16)) {
1100 ARGBToYRow = ARGBToYRow_SSSE3;
1101 }
1102 }
1103 #endif
1104 #if defined(HAS_ARGBTOUVROW_SSSE3)
1105 if (TestCpuFlag(kCpuHasSSSE3)) {
1106 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1107 if (IS_ALIGNED(width, 16)) {
1108 ARGBToUVRow = ARGBToUVRow_SSSE3;
1109 }
1110 }
1111 #endif
1112 #if defined(HAS_ARGBTOYROW_AVX2)
1113 if (TestCpuFlag(kCpuHasAVX2)) {
1114 ARGBToYRow = ARGBToYRow_Any_AVX2;
1115 if (IS_ALIGNED(width, 32)) {
1116 ARGBToYRow = ARGBToYRow_AVX2;
1117 }
1118 }
1119 #endif
1120 #if defined(HAS_ARGBTOUVROW_AVX2)
1121 if (TestCpuFlag(kCpuHasAVX2)) {
1122 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1123 if (IS_ALIGNED(width, 32)) {
1124 ARGBToUVRow = ARGBToUVRow_AVX2;
1125 }
1126 }
1127 #endif
1128 #if defined(HAS_ARGBTOYROW_NEON)
1129 if (TestCpuFlag(kCpuHasNEON)) {
1130 ARGBToYRow = ARGBToYRow_Any_NEON;
1131 if (IS_ALIGNED(width, 16)) {
1132 ARGBToYRow = ARGBToYRow_NEON;
1133 }
1134 }
1135 #endif
1136 #if defined(HAS_ARGBTOUVROW_NEON)
1137 if (TestCpuFlag(kCpuHasNEON)) {
1138 ARGBToUVRow = ARGBToUVRow_Any_NEON;
1139 if (IS_ALIGNED(width, 16)) {
1140 ARGBToUVRow = ARGBToUVRow_NEON;
1141 }
1142 }
1143 #endif
1144 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
1145 if (TestCpuFlag(kCpuHasMSA)) {
1146 ARGBToYRow = ARGBToYRow_Any_MSA;
1147 ARGBToUVRow = ARGBToUVRow_Any_MSA;
1148 if (IS_ALIGNED(width, 16)) {
1149 ARGBToYRow = ARGBToYRow_MSA;
1150 }
1151 if (IS_ALIGNED(width, 32)) {
1152 ARGBToUVRow = ARGBToUVRow_MSA;
1153 }
1154 }
1155 #endif
1156 #if defined(HAS_ARGBTOYROW_LSX)
1157 if (TestCpuFlag(kCpuHasLSX)) {
1158 ARGBToYRow = ARGBToYRow_Any_LSX;
1159 if (IS_ALIGNED(width, 16)) {
1160 ARGBToYRow = ARGBToYRow_LSX;
1161 }
1162 }
1163 #endif
1164 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1165 if (TestCpuFlag(kCpuHasLSX)) {
1166 ARGBToYRow = ARGBToYRow_Any_LSX;
1167 ARGBToUVRow = ARGBToUVRow_Any_LSX;
1168 if (IS_ALIGNED(width, 16)) {
1169 ARGBToYRow = ARGBToYRow_LSX;
1170 ARGBToUVRow = ARGBToUVRow_LSX;
1171 }
1172 }
1173 #endif
1174 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1175 if (TestCpuFlag(kCpuHasLASX)) {
1176 ARGBToYRow = ARGBToYRow_Any_LASX;
1177 ARGBToUVRow = ARGBToUVRow_Any_LASX;
1178 if (IS_ALIGNED(width, 32)) {
1179 ARGBToYRow = ARGBToYRow_LASX;
1180 ARGBToUVRow = ARGBToUVRow_LASX;
1181 }
1182 }
1183 #endif
1184 #if defined(HAS_ARGBTOYROW_RVV)
1185 if (TestCpuFlag(kCpuHasRVV)) {
1186 ARGBToYRow = ARGBToYRow_RVV;
1187 }
1188 #endif
1189 #if defined(HAS_I422TOYUY2ROW_SSE2)
1190 if (TestCpuFlag(kCpuHasSSE2)) {
1191 I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
1192 if (IS_ALIGNED(width, 16)) {
1193 I422ToYUY2Row = I422ToYUY2Row_SSE2;
1194 }
1195 }
1196 #endif
1197 #if defined(HAS_I422TOYUY2ROW_AVX2)
1198 if (TestCpuFlag(kCpuHasAVX2)) {
1199 I422ToYUY2Row = I422ToYUY2Row_Any_AVX2;
1200 if (IS_ALIGNED(width, 32)) {
1201 I422ToYUY2Row = I422ToYUY2Row_AVX2;
1202 }
1203 }
1204 #endif
1205 #if defined(HAS_I422TOYUY2ROW_NEON)
1206 if (TestCpuFlag(kCpuHasNEON)) {
1207 I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
1208 if (IS_ALIGNED(width, 16)) {
1209 I422ToYUY2Row = I422ToYUY2Row_NEON;
1210 }
1211 }
1212 #endif
1213 #if defined(HAS_I422TOYUY2ROW_MSA)
1214 if (TestCpuFlag(kCpuHasMSA)) {
1215 I422ToYUY2Row = I422ToYUY2Row_Any_MSA;
1216 if (IS_ALIGNED(width, 32)) {
1217 I422ToYUY2Row = I422ToYUY2Row_MSA;
1218 }
1219 }
1220 #endif
1221 #if defined(HAS_I422TOYUY2ROW_LSX)
1222 if (TestCpuFlag(kCpuHasLSX)) {
1223 I422ToYUY2Row = I422ToYUY2Row_Any_LSX;
1224 if (IS_ALIGNED(width, 16)) {
1225 I422ToYUY2Row = I422ToYUY2Row_LSX;
1226 }
1227 }
1228 #endif
1229 #if defined(HAS_I422TOYUY2ROW_LASX)
1230 if (TestCpuFlag(kCpuHasLASX)) {
1231 I422ToYUY2Row = I422ToYUY2Row_Any_LASX;
1232 if (IS_ALIGNED(width, 32)) {
1233 I422ToYUY2Row = I422ToYUY2Row_LASX;
1234 }
1235 }
1236 #endif
1237
1238 {
1239 // Allocate a rows of yuv.
1240 align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1241 uint8_t* row_u = row_y + ((width + 63) & ~63);
1242 uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1243 if (!row_y)
1244 return 1;
1245
1246 for (y = 0; y < height; ++y) {
1247 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1248 ARGBToYRow(src_argb, row_y, width);
1249 I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
1250 src_argb += src_stride_argb;
1251 dst_yuy2 += dst_stride_yuy2;
1252 }
1253
1254 free_aligned_buffer_64(row_y);
1255 }
1256 return 0;
1257 }
1258
1259 // Convert ARGB to UYVY.
1260 LIBYUV_API
ARGBToUYVY(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_uyvy,int dst_stride_uyvy,int width,int height)1261 int ARGBToUYVY(const uint8_t* src_argb,
1262 int src_stride_argb,
1263 uint8_t* dst_uyvy,
1264 int dst_stride_uyvy,
1265 int width,
1266 int height) {
1267 int y;
1268 void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1269 uint8_t* dst_u, uint8_t* dst_v, int width) =
1270 ARGBToUVRow_C;
1271 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1272 ARGBToYRow_C;
1273 void (*I422ToUYVYRow)(const uint8_t* src_y, const uint8_t* src_u,
1274 const uint8_t* src_v, uint8_t* dst_uyvy, int width) =
1275 I422ToUYVYRow_C;
1276
1277 if (!src_argb || !dst_uyvy || width <= 0 || height == 0) {
1278 return -1;
1279 }
1280 // Negative height means invert the image.
1281 if (height < 0) {
1282 height = -height;
1283 dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
1284 dst_stride_uyvy = -dst_stride_uyvy;
1285 }
1286 // Coalesce rows.
1287 if (src_stride_argb == width * 4 && dst_stride_uyvy == width * 2) {
1288 width *= height;
1289 height = 1;
1290 src_stride_argb = dst_stride_uyvy = 0;
1291 }
1292 #if defined(HAS_ARGBTOYROW_SSSE3)
1293 if (TestCpuFlag(kCpuHasSSSE3)) {
1294 ARGBToYRow = ARGBToYRow_Any_SSSE3;
1295 if (IS_ALIGNED(width, 16)) {
1296 ARGBToYRow = ARGBToYRow_SSSE3;
1297 }
1298 }
1299 #endif
1300 #if defined(HAS_ARGBTOUVROW_SSSE3)
1301 if (TestCpuFlag(kCpuHasSSSE3)) {
1302 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1303 if (IS_ALIGNED(width, 16)) {
1304 ARGBToUVRow = ARGBToUVRow_SSSE3;
1305 }
1306 }
1307 #endif
1308 #if defined(HAS_ARGBTOYROW_AVX2)
1309 if (TestCpuFlag(kCpuHasAVX2)) {
1310 ARGBToYRow = ARGBToYRow_Any_AVX2;
1311 if (IS_ALIGNED(width, 32)) {
1312 ARGBToYRow = ARGBToYRow_AVX2;
1313 }
1314 }
1315 #endif
1316 #if defined(HAS_ARGBTOUVROW_AVX2)
1317 if (TestCpuFlag(kCpuHasAVX2)) {
1318 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1319 if (IS_ALIGNED(width, 32)) {
1320 ARGBToUVRow = ARGBToUVRow_AVX2;
1321 }
1322 }
1323 #endif
1324 #if defined(HAS_ARGBTOYROW_NEON)
1325 if (TestCpuFlag(kCpuHasNEON)) {
1326 ARGBToYRow = ARGBToYRow_Any_NEON;
1327 if (IS_ALIGNED(width, 16)) {
1328 ARGBToYRow = ARGBToYRow_NEON;
1329 }
1330 }
1331 #endif
1332 #if defined(HAS_ARGBTOUVROW_NEON)
1333 if (TestCpuFlag(kCpuHasNEON)) {
1334 ARGBToUVRow = ARGBToUVRow_Any_NEON;
1335 if (IS_ALIGNED(width, 16)) {
1336 ARGBToUVRow = ARGBToUVRow_NEON;
1337 }
1338 }
1339 #endif
1340 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
1341 if (TestCpuFlag(kCpuHasMSA)) {
1342 ARGBToYRow = ARGBToYRow_Any_MSA;
1343 ARGBToUVRow = ARGBToUVRow_Any_MSA;
1344 if (IS_ALIGNED(width, 16)) {
1345 ARGBToYRow = ARGBToYRow_MSA;
1346 }
1347 if (IS_ALIGNED(width, 32)) {
1348 ARGBToUVRow = ARGBToUVRow_MSA;
1349 }
1350 }
1351 #endif
1352 #if defined(HAS_ARGBTOYROW_LSX)
1353 if (TestCpuFlag(kCpuHasLSX)) {
1354 ARGBToYRow = ARGBToYRow_Any_LSX;
1355 if (IS_ALIGNED(width, 16)) {
1356 ARGBToYRow = ARGBToYRow_LSX;
1357 }
1358 }
1359 #endif
1360 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1361 if (TestCpuFlag(kCpuHasLSX)) {
1362 ARGBToYRow = ARGBToYRow_Any_LSX;
1363 ARGBToUVRow = ARGBToUVRow_Any_LSX;
1364 if (IS_ALIGNED(width, 16)) {
1365 ARGBToYRow = ARGBToYRow_LSX;
1366 ARGBToUVRow = ARGBToUVRow_LSX;
1367 }
1368 }
1369 #endif
1370 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1371 if (TestCpuFlag(kCpuHasLASX)) {
1372 ARGBToYRow = ARGBToYRow_Any_LASX;
1373 ARGBToUVRow = ARGBToUVRow_Any_LASX;
1374 if (IS_ALIGNED(width, 32)) {
1375 ARGBToYRow = ARGBToYRow_LASX;
1376 ARGBToUVRow = ARGBToUVRow_LASX;
1377 }
1378 }
1379 #endif
1380 #if defined(HAS_ARGBTOYROW_RVV)
1381 if (TestCpuFlag(kCpuHasRVV)) {
1382 ARGBToYRow = ARGBToYRow_RVV;
1383 }
1384 #endif
1385 #if defined(HAS_I422TOUYVYROW_SSE2)
1386 if (TestCpuFlag(kCpuHasSSE2)) {
1387 I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
1388 if (IS_ALIGNED(width, 16)) {
1389 I422ToUYVYRow = I422ToUYVYRow_SSE2;
1390 }
1391 }
1392 #endif
1393 #if defined(HAS_I422TOUYVYROW_AVX2)
1394 if (TestCpuFlag(kCpuHasAVX2)) {
1395 I422ToUYVYRow = I422ToUYVYRow_Any_AVX2;
1396 if (IS_ALIGNED(width, 32)) {
1397 I422ToUYVYRow = I422ToUYVYRow_AVX2;
1398 }
1399 }
1400 #endif
1401 #if defined(HAS_I422TOUYVYROW_NEON)
1402 if (TestCpuFlag(kCpuHasNEON)) {
1403 I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
1404 if (IS_ALIGNED(width, 16)) {
1405 I422ToUYVYRow = I422ToUYVYRow_NEON;
1406 }
1407 }
1408 #endif
1409 #if defined(HAS_I422TOUYVYROW_MSA)
1410 if (TestCpuFlag(kCpuHasMSA)) {
1411 I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
1412 if (IS_ALIGNED(width, 32)) {
1413 I422ToUYVYRow = I422ToUYVYRow_MSA;
1414 }
1415 }
1416 #endif
1417 #if defined(HAS_I422TOUYVYROW_LSX)
1418 if (TestCpuFlag(kCpuHasLSX)) {
1419 I422ToUYVYRow = I422ToUYVYRow_Any_LSX;
1420 if (IS_ALIGNED(width, 16)) {
1421 I422ToUYVYRow = I422ToUYVYRow_LSX;
1422 }
1423 }
1424 #endif
1425 #if defined(HAS_I422TOUYVYROW_LASX)
1426 if (TestCpuFlag(kCpuHasLASX)) {
1427 I422ToUYVYRow = I422ToUYVYRow_Any_LASX;
1428 if (IS_ALIGNED(width, 32)) {
1429 I422ToUYVYRow = I422ToUYVYRow_LASX;
1430 }
1431 }
1432 #endif
1433
1434 {
1435 // Allocate a rows of yuv.
1436 align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1437 uint8_t* row_u = row_y + ((width + 63) & ~63);
1438 uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1439 if (!row_y)
1440 return 1;
1441
1442 for (y = 0; y < height; ++y) {
1443 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1444 ARGBToYRow(src_argb, row_y, width);
1445 I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
1446 src_argb += src_stride_argb;
1447 dst_uyvy += dst_stride_uyvy;
1448 }
1449
1450 free_aligned_buffer_64(row_y);
1451 }
1452 return 0;
1453 }
1454
1455 // Convert ARGB to I400.
1456 LIBYUV_API
ARGBToI400(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,int width,int height)1457 int ARGBToI400(const uint8_t* src_argb,
1458 int src_stride_argb,
1459 uint8_t* dst_y,
1460 int dst_stride_y,
1461 int width,
1462 int height) {
1463 int y;
1464 void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1465 ARGBToYRow_C;
1466 if (!src_argb || !dst_y || width <= 0 || height == 0) {
1467 return -1;
1468 }
1469 if (height < 0) {
1470 height = -height;
1471 src_argb = src_argb + (height - 1) * src_stride_argb;
1472 src_stride_argb = -src_stride_argb;
1473 }
1474 // Coalesce rows.
1475 if (src_stride_argb == width * 4 && dst_stride_y == width) {
1476 width *= height;
1477 height = 1;
1478 src_stride_argb = dst_stride_y = 0;
1479 }
1480 #if defined(HAS_ARGBTOYROW_SSSE3)
1481 if (TestCpuFlag(kCpuHasSSSE3)) {
1482 ARGBToYRow = ARGBToYRow_Any_SSSE3;
1483 if (IS_ALIGNED(width, 16)) {
1484 ARGBToYRow = ARGBToYRow_SSSE3;
1485 }
1486 }
1487 #endif
1488 #if defined(HAS_ARGBTOYROW_AVX2)
1489 if (TestCpuFlag(kCpuHasAVX2)) {
1490 ARGBToYRow = ARGBToYRow_Any_AVX2;
1491 if (IS_ALIGNED(width, 32)) {
1492 ARGBToYRow = ARGBToYRow_AVX2;
1493 }
1494 }
1495 #endif
1496 #if defined(HAS_ARGBTOYROW_NEON)
1497 if (TestCpuFlag(kCpuHasNEON)) {
1498 ARGBToYRow = ARGBToYRow_Any_NEON;
1499 if (IS_ALIGNED(width, 16)) {
1500 ARGBToYRow = ARGBToYRow_NEON;
1501 }
1502 }
1503 #endif
1504 #if defined(HAS_ARGBTOYROW_MSA)
1505 if (TestCpuFlag(kCpuHasMSA)) {
1506 ARGBToYRow = ARGBToYRow_Any_MSA;
1507 if (IS_ALIGNED(width, 16)) {
1508 ARGBToYRow = ARGBToYRow_MSA;
1509 }
1510 }
1511 #endif
1512 #if defined(HAS_ARGBTOYROW_LSX)
1513 if (TestCpuFlag(kCpuHasLSX)) {
1514 ARGBToYRow = ARGBToYRow_Any_LSX;
1515 if (IS_ALIGNED(width, 16)) {
1516 ARGBToYRow = ARGBToYRow_LSX;
1517 }
1518 }
1519 #endif
1520 #if defined(HAS_ARGBTOYROW_LASX)
1521 if (TestCpuFlag(kCpuHasLASX)) {
1522 ARGBToYRow = ARGBToYRow_Any_LASX;
1523 if (IS_ALIGNED(width, 32)) {
1524 ARGBToYRow = ARGBToYRow_LASX;
1525 }
1526 }
1527 #endif
1528 #if defined(HAS_ARGBTOYROW_RVV)
1529 if (TestCpuFlag(kCpuHasRVV)) {
1530 ARGBToYRow = ARGBToYRow_RVV;
1531 }
1532 #endif
1533
1534 for (y = 0; y < height; ++y) {
1535 ARGBToYRow(src_argb, dst_y, width);
1536 src_argb += src_stride_argb;
1537 dst_y += dst_stride_y;
1538 }
1539 return 0;
1540 }
1541
1542 #ifndef __riscv
1543 // Shuffle table for converting ARGB to RGBA.
1544 static const uvec8 kShuffleMaskARGBToRGBA = {
1545 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u};
1546
1547 // Convert ARGB to RGBA.
1548 LIBYUV_API
ARGBToRGBA(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1549 int ARGBToRGBA(const uint8_t* src_argb,
1550 int src_stride_argb,
1551 uint8_t* dst_rgba,
1552 int dst_stride_rgba,
1553 int width,
1554 int height) {
1555 return ARGBShuffle(src_argb, src_stride_argb, dst_rgba, dst_stride_rgba,
1556 (const uint8_t*)(&kShuffleMaskARGBToRGBA), width, height);
1557 }
1558 #else
1559 // Convert ARGB to RGBA.
1560 LIBYUV_API
ARGBToRGBA(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1561 int ARGBToRGBA(const uint8_t* src_argb,
1562 int src_stride_argb,
1563 uint8_t* dst_rgba,
1564 int dst_stride_rgba,
1565 int width,
1566 int height) {
1567 int y;
1568 void (*ARGBToRGBARow)(const uint8_t* src_argb, uint8_t* dst_rgba, int width) =
1569 ARGBToRGBARow_C;
1570 if (!src_argb || !dst_rgba || width <= 0 || height == 0) {
1571 return -1;
1572 }
1573 if (height < 0) {
1574 height = -height;
1575 src_argb = src_argb + (height - 1) * src_stride_argb;
1576 src_stride_argb = -src_stride_argb;
1577 }
1578 // Coalesce rows.
1579 if (src_stride_argb == width * 4 && dst_stride_rgba == width * 4) {
1580 width *= height;
1581 height = 1;
1582 src_stride_argb = dst_stride_rgba = 0;
1583 }
1584
1585 #if defined(HAS_ARGBTORGBAROW_RVV)
1586 if (TestCpuFlag(kCpuHasRVV)) {
1587 ARGBToRGBARow = ARGBToRGBARow_RVV;
1588 }
1589 #endif
1590
1591 for (y = 0; y < height; ++y) {
1592 ARGBToRGBARow(src_argb, dst_rgba, width);
1593 src_argb += src_stride_argb;
1594 dst_rgba += dst_stride_rgba;
1595 }
1596 return 0;
1597 }
1598 #endif
1599
1600 // Convert ARGB To RGB24.
1601 LIBYUV_API
ARGBToRGB24(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)1602 int ARGBToRGB24(const uint8_t* src_argb,
1603 int src_stride_argb,
1604 uint8_t* dst_rgb24,
1605 int dst_stride_rgb24,
1606 int width,
1607 int height) {
1608 int y;
1609 void (*ARGBToRGB24Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1610 ARGBToRGB24Row_C;
1611 if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
1612 return -1;
1613 }
1614 if (height < 0) {
1615 height = -height;
1616 src_argb = src_argb + (height - 1) * src_stride_argb;
1617 src_stride_argb = -src_stride_argb;
1618 }
1619 // Coalesce rows.
1620 if (src_stride_argb == width * 4 && dst_stride_rgb24 == width * 3) {
1621 width *= height;
1622 height = 1;
1623 src_stride_argb = dst_stride_rgb24 = 0;
1624 }
1625 #if defined(HAS_ARGBTORGB24ROW_SSSE3)
1626 if (TestCpuFlag(kCpuHasSSSE3)) {
1627 ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
1628 if (IS_ALIGNED(width, 16)) {
1629 ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
1630 }
1631 }
1632 #endif
1633 #if defined(HAS_ARGBTORGB24ROW_AVX2)
1634 if (TestCpuFlag(kCpuHasAVX2)) {
1635 ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX2;
1636 if (IS_ALIGNED(width, 32)) {
1637 ARGBToRGB24Row = ARGBToRGB24Row_AVX2;
1638 }
1639 }
1640 #endif
1641 #if defined(HAS_ARGBTORGB24ROW_AVX512VBMI)
1642 if (TestCpuFlag(kCpuHasAVX512VBMI)) {
1643 ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX512VBMI;
1644 if (IS_ALIGNED(width, 32)) {
1645 ARGBToRGB24Row = ARGBToRGB24Row_AVX512VBMI;
1646 }
1647 }
1648 #endif
1649 #if defined(HAS_ARGBTORGB24ROW_NEON)
1650 if (TestCpuFlag(kCpuHasNEON)) {
1651 ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
1652 if (IS_ALIGNED(width, 16)) {
1653 ARGBToRGB24Row = ARGBToRGB24Row_NEON;
1654 }
1655 }
1656 #endif
1657 #if defined(HAS_ARGBTORGB24ROW_MSA)
1658 if (TestCpuFlag(kCpuHasMSA)) {
1659 ARGBToRGB24Row = ARGBToRGB24Row_Any_MSA;
1660 if (IS_ALIGNED(width, 16)) {
1661 ARGBToRGB24Row = ARGBToRGB24Row_MSA;
1662 }
1663 }
1664 #endif
1665 #if defined(HAS_ARGBTORGB24ROW_LSX)
1666 if (TestCpuFlag(kCpuHasLSX)) {
1667 ARGBToRGB24Row = ARGBToRGB24Row_Any_LSX;
1668 if (IS_ALIGNED(width, 16)) {
1669 ARGBToRGB24Row = ARGBToRGB24Row_LSX;
1670 }
1671 }
1672 #endif
1673 #if defined(HAS_ARGBTORGB24ROW_LASX)
1674 if (TestCpuFlag(kCpuHasLASX)) {
1675 ARGBToRGB24Row = ARGBToRGB24Row_Any_LASX;
1676 if (IS_ALIGNED(width, 32)) {
1677 ARGBToRGB24Row = ARGBToRGB24Row_LASX;
1678 }
1679 }
1680 #endif
1681 #if defined(HAS_ARGBTORGB24ROW_RVV)
1682 if (TestCpuFlag(kCpuHasRVV)) {
1683 ARGBToRGB24Row = ARGBToRGB24Row_RVV;
1684 }
1685 #endif
1686
1687 for (y = 0; y < height; ++y) {
1688 ARGBToRGB24Row(src_argb, dst_rgb24, width);
1689 src_argb += src_stride_argb;
1690 dst_rgb24 += dst_stride_rgb24;
1691 }
1692 return 0;
1693 }
1694
1695 // Convert ARGB To RAW.
1696 LIBYUV_API
ARGBToRAW(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_raw,int dst_stride_raw,int width,int height)1697 int ARGBToRAW(const uint8_t* src_argb,
1698 int src_stride_argb,
1699 uint8_t* dst_raw,
1700 int dst_stride_raw,
1701 int width,
1702 int height) {
1703 int y;
1704 void (*ARGBToRAWRow)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1705 ARGBToRAWRow_C;
1706 if (!src_argb || !dst_raw || width <= 0 || height == 0) {
1707 return -1;
1708 }
1709 if (height < 0) {
1710 height = -height;
1711 src_argb = src_argb + (height - 1) * src_stride_argb;
1712 src_stride_argb = -src_stride_argb;
1713 }
1714 // Coalesce rows.
1715 if (src_stride_argb == width * 4 && dst_stride_raw == width * 3) {
1716 width *= height;
1717 height = 1;
1718 src_stride_argb = dst_stride_raw = 0;
1719 }
1720 #if defined(HAS_ARGBTORAWROW_SSSE3)
1721 if (TestCpuFlag(kCpuHasSSSE3)) {
1722 ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
1723 if (IS_ALIGNED(width, 16)) {
1724 ARGBToRAWRow = ARGBToRAWRow_SSSE3;
1725 }
1726 }
1727 #endif
1728 #if defined(HAS_ARGBTORAWROW_AVX2)
1729 if (TestCpuFlag(kCpuHasAVX2)) {
1730 ARGBToRAWRow = ARGBToRAWRow_Any_AVX2;
1731 if (IS_ALIGNED(width, 32)) {
1732 ARGBToRAWRow = ARGBToRAWRow_AVX2;
1733 }
1734 }
1735 #endif
1736 #if defined(HAS_ARGBTORAWROW_NEON)
1737 if (TestCpuFlag(kCpuHasNEON)) {
1738 ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
1739 if (IS_ALIGNED(width, 8)) {
1740 ARGBToRAWRow = ARGBToRAWRow_NEON;
1741 }
1742 }
1743 #endif
1744 #if defined(HAS_ARGBTORAWROW_MSA)
1745 if (TestCpuFlag(kCpuHasMSA)) {
1746 ARGBToRAWRow = ARGBToRAWRow_Any_MSA;
1747 if (IS_ALIGNED(width, 16)) {
1748 ARGBToRAWRow = ARGBToRAWRow_MSA;
1749 }
1750 }
1751 #endif
1752 #if defined(HAS_ARGBTORAWROW_LSX)
1753 if (TestCpuFlag(kCpuHasLSX)) {
1754 ARGBToRAWRow = ARGBToRAWRow_Any_LSX;
1755 if (IS_ALIGNED(width, 16)) {
1756 ARGBToRAWRow = ARGBToRAWRow_LSX;
1757 }
1758 }
1759 #endif
1760 #if defined(HAS_ARGBTORAWROW_LASX)
1761 if (TestCpuFlag(kCpuHasLASX)) {
1762 ARGBToRAWRow = ARGBToRAWRow_Any_LASX;
1763 if (IS_ALIGNED(width, 32)) {
1764 ARGBToRAWRow = ARGBToRAWRow_LASX;
1765 }
1766 }
1767 #endif
1768 #if defined(HAS_ARGBTORAWROW_RVV)
1769 if (TestCpuFlag(kCpuHasRVV)) {
1770 ARGBToRAWRow = ARGBToRAWRow_RVV;
1771 }
1772 #endif
1773
1774 for (y = 0; y < height; ++y) {
1775 ARGBToRAWRow(src_argb, dst_raw, width);
1776 src_argb += src_stride_argb;
1777 dst_raw += dst_stride_raw;
1778 }
1779 return 0;
1780 }
1781
1782 // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
1783 static const uint8_t kDither565_4x4[16] = {
1784 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
1785 };
1786
1787 // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
1788 LIBYUV_API
ARGBToRGB565Dither(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb565,int dst_stride_rgb565,const uint8_t * dither4x4,int width,int height)1789 int ARGBToRGB565Dither(const uint8_t* src_argb,
1790 int src_stride_argb,
1791 uint8_t* dst_rgb565,
1792 int dst_stride_rgb565,
1793 const uint8_t* dither4x4,
1794 int width,
1795 int height) {
1796 int y;
1797 void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
1798 uint32_t dither4, int width) =
1799 ARGBToRGB565DitherRow_C;
1800 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1801 return -1;
1802 }
1803 if (height < 0) {
1804 height = -height;
1805 src_argb = src_argb + (height - 1) * src_stride_argb;
1806 src_stride_argb = -src_stride_argb;
1807 }
1808 if (!dither4x4) {
1809 dither4x4 = kDither565_4x4;
1810 }
1811 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
1812 if (TestCpuFlag(kCpuHasSSE2)) {
1813 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
1814 if (IS_ALIGNED(width, 4)) {
1815 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
1816 }
1817 }
1818 #endif
1819 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
1820 if (TestCpuFlag(kCpuHasAVX2)) {
1821 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
1822 if (IS_ALIGNED(width, 8)) {
1823 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
1824 }
1825 }
1826 #endif
1827 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
1828 if (TestCpuFlag(kCpuHasNEON)) {
1829 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
1830 if (IS_ALIGNED(width, 8)) {
1831 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
1832 }
1833 }
1834 #endif
1835 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
1836 if (TestCpuFlag(kCpuHasMSA)) {
1837 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
1838 if (IS_ALIGNED(width, 8)) {
1839 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
1840 }
1841 }
1842 #endif
1843 #if defined(HAS_ARGBTORGB565DITHERROW_LSX)
1844 if (TestCpuFlag(kCpuHasLSX)) {
1845 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
1846 if (IS_ALIGNED(width, 8)) {
1847 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
1848 }
1849 }
1850 #endif
1851 #if defined(HAS_ARGBTORGB565DITHERROW_LASX)
1852 if (TestCpuFlag(kCpuHasLASX)) {
1853 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
1854 if (IS_ALIGNED(width, 16)) {
1855 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
1856 }
1857 }
1858 #endif
1859
1860 for (y = 0; y < height; ++y) {
1861 ARGBToRGB565DitherRow(src_argb, dst_rgb565,
1862 *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
1863 width);
1864 src_argb += src_stride_argb;
1865 dst_rgb565 += dst_stride_rgb565;
1866 }
1867 return 0;
1868 }
1869
1870 // Convert ARGB To RGB565.
1871 // TODO(fbarchard): Consider using dither function low level with zeros.
1872 LIBYUV_API
ARGBToRGB565(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)1873 int ARGBToRGB565(const uint8_t* src_argb,
1874 int src_stride_argb,
1875 uint8_t* dst_rgb565,
1876 int dst_stride_rgb565,
1877 int width,
1878 int height) {
1879 int y;
1880 void (*ARGBToRGB565Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
1881 int width) = ARGBToRGB565Row_C;
1882 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1883 return -1;
1884 }
1885 if (height < 0) {
1886 height = -height;
1887 src_argb = src_argb + (height - 1) * src_stride_argb;
1888 src_stride_argb = -src_stride_argb;
1889 }
1890 // Coalesce rows.
1891 if (src_stride_argb == width * 4 && dst_stride_rgb565 == width * 2) {
1892 width *= height;
1893 height = 1;
1894 src_stride_argb = dst_stride_rgb565 = 0;
1895 }
1896 #if defined(HAS_ARGBTORGB565ROW_SSE2)
1897 if (TestCpuFlag(kCpuHasSSE2)) {
1898 ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
1899 if (IS_ALIGNED(width, 4)) {
1900 ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
1901 }
1902 }
1903 #endif
1904 #if defined(HAS_ARGBTORGB565ROW_AVX2)
1905 if (TestCpuFlag(kCpuHasAVX2)) {
1906 ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2;
1907 if (IS_ALIGNED(width, 8)) {
1908 ARGBToRGB565Row = ARGBToRGB565Row_AVX2;
1909 }
1910 }
1911 #endif
1912 #if defined(HAS_ARGBTORGB565ROW_NEON)
1913 if (TestCpuFlag(kCpuHasNEON)) {
1914 ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
1915 if (IS_ALIGNED(width, 8)) {
1916 ARGBToRGB565Row = ARGBToRGB565Row_NEON;
1917 }
1918 }
1919 #endif
1920 #if defined(HAS_ARGBTORGB565ROW_MSA)
1921 if (TestCpuFlag(kCpuHasMSA)) {
1922 ARGBToRGB565Row = ARGBToRGB565Row_Any_MSA;
1923 if (IS_ALIGNED(width, 8)) {
1924 ARGBToRGB565Row = ARGBToRGB565Row_MSA;
1925 }
1926 }
1927 #endif
1928 #if defined(HAS_ARGBTORGB565ROW_LSX)
1929 if (TestCpuFlag(kCpuHasLSX)) {
1930 ARGBToRGB565Row = ARGBToRGB565Row_Any_LSX;
1931 if (IS_ALIGNED(width, 8)) {
1932 ARGBToRGB565Row = ARGBToRGB565Row_LSX;
1933 }
1934 }
1935 #endif
1936
1937 #if defined(HAS_ARGBTORGB565ROW_LASX)
1938 if (TestCpuFlag(kCpuHasLASX)) {
1939 ARGBToRGB565Row = ARGBToRGB565Row_Any_LASX;
1940 if (IS_ALIGNED(width, 16)) {
1941 ARGBToRGB565Row = ARGBToRGB565Row_LASX;
1942 }
1943 }
1944 #endif
1945
1946 for (y = 0; y < height; ++y) {
1947 ARGBToRGB565Row(src_argb, dst_rgb565, width);
1948 src_argb += src_stride_argb;
1949 dst_rgb565 += dst_stride_rgb565;
1950 }
1951 return 0;
1952 }
1953
1954 // Convert ARGB To ARGB1555.
1955 LIBYUV_API
ARGBToARGB1555(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb1555,int dst_stride_argb1555,int width,int height)1956 int ARGBToARGB1555(const uint8_t* src_argb,
1957 int src_stride_argb,
1958 uint8_t* dst_argb1555,
1959 int dst_stride_argb1555,
1960 int width,
1961 int height) {
1962 int y;
1963 void (*ARGBToARGB1555Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
1964 int width) = ARGBToARGB1555Row_C;
1965 if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
1966 return -1;
1967 }
1968 if (height < 0) {
1969 height = -height;
1970 src_argb = src_argb + (height - 1) * src_stride_argb;
1971 src_stride_argb = -src_stride_argb;
1972 }
1973 // Coalesce rows.
1974 if (src_stride_argb == width * 4 && dst_stride_argb1555 == width * 2) {
1975 width *= height;
1976 height = 1;
1977 src_stride_argb = dst_stride_argb1555 = 0;
1978 }
1979 #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
1980 if (TestCpuFlag(kCpuHasSSE2)) {
1981 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
1982 if (IS_ALIGNED(width, 4)) {
1983 ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
1984 }
1985 }
1986 #endif
1987 #if defined(HAS_ARGBTOARGB1555ROW_AVX2)
1988 if (TestCpuFlag(kCpuHasAVX2)) {
1989 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2;
1990 if (IS_ALIGNED(width, 8)) {
1991 ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2;
1992 }
1993 }
1994 #endif
1995 #if defined(HAS_ARGBTOARGB1555ROW_NEON)
1996 if (TestCpuFlag(kCpuHasNEON)) {
1997 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
1998 if (IS_ALIGNED(width, 8)) {
1999 ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
2000 }
2001 }
2002 #endif
2003 #if defined(HAS_ARGBTOARGB1555ROW_MSA)
2004 if (TestCpuFlag(kCpuHasMSA)) {
2005 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_MSA;
2006 if (IS_ALIGNED(width, 8)) {
2007 ARGBToARGB1555Row = ARGBToARGB1555Row_MSA;
2008 }
2009 }
2010 #endif
2011 #if defined(HAS_ARGBTOARGB1555ROW_LSX)
2012 if (TestCpuFlag(kCpuHasLSX)) {
2013 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LSX;
2014 if (IS_ALIGNED(width, 8)) {
2015 ARGBToARGB1555Row = ARGBToARGB1555Row_LSX;
2016 }
2017 }
2018 #endif
2019 #if defined(HAS_ARGBTOARGB1555ROW_LASX)
2020 if (TestCpuFlag(kCpuHasLASX)) {
2021 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LASX;
2022 if (IS_ALIGNED(width, 16)) {
2023 ARGBToARGB1555Row = ARGBToARGB1555Row_LASX;
2024 }
2025 }
2026 #endif
2027
2028 for (y = 0; y < height; ++y) {
2029 ARGBToARGB1555Row(src_argb, dst_argb1555, width);
2030 src_argb += src_stride_argb;
2031 dst_argb1555 += dst_stride_argb1555;
2032 }
2033 return 0;
2034 }
2035
2036 // Convert ARGB To ARGB4444.
2037 LIBYUV_API
ARGBToARGB4444(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb4444,int dst_stride_argb4444,int width,int height)2038 int ARGBToARGB4444(const uint8_t* src_argb,
2039 int src_stride_argb,
2040 uint8_t* dst_argb4444,
2041 int dst_stride_argb4444,
2042 int width,
2043 int height) {
2044 int y;
2045 void (*ARGBToARGB4444Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
2046 int width) = ARGBToARGB4444Row_C;
2047 if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
2048 return -1;
2049 }
2050 if (height < 0) {
2051 height = -height;
2052 src_argb = src_argb + (height - 1) * src_stride_argb;
2053 src_stride_argb = -src_stride_argb;
2054 }
2055 // Coalesce rows.
2056 if (src_stride_argb == width * 4 && dst_stride_argb4444 == width * 2) {
2057 width *= height;
2058 height = 1;
2059 src_stride_argb = dst_stride_argb4444 = 0;
2060 }
2061 #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
2062 if (TestCpuFlag(kCpuHasSSE2)) {
2063 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
2064 if (IS_ALIGNED(width, 4)) {
2065 ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
2066 }
2067 }
2068 #endif
2069 #if defined(HAS_ARGBTOARGB4444ROW_AVX2)
2070 if (TestCpuFlag(kCpuHasAVX2)) {
2071 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2;
2072 if (IS_ALIGNED(width, 8)) {
2073 ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2;
2074 }
2075 }
2076 #endif
2077 #if defined(HAS_ARGBTOARGB4444ROW_NEON)
2078 if (TestCpuFlag(kCpuHasNEON)) {
2079 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
2080 if (IS_ALIGNED(width, 8)) {
2081 ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
2082 }
2083 }
2084 #endif
2085 #if defined(HAS_ARGBTOARGB4444ROW_MSA)
2086 if (TestCpuFlag(kCpuHasMSA)) {
2087 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_MSA;
2088 if (IS_ALIGNED(width, 8)) {
2089 ARGBToARGB4444Row = ARGBToARGB4444Row_MSA;
2090 }
2091 }
2092 #endif
2093 #if defined(HAS_ARGBTOARGB4444ROW_LSX)
2094 if (TestCpuFlag(kCpuHasLSX)) {
2095 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LSX;
2096 if (IS_ALIGNED(width, 8)) {
2097 ARGBToARGB4444Row = ARGBToARGB4444Row_LSX;
2098 }
2099 }
2100 #endif
2101 #if defined(HAS_ARGBTOARGB4444ROW_LASX)
2102 if (TestCpuFlag(kCpuHasLASX)) {
2103 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LASX;
2104 if (IS_ALIGNED(width, 16)) {
2105 ARGBToARGB4444Row = ARGBToARGB4444Row_LASX;
2106 }
2107 }
2108 #endif
2109
2110 for (y = 0; y < height; ++y) {
2111 ARGBToARGB4444Row(src_argb, dst_argb4444, width);
2112 src_argb += src_stride_argb;
2113 dst_argb4444 += dst_stride_argb4444;
2114 }
2115 return 0;
2116 }
2117
2118 // Convert ABGR To AR30.
2119 LIBYUV_API
ABGRToAR30(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)2120 int ABGRToAR30(const uint8_t* src_abgr,
2121 int src_stride_abgr,
2122 uint8_t* dst_ar30,
2123 int dst_stride_ar30,
2124 int width,
2125 int height) {
2126 int y;
2127 void (*ABGRToAR30Row)(const uint8_t* src_abgr, uint8_t* dst_rgb, int width) =
2128 ABGRToAR30Row_C;
2129 if (!src_abgr || !dst_ar30 || width <= 0 || height == 0) {
2130 return -1;
2131 }
2132 if (height < 0) {
2133 height = -height;
2134 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2135 src_stride_abgr = -src_stride_abgr;
2136 }
2137 // Coalesce rows.
2138 if (src_stride_abgr == width * 4 && dst_stride_ar30 == width * 4) {
2139 width *= height;
2140 height = 1;
2141 src_stride_abgr = dst_stride_ar30 = 0;
2142 }
2143 #if defined(HAS_ABGRTOAR30ROW_SSSE3)
2144 if (TestCpuFlag(kCpuHasSSSE3)) {
2145 ABGRToAR30Row = ABGRToAR30Row_Any_SSSE3;
2146 if (IS_ALIGNED(width, 4)) {
2147 ABGRToAR30Row = ABGRToAR30Row_SSSE3;
2148 }
2149 }
2150 #endif
2151 #if defined(HAS_ABGRTOAR30ROW_AVX2)
2152 if (TestCpuFlag(kCpuHasAVX2)) {
2153 ABGRToAR30Row = ABGRToAR30Row_Any_AVX2;
2154 if (IS_ALIGNED(width, 8)) {
2155 ABGRToAR30Row = ABGRToAR30Row_AVX2;
2156 }
2157 }
2158 #endif
2159 for (y = 0; y < height; ++y) {
2160 ABGRToAR30Row(src_abgr, dst_ar30, width);
2161 src_abgr += src_stride_abgr;
2162 dst_ar30 += dst_stride_ar30;
2163 }
2164 return 0;
2165 }
2166
2167 // Convert ARGB To AR30.
2168 LIBYUV_API
ARGBToAR30(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)2169 int ARGBToAR30(const uint8_t* src_argb,
2170 int src_stride_argb,
2171 uint8_t* dst_ar30,
2172 int dst_stride_ar30,
2173 int width,
2174 int height) {
2175 int y;
2176 void (*ARGBToAR30Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
2177 ARGBToAR30Row_C;
2178 if (!src_argb || !dst_ar30 || width <= 0 || height == 0) {
2179 return -1;
2180 }
2181 if (height < 0) {
2182 height = -height;
2183 src_argb = src_argb + (height - 1) * src_stride_argb;
2184 src_stride_argb = -src_stride_argb;
2185 }
2186 // Coalesce rows.
2187 if (src_stride_argb == width * 4 && dst_stride_ar30 == width * 4) {
2188 width *= height;
2189 height = 1;
2190 src_stride_argb = dst_stride_ar30 = 0;
2191 }
2192 #if defined(HAS_ARGBTOAR30ROW_SSSE3)
2193 if (TestCpuFlag(kCpuHasSSSE3)) {
2194 ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3;
2195 if (IS_ALIGNED(width, 4)) {
2196 ARGBToAR30Row = ARGBToAR30Row_SSSE3;
2197 }
2198 }
2199 #endif
2200 #if defined(HAS_ARGBTOAR30ROW_AVX2)
2201 if (TestCpuFlag(kCpuHasAVX2)) {
2202 ARGBToAR30Row = ARGBToAR30Row_Any_AVX2;
2203 if (IS_ALIGNED(width, 8)) {
2204 ARGBToAR30Row = ARGBToAR30Row_AVX2;
2205 }
2206 }
2207 #endif
2208 for (y = 0; y < height; ++y) {
2209 ARGBToAR30Row(src_argb, dst_ar30, width);
2210 src_argb += src_stride_argb;
2211 dst_ar30 += dst_stride_ar30;
2212 }
2213 return 0;
2214 }
2215
2216 // Convert ARGB to J420. (JPeg full range I420).
2217 LIBYUV_API
ARGBToJ420(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2218 int ARGBToJ420(const uint8_t* src_argb,
2219 int src_stride_argb,
2220 uint8_t* dst_yj,
2221 int dst_stride_yj,
2222 uint8_t* dst_uj,
2223 int dst_stride_uj,
2224 uint8_t* dst_vj,
2225 int dst_stride_vj,
2226 int width,
2227 int height) {
2228 int y;
2229 void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2230 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2231 ARGBToUVJRow_C;
2232 void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2233 ARGBToYJRow_C;
2234 if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2235 return -1;
2236 }
2237 // Negative height means invert the image.
2238 if (height < 0) {
2239 height = -height;
2240 src_argb = src_argb + (height - 1) * src_stride_argb;
2241 src_stride_argb = -src_stride_argb;
2242 }
2243 #if defined(HAS_ARGBTOYJROW_NEON)
2244 if (TestCpuFlag(kCpuHasNEON)) {
2245 ARGBToYJRow = ARGBToYJRow_Any_NEON;
2246 if (IS_ALIGNED(width, 16)) {
2247 ARGBToYJRow = ARGBToYJRow_NEON;
2248 }
2249 }
2250 #endif
2251 #if defined(HAS_ARGBTOUVJROW_NEON)
2252 if (TestCpuFlag(kCpuHasNEON)) {
2253 ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2254 if (IS_ALIGNED(width, 16)) {
2255 ARGBToUVJRow = ARGBToUVJRow_NEON;
2256 }
2257 }
2258 #endif
2259 #if defined(HAS_ARGBTOYJROW_SSSE3)
2260 if (TestCpuFlag(kCpuHasSSSE3)) {
2261 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2262 if (IS_ALIGNED(width, 16)) {
2263 ARGBToYJRow = ARGBToYJRow_SSSE3;
2264 }
2265 }
2266 #endif
2267 #if defined(HAS_ARGBTOUVJROW_SSSE3)
2268 if (TestCpuFlag(kCpuHasSSSE3)) {
2269 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2270 if (IS_ALIGNED(width, 16)) {
2271 ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2272 }
2273 }
2274 #endif
2275 #if defined(HAS_ARGBTOYJROW_AVX2)
2276 if (TestCpuFlag(kCpuHasAVX2)) {
2277 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2278 if (IS_ALIGNED(width, 32)) {
2279 ARGBToYJRow = ARGBToYJRow_AVX2;
2280 }
2281 }
2282 #endif
2283 #if defined(HAS_ARGBTOUVJROW_AVX2)
2284 if (TestCpuFlag(kCpuHasAVX2)) {
2285 ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2286 if (IS_ALIGNED(width, 32)) {
2287 ARGBToUVJRow = ARGBToUVJRow_AVX2;
2288 }
2289 }
2290 #endif
2291 #if defined(HAS_ARGBTOYJROW_MSA) && defined(HAS_ARGBTOUVJROW_MSA)
2292 if (TestCpuFlag(kCpuHasMSA)) {
2293 ARGBToYJRow = ARGBToYJRow_Any_MSA;
2294 ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
2295 if (IS_ALIGNED(width, 16)) {
2296 ARGBToYJRow = ARGBToYJRow_MSA;
2297 }
2298 if (IS_ALIGNED(width, 32)) {
2299 ARGBToUVJRow = ARGBToUVJRow_MSA;
2300 }
2301 }
2302 #endif
2303 #if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2304 if (TestCpuFlag(kCpuHasLSX)) {
2305 ARGBToYJRow = ARGBToYJRow_Any_LSX;
2306 ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2307 if (IS_ALIGNED(width, 16)) {
2308 ARGBToYJRow = ARGBToYJRow_LSX;
2309 ARGBToUVJRow = ARGBToUVJRow_LSX;
2310 }
2311 }
2312 #endif
2313 #if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2314 if (TestCpuFlag(kCpuHasLASX)) {
2315 ARGBToYJRow = ARGBToYJRow_Any_LASX;
2316 ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2317 if (IS_ALIGNED(width, 32)) {
2318 ARGBToYJRow = ARGBToYJRow_LASX;
2319 ARGBToUVJRow = ARGBToUVJRow_LASX;
2320 }
2321 }
2322 #endif
2323 #if defined(HAS_ARGBTOYJROW_RVV)
2324 if (TestCpuFlag(kCpuHasRVV)) {
2325 ARGBToYJRow = ARGBToYJRow_RVV;
2326 }
2327 #endif
2328
2329 for (y = 0; y < height - 1; y += 2) {
2330 ARGBToUVJRow(src_argb, src_stride_argb, dst_uj, dst_vj, width);
2331 ARGBToYJRow(src_argb, dst_yj, width);
2332 ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
2333 src_argb += src_stride_argb * 2;
2334 dst_yj += dst_stride_yj * 2;
2335 dst_uj += dst_stride_uj;
2336 dst_vj += dst_stride_vj;
2337 }
2338 if (height & 1) {
2339 ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2340 ARGBToYJRow(src_argb, dst_yj, width);
2341 }
2342 return 0;
2343 }
2344
2345 // Convert ARGB to J422. (JPeg full range I422).
2346 LIBYUV_API
ARGBToJ422(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2347 int ARGBToJ422(const uint8_t* src_argb,
2348 int src_stride_argb,
2349 uint8_t* dst_yj,
2350 int dst_stride_yj,
2351 uint8_t* dst_uj,
2352 int dst_stride_uj,
2353 uint8_t* dst_vj,
2354 int dst_stride_vj,
2355 int width,
2356 int height) {
2357 int y;
2358 void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2359 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2360 ARGBToUVJRow_C;
2361 void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2362 ARGBToYJRow_C;
2363 if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2364 return -1;
2365 }
2366 // Negative height means invert the image.
2367 if (height < 0) {
2368 height = -height;
2369 src_argb = src_argb + (height - 1) * src_stride_argb;
2370 src_stride_argb = -src_stride_argb;
2371 }
2372 // Coalesce rows.
2373 if (src_stride_argb == width * 4 && dst_stride_yj == width &&
2374 dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
2375 width *= height;
2376 height = 1;
2377 src_stride_argb = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
2378 }
2379 #if defined(HAS_ARGBTOYJROW_SSSE3)
2380 if (TestCpuFlag(kCpuHasSSSE3)) {
2381 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2382 if (IS_ALIGNED(width, 16)) {
2383 ARGBToYJRow = ARGBToYJRow_SSSE3;
2384 }
2385 }
2386 #endif
2387 #if defined(HAS_ARGBTOUVJROW_SSSE3)
2388 if (TestCpuFlag(kCpuHasSSSE3)) {
2389 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2390 if (IS_ALIGNED(width, 16)) {
2391 ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2392 }
2393 }
2394 #endif
2395 #if defined(HAS_ARGBTOYJROW_AVX2)
2396 if (TestCpuFlag(kCpuHasAVX2)) {
2397 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2398 if (IS_ALIGNED(width, 32)) {
2399 ARGBToYJRow = ARGBToYJRow_AVX2;
2400 }
2401 }
2402 #endif
2403 #if defined(HAS_ARGBTOUVJROW_AVX2)
2404 if (TestCpuFlag(kCpuHasAVX2)) {
2405 ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2406 if (IS_ALIGNED(width, 32)) {
2407 ARGBToUVJRow = ARGBToUVJRow_AVX2;
2408 }
2409 }
2410 #endif
2411 #if defined(HAS_ARGBTOYJROW_NEON)
2412 if (TestCpuFlag(kCpuHasNEON)) {
2413 ARGBToYJRow = ARGBToYJRow_Any_NEON;
2414 if (IS_ALIGNED(width, 16)) {
2415 ARGBToYJRow = ARGBToYJRow_NEON;
2416 }
2417 }
2418 #endif
2419 #if defined(HAS_ARGBTOUVJROW_NEON)
2420 if (TestCpuFlag(kCpuHasNEON)) {
2421 ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2422 if (IS_ALIGNED(width, 16)) {
2423 ARGBToUVJRow = ARGBToUVJRow_NEON;
2424 }
2425 }
2426 #endif
2427 #if defined(HAS_ARGBTOYJROW_MSA) && defined(HAS_ARGBTOUVJROW_MSA)
2428 if (TestCpuFlag(kCpuHasMSA)) {
2429 ARGBToYJRow = ARGBToYJRow_Any_MSA;
2430 ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
2431 if (IS_ALIGNED(width, 16)) {
2432 ARGBToYJRow = ARGBToYJRow_MSA;
2433 }
2434 if (IS_ALIGNED(width, 32)) {
2435 ARGBToUVJRow = ARGBToUVJRow_MSA;
2436 }
2437 }
2438 #endif
2439 #if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2440 if (TestCpuFlag(kCpuHasLSX)) {
2441 ARGBToYJRow = ARGBToYJRow_Any_LSX;
2442 ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2443 if (IS_ALIGNED(width, 16)) {
2444 ARGBToYJRow = ARGBToYJRow_LSX;
2445 ARGBToUVJRow = ARGBToUVJRow_LSX;
2446 }
2447 }
2448 #endif
2449 #if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2450 if (TestCpuFlag(kCpuHasLASX)) {
2451 ARGBToYJRow = ARGBToYJRow_Any_LASX;
2452 ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2453 if (IS_ALIGNED(width, 32)) {
2454 ARGBToYJRow = ARGBToYJRow_LASX;
2455 ARGBToUVJRow = ARGBToUVJRow_LASX;
2456 }
2457 }
2458 #endif
2459 #if defined(HAS_ARGBTOYJROW_RVV)
2460 if (TestCpuFlag(kCpuHasRVV)) {
2461 ARGBToYJRow = ARGBToYJRow_RVV;
2462 }
2463 #endif
2464
2465 for (y = 0; y < height; ++y) {
2466 ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2467 ARGBToYJRow(src_argb, dst_yj, width);
2468 src_argb += src_stride_argb;
2469 dst_yj += dst_stride_yj;
2470 dst_uj += dst_stride_uj;
2471 dst_vj += dst_stride_vj;
2472 }
2473 return 0;
2474 }
2475
2476 // Convert ARGB to J400.
2477 LIBYUV_API
ARGBToJ400(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2478 int ARGBToJ400(const uint8_t* src_argb,
2479 int src_stride_argb,
2480 uint8_t* dst_yj,
2481 int dst_stride_yj,
2482 int width,
2483 int height) {
2484 int y;
2485 void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2486 ARGBToYJRow_C;
2487 if (!src_argb || !dst_yj || width <= 0 || height == 0) {
2488 return -1;
2489 }
2490 if (height < 0) {
2491 height = -height;
2492 src_argb = src_argb + (height - 1) * src_stride_argb;
2493 src_stride_argb = -src_stride_argb;
2494 }
2495 // Coalesce rows.
2496 if (src_stride_argb == width * 4 && dst_stride_yj == width) {
2497 width *= height;
2498 height = 1;
2499 src_stride_argb = dst_stride_yj = 0;
2500 }
2501 #if defined(HAS_ARGBTOYJROW_SSSE3)
2502 if (TestCpuFlag(kCpuHasSSSE3)) {
2503 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2504 if (IS_ALIGNED(width, 16)) {
2505 ARGBToYJRow = ARGBToYJRow_SSSE3;
2506 }
2507 }
2508 #endif
2509 #if defined(HAS_ARGBTOYJROW_AVX2)
2510 if (TestCpuFlag(kCpuHasAVX2)) {
2511 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2512 if (IS_ALIGNED(width, 32)) {
2513 ARGBToYJRow = ARGBToYJRow_AVX2;
2514 }
2515 }
2516 #endif
2517 #if defined(HAS_ARGBTOYJROW_NEON)
2518 if (TestCpuFlag(kCpuHasNEON)) {
2519 ARGBToYJRow = ARGBToYJRow_Any_NEON;
2520 if (IS_ALIGNED(width, 16)) {
2521 ARGBToYJRow = ARGBToYJRow_NEON;
2522 }
2523 }
2524 #endif
2525 #if defined(HAS_ARGBTOYJROW_MSA)
2526 if (TestCpuFlag(kCpuHasMSA)) {
2527 ARGBToYJRow = ARGBToYJRow_Any_MSA;
2528 if (IS_ALIGNED(width, 16)) {
2529 ARGBToYJRow = ARGBToYJRow_MSA;
2530 }
2531 }
2532 #endif
2533 #if defined(HAS_ARGBTOYJROW_RVV)
2534 if (TestCpuFlag(kCpuHasRVV)) {
2535 ARGBToYJRow = ARGBToYJRow_RVV;
2536 }
2537 #endif
2538
2539 for (y = 0; y < height; ++y) {
2540 ARGBToYJRow(src_argb, dst_yj, width);
2541 src_argb += src_stride_argb;
2542 dst_yj += dst_stride_yj;
2543 }
2544 return 0;
2545 }
2546
2547 // Convert RGBA to J400.
2548 LIBYUV_API
RGBAToJ400(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2549 int RGBAToJ400(const uint8_t* src_rgba,
2550 int src_stride_rgba,
2551 uint8_t* dst_yj,
2552 int dst_stride_yj,
2553 int width,
2554 int height) {
2555 int y;
2556 void (*RGBAToYJRow)(const uint8_t* src_rgba, uint8_t* dst_yj, int width) =
2557 RGBAToYJRow_C;
2558 if (!src_rgba || !dst_yj || width <= 0 || height == 0) {
2559 return -1;
2560 }
2561 if (height < 0) {
2562 height = -height;
2563 src_rgba = src_rgba + (height - 1) * src_stride_rgba;
2564 src_stride_rgba = -src_stride_rgba;
2565 }
2566 // Coalesce rows.
2567 if (src_stride_rgba == width * 4 && dst_stride_yj == width) {
2568 width *= height;
2569 height = 1;
2570 src_stride_rgba = dst_stride_yj = 0;
2571 }
2572 #if defined(HAS_RGBATOYJROW_SSSE3)
2573 if (TestCpuFlag(kCpuHasSSSE3)) {
2574 RGBAToYJRow = RGBAToYJRow_Any_SSSE3;
2575 if (IS_ALIGNED(width, 16)) {
2576 RGBAToYJRow = RGBAToYJRow_SSSE3;
2577 }
2578 }
2579 #endif
2580 #if defined(HAS_RGBATOYJROW_AVX2)
2581 if (TestCpuFlag(kCpuHasAVX2)) {
2582 RGBAToYJRow = RGBAToYJRow_Any_AVX2;
2583 if (IS_ALIGNED(width, 32)) {
2584 RGBAToYJRow = RGBAToYJRow_AVX2;
2585 }
2586 }
2587 #endif
2588 #if defined(HAS_RGBATOYJROW_NEON)
2589 if (TestCpuFlag(kCpuHasNEON)) {
2590 RGBAToYJRow = RGBAToYJRow_Any_NEON;
2591 if (IS_ALIGNED(width, 16)) {
2592 RGBAToYJRow = RGBAToYJRow_NEON;
2593 }
2594 }
2595 #endif
2596 #if defined(HAS_RGBATOYJROW_MSA)
2597 if (TestCpuFlag(kCpuHasMSA)) {
2598 RGBAToYJRow = RGBAToYJRow_Any_MSA;
2599 if (IS_ALIGNED(width, 16)) {
2600 RGBAToYJRow = RGBAToYJRow_MSA;
2601 }
2602 }
2603 #endif
2604 #if defined(HAS_RGBATOYJROW_LSX)
2605 if (TestCpuFlag(kCpuHasLSX)) {
2606 RGBAToYJRow = RGBAToYJRow_Any_LSX;
2607 if (IS_ALIGNED(width, 16)) {
2608 RGBAToYJRow = RGBAToYJRow_LSX;
2609 }
2610 }
2611 #endif
2612 #if defined(HAS_RGBATOYJROW_LASX)
2613 if (TestCpuFlag(kCpuHasLASX)) {
2614 RGBAToYJRow = RGBAToYJRow_Any_LASX;
2615 if (IS_ALIGNED(width, 32)) {
2616 RGBAToYJRow = RGBAToYJRow_LASX;
2617 }
2618 }
2619 #endif
2620 #if defined(HAS_RGBATOYJROW_RVV)
2621 if (TestCpuFlag(kCpuHasRVV)) {
2622 RGBAToYJRow = RGBAToYJRow_RVV;
2623 }
2624 #endif
2625
2626 for (y = 0; y < height; ++y) {
2627 RGBAToYJRow(src_rgba, dst_yj, width);
2628 src_rgba += src_stride_rgba;
2629 dst_yj += dst_stride_yj;
2630 }
2631 return 0;
2632 }
2633
2634 // Convert ABGR to J420. (JPeg full range I420).
2635 LIBYUV_API
ABGRToJ420(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2636 int ABGRToJ420(const uint8_t* src_abgr,
2637 int src_stride_abgr,
2638 uint8_t* dst_yj,
2639 int dst_stride_yj,
2640 uint8_t* dst_uj,
2641 int dst_stride_uj,
2642 uint8_t* dst_vj,
2643 int dst_stride_vj,
2644 int width,
2645 int height) {
2646 int y;
2647 void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
2648 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2649 ABGRToUVJRow_C;
2650 void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2651 ABGRToYJRow_C;
2652 if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2653 return -1;
2654 }
2655 // Negative height means invert the image.
2656 if (height < 0) {
2657 height = -height;
2658 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2659 src_stride_abgr = -src_stride_abgr;
2660 }
2661 #if defined(HAS_ABGRTOYJROW_SSSE3)
2662 if (TestCpuFlag(kCpuHasSSSE3)) {
2663 ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2664 if (IS_ALIGNED(width, 16)) {
2665 ABGRToYJRow = ABGRToYJRow_SSSE3;
2666 }
2667 }
2668 #endif
2669 #if defined(HAS_ABGRTOUVJROW_SSSE3)
2670 if (TestCpuFlag(kCpuHasSSSE3)) {
2671 ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
2672 if (IS_ALIGNED(width, 16)) {
2673 ABGRToUVJRow = ABGRToUVJRow_SSSE3;
2674 }
2675 }
2676 #endif
2677 #if defined(HAS_ABGRTOYJROW_AVX2)
2678 if (TestCpuFlag(kCpuHasAVX2)) {
2679 ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2680 if (IS_ALIGNED(width, 32)) {
2681 ABGRToYJRow = ABGRToYJRow_AVX2;
2682 }
2683 }
2684 #endif
2685 #if defined(HAS_ABGRTOUVJROW_AVX2)
2686 if (TestCpuFlag(kCpuHasAVX2)) {
2687 ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
2688 if (IS_ALIGNED(width, 32)) {
2689 ABGRToUVJRow = ABGRToUVJRow_AVX2;
2690 }
2691 }
2692 #endif
2693 #if defined(HAS_ABGRTOYJROW_NEON)
2694 if (TestCpuFlag(kCpuHasNEON)) {
2695 ABGRToYJRow = ABGRToYJRow_Any_NEON;
2696 if (IS_ALIGNED(width, 16)) {
2697 ABGRToYJRow = ABGRToYJRow_NEON;
2698 }
2699 }
2700 #endif
2701 #if defined(HAS_ABGRTOUVJROW_NEON)
2702 if (TestCpuFlag(kCpuHasNEON)) {
2703 ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
2704 if (IS_ALIGNED(width, 16)) {
2705 ABGRToUVJRow = ABGRToUVJRow_NEON;
2706 }
2707 }
2708 #endif
2709 #if defined(HAS_ABGRTOYJROW_MSA) && defined(HAS_ABGRTOUVJROW_MSA)
2710 if (TestCpuFlag(kCpuHasMSA)) {
2711 ABGRToYJRow = ABGRToYJRow_Any_MSA;
2712 ABGRToUVJRow = ABGRToUVJRow_Any_MSA;
2713 if (IS_ALIGNED(width, 16)) {
2714 ABGRToYJRow = ABGRToYJRow_MSA;
2715 ABGRToUVJRow = ABGRToUVJRow_MSA;
2716 }
2717 }
2718 #endif
2719 #if defined(HAS_ABGRTOYJROW_LSX)
2720 if (TestCpuFlag(kCpuHasLSX)) {
2721 ABGRToYJRow = ABGRToYJRow_Any_LSX;
2722 if (IS_ALIGNED(width, 16)) {
2723 ABGRToYJRow = ABGRToYJRow_LSX;
2724 }
2725 }
2726 #endif
2727 #if defined(HAS_ABGRTOYJROW_LASX)
2728 if (TestCpuFlag(kCpuHasLASX)) {
2729 ABGRToYJRow = ABGRToYJRow_Any_LASX;
2730 if (IS_ALIGNED(width, 32)) {
2731 ABGRToYJRow = ABGRToYJRow_LASX;
2732 }
2733 }
2734 #endif
2735 #if defined(HAS_ABGRTOYJROW_RVV)
2736 if (TestCpuFlag(kCpuHasRVV)) {
2737 ABGRToYJRow = ABGRToYJRow_RVV;
2738 }
2739 #endif
2740
2741 for (y = 0; y < height - 1; y += 2) {
2742 ABGRToUVJRow(src_abgr, src_stride_abgr, dst_uj, dst_vj, width);
2743 ABGRToYJRow(src_abgr, dst_yj, width);
2744 ABGRToYJRow(src_abgr + src_stride_abgr, dst_yj + dst_stride_yj, width);
2745 src_abgr += src_stride_abgr * 2;
2746 dst_yj += dst_stride_yj * 2;
2747 dst_uj += dst_stride_uj;
2748 dst_vj += dst_stride_vj;
2749 }
2750 if (height & 1) {
2751 ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
2752 ABGRToYJRow(src_abgr, dst_yj, width);
2753 }
2754 return 0;
2755 }
2756
2757 // Convert ABGR to J422. (JPeg full range I422).
2758 LIBYUV_API
ABGRToJ422(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2759 int ABGRToJ422(const uint8_t* src_abgr,
2760 int src_stride_abgr,
2761 uint8_t* dst_yj,
2762 int dst_stride_yj,
2763 uint8_t* dst_uj,
2764 int dst_stride_uj,
2765 uint8_t* dst_vj,
2766 int dst_stride_vj,
2767 int width,
2768 int height) {
2769 int y;
2770 void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
2771 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2772 ABGRToUVJRow_C;
2773 void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2774 ABGRToYJRow_C;
2775 if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2776 return -1;
2777 }
2778 // Negative height means invert the image.
2779 if (height < 0) {
2780 height = -height;
2781 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2782 src_stride_abgr = -src_stride_abgr;
2783 }
2784 // Coalesce rows.
2785 if (src_stride_abgr == width * 4 && dst_stride_yj == width &&
2786 dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
2787 width *= height;
2788 height = 1;
2789 src_stride_abgr = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
2790 }
2791 #if defined(HAS_ABGRTOYJROW_SSSE3)
2792 if (TestCpuFlag(kCpuHasSSSE3)) {
2793 ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2794 if (IS_ALIGNED(width, 16)) {
2795 ABGRToYJRow = ABGRToYJRow_SSSE3;
2796 }
2797 }
2798 #endif
2799 #if defined(HAS_ABGRTOUVJROW_SSSE3)
2800 if (TestCpuFlag(kCpuHasSSSE3)) {
2801 ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
2802 if (IS_ALIGNED(width, 16)) {
2803 ABGRToUVJRow = ABGRToUVJRow_SSSE3;
2804 }
2805 }
2806 #endif
2807 #if defined(HAS_ABGRTOYJROW_AVX2)
2808 if (TestCpuFlag(kCpuHasAVX2)) {
2809 ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2810 if (IS_ALIGNED(width, 32)) {
2811 ABGRToYJRow = ABGRToYJRow_AVX2;
2812 }
2813 }
2814 #endif
2815 #if defined(HAS_ABGRTOUVJROW_AVX2)
2816 if (TestCpuFlag(kCpuHasAVX2)) {
2817 ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
2818 if (IS_ALIGNED(width, 32)) {
2819 ABGRToUVJRow = ABGRToUVJRow_AVX2;
2820 }
2821 }
2822 #endif
2823 #if defined(HAS_ABGRTOYJROW_NEON)
2824 if (TestCpuFlag(kCpuHasNEON)) {
2825 ABGRToYJRow = ABGRToYJRow_Any_NEON;
2826 if (IS_ALIGNED(width, 16)) {
2827 ABGRToYJRow = ABGRToYJRow_NEON;
2828 }
2829 }
2830 #endif
2831 #if defined(HAS_ABGRTOUVJROW_NEON)
2832 if (TestCpuFlag(kCpuHasNEON)) {
2833 ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
2834 if (IS_ALIGNED(width, 16)) {
2835 ABGRToUVJRow = ABGRToUVJRow_NEON;
2836 }
2837 }
2838 #endif
2839 #if defined(HAS_ABGRTOYJROW_MSA) && defined(HAS_ABGRTOUVJROW_MSA)
2840 if (TestCpuFlag(kCpuHasMSA)) {
2841 ABGRToYJRow = ABGRToYJRow_Any_MSA;
2842 ABGRToUVJRow = ABGRToUVJRow_Any_MSA;
2843 if (IS_ALIGNED(width, 16)) {
2844 ABGRToYJRow = ABGRToYJRow_MSA;
2845 }
2846 if (IS_ALIGNED(width, 32)) {
2847 ABGRToUVJRow = ABGRToUVJRow_MSA;
2848 }
2849 }
2850 #endif
2851 #if defined(HAS_ABGRTOYJROW_LSX)
2852 if (TestCpuFlag(kCpuHasLSX)) {
2853 ABGRToYJRow = ABGRToYJRow_Any_LSX;
2854 if (IS_ALIGNED(width, 16)) {
2855 ABGRToYJRow = ABGRToYJRow_LSX;
2856 }
2857 }
2858 #endif
2859 #if defined(HAS_ABGRTOYJROW_LASX)
2860 if (TestCpuFlag(kCpuHasLASX)) {
2861 ABGRToYJRow = ABGRToYJRow_Any_LASX;
2862 if (IS_ALIGNED(width, 32)) {
2863 ABGRToYJRow = ABGRToYJRow_LASX;
2864 }
2865 }
2866 #endif
2867 #if defined(HAS_ABGRTOYJROW_RVV)
2868 if (TestCpuFlag(kCpuHasRVV)) {
2869 ABGRToYJRow = ABGRToYJRow_RVV;
2870 }
2871 #endif
2872
2873 for (y = 0; y < height; ++y) {
2874 ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
2875 ABGRToYJRow(src_abgr, dst_yj, width);
2876 src_abgr += src_stride_abgr;
2877 dst_yj += dst_stride_yj;
2878 dst_uj += dst_stride_uj;
2879 dst_vj += dst_stride_vj;
2880 }
2881 return 0;
2882 }
2883
2884 // Convert ABGR to J400.
2885 LIBYUV_API
ABGRToJ400(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2886 int ABGRToJ400(const uint8_t* src_abgr,
2887 int src_stride_abgr,
2888 uint8_t* dst_yj,
2889 int dst_stride_yj,
2890 int width,
2891 int height) {
2892 int y;
2893 void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2894 ABGRToYJRow_C;
2895 if (!src_abgr || !dst_yj || width <= 0 || height == 0) {
2896 return -1;
2897 }
2898 if (height < 0) {
2899 height = -height;
2900 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2901 src_stride_abgr = -src_stride_abgr;
2902 }
2903 // Coalesce rows.
2904 if (src_stride_abgr == width * 4 && dst_stride_yj == width) {
2905 width *= height;
2906 height = 1;
2907 src_stride_abgr = dst_stride_yj = 0;
2908 }
2909 #if defined(HAS_ABGRTOYJROW_SSSE3)
2910 if (TestCpuFlag(kCpuHasSSSE3)) {
2911 ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2912 if (IS_ALIGNED(width, 16)) {
2913 ABGRToYJRow = ABGRToYJRow_SSSE3;
2914 }
2915 }
2916 #endif
2917 #if defined(HAS_ABGRTOYJROW_AVX2)
2918 if (TestCpuFlag(kCpuHasAVX2)) {
2919 ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2920 if (IS_ALIGNED(width, 32)) {
2921 ABGRToYJRow = ABGRToYJRow_AVX2;
2922 }
2923 }
2924 #endif
2925 #if defined(HAS_ABGRTOYJROW_NEON)
2926 if (TestCpuFlag(kCpuHasNEON)) {
2927 ABGRToYJRow = ABGRToYJRow_Any_NEON;
2928 if (IS_ALIGNED(width, 16)) {
2929 ABGRToYJRow = ABGRToYJRow_NEON;
2930 }
2931 }
2932 #endif
2933 #if defined(HAS_ABGRTOYJROW_MSA)
2934 if (TestCpuFlag(kCpuHasMSA)) {
2935 ABGRToYJRow = ABGRToYJRow_Any_MSA;
2936 if (IS_ALIGNED(width, 16)) {
2937 ABGRToYJRow = ABGRToYJRow_MSA;
2938 }
2939 }
2940 #endif
2941 #if defined(HAS_ABGRTOYJROW_LSX)
2942 if (TestCpuFlag(kCpuHasLSX)) {
2943 ABGRToYJRow = ABGRToYJRow_Any_LSX;
2944 if (IS_ALIGNED(width, 16)) {
2945 ABGRToYJRow = ABGRToYJRow_LSX;
2946 }
2947 }
2948 #endif
2949 #if defined(HAS_ABGRTOYJROW_LASX)
2950 if (TestCpuFlag(kCpuHasLASX)) {
2951 ABGRToYJRow = ABGRToYJRow_Any_LASX;
2952 if (IS_ALIGNED(width, 32)) {
2953 ABGRToYJRow = ABGRToYJRow_LASX;
2954 }
2955 }
2956 #endif
2957 #if defined(HAS_ABGRTOYJROW_RVV)
2958 if (TestCpuFlag(kCpuHasRVV)) {
2959 ABGRToYJRow = ABGRToYJRow_RVV;
2960 }
2961 #endif
2962
2963 for (y = 0; y < height; ++y) {
2964 ABGRToYJRow(src_abgr, dst_yj, width);
2965 src_abgr += src_stride_abgr;
2966 dst_yj += dst_stride_yj;
2967 }
2968 return 0;
2969 }
2970
2971 // Convert ARGB to AR64.
2972 LIBYUV_API
ARGBToAR64(const uint8_t * src_argb,int src_stride_argb,uint16_t * dst_ar64,int dst_stride_ar64,int width,int height)2973 int ARGBToAR64(const uint8_t* src_argb,
2974 int src_stride_argb,
2975 uint16_t* dst_ar64,
2976 int dst_stride_ar64,
2977 int width,
2978 int height) {
2979 int y;
2980 void (*ARGBToAR64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
2981 int width) = ARGBToAR64Row_C;
2982 if (!src_argb || !dst_ar64 || width <= 0 || height == 0) {
2983 return -1;
2984 }
2985 // Negative height means invert the image.
2986 if (height < 0) {
2987 height = -height;
2988 src_argb = src_argb + (height - 1) * src_stride_argb;
2989 src_stride_argb = -src_stride_argb;
2990 }
2991 // Coalesce rows.
2992 if (src_stride_argb == width * 4 && dst_stride_ar64 == width * 4) {
2993 width *= height;
2994 height = 1;
2995 src_stride_argb = dst_stride_ar64 = 0;
2996 }
2997 #if defined(HAS_ARGBTOAR64ROW_SSSE3)
2998 if (TestCpuFlag(kCpuHasSSSE3)) {
2999 ARGBToAR64Row = ARGBToAR64Row_Any_SSSE3;
3000 if (IS_ALIGNED(width, 4)) {
3001 ARGBToAR64Row = ARGBToAR64Row_SSSE3;
3002 }
3003 }
3004 #endif
3005 #if defined(HAS_ARGBTOAR64ROW_AVX2)
3006 if (TestCpuFlag(kCpuHasAVX2)) {
3007 ARGBToAR64Row = ARGBToAR64Row_Any_AVX2;
3008 if (IS_ALIGNED(width, 8)) {
3009 ARGBToAR64Row = ARGBToAR64Row_AVX2;
3010 }
3011 }
3012 #endif
3013 #if defined(HAS_ARGBTOAR64ROW_NEON)
3014 if (TestCpuFlag(kCpuHasNEON)) {
3015 ARGBToAR64Row = ARGBToAR64Row_Any_NEON;
3016 if (IS_ALIGNED(width, 8)) {
3017 ARGBToAR64Row = ARGBToAR64Row_NEON;
3018 }
3019 }
3020 #endif
3021 #if defined(HAS_ARGBTOAR64ROW_RVV)
3022 if (TestCpuFlag(kCpuHasRVV)) {
3023 ARGBToAR64Row = ARGBToAR64Row_RVV;
3024 }
3025 #endif
3026
3027 for (y = 0; y < height; ++y) {
3028 ARGBToAR64Row(src_argb, dst_ar64, width);
3029 src_argb += src_stride_argb;
3030 dst_ar64 += dst_stride_ar64;
3031 }
3032 return 0;
3033 }
3034
3035 // Convert ARGB to AB64.
3036 LIBYUV_API
ARGBToAB64(const uint8_t * src_argb,int src_stride_argb,uint16_t * dst_ab64,int dst_stride_ab64,int width,int height)3037 int ARGBToAB64(const uint8_t* src_argb,
3038 int src_stride_argb,
3039 uint16_t* dst_ab64,
3040 int dst_stride_ab64,
3041 int width,
3042 int height) {
3043 int y;
3044 void (*ARGBToAB64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
3045 int width) = ARGBToAB64Row_C;
3046 if (!src_argb || !dst_ab64 || width <= 0 || height == 0) {
3047 return -1;
3048 }
3049 // Negative height means invert the image.
3050 if (height < 0) {
3051 height = -height;
3052 src_argb = src_argb + (height - 1) * src_stride_argb;
3053 src_stride_argb = -src_stride_argb;
3054 }
3055 // Coalesce rows.
3056 if (src_stride_argb == width * 4 && dst_stride_ab64 == width * 4) {
3057 width *= height;
3058 height = 1;
3059 src_stride_argb = dst_stride_ab64 = 0;
3060 }
3061 #if defined(HAS_ARGBTOAB64ROW_SSSE3)
3062 if (TestCpuFlag(kCpuHasSSSE3)) {
3063 ARGBToAB64Row = ARGBToAB64Row_Any_SSSE3;
3064 if (IS_ALIGNED(width, 4)) {
3065 ARGBToAB64Row = ARGBToAB64Row_SSSE3;
3066 }
3067 }
3068 #endif
3069 #if defined(HAS_ARGBTOAB64ROW_AVX2)
3070 if (TestCpuFlag(kCpuHasAVX2)) {
3071 ARGBToAB64Row = ARGBToAB64Row_Any_AVX2;
3072 if (IS_ALIGNED(width, 8)) {
3073 ARGBToAB64Row = ARGBToAB64Row_AVX2;
3074 }
3075 }
3076 #endif
3077 #if defined(HAS_ARGBTOAB64ROW_NEON)
3078 if (TestCpuFlag(kCpuHasNEON)) {
3079 ARGBToAB64Row = ARGBToAB64Row_Any_NEON;
3080 if (IS_ALIGNED(width, 8)) {
3081 ARGBToAB64Row = ARGBToAB64Row_NEON;
3082 }
3083 }
3084 #endif
3085 #if defined(HAS_ARGBTOAB64ROW_RVV)
3086 if (TestCpuFlag(kCpuHasRVV)) {
3087 ARGBToAB64Row = ARGBToAB64Row_RVV;
3088 }
3089 #endif
3090
3091 for (y = 0; y < height; ++y) {
3092 ARGBToAB64Row(src_argb, dst_ab64, width);
3093 src_argb += src_stride_argb;
3094 dst_ab64 += dst_stride_ab64;
3095 }
3096 return 0;
3097 }
3098
3099 // Enabled if 1 pass is available
3100 #if defined(HAS_RAWTOYJROW_NEON) || defined(HAS_RAWTOYJROW_MSA) || \
3101 defined(HAS_RAWTOYJROW_RVV)
3102 #define HAS_RAWTOYJROW
3103 #endif
3104
3105 // RAW to JNV21 full range NV21
3106 LIBYUV_API
RAWToJNV21(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)3107 int RAWToJNV21(const uint8_t* src_raw,
3108 int src_stride_raw,
3109 uint8_t* dst_y,
3110 int dst_stride_y,
3111 uint8_t* dst_vu,
3112 int dst_stride_vu,
3113 int width,
3114 int height) {
3115 int y;
3116 int halfwidth = (width + 1) >> 1;
3117 #if defined(HAS_RAWTOYJROW)
3118 void (*RAWToUVJRow)(const uint8_t* src_raw, int src_stride_raw,
3119 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3120 RAWToUVJRow_C;
3121 void (*RAWToYJRow)(const uint8_t* src_raw, uint8_t* dst_y, int width) =
3122 RAWToYJRow_C;
3123 #else
3124 void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3125 RAWToARGBRow_C;
3126 void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
3127 uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3128 ARGBToUVJRow_C;
3129 void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
3130 ARGBToYJRow_C;
3131 #endif
3132 void (*MergeUVRow_)(const uint8_t* src_uj, const uint8_t* src_vj,
3133 uint8_t* dst_vu, int width) = MergeUVRow_C;
3134 if (!src_raw || !dst_y || !dst_vu || width <= 0 || height == 0) {
3135 return -1;
3136 }
3137 // Negative height means invert the image.
3138 if (height < 0) {
3139 height = -height;
3140 src_raw = src_raw + (height - 1) * src_stride_raw;
3141 src_stride_raw = -src_stride_raw;
3142 }
3143
3144 #if defined(HAS_RAWTOYJROW)
3145
3146 // Neon version does direct RAW to YUV.
3147 #if defined(HAS_RAWTOYJROW_NEON) && defined(HAS_RAWTOUVJROW_NEON)
3148 if (TestCpuFlag(kCpuHasNEON)) {
3149 RAWToUVJRow = RAWToUVJRow_Any_NEON;
3150 RAWToYJRow = RAWToYJRow_Any_NEON;
3151 if (IS_ALIGNED(width, 16)) {
3152 RAWToYJRow = RAWToYJRow_NEON;
3153 RAWToUVJRow = RAWToUVJRow_NEON;
3154 }
3155 }
3156 #endif
3157 #if defined(HAS_RAWTOYJROW_MSA) && defined(HAS_RAWTOUVJROW_MSA)
3158 if (TestCpuFlag(kCpuHasMSA)) {
3159 RAWToUVJRow = RAWToUVJRow_Any_MSA;
3160 RAWToYJRow = RAWToYJRow_Any_MSA;
3161 if (IS_ALIGNED(width, 16)) {
3162 RAWToYJRow = RAWToYJRow_MSA;
3163 RAWToUVJRow = RAWToUVJRow_MSA;
3164 }
3165 }
3166 #endif
3167 #if defined(HAS_RAWTOYJROW_LSX)
3168 if (TestCpuFlag(kCpuHasLSX)) {
3169 RAWToYJRow = RAWToYJRow_Any_LSX;
3170 if (IS_ALIGNED(width, 16)) {
3171 RAWToYJRow = RAWToYJRow_LSX;
3172 }
3173 }
3174 #endif
3175 #if defined(HAS_RAWTOYJROW_LASX)
3176 if (TestCpuFlag(kCpuHasLASX)) {
3177 RAWToYJRow = RAWToYJRow_Any_LASX;
3178 if (IS_ALIGNED(width, 32)) {
3179 RAWToYJRow = RAWToYJRow_LASX;
3180 }
3181 }
3182 #endif
3183 #if defined(HAS_RAWTOYJROW_RVV)
3184 if (TestCpuFlag(kCpuHasRVV)) {
3185 RAWToYJRow = RAWToYJRow_RVV;
3186 }
3187 #endif
3188
3189 // Other platforms do intermediate conversion from RAW to ARGB.
3190 #else // HAS_RAWTOYJROW
3191
3192 #if defined(HAS_RAWTOARGBROW_SSSE3)
3193 if (TestCpuFlag(kCpuHasSSSE3)) {
3194 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
3195 if (IS_ALIGNED(width, 16)) {
3196 RAWToARGBRow = RAWToARGBRow_SSSE3;
3197 }
3198 }
3199 #endif
3200 #if defined(HAS_ARGBTOYJROW_SSSE3)
3201 if (TestCpuFlag(kCpuHasSSSE3)) {
3202 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
3203 if (IS_ALIGNED(width, 16)) {
3204 ARGBToYJRow = ARGBToYJRow_SSSE3;
3205 }
3206 }
3207 #endif
3208 #if defined(HAS_ARGBTOYJROW_AVX2)
3209 if (TestCpuFlag(kCpuHasAVX2)) {
3210 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
3211 if (IS_ALIGNED(width, 32)) {
3212 ARGBToYJRow = ARGBToYJRow_AVX2;
3213 }
3214 }
3215 #endif
3216 #if defined(HAS_ARGBTOUVJROW_SSSE3)
3217 if (TestCpuFlag(kCpuHasSSSE3)) {
3218 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
3219 if (IS_ALIGNED(width, 16)) {
3220 ARGBToUVJRow = ARGBToUVJRow_SSSE3;
3221 }
3222 }
3223 #endif
3224 #if defined(HAS_ARGBTOUVJROW_AVX2)
3225 if (TestCpuFlag(kCpuHasAVX2)) {
3226 ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
3227 if (IS_ALIGNED(width, 32)) {
3228 ARGBToUVJRow = ARGBToUVJRow_AVX2;
3229 }
3230 }
3231 #endif
3232 #endif // HAS_RAWTOYJROW
3233 #if defined(HAS_MERGEUVROW_SSE2)
3234 if (TestCpuFlag(kCpuHasSSE2)) {
3235 MergeUVRow_ = MergeUVRow_Any_SSE2;
3236 if (IS_ALIGNED(halfwidth, 16)) {
3237 MergeUVRow_ = MergeUVRow_SSE2;
3238 }
3239 }
3240 #endif
3241 #if defined(HAS_MERGEUVROW_AVX2)
3242 if (TestCpuFlag(kCpuHasAVX2)) {
3243 MergeUVRow_ = MergeUVRow_Any_AVX2;
3244 if (IS_ALIGNED(halfwidth, 16)) {
3245 MergeUVRow_ = MergeUVRow_AVX2;
3246 }
3247 }
3248 #endif
3249 #if defined(HAS_MERGEUVROW_AVX512BW)
3250 if (TestCpuFlag(kCpuHasAVX512BW)) {
3251 MergeUVRow_ = MergeUVRow_Any_AVX512BW;
3252 if (IS_ALIGNED(halfwidth, 64)) {
3253 MergeUVRow_ = MergeUVRow_AVX512BW;
3254 }
3255 }
3256 #endif
3257 #if defined(HAS_MERGEUVROW_NEON)
3258 if (TestCpuFlag(kCpuHasNEON)) {
3259 MergeUVRow_ = MergeUVRow_Any_NEON;
3260 if (IS_ALIGNED(halfwidth, 16)) {
3261 MergeUVRow_ = MergeUVRow_NEON;
3262 }
3263 }
3264 #endif
3265 #if defined(HAS_MERGEUVROW_MSA)
3266 if (TestCpuFlag(kCpuHasMSA)) {
3267 MergeUVRow_ = MergeUVRow_Any_MSA;
3268 if (IS_ALIGNED(halfwidth, 16)) {
3269 MergeUVRow_ = MergeUVRow_MSA;
3270 }
3271 }
3272 #endif
3273 #if defined(HAS_MERGEUVROW_LSX)
3274 if (TestCpuFlag(kCpuHasLSX)) {
3275 MergeUVRow_ = MergeUVRow_Any_LSX;
3276 if (IS_ALIGNED(halfwidth, 16)) {
3277 MergeUVRow_ = MergeUVRow_LSX;
3278 }
3279 }
3280 #endif
3281 #if defined(HAS_MERGEUVROW_RVV)
3282 if (TestCpuFlag(kCpuHasRVV)) {
3283 MergeUVRow_ = MergeUVRow_RVV;
3284 }
3285 #endif
3286 {
3287 #if defined(HAS_RAWTOYJROW)
3288 // Allocate a row of uv.
3289 const int row_uv_size = ((halfwidth + 31) & ~31);
3290 align_buffer_64(row_uj, row_uv_size * 2);
3291 uint8_t* row_vj = row_uj + row_uv_size;
3292 #else
3293 // Allocate row of uv and 2 rows of ARGB.
3294 const int row_size = ((width * 4 + 31) & ~31);
3295 const int row_uv_size = ((halfwidth + 31) & ~31);
3296 align_buffer_64(row_uj, row_uv_size * 2 + row_size * 2);
3297 uint8_t* row_vj = row_uj + row_uv_size;
3298 uint8_t* row = row_vj + row_uv_size;
3299 #endif
3300 if (!row_uj)
3301 return 1;
3302
3303 for (y = 0; y < height - 1; y += 2) {
3304 #if defined(HAS_RAWTOYJROW)
3305 RAWToUVJRow(src_raw, src_stride_raw, row_uj, row_vj, width);
3306 MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3307 RAWToYJRow(src_raw, dst_y, width);
3308 RAWToYJRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
3309 #else
3310 RAWToARGBRow(src_raw, row, width);
3311 RAWToARGBRow(src_raw + src_stride_raw, row + row_size, width);
3312 ARGBToUVJRow(row, row_size, row_uj, row_vj, width);
3313 MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3314 ARGBToYJRow(row, dst_y, width);
3315 ARGBToYJRow(row + row_size, dst_y + dst_stride_y, width);
3316 #endif
3317 src_raw += src_stride_raw * 2;
3318 dst_y += dst_stride_y * 2;
3319 dst_vu += dst_stride_vu;
3320 }
3321 if (height & 1) {
3322 #if defined(HAS_RAWTOYJROW)
3323 RAWToUVJRow(src_raw, 0, row_uj, row_vj, width);
3324 MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3325 RAWToYJRow(src_raw, dst_y, width);
3326 #else
3327 RAWToARGBRow(src_raw, row, width);
3328 ARGBToUVJRow(row, 0, row_uj, row_vj, width);
3329 MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3330 ARGBToYJRow(row, dst_y, width);
3331 #endif
3332 }
3333 free_aligned_buffer_64(row_uj);
3334 }
3335 return 0;
3336 }
3337 #undef HAS_RAWTOYJROW
3338
3339 #ifdef __cplusplus
3340 } // extern "C"
3341 } // namespace libyuv
3342 #endif
3343