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