media/libyuv/source/convert_from_argb.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_argb.h"
    13 #include "libyuv/basic_types.h"
    14 #include "libyuv/cpu_id.h"
    15 #include "libyuv/format_conversion.h"
    16 #include "libyuv/planar_functions.h"
    17 #include "libyuv/row.h"
    19 #ifdef __cplusplus
    20 namespace libyuv {
    21 extern "C" {
    22 #endif
    24 // ARGB little endian (bgra in memory) to I444
    25 LIBYUV_API
    26 int ARGBToI444(const uint8* src_argb, int src_stride_argb,
    27                uint8* dst_y, int dst_stride_y,
    28                uint8* dst_u, int dst_stride_u,
    29                uint8* dst_v, int dst_stride_v,
    30                int width, int height) {
    31   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
    32     return -1;
    33   }
    34   if (height < 0) {
    35     height = -height;
    36     src_argb = src_argb + (height - 1) * src_stride_argb;
    37     src_stride_argb = -src_stride_argb;
    38   }
    39   // Coalesce rows.
    40   if (src_stride_argb == width * 4 &&
    41       dst_stride_y == width &&
    42       dst_stride_u == width &&
    43       dst_stride_v == width) {
    44     width *= height;
    45     height = 1;
    46     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
    47   }
    48   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
    49       ARGBToYRow_C;
    50   void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
    51                          int pix) = ARGBToUV444Row_C;
    52 #if defined(HAS_ARGBTOUV444ROW_SSSE3)
    53     if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
    54       ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
    55       if (IS_ALIGNED(width, 16)) {
    56         ARGBToUV444Row = ARGBToUV444Row_Unaligned_SSSE3;
    57         if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
    58           ARGBToUV444Row = ARGBToUV444Row_SSSE3;
    59         }
    60       }
    61   }
    62 #endif
    63 #if defined(HAS_ARGBTOYROW_SSSE3)
    64   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
    65     ARGBToYRow = ARGBToYRow_Any_SSSE3;
    66     if (IS_ALIGNED(width, 16)) {
    67       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
    68       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
    69           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
    70         ARGBToYRow = ARGBToYRow_SSSE3;
    71       }
    72     }
    73   }
    75 #elif defined(HAS_ARGBTOYROW_NEON)
    76   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
    77     ARGBToYRow = ARGBToYRow_Any_NEON;
    78     ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
    79     if (IS_ALIGNED(width, 8)) {
    80       ARGBToYRow = ARGBToYRow_NEON;
    81       ARGBToUV444Row = ARGBToUV444Row_NEON;
    82     }
    83   }
    84 #endif
    86   for (int y = 0; y < height; ++y) {
    87     ARGBToUV444Row(src_argb, dst_u, dst_v, width);
    88     ARGBToYRow(src_argb, dst_y, width);
    89     src_argb += src_stride_argb;
    90     dst_y += dst_stride_y;
    91     dst_u += dst_stride_u;
    92     dst_v += dst_stride_v;
    93   }
    94   return 0;
    95 }
    97 // ARGB little endian (bgra in memory) to I422
    98 LIBYUV_API
    99 int ARGBToI422(const uint8* src_argb, int src_stride_argb,
   100                uint8* dst_y, int dst_stride_y,
   101                uint8* dst_u, int dst_stride_u,
   102                uint8* dst_v, int dst_stride_v,
   103                int width, int height) {
   104   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
   105     return -1;
   106   }
   107   if (height < 0) {
   108     height = -height;
   109     src_argb = src_argb + (height - 1) * src_stride_argb;
   110     src_stride_argb = -src_stride_argb;
   111   }
   112   // Coalesce rows.
   113   if (src_stride_argb == width * 4 &&
   114       dst_stride_y == width &&
   115       dst_stride_u * 2 == width &&
   116       dst_stride_v * 2 == width) {
   117     width *= height;
   118     height = 1;
   119     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
   120   }
   121   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
   122                          int pix) = ARGBToUV422Row_C;
   123 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
   124   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   125     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
   126     if (IS_ALIGNED(width, 16)) {
   127       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
   128       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   129         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
   130       }
   131     }
   132   }
   133 #endif
   135   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   136       ARGBToYRow_C;
   137 #if defined(HAS_ARGBTOYROW_SSSE3)
   138   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   139     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   140     if (IS_ALIGNED(width, 16)) {
   141       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   142       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
   143           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
   144         ARGBToYRow = ARGBToYRow_SSSE3;
   145       }
   146     }
   147   }
   148 #elif defined(HAS_ARGBTOYROW_NEON)
   149   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   150     ARGBToYRow = ARGBToYRow_Any_NEON;
   151     if (IS_ALIGNED(width, 8)) {
   152       ARGBToYRow = ARGBToYRow_NEON;
   153     }
   154     if (width >= 16) {
   155       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
   156       if (IS_ALIGNED(width, 16)) {
   157         ARGBToUV422Row = ARGBToUV422Row_NEON;
   158       }
   159     }
   160   }
   161 #endif
   163   for (int y = 0; y < height; ++y) {
   164     ARGBToUV422Row(src_argb, dst_u, dst_v, width);
   165     ARGBToYRow(src_argb, dst_y, width);
   166     src_argb += src_stride_argb;
   167     dst_y += dst_stride_y;
   168     dst_u += dst_stride_u;
   169     dst_v += dst_stride_v;
   170   }
   171   return 0;
   172 }
   174 // ARGB little endian (bgra in memory) to I411
   175 LIBYUV_API
   176 int ARGBToI411(const uint8* src_argb, int src_stride_argb,
   177                uint8* dst_y, int dst_stride_y,
   178                uint8* dst_u, int dst_stride_u,
   179                uint8* dst_v, int dst_stride_v,
   180                int width, int height) {
   181   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
   182     return -1;
   183   }
   184   if (height < 0) {
   185     height = -height;
   186     src_argb = src_argb + (height - 1) * src_stride_argb;
   187     src_stride_argb = -src_stride_argb;
   188   }
   189   // Coalesce rows.
   190   if (src_stride_argb == width * 4 &&
   191       dst_stride_y == width &&
   192       dst_stride_u * 4 == width &&
   193       dst_stride_v * 4 == width) {
   194     width *= height;
   195     height = 1;
   196     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
   197   }
   198   void (*ARGBToUV411Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
   199                          int pix) = ARGBToUV411Row_C;
   200   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   201       ARGBToYRow_C;
   202 #if defined(HAS_ARGBTOYROW_SSSE3)
   203   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   204     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   205     if (IS_ALIGNED(width, 16)) {
   206       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   207       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
   208           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
   209         ARGBToYRow = ARGBToYRow_SSSE3;
   210       }
   211     }
   212   }
   213 #endif
   214 #if defined(HAS_ARGBTOYROW_AVX2)
   215   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
   216     ARGBToYRow = ARGBToYRow_Any_AVX2;
   217     if (IS_ALIGNED(width, 32)) {
   218       ARGBToYRow = ARGBToYRow_AVX2;
   219     }
   220   }
   221 #endif
   222 #if defined(HAS_ARGBTOYROW_NEON)
   223   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   224     ARGBToYRow = ARGBToYRow_Any_NEON;
   225     if (IS_ALIGNED(width, 8)) {
   226       ARGBToYRow = ARGBToYRow_NEON;
   227     }
   228     if (width >= 32) {
   229       ARGBToUV411Row = ARGBToUV411Row_Any_NEON;
   230       if (IS_ALIGNED(width, 32)) {
   231         ARGBToUV411Row = ARGBToUV411Row_NEON;
   232       }
   233     }
   234   }
   235 #endif
   237   for (int y = 0; y < height; ++y) {
   238     ARGBToUV411Row(src_argb, dst_u, dst_v, width);
   239     ARGBToYRow(src_argb, dst_y, width);
   240     src_argb += src_stride_argb;
   241     dst_y += dst_stride_y;
   242     dst_u += dst_stride_u;
   243     dst_v += dst_stride_v;
   244   }
   245   return 0;
   246 }
   248 LIBYUV_API
   249 int ARGBToNV12(const uint8* src_argb, int src_stride_argb,
   250                uint8* dst_y, int dst_stride_y,
   251                uint8* dst_uv, int dst_stride_uv,
   252                int width, int height) {
   253   if (!src_argb ||
   254       !dst_y || !dst_uv ||
   255       width <= 0 || height == 0) {
   256     return -1;
   257   }
   258   // Negative height means invert the image.
   259   if (height < 0) {
   260     height = -height;
   261     src_argb = src_argb + (height - 1) * src_stride_argb;
   262     src_stride_argb = -src_stride_argb;
   263   }
   264   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
   265                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
   266   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   267       ARGBToYRow_C;
   268 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
   269   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   270     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
   271     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   272     if (IS_ALIGNED(width, 16)) {
   273       ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
   274       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   275       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   276         ARGBToUVRow = ARGBToUVRow_SSSE3;
   277         if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
   278           ARGBToYRow = ARGBToYRow_SSSE3;
   279         }
   280       }
   281     }
   282   }
   283 #elif defined(HAS_ARGBTOYROW_NEON)
   284   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   285     ARGBToYRow = ARGBToYRow_Any_NEON;
   286     if (IS_ALIGNED(width, 8)) {
   287       ARGBToYRow = ARGBToYRow_NEON;
   288     }
   289     if (width >= 16) {
   290       ARGBToUVRow = ARGBToUVRow_Any_NEON;
   291       if (IS_ALIGNED(width, 16)) {
   292         ARGBToUVRow = ARGBToUVRow_NEON;
   293       }
   294     }
   295   }
   296 #endif
   297   int halfwidth = (width + 1) >> 1;
   298   void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
   299                       int width) = MergeUVRow_C;
   300 #if defined(HAS_MERGEUVROW_SSE2)
   301   if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
   302     MergeUVRow_ = MergeUVRow_Any_SSE2;
   303     if (IS_ALIGNED(halfwidth, 16)) {
   304       MergeUVRow_ = MergeUVRow_Unaligned_SSE2;
   305       if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) {
   306         MergeUVRow_ = MergeUVRow_SSE2;
   307       }
   308     }
   309   }
   310 #endif
   311 #if defined(HAS_MERGEUVROW_AVX2)
   312   if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
   313     MergeUVRow_ = MergeUVRow_Any_AVX2;
   314     if (IS_ALIGNED(halfwidth, 32)) {
   315       MergeUVRow_ = MergeUVRow_AVX2;
   316     }
   317   }
   318 #endif
   319 #if defined(HAS_MERGEUVROW_NEON)
   320   if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
   321     MergeUVRow_ = MergeUVRow_Any_NEON;
   322     if (IS_ALIGNED(halfwidth, 16)) {
   323       MergeUVRow_ = MergeUVRow_NEON;
   324     }
   325   }
   326 #endif
   328   // Allocate a rows of uv.
   329   align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2);
   330   uint8* row_v = row_u + ((halfwidth + 15) & ~15);
   332   for (int y = 0; y < height - 1; y += 2) {
   333     ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
   334     MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
   335     ARGBToYRow(src_argb, dst_y, width);
   336     ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
   337     src_argb += src_stride_argb * 2;
   338     dst_y += dst_stride_y * 2;
   339     dst_uv += dst_stride_uv;
   340   }
   341   if (height & 1) {
   342     ARGBToUVRow(src_argb, 0, row_u, row_v, width);
   343     MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
   344     ARGBToYRow(src_argb, dst_y, width);
   345   }
   346   free_aligned_buffer_64(row_u);
   347   return 0;
   348 }
   350 // Same as NV12 but U and V swapped.
   351 LIBYUV_API
   352 int ARGBToNV21(const uint8* src_argb, int src_stride_argb,
   353                uint8* dst_y, int dst_stride_y,
   354                uint8* dst_uv, int dst_stride_uv,
   355                int width, int height) {
   356   if (!src_argb ||
   357       !dst_y || !dst_uv ||
   358       width <= 0 || height == 0) {
   359     return -1;
   360   }
   361   // Negative height means invert the image.
   362   if (height < 0) {
   363     height = -height;
   364     src_argb = src_argb + (height - 1) * src_stride_argb;
   365     src_stride_argb = -src_stride_argb;
   366   }
   367   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
   368                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
   369   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   370       ARGBToYRow_C;
   371 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
   372   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   373     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
   374     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   375     if (IS_ALIGNED(width, 16)) {
   376       ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
   377       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   378       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   379         ARGBToUVRow = ARGBToUVRow_SSSE3;
   380         if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
   381           ARGBToYRow = ARGBToYRow_SSSE3;
   382         }
   383       }
   384     }
   385   }
   386 #elif defined(HAS_ARGBTOYROW_NEON)
   387   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   388     ARGBToYRow = ARGBToYRow_Any_NEON;
   389     if (IS_ALIGNED(width, 8)) {
   390       ARGBToYRow = ARGBToYRow_NEON;
   391     }
   392     if (width >= 16) {
   393       ARGBToUVRow = ARGBToUVRow_Any_NEON;
   394       if (IS_ALIGNED(width, 16)) {
   395         ARGBToUVRow = ARGBToUVRow_NEON;
   396       }
   397     }
   398   }
   399 #endif
   400   int halfwidth = (width + 1) >> 1;
   401   void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
   402                       int width) = MergeUVRow_C;
   403 #if defined(HAS_MERGEUVROW_SSE2)
   404   if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
   405     MergeUVRow_ = MergeUVRow_Any_SSE2;
   406     if (IS_ALIGNED(halfwidth, 16)) {
   407       MergeUVRow_ = MergeUVRow_Unaligned_SSE2;
   408       if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) {
   409         MergeUVRow_ = MergeUVRow_SSE2;
   410       }
   411     }
   412   }
   413 #endif
   414 #if defined(HAS_MERGEUVROW_AVX2)
   415   if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
   416     MergeUVRow_ = MergeUVRow_Any_AVX2;
   417     if (IS_ALIGNED(halfwidth, 32)) {
   418       MergeUVRow_ = MergeUVRow_AVX2;
   419     }
   420   }
   421 #endif
   422 #if defined(HAS_MERGEUVROW_NEON)
   423   if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
   424     MergeUVRow_ = MergeUVRow_Any_NEON;
   425     if (IS_ALIGNED(halfwidth, 16)) {
   426       MergeUVRow_ = MergeUVRow_NEON;
   427     }
   428   }
   429 #endif
   431   // Allocate a rows of uv.
   432   align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2);
   433   uint8* row_v = row_u + ((halfwidth + 15) & ~15);
   435   for (int y = 0; y < height - 1; y += 2) {
   436     ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
   437     MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
   438     ARGBToYRow(src_argb, dst_y, width);
   439     ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
   440     src_argb += src_stride_argb * 2;
   441     dst_y += dst_stride_y * 2;
   442     dst_uv += dst_stride_uv;
   443   }
   444   if (height & 1) {
   445     ARGBToUVRow(src_argb, 0, row_u, row_v, width);
   446     MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
   447     ARGBToYRow(src_argb, dst_y, width);
   448   }
   449   free_aligned_buffer_64(row_u);
   450   return 0;
   451 }
   453 // Convert ARGB to YUY2.
   454 LIBYUV_API
   455 int ARGBToYUY2(const uint8* src_argb, int src_stride_argb,
   456                uint8* dst_yuy2, int dst_stride_yuy2,
   457                int width, int height) {
   458   if (!src_argb || !dst_yuy2 ||
   459       width <= 0 || height == 0) {
   460     return -1;
   461   }
   462   // Negative height means invert the image.
   463   if (height < 0) {
   464     height = -height;
   465     dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
   466     dst_stride_yuy2 = -dst_stride_yuy2;
   467   }
   468   // Coalesce rows.
   469   if (src_stride_argb == width * 4 &&
   470       dst_stride_yuy2 == width * 2) {
   471     width *= height;
   472     height = 1;
   473     src_stride_argb = dst_stride_yuy2 = 0;
   474   }
   475   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
   476                          int pix) = ARGBToUV422Row_C;
   477 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
   478   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   479     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
   480     if (IS_ALIGNED(width, 16)) {
   481       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
   482       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   483         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
   484       }
   485     }
   486   }
   487 #endif
   488   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   489       ARGBToYRow_C;
   490 #if defined(HAS_ARGBTOYROW_SSSE3)
   491   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   492     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   493     if (IS_ALIGNED(width, 16)) {
   494       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   495       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   496         ARGBToYRow = ARGBToYRow_SSSE3;
   497       }
   498     }
   499   }
   500 #elif defined(HAS_ARGBTOYROW_NEON)
   501   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   502     ARGBToYRow = ARGBToYRow_Any_NEON;
   503     if (IS_ALIGNED(width, 8)) {
   504       ARGBToYRow = ARGBToYRow_NEON;
   505     }
   506     if (width >= 16) {
   507       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
   508       if (IS_ALIGNED(width, 16)) {
   509         ARGBToUV422Row = ARGBToUV422Row_NEON;
   510       }
   511     }
   512   }
   513 #endif
   515   void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u,
   516                         const uint8* src_v, uint8* dst_yuy2, int width) =
   517       I422ToYUY2Row_C;
   518 #if defined(HAS_I422TOYUY2ROW_SSE2)
   519   if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
   520     I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
   521     if (IS_ALIGNED(width, 16)) {
   522       I422ToYUY2Row = I422ToYUY2Row_SSE2;
   523     }
   524   }
   525 #elif defined(HAS_I422TOYUY2ROW_NEON)
   526   if (TestCpuFlag(kCpuHasNEON) && width >= 16) {
   527     I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
   528     if (IS_ALIGNED(width, 16)) {
   529       I422ToYUY2Row = I422ToYUY2Row_NEON;
   530     }
   531   }
   532 #endif
   534   // Allocate a rows of yuv.
   535   align_buffer_64(row_y, ((width + 63) & ~63) * 2);
   536   uint8* row_u = row_y + ((width + 63) & ~63);
   537   uint8* row_v = row_u + ((width + 63) & ~63) / 2;
   539   for (int y = 0; y < height; ++y) {
   540     ARGBToUV422Row(src_argb, row_u, row_v, width);
   541     ARGBToYRow(src_argb, row_y, width);
   542     I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
   543     src_argb += src_stride_argb;
   544     dst_yuy2 += dst_stride_yuy2;
   545   }
   547   free_aligned_buffer_64(row_y);
   548   return 0;
   549 }
   551 // Convert ARGB to UYVY.
   552 LIBYUV_API
   553 int ARGBToUYVY(const uint8* src_argb, int src_stride_argb,
   554                uint8* dst_uyvy, int dst_stride_uyvy,
   555                int width, int height) {
   556   if (!src_argb || !dst_uyvy ||
   557       width <= 0 || height == 0) {
   558     return -1;
   559   }
   560   // Negative height means invert the image.
   561   if (height < 0) {
   562     height = -height;
   563     dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
   564     dst_stride_uyvy = -dst_stride_uyvy;
   565   }
   566   // Coalesce rows.
   567   if (src_stride_argb == width * 4 &&
   568       dst_stride_uyvy == width * 2) {
   569     width *= height;
   570     height = 1;
   571     src_stride_argb = dst_stride_uyvy = 0;
   572   }
   573   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
   574                          int pix) = ARGBToUV422Row_C;
   575 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
   576   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   577     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
   578     if (IS_ALIGNED(width, 16)) {
   579       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
   580       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   581         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
   582       }
   583     }
   584   }
   585 #endif
   586   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   587       ARGBToYRow_C;
   588 #if defined(HAS_ARGBTOYROW_SSSE3)
   589   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   590     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   591     if (IS_ALIGNED(width, 16)) {
   592       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   593       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   594         ARGBToYRow = ARGBToYRow_SSSE3;
   595       }
   596     }
   597   }
   598 #elif defined(HAS_ARGBTOYROW_NEON)
   599   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   600     ARGBToYRow = ARGBToYRow_Any_NEON;
   601     if (IS_ALIGNED(width, 8)) {
   602       ARGBToYRow = ARGBToYRow_NEON;
   603     }
   604     if (width >= 16) {
   605       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
   606       if (IS_ALIGNED(width, 16)) {
   607         ARGBToUV422Row = ARGBToUV422Row_NEON;
   608       }
   609     }
   610   }
   611 #endif
   613   void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u,
   614                         const uint8* src_v, uint8* dst_uyvy, int width) =
   615       I422ToUYVYRow_C;
   616 #if defined(HAS_I422TOUYVYROW_SSE2)
   617   if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
   618     I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
   619     if (IS_ALIGNED(width, 16)) {
   620       I422ToUYVYRow = I422ToUYVYRow_SSE2;
   621     }
   622   }
   623 #elif defined(HAS_I422TOUYVYROW_NEON)
   624   if (TestCpuFlag(kCpuHasNEON) && width >= 16) {
   625     I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
   626     if (IS_ALIGNED(width, 16)) {
   627       I422ToUYVYRow = I422ToUYVYRow_NEON;
   628     }
   629   }
   630 #endif
   632   // Allocate a rows of yuv.
   633   align_buffer_64(row_y, ((width + 63) & ~63) * 2);
   634   uint8* row_u = row_y + ((width + 63) & ~63);
   635   uint8* row_v = row_u + ((width + 63) & ~63) / 2;
   637   for (int y = 0; y < height; ++y) {
   638     ARGBToUV422Row(src_argb, row_u, row_v, width);
   639     ARGBToYRow(src_argb, row_y, width);
   640     I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
   641     src_argb += src_stride_argb;
   642     dst_uyvy += dst_stride_uyvy;
   643   }
   645   free_aligned_buffer_64(row_y);
   646   return 0;
   647 }
   649 // Convert ARGB to I400.
   650 LIBYUV_API
   651 int ARGBToI400(const uint8* src_argb, int src_stride_argb,
   652                uint8* dst_y, int dst_stride_y,
   653                int width, int height) {
   654   if (!src_argb || !dst_y || width <= 0 || height == 0) {
   655     return -1;
   656   }
   657   if (height < 0) {
   658     height = -height;
   659     src_argb = src_argb + (height - 1) * src_stride_argb;
   660     src_stride_argb = -src_stride_argb;
   661   }
   662   // Coalesce rows.
   663   if (src_stride_argb == width * 4 &&
   664       dst_stride_y == width) {
   665     width *= height;
   666     height = 1;
   667     src_stride_argb = dst_stride_y = 0;
   668   }
   669   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
   670       ARGBToYRow_C;
   671 #if defined(HAS_ARGBTOYROW_SSSE3)
   672   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   673     ARGBToYRow = ARGBToYRow_Any_SSSE3;
   674     if (IS_ALIGNED(width, 16)) {
   675       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
   676       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
   677           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
   678         ARGBToYRow = ARGBToYRow_SSSE3;
   679       }
   680     }
   681   }
   682 #endif
   683 #if defined(HAS_ARGBTOYROW_AVX2)
   684   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
   685     ARGBToYRow = ARGBToYRow_Any_AVX2;
   686     if (IS_ALIGNED(width, 32)) {
   687       ARGBToYRow = ARGBToYRow_AVX2;
   688     }
   689   }
   690 #endif
   691 #if defined(HAS_ARGBTOYROW_NEON)
   692   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   693     ARGBToYRow = ARGBToYRow_Any_NEON;
   694     if (IS_ALIGNED(width, 8)) {
   695       ARGBToYRow = ARGBToYRow_NEON;
   696     }
   697   }
   698 #endif
   700   for (int y = 0; y < height; ++y) {
   701     ARGBToYRow(src_argb, dst_y, width);
   702     src_argb += src_stride_argb;
   703     dst_y += dst_stride_y;
   704   }
   705   return 0;
   706 }
   708 // Shuffle table for converting ARGB to RGBA.
   709 static uvec8 kShuffleMaskARGBToRGBA = {
   710   3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u
   711 };
   713 // Convert ARGB to RGBA.
   714 LIBYUV_API
   715 int ARGBToRGBA(const uint8* src_argb, int src_stride_argb,
   716                uint8* dst_rgba, int dst_stride_rgba,
   717                int width, int height) {
   718   return ARGBShuffle(src_argb, src_stride_argb,
   719                      dst_rgba, dst_stride_rgba,
   720                      (const uint8*)(&kShuffleMaskARGBToRGBA),
   721                      width, height);
   722 }
   724 // Convert ARGB To RGB24.
   725 LIBYUV_API
   726 int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
   727                 uint8* dst_rgb24, int dst_stride_rgb24,
   728                 int width, int height) {
   729   if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
   730     return -1;
   731   }
   732   if (height < 0) {
   733     height = -height;
   734     src_argb = src_argb + (height - 1) * src_stride_argb;
   735     src_stride_argb = -src_stride_argb;
   736   }
   737   // Coalesce rows.
   738   if (src_stride_argb == width * 4 &&
   739       dst_stride_rgb24 == width * 3) {
   740     width *= height;
   741     height = 1;
   742     src_stride_argb = dst_stride_rgb24 = 0;
   743   }
   744   void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
   745       ARGBToRGB24Row_C;
   746 #if defined(HAS_ARGBTORGB24ROW_SSSE3)
   747   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   748     ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
   749     if (IS_ALIGNED(width, 16)) {
   750       ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
   751     }
   752   }
   753 #elif defined(HAS_ARGBTORGB24ROW_NEON)
   754   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   755     ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
   756     if (IS_ALIGNED(width, 8)) {
   757       ARGBToRGB24Row = ARGBToRGB24Row_NEON;
   758     }
   759   }
   760 #endif
   762   for (int y = 0; y < height; ++y) {
   763     ARGBToRGB24Row(src_argb, dst_rgb24, width);
   764     src_argb += src_stride_argb;
   765     dst_rgb24 += dst_stride_rgb24;
   766   }
   767   return 0;
   768 }
   770 // Convert ARGB To RAW.
   771 LIBYUV_API
   772 int ARGBToRAW(const uint8* src_argb, int src_stride_argb,
   773               uint8* dst_raw, int dst_stride_raw,
   774               int width, int height) {
   775   if (!src_argb || !dst_raw || width <= 0 || height == 0) {
   776     return -1;
   777   }
   778   if (height < 0) {
   779     height = -height;
   780     src_argb = src_argb + (height - 1) * src_stride_argb;
   781     src_stride_argb = -src_stride_argb;
   782   }
   783   // Coalesce rows.
   784   if (src_stride_argb == width * 4 &&
   785       dst_stride_raw == width * 3) {
   786     width *= height;
   787     height = 1;
   788     src_stride_argb = dst_stride_raw = 0;
   789   }
   790   void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int pix) =
   791       ARGBToRAWRow_C;
   792 #if defined(HAS_ARGBTORAWROW_SSSE3)
   793   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   794     ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
   795     if (IS_ALIGNED(width, 16)) {
   796       ARGBToRAWRow = ARGBToRAWRow_SSSE3;
   797     }
   798   }
   799 #elif defined(HAS_ARGBTORAWROW_NEON)
   800   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   801     ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
   802     if (IS_ALIGNED(width, 8)) {
   803       ARGBToRAWRow = ARGBToRAWRow_NEON;
   804     }
   805   }
   806 #endif
   808   for (int y = 0; y < height; ++y) {
   809     ARGBToRAWRow(src_argb, dst_raw, width);
   810     src_argb += src_stride_argb;
   811     dst_raw += dst_stride_raw;
   812   }
   813   return 0;
   814 }
   816 // Convert ARGB To RGB565.
   817 LIBYUV_API
   818 int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
   819                  uint8* dst_rgb565, int dst_stride_rgb565,
   820                  int width, int height) {
   821   if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
   822     return -1;
   823   }
   824   if (height < 0) {
   825     height = -height;
   826     src_argb = src_argb + (height - 1) * src_stride_argb;
   827     src_stride_argb = -src_stride_argb;
   828   }
   829   // Coalesce rows.
   830   if (src_stride_argb == width * 4 &&
   831       dst_stride_rgb565 == width * 2) {
   832     width *= height;
   833     height = 1;
   834     src_stride_argb = dst_stride_rgb565 = 0;
   835   }
   836   void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
   837       ARGBToRGB565Row_C;
   838 #if defined(HAS_ARGBTORGB565ROW_SSE2)
   839   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
   840       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   841     ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
   842     if (IS_ALIGNED(width, 4)) {
   843       ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
   844     }
   845   }
   846 #elif defined(HAS_ARGBTORGB565ROW_NEON)
   847   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   848     ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
   849     if (IS_ALIGNED(width, 8)) {
   850       ARGBToRGB565Row = ARGBToRGB565Row_NEON;
   851     }
   852   }
   853 #endif
   855   for (int y = 0; y < height; ++y) {
   856     ARGBToRGB565Row(src_argb, dst_rgb565, width);
   857     src_argb += src_stride_argb;
   858     dst_rgb565 += dst_stride_rgb565;
   859   }
   860   return 0;
   861 }
   863 // Convert ARGB To ARGB1555.
   864 LIBYUV_API
   865 int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
   866                    uint8* dst_argb1555, int dst_stride_argb1555,
   867                    int width, int height) {
   868   if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
   869     return -1;
   870   }
   871   if (height < 0) {
   872     height = -height;
   873     src_argb = src_argb + (height - 1) * src_stride_argb;
   874     src_stride_argb = -src_stride_argb;
   875   }
   876   // Coalesce rows.
   877   if (src_stride_argb == width * 4 &&
   878       dst_stride_argb1555 == width * 2) {
   879     width *= height;
   880     height = 1;
   881     src_stride_argb = dst_stride_argb1555 = 0;
   882   }
   883   void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
   884       ARGBToARGB1555Row_C;
   885 #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
   886   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
   887       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   888     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
   889     if (IS_ALIGNED(width, 4)) {
   890       ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
   891     }
   892   }
   893 #elif defined(HAS_ARGBTOARGB1555ROW_NEON)
   894   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   895     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
   896     if (IS_ALIGNED(width, 8)) {
   897       ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
   898     }
   899   }
   900 #endif
   902   for (int y = 0; y < height; ++y) {
   903     ARGBToARGB1555Row(src_argb, dst_argb1555, width);
   904     src_argb += src_stride_argb;
   905     dst_argb1555 += dst_stride_argb1555;
   906   }
   907   return 0;
   908 }
   910 // Convert ARGB To ARGB4444.
   911 LIBYUV_API
   912 int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
   913                    uint8* dst_argb4444, int dst_stride_argb4444,
   914                    int width, int height) {
   915   if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
   916     return -1;
   917   }
   918   if (height < 0) {
   919     height = -height;
   920     src_argb = src_argb + (height - 1) * src_stride_argb;
   921     src_stride_argb = -src_stride_argb;
   922   }
   923   // Coalesce rows.
   924   if (src_stride_argb == width * 4 &&
   925       dst_stride_argb4444 == width * 2) {
   926     width *= height;
   927     height = 1;
   928     src_stride_argb = dst_stride_argb4444 = 0;
   929   }
   930   void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
   931       ARGBToARGB4444Row_C;
   932 #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
   933   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
   934       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   935     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
   936     if (IS_ALIGNED(width, 4)) {
   937       ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
   938     }
   939   }
   940 #elif defined(HAS_ARGBTOARGB4444ROW_NEON)
   941   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
   942     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
   943     if (IS_ALIGNED(width, 8)) {
   944       ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
   945     }
   946   }
   947 #endif
   949   for (int y = 0; y < height; ++y) {
   950     ARGBToARGB4444Row(src_argb, dst_argb4444, width);
   951     src_argb += src_stride_argb;
   952     dst_argb4444 += dst_stride_argb4444;
   953   }
   954   return 0;
   955 }
   957 // Convert ARGB to J420. (JPeg full range I420).
   958 LIBYUV_API
   959 int ARGBToJ420(const uint8* src_argb, int src_stride_argb,
   960                uint8* dst_yj, int dst_stride_yj,
   961                uint8* dst_u, int dst_stride_u,
   962                uint8* dst_v, int dst_stride_v,
   963                int width, int height) {
   964   if (!src_argb ||
   965       !dst_yj || !dst_u || !dst_v ||
   966       width <= 0 || height == 0) {
   967     return -1;
   968   }
   969   // Negative height means invert the image.
   970   if (height < 0) {
   971     height = -height;
   972     src_argb = src_argb + (height - 1) * src_stride_argb;
   973     src_stride_argb = -src_stride_argb;
   974   }
   975   void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb,
   976                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C;
   977   void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) =
   978       ARGBToYJRow_C;
   979 #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
   980   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
   981     ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
   982     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
   983     if (IS_ALIGNED(width, 16)) {
   984       ARGBToUVJRow = ARGBToUVJRow_Unaligned_SSSE3;
   985       ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3;
   986       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
   987         ARGBToUVJRow = ARGBToUVJRow_SSSE3;
   988         if (IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) {
   989           ARGBToYJRow = ARGBToYJRow_SSSE3;
   990         }
   991       }
   992     }
   993   }
   994 #endif
   995 #if defined(HAS_ARGBTOYJROW_AVX2) && defined(HAS_ARGBTOUVJROW_AVX2)
   996   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
   997     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
   998     if (IS_ALIGNED(width, 32)) {
   999       ARGBToYJRow = ARGBToYJRow_AVX2;
  1002 #endif
  1003 #if defined(HAS_ARGBTOYJROW_NEON)
  1004   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
  1005     ARGBToYJRow = ARGBToYJRow_Any_NEON;
  1006     if (IS_ALIGNED(width, 8)) {
  1007       ARGBToYJRow = ARGBToYJRow_NEON;
  1009     if (width >= 16) {
  1010       ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
  1011       if (IS_ALIGNED(width, 16)) {
  1012         ARGBToUVJRow = ARGBToUVJRow_NEON;
  1016 #endif
  1018   for (int y = 0; y < height - 1; y += 2) {
  1019     ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width);
  1020     ARGBToYJRow(src_argb, dst_yj, width);
  1021     ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
  1022     src_argb += src_stride_argb * 2;
  1023     dst_yj += dst_stride_yj * 2;
  1024     dst_u += dst_stride_u;
  1025     dst_v += dst_stride_v;
  1027   if (height & 1) {
  1028     ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
  1029     ARGBToYJRow(src_argb, dst_yj, width);
  1031   return 0;
  1034 // Convert ARGB to J400.
  1035 LIBYUV_API
  1036 int ARGBToJ400(const uint8* src_argb, int src_stride_argb,
  1037                uint8* dst_yj, int dst_stride_yj,
  1038                int width, int height) {
  1039   if (!src_argb || !dst_yj || width <= 0 || height == 0) {
  1040     return -1;
  1042   if (height < 0) {
  1043     height = -height;
  1044     src_argb = src_argb + (height - 1) * src_stride_argb;
  1045     src_stride_argb = -src_stride_argb;
  1047   // Coalesce rows.
  1048   if (src_stride_argb == width * 4 &&
  1049       dst_stride_yj == width) {
  1050     width *= height;
  1051     height = 1;
  1052     src_stride_argb = dst_stride_yj = 0;
  1054   void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) =
  1055       ARGBToYJRow_C;
  1056 #if defined(HAS_ARGBTOYJROW_SSSE3)
  1057   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
  1058     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
  1059     if (IS_ALIGNED(width, 16)) {
  1060       ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3;
  1061       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
  1062           IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) {
  1063         ARGBToYJRow = ARGBToYJRow_SSSE3;
  1067 #endif
  1068 #if defined(HAS_ARGBTOYJROW_AVX2)
  1069   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
  1070     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
  1071     if (IS_ALIGNED(width, 32)) {
  1072       ARGBToYJRow = ARGBToYJRow_AVX2;
  1075 #endif
  1076 #if defined(HAS_ARGBTOYJROW_NEON)
  1077   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
  1078     ARGBToYJRow = ARGBToYJRow_Any_NEON;
  1079     if (IS_ALIGNED(width, 8)) {
  1080       ARGBToYJRow = ARGBToYJRow_NEON;
  1083 #endif
  1085   for (int y = 0; y < height; ++y) {
  1086     ARGBToYJRow(src_argb, dst_yj, width);
  1087     src_argb += src_stride_argb;
  1088     dst_yj += dst_stride_yj;
  1090   return 0;
  1093 #ifdef __cplusplus
  1094 }  // extern "C"
  1095 }  // namespace libyuv
  1096 #endif

mercurial