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 * src_argb,int src_stride_argb,uint8 * dst_y,int dst_stride_y,uint8 * dst_u,int dst_stride_u,uint8 * dst_v,int dst_stride_v,int width,int height)25 int ARGBToI444(const uint8* src_argb,
26 int src_stride_argb,
27 uint8* dst_y,
28 int dst_stride_y,
29 uint8* dst_u,
30 int dst_stride_u,
31 uint8* dst_v,
32 int dst_stride_v,
33 int width,
34 int height) {
35 int y;
36 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
37 ARGBToYRow_C;
38 void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
39 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_ARGBTOYROW_SSSE3)
80 if (TestCpuFlag(kCpuHasSSSE3)) {
81 ARGBToYRow = ARGBToYRow_Any_SSSE3;
82 if (IS_ALIGNED(width, 16)) {
83 ARGBToYRow = ARGBToYRow_SSSE3;
84 }
85 }
86 #endif
87 #if defined(HAS_ARGBTOYROW_AVX2)
88 if (TestCpuFlag(kCpuHasAVX2)) {
89 ARGBToYRow = ARGBToYRow_Any_AVX2;
90 if (IS_ALIGNED(width, 32)) {
91 ARGBToYRow = ARGBToYRow_AVX2;
92 }
93 }
94 #endif
95 #if defined(HAS_ARGBTOYROW_NEON)
96 if (TestCpuFlag(kCpuHasNEON)) {
97 ARGBToYRow = ARGBToYRow_Any_NEON;
98 if (IS_ALIGNED(width, 8)) {
99 ARGBToYRow = ARGBToYRow_NEON;
100 }
101 }
102 #endif
103 #if defined(HAS_ARGBTOYROW_DSPR2)
104 if (TestCpuFlag(kCpuHasDSPR2)) {
105 ARGBToYRow = ARGBToYRow_Any_DSPR2;
106 if (IS_ALIGNED(width, 8)) {
107 ARGBToYRow = ARGBToYRow_DSPR2;
108 }
109 }
110 #endif
111 #if defined(HAS_ARGBTOYROW_MSA)
112 if (TestCpuFlag(kCpuHasMSA)) {
113 ARGBToYRow = ARGBToYRow_Any_MSA;
114 if (IS_ALIGNED(width, 16)) {
115 ARGBToYRow = ARGBToYRow_MSA;
116 }
117 }
118 #endif
119
120 for (y = 0; y < height; ++y) {
121 ARGBToUV444Row(src_argb, dst_u, dst_v, width);
122 ARGBToYRow(src_argb, dst_y, width);
123 src_argb += src_stride_argb;
124 dst_y += dst_stride_y;
125 dst_u += dst_stride_u;
126 dst_v += dst_stride_v;
127 }
128 return 0;
129 }
130
131 // ARGB little endian (bgra in memory) to I422
132 LIBYUV_API
ARGBToI422(const uint8 * src_argb,int src_stride_argb,uint8 * dst_y,int dst_stride_y,uint8 * dst_u,int dst_stride_u,uint8 * dst_v,int dst_stride_v,int width,int height)133 int ARGBToI422(const uint8* src_argb,
134 int src_stride_argb,
135 uint8* dst_y,
136 int dst_stride_y,
137 uint8* dst_u,
138 int dst_stride_u,
139 uint8* dst_v,
140 int dst_stride_v,
141 int width,
142 int height) {
143 int y;
144 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
145 uint8* dst_v, int width) = ARGBToUVRow_C;
146 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
147 ARGBToYRow_C;
148 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
149 return -1;
150 }
151 // Negative height means invert the image.
152 if (height < 0) {
153 height = -height;
154 src_argb = src_argb + (height - 1) * src_stride_argb;
155 src_stride_argb = -src_stride_argb;
156 }
157 // Coalesce rows.
158 if (src_stride_argb == width * 4 && dst_stride_y == width &&
159 dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
160 width *= height;
161 height = 1;
162 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
163 }
164 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
165 if (TestCpuFlag(kCpuHasSSSE3)) {
166 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
167 ARGBToYRow = ARGBToYRow_Any_SSSE3;
168 if (IS_ALIGNED(width, 16)) {
169 ARGBToUVRow = ARGBToUVRow_SSSE3;
170 ARGBToYRow = ARGBToYRow_SSSE3;
171 }
172 }
173 #endif
174 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
175 if (TestCpuFlag(kCpuHasAVX2)) {
176 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
177 ARGBToYRow = ARGBToYRow_Any_AVX2;
178 if (IS_ALIGNED(width, 32)) {
179 ARGBToUVRow = ARGBToUVRow_AVX2;
180 ARGBToYRow = ARGBToYRow_AVX2;
181 }
182 }
183 #endif
184 #if defined(HAS_ARGBTOYROW_NEON)
185 if (TestCpuFlag(kCpuHasNEON)) {
186 ARGBToYRow = ARGBToYRow_Any_NEON;
187 if (IS_ALIGNED(width, 8)) {
188 ARGBToYRow = ARGBToYRow_NEON;
189 }
190 }
191 #endif
192 #if defined(HAS_ARGBTOUVROW_NEON)
193 if (TestCpuFlag(kCpuHasNEON)) {
194 ARGBToUVRow = ARGBToUVRow_Any_NEON;
195 if (IS_ALIGNED(width, 16)) {
196 ARGBToUVRow = ARGBToUVRow_NEON;
197 }
198 }
199 #endif
200 #if defined(HAS_ARGBTOYROW_DSPR2)
201 if (TestCpuFlag(kCpuHasDSPR2)) {
202 ARGBToYRow = ARGBToYRow_Any_DSPR2;
203 if (IS_ALIGNED(width, 8)) {
204 ARGBToYRow = ARGBToYRow_DSPR2;
205 }
206 }
207 #endif
208 #if defined(HAS_ARGBTOUVROW_DSPR2)
209 if (TestCpuFlag(kCpuHasDSPR2)) {
210 ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
211 if (IS_ALIGNED(width, 16)) {
212 ARGBToUVRow = ARGBToUVRow_DSPR2;
213 }
214 }
215 #endif
216
217 #if defined(HAS_ARGBTOYROW_MSA)
218 if (TestCpuFlag(kCpuHasMSA)) {
219 ARGBToYRow = ARGBToYRow_Any_MSA;
220 if (IS_ALIGNED(width, 16)) {
221 ARGBToYRow = ARGBToYRow_MSA;
222 }
223 }
224 #endif
225 #if defined(HAS_ARGBTOUVROW_MSA)
226 if (TestCpuFlag(kCpuHasMSA)) {
227 ARGBToUVRow = ARGBToUVRow_Any_MSA;
228 if (IS_ALIGNED(width, 32)) {
229 ARGBToUVRow = ARGBToUVRow_MSA;
230 }
231 }
232 #endif
233
234 for (y = 0; y < height; ++y) {
235 ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
236 ARGBToYRow(src_argb, dst_y, width);
237 src_argb += src_stride_argb;
238 dst_y += dst_stride_y;
239 dst_u += dst_stride_u;
240 dst_v += dst_stride_v;
241 }
242 return 0;
243 }
244
245 LIBYUV_API
ARGBToNV12(const uint8 * src_argb,int src_stride_argb,uint8 * dst_y,int dst_stride_y,uint8 * dst_uv,int dst_stride_uv,int width,int height)246 int ARGBToNV12(const uint8* src_argb,
247 int src_stride_argb,
248 uint8* dst_y,
249 int dst_stride_y,
250 uint8* dst_uv,
251 int dst_stride_uv,
252 int width,
253 int height) {
254 int y;
255 int halfwidth = (width + 1) >> 1;
256 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
257 uint8* dst_v, int width) = ARGBToUVRow_C;
258 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
259 ARGBToYRow_C;
260 void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
261 int width) = MergeUVRow_C;
262 if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
263 return -1;
264 }
265 // Negative height means invert the image.
266 if (height < 0) {
267 height = -height;
268 src_argb = src_argb + (height - 1) * src_stride_argb;
269 src_stride_argb = -src_stride_argb;
270 }
271 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
272 if (TestCpuFlag(kCpuHasSSSE3)) {
273 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
274 ARGBToYRow = ARGBToYRow_Any_SSSE3;
275 if (IS_ALIGNED(width, 16)) {
276 ARGBToUVRow = ARGBToUVRow_SSSE3;
277 ARGBToYRow = ARGBToYRow_SSSE3;
278 }
279 }
280 #endif
281 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
282 if (TestCpuFlag(kCpuHasAVX2)) {
283 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
284 ARGBToYRow = ARGBToYRow_Any_AVX2;
285 if (IS_ALIGNED(width, 32)) {
286 ARGBToUVRow = ARGBToUVRow_AVX2;
287 ARGBToYRow = ARGBToYRow_AVX2;
288 }
289 }
290 #endif
291 #if defined(HAS_ARGBTOYROW_NEON)
292 if (TestCpuFlag(kCpuHasNEON)) {
293 ARGBToYRow = ARGBToYRow_Any_NEON;
294 if (IS_ALIGNED(width, 8)) {
295 ARGBToYRow = ARGBToYRow_NEON;
296 }
297 }
298 #endif
299 #if defined(HAS_ARGBTOUVROW_NEON)
300 if (TestCpuFlag(kCpuHasNEON)) {
301 ARGBToUVRow = ARGBToUVRow_Any_NEON;
302 if (IS_ALIGNED(width, 16)) {
303 ARGBToUVRow = ARGBToUVRow_NEON;
304 }
305 }
306 #endif
307 #if defined(HAS_ARGBTOYROW_MSA)
308 if (TestCpuFlag(kCpuHasMSA)) {
309 ARGBToYRow = ARGBToYRow_Any_MSA;
310 if (IS_ALIGNED(width, 16)) {
311 ARGBToYRow = ARGBToYRow_MSA;
312 }
313 }
314 #endif
315 #if defined(HAS_ARGBTOUVROW_MSA)
316 if (TestCpuFlag(kCpuHasMSA)) {
317 ARGBToUVRow = ARGBToUVRow_Any_MSA;
318 if (IS_ALIGNED(width, 32)) {
319 ARGBToUVRow = ARGBToUVRow_MSA;
320 }
321 }
322 #endif
323 #if defined(HAS_MERGEUVROW_SSE2)
324 if (TestCpuFlag(kCpuHasSSE2)) {
325 MergeUVRow_ = MergeUVRow_Any_SSE2;
326 if (IS_ALIGNED(halfwidth, 16)) {
327 MergeUVRow_ = MergeUVRow_SSE2;
328 }
329 }
330 #endif
331 #if defined(HAS_MERGEUVROW_AVX2)
332 if (TestCpuFlag(kCpuHasAVX2)) {
333 MergeUVRow_ = MergeUVRow_Any_AVX2;
334 if (IS_ALIGNED(halfwidth, 32)) {
335 MergeUVRow_ = MergeUVRow_AVX2;
336 }
337 }
338 #endif
339 #if defined(HAS_MERGEUVROW_NEON)
340 if (TestCpuFlag(kCpuHasNEON)) {
341 MergeUVRow_ = MergeUVRow_Any_NEON;
342 if (IS_ALIGNED(halfwidth, 16)) {
343 MergeUVRow_ = MergeUVRow_NEON;
344 }
345 }
346 #endif
347 #if defined(HAS_ARGBTOYROW_DSPR2)
348 if (TestCpuFlag(kCpuHasDSPR2)) {
349 ARGBToYRow = ARGBToYRow_Any_DSPR2;
350 if (IS_ALIGNED(width, 8)) {
351 ARGBToYRow = ARGBToYRow_DSPR2;
352 }
353 }
354 #endif
355 #if defined(HAS_ARGBTOUVROW_DSPR2)
356 if (TestCpuFlag(kCpuHasDSPR2)) {
357 ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
358 if (IS_ALIGNED(width, 16)) {
359 ARGBToUVRow = ARGBToUVRow_DSPR2;
360 }
361 }
362 #endif
363 #if defined(HAS_MERGEUVROW_MSA)
364 if (TestCpuFlag(kCpuHasMSA)) {
365 MergeUVRow_ = MergeUVRow_Any_MSA;
366 if (IS_ALIGNED(halfwidth, 16)) {
367 MergeUVRow_ = MergeUVRow_MSA;
368 }
369 }
370 #endif
371 {
372 // Allocate a rows of uv.
373 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
374 uint8* row_v = row_u + ((halfwidth + 31) & ~31);
375
376 for (y = 0; y < height - 1; y += 2) {
377 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
378 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
379 ARGBToYRow(src_argb, dst_y, width);
380 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
381 src_argb += src_stride_argb * 2;
382 dst_y += dst_stride_y * 2;
383 dst_uv += dst_stride_uv;
384 }
385 if (height & 1) {
386 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
387 MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
388 ARGBToYRow(src_argb, dst_y, width);
389 }
390 free_aligned_buffer_64(row_u);
391 }
392 return 0;
393 }
394
395 // Same as NV12 but U and V swapped.
396 LIBYUV_API
ARGBToNV21(const uint8 * src_argb,int src_stride_argb,uint8 * dst_y,int dst_stride_y,uint8 * dst_uv,int dst_stride_uv,int width,int height)397 int ARGBToNV21(const uint8* src_argb,
398 int src_stride_argb,
399 uint8* dst_y,
400 int dst_stride_y,
401 uint8* dst_uv,
402 int dst_stride_uv,
403 int width,
404 int height) {
405 int y;
406 int halfwidth = (width + 1) >> 1;
407 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
408 uint8* dst_v, int width) = ARGBToUVRow_C;
409 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
410 ARGBToYRow_C;
411 void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
412 int width) = MergeUVRow_C;
413 if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
414 return -1;
415 }
416 // Negative height means invert the image.
417 if (height < 0) {
418 height = -height;
419 src_argb = src_argb + (height - 1) * src_stride_argb;
420 src_stride_argb = -src_stride_argb;
421 }
422 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
423 if (TestCpuFlag(kCpuHasSSSE3)) {
424 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
425 ARGBToYRow = ARGBToYRow_Any_SSSE3;
426 if (IS_ALIGNED(width, 16)) {
427 ARGBToUVRow = ARGBToUVRow_SSSE3;
428 ARGBToYRow = ARGBToYRow_SSSE3;
429 }
430 }
431 #endif
432 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
433 if (TestCpuFlag(kCpuHasAVX2)) {
434 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
435 ARGBToYRow = ARGBToYRow_Any_AVX2;
436 if (IS_ALIGNED(width, 32)) {
437 ARGBToUVRow = ARGBToUVRow_AVX2;
438 ARGBToYRow = ARGBToYRow_AVX2;
439 }
440 }
441 #endif
442 #if defined(HAS_ARGBTOYROW_NEON)
443 if (TestCpuFlag(kCpuHasNEON)) {
444 ARGBToYRow = ARGBToYRow_Any_NEON;
445 if (IS_ALIGNED(width, 8)) {
446 ARGBToYRow = ARGBToYRow_NEON;
447 }
448 }
449 #endif
450 #if defined(HAS_ARGBTOUVROW_NEON)
451 if (TestCpuFlag(kCpuHasNEON)) {
452 ARGBToUVRow = ARGBToUVRow_Any_NEON;
453 if (IS_ALIGNED(width, 16)) {
454 ARGBToUVRow = ARGBToUVRow_NEON;
455 }
456 }
457 #endif
458 #if defined(HAS_ARGBTOYROW_MSA)
459 if (TestCpuFlag(kCpuHasMSA)) {
460 ARGBToYRow = ARGBToYRow_Any_MSA;
461 if (IS_ALIGNED(width, 16)) {
462 ARGBToYRow = ARGBToYRow_MSA;
463 }
464 }
465 #endif
466 #if defined(HAS_ARGBTOUVROW_MSA)
467 if (TestCpuFlag(kCpuHasMSA)) {
468 ARGBToUVRow = ARGBToUVRow_Any_MSA;
469 if (IS_ALIGNED(width, 32)) {
470 ARGBToUVRow = ARGBToUVRow_MSA;
471 }
472 }
473 #endif
474 #if defined(HAS_MERGEUVROW_SSE2)
475 if (TestCpuFlag(kCpuHasSSE2)) {
476 MergeUVRow_ = MergeUVRow_Any_SSE2;
477 if (IS_ALIGNED(halfwidth, 16)) {
478 MergeUVRow_ = MergeUVRow_SSE2;
479 }
480 }
481 #endif
482 #if defined(HAS_MERGEUVROW_AVX2)
483 if (TestCpuFlag(kCpuHasAVX2)) {
484 MergeUVRow_ = MergeUVRow_Any_AVX2;
485 if (IS_ALIGNED(halfwidth, 32)) {
486 MergeUVRow_ = MergeUVRow_AVX2;
487 }
488 }
489 #endif
490 #if defined(HAS_MERGEUVROW_NEON)
491 if (TestCpuFlag(kCpuHasNEON)) {
492 MergeUVRow_ = MergeUVRow_Any_NEON;
493 if (IS_ALIGNED(halfwidth, 16)) {
494 MergeUVRow_ = MergeUVRow_NEON;
495 }
496 }
497 #endif
498 #if defined(HAS_ARGBTOYROW_DSPR2)
499 if (TestCpuFlag(kCpuHasDSPR2)) {
500 ARGBToYRow = ARGBToYRow_Any_DSPR2;
501 if (IS_ALIGNED(width, 8)) {
502 ARGBToYRow = ARGBToYRow_DSPR2;
503 }
504 }
505 #endif
506 #if defined(HAS_ARGBTOUVROW_DSPR2)
507 if (TestCpuFlag(kCpuHasDSPR2)) {
508 ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
509 if (IS_ALIGNED(width, 16)) {
510 ARGBToUVRow = ARGBToUVRow_DSPR2;
511 }
512 }
513 #endif
514 #if defined(HAS_MERGEUVROW_MSA)
515 if (TestCpuFlag(kCpuHasMSA)) {
516 MergeUVRow_ = MergeUVRow_Any_MSA;
517 if (IS_ALIGNED(halfwidth, 16)) {
518 MergeUVRow_ = MergeUVRow_MSA;
519 }
520 }
521 #endif
522 {
523 // Allocate a rows of uv.
524 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
525 uint8* row_v = row_u + ((halfwidth + 31) & ~31);
526
527 for (y = 0; y < height - 1; y += 2) {
528 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
529 MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
530 ARGBToYRow(src_argb, dst_y, width);
531 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
532 src_argb += src_stride_argb * 2;
533 dst_y += dst_stride_y * 2;
534 dst_uv += dst_stride_uv;
535 }
536 if (height & 1) {
537 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
538 MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
539 ARGBToYRow(src_argb, dst_y, width);
540 }
541 free_aligned_buffer_64(row_u);
542 }
543 return 0;
544 }
545
546 // Convert ARGB to YUY2.
547 LIBYUV_API
ARGBToYUY2(const uint8 * src_argb,int src_stride_argb,uint8 * dst_yuy2,int dst_stride_yuy2,int width,int height)548 int ARGBToYUY2(const uint8* src_argb,
549 int src_stride_argb,
550 uint8* dst_yuy2,
551 int dst_stride_yuy2,
552 int width,
553 int height) {
554 int y;
555 void (*ARGBToUVRow)(const uint8* src_argb, int src_stride_argb, uint8* dst_u,
556 uint8* dst_v, int width) = ARGBToUVRow_C;
557 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
558 ARGBToYRow_C;
559 void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u,
560 const uint8* src_v, uint8* dst_yuy2, int width) =
561 I422ToYUY2Row_C;
562
563 if (!src_argb || !dst_yuy2 || width <= 0 || height == 0) {
564 return -1;
565 }
566 // Negative height means invert the image.
567 if (height < 0) {
568 height = -height;
569 dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
570 dst_stride_yuy2 = -dst_stride_yuy2;
571 }
572 // Coalesce rows.
573 if (src_stride_argb == width * 4 && dst_stride_yuy2 == width * 2) {
574 width *= height;
575 height = 1;
576 src_stride_argb = dst_stride_yuy2 = 0;
577 }
578 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
579 if (TestCpuFlag(kCpuHasSSSE3)) {
580 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
581 ARGBToYRow = ARGBToYRow_Any_SSSE3;
582 if (IS_ALIGNED(width, 16)) {
583 ARGBToUVRow = ARGBToUVRow_SSSE3;
584 ARGBToYRow = ARGBToYRow_SSSE3;
585 }
586 }
587 #endif
588 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
589 if (TestCpuFlag(kCpuHasAVX2)) {
590 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
591 ARGBToYRow = ARGBToYRow_Any_AVX2;
592 if (IS_ALIGNED(width, 32)) {
593 ARGBToUVRow = ARGBToUVRow_AVX2;
594 ARGBToYRow = ARGBToYRow_AVX2;
595 }
596 }
597 #endif
598 #if defined(HAS_ARGBTOYROW_NEON)
599 if (TestCpuFlag(kCpuHasNEON)) {
600 ARGBToYRow = ARGBToYRow_Any_NEON;
601 if (IS_ALIGNED(width, 8)) {
602 ARGBToYRow = ARGBToYRow_NEON;
603 }
604 }
605 #endif
606 #if defined(HAS_ARGBTOUVROW_NEON)
607 if (TestCpuFlag(kCpuHasNEON)) {
608 ARGBToUVRow = ARGBToUVRow_Any_NEON;
609 if (IS_ALIGNED(width, 16)) {
610 ARGBToUVRow = ARGBToUVRow_NEON;
611 }
612 }
613 #endif
614 #if defined(HAS_ARGBTOYROW_MSA)
615 if (TestCpuFlag(kCpuHasMSA)) {
616 ARGBToYRow = ARGBToYRow_Any_MSA;
617 if (IS_ALIGNED(width, 16)) {
618 ARGBToYRow = ARGBToYRow_MSA;
619 }
620 }
621 #endif
622 #if defined(HAS_ARGBTOUVROW_MSA)
623 if (TestCpuFlag(kCpuHasMSA)) {
624 ARGBToUVRow = ARGBToUVRow_Any_MSA;
625 if (IS_ALIGNED(width, 32)) {
626 ARGBToUVRow = ARGBToUVRow_MSA;
627 }
628 }
629 #endif
630 #if defined(HAS_I422TOYUY2ROW_SSE2)
631 if (TestCpuFlag(kCpuHasSSE2)) {
632 I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
633 if (IS_ALIGNED(width, 16)) {
634 I422ToYUY2Row = I422ToYUY2Row_SSE2;
635 }
636 }
637 #endif
638 #if defined(HAS_I422TOYUY2ROW_NEON)
639 if (TestCpuFlag(kCpuHasNEON)) {
640 I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
641 if (IS_ALIGNED(width, 16)) {
642 I422ToYUY2Row = I422ToYUY2Row_NEON;
643 }
644 }
645 #endif
646 #if defined(HAS_ARGBTOYROW_DSPR2)
647 if (TestCpuFlag(kCpuHasDSPR2)) {
648 ARGBToYRow = ARGBToYRow_Any_DSPR2;
649 if (IS_ALIGNED(width, 8)) {
650 ARGBToYRow = ARGBToYRow_DSPR2;
651 }
652 }
653 #endif
654 #if defined(HAS_ARGBTOUVROW_DSPR2)
655 if (TestCpuFlag(kCpuHasDSPR2)) {
656 ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
657 if (IS_ALIGNED(width, 16)) {
658 ARGBToUVRow = ARGBToUVRow_DSPR2;
659 }
660 }
661 #endif
662 #if defined(HAS_I422TOYUY2ROW_MSA)
663 if (TestCpuFlag(kCpuHasMSA)) {
664 I422ToYUY2Row = I422ToYUY2Row_Any_MSA;
665 if (IS_ALIGNED(width, 32)) {
666 I422ToYUY2Row = I422ToYUY2Row_MSA;
667 }
668 }
669 #endif
670
671 {
672 // Allocate a rows of yuv.
673 align_buffer_64(row_y, ((width + 63) & ~63) * 2);
674 uint8* row_u = row_y + ((width + 63) & ~63);
675 uint8* row_v = row_u + ((width + 63) & ~63) / 2;
676
677 for (y = 0; y < height; ++y) {
678 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
679 ARGBToYRow(src_argb, row_y, width);
680 I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
681 src_argb += src_stride_argb;
682 dst_yuy2 += dst_stride_yuy2;
683 }
684
685 free_aligned_buffer_64(row_y);
686 }
687 return 0;
688 }
689
690 // Convert ARGB to UYVY.
691 LIBYUV_API
ARGBToUYVY(const uint8 * src_argb,int src_stride_argb,uint8 * dst_uyvy,int dst_stride_uyvy,int width,int height)692 int ARGBToUYVY(const uint8* src_argb,
693 int src_stride_argb,
694 uint8* dst_uyvy,
695 int dst_stride_uyvy,
696 int width,
697 int height) {
698 int y;
699 void (*ARGBToUVRow)(const uint8* src_argb, int src_stride_argb, uint8* dst_u,
700 uint8* dst_v, int width) = ARGBToUVRow_C;
701 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
702 ARGBToYRow_C;
703 void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u,
704 const uint8* src_v, uint8* dst_uyvy, int width) =
705 I422ToUYVYRow_C;
706
707 if (!src_argb || !dst_uyvy || width <= 0 || height == 0) {
708 return -1;
709 }
710 // Negative height means invert the image.
711 if (height < 0) {
712 height = -height;
713 dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
714 dst_stride_uyvy = -dst_stride_uyvy;
715 }
716 // Coalesce rows.
717 if (src_stride_argb == width * 4 && dst_stride_uyvy == width * 2) {
718 width *= height;
719 height = 1;
720 src_stride_argb = dst_stride_uyvy = 0;
721 }
722 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
723 if (TestCpuFlag(kCpuHasSSSE3)) {
724 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
725 ARGBToYRow = ARGBToYRow_Any_SSSE3;
726 if (IS_ALIGNED(width, 16)) {
727 ARGBToUVRow = ARGBToUVRow_SSSE3;
728 ARGBToYRow = ARGBToYRow_SSSE3;
729 }
730 }
731 #endif
732 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
733 if (TestCpuFlag(kCpuHasAVX2)) {
734 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
735 ARGBToYRow = ARGBToYRow_Any_AVX2;
736 if (IS_ALIGNED(width, 32)) {
737 ARGBToUVRow = ARGBToUVRow_AVX2;
738 ARGBToYRow = ARGBToYRow_AVX2;
739 }
740 }
741 #endif
742 #if defined(HAS_ARGBTOYROW_NEON)
743 if (TestCpuFlag(kCpuHasNEON)) {
744 ARGBToYRow = ARGBToYRow_Any_NEON;
745 if (IS_ALIGNED(width, 8)) {
746 ARGBToYRow = ARGBToYRow_NEON;
747 }
748 }
749 #endif
750 #if defined(HAS_ARGBTOUVROW_NEON)
751 if (TestCpuFlag(kCpuHasNEON)) {
752 ARGBToUVRow = ARGBToUVRow_Any_NEON;
753 if (IS_ALIGNED(width, 16)) {
754 ARGBToUVRow = ARGBToUVRow_NEON;
755 }
756 }
757 #endif
758 #if defined(HAS_ARGBTOYROW_MSA)
759 if (TestCpuFlag(kCpuHasMSA)) {
760 ARGBToYRow = ARGBToYRow_Any_MSA;
761 if (IS_ALIGNED(width, 16)) {
762 ARGBToYRow = ARGBToYRow_MSA;
763 }
764 }
765 #endif
766 #if defined(HAS_ARGBTOUVROW_MSA)
767 if (TestCpuFlag(kCpuHasMSA)) {
768 ARGBToUVRow = ARGBToUVRow_Any_MSA;
769 if (IS_ALIGNED(width, 32)) {
770 ARGBToUVRow = ARGBToUVRow_MSA;
771 }
772 }
773 #endif
774 #if defined(HAS_I422TOUYVYROW_SSE2)
775 if (TestCpuFlag(kCpuHasSSE2)) {
776 I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
777 if (IS_ALIGNED(width, 16)) {
778 I422ToUYVYRow = I422ToUYVYRow_SSE2;
779 }
780 }
781 #endif
782 #if defined(HAS_I422TOUYVYROW_NEON)
783 if (TestCpuFlag(kCpuHasNEON)) {
784 I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
785 if (IS_ALIGNED(width, 16)) {
786 I422ToUYVYRow = I422ToUYVYRow_NEON;
787 }
788 }
789 #endif
790 #if defined(HAS_ARGBTOYROW_DSPR2)
791 if (TestCpuFlag(kCpuHasDSPR2)) {
792 ARGBToYRow = ARGBToYRow_Any_DSPR2;
793 if (IS_ALIGNED(width, 8)) {
794 ARGBToYRow = ARGBToYRow_DSPR2;
795 }
796 }
797 #endif
798 #if defined(HAS_ARGBTOUVROW_DSPR2)
799 if (TestCpuFlag(kCpuHasDSPR2)) {
800 ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
801 if (IS_ALIGNED(width, 16)) {
802 ARGBToUVRow = ARGBToUVRow_DSPR2;
803 }
804 }
805 #endif
806 #if defined(HAS_I422TOUYVYROW_MSA)
807 if (TestCpuFlag(kCpuHasMSA)) {
808 I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
809 if (IS_ALIGNED(width, 32)) {
810 I422ToUYVYRow = I422ToUYVYRow_MSA;
811 }
812 }
813 #endif
814
815 {
816 // Allocate a rows of yuv.
817 align_buffer_64(row_y, ((width + 63) & ~63) * 2);
818 uint8* row_u = row_y + ((width + 63) & ~63);
819 uint8* row_v = row_u + ((width + 63) & ~63) / 2;
820
821 for (y = 0; y < height; ++y) {
822 ARGBToUVRow(src_argb, 0, row_u, row_v, width);
823 ARGBToYRow(src_argb, row_y, width);
824 I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
825 src_argb += src_stride_argb;
826 dst_uyvy += dst_stride_uyvy;
827 }
828
829 free_aligned_buffer_64(row_y);
830 }
831 return 0;
832 }
833
834 // Convert ARGB to I400.
835 LIBYUV_API
ARGBToI400(const uint8 * src_argb,int src_stride_argb,uint8 * dst_y,int dst_stride_y,int width,int height)836 int ARGBToI400(const uint8* src_argb,
837 int src_stride_argb,
838 uint8* dst_y,
839 int dst_stride_y,
840 int width,
841 int height) {
842 int y;
843 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
844 ARGBToYRow_C;
845 if (!src_argb || !dst_y || width <= 0 || height == 0) {
846 return -1;
847 }
848 if (height < 0) {
849 height = -height;
850 src_argb = src_argb + (height - 1) * src_stride_argb;
851 src_stride_argb = -src_stride_argb;
852 }
853 // Coalesce rows.
854 if (src_stride_argb == width * 4 && dst_stride_y == width) {
855 width *= height;
856 height = 1;
857 src_stride_argb = dst_stride_y = 0;
858 }
859 #if defined(HAS_ARGBTOYROW_SSSE3)
860 if (TestCpuFlag(kCpuHasSSSE3)) {
861 ARGBToYRow = ARGBToYRow_Any_SSSE3;
862 if (IS_ALIGNED(width, 16)) {
863 ARGBToYRow = ARGBToYRow_SSSE3;
864 }
865 }
866 #endif
867 #if defined(HAS_ARGBTOYROW_AVX2)
868 if (TestCpuFlag(kCpuHasAVX2)) {
869 ARGBToYRow = ARGBToYRow_Any_AVX2;
870 if (IS_ALIGNED(width, 32)) {
871 ARGBToYRow = ARGBToYRow_AVX2;
872 }
873 }
874 #endif
875 #if defined(HAS_ARGBTOYROW_NEON)
876 if (TestCpuFlag(kCpuHasNEON)) {
877 ARGBToYRow = ARGBToYRow_Any_NEON;
878 if (IS_ALIGNED(width, 8)) {
879 ARGBToYRow = ARGBToYRow_NEON;
880 }
881 }
882 #endif
883 #if defined(HAS_ARGBTOYROW_DSPR2)
884 if (TestCpuFlag(kCpuHasDSPR2)) {
885 ARGBToYRow = ARGBToYRow_Any_DSPR2;
886 if (IS_ALIGNED(width, 8)) {
887 ARGBToYRow = ARGBToYRow_DSPR2;
888 }
889 }
890 #endif
891 #if defined(HAS_ARGBTOYROW_MSA)
892 if (TestCpuFlag(kCpuHasMSA)) {
893 ARGBToYRow = ARGBToYRow_Any_MSA;
894 if (IS_ALIGNED(width, 16)) {
895 ARGBToYRow = ARGBToYRow_MSA;
896 }
897 }
898 #endif
899
900 for (y = 0; y < height; ++y) {
901 ARGBToYRow(src_argb, dst_y, width);
902 src_argb += src_stride_argb;
903 dst_y += dst_stride_y;
904 }
905 return 0;
906 }
907
908 // Shuffle table for converting ARGB to RGBA.
909 static uvec8 kShuffleMaskARGBToRGBA = {3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u,
910 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u};
911
912 // Convert ARGB to RGBA.
913 LIBYUV_API
ARGBToRGBA(const uint8 * src_argb,int src_stride_argb,uint8 * dst_rgba,int dst_stride_rgba,int width,int height)914 int ARGBToRGBA(const uint8* src_argb,
915 int src_stride_argb,
916 uint8* dst_rgba,
917 int dst_stride_rgba,
918 int width,
919 int height) {
920 return ARGBShuffle(src_argb, src_stride_argb, dst_rgba, dst_stride_rgba,
921 (const uint8*)(&kShuffleMaskARGBToRGBA), width, height);
922 }
923
924 // Convert ARGB To RGB24.
925 LIBYUV_API
ARGBToRGB24(const uint8 * src_argb,int src_stride_argb,uint8 * dst_rgb24,int dst_stride_rgb24,int width,int height)926 int ARGBToRGB24(const uint8* src_argb,
927 int src_stride_argb,
928 uint8* dst_rgb24,
929 int dst_stride_rgb24,
930 int width,
931 int height) {
932 int y;
933 void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int width) =
934 ARGBToRGB24Row_C;
935 if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
936 return -1;
937 }
938 if (height < 0) {
939 height = -height;
940 src_argb = src_argb + (height - 1) * src_stride_argb;
941 src_stride_argb = -src_stride_argb;
942 }
943 // Coalesce rows.
944 if (src_stride_argb == width * 4 && dst_stride_rgb24 == width * 3) {
945 width *= height;
946 height = 1;
947 src_stride_argb = dst_stride_rgb24 = 0;
948 }
949 #if defined(HAS_ARGBTORGB24ROW_SSSE3)
950 if (TestCpuFlag(kCpuHasSSSE3)) {
951 ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
952 if (IS_ALIGNED(width, 16)) {
953 ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
954 }
955 }
956 #endif
957 #if defined(HAS_ARGBTORGB24ROW_NEON)
958 if (TestCpuFlag(kCpuHasNEON)) {
959 ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
960 if (IS_ALIGNED(width, 8)) {
961 ARGBToRGB24Row = ARGBToRGB24Row_NEON;
962 }
963 }
964 #endif
965 #if defined(HAS_ARGBTORGB24ROW_MSA)
966 if (TestCpuFlag(kCpuHasMSA)) {
967 ARGBToRGB24Row = ARGBToRGB24Row_Any_MSA;
968 if (IS_ALIGNED(width, 16)) {
969 ARGBToRGB24Row = ARGBToRGB24Row_MSA;
970 }
971 }
972 #endif
973
974 for (y = 0; y < height; ++y) {
975 ARGBToRGB24Row(src_argb, dst_rgb24, width);
976 src_argb += src_stride_argb;
977 dst_rgb24 += dst_stride_rgb24;
978 }
979 return 0;
980 }
981
982 // Convert ARGB To RAW.
983 LIBYUV_API
ARGBToRAW(const uint8 * src_argb,int src_stride_argb,uint8 * dst_raw,int dst_stride_raw,int width,int height)984 int ARGBToRAW(const uint8* src_argb,
985 int src_stride_argb,
986 uint8* dst_raw,
987 int dst_stride_raw,
988 int width,
989 int height) {
990 int y;
991 void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int width) =
992 ARGBToRAWRow_C;
993 if (!src_argb || !dst_raw || width <= 0 || height == 0) {
994 return -1;
995 }
996 if (height < 0) {
997 height = -height;
998 src_argb = src_argb + (height - 1) * src_stride_argb;
999 src_stride_argb = -src_stride_argb;
1000 }
1001 // Coalesce rows.
1002 if (src_stride_argb == width * 4 && dst_stride_raw == width * 3) {
1003 width *= height;
1004 height = 1;
1005 src_stride_argb = dst_stride_raw = 0;
1006 }
1007 #if defined(HAS_ARGBTORAWROW_SSSE3)
1008 if (TestCpuFlag(kCpuHasSSSE3)) {
1009 ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
1010 if (IS_ALIGNED(width, 16)) {
1011 ARGBToRAWRow = ARGBToRAWRow_SSSE3;
1012 }
1013 }
1014 #endif
1015 #if defined(HAS_ARGBTORAWROW_NEON)
1016 if (TestCpuFlag(kCpuHasNEON)) {
1017 ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
1018 if (IS_ALIGNED(width, 8)) {
1019 ARGBToRAWRow = ARGBToRAWRow_NEON;
1020 }
1021 }
1022 #endif
1023 #if defined(HAS_ARGBTORAWROW_MSA)
1024 if (TestCpuFlag(kCpuHasMSA)) {
1025 ARGBToRAWRow = ARGBToRAWRow_Any_MSA;
1026 if (IS_ALIGNED(width, 16)) {
1027 ARGBToRAWRow = ARGBToRAWRow_MSA;
1028 }
1029 }
1030 #endif
1031
1032 for (y = 0; y < height; ++y) {
1033 ARGBToRAWRow(src_argb, dst_raw, width);
1034 src_argb += src_stride_argb;
1035 dst_raw += dst_stride_raw;
1036 }
1037 return 0;
1038 }
1039
1040 // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
1041 static const uint8 kDither565_4x4[16] = {
1042 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
1043 };
1044
1045 // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
1046 LIBYUV_API
ARGBToRGB565Dither(const uint8 * src_argb,int src_stride_argb,uint8 * dst_rgb565,int dst_stride_rgb565,const uint8 * dither4x4,int width,int height)1047 int ARGBToRGB565Dither(const uint8* src_argb,
1048 int src_stride_argb,
1049 uint8* dst_rgb565,
1050 int dst_stride_rgb565,
1051 const uint8* dither4x4,
1052 int width,
1053 int height) {
1054 int y;
1055 void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb,
1056 const uint32 dither4, int width) =
1057 ARGBToRGB565DitherRow_C;
1058 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1059 return -1;
1060 }
1061 if (height < 0) {
1062 height = -height;
1063 src_argb = src_argb + (height - 1) * src_stride_argb;
1064 src_stride_argb = -src_stride_argb;
1065 }
1066 if (!dither4x4) {
1067 dither4x4 = kDither565_4x4;
1068 }
1069 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
1070 if (TestCpuFlag(kCpuHasSSE2)) {
1071 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
1072 if (IS_ALIGNED(width, 4)) {
1073 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
1074 }
1075 }
1076 #endif
1077 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
1078 if (TestCpuFlag(kCpuHasAVX2)) {
1079 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
1080 if (IS_ALIGNED(width, 8)) {
1081 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
1082 }
1083 }
1084 #endif
1085 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
1086 if (TestCpuFlag(kCpuHasNEON)) {
1087 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
1088 if (IS_ALIGNED(width, 8)) {
1089 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
1090 }
1091 }
1092 #endif
1093 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
1094 if (TestCpuFlag(kCpuHasMSA)) {
1095 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
1096 if (IS_ALIGNED(width, 8)) {
1097 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
1098 }
1099 }
1100 #endif
1101
1102 for (y = 0; y < height; ++y) {
1103 ARGBToRGB565DitherRow(src_argb, dst_rgb565,
1104 *(uint32*)(dither4x4 + ((y & 3) << 2)),
1105 width); /* NOLINT */
1106 src_argb += src_stride_argb;
1107 dst_rgb565 += dst_stride_rgb565;
1108 }
1109 return 0;
1110 }
1111
1112 // Convert ARGB To RGB565.
1113 // TODO(fbarchard): Consider using dither function low level with zeros.
1114 LIBYUV_API
ARGBToRGB565(const uint8 * src_argb,int src_stride_argb,uint8 * dst_rgb565,int dst_stride_rgb565,int width,int height)1115 int ARGBToRGB565(const uint8* src_argb,
1116 int src_stride_argb,
1117 uint8* dst_rgb565,
1118 int dst_stride_rgb565,
1119 int width,
1120 int height) {
1121 int y;
1122 void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int width) =
1123 ARGBToRGB565Row_C;
1124 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1125 return -1;
1126 }
1127 if (height < 0) {
1128 height = -height;
1129 src_argb = src_argb + (height - 1) * src_stride_argb;
1130 src_stride_argb = -src_stride_argb;
1131 }
1132 // Coalesce rows.
1133 if (src_stride_argb == width * 4 && dst_stride_rgb565 == width * 2) {
1134 width *= height;
1135 height = 1;
1136 src_stride_argb = dst_stride_rgb565 = 0;
1137 }
1138 #if defined(HAS_ARGBTORGB565ROW_SSE2)
1139 if (TestCpuFlag(kCpuHasSSE2)) {
1140 ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
1141 if (IS_ALIGNED(width, 4)) {
1142 ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
1143 }
1144 }
1145 #endif
1146 #if defined(HAS_ARGBTORGB565ROW_AVX2)
1147 if (TestCpuFlag(kCpuHasAVX2)) {
1148 ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2;
1149 if (IS_ALIGNED(width, 8)) {
1150 ARGBToRGB565Row = ARGBToRGB565Row_AVX2;
1151 }
1152 }
1153 #endif
1154 #if defined(HAS_ARGBTORGB565ROW_NEON)
1155 if (TestCpuFlag(kCpuHasNEON)) {
1156 ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
1157 if (IS_ALIGNED(width, 8)) {
1158 ARGBToRGB565Row = ARGBToRGB565Row_NEON;
1159 }
1160 }
1161 #endif
1162 #if defined(HAS_ARGBTORGB565ROW_MSA)
1163 if (TestCpuFlag(kCpuHasMSA)) {
1164 ARGBToRGB565Row = ARGBToRGB565Row_Any_MSA;
1165 if (IS_ALIGNED(width, 8)) {
1166 ARGBToRGB565Row = ARGBToRGB565Row_MSA;
1167 }
1168 }
1169 #endif
1170
1171 for (y = 0; y < height; ++y) {
1172 ARGBToRGB565Row(src_argb, dst_rgb565, width);
1173 src_argb += src_stride_argb;
1174 dst_rgb565 += dst_stride_rgb565;
1175 }
1176 return 0;
1177 }
1178
1179 // Convert ARGB To ARGB1555.
1180 LIBYUV_API
ARGBToARGB1555(const uint8 * src_argb,int src_stride_argb,uint8 * dst_argb1555,int dst_stride_argb1555,int width,int height)1181 int ARGBToARGB1555(const uint8* src_argb,
1182 int src_stride_argb,
1183 uint8* dst_argb1555,
1184 int dst_stride_argb1555,
1185 int width,
1186 int height) {
1187 int y;
1188 void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int width) =
1189 ARGBToARGB1555Row_C;
1190 if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
1191 return -1;
1192 }
1193 if (height < 0) {
1194 height = -height;
1195 src_argb = src_argb + (height - 1) * src_stride_argb;
1196 src_stride_argb = -src_stride_argb;
1197 }
1198 // Coalesce rows.
1199 if (src_stride_argb == width * 4 && dst_stride_argb1555 == width * 2) {
1200 width *= height;
1201 height = 1;
1202 src_stride_argb = dst_stride_argb1555 = 0;
1203 }
1204 #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
1205 if (TestCpuFlag(kCpuHasSSE2)) {
1206 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
1207 if (IS_ALIGNED(width, 4)) {
1208 ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
1209 }
1210 }
1211 #endif
1212 #if defined(HAS_ARGBTOARGB1555ROW_AVX2)
1213 if (TestCpuFlag(kCpuHasAVX2)) {
1214 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2;
1215 if (IS_ALIGNED(width, 8)) {
1216 ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2;
1217 }
1218 }
1219 #endif
1220 #if defined(HAS_ARGBTOARGB1555ROW_NEON)
1221 if (TestCpuFlag(kCpuHasNEON)) {
1222 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
1223 if (IS_ALIGNED(width, 8)) {
1224 ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
1225 }
1226 }
1227 #endif
1228 #if defined(HAS_ARGBTOARGB1555ROW_MSA)
1229 if (TestCpuFlag(kCpuHasMSA)) {
1230 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_MSA;
1231 if (IS_ALIGNED(width, 8)) {
1232 ARGBToARGB1555Row = ARGBToARGB1555Row_MSA;
1233 }
1234 }
1235 #endif
1236
1237 for (y = 0; y < height; ++y) {
1238 ARGBToARGB1555Row(src_argb, dst_argb1555, width);
1239 src_argb += src_stride_argb;
1240 dst_argb1555 += dst_stride_argb1555;
1241 }
1242 return 0;
1243 }
1244
1245 // Convert ARGB To ARGB4444.
1246 LIBYUV_API
ARGBToARGB4444(const uint8 * src_argb,int src_stride_argb,uint8 * dst_argb4444,int dst_stride_argb4444,int width,int height)1247 int ARGBToARGB4444(const uint8* src_argb,
1248 int src_stride_argb,
1249 uint8* dst_argb4444,
1250 int dst_stride_argb4444,
1251 int width,
1252 int height) {
1253 int y;
1254 void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int width) =
1255 ARGBToARGB4444Row_C;
1256 if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
1257 return -1;
1258 }
1259 if (height < 0) {
1260 height = -height;
1261 src_argb = src_argb + (height - 1) * src_stride_argb;
1262 src_stride_argb = -src_stride_argb;
1263 }
1264 // Coalesce rows.
1265 if (src_stride_argb == width * 4 && dst_stride_argb4444 == width * 2) {
1266 width *= height;
1267 height = 1;
1268 src_stride_argb = dst_stride_argb4444 = 0;
1269 }
1270 #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
1271 if (TestCpuFlag(kCpuHasSSE2)) {
1272 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
1273 if (IS_ALIGNED(width, 4)) {
1274 ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
1275 }
1276 }
1277 #endif
1278 #if defined(HAS_ARGBTOARGB4444ROW_AVX2)
1279 if (TestCpuFlag(kCpuHasAVX2)) {
1280 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2;
1281 if (IS_ALIGNED(width, 8)) {
1282 ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2;
1283 }
1284 }
1285 #endif
1286 #if defined(HAS_ARGBTOARGB4444ROW_NEON)
1287 if (TestCpuFlag(kCpuHasNEON)) {
1288 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
1289 if (IS_ALIGNED(width, 8)) {
1290 ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
1291 }
1292 }
1293 #endif
1294 #if defined(HAS_ARGBTOARGB4444ROW_MSA)
1295 if (TestCpuFlag(kCpuHasMSA)) {
1296 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_MSA;
1297 if (IS_ALIGNED(width, 8)) {
1298 ARGBToARGB4444Row = ARGBToARGB4444Row_MSA;
1299 }
1300 }
1301 #endif
1302
1303 for (y = 0; y < height; ++y) {
1304 ARGBToARGB4444Row(src_argb, dst_argb4444, width);
1305 src_argb += src_stride_argb;
1306 dst_argb4444 += dst_stride_argb4444;
1307 }
1308 return 0;
1309 }
1310
1311 // Convert ARGB to J420. (JPeg full range I420).
1312 LIBYUV_API
ARGBToJ420(const uint8 * src_argb,int src_stride_argb,uint8 * dst_yj,int dst_stride_yj,uint8 * dst_u,int dst_stride_u,uint8 * dst_v,int dst_stride_v,int width,int height)1313 int ARGBToJ420(const uint8* src_argb,
1314 int src_stride_argb,
1315 uint8* dst_yj,
1316 int dst_stride_yj,
1317 uint8* dst_u,
1318 int dst_stride_u,
1319 uint8* dst_v,
1320 int dst_stride_v,
1321 int width,
1322 int height) {
1323 int y;
1324 void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb,
1325 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C;
1326 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int width) =
1327 ARGBToYJRow_C;
1328 if (!src_argb || !dst_yj || !dst_u || !dst_v || width <= 0 || height == 0) {
1329 return -1;
1330 }
1331 // Negative height means invert the image.
1332 if (height < 0) {
1333 height = -height;
1334 src_argb = src_argb + (height - 1) * src_stride_argb;
1335 src_stride_argb = -src_stride_argb;
1336 }
1337 #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
1338 if (TestCpuFlag(kCpuHasSSSE3)) {
1339 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
1340 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
1341 if (IS_ALIGNED(width, 16)) {
1342 ARGBToUVJRow = ARGBToUVJRow_SSSE3;
1343 ARGBToYJRow = ARGBToYJRow_SSSE3;
1344 }
1345 }
1346 #endif
1347 #if defined(HAS_ARGBTOYJROW_AVX2)
1348 if (TestCpuFlag(kCpuHasAVX2)) {
1349 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
1350 if (IS_ALIGNED(width, 32)) {
1351 ARGBToYJRow = ARGBToYJRow_AVX2;
1352 }
1353 }
1354 #endif
1355 #if defined(HAS_ARGBTOYJROW_NEON)
1356 if (TestCpuFlag(kCpuHasNEON)) {
1357 ARGBToYJRow = ARGBToYJRow_Any_NEON;
1358 if (IS_ALIGNED(width, 8)) {
1359 ARGBToYJRow = ARGBToYJRow_NEON;
1360 }
1361 }
1362 #endif
1363 #if defined(HAS_ARGBTOUVJROW_NEON)
1364 if (TestCpuFlag(kCpuHasNEON)) {
1365 ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
1366 if (IS_ALIGNED(width, 16)) {
1367 ARGBToUVJRow = ARGBToUVJRow_NEON;
1368 }
1369 }
1370 #endif
1371 #if defined(HAS_ARGBTOYJROW_MSA)
1372 if (TestCpuFlag(kCpuHasMSA)) {
1373 ARGBToYJRow = ARGBToYJRow_Any_MSA;
1374 if (IS_ALIGNED(width, 16)) {
1375 ARGBToYJRow = ARGBToYJRow_MSA;
1376 }
1377 }
1378 #endif
1379 #if defined(HAS_ARGBTOUVJROW_MSA)
1380 if (TestCpuFlag(kCpuHasMSA)) {
1381 ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
1382 if (IS_ALIGNED(width, 32)) {
1383 ARGBToUVJRow = ARGBToUVJRow_MSA;
1384 }
1385 }
1386 #endif
1387
1388 for (y = 0; y < height - 1; y += 2) {
1389 ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width);
1390 ARGBToYJRow(src_argb, dst_yj, width);
1391 ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
1392 src_argb += src_stride_argb * 2;
1393 dst_yj += dst_stride_yj * 2;
1394 dst_u += dst_stride_u;
1395 dst_v += dst_stride_v;
1396 }
1397 if (height & 1) {
1398 ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
1399 ARGBToYJRow(src_argb, dst_yj, width);
1400 }
1401 return 0;
1402 }
1403
1404 // Convert ARGB to J422. (JPeg full range I422).
1405 LIBYUV_API
ARGBToJ422(const uint8 * src_argb,int src_stride_argb,uint8 * dst_yj,int dst_stride_yj,uint8 * dst_u,int dst_stride_u,uint8 * dst_v,int dst_stride_v,int width,int height)1406 int ARGBToJ422(const uint8* src_argb,
1407 int src_stride_argb,
1408 uint8* dst_yj,
1409 int dst_stride_yj,
1410 uint8* dst_u,
1411 int dst_stride_u,
1412 uint8* dst_v,
1413 int dst_stride_v,
1414 int width,
1415 int height) {
1416 int y;
1417 void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb,
1418 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C;
1419 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int width) =
1420 ARGBToYJRow_C;
1421 if (!src_argb || !dst_yj || !dst_u || !dst_v || width <= 0 || height == 0) {
1422 return -1;
1423 }
1424 // Negative height means invert the image.
1425 if (height < 0) {
1426 height = -height;
1427 src_argb = src_argb + (height - 1) * src_stride_argb;
1428 src_stride_argb = -src_stride_argb;
1429 }
1430 // Coalesce rows.
1431 if (src_stride_argb == width * 4 && dst_stride_yj == width &&
1432 dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
1433 width *= height;
1434 height = 1;
1435 src_stride_argb = dst_stride_yj = dst_stride_u = dst_stride_v = 0;
1436 }
1437 #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
1438 if (TestCpuFlag(kCpuHasSSSE3)) {
1439 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
1440 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
1441 if (IS_ALIGNED(width, 16)) {
1442 ARGBToUVJRow = ARGBToUVJRow_SSSE3;
1443 ARGBToYJRow = ARGBToYJRow_SSSE3;
1444 }
1445 }
1446 #endif
1447 #if defined(HAS_ARGBTOYJROW_AVX2)
1448 if (TestCpuFlag(kCpuHasAVX2)) {
1449 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
1450 if (IS_ALIGNED(width, 32)) {
1451 ARGBToYJRow = ARGBToYJRow_AVX2;
1452 }
1453 }
1454 #endif
1455 #if defined(HAS_ARGBTOYJROW_NEON)
1456 if (TestCpuFlag(kCpuHasNEON)) {
1457 ARGBToYJRow = ARGBToYJRow_Any_NEON;
1458 if (IS_ALIGNED(width, 8)) {
1459 ARGBToYJRow = ARGBToYJRow_NEON;
1460 }
1461 }
1462 #endif
1463 #if defined(HAS_ARGBTOUVJROW_NEON)
1464 if (TestCpuFlag(kCpuHasNEON)) {
1465 ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
1466 if (IS_ALIGNED(width, 16)) {
1467 ARGBToUVJRow = ARGBToUVJRow_NEON;
1468 }
1469 }
1470 #endif
1471 #if defined(HAS_ARGBTOYJROW_MSA)
1472 if (TestCpuFlag(kCpuHasMSA)) {
1473 ARGBToYJRow = ARGBToYJRow_Any_MSA;
1474 if (IS_ALIGNED(width, 16)) {
1475 ARGBToYJRow = ARGBToYJRow_MSA;
1476 }
1477 }
1478 #endif
1479 #if defined(HAS_ARGBTOUVJROW_MSA)
1480 if (TestCpuFlag(kCpuHasMSA)) {
1481 ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
1482 if (IS_ALIGNED(width, 32)) {
1483 ARGBToUVJRow = ARGBToUVJRow_MSA;
1484 }
1485 }
1486 #endif
1487
1488 for (y = 0; y < height; ++y) {
1489 ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
1490 ARGBToYJRow(src_argb, dst_yj, width);
1491 src_argb += src_stride_argb;
1492 dst_yj += dst_stride_yj;
1493 dst_u += dst_stride_u;
1494 dst_v += dst_stride_v;
1495 }
1496 return 0;
1497 }
1498
1499 // Convert ARGB to J400.
1500 LIBYUV_API
ARGBToJ400(const uint8 * src_argb,int src_stride_argb,uint8 * dst_yj,int dst_stride_yj,int width,int height)1501 int ARGBToJ400(const uint8* src_argb,
1502 int src_stride_argb,
1503 uint8* dst_yj,
1504 int dst_stride_yj,
1505 int width,
1506 int height) {
1507 int y;
1508 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int width) =
1509 ARGBToYJRow_C;
1510 if (!src_argb || !dst_yj || width <= 0 || height == 0) {
1511 return -1;
1512 }
1513 if (height < 0) {
1514 height = -height;
1515 src_argb = src_argb + (height - 1) * src_stride_argb;
1516 src_stride_argb = -src_stride_argb;
1517 }
1518 // Coalesce rows.
1519 if (src_stride_argb == width * 4 && dst_stride_yj == width) {
1520 width *= height;
1521 height = 1;
1522 src_stride_argb = dst_stride_yj = 0;
1523 }
1524 #if defined(HAS_ARGBTOYJROW_SSSE3)
1525 if (TestCpuFlag(kCpuHasSSSE3)) {
1526 ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
1527 if (IS_ALIGNED(width, 16)) {
1528 ARGBToYJRow = ARGBToYJRow_SSSE3;
1529 }
1530 }
1531 #endif
1532 #if defined(HAS_ARGBTOYJROW_AVX2)
1533 if (TestCpuFlag(kCpuHasAVX2)) {
1534 ARGBToYJRow = ARGBToYJRow_Any_AVX2;
1535 if (IS_ALIGNED(width, 32)) {
1536 ARGBToYJRow = ARGBToYJRow_AVX2;
1537 }
1538 }
1539 #endif
1540 #if defined(HAS_ARGBTOYJROW_NEON)
1541 if (TestCpuFlag(kCpuHasNEON)) {
1542 ARGBToYJRow = ARGBToYJRow_Any_NEON;
1543 if (IS_ALIGNED(width, 8)) {
1544 ARGBToYJRow = ARGBToYJRow_NEON;
1545 }
1546 }
1547 #endif
1548 #if defined(HAS_ARGBTOYJROW_MSA)
1549 if (TestCpuFlag(kCpuHasMSA)) {
1550 ARGBToYJRow = ARGBToYJRow_Any_MSA;
1551 if (IS_ALIGNED(width, 16)) {
1552 ARGBToYJRow = ARGBToYJRow_MSA;
1553 }
1554 }
1555 #endif
1556
1557 for (y = 0; y < height; ++y) {
1558 ARGBToYJRow(src_argb, dst_yj, width);
1559 src_argb += src_stride_argb;
1560 dst_yj += dst_stride_yj;
1561 }
1562 return 0;
1563 }
1564
1565 #ifdef __cplusplus
1566 } // extern "C"
1567 } // namespace libyuv
1568 #endif
1569