LCOV - code coverage report
Current view: top level - media/libyuv/libyuv/source - convert.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 545 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright 2011 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.h"
      12             : 
      13             : #include "libyuv/basic_types.h"
      14             : #include "libyuv/cpu_id.h"
      15             : #include "libyuv/planar_functions.h"
      16             : #include "libyuv/rotate.h"
      17             : #include "libyuv/scale.h"  // For ScalePlane()
      18             : #include "libyuv/row.h"
      19             : 
      20             : #ifdef __cplusplus
      21             : namespace libyuv {
      22             : extern "C" {
      23             : #endif
      24             : 
      25             : #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
      26           0 : static __inline int Abs(int v) {
      27           0 :   return v >= 0 ? v : -v;
      28             : }
      29             : 
      30             : // Any I4xx To I420 format with mirroring.
      31           0 : static int I4xxToI420(const uint8* src_y,
      32             :                       int src_stride_y,
      33             :                       const uint8* src_u,
      34             :                       int src_stride_u,
      35             :                       const uint8* src_v,
      36             :                       int src_stride_v,
      37             :                       uint8* dst_y,
      38             :                       int dst_stride_y,
      39             :                       uint8* dst_u,
      40             :                       int dst_stride_u,
      41             :                       uint8* dst_v,
      42             :                       int dst_stride_v,
      43             :                       int src_y_width,
      44             :                       int src_y_height,
      45             :                       int src_uv_width,
      46             :                       int src_uv_height) {
      47           0 :   const int dst_y_width = Abs(src_y_width);
      48           0 :   const int dst_y_height = Abs(src_y_height);
      49           0 :   const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);
      50           0 :   const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);
      51           0 :   if (src_uv_width == 0 || src_uv_height == 0) {
      52           0 :     return -1;
      53             :   }
      54           0 :   if (dst_y) {
      55             :     ScalePlane(src_y, src_stride_y, src_y_width, src_y_height, dst_y,
      56           0 :                dst_stride_y, dst_y_width, dst_y_height, kFilterBilinear);
      57             :   }
      58             :   ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height, dst_u,
      59           0 :              dst_stride_u, dst_uv_width, dst_uv_height, kFilterBilinear);
      60             :   ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height, dst_v,
      61           0 :              dst_stride_v, dst_uv_width, dst_uv_height, kFilterBilinear);
      62           0 :   return 0;
      63             : }
      64             : 
      65             : // Copy I420 with optional flipping
      66             : // TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
      67             : // is does row coalescing.
      68             : LIBYUV_API
      69           0 : int I420Copy(const uint8* src_y,
      70             :              int src_stride_y,
      71             :              const uint8* src_u,
      72             :              int src_stride_u,
      73             :              const uint8* src_v,
      74             :              int src_stride_v,
      75             :              uint8* dst_y,
      76             :              int dst_stride_y,
      77             :              uint8* dst_u,
      78             :              int dst_stride_u,
      79             :              uint8* dst_v,
      80             :              int dst_stride_v,
      81             :              int width,
      82             :              int height) {
      83           0 :   int halfwidth = (width + 1) >> 1;
      84           0 :   int halfheight = (height + 1) >> 1;
      85           0 :   if (!src_u || !src_v || !dst_u || !dst_v || width <= 0 || height == 0) {
      86           0 :     return -1;
      87             :   }
      88             :   // Negative height means invert the image.
      89           0 :   if (height < 0) {
      90           0 :     height = -height;
      91           0 :     halfheight = (height + 1) >> 1;
      92           0 :     src_y = src_y + (height - 1) * src_stride_y;
      93           0 :     src_u = src_u + (halfheight - 1) * src_stride_u;
      94           0 :     src_v = src_v + (halfheight - 1) * src_stride_v;
      95           0 :     src_stride_y = -src_stride_y;
      96           0 :     src_stride_u = -src_stride_u;
      97           0 :     src_stride_v = -src_stride_v;
      98             :   }
      99             : 
     100           0 :   if (dst_y) {
     101           0 :     CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
     102             :   }
     103             :   // Copy UV planes.
     104           0 :   CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
     105           0 :   CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
     106           0 :   return 0;
     107             : }
     108             : 
     109             : // 422 chroma is 1/2 width, 1x height
     110             : // 420 chroma is 1/2 width, 1/2 height
     111             : LIBYUV_API
     112           0 : int I422ToI420(const uint8* src_y,
     113             :                int src_stride_y,
     114             :                const uint8* src_u,
     115             :                int src_stride_u,
     116             :                const uint8* src_v,
     117             :                int src_stride_v,
     118             :                uint8* dst_y,
     119             :                int dst_stride_y,
     120             :                uint8* dst_u,
     121             :                int dst_stride_u,
     122             :                uint8* dst_v,
     123             :                int dst_stride_v,
     124             :                int width,
     125             :                int height) {
     126           0 :   const int src_uv_width = SUBSAMPLE(width, 1, 1);
     127             :   return I4xxToI420(src_y, src_stride_y, src_u, src_stride_u, src_v,
     128             :                     src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
     129           0 :                     dst_v, dst_stride_v, width, height, src_uv_width, height);
     130             : }
     131             : 
     132             : // 444 chroma is 1x width, 1x height
     133             : // 420 chroma is 1/2 width, 1/2 height
     134             : LIBYUV_API
     135           0 : int I444ToI420(const uint8* src_y,
     136             :                int src_stride_y,
     137             :                const uint8* src_u,
     138             :                int src_stride_u,
     139             :                const uint8* src_v,
     140             :                int src_stride_v,
     141             :                uint8* dst_y,
     142             :                int dst_stride_y,
     143             :                uint8* dst_u,
     144             :                int dst_stride_u,
     145             :                uint8* dst_v,
     146             :                int dst_stride_v,
     147             :                int width,
     148             :                int height) {
     149             :   return I4xxToI420(src_y, src_stride_y, src_u, src_stride_u, src_v,
     150             :                     src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
     151           0 :                     dst_v, dst_stride_v, width, height, width, height);
     152             : }
     153             : 
     154             : // I400 is greyscale typically used in MJPG
     155             : LIBYUV_API
     156           0 : int I400ToI420(const uint8* src_y,
     157             :                int src_stride_y,
     158             :                uint8* dst_y,
     159             :                int dst_stride_y,
     160             :                uint8* dst_u,
     161             :                int dst_stride_u,
     162             :                uint8* dst_v,
     163             :                int dst_stride_v,
     164             :                int width,
     165             :                int height) {
     166           0 :   int halfwidth = (width + 1) >> 1;
     167           0 :   int halfheight = (height + 1) >> 1;
     168           0 :   if (!dst_u || !dst_v || width <= 0 || height == 0) {
     169           0 :     return -1;
     170             :   }
     171             :   // Negative height means invert the image.
     172           0 :   if (height < 0) {
     173           0 :     height = -height;
     174           0 :     halfheight = (height + 1) >> 1;
     175           0 :     src_y = src_y + (height - 1) * src_stride_y;
     176           0 :     src_stride_y = -src_stride_y;
     177             :   }
     178           0 :   if (dst_y) {
     179           0 :     CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
     180             :   }
     181           0 :   SetPlane(dst_u, dst_stride_u, halfwidth, halfheight, 128);
     182           0 :   SetPlane(dst_v, dst_stride_v, halfwidth, halfheight, 128);
     183           0 :   return 0;
     184             : }
     185             : 
     186           0 : static void CopyPlane2(const uint8* src,
     187             :                        int src_stride_0,
     188             :                        int src_stride_1,
     189             :                        uint8* dst,
     190             :                        int dst_stride,
     191             :                        int width,
     192             :                        int height) {
     193             :   int y;
     194           0 :   void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
     195             : #if defined(HAS_COPYROW_SSE2)
     196           0 :   if (TestCpuFlag(kCpuHasSSE2)) {
     197           0 :     CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2;
     198             :   }
     199             : #endif
     200             : #if defined(HAS_COPYROW_AVX)
     201           0 :   if (TestCpuFlag(kCpuHasAVX)) {
     202           0 :     CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX;
     203             :   }
     204             : #endif
     205             : #if defined(HAS_COPYROW_ERMS)
     206           0 :   if (TestCpuFlag(kCpuHasERMS)) {
     207           0 :     CopyRow = CopyRow_ERMS;
     208             :   }
     209             : #endif
     210             : #if defined(HAS_COPYROW_NEON)
     211             :   if (TestCpuFlag(kCpuHasNEON)) {
     212             :     CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON;
     213             :   }
     214             : #endif
     215             : #if defined(HAS_COPYROW_MIPS)
     216             :   if (TestCpuFlag(kCpuHasMIPS)) {
     217             :     CopyRow = CopyRow_MIPS;
     218             :   }
     219             : #endif
     220             : 
     221             :   // Copy plane
     222           0 :   for (y = 0; y < height - 1; y += 2) {
     223           0 :     CopyRow(src, dst, width);
     224           0 :     CopyRow(src + src_stride_0, dst + dst_stride, width);
     225           0 :     src += src_stride_0 + src_stride_1;
     226           0 :     dst += dst_stride * 2;
     227             :   }
     228           0 :   if (height & 1) {
     229           0 :     CopyRow(src, dst, width);
     230             :   }
     231           0 : }
     232             : 
     233             : // Support converting from FOURCC_M420
     234             : // Useful for bandwidth constrained transports like USB 1.0 and 2.0 and for
     235             : // easy conversion to I420.
     236             : // M420 format description:
     237             : // M420 is row biplanar 420: 2 rows of Y and 1 row of UV.
     238             : // Chroma is half width / half height. (420)
     239             : // src_stride_m420 is row planar. Normally this will be the width in pixels.
     240             : //   The UV plane is half width, but 2 values, so src_stride_m420 applies to
     241             : //   this as well as the two Y planes.
     242           0 : static int X420ToI420(const uint8* src_y,
     243             :                       int src_stride_y0,
     244             :                       int src_stride_y1,
     245             :                       const uint8* src_uv,
     246             :                       int src_stride_uv,
     247             :                       uint8* dst_y,
     248             :                       int dst_stride_y,
     249             :                       uint8* dst_u,
     250             :                       int dst_stride_u,
     251             :                       uint8* dst_v,
     252             :                       int dst_stride_v,
     253             :                       int width,
     254             :                       int height) {
     255           0 :   int halfwidth = (width + 1) >> 1;
     256           0 :   int halfheight = (height + 1) >> 1;
     257           0 :   if (!src_uv || !dst_u || !dst_v || width <= 0 || height == 0) {
     258           0 :     return -1;
     259             :   }
     260             :   // Negative height means invert the image.
     261           0 :   if (height < 0) {
     262           0 :     height = -height;
     263           0 :     halfheight = (height + 1) >> 1;
     264           0 :     if (dst_y) {
     265           0 :       dst_y = dst_y + (height - 1) * dst_stride_y;
     266             :     }
     267           0 :     dst_u = dst_u + (halfheight - 1) * dst_stride_u;
     268           0 :     dst_v = dst_v + (halfheight - 1) * dst_stride_v;
     269           0 :     dst_stride_y = -dst_stride_y;
     270           0 :     dst_stride_u = -dst_stride_u;
     271           0 :     dst_stride_v = -dst_stride_v;
     272             :   }
     273             :   // Coalesce rows.
     274           0 :   if (src_stride_y0 == width && src_stride_y1 == width &&
     275             :       dst_stride_y == width) {
     276           0 :     width *= height;
     277           0 :     height = 1;
     278           0 :     src_stride_y0 = src_stride_y1 = dst_stride_y = 0;
     279             :   }
     280             :   // Coalesce rows.
     281           0 :   if (src_stride_uv == halfwidth * 2 && dst_stride_u == halfwidth &&
     282             :       dst_stride_v == halfwidth) {
     283           0 :     halfwidth *= halfheight;
     284           0 :     halfheight = 1;
     285           0 :     src_stride_uv = dst_stride_u = dst_stride_v = 0;
     286             :   }
     287             : 
     288           0 :   if (dst_y) {
     289           0 :     if (src_stride_y0 == src_stride_y1) {
     290           0 :       CopyPlane(src_y, src_stride_y0, dst_y, dst_stride_y, width, height);
     291             :     } else {
     292             :       CopyPlane2(src_y, src_stride_y0, src_stride_y1, dst_y, dst_stride_y,
     293           0 :                  width, height);
     294             :     }
     295             :   }
     296             : 
     297             :   // Split UV plane - NV12 / NV21
     298             :   SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v, dst_stride_v,
     299           0 :                halfwidth, halfheight);
     300             : 
     301           0 :   return 0;
     302             : }
     303             : 
     304             : // Convert NV12 to I420.
     305             : LIBYUV_API
     306           0 : int NV12ToI420(const uint8* src_y,
     307             :                int src_stride_y,
     308             :                const uint8* src_uv,
     309             :                int src_stride_uv,
     310             :                uint8* dst_y,
     311             :                int dst_stride_y,
     312             :                uint8* dst_u,
     313             :                int dst_stride_u,
     314             :                uint8* dst_v,
     315             :                int dst_stride_v,
     316             :                int width,
     317             :                int height) {
     318             :   return X420ToI420(src_y, src_stride_y, src_stride_y, src_uv, src_stride_uv,
     319             :                     dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v,
     320           0 :                     dst_stride_v, width, height);
     321             : }
     322             : 
     323             : // Convert NV21 to I420.  Same as NV12 but u and v pointers swapped.
     324             : LIBYUV_API
     325           0 : int NV21ToI420(const uint8* src_y,
     326             :                int src_stride_y,
     327             :                const uint8* src_vu,
     328             :                int src_stride_vu,
     329             :                uint8* dst_y,
     330             :                int dst_stride_y,
     331             :                uint8* dst_u,
     332             :                int dst_stride_u,
     333             :                uint8* dst_v,
     334             :                int dst_stride_v,
     335             :                int width,
     336             :                int height) {
     337             :   return X420ToI420(src_y, src_stride_y, src_stride_y, src_vu, src_stride_vu,
     338             :                     dst_y, dst_stride_y, dst_v, dst_stride_v, dst_u,
     339           0 :                     dst_stride_u, width, height);
     340             : }
     341             : 
     342             : // Convert M420 to I420.
     343             : LIBYUV_API
     344           0 : int M420ToI420(const uint8* src_m420,
     345             :                int src_stride_m420,
     346             :                uint8* dst_y,
     347             :                int dst_stride_y,
     348             :                uint8* dst_u,
     349             :                int dst_stride_u,
     350             :                uint8* dst_v,
     351             :                int dst_stride_v,
     352             :                int width,
     353             :                int height) {
     354           0 :   return X420ToI420(src_m420, src_stride_m420, src_stride_m420 * 2,
     355           0 :                     src_m420 + src_stride_m420 * 2, src_stride_m420 * 3, dst_y,
     356             :                     dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
     357           0 :                     width, height);
     358             : }
     359             : 
     360             : // Convert YUY2 to I420.
     361             : LIBYUV_API
     362           0 : int YUY2ToI420(const uint8* src_yuy2,
     363             :                int src_stride_yuy2,
     364             :                uint8* dst_y,
     365             :                int dst_stride_y,
     366             :                uint8* dst_u,
     367             :                int dst_stride_u,
     368             :                uint8* dst_v,
     369             :                int dst_stride_v,
     370             :                int width,
     371             :                int height) {
     372             :   int y;
     373             :   void (*YUY2ToUVRow)(const uint8* src_yuy2, int src_stride_yuy2, uint8* dst_u,
     374           0 :                       uint8* dst_v, int width) = YUY2ToUVRow_C;
     375             :   void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int width) =
     376           0 :       YUY2ToYRow_C;
     377             :   // Negative height means invert the image.
     378           0 :   if (height < 0) {
     379           0 :     height = -height;
     380           0 :     src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
     381           0 :     src_stride_yuy2 = -src_stride_yuy2;
     382             :   }
     383             : #if defined(HAS_YUY2TOYROW_SSE2)
     384           0 :   if (TestCpuFlag(kCpuHasSSE2)) {
     385           0 :     YUY2ToUVRow = YUY2ToUVRow_Any_SSE2;
     386           0 :     YUY2ToYRow = YUY2ToYRow_Any_SSE2;
     387           0 :     if (IS_ALIGNED(width, 16)) {
     388           0 :       YUY2ToUVRow = YUY2ToUVRow_SSE2;
     389           0 :       YUY2ToYRow = YUY2ToYRow_SSE2;
     390             :     }
     391             :   }
     392             : #endif
     393             : #if defined(HAS_YUY2TOYROW_AVX2)
     394           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
     395           0 :     YUY2ToUVRow = YUY2ToUVRow_Any_AVX2;
     396           0 :     YUY2ToYRow = YUY2ToYRow_Any_AVX2;
     397           0 :     if (IS_ALIGNED(width, 32)) {
     398           0 :       YUY2ToUVRow = YUY2ToUVRow_AVX2;
     399           0 :       YUY2ToYRow = YUY2ToYRow_AVX2;
     400             :     }
     401             :   }
     402             : #endif
     403             : #if defined(HAS_YUY2TOYROW_NEON)
     404             :   if (TestCpuFlag(kCpuHasNEON)) {
     405             :     YUY2ToYRow = YUY2ToYRow_Any_NEON;
     406             :     YUY2ToUVRow = YUY2ToUVRow_Any_NEON;
     407             :     if (IS_ALIGNED(width, 16)) {
     408             :       YUY2ToYRow = YUY2ToYRow_NEON;
     409             :       YUY2ToUVRow = YUY2ToUVRow_NEON;
     410             :     }
     411             :   }
     412             : #endif
     413             : #if defined(HAS_YUY2TOYROW_MSA)
     414             :   if (TestCpuFlag(kCpuHasMSA)) {
     415             :     YUY2ToYRow = YUY2ToYRow_Any_MSA;
     416             :     YUY2ToUVRow = YUY2ToUVRow_Any_MSA;
     417             :     if (IS_ALIGNED(width, 32)) {
     418             :       YUY2ToYRow = YUY2ToYRow_MSA;
     419             :       YUY2ToUVRow = YUY2ToUVRow_MSA;
     420             :     }
     421             :   }
     422             : #endif
     423             : 
     424           0 :   for (y = 0; y < height - 1; y += 2) {
     425           0 :     YUY2ToUVRow(src_yuy2, src_stride_yuy2, dst_u, dst_v, width);
     426           0 :     YUY2ToYRow(src_yuy2, dst_y, width);
     427           0 :     YUY2ToYRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, width);
     428           0 :     src_yuy2 += src_stride_yuy2 * 2;
     429           0 :     dst_y += dst_stride_y * 2;
     430           0 :     dst_u += dst_stride_u;
     431           0 :     dst_v += dst_stride_v;
     432             :   }
     433           0 :   if (height & 1) {
     434           0 :     YUY2ToUVRow(src_yuy2, 0, dst_u, dst_v, width);
     435           0 :     YUY2ToYRow(src_yuy2, dst_y, width);
     436             :   }
     437           0 :   return 0;
     438             : }
     439             : 
     440             : // Convert UYVY to I420.
     441             : LIBYUV_API
     442           0 : int UYVYToI420(const uint8* src_uyvy,
     443             :                int src_stride_uyvy,
     444             :                uint8* dst_y,
     445             :                int dst_stride_y,
     446             :                uint8* dst_u,
     447             :                int dst_stride_u,
     448             :                uint8* dst_v,
     449             :                int dst_stride_v,
     450             :                int width,
     451             :                int height) {
     452             :   int y;
     453             :   void (*UYVYToUVRow)(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_u,
     454           0 :                       uint8* dst_v, int width) = UYVYToUVRow_C;
     455             :   void (*UYVYToYRow)(const uint8* src_uyvy, uint8* dst_y, int width) =
     456           0 :       UYVYToYRow_C;
     457             :   // Negative height means invert the image.
     458           0 :   if (height < 0) {
     459           0 :     height = -height;
     460           0 :     src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
     461           0 :     src_stride_uyvy = -src_stride_uyvy;
     462             :   }
     463             : #if defined(HAS_UYVYTOYROW_SSE2)
     464           0 :   if (TestCpuFlag(kCpuHasSSE2)) {
     465           0 :     UYVYToUVRow = UYVYToUVRow_Any_SSE2;
     466           0 :     UYVYToYRow = UYVYToYRow_Any_SSE2;
     467           0 :     if (IS_ALIGNED(width, 16)) {
     468           0 :       UYVYToUVRow = UYVYToUVRow_SSE2;
     469           0 :       UYVYToYRow = UYVYToYRow_SSE2;
     470             :     }
     471             :   }
     472             : #endif
     473             : #if defined(HAS_UYVYTOYROW_AVX2)
     474           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
     475           0 :     UYVYToUVRow = UYVYToUVRow_Any_AVX2;
     476           0 :     UYVYToYRow = UYVYToYRow_Any_AVX2;
     477           0 :     if (IS_ALIGNED(width, 32)) {
     478           0 :       UYVYToUVRow = UYVYToUVRow_AVX2;
     479           0 :       UYVYToYRow = UYVYToYRow_AVX2;
     480             :     }
     481             :   }
     482             : #endif
     483             : #if defined(HAS_UYVYTOYROW_NEON)
     484             :   if (TestCpuFlag(kCpuHasNEON)) {
     485             :     UYVYToYRow = UYVYToYRow_Any_NEON;
     486             :     UYVYToUVRow = UYVYToUVRow_Any_NEON;
     487             :     if (IS_ALIGNED(width, 16)) {
     488             :       UYVYToYRow = UYVYToYRow_NEON;
     489             :       UYVYToUVRow = UYVYToUVRow_NEON;
     490             :     }
     491             :   }
     492             : #endif
     493             : #if defined(HAS_UYVYTOYROW_MSA)
     494             :   if (TestCpuFlag(kCpuHasMSA)) {
     495             :     UYVYToYRow = UYVYToYRow_Any_MSA;
     496             :     UYVYToUVRow = UYVYToUVRow_Any_MSA;
     497             :     if (IS_ALIGNED(width, 32)) {
     498             :       UYVYToYRow = UYVYToYRow_MSA;
     499             :       UYVYToUVRow = UYVYToUVRow_MSA;
     500             :     }
     501             :   }
     502             : #endif
     503             : 
     504           0 :   for (y = 0; y < height - 1; y += 2) {
     505           0 :     UYVYToUVRow(src_uyvy, src_stride_uyvy, dst_u, dst_v, width);
     506           0 :     UYVYToYRow(src_uyvy, dst_y, width);
     507           0 :     UYVYToYRow(src_uyvy + src_stride_uyvy, dst_y + dst_stride_y, width);
     508           0 :     src_uyvy += src_stride_uyvy * 2;
     509           0 :     dst_y += dst_stride_y * 2;
     510           0 :     dst_u += dst_stride_u;
     511           0 :     dst_v += dst_stride_v;
     512             :   }
     513           0 :   if (height & 1) {
     514           0 :     UYVYToUVRow(src_uyvy, 0, dst_u, dst_v, width);
     515           0 :     UYVYToYRow(src_uyvy, dst_y, width);
     516             :   }
     517           0 :   return 0;
     518             : }
     519             : 
     520             : // Convert ARGB to I420.
     521             : LIBYUV_API
     522           0 : int ARGBToI420(const uint8* src_argb,
     523             :                int src_stride_argb,
     524             :                uint8* dst_y,
     525             :                int dst_stride_y,
     526             :                uint8* dst_u,
     527             :                int dst_stride_u,
     528             :                uint8* dst_v,
     529             :                int dst_stride_v,
     530             :                int width,
     531             :                int height) {
     532             :   int y;
     533             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
     534           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
     535             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
     536           0 :       ARGBToYRow_C;
     537           0 :   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
     538           0 :     return -1;
     539             :   }
     540             :   // Negative height means invert the image.
     541           0 :   if (height < 0) {
     542           0 :     height = -height;
     543           0 :     src_argb = src_argb + (height - 1) * src_stride_argb;
     544           0 :     src_stride_argb = -src_stride_argb;
     545             :   }
     546             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
     547           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
     548           0 :     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
     549           0 :     ARGBToYRow = ARGBToYRow_Any_SSSE3;
     550           0 :     if (IS_ALIGNED(width, 16)) {
     551           0 :       ARGBToUVRow = ARGBToUVRow_SSSE3;
     552           0 :       ARGBToYRow = ARGBToYRow_SSSE3;
     553             :     }
     554             :   }
     555             : #endif
     556             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
     557           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
     558           0 :     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
     559           0 :     ARGBToYRow = ARGBToYRow_Any_AVX2;
     560           0 :     if (IS_ALIGNED(width, 32)) {
     561           0 :       ARGBToUVRow = ARGBToUVRow_AVX2;
     562           0 :       ARGBToYRow = ARGBToYRow_AVX2;
     563             :     }
     564             :   }
     565             : #endif
     566             : #if defined(HAS_ARGBTOYROW_NEON)
     567             :   if (TestCpuFlag(kCpuHasNEON)) {
     568             :     ARGBToYRow = ARGBToYRow_Any_NEON;
     569             :     if (IS_ALIGNED(width, 8)) {
     570             :       ARGBToYRow = ARGBToYRow_NEON;
     571             :     }
     572             :   }
     573             : #endif
     574             : #if defined(HAS_ARGBTOUVROW_NEON)
     575             :   if (TestCpuFlag(kCpuHasNEON)) {
     576             :     ARGBToUVRow = ARGBToUVRow_Any_NEON;
     577             :     if (IS_ALIGNED(width, 16)) {
     578             :       ARGBToUVRow = ARGBToUVRow_NEON;
     579             :     }
     580             :   }
     581             : #endif
     582             : #if defined(HAS_ARGBTOYROW_DSPR2)
     583             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     584             :     ARGBToYRow = ARGBToYRow_Any_DSPR2;
     585             :     if (IS_ALIGNED(width, 8)) {
     586             :       ARGBToYRow = ARGBToYRow_DSPR2;
     587             :     }
     588             :   }
     589             : #endif
     590             : #if defined(HAS_ARGBTOYROW_MSA)
     591             :   if (TestCpuFlag(kCpuHasMSA)) {
     592             :     ARGBToYRow = ARGBToYRow_Any_MSA;
     593             :     if (IS_ALIGNED(width, 16)) {
     594             :       ARGBToYRow = ARGBToYRow_MSA;
     595             :     }
     596             :   }
     597             : #endif
     598             : #if defined(HAS_ARGBTOUVROW_DSPR2)
     599             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     600             :     ARGBToUVRow = ARGBToUVRow_Any_DSPR2;
     601             :     if (IS_ALIGNED(width, 16)) {
     602             :       ARGBToUVRow = ARGBToUVRow_DSPR2;
     603             :     }
     604             :   }
     605             : #endif
     606             : #if defined(HAS_ARGBTOUVROW_MSA)
     607             :   if (TestCpuFlag(kCpuHasMSA)) {
     608             :     ARGBToUVRow = ARGBToUVRow_Any_MSA;
     609             :     if (IS_ALIGNED(width, 32)) {
     610             :       ARGBToUVRow = ARGBToUVRow_MSA;
     611             :     }
     612             :   }
     613             : #endif
     614             : 
     615           0 :   for (y = 0; y < height - 1; y += 2) {
     616           0 :     ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width);
     617           0 :     ARGBToYRow(src_argb, dst_y, width);
     618           0 :     ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
     619           0 :     src_argb += src_stride_argb * 2;
     620           0 :     dst_y += dst_stride_y * 2;
     621           0 :     dst_u += dst_stride_u;
     622           0 :     dst_v += dst_stride_v;
     623             :   }
     624           0 :   if (height & 1) {
     625           0 :     ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
     626           0 :     ARGBToYRow(src_argb, dst_y, width);
     627             :   }
     628           0 :   return 0;
     629             : }
     630             : 
     631             : // Convert BGRA to I420.
     632             : LIBYUV_API
     633           0 : int BGRAToI420(const uint8* src_bgra,
     634             :                int src_stride_bgra,
     635             :                uint8* dst_y,
     636             :                int dst_stride_y,
     637             :                uint8* dst_u,
     638             :                int dst_stride_u,
     639             :                uint8* dst_v,
     640             :                int dst_stride_v,
     641             :                int width,
     642             :                int height) {
     643             :   int y;
     644             :   void (*BGRAToUVRow)(const uint8* src_bgra0, int src_stride_bgra, uint8* dst_u,
     645           0 :                       uint8* dst_v, int width) = BGRAToUVRow_C;
     646             :   void (*BGRAToYRow)(const uint8* src_bgra, uint8* dst_y, int width) =
     647           0 :       BGRAToYRow_C;
     648           0 :   if (!src_bgra || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
     649           0 :     return -1;
     650             :   }
     651             :   // Negative height means invert the image.
     652           0 :   if (height < 0) {
     653           0 :     height = -height;
     654           0 :     src_bgra = src_bgra + (height - 1) * src_stride_bgra;
     655           0 :     src_stride_bgra = -src_stride_bgra;
     656             :   }
     657             : #if defined(HAS_BGRATOYROW_SSSE3) && defined(HAS_BGRATOUVROW_SSSE3)
     658           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
     659           0 :     BGRAToUVRow = BGRAToUVRow_Any_SSSE3;
     660           0 :     BGRAToYRow = BGRAToYRow_Any_SSSE3;
     661           0 :     if (IS_ALIGNED(width, 16)) {
     662           0 :       BGRAToUVRow = BGRAToUVRow_SSSE3;
     663           0 :       BGRAToYRow = BGRAToYRow_SSSE3;
     664             :     }
     665             :   }
     666             : #endif
     667             : #if defined(HAS_BGRATOYROW_NEON)
     668             :   if (TestCpuFlag(kCpuHasNEON)) {
     669             :     BGRAToYRow = BGRAToYRow_Any_NEON;
     670             :     if (IS_ALIGNED(width, 8)) {
     671             :       BGRAToYRow = BGRAToYRow_NEON;
     672             :     }
     673             :   }
     674             : #endif
     675             : #if defined(HAS_BGRATOUVROW_NEON)
     676             :   if (TestCpuFlag(kCpuHasNEON)) {
     677             :     BGRAToUVRow = BGRAToUVRow_Any_NEON;
     678             :     if (IS_ALIGNED(width, 16)) {
     679             :       BGRAToUVRow = BGRAToUVRow_NEON;
     680             :     }
     681             :   }
     682             : #endif
     683             : #if defined(HAS_BGRATOYROW_DSPR2)
     684             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     685             :     BGRAToYRow = BGRAToYRow_Any_DSPR2;
     686             :     if (IS_ALIGNED(width, 8)) {
     687             :       BGRAToYRow = BGRAToYRow_DSPR2;
     688             :     }
     689             :   }
     690             : #endif
     691             : #if defined(HAS_BGRATOUVROW_DSPR2)
     692             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     693             :     BGRAToUVRow = BGRAToUVRow_Any_DSPR2;
     694             :     if (IS_ALIGNED(width, 16)) {
     695             :       BGRAToUVRow = BGRAToUVRow_DSPR2;
     696             :     }
     697             :   }
     698             : #endif
     699             : #if defined(HAS_BGRATOYROW_MSA)
     700             :   if (TestCpuFlag(kCpuHasMSA)) {
     701             :     BGRAToYRow = BGRAToYRow_Any_MSA;
     702             :     if (IS_ALIGNED(width, 16)) {
     703             :       BGRAToYRow = BGRAToYRow_MSA;
     704             :     }
     705             :   }
     706             : #endif
     707             : #if defined(HAS_BGRATOUVROW_MSA)
     708             :   if (TestCpuFlag(kCpuHasMSA)) {
     709             :     BGRAToUVRow = BGRAToUVRow_Any_MSA;
     710             :     if (IS_ALIGNED(width, 16)) {
     711             :       BGRAToUVRow = BGRAToUVRow_MSA;
     712             :     }
     713             :   }
     714             : #endif
     715             : 
     716           0 :   for (y = 0; y < height - 1; y += 2) {
     717           0 :     BGRAToUVRow(src_bgra, src_stride_bgra, dst_u, dst_v, width);
     718           0 :     BGRAToYRow(src_bgra, dst_y, width);
     719           0 :     BGRAToYRow(src_bgra + src_stride_bgra, dst_y + dst_stride_y, width);
     720           0 :     src_bgra += src_stride_bgra * 2;
     721           0 :     dst_y += dst_stride_y * 2;
     722           0 :     dst_u += dst_stride_u;
     723           0 :     dst_v += dst_stride_v;
     724             :   }
     725           0 :   if (height & 1) {
     726           0 :     BGRAToUVRow(src_bgra, 0, dst_u, dst_v, width);
     727           0 :     BGRAToYRow(src_bgra, dst_y, width);
     728             :   }
     729           0 :   return 0;
     730             : }
     731             : 
     732             : // Convert ABGR to I420.
     733             : LIBYUV_API
     734           0 : int ABGRToI420(const uint8* src_abgr,
     735             :                int src_stride_abgr,
     736             :                uint8* dst_y,
     737             :                int dst_stride_y,
     738             :                uint8* dst_u,
     739             :                int dst_stride_u,
     740             :                uint8* dst_v,
     741             :                int dst_stride_v,
     742             :                int width,
     743             :                int height) {
     744             :   int y;
     745             :   void (*ABGRToUVRow)(const uint8* src_abgr0, int src_stride_abgr, uint8* dst_u,
     746           0 :                       uint8* dst_v, int width) = ABGRToUVRow_C;
     747             :   void (*ABGRToYRow)(const uint8* src_abgr, uint8* dst_y, int width) =
     748           0 :       ABGRToYRow_C;
     749           0 :   if (!src_abgr || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
     750           0 :     return -1;
     751             :   }
     752             :   // Negative height means invert the image.
     753           0 :   if (height < 0) {
     754           0 :     height = -height;
     755           0 :     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
     756           0 :     src_stride_abgr = -src_stride_abgr;
     757             :   }
     758             : #if defined(HAS_ABGRTOYROW_SSSE3) && defined(HAS_ABGRTOUVROW_SSSE3)
     759           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
     760           0 :     ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
     761           0 :     ABGRToYRow = ABGRToYRow_Any_SSSE3;
     762           0 :     if (IS_ALIGNED(width, 16)) {
     763           0 :       ABGRToUVRow = ABGRToUVRow_SSSE3;
     764           0 :       ABGRToYRow = ABGRToYRow_SSSE3;
     765             :     }
     766             :   }
     767             : #endif
     768             : #if defined(HAS_ABGRTOYROW_NEON)
     769             :   if (TestCpuFlag(kCpuHasNEON)) {
     770             :     ABGRToYRow = ABGRToYRow_Any_NEON;
     771             :     if (IS_ALIGNED(width, 8)) {
     772             :       ABGRToYRow = ABGRToYRow_NEON;
     773             :     }
     774             :   }
     775             : #endif
     776             : #if defined(HAS_ABGRTOUVROW_NEON)
     777             :   if (TestCpuFlag(kCpuHasNEON)) {
     778             :     ABGRToUVRow = ABGRToUVRow_Any_NEON;
     779             :     if (IS_ALIGNED(width, 16)) {
     780             :       ABGRToUVRow = ABGRToUVRow_NEON;
     781             :     }
     782             :   }
     783             : #endif
     784             : #if defined(HAS_ABGRTOYROW_DSPR2)
     785             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     786             :     ABGRToYRow = ABGRToYRow_Any_DSPR2;
     787             :     if (IS_ALIGNED(width, 8)) {
     788             :       ABGRToYRow = ABGRToYRow_DSPR2;
     789             :     }
     790             :   }
     791             : #endif
     792             : #if defined(HAS_ABGRTOUVROW_DSPR2)
     793             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     794             :     ABGRToUVRow = ABGRToUVRow_Any_DSPR2;
     795             :     if (IS_ALIGNED(width, 16)) {
     796             :       ABGRToUVRow = ABGRToUVRow_DSPR2;
     797             :     }
     798             :   }
     799             : #endif
     800             : #if defined(HAS_ABGRTOYROW_MSA)
     801             :   if (TestCpuFlag(kCpuHasMSA)) {
     802             :     ABGRToYRow = ABGRToYRow_Any_MSA;
     803             :     if (IS_ALIGNED(width, 16)) {
     804             :       ABGRToYRow = ABGRToYRow_MSA;
     805             :     }
     806             :   }
     807             : #endif
     808             : #if defined(HAS_ABGRTOUVROW_MSA)
     809             :   if (TestCpuFlag(kCpuHasMSA)) {
     810             :     ABGRToUVRow = ABGRToUVRow_Any_MSA;
     811             :     if (IS_ALIGNED(width, 16)) {
     812             :       ABGRToUVRow = ABGRToUVRow_MSA;
     813             :     }
     814             :   }
     815             : #endif
     816             : 
     817           0 :   for (y = 0; y < height - 1; y += 2) {
     818           0 :     ABGRToUVRow(src_abgr, src_stride_abgr, dst_u, dst_v, width);
     819           0 :     ABGRToYRow(src_abgr, dst_y, width);
     820           0 :     ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
     821           0 :     src_abgr += src_stride_abgr * 2;
     822           0 :     dst_y += dst_stride_y * 2;
     823           0 :     dst_u += dst_stride_u;
     824           0 :     dst_v += dst_stride_v;
     825             :   }
     826           0 :   if (height & 1) {
     827           0 :     ABGRToUVRow(src_abgr, 0, dst_u, dst_v, width);
     828           0 :     ABGRToYRow(src_abgr, dst_y, width);
     829             :   }
     830           0 :   return 0;
     831             : }
     832             : 
     833             : // Convert RGBA to I420.
     834             : LIBYUV_API
     835           0 : int RGBAToI420(const uint8* src_rgba,
     836             :                int src_stride_rgba,
     837             :                uint8* dst_y,
     838             :                int dst_stride_y,
     839             :                uint8* dst_u,
     840             :                int dst_stride_u,
     841             :                uint8* dst_v,
     842             :                int dst_stride_v,
     843             :                int width,
     844             :                int height) {
     845             :   int y;
     846             :   void (*RGBAToUVRow)(const uint8* src_rgba0, int src_stride_rgba, uint8* dst_u,
     847           0 :                       uint8* dst_v, int width) = RGBAToUVRow_C;
     848             :   void (*RGBAToYRow)(const uint8* src_rgba, uint8* dst_y, int width) =
     849           0 :       RGBAToYRow_C;
     850           0 :   if (!src_rgba || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
     851           0 :     return -1;
     852             :   }
     853             :   // Negative height means invert the image.
     854           0 :   if (height < 0) {
     855           0 :     height = -height;
     856           0 :     src_rgba = src_rgba + (height - 1) * src_stride_rgba;
     857           0 :     src_stride_rgba = -src_stride_rgba;
     858             :   }
     859             : #if defined(HAS_RGBATOYROW_SSSE3) && defined(HAS_RGBATOUVROW_SSSE3)
     860           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
     861           0 :     RGBAToUVRow = RGBAToUVRow_Any_SSSE3;
     862           0 :     RGBAToYRow = RGBAToYRow_Any_SSSE3;
     863           0 :     if (IS_ALIGNED(width, 16)) {
     864           0 :       RGBAToUVRow = RGBAToUVRow_SSSE3;
     865           0 :       RGBAToYRow = RGBAToYRow_SSSE3;
     866             :     }
     867             :   }
     868             : #endif
     869             : #if defined(HAS_RGBATOYROW_NEON)
     870             :   if (TestCpuFlag(kCpuHasNEON)) {
     871             :     RGBAToYRow = RGBAToYRow_Any_NEON;
     872             :     if (IS_ALIGNED(width, 8)) {
     873             :       RGBAToYRow = RGBAToYRow_NEON;
     874             :     }
     875             :   }
     876             : #endif
     877             : #if defined(HAS_RGBATOUVROW_NEON)
     878             :   if (TestCpuFlag(kCpuHasNEON)) {
     879             :     RGBAToUVRow = RGBAToUVRow_Any_NEON;
     880             :     if (IS_ALIGNED(width, 16)) {
     881             :       RGBAToUVRow = RGBAToUVRow_NEON;
     882             :     }
     883             :   }
     884             : #endif
     885             : #if defined(HAS_RGBATOYROW_DSPR2)
     886             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     887             :     RGBAToYRow = RGBAToYRow_Any_DSPR2;
     888             :     if (IS_ALIGNED(width, 8)) {
     889             :       RGBAToYRow = RGBAToYRow_DSPR2;
     890             :     }
     891             :   }
     892             : #endif
     893             : #if defined(HAS_RGBATOUVROW_DSPR2)
     894             :   if (TestCpuFlag(kCpuHasDSPR2)) {
     895             :     RGBAToUVRow = RGBAToUVRow_Any_DSPR2;
     896             :     if (IS_ALIGNED(width, 16)) {
     897             :       RGBAToUVRow = RGBAToUVRow_DSPR2;
     898             :     }
     899             :   }
     900             : #endif
     901             : #if defined(HAS_RGBATOYROW_MSA)
     902             :   if (TestCpuFlag(kCpuHasMSA)) {
     903             :     RGBAToYRow = RGBAToYRow_Any_MSA;
     904             :     if (IS_ALIGNED(width, 16)) {
     905             :       RGBAToYRow = RGBAToYRow_MSA;
     906             :     }
     907             :   }
     908             : #endif
     909             : #if defined(HAS_RGBATOUVROW_MSA)
     910             :   if (TestCpuFlag(kCpuHasMSA)) {
     911             :     RGBAToUVRow = RGBAToUVRow_Any_MSA;
     912             :     if (IS_ALIGNED(width, 16)) {
     913             :       RGBAToUVRow = RGBAToUVRow_MSA;
     914             :     }
     915             :   }
     916             : #endif
     917             : 
     918           0 :   for (y = 0; y < height - 1; y += 2) {
     919           0 :     RGBAToUVRow(src_rgba, src_stride_rgba, dst_u, dst_v, width);
     920           0 :     RGBAToYRow(src_rgba, dst_y, width);
     921           0 :     RGBAToYRow(src_rgba + src_stride_rgba, dst_y + dst_stride_y, width);
     922           0 :     src_rgba += src_stride_rgba * 2;
     923           0 :     dst_y += dst_stride_y * 2;
     924           0 :     dst_u += dst_stride_u;
     925           0 :     dst_v += dst_stride_v;
     926             :   }
     927           0 :   if (height & 1) {
     928           0 :     RGBAToUVRow(src_rgba, 0, dst_u, dst_v, width);
     929           0 :     RGBAToYRow(src_rgba, dst_y, width);
     930             :   }
     931           0 :   return 0;
     932             : }
     933             : 
     934             : // Convert RGB24 to I420.
     935             : LIBYUV_API
     936           0 : int RGB24ToI420(const uint8* src_rgb24,
     937             :                 int src_stride_rgb24,
     938             :                 uint8* dst_y,
     939             :                 int dst_stride_y,
     940             :                 uint8* dst_u,
     941             :                 int dst_stride_u,
     942             :                 uint8* dst_v,
     943             :                 int dst_stride_v,
     944             :                 int width,
     945             :                 int height) {
     946             :   int y;
     947             : #if (defined(HAS_RGB24TOYROW_NEON) || defined(HAS_RGB24TOYROW_MSA))
     948             :   void (*RGB24ToUVRow)(const uint8* src_rgb24, int src_stride_rgb24,
     949             :                        uint8* dst_u, uint8* dst_v, int width) = RGB24ToUVRow_C;
     950             :   void (*RGB24ToYRow)(const uint8* src_rgb24, uint8* dst_y, int width) =
     951             :       RGB24ToYRow_C;
     952             : #else
     953             :   void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
     954           0 :       RGB24ToARGBRow_C;
     955             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
     956           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
     957             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
     958           0 :       ARGBToYRow_C;
     959             : #endif
     960           0 :   if (!src_rgb24 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
     961           0 :     return -1;
     962             :   }
     963             :   // Negative height means invert the image.
     964           0 :   if (height < 0) {
     965           0 :     height = -height;
     966           0 :     src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
     967           0 :     src_stride_rgb24 = -src_stride_rgb24;
     968             :   }
     969             : 
     970             : // Neon version does direct RGB24 to YUV.
     971             : #if defined(HAS_RGB24TOYROW_NEON)
     972             :   if (TestCpuFlag(kCpuHasNEON)) {
     973             :     RGB24ToUVRow = RGB24ToUVRow_Any_NEON;
     974             :     RGB24ToYRow = RGB24ToYRow_Any_NEON;
     975             :     if (IS_ALIGNED(width, 8)) {
     976             :       RGB24ToYRow = RGB24ToYRow_NEON;
     977             :       if (IS_ALIGNED(width, 16)) {
     978             :         RGB24ToUVRow = RGB24ToUVRow_NEON;
     979             :       }
     980             :     }
     981             :   }
     982             : #elif defined(HAS_RGB24TOYROW_MSA)
     983             :   if (TestCpuFlag(kCpuHasMSA)) {
     984             :     RGB24ToUVRow = RGB24ToUVRow_Any_MSA;
     985             :     RGB24ToYRow = RGB24ToYRow_Any_MSA;
     986             :     if (IS_ALIGNED(width, 16)) {
     987             :       RGB24ToYRow = RGB24ToYRow_MSA;
     988             :       RGB24ToUVRow = RGB24ToUVRow_MSA;
     989             :     }
     990             :   }
     991             : // Other platforms do intermediate conversion from RGB24 to ARGB.
     992             : #else
     993             : #if defined(HAS_RGB24TOARGBROW_SSSE3)
     994           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
     995           0 :     RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
     996           0 :     if (IS_ALIGNED(width, 16)) {
     997           0 :       RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
     998             :     }
     999             :   }
    1000             : #endif
    1001             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
    1002           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
    1003           0 :     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
    1004           0 :     ARGBToYRow = ARGBToYRow_Any_SSSE3;
    1005           0 :     if (IS_ALIGNED(width, 16)) {
    1006           0 :       ARGBToUVRow = ARGBToUVRow_SSSE3;
    1007           0 :       ARGBToYRow = ARGBToYRow_SSSE3;
    1008             :     }
    1009             :   }
    1010             : #endif
    1011             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
    1012           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
    1013           0 :     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
    1014           0 :     ARGBToYRow = ARGBToYRow_Any_AVX2;
    1015           0 :     if (IS_ALIGNED(width, 32)) {
    1016           0 :       ARGBToUVRow = ARGBToUVRow_AVX2;
    1017           0 :       ARGBToYRow = ARGBToYRow_AVX2;
    1018             :     }
    1019             :   }
    1020             : #endif
    1021             :   {
    1022             :     // Allocate 2 rows of ARGB.
    1023           0 :     const int kRowSize = (width * 4 + 31) & ~31;
    1024           0 :     align_buffer_64(row, kRowSize * 2);
    1025             : #endif
    1026             : 
    1027           0 :   for (y = 0; y < height - 1; y += 2) {
    1028             : #if (defined(HAS_RGB24TOYROW_NEON) || defined(HAS_RGB24TOYROW_MSA))
    1029             :     RGB24ToUVRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width);
    1030             :     RGB24ToYRow(src_rgb24, dst_y, width);
    1031             :     RGB24ToYRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width);
    1032             : #else
    1033           0 :     RGB24ToARGBRow(src_rgb24, row, width);
    1034           0 :     RGB24ToARGBRow(src_rgb24 + src_stride_rgb24, row + kRowSize, width);
    1035           0 :     ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
    1036           0 :     ARGBToYRow(row, dst_y, width);
    1037           0 :     ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
    1038             : #endif
    1039           0 :     src_rgb24 += src_stride_rgb24 * 2;
    1040           0 :     dst_y += dst_stride_y * 2;
    1041           0 :     dst_u += dst_stride_u;
    1042           0 :     dst_v += dst_stride_v;
    1043             :   }
    1044           0 :   if (height & 1) {
    1045             : #if (defined(HAS_RGB24TOYROW_NEON) || defined(HAS_RGB24TOYROW_MSA))
    1046             :     RGB24ToUVRow(src_rgb24, 0, dst_u, dst_v, width);
    1047             :     RGB24ToYRow(src_rgb24, dst_y, width);
    1048             : #else
    1049           0 :     RGB24ToARGBRow(src_rgb24, row, width);
    1050           0 :     ARGBToUVRow(row, 0, dst_u, dst_v, width);
    1051           0 :     ARGBToYRow(row, dst_y, width);
    1052             : #endif
    1053             :   }
    1054             : #if !(defined(HAS_RGB24TOYROW_NEON) || defined(HAS_RGB24TOYROW_MSA))
    1055           0 :   free_aligned_buffer_64(row);
    1056             : }
    1057             : #endif
    1058           0 : return 0;
    1059             : }
    1060             : 
    1061             : // Convert RAW to I420.
    1062             : LIBYUV_API
    1063           0 : int RAWToI420(const uint8* src_raw,
    1064             :               int src_stride_raw,
    1065             :               uint8* dst_y,
    1066             :               int dst_stride_y,
    1067             :               uint8* dst_u,
    1068             :               int dst_stride_u,
    1069             :               uint8* dst_v,
    1070             :               int dst_stride_v,
    1071             :               int width,
    1072             :               int height) {
    1073             :   int y;
    1074             : #if (defined(HAS_RAWTOYROW_NEON) || defined(HAS_RAWTOYROW_MSA))
    1075             :   void (*RAWToUVRow)(const uint8* src_raw, int src_stride_raw, uint8* dst_u,
    1076             :                      uint8* dst_v, int width) = RAWToUVRow_C;
    1077             :   void (*RAWToYRow)(const uint8* src_raw, uint8* dst_y, int width) =
    1078             :       RAWToYRow_C;
    1079             : #else
    1080             :   void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
    1081           0 :       RAWToARGBRow_C;
    1082             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
    1083           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
    1084             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
    1085           0 :       ARGBToYRow_C;
    1086             : #endif
    1087           0 :   if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
    1088           0 :     return -1;
    1089             :   }
    1090             :   // Negative height means invert the image.
    1091           0 :   if (height < 0) {
    1092           0 :     height = -height;
    1093           0 :     src_raw = src_raw + (height - 1) * src_stride_raw;
    1094           0 :     src_stride_raw = -src_stride_raw;
    1095             :   }
    1096             : 
    1097             : // Neon version does direct RAW to YUV.
    1098             : #if defined(HAS_RAWTOYROW_NEON)
    1099             :   if (TestCpuFlag(kCpuHasNEON)) {
    1100             :     RAWToUVRow = RAWToUVRow_Any_NEON;
    1101             :     RAWToYRow = RAWToYRow_Any_NEON;
    1102             :     if (IS_ALIGNED(width, 8)) {
    1103             :       RAWToYRow = RAWToYRow_NEON;
    1104             :       if (IS_ALIGNED(width, 16)) {
    1105             :         RAWToUVRow = RAWToUVRow_NEON;
    1106             :       }
    1107             :     }
    1108             :   }
    1109             : #elif defined(HAS_RAWTOYROW_MSA)
    1110             :   if (TestCpuFlag(kCpuHasMSA)) {
    1111             :     RAWToUVRow = RAWToUVRow_Any_MSA;
    1112             :     RAWToYRow = RAWToYRow_Any_MSA;
    1113             :     if (IS_ALIGNED(width, 16)) {
    1114             :       RAWToYRow = RAWToYRow_MSA;
    1115             :       RAWToUVRow = RAWToUVRow_MSA;
    1116             :     }
    1117             :   }
    1118             : // Other platforms do intermediate conversion from RAW to ARGB.
    1119             : #else
    1120             : #if defined(HAS_RAWTOARGBROW_SSSE3)
    1121           0 :     if (TestCpuFlag(kCpuHasSSSE3)) {
    1122           0 :       RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
    1123           0 :       if (IS_ALIGNED(width, 16)) {
    1124           0 :         RAWToARGBRow = RAWToARGBRow_SSSE3;
    1125             :       }
    1126             :     }
    1127             : #endif
    1128             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
    1129           0 :     if (TestCpuFlag(kCpuHasSSSE3)) {
    1130           0 :       ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
    1131           0 :       ARGBToYRow = ARGBToYRow_Any_SSSE3;
    1132           0 :       if (IS_ALIGNED(width, 16)) {
    1133           0 :         ARGBToUVRow = ARGBToUVRow_SSSE3;
    1134           0 :         ARGBToYRow = ARGBToYRow_SSSE3;
    1135             :       }
    1136             :     }
    1137             : #endif
    1138             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
    1139           0 :     if (TestCpuFlag(kCpuHasAVX2)) {
    1140           0 :       ARGBToUVRow = ARGBToUVRow_Any_AVX2;
    1141           0 :       ARGBToYRow = ARGBToYRow_Any_AVX2;
    1142           0 :       if (IS_ALIGNED(width, 32)) {
    1143           0 :         ARGBToUVRow = ARGBToUVRow_AVX2;
    1144           0 :         ARGBToYRow = ARGBToYRow_AVX2;
    1145             :       }
    1146             :     }
    1147             : #endif
    1148             : #if defined(HAS_RAWTOARGBROW_DSPR2)
    1149             :     if (TestCpuFlag(kCpuHasDSPR2)) {
    1150             :       RAWToARGBRow = RAWToARGBRow_Any_DSPR2;
    1151             :       if (IS_ALIGNED(width, 4)) {
    1152             :         RAWToARGBRow = RAWToARGBRow_DSPR2;
    1153             :       }
    1154             :     }
    1155             : #endif
    1156             :     {
    1157             :       // Allocate 2 rows of ARGB.
    1158           0 :       const int kRowSize = (width * 4 + 31) & ~31;
    1159           0 :       align_buffer_64(row, kRowSize * 2);
    1160             : #endif
    1161             : 
    1162           0 :   for (y = 0; y < height - 1; y += 2) {
    1163             : #if (defined(HAS_RAWTOYROW_NEON) || defined(HAS_RAWTOYROW_MSA))
    1164             :     RAWToUVRow(src_raw, src_stride_raw, dst_u, dst_v, width);
    1165             :     RAWToYRow(src_raw, dst_y, width);
    1166             :     RAWToYRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
    1167             : #else
    1168           0 :     RAWToARGBRow(src_raw, row, width);
    1169           0 :     RAWToARGBRow(src_raw + src_stride_raw, row + kRowSize, width);
    1170           0 :     ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
    1171           0 :     ARGBToYRow(row, dst_y, width);
    1172           0 :     ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
    1173             : #endif
    1174           0 :     src_raw += src_stride_raw * 2;
    1175           0 :     dst_y += dst_stride_y * 2;
    1176           0 :     dst_u += dst_stride_u;
    1177           0 :     dst_v += dst_stride_v;
    1178             :   }
    1179           0 :   if (height & 1) {
    1180             : #if (defined(HAS_RAWTOYROW_NEON) || defined(HAS_RAWTOYROW_MSA))
    1181             :     RAWToUVRow(src_raw, 0, dst_u, dst_v, width);
    1182             :     RAWToYRow(src_raw, dst_y, width);
    1183             : #else
    1184           0 :     RAWToARGBRow(src_raw, row, width);
    1185           0 :     ARGBToUVRow(row, 0, dst_u, dst_v, width);
    1186           0 :     ARGBToYRow(row, dst_y, width);
    1187             : #endif
    1188             :   }
    1189             : #if !(defined(HAS_RAWTOYROW_NEON) || defined(HAS_RAWTOYROW_MSA))
    1190           0 :   free_aligned_buffer_64(row);
    1191             : }
    1192             : #endif
    1193           0 : return 0;
    1194             : }
    1195             : 
    1196             : // Convert RGB565 to I420.
    1197             : LIBYUV_API
    1198           0 : int RGB565ToI420(const uint8* src_rgb565,
    1199             :                  int src_stride_rgb565,
    1200             :                  uint8* dst_y,
    1201             :                  int dst_stride_y,
    1202             :                  uint8* dst_u,
    1203             :                  int dst_stride_u,
    1204             :                  uint8* dst_v,
    1205             :                  int dst_stride_v,
    1206             :                  int width,
    1207             :                  int height) {
    1208             :   int y;
    1209             : #if (defined(HAS_RGB565TOYROW_NEON) || defined(HAS_RGB565TOYROW_MSA))
    1210             :   void (*RGB565ToUVRow)(const uint8* src_rgb565, int src_stride_rgb565,
    1211             :                         uint8* dst_u, uint8* dst_v, int width) =
    1212             :       RGB565ToUVRow_C;
    1213             :   void (*RGB565ToYRow)(const uint8* src_rgb565, uint8* dst_y, int width) =
    1214             :       RGB565ToYRow_C;
    1215             : #else
    1216             :   void (*RGB565ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
    1217           0 :       RGB565ToARGBRow_C;
    1218             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
    1219           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
    1220             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
    1221           0 :       ARGBToYRow_C;
    1222             : #endif
    1223           0 :   if (!src_rgb565 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
    1224           0 :     return -1;
    1225             :   }
    1226             :   // Negative height means invert the image.
    1227           0 :   if (height < 0) {
    1228           0 :     height = -height;
    1229           0 :     src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
    1230           0 :     src_stride_rgb565 = -src_stride_rgb565;
    1231             :   }
    1232             : 
    1233             : // Neon version does direct RGB565 to YUV.
    1234             : #if defined(HAS_RGB565TOYROW_NEON)
    1235             :   if (TestCpuFlag(kCpuHasNEON)) {
    1236             :     RGB565ToUVRow = RGB565ToUVRow_Any_NEON;
    1237             :     RGB565ToYRow = RGB565ToYRow_Any_NEON;
    1238             :     if (IS_ALIGNED(width, 8)) {
    1239             :       RGB565ToYRow = RGB565ToYRow_NEON;
    1240             :       if (IS_ALIGNED(width, 16)) {
    1241             :         RGB565ToUVRow = RGB565ToUVRow_NEON;
    1242             :       }
    1243             :     }
    1244             :   }
    1245             : #elif defined(HAS_RGB565TOYROW_MSA)
    1246             :   if (TestCpuFlag(kCpuHasMSA)) {
    1247             :     RGB565ToUVRow = RGB565ToUVRow_Any_MSA;
    1248             :     RGB565ToYRow = RGB565ToYRow_Any_MSA;
    1249             :     if (IS_ALIGNED(width, 16)) {
    1250             :       RGB565ToYRow = RGB565ToYRow_MSA;
    1251             :       RGB565ToUVRow = RGB565ToUVRow_MSA;
    1252             :     }
    1253             :   }
    1254             : // Other platforms do intermediate conversion from RGB565 to ARGB.
    1255             : #else
    1256             : #if defined(HAS_RGB565TOARGBROW_SSE2)
    1257           0 :       if (TestCpuFlag(kCpuHasSSE2)) {
    1258           0 :         RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
    1259           0 :         if (IS_ALIGNED(width, 8)) {
    1260           0 :           RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
    1261             :         }
    1262             :       }
    1263             : #endif
    1264             : #if defined(HAS_RGB565TOARGBROW_AVX2)
    1265             :       if (TestCpuFlag(kCpuHasAVX2)) {
    1266             :         RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
    1267             :         if (IS_ALIGNED(width, 16)) {
    1268             :           RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
    1269             :         }
    1270             :       }
    1271             : #endif
    1272             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
    1273           0 :       if (TestCpuFlag(kCpuHasSSSE3)) {
    1274           0 :         ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
    1275           0 :         ARGBToYRow = ARGBToYRow_Any_SSSE3;
    1276           0 :         if (IS_ALIGNED(width, 16)) {
    1277           0 :           ARGBToUVRow = ARGBToUVRow_SSSE3;
    1278           0 :           ARGBToYRow = ARGBToYRow_SSSE3;
    1279             :         }
    1280             :       }
    1281             : #endif
    1282             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
    1283           0 :       if (TestCpuFlag(kCpuHasAVX2)) {
    1284           0 :         ARGBToUVRow = ARGBToUVRow_Any_AVX2;
    1285           0 :         ARGBToYRow = ARGBToYRow_Any_AVX2;
    1286           0 :         if (IS_ALIGNED(width, 32)) {
    1287           0 :           ARGBToUVRow = ARGBToUVRow_AVX2;
    1288           0 :           ARGBToYRow = ARGBToYRow_AVX2;
    1289             :         }
    1290             :       }
    1291             : #endif
    1292             : #if defined(HAS_RGB565TOARGBROW_DSPR2)
    1293             :       if (TestCpuFlag(kCpuHasDSPR2)) {
    1294             :         RGB565ToARGBRow = RGB565ToARGBRow_Any_DSPR2;
    1295             :         if (IS_ALIGNED(width, 8)) {
    1296             :           RGB565ToARGBRow = RGB565ToARGBRow_DSPR2;
    1297             :         }
    1298             :       }
    1299             : #endif
    1300             :       {
    1301             :         // Allocate 2 rows of ARGB.
    1302           0 :         const int kRowSize = (width * 4 + 31) & ~31;
    1303           0 :         align_buffer_64(row, kRowSize * 2);
    1304             : #endif
    1305             : 
    1306           0 :   for (y = 0; y < height - 1; y += 2) {
    1307             : #if (defined(HAS_RGB565TOYROW_NEON) || defined(HAS_RGB565TOYROW_MSA))
    1308             :     RGB565ToUVRow(src_rgb565, src_stride_rgb565, dst_u, dst_v, width);
    1309             :     RGB565ToYRow(src_rgb565, dst_y, width);
    1310             :     RGB565ToYRow(src_rgb565 + src_stride_rgb565, dst_y + dst_stride_y, width);
    1311             : #else
    1312           0 :     RGB565ToARGBRow(src_rgb565, row, width);
    1313           0 :     RGB565ToARGBRow(src_rgb565 + src_stride_rgb565, row + kRowSize, width);
    1314           0 :     ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
    1315           0 :     ARGBToYRow(row, dst_y, width);
    1316           0 :     ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
    1317             : #endif
    1318           0 :     src_rgb565 += src_stride_rgb565 * 2;
    1319           0 :     dst_y += dst_stride_y * 2;
    1320           0 :     dst_u += dst_stride_u;
    1321           0 :     dst_v += dst_stride_v;
    1322             :   }
    1323           0 :   if (height & 1) {
    1324             : #if (defined(HAS_RGB565TOYROW_NEON) || defined(HAS_RGB565TOYROW_MSA))
    1325             :     RGB565ToUVRow(src_rgb565, 0, dst_u, dst_v, width);
    1326             :     RGB565ToYRow(src_rgb565, dst_y, width);
    1327             : #else
    1328           0 :     RGB565ToARGBRow(src_rgb565, row, width);
    1329           0 :     ARGBToUVRow(row, 0, dst_u, dst_v, width);
    1330           0 :     ARGBToYRow(row, dst_y, width);
    1331             : #endif
    1332             :   }
    1333             : #if !(defined(HAS_RGB565TOYROW_NEON) || defined(HAS_RGB565TOYROW_MSA))
    1334           0 :   free_aligned_buffer_64(row);
    1335             : }
    1336             : #endif
    1337           0 : return 0;
    1338             : }
    1339             : 
    1340             : // Convert ARGB1555 to I420.
    1341             : LIBYUV_API
    1342           0 : int ARGB1555ToI420(const uint8* src_argb1555,
    1343             :                    int src_stride_argb1555,
    1344             :                    uint8* dst_y,
    1345             :                    int dst_stride_y,
    1346             :                    uint8* dst_u,
    1347             :                    int dst_stride_u,
    1348             :                    uint8* dst_v,
    1349             :                    int dst_stride_v,
    1350             :                    int width,
    1351             :                    int height) {
    1352             :   int y;
    1353             : #if (defined(HAS_ARGB1555TOYROW_NEON) || defined(HAS_ARGB1555TOYROW_MSA))
    1354             :   void (*ARGB1555ToUVRow)(const uint8* src_argb1555, int src_stride_argb1555,
    1355             :                           uint8* dst_u, uint8* dst_v, int width) =
    1356             :       ARGB1555ToUVRow_C;
    1357             :   void (*ARGB1555ToYRow)(const uint8* src_argb1555, uint8* dst_y, int width) =
    1358             :       ARGB1555ToYRow_C;
    1359             : #else
    1360             :   void (*ARGB1555ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
    1361           0 :       ARGB1555ToARGBRow_C;
    1362             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
    1363           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
    1364             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
    1365           0 :       ARGBToYRow_C;
    1366             : #endif
    1367           0 :   if (!src_argb1555 || !dst_y || !dst_u || !dst_v || width <= 0 ||
    1368             :       height == 0) {
    1369           0 :     return -1;
    1370             :   }
    1371             :   // Negative height means invert the image.
    1372           0 :   if (height < 0) {
    1373           0 :     height = -height;
    1374           0 :     src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
    1375           0 :     src_stride_argb1555 = -src_stride_argb1555;
    1376             :   }
    1377             : 
    1378             : // Neon version does direct ARGB1555 to YUV.
    1379             : #if defined(HAS_ARGB1555TOYROW_NEON)
    1380             :   if (TestCpuFlag(kCpuHasNEON)) {
    1381             :     ARGB1555ToUVRow = ARGB1555ToUVRow_Any_NEON;
    1382             :     ARGB1555ToYRow = ARGB1555ToYRow_Any_NEON;
    1383             :     if (IS_ALIGNED(width, 8)) {
    1384             :       ARGB1555ToYRow = ARGB1555ToYRow_NEON;
    1385             :       if (IS_ALIGNED(width, 16)) {
    1386             :         ARGB1555ToUVRow = ARGB1555ToUVRow_NEON;
    1387             :       }
    1388             :     }
    1389             :   }
    1390             : #elif defined(HAS_ARGB1555TOYROW_MSA)
    1391             :   if (TestCpuFlag(kCpuHasMSA)) {
    1392             :     ARGB1555ToUVRow = ARGB1555ToUVRow_Any_MSA;
    1393             :     ARGB1555ToYRow = ARGB1555ToYRow_Any_MSA;
    1394             :     if (IS_ALIGNED(width, 16)) {
    1395             :       ARGB1555ToYRow = ARGB1555ToYRow_MSA;
    1396             :       ARGB1555ToUVRow = ARGB1555ToUVRow_MSA;
    1397             :     }
    1398             :   }
    1399             : // Other platforms do intermediate conversion from ARGB1555 to ARGB.
    1400             : #else
    1401             : #if defined(HAS_ARGB1555TOARGBROW_SSE2)
    1402           0 :         if (TestCpuFlag(kCpuHasSSE2)) {
    1403           0 :           ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
    1404           0 :           if (IS_ALIGNED(width, 8)) {
    1405           0 :             ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
    1406             :           }
    1407             :         }
    1408             : #endif
    1409             : #if defined(HAS_ARGB1555TOARGBROW_AVX2)
    1410             :         if (TestCpuFlag(kCpuHasAVX2)) {
    1411             :           ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
    1412             :           if (IS_ALIGNED(width, 16)) {
    1413             :             ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
    1414             :           }
    1415             :         }
    1416             : #endif
    1417             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
    1418           0 :         if (TestCpuFlag(kCpuHasSSSE3)) {
    1419           0 :           ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
    1420           0 :           ARGBToYRow = ARGBToYRow_Any_SSSE3;
    1421           0 :           if (IS_ALIGNED(width, 16)) {
    1422           0 :             ARGBToUVRow = ARGBToUVRow_SSSE3;
    1423           0 :             ARGBToYRow = ARGBToYRow_SSSE3;
    1424             :           }
    1425             :         }
    1426             : #endif
    1427             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
    1428           0 :         if (TestCpuFlag(kCpuHasAVX2)) {
    1429           0 :           ARGBToUVRow = ARGBToUVRow_Any_AVX2;
    1430           0 :           ARGBToYRow = ARGBToYRow_Any_AVX2;
    1431           0 :           if (IS_ALIGNED(width, 32)) {
    1432           0 :             ARGBToUVRow = ARGBToUVRow_AVX2;
    1433           0 :             ARGBToYRow = ARGBToYRow_AVX2;
    1434             :           }
    1435             :         }
    1436             : #endif
    1437             :         {
    1438             :           // Allocate 2 rows of ARGB.
    1439           0 :           const int kRowSize = (width * 4 + 31) & ~31;
    1440           0 :           align_buffer_64(row, kRowSize * 2);
    1441             : #endif
    1442             : 
    1443           0 :   for (y = 0; y < height - 1; y += 2) {
    1444             : #if (defined(HAS_ARGB1555TOYROW_NEON) || defined(HAS_ARGB1555TOYROW_MSA))
    1445             :     ARGB1555ToUVRow(src_argb1555, src_stride_argb1555, dst_u, dst_v, width);
    1446             :     ARGB1555ToYRow(src_argb1555, dst_y, width);
    1447             :     ARGB1555ToYRow(src_argb1555 + src_stride_argb1555, dst_y + dst_stride_y,
    1448             :                    width);
    1449             : #else
    1450           0 :     ARGB1555ToARGBRow(src_argb1555, row, width);
    1451           0 :     ARGB1555ToARGBRow(src_argb1555 + src_stride_argb1555, row + kRowSize,
    1452           0 :                       width);
    1453           0 :     ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
    1454           0 :     ARGBToYRow(row, dst_y, width);
    1455           0 :     ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
    1456             : #endif
    1457           0 :     src_argb1555 += src_stride_argb1555 * 2;
    1458           0 :     dst_y += dst_stride_y * 2;
    1459           0 :     dst_u += dst_stride_u;
    1460           0 :     dst_v += dst_stride_v;
    1461             :   }
    1462           0 :   if (height & 1) {
    1463             : #if (defined(HAS_ARGB1555TOYROW_NEON) || defined(HAS_ARGB1555TOYROW_MSA))
    1464             :     ARGB1555ToUVRow(src_argb1555, 0, dst_u, dst_v, width);
    1465             :     ARGB1555ToYRow(src_argb1555, dst_y, width);
    1466             : #else
    1467           0 :     ARGB1555ToARGBRow(src_argb1555, row, width);
    1468           0 :     ARGBToUVRow(row, 0, dst_u, dst_v, width);
    1469           0 :     ARGBToYRow(row, dst_y, width);
    1470             : #endif
    1471             :   }
    1472             : #if !(defined(HAS_ARGB1555TOYROW_NEON) || defined(HAS_ARGB1555TOYROW_MSA))
    1473           0 :   free_aligned_buffer_64(row);
    1474             : }
    1475             : #endif
    1476           0 : return 0;
    1477             : }
    1478             : 
    1479             : // Convert ARGB4444 to I420.
    1480             : LIBYUV_API
    1481           0 : int ARGB4444ToI420(const uint8* src_argb4444,
    1482             :                    int src_stride_argb4444,
    1483             :                    uint8* dst_y,
    1484             :                    int dst_stride_y,
    1485             :                    uint8* dst_u,
    1486             :                    int dst_stride_u,
    1487             :                    uint8* dst_v,
    1488             :                    int dst_stride_v,
    1489             :                    int width,
    1490             :                    int height) {
    1491             :   int y;
    1492             : #if defined(HAS_ARGB4444TOYROW_NEON)
    1493             :   void (*ARGB4444ToUVRow)(const uint8* src_argb4444, int src_stride_argb4444,
    1494             :                           uint8* dst_u, uint8* dst_v, int width) =
    1495             :       ARGB4444ToUVRow_C;
    1496             :   void (*ARGB4444ToYRow)(const uint8* src_argb4444, uint8* dst_y, int width) =
    1497             :       ARGB4444ToYRow_C;
    1498             : #else
    1499             :   void (*ARGB4444ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
    1500           0 :       ARGB4444ToARGBRow_C;
    1501             :   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u,
    1502           0 :                       uint8* dst_v, int width) = ARGBToUVRow_C;
    1503             :   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) =
    1504           0 :       ARGBToYRow_C;
    1505             : #endif
    1506           0 :   if (!src_argb4444 || !dst_y || !dst_u || !dst_v || width <= 0 ||
    1507             :       height == 0) {
    1508           0 :     return -1;
    1509             :   }
    1510             :   // Negative height means invert the image.
    1511           0 :   if (height < 0) {
    1512           0 :     height = -height;
    1513           0 :     src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
    1514           0 :     src_stride_argb4444 = -src_stride_argb4444;
    1515             :   }
    1516             : 
    1517             : // Neon version does direct ARGB4444 to YUV.
    1518             : #if defined(HAS_ARGB4444TOYROW_NEON)
    1519             :   if (TestCpuFlag(kCpuHasNEON)) {
    1520             :     ARGB4444ToUVRow = ARGB4444ToUVRow_Any_NEON;
    1521             :     ARGB4444ToYRow = ARGB4444ToYRow_Any_NEON;
    1522             :     if (IS_ALIGNED(width, 8)) {
    1523             :       ARGB4444ToYRow = ARGB4444ToYRow_NEON;
    1524             :       if (IS_ALIGNED(width, 16)) {
    1525             :         ARGB4444ToUVRow = ARGB4444ToUVRow_NEON;
    1526             :       }
    1527             :     }
    1528             :   }
    1529             : // Other platforms do intermediate conversion from ARGB4444 to ARGB.
    1530             : #else
    1531             : #if defined(HAS_ARGB4444TOARGBROW_SSE2)
    1532           0 :   if (TestCpuFlag(kCpuHasSSE2)) {
    1533           0 :     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
    1534           0 :     if (IS_ALIGNED(width, 8)) {
    1535           0 :       ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
    1536             :     }
    1537             :   }
    1538             : #endif
    1539             : #if defined(HAS_ARGB4444TOARGBROW_AVX2)
    1540             :   if (TestCpuFlag(kCpuHasAVX2)) {
    1541             :     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
    1542             :     if (IS_ALIGNED(width, 16)) {
    1543             :       ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
    1544             :     }
    1545             :   }
    1546             : #endif
    1547             : #if defined(HAS_ARGB4444TOARGBROW_MSA)
    1548             :   if (TestCpuFlag(kCpuHasMSA)) {
    1549             :     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
    1550             :     if (IS_ALIGNED(width, 16)) {
    1551             :       ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
    1552             :     }
    1553             :   }
    1554             : #endif
    1555             : #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
    1556           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
    1557           0 :     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
    1558           0 :     ARGBToYRow = ARGBToYRow_Any_SSSE3;
    1559           0 :     if (IS_ALIGNED(width, 16)) {
    1560           0 :       ARGBToUVRow = ARGBToUVRow_SSSE3;
    1561           0 :       ARGBToYRow = ARGBToYRow_SSSE3;
    1562             :     }
    1563             :   }
    1564             : #endif
    1565             : #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
    1566           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
    1567           0 :     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
    1568           0 :     ARGBToYRow = ARGBToYRow_Any_AVX2;
    1569           0 :     if (IS_ALIGNED(width, 32)) {
    1570           0 :       ARGBToUVRow = ARGBToUVRow_AVX2;
    1571           0 :       ARGBToYRow = ARGBToYRow_AVX2;
    1572             :     }
    1573             :   }
    1574             : #endif
    1575             : #if defined(HAS_ARGBTOYROW_MSA)
    1576             :   if (TestCpuFlag(kCpuHasMSA)) {
    1577             :     ARGBToUVRow = ARGBToUVRow_Any_MSA;
    1578             :     ARGBToYRow = ARGBToYRow_Any_MSA;
    1579             :     if (IS_ALIGNED(width, 16)) {
    1580             :       ARGBToYRow = ARGBToYRow_MSA;
    1581             :       if (IS_ALIGNED(width, 32)) {
    1582             :         ARGBToUVRow = ARGBToUVRow_MSA;
    1583             :       }
    1584             :     }
    1585             :   }
    1586             : #endif
    1587             :   {
    1588             :     // Allocate 2 rows of ARGB.
    1589           0 :     const int kRowSize = (width * 4 + 31) & ~31;
    1590           0 :     align_buffer_64(row, kRowSize * 2);
    1591             : #endif
    1592             : 
    1593           0 :   for (y = 0; y < height - 1; y += 2) {
    1594             : #if defined(HAS_ARGB4444TOYROW_NEON)
    1595             :     ARGB4444ToUVRow(src_argb4444, src_stride_argb4444, dst_u, dst_v, width);
    1596             :     ARGB4444ToYRow(src_argb4444, dst_y, width);
    1597             :     ARGB4444ToYRow(src_argb4444 + src_stride_argb4444, dst_y + dst_stride_y,
    1598             :                    width);
    1599             : #else
    1600           0 :       ARGB4444ToARGBRow(src_argb4444, row, width);
    1601           0 :       ARGB4444ToARGBRow(src_argb4444 + src_stride_argb4444, row + kRowSize,
    1602           0 :                         width);
    1603           0 :       ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
    1604           0 :       ARGBToYRow(row, dst_y, width);
    1605           0 :       ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
    1606             : #endif
    1607           0 :     src_argb4444 += src_stride_argb4444 * 2;
    1608           0 :     dst_y += dst_stride_y * 2;
    1609           0 :     dst_u += dst_stride_u;
    1610           0 :     dst_v += dst_stride_v;
    1611             :   }
    1612           0 :   if (height & 1) {
    1613             : #if defined(HAS_ARGB4444TOYROW_NEON)
    1614             :     ARGB4444ToUVRow(src_argb4444, 0, dst_u, dst_v, width);
    1615             :     ARGB4444ToYRow(src_argb4444, dst_y, width);
    1616             : #else
    1617           0 :       ARGB4444ToARGBRow(src_argb4444, row, width);
    1618           0 :       ARGBToUVRow(row, 0, dst_u, dst_v, width);
    1619           0 :       ARGBToYRow(row, dst_y, width);
    1620             : #endif
    1621             :   }
    1622             : #if !defined(HAS_ARGB4444TOYROW_NEON)
    1623           0 :   free_aligned_buffer_64(row);
    1624             : }
    1625             : #endif
    1626           0 : return 0;
    1627             : }
    1628             : 
    1629           0 : static void SplitPixels(const uint8* src_u,
    1630             :                         int src_pixel_stride_uv,
    1631             :                         uint8* dst_u,
    1632             :                         int width) {
    1633             :   int i;
    1634           0 :   for (i = 0; i < width; ++i) {
    1635           0 :     *dst_u = *src_u;
    1636           0 :     ++dst_u;
    1637           0 :     src_u += src_pixel_stride_uv;
    1638             :   }
    1639           0 : }
    1640             : 
    1641             : // Convert Android420 to I420.
    1642             : LIBYUV_API
    1643           0 : int Android420ToI420(const uint8* src_y,
    1644             :                      int src_stride_y,
    1645             :                      const uint8* src_u,
    1646             :                      int src_stride_u,
    1647             :                      const uint8* src_v,
    1648             :                      int src_stride_v,
    1649             :                      int src_pixel_stride_uv,
    1650             :                      uint8* dst_y,
    1651             :                      int dst_stride_y,
    1652             :                      uint8* dst_u,
    1653             :                      int dst_stride_u,
    1654             :                      uint8* dst_v,
    1655             :                      int dst_stride_v,
    1656             :                      int width,
    1657             :                      int height) {
    1658             :   int y;
    1659           0 :   const ptrdiff_t vu_off = src_v - src_u;
    1660           0 :   int halfwidth = (width + 1) >> 1;
    1661           0 :   int halfheight = (height + 1) >> 1;
    1662           0 :   if (!src_u || !src_v || !dst_u || !dst_v || width <= 0 || height == 0) {
    1663           0 :     return -1;
    1664             :   }
    1665             :   // Negative height means invert the image.
    1666           0 :   if (height < 0) {
    1667           0 :     height = -height;
    1668           0 :     halfheight = (height + 1) >> 1;
    1669           0 :     src_y = src_y + (height - 1) * src_stride_y;
    1670           0 :     src_u = src_u + (halfheight - 1) * src_stride_u;
    1671           0 :     src_v = src_v + (halfheight - 1) * src_stride_v;
    1672           0 :     src_stride_y = -src_stride_y;
    1673           0 :     src_stride_u = -src_stride_u;
    1674           0 :     src_stride_v = -src_stride_v;
    1675             :   }
    1676             : 
    1677           0 :   if (dst_y) {
    1678           0 :     CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
    1679             :   }
    1680             : 
    1681             :   // Copy UV planes as is - I420
    1682           0 :   if (src_pixel_stride_uv == 1) {
    1683           0 :     CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
    1684           0 :     CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
    1685           0 :     return 0;
    1686             :     // Split UV planes - NV21
    1687           0 :   } else if (src_pixel_stride_uv == 2 && vu_off == -1 &&
    1688             :              src_stride_u == src_stride_v) {
    1689             :     SplitUVPlane(src_v, src_stride_v, dst_v, dst_stride_v, dst_u, dst_stride_u,
    1690           0 :                  halfwidth, halfheight);
    1691           0 :     return 0;
    1692             :     // Split UV planes - NV12
    1693           0 :   } else if (src_pixel_stride_uv == 2 && vu_off == 1 &&
    1694             :              src_stride_u == src_stride_v) {
    1695             :     SplitUVPlane(src_u, src_stride_u, dst_u, dst_stride_u, dst_v, dst_stride_v,
    1696           0 :                  halfwidth, halfheight);
    1697           0 :     return 0;
    1698             :   }
    1699             : 
    1700           0 :   for (y = 0; y < halfheight; ++y) {
    1701           0 :     SplitPixels(src_u, src_pixel_stride_uv, dst_u, halfwidth);
    1702           0 :     SplitPixels(src_v, src_pixel_stride_uv, dst_v, halfwidth);
    1703           0 :     src_u += src_stride_u;
    1704           0 :     src_v += src_stride_v;
    1705           0 :     dst_u += dst_stride_u;
    1706           0 :     dst_v += dst_stride_v;
    1707             :   }
    1708           0 :   return 0;
    1709             : }
    1710             : 
    1711             : #ifdef __cplusplus
    1712             : }  // extern "C"
    1713             : }  // namespace libyuv
    1714             : #endif

Generated by: LCOV version 1.13