1c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com/*
2b0c97975894a5eebebf9d93147cdd941a3accb63fbarchard@google.com *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com *
4c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com *  Use of this source code is governed by a BSD-style license
5c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com *  that can be found in the LICENSE file in the root of the source
6c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com *  tree. An additional intellectual property rights grant can be found
7cde587092fef0dbed2c35602f30b79e7b892e766fbarchard@google.com *  in the file PATENTS. All contributing project authors may
8c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com *  be found in the AUTHORS file in the root of the source tree.
9c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com */
10c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
11c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#include "libyuv/convert_argb.h"
12c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
13c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#include "libyuv/cpu_id.h"
14c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#include "libyuv/format_conversion.h"
15c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#ifdef HAVE_JPEG
16c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#include "libyuv/mjpeg_decoder.h"
17c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
18c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#include "libyuv/rotate_argb.h"
19142f6c4ed5eaeec0176f255e64bac8d8c70b42e1fbarchard@google.com#include "libyuv/row.h"
20d7c7bfac57ce1775d6424865d8d4ec8b278070bafbarchard@google.com#include "libyuv/video_common.h"
21c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
22c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#ifdef __cplusplus
23c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comnamespace libyuv {
24c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comextern "C" {
25c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
26c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
27c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Copy ARGB with optional flipping
28fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
29c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint ARGBCopy(const uint8* src_argb, int src_stride_argb,
30c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com             uint8* dst_argb, int dst_stride_argb,
31c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com             int width, int height) {
3225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_argb || !dst_argb ||
33c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      width <= 0 || height == 0) {
34c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    return -1;
35c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
36c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
37c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
38c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
39c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_argb = src_argb + (height - 1) * src_stride_argb;
40c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_argb = -src_stride_argb;
41c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
42c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
43c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
44c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com            width * 4, height);
45c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
46c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
47c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
48c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert I444 to ARGB.
49fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
50c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint I444ToARGB(const uint8* src_y, int src_stride_y,
51c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_u, int src_stride_u,
52c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_v, int src_stride_v,
53c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
54c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
558798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
568798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*I444ToARGBRow)(const uint8* y_buf,
578798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* u_buf,
588798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* v_buf,
598798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
608798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = I444ToARGBRow_C;
6125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_u || !src_v ||
6225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_argb ||
6325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
64bc81e2dc0547addddfa75c938cf17380fd0980a6fbarchard@google.com    return -1;
65bc81e2dc0547addddfa75c938cf17380fd0980a6fbarchard@google.com  }
66c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
67c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
68c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
69c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
70c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
71c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
72095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
73518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_y == width &&
74518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_u == width &&
75518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_v == width &&
76518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
77095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
78095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
79095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
80518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
81c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_I444TOARGBROW_SSSE3)
82c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
83c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
84c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
85c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      I444ToARGBRow = I444ToARGBRow_Unaligned_SSSE3;
86c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
87c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        I444ToARGBRow = I444ToARGBRow_SSSE3;
88c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
89c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
90c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
91b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com#elif defined(HAS_I444TOARGBROW_NEON)
92b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
93b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    I444ToARGBRow = I444ToARGBRow_Any_NEON;
94b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
95b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com      I444ToARGBRow = I444ToARGBRow_NEON;
96b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    }
97b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com  }
98c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
99c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
1008798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
101c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I444ToARGBRow(src_y, src_u, src_v, dst_argb, width);
102c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
103c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
104c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_u += src_stride_u;
105c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_v += src_stride_v;
106c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
107c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
108c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
109c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
110c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert I422 to ARGB.
111fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
112c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint I422ToARGB(const uint8* src_y, int src_stride_y,
113c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_u, int src_stride_u,
114c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_v, int src_stride_v,
115c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
116c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
1178798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
1188798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*I422ToARGBRow)(const uint8* y_buf,
1198798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* u_buf,
1208798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* v_buf,
1218798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
1228798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = I422ToARGBRow_C;
12325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_u || !src_v ||
12425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_argb ||
12525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
12625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
12725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
128c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
129c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
130c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
131c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
132c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
133c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
134095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
135518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_y == width &&
136518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_u * 2 == width &&
137518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_v * 2 == width &&
138518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
139095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
140095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
141095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
142518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
1438d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com#if defined(HAS_I422TOARGBROW_SSSE3)
144c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
145c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
146c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
147c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3;
148c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
149c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        I422ToARGBRow = I422ToARGBRow_SSSE3;
150c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
151c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
152c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
153c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#endif
154c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#if defined(HAS_I422TOARGBROW_AVX2)
155c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && width >= 16) {
156c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com    I422ToARGBRow = I422ToARGBRow_Any_AVX2;
157c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
158c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com      I422ToARGBRow = I422ToARGBRow_AVX2;
159c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com    }
160c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com  }
161c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#endif
162c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#if defined(HAS_I422TOARGBROW_NEON)
1638d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1648d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    I422ToARGBRow = I422ToARGBRow_Any_NEON;
1658d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
1668d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com      I422ToARGBRow = I422ToARGBRow_NEON;
1678d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    }
1688d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  }
169c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#endif
170c297d103f199dc8c9565ea0f35bdb0832a9d10b8fbarchard@google.com#if defined(HAS_I422TOARGBROW_MIPS_DSPR2)
1716c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
1726c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
1736c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com      IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
1746c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com      IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
1756c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
1766c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com    I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2;
1776c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com  }
178c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
179c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
1808798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
181c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
182c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
183c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
184c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_u += src_stride_u;
185c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_v += src_stride_v;
186c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
187c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
188c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
189c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
190c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert I411 to ARGB.
191fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
192c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint I411ToARGB(const uint8* src_y, int src_stride_y,
193c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_u, int src_stride_u,
194c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_v, int src_stride_v,
195c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
196c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
1978798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
1988798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*I411ToARGBRow)(const uint8* y_buf,
1998798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* u_buf,
2008798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* v_buf,
2018798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
2028798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = I411ToARGBRow_C;
20325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_u || !src_v ||
20425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_argb ||
20525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
20625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
20725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
208c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
209c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
210c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
211c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
212c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
213c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
214095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
215518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_y == width &&
216518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_u * 4 == width &&
217518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      src_stride_v * 4 == width &&
218518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
219095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
220095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
221095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
222518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
223c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_I411TOARGBROW_SSSE3)
224c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
225c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I411ToARGBRow = I411ToARGBRow_Any_SSSE3;
226c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
227c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      I411ToARGBRow = I411ToARGBRow_Unaligned_SSSE3;
228c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
229c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        I411ToARGBRow = I411ToARGBRow_SSSE3;
230c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
231c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
232c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
233b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com#elif defined(HAS_I411TOARGBROW_NEON)
234b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
235b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    I411ToARGBRow = I411ToARGBRow_Any_NEON;
236b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
237b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com      I411ToARGBRow = I411ToARGBRow_NEON;
238b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com    }
239b883ce6e2c15627ab9fa95e1bb6eca0dc399d364fbarchard@google.com  }
240c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
241c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
2428798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
243c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I411ToARGBRow(src_y, src_u, src_v, dst_argb, width);
244c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
245c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
246c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_u += src_stride_u;
247c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_v += src_stride_v;
248c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
249c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
250c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
251c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
252c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert I400 to ARGB.
253fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
254c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint I400ToARGB_Reference(const uint8* src_y, int src_stride_y,
255c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                         uint8* dst_argb, int dst_stride_argb,
256c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                         int width, int height) {
2578798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
2588798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*YToARGBRow)(const uint8* y_buf,
2598798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                     uint8* rgb_buf,
2608798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                     int width) = YToARGBRow_C;
26125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !dst_argb ||
26225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
26325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
26425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
265c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
266c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
267c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
268c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
269c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
270c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
271095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
272518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_y == width &&
273518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
274095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
275095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
276095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y = dst_stride_argb = 0;
277518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
278c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_YTOARGBROW_SSE2)
2791d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
280c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
2811d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    YToARGBRow = YToARGBRow_Any_SSE2;
2821d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
2831d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com      YToARGBRow = YToARGBRow_SSE2;
2841d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    }
285c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
28630859f75f28c2435753d33eb7a48ccab169feb6dfbarchard@google.com#elif defined(HAS_YTOARGBROW_NEON)
2871d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
2881d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    YToARGBRow = YToARGBRow_Any_NEON;
2891d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
2901d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com      YToARGBRow = YToARGBRow_NEON;
2911d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com    }
29230859f75f28c2435753d33eb7a48ccab169feb6dfbarchard@google.com  }
293c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
294c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
2958798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
296c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    YToARGBRow(src_y, dst_argb, width);
297c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
298c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
299c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
300c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
301c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
302c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
303c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert I400 to ARGB.
304fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
305c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint I400ToARGB(const uint8* src_y, int src_stride_y,
306c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
307c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
3088798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
3098798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*I400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) =
3108798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      I400ToARGBRow_C;
31125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !dst_argb ||
31225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
31325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
31425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
31525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
316c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
317c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
318c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y = src_y + (height - 1) * src_stride_y;
319c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_y = -src_stride_y;
320c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
321095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
322518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_y == width &&
323518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
324095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
325095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
326095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y = dst_stride_argb = 0;
327518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
328c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_I400TOARGBROW_SSE2)
32900b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
33000b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    I400ToARGBRow = I400ToARGBRow_Any_SSE2;
33100b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
33200b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com      I400ToARGBRow = I400ToARGBRow_Unaligned_SSE2;
33300b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
33400b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com        I400ToARGBRow = I400ToARGBRow_SSE2;
33500b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com      }
33600b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    }
33700b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com  }
33800b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com#elif defined(HAS_I400TOARGBROW_NEON)
33900b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
34000b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    I400ToARGBRow = I400ToARGBRow_Any_NEON;
34100b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
34200b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com      I400ToARGBRow = I400ToARGBRow_NEON;
34300b69a2fe66183be5f72cb80c59f22e137b45359fbarchard@google.com    }
344c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
345c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
3468798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
347c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    I400ToARGBRow(src_y, dst_argb, width);
348c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
349c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
350c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
351c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
352c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
353c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
3541096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com// Shuffle table for converting BGRA to ARGB.
355f2aa91a1ac08703d5a22af7fa48c59eba8eb397afbarchard@google.comstatic uvec8 kShuffleMaskBGRAToARGB = {
3561096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u
3571096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com};
3581096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com
3591096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com// Shuffle table for converting ABGR to ARGB.
360f2aa91a1ac08703d5a22af7fa48c59eba8eb397afbarchard@google.comstatic uvec8 kShuffleMaskABGRToARGB = {
3611096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u
3621096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com};
3631096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com
3641096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com// Shuffle table for converting RGBA to ARGB.
365f2aa91a1ac08703d5a22af7fa48c59eba8eb397afbarchard@google.comstatic uvec8 kShuffleMaskRGBAToARGB = {
3661096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u
3671096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com};
3681096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com
369d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com// Convert BGRA to ARGB.
370fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
371d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.comint BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
372c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
373c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
3741096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  return ARGBShuffle(src_bgra, src_stride_bgra,
3751096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     dst_argb, dst_stride_argb,
376a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com                     (const uint8*)(&kShuffleMaskBGRAToARGB),
3771096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     width, height);
378c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
379c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
3802a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com// Convert ARGB to BGRA (same as BGRAToARGB).
3812a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.comLIBYUV_API
3822a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.comint ARGBToBGRA(const uint8* src_bgra, int src_stride_bgra,
3832a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
3842a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com               int width, int height) {
3852a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com  return ARGBShuffle(src_bgra, src_stride_bgra,
3862a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     dst_argb, dst_stride_argb,
3872a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     (const uint8*)(&kShuffleMaskBGRAToARGB),
3882a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     width, height);
3892a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com}
3902a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com
391d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com// Convert ABGR to ARGB.
392fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
393d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.comint ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
394c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
395c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
3961096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  return ARGBShuffle(src_abgr, src_stride_abgr,
3971096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     dst_argb, dst_stride_argb,
398a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com                     (const uint8*)(&kShuffleMaskABGRToARGB),
3991096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     width, height);
400c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
401c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
4022a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com// Convert ARGB to ABGR to (same as ABGRToARGB).
4032a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.comLIBYUV_API
4042a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.comint ARGBToABGR(const uint8* src_abgr, int src_stride_abgr,
4052a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
4062a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com               int width, int height) {
4072a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com  return ARGBShuffle(src_abgr, src_stride_abgr,
4082a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     dst_argb, dst_stride_argb,
4092a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     (const uint8*)(&kShuffleMaskABGRToARGB),
4102a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com                     width, height);
4112a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com}
4122a35da39126a2dd3d5725c37e7326eb52521291dfbarchard@google.com
413b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.com// Convert RGBA to ARGB.
414fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
415b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.comint RGBAToARGB(const uint8* src_rgba, int src_stride_rgba,
416b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
417b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.com               int width, int height) {
4181096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com  return ARGBShuffle(src_rgba, src_stride_rgba,
4191096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     dst_argb, dst_stride_argb,
420a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com                     (const uint8*)(&kShuffleMaskRGBAToARGB),
4211096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com                     width, height);
422b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.com}
423b8eabfea6487a4be3c1497a7ba7c9e2ab2f5f46dfbarchard@google.com
424c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com// Convert RGB24 to ARGB.
425fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
426c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.comint RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
427bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com                uint8* dst_argb, int dst_stride_argb,
428bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com                int width, int height) {
4298798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
4308798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
4318798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      RGB24ToARGBRow_C;
432c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com  if (!src_rgb24 || !dst_argb ||
43325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
43425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
43525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
43625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
437c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
438c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
439c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
440c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_stride_rgb24 = -src_stride_rgb24;
441c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
442095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
443518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_rgb24 == width * 3 &&
444518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
445095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
446095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
447095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_rgb24 = dst_stride_argb = 0;
448518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
449c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com#if defined(HAS_RGB24TOARGBROW_SSSE3)
450bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
451c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
452bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
453bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
454bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
455bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
456c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com  }
457c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com#elif defined(HAS_RGB24TOARGBROW_NEON)
458bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
459bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
460bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
461bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB24ToARGBRow = RGB24ToARGBRow_NEON;
462bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
463c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
464c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
465c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
4668798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
467c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    RGB24ToARGBRow(src_rgb24, dst_argb, width);
468c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_rgb24 += src_stride_rgb24;
469c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
470c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
471c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
472c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
473c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
474c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com// Convert RAW to ARGB.
475fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
476c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.comint RAWToARGB(const uint8* src_raw, int src_stride_raw,
477bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com              uint8* dst_argb, int dst_stride_argb,
478bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com              int width, int height) {
4798798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
4808798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
4818798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      RAWToARGBRow_C;
482c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com  if (!src_raw || !dst_argb ||
48325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
48425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
48525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
48625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
487c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
488c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
489c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_raw = src_raw + (height - 1) * src_stride_raw;
490c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_stride_raw = -src_stride_raw;
491c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
492095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
493518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_raw == width * 3 &&
494518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
495095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
496095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
497095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_raw = dst_stride_argb = 0;
498518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
499c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com#if defined(HAS_RAWTOARGBROW_SSSE3)
500bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
501c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
502bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
503bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
504bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RAWToARGBRow = RAWToARGBRow_SSSE3;
505bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
506c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com  }
507c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com#elif defined(HAS_RAWTOARGBROW_NEON)
508bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
509bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToARGBRow = RAWToARGBRow_Any_NEON;
510bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
511bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RAWToARGBRow = RAWToARGBRow_NEON;
512bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
513c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
514c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
515c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
5168798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
517c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    RAWToARGBRow(src_raw, dst_argb, width);
518c7277d08e8d33d470b0f4a5e9c3c58f5f250f114fbarchard@google.com    src_raw += src_stride_raw;
519c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
520c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
521c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
522c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
523c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
524c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert RGB565 to ARGB.
525fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
526c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
527c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                 uint8* dst_argb, int dst_stride_argb,
528c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                 int width, int height) {
5298798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
5308798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) =
5318798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      RGB565ToARGBRow_C;
53225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_rgb565 || !dst_argb ||
53325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
53425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
53525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
53625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
537c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
538c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
539c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
540c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_rgb565 = -src_stride_rgb565;
541c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
542095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
543518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_rgb565 == width * 2 &&
544518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
545095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
546095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
547095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_rgb565 = dst_stride_argb = 0;
548518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
549c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_RGB565TOARGBROW_SSE2)
550bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
551c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
552bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
553bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
554bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
555bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
556bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
557bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#elif defined(HAS_RGB565TOARGBROW_NEON)
558bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
559bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
560bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
561bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB565ToARGBRow = RGB565ToARGBRow_NEON;
562bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
563c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
564c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
565c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
5668798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
567c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    RGB565ToARGBRow(src_rgb565, dst_argb, width);
568c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_rgb565 += src_stride_rgb565;
569c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
570c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
571c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
572c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
573c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
574c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert ARGB1555 to ARGB.
575fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
576c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
577c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                   uint8* dst_argb, int dst_stride_argb,
578c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                   int width, int height) {
5798798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
5808798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
5818798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      int pix) = ARGB1555ToARGBRow_C;
58225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_argb1555 || !dst_argb ||
5834b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com      width <= 0 || height == 0) {
58425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
58525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
58625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
587c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
588c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
589c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
590c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_argb1555 = -src_stride_argb1555;
591c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
592095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
593518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_argb1555 == width * 2 &&
594518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
595095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
596095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
597095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_argb1555 = dst_stride_argb = 0;
598518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
599c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_ARGB1555TOARGBROW_SSE2)
6004b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
601c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
6024b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
6034b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
6044b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com      ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
6054b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    }
6064b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  }
6074b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com#elif defined(HAS_ARGB1555TOARGBROW_NEON)
6084b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
6094b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
6104b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
6114b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com      ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
6124b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    }
613c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
614c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
615c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
6168798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
617c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
618c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_argb1555 += src_stride_argb1555;
619c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
620c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
621c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
622c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
623c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
624c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert ARGB4444 to ARGB.
625fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
626c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
627c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                   uint8* dst_argb, int dst_stride_argb,
628c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                   int width, int height) {
6298798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
6308798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
6318798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      int pix) = ARGB4444ToARGBRow_C;
63225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_argb4444 || !dst_argb ||
63325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
63425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
63525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
63625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
637c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
638c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
639c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
640c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_argb4444 = -src_stride_argb4444;
641c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
642095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
643518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  if (src_stride_argb4444 == width * 2 &&
644518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
645095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
646095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
647095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_argb4444 = dst_stride_argb = 0;
648518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
649c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_ARGB4444TOARGBROW_SSE2)
6504b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
651c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
6524b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
6534b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
6544b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com      ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
6554b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    }
6564b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  }
6574b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com#elif defined(HAS_ARGB4444TOARGBROW_NEON)
6584b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
6594b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
6604b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
6614b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com      ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
6624b4a32cb17596321ccee7ba3179bcd3ad6e2c81efbarchard@google.com    }
663c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
664c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
665c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
6668798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
667c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
668c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_argb4444 += src_stride_argb4444;
669c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
670c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
671c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
672c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
673c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
674c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert NV12 to ARGB.
675fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
676c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint NV12ToARGB(const uint8* src_y, int src_stride_y,
677c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               const uint8* src_uv, int src_stride_uv,
678c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
679c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
6808798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
6818798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*NV12ToARGBRow)(const uint8* y_buf,
6828798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* uv_buf,
6838798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
6848798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = NV12ToARGBRow_C;
68525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_uv || !dst_argb ||
68625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
68725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
68825ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
689c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
690c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
691c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
692c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
693c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
694c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
695c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_NV12TOARGBROW_SSSE3)
696c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
697c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
698c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
699c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
700c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
701c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        NV12ToARGBRow = NV12ToARGBRow_SSSE3;
702c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
703c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
704c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
70515449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com#elif defined(HAS_NV12TOARGBROW_NEON)
70664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
70764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
70864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
70964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com      NV12ToARGBRow = NV12ToARGBRow_NEON;
71064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    }
71164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com  }
71264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#endif
713c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
7148798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
715c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow(src_y, src_uv, dst_argb, width);
716c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
717c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
718c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (y & 1) {
719c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      src_uv += src_stride_uv;
720c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
721c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
722c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
723c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
724c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
725c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert NV21 to ARGB.
726fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
727c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint NV21ToARGB(const uint8* src_y, int src_stride_y,
72864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com               const uint8* src_uv, int src_stride_uv,
729c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
730c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
7318798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
7328798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*NV21ToARGBRow)(const uint8* y_buf,
7338798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* uv_buf,
7348798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
7358798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = NV21ToARGBRow_C;
73664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com  if (!src_y || !src_uv || !dst_argb ||
73725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
73825ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
73925ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
740c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
741c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
742c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
743c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
744c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
745c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
746c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_NV21TOARGBROW_SSSE3)
747c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
748c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
749c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
750c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      NV21ToARGBRow = NV21ToARGBRow_Unaligned_SSSE3;
751c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
752c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        NV21ToARGBRow = NV21ToARGBRow_SSSE3;
753c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
754c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
755c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
756c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
75764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#if defined(HAS_NV21TOARGBROW_NEON)
75864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
75964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
76064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
76164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com      NV21ToARGBRow = NV21ToARGBRow_NEON;
76264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    }
76364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com  }
76464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#endif
765c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
7668798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
76764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com    NV21ToARGBRow(src_y, src_uv, dst_argb, width);
768c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
769c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_y += src_stride_y;
770c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (y & 1) {
77164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com      src_uv += src_stride_uv;
772c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
773c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
774c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
775c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
776c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
777c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert M420 to ARGB.
778fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
779c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint M420ToARGB(const uint8* src_m420, int src_stride_m420,
780c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
781c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
7828798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
7838798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*NV12ToARGBRow)(const uint8* y_buf,
7848798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        const uint8* uv_buf,
7858798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        uint8* rgb_buf,
7868798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                        int width) = NV12ToARGBRow_C;
78725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_m420 || !dst_argb ||
78825ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
78925ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
79025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
791c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
792c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
793c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
794c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
795c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_stride_argb = -dst_stride_argb;
796c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
797c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#if defined(HAS_NV12TOARGBROW_SSSE3)
798c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
799c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
800c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
801c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
802c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
803c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com        NV12ToARGBRow = NV12ToARGBRow_SSSE3;
804c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com      }
805c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
806c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
807fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com#elif defined(HAS_NV12TOARGBROW_NEON)
808fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
809fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com    NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
810fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
811fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com      NV12ToARGBRow = NV12ToARGBRow_NEON;
812fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com    }
813fe44ff67817a50ec50987c369558467696ab08f3fbarchard@google.com  }
814c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
815c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
8168798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
817c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
818c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
819c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com                  dst_argb + dst_stride_argb, width);
820c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb * 2;
821c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_m420 += src_stride_m420 * 3;
822c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
823c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height & 1) {
824c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
825c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
826c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
827c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
828c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
829c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert YUY2 to ARGB.
830fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
831c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
832c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
833c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
8348798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
8358798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) =
8368798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      YUY2ToARGBRow_C;
83725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_yuy2 || !dst_argb ||
83825ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
83925ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
84025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
841c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
842c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
843c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
844c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
845c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_yuy2 = -src_stride_yuy2;
846c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
847095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
848d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  if (src_stride_yuy2 == width * 2 &&
849518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
850095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
851095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
852095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_yuy2 = dst_stride_argb = 0;
853518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
854793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com#if defined(HAS_YUY2TOARGBROW_SSSE3)
855735f9921e912e3c19846f01143d3978b47b02aa6fbarchard@google.com  // Posix is 16, Windows is 8.
856d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
857793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
858f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
859793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com      YUY2ToARGBRow = YUY2ToARGBRow_Unaligned_SSSE3;
860d8427fd50a65f99376420ecfc8e4dd6781ea843cfbarchard@google.com      if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16) &&
8616784e4b4140e7e59bf73208f5a6565f7af6408affbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
862793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com        YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
8638d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com      }
8648d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    }
8658d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  }
866793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com#elif defined(HAS_YUY2TOARGBROW_NEON)
8678d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
868793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
8698d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
870793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com      YUY2ToARGBRow = YUY2ToARGBRow_NEON;
871c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
872c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
873c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
8748798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
875793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    YUY2ToARGBRow(src_yuy2, dst_argb, width);
876c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_yuy2 += src_stride_yuy2;
877c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
878c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
879c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
880c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
881c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
882c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com// Convert UYVY to ARGB.
883fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
884c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
885c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               uint8* dst_argb, int dst_stride_argb,
886c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com               int width, int height) {
8878798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  int y;
8888798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) =
8898798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      UYVYToARGBRow_C;
89025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_uyvy || !dst_argb ||
89125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
89225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
89325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
894c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  // Negative height means invert the image.
895c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  if (height < 0) {
896c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    height = -height;
897c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
898c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_stride_uyvy = -src_stride_uyvy;
899c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
900095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
901d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  if (src_stride_uyvy == width * 2 &&
902518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com      dst_stride_argb == width * 4) {
903095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
904095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    height = 1;
905095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_uyvy = dst_stride_argb = 0;
906518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com  }
907793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com#if defined(HAS_UYVYTOARGBROW_SSSE3)
908735f9921e912e3c19846f01143d3978b47b02aa6fbarchard@google.com  // Posix is 16, Windows is 8.
909d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
910793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
911f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
912793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com      UYVYToARGBRow = UYVYToARGBRow_Unaligned_SSSE3;
913d8427fd50a65f99376420ecfc8e4dd6781ea843cfbarchard@google.com      if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16) &&
9146784e4b4140e7e59bf73208f5a6565f7af6408affbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
915793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com        UYVYToARGBRow = UYVYToARGBRow_SSSE3;
9168d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com      }
9178d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    }
9188d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  }
919793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com#elif defined(HAS_UYVYTOARGBROW_NEON)
9208d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
921793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
9228d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
923793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com      UYVYToARGBRow = UYVYToARGBRow_NEON;
924c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    }
925c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
926c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
9278798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com  for (y = 0; y < height; ++y) {
928793e5a06ffe55a911f8aa3f4731ae681039952bcfbarchard@google.com    UYVYToARGBRow(src_uyvy, dst_argb, width);
929c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    src_uyvy += src_stride_uyvy;
930c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com    dst_argb += dst_stride_argb;
931c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  }
932c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com  return 0;
933c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}
934c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com
935c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#ifdef __cplusplus
936c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}  // extern "C"
937c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com}  // namespace libyuv
938c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com#endif
939