media/libyuv/source/convert_argb.cc

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:8e46fb1eec5b
1 /*
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "libyuv/convert_argb.h"
12
13 #include "libyuv/cpu_id.h"
14 #include "libyuv/format_conversion.h"
15 #ifdef HAVE_JPEG
16 #include "libyuv/mjpeg_decoder.h"
17 #endif
18 #include "libyuv/rotate_argb.h"
19 #include "libyuv/row.h"
20 #include "libyuv/video_common.h"
21
22 #ifdef __cplusplus
23 namespace libyuv {
24 extern "C" {
25 #endif
26
27 // Copy ARGB with optional flipping
28 LIBYUV_API
29 int ARGBCopy(const uint8* src_argb, int src_stride_argb,
30 uint8* dst_argb, int dst_stride_argb,
31 int width, int height) {
32 if (!src_argb || !dst_argb ||
33 width <= 0 || height == 0) {
34 return -1;
35 }
36 // Negative height means invert the image.
37 if (height < 0) {
38 height = -height;
39 src_argb = src_argb + (height - 1) * src_stride_argb;
40 src_stride_argb = -src_stride_argb;
41 }
42
43 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
44 width * 4, height);
45 return 0;
46 }
47
48 // Convert I444 to ARGB.
49 LIBYUV_API
50 int I444ToARGB(const uint8* src_y, int src_stride_y,
51 const uint8* src_u, int src_stride_u,
52 const uint8* src_v, int src_stride_v,
53 uint8* dst_argb, int dst_stride_argb,
54 int width, int height) {
55 if (!src_y || !src_u || !src_v ||
56 !dst_argb ||
57 width <= 0 || height == 0) {
58 return -1;
59 }
60 // Negative height means invert the image.
61 if (height < 0) {
62 height = -height;
63 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
64 dst_stride_argb = -dst_stride_argb;
65 }
66 // Coalesce rows.
67 if (src_stride_y == width &&
68 src_stride_u == width &&
69 src_stride_v == width &&
70 dst_stride_argb == width * 4) {
71 width *= height;
72 height = 1;
73 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
74 }
75 void (*I444ToARGBRow)(const uint8* y_buf,
76 const uint8* u_buf,
77 const uint8* v_buf,
78 uint8* rgb_buf,
79 int width) = I444ToARGBRow_C;
80 #if defined(HAS_I444TOARGBROW_SSSE3)
81 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
82 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
83 if (IS_ALIGNED(width, 8)) {
84 I444ToARGBRow = I444ToARGBRow_Unaligned_SSSE3;
85 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
86 I444ToARGBRow = I444ToARGBRow_SSSE3;
87 }
88 }
89 }
90 #elif defined(HAS_I444TOARGBROW_NEON)
91 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
92 I444ToARGBRow = I444ToARGBRow_Any_NEON;
93 if (IS_ALIGNED(width, 8)) {
94 I444ToARGBRow = I444ToARGBRow_NEON;
95 }
96 }
97 #endif
98
99 for (int y = 0; y < height; ++y) {
100 I444ToARGBRow(src_y, src_u, src_v, dst_argb, width);
101 dst_argb += dst_stride_argb;
102 src_y += src_stride_y;
103 src_u += src_stride_u;
104 src_v += src_stride_v;
105 }
106 return 0;
107 }
108
109 // Convert I422 to ARGB.
110 LIBYUV_API
111 int I422ToARGB(const uint8* src_y, int src_stride_y,
112 const uint8* src_u, int src_stride_u,
113 const uint8* src_v, int src_stride_v,
114 uint8* dst_argb, int dst_stride_argb,
115 int width, int height) {
116 if (!src_y || !src_u || !src_v ||
117 !dst_argb ||
118 width <= 0 || height == 0) {
119 return -1;
120 }
121 // Negative height means invert the image.
122 if (height < 0) {
123 height = -height;
124 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
125 dst_stride_argb = -dst_stride_argb;
126 }
127 // Coalesce rows.
128 if (src_stride_y == width &&
129 src_stride_u * 2 == width &&
130 src_stride_v * 2 == width &&
131 dst_stride_argb == width * 4) {
132 width *= height;
133 height = 1;
134 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
135 }
136 void (*I422ToARGBRow)(const uint8* y_buf,
137 const uint8* u_buf,
138 const uint8* v_buf,
139 uint8* rgb_buf,
140 int width) = I422ToARGBRow_C;
141 #if defined(HAS_I422TOARGBROW_SSSE3)
142 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
143 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
144 if (IS_ALIGNED(width, 8)) {
145 I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3;
146 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
147 I422ToARGBRow = I422ToARGBRow_SSSE3;
148 }
149 }
150 }
151 #endif
152 #if defined(HAS_I422TOARGBROW_AVX2)
153 if (TestCpuFlag(kCpuHasAVX2) && width >= 16) {
154 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
155 if (IS_ALIGNED(width, 16)) {
156 I422ToARGBRow = I422ToARGBRow_AVX2;
157 }
158 }
159 #endif
160 #if defined(HAS_I422TOARGBROW_NEON)
161 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
162 I422ToARGBRow = I422ToARGBRow_Any_NEON;
163 if (IS_ALIGNED(width, 8)) {
164 I422ToARGBRow = I422ToARGBRow_NEON;
165 }
166 }
167 #endif
168 #if defined(HAS_I422TOARGBROW_MIPS_DSPR2)
169 if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
170 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
171 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
172 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
173 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
174 I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2;
175 }
176 #endif
177
178 for (int y = 0; y < height; ++y) {
179 I422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
180 dst_argb += dst_stride_argb;
181 src_y += src_stride_y;
182 src_u += src_stride_u;
183 src_v += src_stride_v;
184 }
185 return 0;
186 }
187
188 // Convert I411 to ARGB.
189 LIBYUV_API
190 int I411ToARGB(const uint8* src_y, int src_stride_y,
191 const uint8* src_u, int src_stride_u,
192 const uint8* src_v, int src_stride_v,
193 uint8* dst_argb, int dst_stride_argb,
194 int width, int height) {
195 if (!src_y || !src_u || !src_v ||
196 !dst_argb ||
197 width <= 0 || height == 0) {
198 return -1;
199 }
200 // Negative height means invert the image.
201 if (height < 0) {
202 height = -height;
203 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
204 dst_stride_argb = -dst_stride_argb;
205 }
206 // Coalesce rows.
207 if (src_stride_y == width &&
208 src_stride_u * 4 == width &&
209 src_stride_v * 4 == width &&
210 dst_stride_argb == width * 4) {
211 width *= height;
212 height = 1;
213 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
214 }
215 void (*I411ToARGBRow)(const uint8* y_buf,
216 const uint8* u_buf,
217 const uint8* v_buf,
218 uint8* rgb_buf,
219 int width) = I411ToARGBRow_C;
220 #if defined(HAS_I411TOARGBROW_SSSE3)
221 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
222 I411ToARGBRow = I411ToARGBRow_Any_SSSE3;
223 if (IS_ALIGNED(width, 8)) {
224 I411ToARGBRow = I411ToARGBRow_Unaligned_SSSE3;
225 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
226 I411ToARGBRow = I411ToARGBRow_SSSE3;
227 }
228 }
229 }
230 #elif defined(HAS_I411TOARGBROW_NEON)
231 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
232 I411ToARGBRow = I411ToARGBRow_Any_NEON;
233 if (IS_ALIGNED(width, 8)) {
234 I411ToARGBRow = I411ToARGBRow_NEON;
235 }
236 }
237 #endif
238
239 for (int y = 0; y < height; ++y) {
240 I411ToARGBRow(src_y, src_u, src_v, dst_argb, width);
241 dst_argb += dst_stride_argb;
242 src_y += src_stride_y;
243 src_u += src_stride_u;
244 src_v += src_stride_v;
245 }
246 return 0;
247 }
248
249 // Convert I400 to ARGB.
250 LIBYUV_API
251 int I400ToARGB_Reference(const uint8* src_y, int src_stride_y,
252 uint8* dst_argb, int dst_stride_argb,
253 int width, int height) {
254 if (!src_y || !dst_argb ||
255 width <= 0 || height == 0) {
256 return -1;
257 }
258 // Negative height means invert the image.
259 if (height < 0) {
260 height = -height;
261 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
262 dst_stride_argb = -dst_stride_argb;
263 }
264 // Coalesce rows.
265 if (src_stride_y == width &&
266 dst_stride_argb == width * 4) {
267 width *= height;
268 height = 1;
269 src_stride_y = dst_stride_argb = 0;
270 }
271 void (*YToARGBRow)(const uint8* y_buf,
272 uint8* rgb_buf,
273 int width) = YToARGBRow_C;
274 #if defined(HAS_YTOARGBROW_SSE2)
275 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
276 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
277 YToARGBRow = YToARGBRow_Any_SSE2;
278 if (IS_ALIGNED(width, 8)) {
279 YToARGBRow = YToARGBRow_SSE2;
280 }
281 }
282 #elif defined(HAS_YTOARGBROW_NEON)
283 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
284 YToARGBRow = YToARGBRow_Any_NEON;
285 if (IS_ALIGNED(width, 8)) {
286 YToARGBRow = YToARGBRow_NEON;
287 }
288 }
289 #endif
290
291 for (int y = 0; y < height; ++y) {
292 YToARGBRow(src_y, dst_argb, width);
293 dst_argb += dst_stride_argb;
294 src_y += src_stride_y;
295 }
296 return 0;
297 }
298
299 // Convert I400 to ARGB.
300 LIBYUV_API
301 int I400ToARGB(const uint8* src_y, int src_stride_y,
302 uint8* dst_argb, int dst_stride_argb,
303 int width, int height) {
304 if (!src_y || !dst_argb ||
305 width <= 0 || height == 0) {
306 return -1;
307 }
308 // Negative height means invert the image.
309 if (height < 0) {
310 height = -height;
311 src_y = src_y + (height - 1) * src_stride_y;
312 src_stride_y = -src_stride_y;
313 }
314 // Coalesce rows.
315 if (src_stride_y == width &&
316 dst_stride_argb == width * 4) {
317 width *= height;
318 height = 1;
319 src_stride_y = dst_stride_argb = 0;
320 }
321 void (*I400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) =
322 I400ToARGBRow_C;
323 #if defined(HAS_I400TOARGBROW_SSE2)
324 if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
325 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
326 if (IS_ALIGNED(width, 8)) {
327 I400ToARGBRow = I400ToARGBRow_Unaligned_SSE2;
328 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
329 I400ToARGBRow = I400ToARGBRow_SSE2;
330 }
331 }
332 }
333 #elif defined(HAS_I400TOARGBROW_NEON)
334 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
335 I400ToARGBRow = I400ToARGBRow_Any_NEON;
336 if (IS_ALIGNED(width, 8)) {
337 I400ToARGBRow = I400ToARGBRow_NEON;
338 }
339 }
340 #endif
341 for (int y = 0; y < height; ++y) {
342 I400ToARGBRow(src_y, dst_argb, width);
343 src_y += src_stride_y;
344 dst_argb += dst_stride_argb;
345 }
346 return 0;
347 }
348
349 // Shuffle table for converting BGRA to ARGB.
350 static uvec8 kShuffleMaskBGRAToARGB = {
351 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u
352 };
353
354 // Shuffle table for converting ABGR to ARGB.
355 static uvec8 kShuffleMaskABGRToARGB = {
356 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u
357 };
358
359 // Shuffle table for converting RGBA to ARGB.
360 static uvec8 kShuffleMaskRGBAToARGB = {
361 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u
362 };
363
364 // Convert BGRA to ARGB.
365 LIBYUV_API
366 int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
367 uint8* dst_argb, int dst_stride_argb,
368 int width, int height) {
369 return ARGBShuffle(src_bgra, src_stride_bgra,
370 dst_argb, dst_stride_argb,
371 (const uint8*)(&kShuffleMaskBGRAToARGB),
372 width, height);
373 }
374
375 // Convert ABGR to ARGB.
376 LIBYUV_API
377 int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
378 uint8* dst_argb, int dst_stride_argb,
379 int width, int height) {
380 return ARGBShuffle(src_abgr, src_stride_abgr,
381 dst_argb, dst_stride_argb,
382 (const uint8*)(&kShuffleMaskABGRToARGB),
383 width, height);
384 }
385
386 // Convert RGBA to ARGB.
387 LIBYUV_API
388 int RGBAToARGB(const uint8* src_rgba, int src_stride_rgba,
389 uint8* dst_argb, int dst_stride_argb,
390 int width, int height) {
391 return ARGBShuffle(src_rgba, src_stride_rgba,
392 dst_argb, dst_stride_argb,
393 (const uint8*)(&kShuffleMaskRGBAToARGB),
394 width, height);
395 }
396
397 // Convert RGB24 to ARGB.
398 LIBYUV_API
399 int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
400 uint8* dst_argb, int dst_stride_argb,
401 int width, int height) {
402 if (!src_rgb24 || !dst_argb ||
403 width <= 0 || height == 0) {
404 return -1;
405 }
406 // Negative height means invert the image.
407 if (height < 0) {
408 height = -height;
409 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
410 src_stride_rgb24 = -src_stride_rgb24;
411 }
412 // Coalesce rows.
413 if (src_stride_rgb24 == width * 3 &&
414 dst_stride_argb == width * 4) {
415 width *= height;
416 height = 1;
417 src_stride_rgb24 = dst_stride_argb = 0;
418 }
419 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
420 RGB24ToARGBRow_C;
421 #if defined(HAS_RGB24TOARGBROW_SSSE3)
422 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
423 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
424 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
425 if (IS_ALIGNED(width, 16)) {
426 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
427 }
428 }
429 #elif defined(HAS_RGB24TOARGBROW_NEON)
430 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
431 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
432 if (IS_ALIGNED(width, 8)) {
433 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
434 }
435 }
436 #endif
437
438 for (int y = 0; y < height; ++y) {
439 RGB24ToARGBRow(src_rgb24, dst_argb, width);
440 src_rgb24 += src_stride_rgb24;
441 dst_argb += dst_stride_argb;
442 }
443 return 0;
444 }
445
446 // Convert RAW to ARGB.
447 LIBYUV_API
448 int RAWToARGB(const uint8* src_raw, int src_stride_raw,
449 uint8* dst_argb, int dst_stride_argb,
450 int width, int height) {
451 if (!src_raw || !dst_argb ||
452 width <= 0 || height == 0) {
453 return -1;
454 }
455 // Negative height means invert the image.
456 if (height < 0) {
457 height = -height;
458 src_raw = src_raw + (height - 1) * src_stride_raw;
459 src_stride_raw = -src_stride_raw;
460 }
461 // Coalesce rows.
462 if (src_stride_raw == width * 3 &&
463 dst_stride_argb == width * 4) {
464 width *= height;
465 height = 1;
466 src_stride_raw = dst_stride_argb = 0;
467 }
468 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
469 RAWToARGBRow_C;
470 #if defined(HAS_RAWTOARGBROW_SSSE3)
471 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
472 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
473 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
474 if (IS_ALIGNED(width, 16)) {
475 RAWToARGBRow = RAWToARGBRow_SSSE3;
476 }
477 }
478 #elif defined(HAS_RAWTOARGBROW_NEON)
479 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
480 RAWToARGBRow = RAWToARGBRow_Any_NEON;
481 if (IS_ALIGNED(width, 8)) {
482 RAWToARGBRow = RAWToARGBRow_NEON;
483 }
484 }
485 #endif
486
487 for (int y = 0; y < height; ++y) {
488 RAWToARGBRow(src_raw, dst_argb, width);
489 src_raw += src_stride_raw;
490 dst_argb += dst_stride_argb;
491 }
492 return 0;
493 }
494
495 // Convert RGB565 to ARGB.
496 LIBYUV_API
497 int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
498 uint8* dst_argb, int dst_stride_argb,
499 int width, int height) {
500 if (!src_rgb565 || !dst_argb ||
501 width <= 0 || height == 0) {
502 return -1;
503 }
504 // Negative height means invert the image.
505 if (height < 0) {
506 height = -height;
507 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
508 src_stride_rgb565 = -src_stride_rgb565;
509 }
510 // Coalesce rows.
511 if (src_stride_rgb565 == width * 2 &&
512 dst_stride_argb == width * 4) {
513 width *= height;
514 height = 1;
515 src_stride_rgb565 = dst_stride_argb = 0;
516 }
517 void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) =
518 RGB565ToARGBRow_C;
519 #if defined(HAS_RGB565TOARGBROW_SSE2)
520 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
521 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
522 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
523 if (IS_ALIGNED(width, 8)) {
524 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
525 }
526 }
527 #elif defined(HAS_RGB565TOARGBROW_NEON)
528 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
529 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
530 if (IS_ALIGNED(width, 8)) {
531 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
532 }
533 }
534 #endif
535
536 for (int y = 0; y < height; ++y) {
537 RGB565ToARGBRow(src_rgb565, dst_argb, width);
538 src_rgb565 += src_stride_rgb565;
539 dst_argb += dst_stride_argb;
540 }
541 return 0;
542 }
543
544 // Convert ARGB1555 to ARGB.
545 LIBYUV_API
546 int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
547 uint8* dst_argb, int dst_stride_argb,
548 int width, int height) {
549 if (!src_argb1555 || !dst_argb ||
550 width <= 0 || height == 0) {
551 return -1;
552 }
553 // Negative height means invert the image.
554 if (height < 0) {
555 height = -height;
556 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
557 src_stride_argb1555 = -src_stride_argb1555;
558 }
559 // Coalesce rows.
560 if (src_stride_argb1555 == width * 2 &&
561 dst_stride_argb == width * 4) {
562 width *= height;
563 height = 1;
564 src_stride_argb1555 = dst_stride_argb = 0;
565 }
566 void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
567 int pix) = ARGB1555ToARGBRow_C;
568 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
569 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
570 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
571 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
572 if (IS_ALIGNED(width, 8)) {
573 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
574 }
575 }
576 #elif defined(HAS_ARGB1555TOARGBROW_NEON)
577 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
578 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
579 if (IS_ALIGNED(width, 8)) {
580 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
581 }
582 }
583 #endif
584
585 for (int y = 0; y < height; ++y) {
586 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
587 src_argb1555 += src_stride_argb1555;
588 dst_argb += dst_stride_argb;
589 }
590 return 0;
591 }
592
593 // Convert ARGB4444 to ARGB.
594 LIBYUV_API
595 int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
596 uint8* dst_argb, int dst_stride_argb,
597 int width, int height) {
598 if (!src_argb4444 || !dst_argb ||
599 width <= 0 || height == 0) {
600 return -1;
601 }
602 // Negative height means invert the image.
603 if (height < 0) {
604 height = -height;
605 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
606 src_stride_argb4444 = -src_stride_argb4444;
607 }
608 // Coalesce rows.
609 if (src_stride_argb4444 == width * 2 &&
610 dst_stride_argb == width * 4) {
611 width *= height;
612 height = 1;
613 src_stride_argb4444 = dst_stride_argb = 0;
614 }
615 void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
616 int pix) = ARGB4444ToARGBRow_C;
617 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
618 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
619 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
620 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
621 if (IS_ALIGNED(width, 8)) {
622 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
623 }
624 }
625 #elif defined(HAS_ARGB4444TOARGBROW_NEON)
626 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
627 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
628 if (IS_ALIGNED(width, 8)) {
629 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
630 }
631 }
632 #endif
633
634 for (int y = 0; y < height; ++y) {
635 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
636 src_argb4444 += src_stride_argb4444;
637 dst_argb += dst_stride_argb;
638 }
639 return 0;
640 }
641
642 // Convert NV12 to ARGB.
643 LIBYUV_API
644 int NV12ToARGB(const uint8* src_y, int src_stride_y,
645 const uint8* src_uv, int src_stride_uv,
646 uint8* dst_argb, int dst_stride_argb,
647 int width, int height) {
648 if (!src_y || !src_uv || !dst_argb ||
649 width <= 0 || height == 0) {
650 return -1;
651 }
652 // Negative height means invert the image.
653 if (height < 0) {
654 height = -height;
655 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
656 dst_stride_argb = -dst_stride_argb;
657 }
658 void (*NV12ToARGBRow)(const uint8* y_buf,
659 const uint8* uv_buf,
660 uint8* rgb_buf,
661 int width) = NV12ToARGBRow_C;
662 #if defined(HAS_NV12TOARGBROW_SSSE3)
663 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
664 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
665 if (IS_ALIGNED(width, 8)) {
666 NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
667 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
668 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
669 }
670 }
671 }
672 #elif defined(HAS_NV12TOARGBROW_NEON)
673 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
674 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
675 if (IS_ALIGNED(width, 8)) {
676 NV12ToARGBRow = NV12ToARGBRow_NEON;
677 }
678 }
679 #endif
680
681 for (int y = 0; y < height; ++y) {
682 NV12ToARGBRow(src_y, src_uv, dst_argb, width);
683 dst_argb += dst_stride_argb;
684 src_y += src_stride_y;
685 if (y & 1) {
686 src_uv += src_stride_uv;
687 }
688 }
689 return 0;
690 }
691
692 // Convert NV21 to ARGB.
693 LIBYUV_API
694 int NV21ToARGB(const uint8* src_y, int src_stride_y,
695 const uint8* src_uv, int src_stride_uv,
696 uint8* dst_argb, int dst_stride_argb,
697 int width, int height) {
698 if (!src_y || !src_uv || !dst_argb ||
699 width <= 0 || height == 0) {
700 return -1;
701 }
702 // Negative height means invert the image.
703 if (height < 0) {
704 height = -height;
705 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
706 dst_stride_argb = -dst_stride_argb;
707 }
708 void (*NV21ToARGBRow)(const uint8* y_buf,
709 const uint8* uv_buf,
710 uint8* rgb_buf,
711 int width) = NV21ToARGBRow_C;
712 #if defined(HAS_NV21TOARGBROW_SSSE3)
713 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
714 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
715 if (IS_ALIGNED(width, 8)) {
716 NV21ToARGBRow = NV21ToARGBRow_Unaligned_SSSE3;
717 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
718 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
719 }
720 }
721 }
722 #endif
723 #if defined(HAS_NV21TOARGBROW_NEON)
724 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
725 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
726 if (IS_ALIGNED(width, 8)) {
727 NV21ToARGBRow = NV21ToARGBRow_NEON;
728 }
729 }
730 #endif
731
732 for (int y = 0; y < height; ++y) {
733 NV21ToARGBRow(src_y, src_uv, dst_argb, width);
734 dst_argb += dst_stride_argb;
735 src_y += src_stride_y;
736 if (y & 1) {
737 src_uv += src_stride_uv;
738 }
739 }
740 return 0;
741 }
742
743 // Convert M420 to ARGB.
744 LIBYUV_API
745 int M420ToARGB(const uint8* src_m420, int src_stride_m420,
746 uint8* dst_argb, int dst_stride_argb,
747 int width, int height) {
748 if (!src_m420 || !dst_argb ||
749 width <= 0 || height == 0) {
750 return -1;
751 }
752 // Negative height means invert the image.
753 if (height < 0) {
754 height = -height;
755 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
756 dst_stride_argb = -dst_stride_argb;
757 }
758 void (*NV12ToARGBRow)(const uint8* y_buf,
759 const uint8* uv_buf,
760 uint8* rgb_buf,
761 int width) = NV12ToARGBRow_C;
762 #if defined(HAS_NV12TOARGBROW_SSSE3)
763 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
764 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
765 if (IS_ALIGNED(width, 8)) {
766 NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
767 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
768 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
769 }
770 }
771 }
772 #elif defined(HAS_NV12TOARGBROW_NEON)
773 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
774 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
775 if (IS_ALIGNED(width, 8)) {
776 NV12ToARGBRow = NV12ToARGBRow_NEON;
777 }
778 }
779 #endif
780
781 for (int y = 0; y < height - 1; y += 2) {
782 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
783 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
784 dst_argb + dst_stride_argb, width);
785 dst_argb += dst_stride_argb * 2;
786 src_m420 += src_stride_m420 * 3;
787 }
788 if (height & 1) {
789 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
790 }
791 return 0;
792 }
793
794 // Convert YUY2 to ARGB.
795 LIBYUV_API
796 int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
797 uint8* dst_argb, int dst_stride_argb,
798 int width, int height) {
799 if (!src_yuy2 || !dst_argb ||
800 width <= 0 || height == 0) {
801 return -1;
802 }
803 // Negative height means invert the image.
804 if (height < 0) {
805 height = -height;
806 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
807 src_stride_yuy2 = -src_stride_yuy2;
808 }
809 // Coalesce rows.
810 if (src_stride_yuy2 == width * 2 &&
811 dst_stride_argb == width * 4) {
812 width *= height;
813 height = 1;
814 src_stride_yuy2 = dst_stride_argb = 0;
815 }
816 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) =
817 YUY2ToARGBRow_C;
818 #if defined(HAS_YUY2TOARGBROW_SSSE3)
819 // Posix is 16, Windows is 8.
820 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
821 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
822 if (IS_ALIGNED(width, 16)) {
823 YUY2ToARGBRow = YUY2ToARGBRow_Unaligned_SSSE3;
824 if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16) &&
825 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
826 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
827 }
828 }
829 }
830 #elif defined(HAS_YUY2TOARGBROW_NEON)
831 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
832 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
833 if (IS_ALIGNED(width, 8)) {
834 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
835 }
836 }
837 #endif
838 for (int y = 0; y < height; ++y) {
839 YUY2ToARGBRow(src_yuy2, dst_argb, width);
840 src_yuy2 += src_stride_yuy2;
841 dst_argb += dst_stride_argb;
842 }
843 return 0;
844 }
845
846 // Convert UYVY to ARGB.
847 LIBYUV_API
848 int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
849 uint8* dst_argb, int dst_stride_argb,
850 int width, int height) {
851 if (!src_uyvy || !dst_argb ||
852 width <= 0 || height == 0) {
853 return -1;
854 }
855 // Negative height means invert the image.
856 if (height < 0) {
857 height = -height;
858 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
859 src_stride_uyvy = -src_stride_uyvy;
860 }
861 // Coalesce rows.
862 if (src_stride_uyvy == width * 2 &&
863 dst_stride_argb == width * 4) {
864 width *= height;
865 height = 1;
866 src_stride_uyvy = dst_stride_argb = 0;
867 }
868 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) =
869 UYVYToARGBRow_C;
870 #if defined(HAS_UYVYTOARGBROW_SSSE3)
871 // Posix is 16, Windows is 8.
872 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
873 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
874 if (IS_ALIGNED(width, 16)) {
875 UYVYToARGBRow = UYVYToARGBRow_Unaligned_SSSE3;
876 if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16) &&
877 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
878 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
879 }
880 }
881 }
882 #elif defined(HAS_UYVYTOARGBROW_NEON)
883 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
884 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
885 if (IS_ALIGNED(width, 8)) {
886 UYVYToARGBRow = UYVYToARGBRow_NEON;
887 }
888 }
889 #endif
890 for (int y = 0; y < height; ++y) {
891 UYVYToARGBRow(src_uyvy, dst_argb, width);
892 src_uyvy += src_stride_uyvy;
893 dst_argb += dst_stride_argb;
894 }
895 return 0;
896 }
897
898 #ifdef __cplusplus
899 } // extern "C"
900 } // namespace libyuv
901 #endif

mercurial