media/libyuv/source/convert_from.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial