Line data Source code
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.h"
12 :
13 : #include "libyuv/basic_types.h"
14 : #include "libyuv/convert.h" // For I420Copy
15 : #include "libyuv/cpu_id.h"
16 : #include "libyuv/planar_functions.h"
17 : #include "libyuv/rotate.h"
18 : #include "libyuv/scale.h" // For ScalePlane()
19 : #include "libyuv/video_common.h"
20 : #include "libyuv/row.h"
21 :
22 : #ifdef __cplusplus
23 : namespace libyuv {
24 : extern "C" {
25 : #endif
26 :
27 : #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
28 0 : static __inline int Abs(int v) {
29 0 : return v >= 0 ? v : -v;
30 : }
31 :
32 : // I420 To any I4xx YUV format with mirroring.
33 0 : static int I420ToI4xx(const uint8* src_y,
34 : int src_stride_y,
35 : const uint8* src_u,
36 : int src_stride_u,
37 : const uint8* src_v,
38 : int src_stride_v,
39 : uint8* dst_y,
40 : int dst_stride_y,
41 : uint8* dst_u,
42 : int dst_stride_u,
43 : uint8* dst_v,
44 : int dst_stride_v,
45 : int src_y_width,
46 : int src_y_height,
47 : int dst_uv_width,
48 : int dst_uv_height) {
49 0 : const int dst_y_width = Abs(src_y_width);
50 0 : const int dst_y_height = Abs(src_y_height);
51 0 : const int src_uv_width = SUBSAMPLE(src_y_width, 1, 1);
52 0 : const int src_uv_height = SUBSAMPLE(src_y_height, 1, 1);
53 0 : if (src_y_width == 0 || src_y_height == 0 || dst_uv_width <= 0 ||
54 : dst_uv_height <= 0) {
55 0 : return -1;
56 : }
57 0 : if (dst_y) {
58 : ScalePlane(src_y, src_stride_y, src_y_width, src_y_height, dst_y,
59 0 : dst_stride_y, dst_y_width, dst_y_height, kFilterBilinear);
60 : }
61 : ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height, dst_u,
62 0 : dst_stride_u, dst_uv_width, dst_uv_height, kFilterBilinear);
63 : ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height, dst_v,
64 0 : dst_stride_v, dst_uv_width, dst_uv_height, kFilterBilinear);
65 0 : return 0;
66 : }
67 :
68 : // 420 chroma is 1/2 width, 1/2 height
69 : // 422 chroma is 1/2 width, 1x height
70 : LIBYUV_API
71 0 : int I420ToI422(const uint8* src_y,
72 : int src_stride_y,
73 : const uint8* src_u,
74 : int src_stride_u,
75 : const uint8* src_v,
76 : int src_stride_v,
77 : uint8* dst_y,
78 : int dst_stride_y,
79 : uint8* dst_u,
80 : int dst_stride_u,
81 : uint8* dst_v,
82 : int dst_stride_v,
83 : int width,
84 : int height) {
85 0 : const int dst_uv_width = (Abs(width) + 1) >> 1;
86 0 : const int dst_uv_height = Abs(height);
87 : return I420ToI4xx(src_y, src_stride_y, src_u, src_stride_u, src_v,
88 : src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
89 : dst_v, dst_stride_v, width, height, dst_uv_width,
90 0 : dst_uv_height);
91 : }
92 :
93 : // 420 chroma is 1/2 width, 1/2 height
94 : // 444 chroma is 1x width, 1x height
95 : LIBYUV_API
96 0 : int I420ToI444(const uint8* src_y,
97 : int src_stride_y,
98 : const uint8* src_u,
99 : int src_stride_u,
100 : const uint8* src_v,
101 : int src_stride_v,
102 : uint8* dst_y,
103 : int dst_stride_y,
104 : uint8* dst_u,
105 : int dst_stride_u,
106 : uint8* dst_v,
107 : int dst_stride_v,
108 : int width,
109 : int height) {
110 0 : const int dst_uv_width = Abs(width);
111 0 : const int dst_uv_height = Abs(height);
112 : return I420ToI4xx(src_y, src_stride_y, src_u, src_stride_u, src_v,
113 : src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
114 : dst_v, dst_stride_v, width, height, dst_uv_width,
115 0 : dst_uv_height);
116 : }
117 :
118 : // Copy to I400. Source can be I420,422,444,400,NV12,NV21
119 : LIBYUV_API
120 0 : int I400Copy(const uint8* src_y,
121 : int src_stride_y,
122 : uint8* dst_y,
123 : int dst_stride_y,
124 : int width,
125 : int height) {
126 0 : if (!src_y || !dst_y || width <= 0 || height == 0) {
127 0 : return -1;
128 : }
129 : // Negative height means invert the image.
130 0 : if (height < 0) {
131 0 : height = -height;
132 0 : src_y = src_y + (height - 1) * src_stride_y;
133 0 : src_stride_y = -src_stride_y;
134 : }
135 0 : CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
136 0 : return 0;
137 : }
138 :
139 : LIBYUV_API
140 0 : int I422ToYUY2(const uint8* src_y,
141 : int src_stride_y,
142 : const uint8* src_u,
143 : int src_stride_u,
144 : const uint8* src_v,
145 : int src_stride_v,
146 : uint8* dst_yuy2,
147 : int dst_stride_yuy2,
148 : int width,
149 : int height) {
150 : int y;
151 : void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u,
152 : const uint8* src_v, uint8* dst_yuy2, int width) =
153 0 : I422ToYUY2Row_C;
154 0 : if (!src_y || !src_u || !src_v || !dst_yuy2 || width <= 0 || height == 0) {
155 0 : return -1;
156 : }
157 : // Negative height means invert the image.
158 0 : if (height < 0) {
159 0 : height = -height;
160 0 : dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
161 0 : dst_stride_yuy2 = -dst_stride_yuy2;
162 : }
163 : // Coalesce rows.
164 0 : if (src_stride_y == width && src_stride_u * 2 == width &&
165 0 : src_stride_v * 2 == width && dst_stride_yuy2 == width * 2) {
166 0 : width *= height;
167 0 : height = 1;
168 0 : src_stride_y = src_stride_u = src_stride_v = dst_stride_yuy2 = 0;
169 : }
170 : #if defined(HAS_I422TOYUY2ROW_SSE2)
171 0 : if (TestCpuFlag(kCpuHasSSE2)) {
172 0 : I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
173 0 : if (IS_ALIGNED(width, 16)) {
174 0 : I422ToYUY2Row = I422ToYUY2Row_SSE2;
175 : }
176 : }
177 : #endif
178 : #if defined(HAS_I422TOYUY2ROW_NEON)
179 : if (TestCpuFlag(kCpuHasNEON)) {
180 : I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
181 : if (IS_ALIGNED(width, 16)) {
182 : I422ToYUY2Row = I422ToYUY2Row_NEON;
183 : }
184 : }
185 : #endif
186 :
187 0 : for (y = 0; y < height; ++y) {
188 0 : I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width);
189 0 : src_y += src_stride_y;
190 0 : src_u += src_stride_u;
191 0 : src_v += src_stride_v;
192 0 : dst_yuy2 += dst_stride_yuy2;
193 : }
194 0 : return 0;
195 : }
196 :
197 : LIBYUV_API
198 0 : int I420ToYUY2(const uint8* src_y,
199 : int src_stride_y,
200 : const uint8* src_u,
201 : int src_stride_u,
202 : const uint8* src_v,
203 : int src_stride_v,
204 : uint8* dst_yuy2,
205 : int dst_stride_yuy2,
206 : int width,
207 : int height) {
208 : int y;
209 : void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u,
210 : const uint8* src_v, uint8* dst_yuy2, int width) =
211 0 : I422ToYUY2Row_C;
212 0 : if (!src_y || !src_u || !src_v || !dst_yuy2 || width <= 0 || height == 0) {
213 0 : return -1;
214 : }
215 : // Negative height means invert the image.
216 0 : if (height < 0) {
217 0 : height = -height;
218 0 : dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
219 0 : dst_stride_yuy2 = -dst_stride_yuy2;
220 : }
221 : #if defined(HAS_I422TOYUY2ROW_SSE2)
222 0 : if (TestCpuFlag(kCpuHasSSE2)) {
223 0 : I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
224 0 : if (IS_ALIGNED(width, 16)) {
225 0 : I422ToYUY2Row = I422ToYUY2Row_SSE2;
226 : }
227 : }
228 : #endif
229 : #if defined(HAS_I422TOYUY2ROW_NEON)
230 : if (TestCpuFlag(kCpuHasNEON)) {
231 : I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
232 : if (IS_ALIGNED(width, 16)) {
233 : I422ToYUY2Row = I422ToYUY2Row_NEON;
234 : }
235 : }
236 : #endif
237 : #if defined(HAS_I422TOYUY2ROW_MSA)
238 : if (TestCpuFlag(kCpuHasMSA)) {
239 : I422ToYUY2Row = I422ToYUY2Row_Any_MSA;
240 : if (IS_ALIGNED(width, 32)) {
241 : I422ToYUY2Row = I422ToYUY2Row_MSA;
242 : }
243 : }
244 : #endif
245 :
246 0 : for (y = 0; y < height - 1; y += 2) {
247 0 : I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width);
248 0 : I422ToYUY2Row(src_y + src_stride_y, src_u, src_v,
249 0 : dst_yuy2 + dst_stride_yuy2, width);
250 0 : src_y += src_stride_y * 2;
251 0 : src_u += src_stride_u;
252 0 : src_v += src_stride_v;
253 0 : dst_yuy2 += dst_stride_yuy2 * 2;
254 : }
255 0 : if (height & 1) {
256 0 : I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width);
257 : }
258 0 : return 0;
259 : }
260 :
261 : LIBYUV_API
262 0 : int I422ToUYVY(const uint8* src_y,
263 : int src_stride_y,
264 : const uint8* src_u,
265 : int src_stride_u,
266 : const uint8* src_v,
267 : int src_stride_v,
268 : uint8* dst_uyvy,
269 : int dst_stride_uyvy,
270 : int width,
271 : int height) {
272 : int y;
273 : void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u,
274 : const uint8* src_v, uint8* dst_uyvy, int width) =
275 0 : I422ToUYVYRow_C;
276 0 : if (!src_y || !src_u || !src_v || !dst_uyvy || width <= 0 || height == 0) {
277 0 : return -1;
278 : }
279 : // Negative height means invert the image.
280 0 : if (height < 0) {
281 0 : height = -height;
282 0 : dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
283 0 : dst_stride_uyvy = -dst_stride_uyvy;
284 : }
285 : // Coalesce rows.
286 0 : if (src_stride_y == width && src_stride_u * 2 == width &&
287 0 : src_stride_v * 2 == width && dst_stride_uyvy == width * 2) {
288 0 : width *= height;
289 0 : height = 1;
290 0 : src_stride_y = src_stride_u = src_stride_v = dst_stride_uyvy = 0;
291 : }
292 : #if defined(HAS_I422TOUYVYROW_SSE2)
293 0 : if (TestCpuFlag(kCpuHasSSE2)) {
294 0 : I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
295 0 : if (IS_ALIGNED(width, 16)) {
296 0 : I422ToUYVYRow = I422ToUYVYRow_SSE2;
297 : }
298 : }
299 : #endif
300 : #if defined(HAS_I422TOUYVYROW_NEON)
301 : if (TestCpuFlag(kCpuHasNEON)) {
302 : I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
303 : if (IS_ALIGNED(width, 16)) {
304 : I422ToUYVYRow = I422ToUYVYRow_NEON;
305 : }
306 : }
307 : #endif
308 : #if defined(HAS_I422TOUYVYROW_MSA)
309 : if (TestCpuFlag(kCpuHasMSA)) {
310 : I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
311 : if (IS_ALIGNED(width, 32)) {
312 : I422ToUYVYRow = I422ToUYVYRow_MSA;
313 : }
314 : }
315 : #endif
316 :
317 0 : for (y = 0; y < height; ++y) {
318 0 : I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width);
319 0 : src_y += src_stride_y;
320 0 : src_u += src_stride_u;
321 0 : src_v += src_stride_v;
322 0 : dst_uyvy += dst_stride_uyvy;
323 : }
324 0 : return 0;
325 : }
326 :
327 : LIBYUV_API
328 0 : int I420ToUYVY(const uint8* src_y,
329 : int src_stride_y,
330 : const uint8* src_u,
331 : int src_stride_u,
332 : const uint8* src_v,
333 : int src_stride_v,
334 : uint8* dst_uyvy,
335 : int dst_stride_uyvy,
336 : int width,
337 : int height) {
338 : int y;
339 : void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u,
340 : const uint8* src_v, uint8* dst_uyvy, int width) =
341 0 : I422ToUYVYRow_C;
342 0 : if (!src_y || !src_u || !src_v || !dst_uyvy || width <= 0 || height == 0) {
343 0 : return -1;
344 : }
345 : // Negative height means invert the image.
346 0 : if (height < 0) {
347 0 : height = -height;
348 0 : dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
349 0 : dst_stride_uyvy = -dst_stride_uyvy;
350 : }
351 : #if defined(HAS_I422TOUYVYROW_SSE2)
352 0 : if (TestCpuFlag(kCpuHasSSE2)) {
353 0 : I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
354 0 : if (IS_ALIGNED(width, 16)) {
355 0 : I422ToUYVYRow = I422ToUYVYRow_SSE2;
356 : }
357 : }
358 : #endif
359 : #if defined(HAS_I422TOUYVYROW_NEON)
360 : if (TestCpuFlag(kCpuHasNEON)) {
361 : I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
362 : if (IS_ALIGNED(width, 16)) {
363 : I422ToUYVYRow = I422ToUYVYRow_NEON;
364 : }
365 : }
366 : #endif
367 : #if defined(HAS_I422TOUYVYROW_MSA)
368 : if (TestCpuFlag(kCpuHasMSA)) {
369 : I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
370 : if (IS_ALIGNED(width, 32)) {
371 : I422ToUYVYRow = I422ToUYVYRow_MSA;
372 : }
373 : }
374 : #endif
375 :
376 0 : for (y = 0; y < height - 1; y += 2) {
377 0 : I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width);
378 0 : I422ToUYVYRow(src_y + src_stride_y, src_u, src_v,
379 0 : dst_uyvy + dst_stride_uyvy, width);
380 0 : src_y += src_stride_y * 2;
381 0 : src_u += src_stride_u;
382 0 : src_v += src_stride_v;
383 0 : dst_uyvy += dst_stride_uyvy * 2;
384 : }
385 0 : if (height & 1) {
386 0 : I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width);
387 : }
388 0 : return 0;
389 : }
390 :
391 : // TODO(fbarchard): test negative height for invert.
392 : LIBYUV_API
393 0 : int I420ToNV12(const uint8* src_y,
394 : int src_stride_y,
395 : const uint8* src_u,
396 : int src_stride_u,
397 : const uint8* src_v,
398 : int src_stride_v,
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 0 : if (!src_y || !src_u || !src_v || !dst_y || !dst_uv || width <= 0 ||
406 : height == 0) {
407 0 : return -1;
408 : }
409 0 : int halfwidth = (width + 1) / 2;
410 0 : int halfheight = height > 0 ? (height + 1) / 2 : (height - 1) / 2;
411 0 : if (dst_y) {
412 0 : CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
413 : }
414 : MergeUVPlane(src_u, src_stride_u, src_v, src_stride_v, dst_uv, dst_stride_uv,
415 0 : halfwidth, halfheight);
416 0 : return 0;
417 : }
418 :
419 : LIBYUV_API
420 0 : int I420ToNV21(const uint8* src_y,
421 : int src_stride_y,
422 : const uint8* src_u,
423 : int src_stride_u,
424 : const uint8* src_v,
425 : int src_stride_v,
426 : uint8* dst_y,
427 : int dst_stride_y,
428 : uint8* dst_vu,
429 : int dst_stride_vu,
430 : int width,
431 : int height) {
432 : return I420ToNV12(src_y, src_stride_y, src_v, src_stride_v, src_u,
433 : src_stride_u, dst_y, dst_stride_y, dst_vu, dst_stride_vu,
434 0 : width, height);
435 : }
436 :
437 : // Convert I422 to RGBA with matrix
438 0 : static int I420ToRGBAMatrix(const uint8* src_y,
439 : int src_stride_y,
440 : const uint8* src_u,
441 : int src_stride_u,
442 : const uint8* src_v,
443 : int src_stride_v,
444 : uint8* dst_rgba,
445 : int dst_stride_rgba,
446 : const struct YuvConstants* yuvconstants,
447 : int width,
448 : int height) {
449 : int y;
450 : void (*I422ToRGBARow)(const uint8* y_buf, const uint8* u_buf,
451 : const uint8* v_buf, uint8* rgb_buf,
452 : const struct YuvConstants* yuvconstants, int width) =
453 0 : I422ToRGBARow_C;
454 0 : if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
455 0 : return -1;
456 : }
457 : // Negative height means invert the image.
458 0 : if (height < 0) {
459 0 : height = -height;
460 0 : dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
461 0 : dst_stride_rgba = -dst_stride_rgba;
462 : }
463 : #if defined(HAS_I422TORGBAROW_SSSE3)
464 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
465 0 : I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
466 0 : if (IS_ALIGNED(width, 8)) {
467 0 : I422ToRGBARow = I422ToRGBARow_SSSE3;
468 : }
469 : }
470 : #endif
471 : #if defined(HAS_I422TORGBAROW_AVX2)
472 0 : if (TestCpuFlag(kCpuHasAVX2)) {
473 0 : I422ToRGBARow = I422ToRGBARow_Any_AVX2;
474 0 : if (IS_ALIGNED(width, 16)) {
475 0 : I422ToRGBARow = I422ToRGBARow_AVX2;
476 : }
477 : }
478 : #endif
479 : #if defined(HAS_I422TORGBAROW_NEON)
480 : if (TestCpuFlag(kCpuHasNEON)) {
481 : I422ToRGBARow = I422ToRGBARow_Any_NEON;
482 : if (IS_ALIGNED(width, 8)) {
483 : I422ToRGBARow = I422ToRGBARow_NEON;
484 : }
485 : }
486 : #endif
487 : #if defined(HAS_I422TORGBAROW_DSPR2)
488 : if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
489 : IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
490 : IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
491 : IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
492 : IS_ALIGNED(dst_rgba, 4) && IS_ALIGNED(dst_stride_rgba, 4)) {
493 : I422ToRGBARow = I422ToRGBARow_DSPR2;
494 : }
495 : #endif
496 : #if defined(HAS_I422TORGBAROW_MSA)
497 : if (TestCpuFlag(kCpuHasMSA)) {
498 : I422ToRGBARow = I422ToRGBARow_Any_MSA;
499 : if (IS_ALIGNED(width, 8)) {
500 : I422ToRGBARow = I422ToRGBARow_MSA;
501 : }
502 : }
503 : #endif
504 :
505 0 : for (y = 0; y < height; ++y) {
506 0 : I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
507 0 : dst_rgba += dst_stride_rgba;
508 0 : src_y += src_stride_y;
509 0 : if (y & 1) {
510 0 : src_u += src_stride_u;
511 0 : src_v += src_stride_v;
512 : }
513 : }
514 0 : return 0;
515 : }
516 :
517 : // Convert I420 to RGBA.
518 : LIBYUV_API
519 0 : int I420ToRGBA(const uint8* src_y,
520 : int src_stride_y,
521 : const uint8* src_u,
522 : int src_stride_u,
523 : const uint8* src_v,
524 : int src_stride_v,
525 : uint8* dst_rgba,
526 : int dst_stride_rgba,
527 : int width,
528 : int height) {
529 : return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
530 : src_stride_v, dst_rgba, dst_stride_rgba,
531 0 : &kYuvI601Constants, width, height);
532 : }
533 :
534 : // Convert I420 to BGRA.
535 : LIBYUV_API
536 0 : int I420ToBGRA(const uint8* src_y,
537 : int src_stride_y,
538 : const uint8* src_u,
539 : int src_stride_u,
540 : const uint8* src_v,
541 : int src_stride_v,
542 : uint8* dst_bgra,
543 : int dst_stride_bgra,
544 : int width,
545 : int height) {
546 : return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
547 : src_stride_v, // Swap U and V
548 : src_u, src_stride_u, dst_bgra, dst_stride_bgra,
549 : &kYvuI601Constants, // Use Yvu matrix
550 0 : width, height);
551 : }
552 :
553 : // Convert I420 to RGB24 with matrix
554 0 : static int I420ToRGB24Matrix(const uint8* src_y,
555 : int src_stride_y,
556 : const uint8* src_u,
557 : int src_stride_u,
558 : const uint8* src_v,
559 : int src_stride_v,
560 : uint8* dst_rgb24,
561 : int dst_stride_rgb24,
562 : const struct YuvConstants* yuvconstants,
563 : int width,
564 : int height) {
565 : int y;
566 : void (*I422ToRGB24Row)(const uint8* y_buf, const uint8* u_buf,
567 : const uint8* v_buf, uint8* rgb_buf,
568 : const struct YuvConstants* yuvconstants, int width) =
569 0 : I422ToRGB24Row_C;
570 0 : if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
571 0 : return -1;
572 : }
573 : // Negative height means invert the image.
574 0 : if (height < 0) {
575 0 : height = -height;
576 0 : dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
577 0 : dst_stride_rgb24 = -dst_stride_rgb24;
578 : }
579 : #if defined(HAS_I422TORGB24ROW_SSSE3)
580 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
581 0 : I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
582 0 : if (IS_ALIGNED(width, 8)) {
583 0 : I422ToRGB24Row = I422ToRGB24Row_SSSE3;
584 : }
585 : }
586 : #endif
587 : #if defined(HAS_I422TORGB24ROW_AVX2)
588 0 : if (TestCpuFlag(kCpuHasAVX2)) {
589 0 : I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
590 0 : if (IS_ALIGNED(width, 16)) {
591 0 : I422ToRGB24Row = I422ToRGB24Row_AVX2;
592 : }
593 : }
594 : #endif
595 : #if defined(HAS_I422TORGB24ROW_NEON)
596 : if (TestCpuFlag(kCpuHasNEON)) {
597 : I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
598 : if (IS_ALIGNED(width, 8)) {
599 : I422ToRGB24Row = I422ToRGB24Row_NEON;
600 : }
601 : }
602 : #endif
603 : #if defined(HAS_I422TORGB24ROW_MSA)
604 : if (TestCpuFlag(kCpuHasMSA)) {
605 : I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
606 : if (IS_ALIGNED(width, 16)) {
607 : I422ToRGB24Row = I422ToRGB24Row_MSA;
608 : }
609 : }
610 : #endif
611 :
612 0 : for (y = 0; y < height; ++y) {
613 0 : I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
614 0 : dst_rgb24 += dst_stride_rgb24;
615 0 : src_y += src_stride_y;
616 0 : if (y & 1) {
617 0 : src_u += src_stride_u;
618 0 : src_v += src_stride_v;
619 : }
620 : }
621 0 : return 0;
622 : }
623 :
624 : // Convert I420 to RGB24.
625 : LIBYUV_API
626 0 : int I420ToRGB24(const uint8* src_y,
627 : int src_stride_y,
628 : const uint8* src_u,
629 : int src_stride_u,
630 : const uint8* src_v,
631 : int src_stride_v,
632 : uint8* dst_rgb24,
633 : int dst_stride_rgb24,
634 : int width,
635 : int height) {
636 : return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
637 : src_stride_v, dst_rgb24, dst_stride_rgb24,
638 0 : &kYuvI601Constants, width, height);
639 : }
640 :
641 : // Convert I420 to RAW.
642 : LIBYUV_API
643 0 : int I420ToRAW(const uint8* src_y,
644 : int src_stride_y,
645 : const uint8* src_u,
646 : int src_stride_u,
647 : const uint8* src_v,
648 : int src_stride_v,
649 : uint8* dst_raw,
650 : int dst_stride_raw,
651 : int width,
652 : int height) {
653 : return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
654 : src_stride_v, // Swap U and V
655 : src_u, src_stride_u, dst_raw, dst_stride_raw,
656 : &kYvuI601Constants, // Use Yvu matrix
657 0 : width, height);
658 : }
659 :
660 : // Convert I420 to ARGB1555.
661 : LIBYUV_API
662 0 : int I420ToARGB1555(const uint8* src_y,
663 : int src_stride_y,
664 : const uint8* src_u,
665 : int src_stride_u,
666 : const uint8* src_v,
667 : int src_stride_v,
668 : uint8* dst_argb1555,
669 : int dst_stride_argb1555,
670 : int width,
671 : int height) {
672 : int y;
673 : void (*I422ToARGB1555Row)(const uint8* y_buf, const uint8* u_buf,
674 : const uint8* v_buf, uint8* rgb_buf,
675 : const struct YuvConstants* yuvconstants,
676 0 : int width) = I422ToARGB1555Row_C;
677 0 : if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
678 : height == 0) {
679 0 : return -1;
680 : }
681 : // Negative height means invert the image.
682 0 : if (height < 0) {
683 0 : height = -height;
684 0 : dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
685 0 : dst_stride_argb1555 = -dst_stride_argb1555;
686 : }
687 : #if defined(HAS_I422TOARGB1555ROW_SSSE3)
688 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
689 0 : I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
690 0 : if (IS_ALIGNED(width, 8)) {
691 0 : I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
692 : }
693 : }
694 : #endif
695 : #if defined(HAS_I422TOARGB1555ROW_AVX2)
696 0 : if (TestCpuFlag(kCpuHasAVX2)) {
697 0 : I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
698 0 : if (IS_ALIGNED(width, 16)) {
699 0 : I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
700 : }
701 : }
702 : #endif
703 : #if defined(HAS_I422TOARGB1555ROW_NEON)
704 : if (TestCpuFlag(kCpuHasNEON)) {
705 : I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
706 : if (IS_ALIGNED(width, 8)) {
707 : I422ToARGB1555Row = I422ToARGB1555Row_NEON;
708 : }
709 : }
710 : #endif
711 : #if defined(HAS_I422TOARGB1555ROW_DSPR2)
712 : if (TestCpuFlag(kCpuHasDSPR2)) {
713 : I422ToARGB1555Row = I422ToARGB1555Row_Any_DSPR2;
714 : if (IS_ALIGNED(width, 4)) {
715 : I422ToARGB1555Row = I422ToARGB1555Row_DSPR2;
716 : }
717 : }
718 : #endif
719 : #if defined(HAS_I422TOARGB1555ROW_MSA)
720 : if (TestCpuFlag(kCpuHasMSA)) {
721 : I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
722 : if (IS_ALIGNED(width, 8)) {
723 : I422ToARGB1555Row = I422ToARGB1555Row_MSA;
724 : }
725 : }
726 : #endif
727 :
728 0 : for (y = 0; y < height; ++y) {
729 : I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
730 0 : width);
731 0 : dst_argb1555 += dst_stride_argb1555;
732 0 : src_y += src_stride_y;
733 0 : if (y & 1) {
734 0 : src_u += src_stride_u;
735 0 : src_v += src_stride_v;
736 : }
737 : }
738 0 : return 0;
739 : }
740 :
741 : // Convert I420 to ARGB4444.
742 : LIBYUV_API
743 0 : int I420ToARGB4444(const uint8* src_y,
744 : int src_stride_y,
745 : const uint8* src_u,
746 : int src_stride_u,
747 : const uint8* src_v,
748 : int src_stride_v,
749 : uint8* dst_argb4444,
750 : int dst_stride_argb4444,
751 : int width,
752 : int height) {
753 : int y;
754 : void (*I422ToARGB4444Row)(const uint8* y_buf, const uint8* u_buf,
755 : const uint8* v_buf, uint8* rgb_buf,
756 : const struct YuvConstants* yuvconstants,
757 0 : int width) = I422ToARGB4444Row_C;
758 0 : if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
759 : height == 0) {
760 0 : return -1;
761 : }
762 : // Negative height means invert the image.
763 0 : if (height < 0) {
764 0 : height = -height;
765 0 : dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
766 0 : dst_stride_argb4444 = -dst_stride_argb4444;
767 : }
768 : #if defined(HAS_I422TOARGB4444ROW_SSSE3)
769 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
770 0 : I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
771 0 : if (IS_ALIGNED(width, 8)) {
772 0 : I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
773 : }
774 : }
775 : #endif
776 : #if defined(HAS_I422TOARGB4444ROW_AVX2)
777 0 : if (TestCpuFlag(kCpuHasAVX2)) {
778 0 : I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
779 0 : if (IS_ALIGNED(width, 16)) {
780 0 : I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
781 : }
782 : }
783 : #endif
784 : #if defined(HAS_I422TOARGB4444ROW_NEON)
785 : if (TestCpuFlag(kCpuHasNEON)) {
786 : I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
787 : if (IS_ALIGNED(width, 8)) {
788 : I422ToARGB4444Row = I422ToARGB4444Row_NEON;
789 : }
790 : }
791 : #endif
792 : #if defined(HAS_I422TOARGB4444ROW_DSPR2)
793 : if (TestCpuFlag(kCpuHasDSPR2)) {
794 : I422ToARGB4444Row = I422ToARGB4444Row_Any_DSPR2;
795 : if (IS_ALIGNED(width, 4)) {
796 : I422ToARGB4444Row = I422ToARGB4444Row_DSPR2;
797 : }
798 : }
799 : #endif
800 : #if defined(HAS_I422TOARGB4444ROW_MSA)
801 : if (TestCpuFlag(kCpuHasMSA)) {
802 : I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
803 : if (IS_ALIGNED(width, 8)) {
804 : I422ToARGB4444Row = I422ToARGB4444Row_MSA;
805 : }
806 : }
807 : #endif
808 :
809 0 : for (y = 0; y < height; ++y) {
810 : I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
811 0 : width);
812 0 : dst_argb4444 += dst_stride_argb4444;
813 0 : src_y += src_stride_y;
814 0 : if (y & 1) {
815 0 : src_u += src_stride_u;
816 0 : src_v += src_stride_v;
817 : }
818 : }
819 0 : return 0;
820 : }
821 :
822 : // Convert I420 to RGB565.
823 : LIBYUV_API
824 0 : int I420ToRGB565(const uint8* src_y,
825 : int src_stride_y,
826 : const uint8* src_u,
827 : int src_stride_u,
828 : const uint8* src_v,
829 : int src_stride_v,
830 : uint8* dst_rgb565,
831 : int dst_stride_rgb565,
832 : int width,
833 : int height) {
834 : int y;
835 : void (*I422ToRGB565Row)(const uint8* y_buf, const uint8* u_buf,
836 : const uint8* v_buf, uint8* rgb_buf,
837 : const struct YuvConstants* yuvconstants, int width) =
838 0 : I422ToRGB565Row_C;
839 0 : if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
840 0 : return -1;
841 : }
842 : // Negative height means invert the image.
843 0 : if (height < 0) {
844 0 : height = -height;
845 0 : dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
846 0 : dst_stride_rgb565 = -dst_stride_rgb565;
847 : }
848 : #if defined(HAS_I422TORGB565ROW_SSSE3)
849 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
850 0 : I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
851 0 : if (IS_ALIGNED(width, 8)) {
852 0 : I422ToRGB565Row = I422ToRGB565Row_SSSE3;
853 : }
854 : }
855 : #endif
856 : #if defined(HAS_I422TORGB565ROW_AVX2)
857 0 : if (TestCpuFlag(kCpuHasAVX2)) {
858 0 : I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
859 0 : if (IS_ALIGNED(width, 16)) {
860 0 : I422ToRGB565Row = I422ToRGB565Row_AVX2;
861 : }
862 : }
863 : #endif
864 : #if defined(HAS_I422TORGB565ROW_NEON)
865 : if (TestCpuFlag(kCpuHasNEON)) {
866 : I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
867 : if (IS_ALIGNED(width, 8)) {
868 : I422ToRGB565Row = I422ToRGB565Row_NEON;
869 : }
870 : }
871 : #endif
872 : #if defined(HAS_I422TORGB565ROW_MSA)
873 : if (TestCpuFlag(kCpuHasMSA)) {
874 : I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
875 : if (IS_ALIGNED(width, 8)) {
876 : I422ToRGB565Row = I422ToRGB565Row_MSA;
877 : }
878 : }
879 : #endif
880 :
881 0 : for (y = 0; y < height; ++y) {
882 0 : I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, &kYuvI601Constants, width);
883 0 : dst_rgb565 += dst_stride_rgb565;
884 0 : src_y += src_stride_y;
885 0 : if (y & 1) {
886 0 : src_u += src_stride_u;
887 0 : src_v += src_stride_v;
888 : }
889 : }
890 0 : return 0;
891 : }
892 :
893 : // Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
894 : static const uint8 kDither565_4x4[16] = {
895 : 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
896 : };
897 :
898 : // Convert I420 to RGB565 with dithering.
899 : LIBYUV_API
900 0 : int I420ToRGB565Dither(const uint8* src_y,
901 : int src_stride_y,
902 : const uint8* src_u,
903 : int src_stride_u,
904 : const uint8* src_v,
905 : int src_stride_v,
906 : uint8* dst_rgb565,
907 : int dst_stride_rgb565,
908 : const uint8* dither4x4,
909 : int width,
910 : int height) {
911 : int y;
912 : void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf,
913 : const uint8* v_buf, uint8* rgb_buf,
914 : const struct YuvConstants* yuvconstants, int width) =
915 0 : I422ToARGBRow_C;
916 : void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb,
917 : const uint32 dither4, int width) =
918 0 : ARGBToRGB565DitherRow_C;
919 0 : if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
920 0 : return -1;
921 : }
922 : // Negative height means invert the image.
923 0 : if (height < 0) {
924 0 : height = -height;
925 0 : dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
926 0 : dst_stride_rgb565 = -dst_stride_rgb565;
927 : }
928 0 : if (!dither4x4) {
929 0 : dither4x4 = kDither565_4x4;
930 : }
931 : #if defined(HAS_I422TOARGBROW_SSSE3)
932 0 : if (TestCpuFlag(kCpuHasSSSE3)) {
933 0 : I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
934 0 : if (IS_ALIGNED(width, 8)) {
935 0 : I422ToARGBRow = I422ToARGBRow_SSSE3;
936 : }
937 : }
938 : #endif
939 : #if defined(HAS_I422TOARGBROW_AVX2)
940 0 : if (TestCpuFlag(kCpuHasAVX2)) {
941 0 : I422ToARGBRow = I422ToARGBRow_Any_AVX2;
942 0 : if (IS_ALIGNED(width, 16)) {
943 0 : I422ToARGBRow = I422ToARGBRow_AVX2;
944 : }
945 : }
946 : #endif
947 : #if defined(HAS_I422TOARGBROW_NEON)
948 : if (TestCpuFlag(kCpuHasNEON)) {
949 : I422ToARGBRow = I422ToARGBRow_Any_NEON;
950 : if (IS_ALIGNED(width, 8)) {
951 : I422ToARGBRow = I422ToARGBRow_NEON;
952 : }
953 : }
954 : #endif
955 : #if defined(HAS_I422TOARGBROW_DSPR2)
956 : if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
957 : IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
958 : IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
959 : IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2)) {
960 : I422ToARGBRow = I422ToARGBRow_DSPR2;
961 : }
962 : #endif
963 : #if defined(HAS_I422TOARGBROW_MSA)
964 : if (TestCpuFlag(kCpuHasMSA)) {
965 : I422ToARGBRow = I422ToARGBRow_Any_MSA;
966 : if (IS_ALIGNED(width, 8)) {
967 : I422ToARGBRow = I422ToARGBRow_MSA;
968 : }
969 : }
970 : #endif
971 : #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
972 0 : if (TestCpuFlag(kCpuHasSSE2)) {
973 0 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
974 0 : if (IS_ALIGNED(width, 4)) {
975 0 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
976 : }
977 : }
978 : #endif
979 : #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
980 0 : if (TestCpuFlag(kCpuHasAVX2)) {
981 0 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
982 0 : if (IS_ALIGNED(width, 8)) {
983 0 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
984 : }
985 : }
986 : #endif
987 : #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
988 : if (TestCpuFlag(kCpuHasNEON)) {
989 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
990 : if (IS_ALIGNED(width, 8)) {
991 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
992 : }
993 : }
994 : #endif
995 : #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
996 : if (TestCpuFlag(kCpuHasMSA)) {
997 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
998 : if (IS_ALIGNED(width, 8)) {
999 : ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
1000 : }
1001 : }
1002 : #endif
1003 : {
1004 : // Allocate a row of argb.
1005 0 : align_buffer_64(row_argb, width * 4);
1006 0 : for (y = 0; y < height; ++y) {
1007 0 : I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
1008 0 : ARGBToRGB565DitherRow(row_argb, dst_rgb565,
1009 0 : *(uint32*)(dither4x4 + ((y & 3) << 2)),
1010 0 : width); // NOLINT
1011 0 : dst_rgb565 += dst_stride_rgb565;
1012 0 : src_y += src_stride_y;
1013 0 : if (y & 1) {
1014 0 : src_u += src_stride_u;
1015 0 : src_v += src_stride_v;
1016 : }
1017 : }
1018 0 : free_aligned_buffer_64(row_argb);
1019 : }
1020 0 : return 0;
1021 : }
1022 :
1023 : // Convert I420 to specified format
1024 : LIBYUV_API
1025 0 : int ConvertFromI420(const uint8* y,
1026 : int y_stride,
1027 : const uint8* u,
1028 : int u_stride,
1029 : const uint8* v,
1030 : int v_stride,
1031 : uint8* dst_sample,
1032 : int dst_sample_stride,
1033 : int width,
1034 : int height,
1035 : uint32 fourcc) {
1036 0 : uint32 format = CanonicalFourCC(fourcc);
1037 0 : int r = 0;
1038 0 : if (!y || !u || !v || !dst_sample || width <= 0 || height == 0) {
1039 0 : return -1;
1040 : }
1041 0 : switch (format) {
1042 : // Single plane formats
1043 : case FOURCC_YUY2:
1044 0 : r = I420ToYUY2(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1045 : dst_sample_stride ? dst_sample_stride : width * 2, width,
1046 0 : height);
1047 0 : break;
1048 : case FOURCC_UYVY:
1049 0 : r = I420ToUYVY(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1050 : dst_sample_stride ? dst_sample_stride : width * 2, width,
1051 0 : height);
1052 0 : break;
1053 : case FOURCC_RGBP:
1054 0 : r = I420ToRGB565(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1055 : dst_sample_stride ? dst_sample_stride : width * 2, width,
1056 0 : height);
1057 0 : break;
1058 : case FOURCC_RGBO:
1059 0 : r = I420ToARGB1555(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1060 : dst_sample_stride ? dst_sample_stride : width * 2,
1061 0 : width, height);
1062 0 : break;
1063 : case FOURCC_R444:
1064 0 : r = I420ToARGB4444(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1065 : dst_sample_stride ? dst_sample_stride : width * 2,
1066 0 : width, height);
1067 0 : break;
1068 : case FOURCC_24BG:
1069 0 : r = I420ToRGB24(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1070 : dst_sample_stride ? dst_sample_stride : width * 3, width,
1071 0 : height);
1072 0 : break;
1073 : case FOURCC_RAW:
1074 0 : r = I420ToRAW(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1075 : dst_sample_stride ? dst_sample_stride : width * 3, width,
1076 0 : height);
1077 0 : break;
1078 : case FOURCC_ARGB:
1079 0 : r = I420ToARGB(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1080 : dst_sample_stride ? dst_sample_stride : width * 4, width,
1081 0 : height);
1082 0 : break;
1083 : case FOURCC_BGRA:
1084 0 : r = I420ToBGRA(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1085 : dst_sample_stride ? dst_sample_stride : width * 4, width,
1086 0 : height);
1087 0 : break;
1088 : case FOURCC_ABGR:
1089 0 : r = I420ToABGR(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1090 : dst_sample_stride ? dst_sample_stride : width * 4, width,
1091 0 : height);
1092 0 : break;
1093 : case FOURCC_RGBA:
1094 0 : r = I420ToRGBA(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1095 : dst_sample_stride ? dst_sample_stride : width * 4, width,
1096 0 : height);
1097 0 : break;
1098 : case FOURCC_I400:
1099 0 : r = I400Copy(y, y_stride, dst_sample,
1100 : dst_sample_stride ? dst_sample_stride : width, width,
1101 0 : height);
1102 0 : break;
1103 : case FOURCC_NV12: {
1104 0 : uint8* dst_uv = dst_sample + width * height;
1105 0 : r = I420ToNV12(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1106 : dst_sample_stride ? dst_sample_stride : width, dst_uv,
1107 : dst_sample_stride ? dst_sample_stride : width, width,
1108 0 : height);
1109 0 : break;
1110 : }
1111 : case FOURCC_NV21: {
1112 0 : uint8* dst_vu = dst_sample + width * height;
1113 0 : r = I420ToNV21(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1114 : dst_sample_stride ? dst_sample_stride : width, dst_vu,
1115 : dst_sample_stride ? dst_sample_stride : width, width,
1116 0 : height);
1117 0 : break;
1118 : }
1119 : // TODO(fbarchard): Add M420.
1120 : // Triplanar formats
1121 : case FOURCC_I420:
1122 : case FOURCC_YV12: {
1123 0 : dst_sample_stride = dst_sample_stride ? dst_sample_stride : width;
1124 0 : int halfstride = (dst_sample_stride + 1) / 2;
1125 0 : int halfheight = (height + 1) / 2;
1126 : uint8* dst_u;
1127 : uint8* dst_v;
1128 0 : if (format == FOURCC_YV12) {
1129 0 : dst_v = dst_sample + dst_sample_stride * height;
1130 0 : dst_u = dst_v + halfstride * halfheight;
1131 : } else {
1132 0 : dst_u = dst_sample + dst_sample_stride * height;
1133 0 : dst_v = dst_u + halfstride * halfheight;
1134 : }
1135 : r = I420Copy(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1136 : dst_sample_stride, dst_u, halfstride, dst_v, halfstride,
1137 0 : width, height);
1138 0 : break;
1139 : }
1140 : case FOURCC_I422:
1141 : case FOURCC_YV16: {
1142 0 : dst_sample_stride = dst_sample_stride ? dst_sample_stride : width;
1143 0 : int halfstride = (dst_sample_stride + 1) / 2;
1144 : uint8* dst_u;
1145 : uint8* dst_v;
1146 0 : if (format == FOURCC_YV16) {
1147 0 : dst_v = dst_sample + dst_sample_stride * height;
1148 0 : dst_u = dst_v + halfstride * height;
1149 : } else {
1150 0 : dst_u = dst_sample + dst_sample_stride * height;
1151 0 : dst_v = dst_u + halfstride * height;
1152 : }
1153 : r = I420ToI422(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1154 : dst_sample_stride, dst_u, halfstride, dst_v, halfstride,
1155 0 : width, height);
1156 0 : break;
1157 : }
1158 : case FOURCC_I444:
1159 : case FOURCC_YV24: {
1160 0 : dst_sample_stride = dst_sample_stride ? dst_sample_stride : width;
1161 : uint8* dst_u;
1162 : uint8* dst_v;
1163 0 : if (format == FOURCC_YV24) {
1164 0 : dst_v = dst_sample + dst_sample_stride * height;
1165 0 : dst_u = dst_v + dst_sample_stride * height;
1166 : } else {
1167 0 : dst_u = dst_sample + dst_sample_stride * height;
1168 0 : dst_v = dst_u + dst_sample_stride * height;
1169 : }
1170 : r = I420ToI444(y, y_stride, u, u_stride, v, v_stride, dst_sample,
1171 : dst_sample_stride, dst_u, dst_sample_stride, dst_v,
1172 0 : dst_sample_stride, width, height);
1173 0 : break;
1174 : }
1175 : // Formats not supported - MJPG, biplanar, some rgb formats.
1176 : default:
1177 0 : return -1; // unknown fourcc - return failure code.
1178 : }
1179 0 : return r;
1180 : }
1181 :
1182 : #ifdef __cplusplus
1183 : } // extern "C"
1184 : } // namespace libyuv
1185 : #endif
|