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