1aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org/*
2b0c97975894a5eebebf9d93147cdd941a3accb63fbarchard@google.com *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org *
4aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org *  Use of this source code is governed by a BSD-style license
5aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org *  that can be found in the LICENSE file in the root of the source
6aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org *  tree. An additional intellectual property rights grant can be found
7cde587092fef0dbed2c35602f30b79e7b892e766fbarchard@google.com *  in the file PATENTS. All contributing project authors may
8aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org */
10aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
11a1280730c24b5c94ef16949777f65e597719488efbarchard@google.com#include "libyuv/convert.h"
12aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
13585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com#include "libyuv/basic_types.h"
14585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com#include "libyuv/cpu_id.h"
15b61497636a648c771ac55d184a80b17aca7414f5fbarchard@google.com#include "libyuv/planar_functions.h"
16b61497636a648c771ac55d184a80b17aca7414f5fbarchard@google.com#include "libyuv/rotate.h"
171d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com#include "libyuv/scale.h"  // For ScalePlane()
18142f6c4ed5eaeec0176f255e64bac8d8c70b42e1fbarchard@google.com#include "libyuv/row.h"
19aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
20fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#ifdef __cplusplus
21a1280730c24b5c94ef16949777f65e597719488efbarchard@google.comnamespace libyuv {
22fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.comextern "C" {
23fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#endif
24aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
2599a1298c54dc35348295165745521120818263b8fbarchard@google.com#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
2699a1298c54dc35348295165745521120818263b8fbarchard@google.comstatic __inline int Abs(int v) {
2799a1298c54dc35348295165745521120818263b8fbarchard@google.com  return v >= 0 ? v : -v;
2899a1298c54dc35348295165745521120818263b8fbarchard@google.com}
2999a1298c54dc35348295165745521120818263b8fbarchard@google.com
3099a1298c54dc35348295165745521120818263b8fbarchard@google.com// Any I4xx To I420 format with mirroring.
3199a1298c54dc35348295165745521120818263b8fbarchard@google.comstatic int I4xxToI420(const uint8* src_y, int src_stride_y,
3299a1298c54dc35348295165745521120818263b8fbarchard@google.com                      const uint8* src_u, int src_stride_u,
3399a1298c54dc35348295165745521120818263b8fbarchard@google.com                      const uint8* src_v, int src_stride_v,
3499a1298c54dc35348295165745521120818263b8fbarchard@google.com                      uint8* dst_y, int dst_stride_y,
3599a1298c54dc35348295165745521120818263b8fbarchard@google.com                      uint8* dst_u, int dst_stride_u,
3699a1298c54dc35348295165745521120818263b8fbarchard@google.com                      uint8* dst_v, int dst_stride_v,
3799a1298c54dc35348295165745521120818263b8fbarchard@google.com                      int src_y_width, int src_y_height,
3899a1298c54dc35348295165745521120818263b8fbarchard@google.com                      int src_uv_width, int src_uv_height) {
3999a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int dst_y_width = Abs(src_y_width);
4099a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int dst_y_height = Abs(src_y_height);
4199a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);
4299a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);
43a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  if (src_y_width == 0 || src_y_height == 0 ||
44a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      src_uv_width == 0 || src_uv_height == 0) {
45a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com    return -1;
46a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  }
4799a1298c54dc35348295165745521120818263b8fbarchard@google.com  ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
4899a1298c54dc35348295165745521120818263b8fbarchard@google.com             dst_y, dst_stride_y, dst_y_width, dst_y_height,
4999a1298c54dc35348295165745521120818263b8fbarchard@google.com             kFilterBilinear);
5099a1298c54dc35348295165745521120818263b8fbarchard@google.com  ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
5199a1298c54dc35348295165745521120818263b8fbarchard@google.com             dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
5299a1298c54dc35348295165745521120818263b8fbarchard@google.com             kFilterBilinear);
5399a1298c54dc35348295165745521120818263b8fbarchard@google.com  ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
5499a1298c54dc35348295165745521120818263b8fbarchard@google.com             dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
5599a1298c54dc35348295165745521120818263b8fbarchard@google.com             kFilterBilinear);
5699a1298c54dc35348295165745521120818263b8fbarchard@google.com  return 0;
5799a1298c54dc35348295165745521120818263b8fbarchard@google.com}
5899a1298c54dc35348295165745521120818263b8fbarchard@google.com
592d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Copy I420 with optional flipping
6099a1298c54dc35348295165745521120818263b8fbarchard@google.com// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
6199a1298c54dc35348295165745521120818263b8fbarchard@google.com// is does row coalescing.
62fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
632d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint I420Copy(const uint8* src_y, int src_stride_y,
642d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             const uint8* src_u, int src_stride_u,
652d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             const uint8* src_v, int src_stride_v,
662d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             uint8* dst_y, int dst_stride_y,
672d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             uint8* dst_u, int dst_stride_u,
682d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             uint8* dst_v, int dst_stride_v,
692d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com             int width, int height) {
70a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfwidth = (width + 1) >> 1;
71a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfheight = (height + 1) >> 1;
722d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  if (!src_y || !src_u || !src_v ||
732d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com      !dst_y || !dst_u || !dst_v ||
742d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com      width <= 0 || height == 0) {
752d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    return -1;
761616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com  }
772d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  // Negative height means invert the image.
782d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  if (height < 0) {
792d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    height = -height;
80a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com    halfheight = (height + 1) >> 1;
812d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_y = src_y + (height - 1) * src_stride_y;
822d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_u = src_u + (halfheight - 1) * src_stride_u;
832d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_v = src_v + (halfheight - 1) * src_stride_v;
842d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_stride_y = -src_stride_y;
852d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_stride_u = -src_stride_u;
862d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_stride_v = -src_stride_v;
872d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
882d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
892d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  if (dst_y) {
902d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
912d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
92a8e4dcb5d5b2ef0334d46b4db0278efb87feaf6cfbarchard@google.com  // Copy UV planes.
932d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
942d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
952d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  return 0;
961616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com}
97032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com
98545a51c1d3c0d28a614b224375bbf00edf81c057fbarchard@google.com// 422 chroma is 1/2 width, 1x height
99545a51c1d3c0d28a614b224375bbf00edf81c057fbarchard@google.com// 420 chroma is 1/2 width, 1/2 height
100fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
1012d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint I422ToI420(const uint8* src_y, int src_stride_y,
102585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               const uint8* src_u, int src_stride_u,
103585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               const uint8* src_v, int src_stride_v,
1042d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
1052d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
1062d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
107585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               int width, int height) {
10899a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int src_uv_width = SUBSAMPLE(width, 1, 1);
10999a1298c54dc35348295165745521120818263b8fbarchard@google.com  return I4xxToI420(src_y, src_stride_y,
11099a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_u, src_stride_u,
11199a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_v, src_stride_v,
11299a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_y, dst_stride_y,
11399a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_u, dst_stride_u,
11499a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_v, dst_stride_v,
11599a1298c54dc35348295165745521120818263b8fbarchard@google.com                    width, height,
11699a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_uv_width, height);
1171616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com}
118aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
119545a51c1d3c0d28a614b224375bbf00edf81c057fbarchard@google.com// 444 chroma is 1x width, 1x height
120545a51c1d3c0d28a614b224375bbf00edf81c057fbarchard@google.com// 420 chroma is 1/2 width, 1/2 height
121fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
1222d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint I444ToI420(const uint8* src_y, int src_stride_y,
1231616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com               const uint8* src_u, int src_stride_u,
1241616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com               const uint8* src_v, int src_stride_v,
1252d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
1262d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
1272d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
1281616c315e0313b61d922f0b75bd6704861b75a56fbarchard@google.com               int width, int height) {
12999a1298c54dc35348295165745521120818263b8fbarchard@google.com  return I4xxToI420(src_y, src_stride_y,
13099a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_u, src_stride_u,
13199a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_v, src_stride_v,
13299a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_y, dst_stride_y,
13399a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_u, dst_stride_u,
13499a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_v, dst_stride_v,
13599a1298c54dc35348295165745521120818263b8fbarchard@google.com                    width, height,
13699a1298c54dc35348295165745521120818263b8fbarchard@google.com                    width, height);
137aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org}
138aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
1398536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com// 411 chroma is 1/4 width, 1x height
1408536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com// 420 chroma is 1/2 width, 1/2 height
141fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
1428536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.comint I411ToI420(const uint8* src_y, int src_stride_y,
1438536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               const uint8* src_u, int src_stride_u,
1448536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               const uint8* src_v, int src_stride_v,
1458536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               uint8* dst_y, int dst_stride_y,
1468536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               uint8* dst_u, int dst_stride_u,
1478536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               uint8* dst_v, int dst_stride_v,
1488536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com               int width, int height) {
14999a1298c54dc35348295165745521120818263b8fbarchard@google.com  const int src_uv_width = SUBSAMPLE(width, 3, 2);
15099a1298c54dc35348295165745521120818263b8fbarchard@google.com  return I4xxToI420(src_y, src_stride_y,
15199a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_u, src_stride_u,
15299a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_v, src_stride_v,
15399a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_y, dst_stride_y,
15499a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_u, dst_stride_u,
15599a1298c54dc35348295165745521120818263b8fbarchard@google.com                    dst_v, dst_stride_v,
15699a1298c54dc35348295165745521120818263b8fbarchard@google.com                    width, height,
15799a1298c54dc35348295165745521120818263b8fbarchard@google.com                    src_uv_width, height);
1588536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com}
1598536b2f389dea8f8b7177f4886d995e3315f12e8fbarchard@google.com
1602d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// I400 is greyscale typically used in MJPG
161fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
1622d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint I400ToI420(const uint8* src_y, int src_stride_y,
1632d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
1642d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
1652d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
166032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com               int width, int height) {
167a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfwidth = (width + 1) >> 1;
168a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfheight = (height + 1) >> 1;
16925ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !dst_y || !dst_u || !dst_v ||
17025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
17125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
17225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
173032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  // Negative height means invert the image.
174032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  if (height < 0) {
175032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com    height = -height;
176a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com    halfheight = (height + 1) >> 1;
1772d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_y = src_y + (height - 1) * src_stride_y;
1782d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_stride_y = -src_stride_y;
1792d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
1802d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
1812d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  SetPlane(dst_u, dst_stride_u, halfwidth, halfheight, 128);
1822d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  SetPlane(dst_v, dst_stride_v, halfwidth, halfheight, 128);
183032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  return 0;
184032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com}
185032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com
1862d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comstatic void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1,
187b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com                       uint8* dst, int dst_stride,
1882d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                       int width, int height) {
189a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
19019932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
191b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_COPYROW_X86)
192b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
19319932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow = CopyRow_X86;
194b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
195b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
19619932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#if defined(HAS_COPYROW_SSE2)
197b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
198b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      IS_ALIGNED(src, 16) &&
199b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      IS_ALIGNED(src_stride_0, 16) && IS_ALIGNED(src_stride_1, 16) &&
200b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) {
201b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    CopyRow = CopyRow_SSE2;
202b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
20319932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#endif
204aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com#if defined(HAS_COPYROW_ERMS)
205aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com  if (TestCpuFlag(kCpuHasERMS)) {
206aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com    CopyRow = CopyRow_ERMS;
207b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
208b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
209b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_COPYROW_NEON)
210b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
211b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    CopyRow = CopyRow_NEON;
21219932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  }
21319932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#endif
21492352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com#if defined(HAS_COPYROW_MIPS)
21592352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS)) {
21692352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com    CopyRow = CopyRow_MIPS;
21792352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com  }
21892352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com#endif
21919932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com
2202d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  // Copy plane
221a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
22219932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow(src, dst, width);
223b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    CopyRow(src + src_stride_0, dst + dst_stride, width);
22419932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    src += src_stride_0 + src_stride_1;
225b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    dst += dst_stride * 2;
22619932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  }
22719932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  if (height & 1) {
22819932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow(src, dst, width);
229585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  }
2302d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com}
2312d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
2322d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Support converting from FOURCC_M420
2332d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Useful for bandwidth constrained transports like USB 1.0 and 2.0 and for
2342d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// easy conversion to I420.
2352d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// M420 format description:
2362d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com// M420 is row biplanar 420: 2 rows of Y and 1 row of UV.
2372d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Chroma is half width / half height. (420)
23864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com// src_stride_m420 is row planar. Normally this will be the width in pixels.
2392d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com//   The UV plane is half width, but 2 values, so src_stride_m420 applies to
2402d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com//   this as well as the two Y planes.
2412d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comstatic int X420ToI420(const uint8* src_y,
2422d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      int src_stride_y0, int src_stride_y1,
2432d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      const uint8* src_uv, int src_stride_uv,
2442d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      uint8* dst_y, int dst_stride_y,
2452d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      uint8* dst_u, int dst_stride_u,
2462d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      uint8* dst_v, int dst_stride_v,
2472d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                      int width, int height) {
248a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
249a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfwidth = (width + 1) >> 1;
250a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfheight = (height + 1) >> 1;
251a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) =
252a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      SplitUVRow_C;
25325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_uv ||
25425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_y || !dst_u || !dst_v ||
25525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
25625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
25725ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
258032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  // Negative height means invert the image.
259032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  if (height < 0) {
260032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com    height = -height;
261a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com    halfheight = (height + 1) >> 1;
2622d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_y = dst_y + (height - 1) * dst_stride_y;
2632d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_u = dst_u + (halfheight - 1) * dst_stride_u;
2642d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_v = dst_v + (halfheight - 1) * dst_stride_v;
2652d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_y = -dst_stride_y;
2662d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_u = -dst_stride_u;
2672d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_v = -dst_stride_v;
2682d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
269095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
2705ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com  if (src_stride_y0 == width &&
2715ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com      src_stride_y1 == width &&
2725ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com      dst_stride_y == width) {
273095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    width *= height;
2745ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com    height = 1;
275095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_y0 = src_stride_y1 = dst_stride_y = 0;
2765ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com  }
277095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  // Coalesce rows.
278095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com  if (src_stride_uv == halfwidth * 2 &&
27987215c0871c6f491ab870378bfff2c3601a02973fbarchard@google.com      dst_stride_u == halfwidth &&
28087215c0871c6f491ab870378bfff2c3601a02973fbarchard@google.com      dst_stride_v == halfwidth) {
281095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    halfwidth *= halfheight;
2825ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com    halfheight = 1;
283095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com    src_stride_uv = dst_stride_u = dst_stride_v = 0;
2845ca144d2140755ab668916335cd927e5583dbb42fbarchard@google.com  }
285f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_SPLITUVROW_SSE2)
286e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
287f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com    SplitUVRow = SplitUVRow_Any_SSE2;
288e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com    if (IS_ALIGNED(halfwidth, 16)) {
289f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com      SplitUVRow = SplitUVRow_Unaligned_SSE2;
290e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com      if (IS_ALIGNED(src_uv, 16) && IS_ALIGNED(src_stride_uv, 16) &&
291e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com          IS_ALIGNED(dst_u, 16) && IS_ALIGNED(dst_stride_u, 16) &&
292e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com          IS_ALIGNED(dst_v, 16) && IS_ALIGNED(dst_stride_v, 16)) {
293f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com        SplitUVRow = SplitUVRow_SSE2;
294db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com      }
295db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com    }
2962b9c21080362d7f1b45f7465847e939b1d270583fbarchard@google.com  }
297db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com#endif
298f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_SPLITUVROW_AVX2)
299e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
300f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com    SplitUVRow = SplitUVRow_Any_AVX2;
301e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com    if (IS_ALIGNED(halfwidth, 32)) {
302b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      SplitUVRow = SplitUVRow_AVX2;
303db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com    }
3042d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
305db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com#endif
306f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_SPLITUVROW_NEON)
307e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
308f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com    SplitUVRow = SplitUVRow_Any_NEON;
309e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com    if (IS_ALIGNED(halfwidth, 16)) {
3104a86a836fcde981b6c3fd3f4a216a3253a2d26bcfbarchard@google.com      SplitUVRow = SplitUVRow_NEON;
311db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com    }
312db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com  }
313db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com#endif
314f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_SPLITUVROW_MIPS_DSPR2)
315e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && halfwidth >= 16) {
316f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com    SplitUVRow = SplitUVRow_Any_MIPS_DSPR2;
317e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com    if (IS_ALIGNED(halfwidth, 16)) {
318f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com      SplitUVRow = SplitUVRow_Unaligned_MIPS_DSPR2;
319e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com      if (IS_ALIGNED(src_uv, 4) && IS_ALIGNED(src_stride_uv, 4) &&
320e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com          IS_ALIGNED(dst_u, 4) && IS_ALIGNED(dst_stride_u, 4) &&
321e0d8648b6ab861cfcf03513439fad8ae39ba50c2fbarchard@google.com          IS_ALIGNED(dst_v, 4) && IS_ALIGNED(dst_stride_v, 4)) {
322f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com        SplitUVRow = SplitUVRow_MIPS_DSPR2;
323db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com      }
324db694edfc2dcdede9adad7febc4e4b7f9506eee8fbarchard@google.com    }
325ca41005256d8b16fef98bc3383c44c4a3b79bb44fbarchard@google.com  }
3262b9c21080362d7f1b45f7465847e939b1d270583fbarchard@google.com#endif
32782ca39582875374c0470473d0dcc6b697f6e5404mikhal@webrtc.org
3282d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  if (dst_y) {
329b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    if (src_stride_y0 == src_stride_y1) {
330b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      CopyPlane(src_y, src_stride_y0, dst_y, dst_stride_y, width, height);
331b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    } else {
332b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      CopyPlane2(src_y, src_stride_y0, src_stride_y1, dst_y, dst_stride_y,
333b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com                 width, height);
334b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    }
335280f4fd8bb7d04ca1a5ecd0b6245a4f3726a9df3mikhal@webrtc.org  }
3362d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
337a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < halfheight; ++y) {
3382d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    // Copy a row of UV.
339f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com    SplitUVRow(src_uv, dst_u, dst_v, halfwidth);
3402d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_u += dst_stride_u;
3412d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_v += dst_stride_v;
3422d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_uv += src_stride_uv;
343032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  }
344032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  return 0;
345032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com}
346032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com
3472d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Convert NV12 to I420.
348fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
3492d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint NV12ToI420(const uint8* src_y, int src_stride_y,
3502d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               const uint8* src_uv, int src_stride_uv,
3512d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
3522d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
3532d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
354032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com               int width, int height) {
3552d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  return X420ToI420(src_y, src_stride_y, src_stride_y,
3562d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    src_uv, src_stride_uv,
3572d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_y, dst_stride_y,
3582d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_u, dst_stride_u,
3592d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_v, dst_stride_v,
3602d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    width, height);
3612d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com}
3622d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
36362a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com// Convert NV21 to I420.  Same as NV12 but u and v pointers swapped.
36462a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.comLIBYUV_API
36562a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.comint NV21ToI420(const uint8* src_y, int src_stride_y,
36662a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com               const uint8* src_vu, int src_stride_vu,
36762a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com               uint8* dst_y, int dst_stride_y,
36862a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com               uint8* dst_u, int dst_stride_u,
36962a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com               uint8* dst_v, int dst_stride_v,
37062a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com               int width, int height) {
37162a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com  return X420ToI420(src_y, src_stride_y, src_stride_y,
37262a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com                    src_vu, src_stride_vu,
37362a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com                    dst_y, dst_stride_y,
37462a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com                    dst_v, dst_stride_v,
37562a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com                    dst_u, dst_stride_u,
37662a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com                    width, height);
37762a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com}
37862a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com
3792d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Convert M420 to I420.
380fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
3812d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint M420ToI420(const uint8* src_m420, int src_stride_m420,
3822d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
3832d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
3842d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
3852d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               int width, int height) {
3862d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  return X420ToI420(src_m420, src_stride_m420, src_stride_m420 * 2,
3872d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    src_m420 + src_stride_m420 * 2, src_stride_m420 * 3,
3882d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_y, dst_stride_y,
3892d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_u, dst_stride_u,
3902d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    dst_v, dst_stride_v,
3912d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com                    width, height);
3922d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com}
3932d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
3942d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Convert Q420 to I420.
3952d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Format is rows of YY/YUYV
396fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
3972d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint Q420ToI420(const uint8* src_y, int src_stride_y,
3982d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               const uint8* src_yuy2, int src_stride_yuy2,
3992d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_y, int dst_stride_y,
4002d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_u, int dst_stride_u,
4012d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               uint8* dst_v, int dst_stride_v,
4022d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com               int width, int height) {
403a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
404a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int halfheight = (height + 1) >> 1;
405a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
406a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*YUY2ToUV422Row)(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v,
407a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      int pix) = YUY2ToUV422Row_C;
408a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) =
409a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      YUY2ToYRow_C;
41025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_y || !src_yuy2 ||
41125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_y || !dst_u || !dst_v ||
41225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
41325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
41425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
415032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  // Negative height means invert the image.
416032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  if (height < 0) {
417032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com    height = -height;
418a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com    halfheight = (height + 1) >> 1;
4192d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_y = dst_y + (height - 1) * dst_stride_y;
4202d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_u = dst_u + (halfheight - 1) * dst_stride_u;
4212d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_v = dst_v + (halfheight - 1) * dst_stride_v;
4222d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_y = -dst_stride_y;
4232d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_u = -dst_stride_u;
4242d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_stride_v = -dst_stride_v;
4252d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com  }
426d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  // CopyRow for rows of just Y in Q420 copied to Y plane of I420.
42719932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#if defined(HAS_COPYROW_NEON)
42862a961bee72e48e4fa14365bd7444c9280540b6ffbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
42919932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow = CopyRow_NEON;
43019932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  }
431d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com#endif
432d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com#if defined(HAS_COPYROW_X86)
43319932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  if (IS_ALIGNED(width, 4)) {
43419932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow = CopyRow_X86;
435d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  }
43619932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#endif
437d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com#if defined(HAS_COPYROW_SSE2)
438d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
439d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
440d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
441d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    CopyRow = CopyRow_SSE2;
44219932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com  }
44319932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#endif
444aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com#if defined(HAS_COPYROW_ERMS)
445aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com  if (TestCpuFlag(kCpuHasERMS)) {
446aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com    CopyRow = CopyRow_ERMS;
447b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
448b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
44992352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com#if defined(HAS_COPYROW_MIPS)
45092352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS)) {
45192352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com    CopyRow = CopyRow_MIPS;
45292352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com  }
45392352b70819e74fabec5be83807e7ab93e4df6c2fbarchard@google.com#endif
45419932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com
455d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com#if defined(HAS_YUY2TOYROW_SSE2)
456bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
457bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2;
458bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_SSE2;
459d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
460d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2;
461d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
462d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
463d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com        YUY2ToUV422Row = YUY2ToUV422Row_SSE2;
464db11d893c275d17264afdd1f488bcd2e77aa867dfbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
465db11d893c275d17264afdd1f488bcd2e77aa867dfbarchard@google.com          YUY2ToYRow = YUY2ToYRow_SSE2;
466db11d893c275d17264afdd1f488bcd2e77aa867dfbarchard@google.com        }
467d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      }
468d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    }
469d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  }
470b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
471b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_AVX2)
472b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
473b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2;
474b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_AVX2;
475b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    if (IS_ALIGNED(width, 32)) {
476b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      YUY2ToUV422Row = YUY2ToUV422Row_AVX2;
477b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      YUY2ToYRow = YUY2ToYRow_AVX2;
478b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    }
479b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
480b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
481b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_NEON)
482bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
483bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_NEON;
484bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (width >= 16) {
485bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON;
486d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    }
487c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
488d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com      YUY2ToYRow = YUY2ToYRow_NEON;
489c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com      YUY2ToUV422Row = YUY2ToUV422Row_NEON;
490d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    }
491032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  }
4922b9c21080362d7f1b45f7465847e939b1d270583fbarchard@google.com#endif
4932b9c21080362d7f1b45f7465847e939b1d270583fbarchard@google.com
494a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
49519932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com    CopyRow(src_y, dst_y, width);
4962d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    src_y += src_stride_y;
497d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    dst_y += dst_stride_y;
4982d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com
499d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
500d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    YUY2ToYRow(src_yuy2, dst_y, width);
501d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    src_yuy2 += src_stride_yuy2;
5022d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_y += dst_stride_y;
5032d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_u += dst_stride_u;
5042d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com    dst_v += dst_stride_v;
505d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  }
506d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com  if (height & 1) {
507d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    CopyRow(src_y, dst_y, width);
508d8a1435fe01177fdf2884067aca59896538f9dbdfbarchard@google.com    YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
509032b5f990f6673afee7d9a7ad3132ca46448d834fbarchard@google.com  }
510280f4fd8bb7d04ca1a5ecd0b6245a4f3726a9df3mikhal@webrtc.org  return 0;
511aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org}
512aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
513b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com// Convert YUY2 to I420.
514fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
515b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2,
5169394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com               uint8* dst_y, int dst_stride_y,
5179394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com               uint8* dst_u, int dst_stride_u,
5189394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com               uint8* dst_v, int dst_stride_v,
5199394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com               int width, int height) {
520a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
521a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*YUY2ToUVRow)(const uint8* src_yuy2, int src_stride_yuy2,
5228798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int pix) = YUY2ToUVRow_C;
523a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*YUY2ToYRow)(const uint8* src_yuy2,
5248798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_y, int pix) = YUY2ToYRow_C;
525b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  // Negative height means invert the image.
526585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  if (height < 0) {
527585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    height = -height;
528b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
529b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_yuy2 = -src_stride_yuy2;
530b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
531b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#if defined(HAS_YUY2TOYROW_SSE2)
532bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
533bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToUVRow = YUY2ToUVRow_Any_SSE2;
534bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_SSE2;
535b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
536b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      YUY2ToUVRow = YUY2ToUVRow_Unaligned_SSE2;
537b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
538b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
539b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        YUY2ToUVRow = YUY2ToUVRow_SSE2;
540b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
541b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com          YUY2ToYRow = YUY2ToYRow_SSE2;
542b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        }
543b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
544b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    }
545b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
546b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
547b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_AVX2)
548b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
549b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    YUY2ToUVRow = YUY2ToUVRow_Any_AVX2;
550b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_AVX2;
551b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    if (IS_ALIGNED(width, 32)) {
552b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      YUY2ToUVRow = YUY2ToUVRow_AVX2;
553b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      YUY2ToYRow = YUY2ToYRow_AVX2;
554b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    }
555b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
556b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
557b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_NEON)
558bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
559bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    YUY2ToYRow = YUY2ToYRow_Any_NEON;
560bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (width >= 16) {
561bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      YUY2ToUVRow = YUY2ToUVRow_Any_NEON;
562dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com    }
563c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
564dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com      YUY2ToYRow = YUY2ToYRow_NEON;
565c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com      YUY2ToUVRow = YUY2ToUVRow_NEON;
566dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com    }
567dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com  }
5689394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com#endif
5695808cb22ce60bf963e15bfb1a0958cb362f5efbcfbarchard@google.com
570a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
571b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    YUY2ToUVRow(src_yuy2, src_stride_yuy2, dst_u, dst_v, width);
572b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    YUY2ToYRow(src_yuy2, dst_y, width);
573b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    YUY2ToYRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, width);
574b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_yuy2 += src_stride_yuy2 * 2;
575b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_y += dst_stride_y * 2;
576b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_u += dst_stride_u;
577b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_v += dst_stride_v;
5789394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
579b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  if (height & 1) {
580c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    YUY2ToUVRow(src_yuy2, 0, dst_u, dst_v, width);
581c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    YUY2ToYRow(src_yuy2, dst_y, width);
582b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
583b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  return 0;
584b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com}
585b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com
586b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com// Convert UYVY to I420.
587fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
588b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy,
589b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_y, int dst_stride_y,
590b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_u, int dst_stride_u,
591b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_v, int dst_stride_v,
592b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               int width, int height) {
593a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
594a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*UYVYToUVRow)(const uint8* src_uyvy, int src_stride_uyvy,
5958798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int pix) = UYVYToUVRow_C;
596a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*UYVYToYRow)(const uint8* src_uyvy,
5978798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_y, int pix) = UYVYToYRow_C;
598b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  // Negative height means invert the image.
599b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  if (height < 0) {
600b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    height = -height;
601b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
602b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_uyvy = -src_stride_uyvy;
603b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
604b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#if defined(HAS_UYVYTOYROW_SSE2)
605bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
606bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    UYVYToUVRow = UYVYToUVRow_Any_SSE2;
607bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    UYVYToYRow = UYVYToYRow_Any_SSE2;
608b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
609b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      UYVYToUVRow = UYVYToUVRow_Unaligned_SSE2;
610b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      UYVYToYRow = UYVYToYRow_Unaligned_SSE2;
611b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) {
612b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        UYVYToUVRow = UYVYToUVRow_SSE2;
613b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
614b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com          UYVYToYRow = UYVYToYRow_SSE2;
615b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        }
616b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
617b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    }
6189394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
619b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
620b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_UYVYTOYROW_AVX2)
621b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
622b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    UYVYToUVRow = UYVYToUVRow_Any_AVX2;
623b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    UYVYToYRow = UYVYToYRow_Any_AVX2;
624b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    if (IS_ALIGNED(width, 32)) {
625b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      UYVYToUVRow = UYVYToUVRow_AVX2;
626b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      UYVYToYRow = UYVYToYRow_AVX2;
627b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com    }
628b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com  }
629b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif
630b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_UYVYTOYROW_NEON)
631bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
632bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    UYVYToYRow = UYVYToYRow_Any_NEON;
633bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (width >= 16) {
634bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      UYVYToUVRow = UYVYToUVRow_Any_NEON;
635dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com    }
636c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
637dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com      UYVYToYRow = UYVYToYRow_NEON;
638c74fe987257b082e0bb887290f97caf7ab3bad66fbarchard@google.com      UYVYToUVRow = UYVYToUVRow_NEON;
639dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com    }
640dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com  }
641b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
642dddf94c343c9a6413468a334e9fd965e4b1b3eb7fbarchard@google.com
643a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
644b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    UYVYToUVRow(src_uyvy, src_stride_uyvy, dst_u, dst_v, width);
645b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    UYVYToYRow(src_uyvy, dst_y, width);
646b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    UYVYToYRow(src_uyvy + src_stride_uyvy, dst_y + dst_stride_y, width);
647b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_uyvy += src_stride_uyvy * 2;
648585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_y += dst_stride_y * 2;
649585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_u += dst_stride_u;
650585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_v += dst_stride_v;
65143575c8fa5a0f18b1ad9146cda3dfb1af13811f2mikhal@webrtc.org  }
652585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  if (height & 1) {
653c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    UYVYToUVRow(src_uyvy, 0, dst_u, dst_v, width);
654c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    UYVYToYRow(src_uyvy, dst_y, width);
655c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com  }
656c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com  return 0;
657c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com}
658c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com
659bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert ARGB to I420.
660fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
661b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint ARGBToI420(const uint8* src_argb, int src_stride_argb,
662585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_y, int dst_stride_y,
663585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_u, int dst_stride_u,
664585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_v, int dst_stride_v,
665585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               int width, int height) {
666a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
667a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
6688798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
669a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
670a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
67125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_argb ||
67225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_y || !dst_u || !dst_v ||
67325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
67425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
67525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
67625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
6779394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height < 0) {
6789394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    height = -height;
679b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb = src_argb + (height - 1) * src_stride_argb;
680b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_argb = -src_stride_argb;
6819394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
6827fa21d677cf82793be81d02e0a1fbcaf9f56cb99fbarchard@google.com#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
683bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
684bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
685bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
686b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
687b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
688b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
689b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
690b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToUVRow = ARGBToUVRow_SSSE3;
691b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
692b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com          ARGBToYRow = ARGBToYRow_SSSE3;
693b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        }
694b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
695b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    }
696b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
697551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com#endif
6987fa21d677cf82793be81d02e0a1fbcaf9f56cb99fbarchard@google.com#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
699551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
700551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
701551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_AVX2;
702551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com    if (IS_ALIGNED(width, 32)) {
703b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      ARGBToUVRow = ARGBToUVRow_AVX2;
704b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com      ARGBToYRow = ARGBToYRow_AVX2;
705551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com    }
706551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com  }
707551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com#endif
708551d2b297e6a071fe58a8f2da2cb69cc0ec56ed8fbarchard@google.com#if defined(HAS_ARGBTOYROW_NEON)
709bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
710bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_NEON;
7110908a701e90dc15d973784f6245131aa65a66f52fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
7120908a701e90dc15d973784f6245131aa65a66f52fbarchard@google.com      ARGBToYRow = ARGBToYRow_NEON;
713522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    }
714522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    if (width >= 16) {
715522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      ARGBToUVRow = ARGBToUVRow_Any_NEON;
716dd2d512e5afad7536e3a010c0193ca1b43c14985fbarchard@google.com      if (IS_ALIGNED(width, 16)) {
717dd2d512e5afad7536e3a010c0193ca1b43c14985fbarchard@google.com        ARGBToUVRow = ARGBToUVRow_NEON;
718dd2d512e5afad7536e3a010c0193ca1b43c14985fbarchard@google.com      }
7190908a701e90dc15d973784f6245131aa65a66f52fbarchard@google.com    }
7200908a701e90dc15d973784f6245131aa65a66f52fbarchard@google.com  }
7219394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com#endif
722b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com
723a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
724b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width);
725b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ARGBToYRow(src_argb, dst_y, width);
726b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
727b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb += src_stride_argb * 2;
728b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_y += dst_stride_y * 2;
729b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_u += dst_stride_u;
730b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    dst_v += dst_stride_v;
7319394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
732b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  if (height & 1) {
733b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
734b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ARGBToYRow(src_argb, dst_y, width);
735b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
736b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  return 0;
737b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com}
738b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com
739bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert BGRA to I420.
740fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
741b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint BGRAToI420(const uint8* src_bgra, int src_stride_bgra,
742b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_y, int dst_stride_y,
743b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_u, int dst_stride_u,
744b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               uint8* dst_v, int dst_stride_v,
745b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com               int width, int height) {
746a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
747a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*BGRAToUVRow)(const uint8* src_bgra0, int src_stride_bgra,
7488798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = BGRAToUVRow_C;
749a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*BGRAToYRow)(const uint8* src_bgra, uint8* dst_y, int pix) =
750a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      BGRAToYRow_C;
75125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_bgra ||
75225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_y || !dst_u || !dst_v ||
75325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
75425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
75525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
75625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
757b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  if (height < 0) {
758b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    height = -height;
759b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_bgra = src_bgra + (height - 1) * src_stride_bgra;
760b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_bgra = -src_stride_bgra;
761b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
762b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#if defined(HAS_BGRATOYROW_SSSE3)
763bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
764bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    BGRAToUVRow = BGRAToUVRow_Any_SSSE3;
765bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    BGRAToYRow = BGRAToYRow_Any_SSSE3;
766b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
767b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      BGRAToUVRow = BGRAToUVRow_Unaligned_SSSE3;
768b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      BGRAToYRow = BGRAToYRow_Unaligned_SSSE3;
769b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16)) {
770b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        BGRAToUVRow = BGRAToUVRow_SSSE3;
771b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
772b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com          BGRAToYRow = BGRAToYRow_SSSE3;
773b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        }
774b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
775b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    }
7769394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
777bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#elif defined(HAS_BGRATOYROW_NEON)
778bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
779bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    BGRAToYRow = BGRAToYRow_Any_NEON;
780bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
781bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      BGRAToYRow = BGRAToYRow_NEON;
782bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
78395730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (width >= 16) {
78495730719503137a7db61a105bec02220f9ed159efbarchard@google.com      BGRAToUVRow = BGRAToUVRow_Any_NEON;
78595730719503137a7db61a105bec02220f9ed159efbarchard@google.com      if (IS_ALIGNED(width, 16)) {
78695730719503137a7db61a105bec02220f9ed159efbarchard@google.com        BGRAToUVRow = BGRAToUVRow_NEON;
78795730719503137a7db61a105bec02220f9ed159efbarchard@google.com      }
78895730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
789bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
790b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
7919394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com
792a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
793b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    BGRAToUVRow(src_bgra, src_stride_bgra, dst_u, dst_v, width);
794b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    BGRAToYRow(src_bgra, dst_y, width);
795b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    BGRAToYRow(src_bgra + src_stride_bgra, dst_y + dst_stride_y, width);
796b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_bgra += src_stride_bgra * 2;
7979394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_y += dst_stride_y * 2;
7989394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_u += dst_stride_u;
7999394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_v += dst_stride_v;
8009394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
8019394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height & 1) {
802c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    BGRAToUVRow(src_bgra, 0, dst_u, dst_v, width);
803c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    BGRAToYRow(src_bgra, dst_y, width);
8049394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
8059394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  return 0;
806abe14f80ba16b62a04e94587a983c8bcbc7bb88amikhal@webrtc.org}
807abe14f80ba16b62a04e94587a983c8bcbc7bb88amikhal@webrtc.org
808bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert ABGR to I420.
809fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
810b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint ABGRToI420(const uint8* src_abgr, int src_stride_abgr,
811585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_y, int dst_stride_y,
812585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_u, int dst_stride_u,
813585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               uint8* dst_v, int dst_stride_v,
814585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com               int width, int height) {
815a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
816a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ABGRToUVRow)(const uint8* src_abgr0, int src_stride_abgr,
8178798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ABGRToUVRow_C;
818a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ABGRToYRow)(const uint8* src_abgr, uint8* dst_y, int pix) =
819a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ABGRToYRow_C;
82025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  if (!src_abgr ||
82125ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      !dst_y || !dst_u || !dst_v ||
82225ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org      width <= 0 || height == 0) {
82325ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org    return -1;
82425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  }
82525ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
8269394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height < 0) {
8279394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    height = -height;
828b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
829b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_abgr = -src_stride_abgr;
8309394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
8319394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com#if defined(HAS_ABGRTOYROW_SSSE3)
832bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
833bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
834bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ABGRToYRow = ABGRToYRow_Any_SSSE3;
835b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
836b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ABGRToUVRow = ABGRToUVRow_Unaligned_SSSE3;
837b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ABGRToYRow = ABGRToYRow_Unaligned_SSSE3;
838b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(src_abgr, 16) && IS_ALIGNED(src_stride_abgr, 16)) {
839b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ABGRToUVRow = ABGRToUVRow_SSSE3;
840b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
841b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com          ABGRToYRow = ABGRToYRow_SSSE3;
842b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        }
843b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
844b5b27d131adf623aa98109fe4196cd492c2d8b60fbarchard@google.com    }
8459394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
846bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#elif defined(HAS_ABGRTOYROW_NEON)
847bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
848bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ABGRToYRow = ABGRToYRow_Any_NEON;
849bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
850bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      ABGRToYRow = ABGRToYRow_NEON;
851bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
85295730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (width >= 16) {
85395730719503137a7db61a105bec02220f9ed159efbarchard@google.com      ABGRToUVRow = ABGRToUVRow_Any_NEON;
85495730719503137a7db61a105bec02220f9ed159efbarchard@google.com      if (IS_ALIGNED(width, 16)) {
85595730719503137a7db61a105bec02220f9ed159efbarchard@google.com        ABGRToUVRow = ABGRToUVRow_NEON;
85695730719503137a7db61a105bec02220f9ed159efbarchard@google.com      }
85795730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
858bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
859b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
8609394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com
861a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
862b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ABGRToUVRow(src_abgr, src_stride_abgr, dst_u, dst_v, width);
863b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ABGRToYRow(src_abgr, dst_y, width);
864b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
865b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_abgr += src_stride_abgr * 2;
8669394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_y += dst_stride_y * 2;
8679394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_u += dst_stride_u;
8689394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_v += dst_stride_v;
8699394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
8709394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height & 1) {
871c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    ABGRToUVRow(src_abgr, 0, dst_u, dst_v, width);
872c8c8047d434c7c2b86c6ddd8ef9507ff14bfb1f3fbarchard@google.com    ABGRToYRow(src_abgr, dst_y, width);
8739394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
8749394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  return 0;
875abe14f80ba16b62a04e94587a983c8bcbc7bb88amikhal@webrtc.org}
876abe14f80ba16b62a04e94587a983c8bcbc7bb88amikhal@webrtc.org
877bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert RGBA to I420.
878fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API
879d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.comint RGBAToI420(const uint8* src_rgba, int src_stride_rgba,
880d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com               uint8* dst_y, int dst_stride_y,
881d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com               uint8* dst_u, int dst_stride_u,
882d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com               uint8* dst_v, int dst_stride_v,
883d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com               int width, int height) {
884a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
885a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGBAToUVRow)(const uint8* src_rgba0, int src_stride_rgba,
8868798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = RGBAToUVRow_C;
887a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGBAToYRow)(const uint8* src_rgba, uint8* dst_y, int pix) =
888a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RGBAToYRow_C;
889d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  if (!src_rgba ||
890d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      !dst_y || !dst_u || !dst_v ||
891d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      width <= 0 || height == 0) {
892d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    return -1;
893d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  }
894d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  // Negative height means invert the image.
895d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  if (height < 0) {
896d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    height = -height;
897d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    src_rgba = src_rgba + (height - 1) * src_stride_rgba;
898d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    src_stride_rgba = -src_stride_rgba;
899d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  }
900d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com#if defined(HAS_RGBATOYROW_SSSE3)
901bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
902bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGBAToUVRow = RGBAToUVRow_Any_SSSE3;
903bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGBAToYRow = RGBAToYRow_Any_SSSE3;
904d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
905d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      RGBAToUVRow = RGBAToUVRow_Unaligned_SSSE3;
906d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      RGBAToYRow = RGBAToYRow_Unaligned_SSSE3;
907d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      if (IS_ALIGNED(src_rgba, 16) && IS_ALIGNED(src_stride_rgba, 16)) {
908d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com        RGBAToUVRow = RGBAToUVRow_SSSE3;
909d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
910d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com          RGBAToYRow = RGBAToYRow_SSSE3;
911d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com        }
912d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com      }
913d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    }
914d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  }
915bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#elif defined(HAS_RGBATOYROW_NEON)
916bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
917bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGBAToYRow = RGBAToYRow_Any_NEON;
918bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
919bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGBAToYRow = RGBAToYRow_NEON;
920bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
92195730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (width >= 16) {
92295730719503137a7db61a105bec02220f9ed159efbarchard@google.com      RGBAToUVRow = RGBAToUVRow_Any_NEON;
92395730719503137a7db61a105bec02220f9ed159efbarchard@google.com      if (IS_ALIGNED(width, 16)) {
92495730719503137a7db61a105bec02220f9ed159efbarchard@google.com        RGBAToUVRow = RGBAToUVRow_NEON;
92595730719503137a7db61a105bec02220f9ed159efbarchard@google.com      }
92695730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
927bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
928d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com#endif
929d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com
930a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
931d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    RGBAToUVRow(src_rgba, src_stride_rgba, dst_u, dst_v, width);
932d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    RGBAToYRow(src_rgba, dst_y, width);
933d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    RGBAToYRow(src_rgba + src_stride_rgba, dst_y + dst_stride_y, width);
934d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    src_rgba += src_stride_rgba * 2;
935d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    dst_y += dst_stride_y * 2;
936d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    dst_u += dst_stride_u;
937d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    dst_v += dst_stride_v;
938d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  }
939d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  if (height & 1) {
940d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    RGBAToUVRow(src_rgba, 0, dst_u, dst_v, width);
941d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com    RGBAToYRow(src_rgba, dst_y, width);
942d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  }
943d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com  return 0;
944d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com}
945d5a27f0533d42bd0e241b0a7887abe1a3d9c0633fbarchard@google.com
946bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert RGB24 to I420.
947d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API
948b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint RGB24ToI420(const uint8* src_rgb24, int src_stride_rgb24,
949585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com                uint8* dst_y, int dst_stride_y,
950585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com                uint8* dst_u, int dst_stride_u,
951585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com                uint8* dst_v, int dst_stride_v,
952585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com                int width, int height) {
953a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
954a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#if defined(HAS_RGB24TOYROW_NEON)
955a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB24ToUVRow)(const uint8* src_rgb24, int src_stride_rgb24,
956a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = RGB24ToUVRow_C;
957a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB24ToYRow)(const uint8* src_rgb24, uint8* dst_y, int pix) =
958a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RGB24ToYRow_C;
959a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#else
960a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
961a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RGB24ToARGBRow_C;
962a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
9638798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
964a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
965a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
966a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  // Allocate 2 rows of ARGB.
967a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  const int kRowSize = (width * 4 + 15) & ~15;
968a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  align_buffer_64(row, kRowSize * 2);
969a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#endif
970bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (!src_rgb24 || !dst_y || !dst_u || !dst_v ||
971d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com      width <= 0 || height == 0) {
972b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    return -1;
973b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
97425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
9759394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height < 0) {
9769394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    height = -height;
977b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
978b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_rgb24 = -src_stride_rgb24;
9799394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
98095730719503137a7db61a105bec02220f9ed159efbarchard@google.com
98195730719503137a7db61a105bec02220f9ed159efbarchard@google.com#if defined(HAS_RGB24TOYROW_NEON)
98295730719503137a7db61a105bec02220f9ed159efbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
98395730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RGB24ToYRow = RGB24ToYRow_Any_NEON;
98495730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
98595730719503137a7db61a105bec02220f9ed159efbarchard@google.com      RGB24ToYRow = RGB24ToYRow_NEON;
98695730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
98795730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (width >= 16) {
98895730719503137a7db61a105bec02220f9ed159efbarchard@google.com      RGB24ToUVRow = RGB24ToUVRow_Any_NEON;
98995730719503137a7db61a105bec02220f9ed159efbarchard@google.com      if (IS_ALIGNED(width, 16)) {
99095730719503137a7db61a105bec02220f9ed159efbarchard@google.com        RGB24ToUVRow = RGB24ToUVRow_NEON;
99195730719503137a7db61a105bec02220f9ed159efbarchard@google.com      }
99295730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
99395730719503137a7db61a105bec02220f9ed159efbarchard@google.com  }
99495730719503137a7db61a105bec02220f9ed159efbarchard@google.com#else  // HAS_RGB24TOYROW_NEON
995d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com
996ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#if defined(HAS_RGB24TOARGBROW_SSSE3)
997bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
998bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
999bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1000bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
1001bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1002bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1003b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
1004bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1005bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1006bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1007bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1008bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      ARGBToUVRow = ARGBToUVRow_SSSE3;
1009bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1010bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1011bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1012bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1013bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1014e5f3fd4cc870b9b22112b3b2f25af06e067c8b7dfbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1015b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1016b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
1017b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1018b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToYRow = ARGBToYRow_SSSE3;
1019b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
1020b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    }
10219394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
1022bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_ARGBTOUVROW_SSSE3
1023bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_RGB24TOYROW_NEON
1024aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
1025a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
1026bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RGB24TOYROW_NEON)
102795730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RGB24ToUVRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width);
1028bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToYRow(src_rgb24, dst_y, width);
1029bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToYRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width);
1030bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
103195730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RGB24ToARGBRow(src_rgb24, row, width);
1032d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    RGB24ToARGBRow(src_rgb24 + src_stride_rgb24, row + kRowSize, width);
1033d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
1034ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1035d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
1036bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1037b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_rgb24 += src_stride_rgb24 * 2;
10389394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_y += dst_stride_y * 2;
10399394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_u += dst_stride_u;
10409394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com    dst_v += dst_stride_v;
10419394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
10429394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  if (height & 1) {
1043bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RGB24TOYROW_NEON)
104495730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RGB24ToUVRow(src_rgb24, 0, dst_u, dst_v, width);
1045bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB24ToYRow(src_rgb24, dst_y, width);
1046bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
104795730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RGB24ToARGBRow(src_rgb24, row, width);
104895730719503137a7db61a105bec02220f9ed159efbarchard@google.com    ARGBToUVRow(row, 0, dst_u, dst_v, width);
1049ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1050bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
10519394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  }
1052d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#if !defined(HAS_RGB24TOYROW_NEON)
1053d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  free_aligned_buffer_64(row);
1054d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#endif
10559394ed99fcc9802a068ba4a44c36aed79ce87157fbarchard@google.com  return 0;
1056585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com}
1057585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com
1058bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert RAW to I420.
1059d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API
1060b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint RAWToI420(const uint8* src_raw, int src_stride_raw,
10611c5136d0699d8705971d765902ae692759f15d21fbarchard@google.com              uint8* dst_y, int dst_stride_y,
10621c5136d0699d8705971d765902ae692759f15d21fbarchard@google.com              uint8* dst_u, int dst_stride_u,
10631c5136d0699d8705971d765902ae692759f15d21fbarchard@google.com              uint8* dst_v, int dst_stride_v,
10641c5136d0699d8705971d765902ae692759f15d21fbarchard@google.com              int width, int height) {
1065a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
1066a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#if defined(HAS_RAWTOYROW_NEON)
1067a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RAWToUVRow)(const uint8* src_raw, int src_stride_raw,
1068a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = RAWToUVRow_C;
1069a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RAWToYRow)(const uint8* src_raw, uint8* dst_y, int pix) =
1070a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RAWToYRow_C;
1071a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#else
1072a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
1073a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RAWToARGBRow_C;
1074a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
10758798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
1076a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
1077a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
1078a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  // Allocate 2 rows of ARGB.
1079a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  const int kRowSize = (width * 4 + 15) & ~15;
1080a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  align_buffer_64(row, kRowSize * 2);
1081a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#endif
1082bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (!src_raw || !dst_y || !dst_u || !dst_v ||
1083d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com      width <= 0 || height == 0) {
1084b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    return -1;
1085b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
108625ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
1087585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  if (height < 0) {
1088585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    height = -height;
1089b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_raw = src_raw + (height - 1) * src_stride_raw;
1090b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_raw = -src_stride_raw;
1091585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  }
109295730719503137a7db61a105bec02220f9ed159efbarchard@google.com
109395730719503137a7db61a105bec02220f9ed159efbarchard@google.com#if defined(HAS_RAWTOYROW_NEON)
109495730719503137a7db61a105bec02220f9ed159efbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
109595730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RAWToYRow = RAWToYRow_Any_NEON;
109695730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (IS_ALIGNED(width, 8)) {
109795730719503137a7db61a105bec02220f9ed159efbarchard@google.com      RAWToYRow = RAWToYRow_NEON;
109895730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
109995730719503137a7db61a105bec02220f9ed159efbarchard@google.com    if (width >= 16) {
110095730719503137a7db61a105bec02220f9ed159efbarchard@google.com      RAWToUVRow = RAWToUVRow_Any_NEON;
110195730719503137a7db61a105bec02220f9ed159efbarchard@google.com      if (IS_ALIGNED(width, 16)) {
110295730719503137a7db61a105bec02220f9ed159efbarchard@google.com        RAWToUVRow = RAWToUVRow_NEON;
110395730719503137a7db61a105bec02220f9ed159efbarchard@google.com      }
110495730719503137a7db61a105bec02220f9ed159efbarchard@google.com    }
110595730719503137a7db61a105bec02220f9ed159efbarchard@google.com  }
110695730719503137a7db61a105bec02220f9ed159efbarchard@google.com#else  // HAS_RAWTOYROW_NEON
1107d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com
1108ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#if defined(HAS_RAWTOARGBROW_SSSE3)
1109bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1110bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1111bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1112bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RAWToARGBRow = RAWToARGBRow_SSSE3;
1113bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1114bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1115b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
1116bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1117bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1118bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1119bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1120bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      ARGBToUVRow = ARGBToUVRow_SSSE3;
1121bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1122bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1123bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1124bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1125bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1126e5f3fd4cc870b9b22112b3b2f25af06e067c8b7dfbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1127b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1128b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
1129b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1130b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToYRow = ARGBToYRow_SSSE3;
1131b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
1132b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    }
1133585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  }
1134bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_ARGBTOUVROW_SSSE3
1135bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_RAWTOYROW_NEON
1136585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com
1137a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
1138bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RAWTOYROW_NEON)
113995730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RAWToUVRow(src_raw, src_stride_raw, dst_u, dst_v, width);
1140bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToYRow(src_raw, dst_y, width);
1141bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToYRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
1142bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
114395730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RAWToARGBRow(src_raw, row, width);
1144d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    RAWToARGBRow(src_raw + src_stride_raw, row + kRowSize, width);
1145d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
1146ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1147d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
1148bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1149b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_raw += src_stride_raw * 2;
1150585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_y += dst_stride_y * 2;
1151585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_u += dst_stride_u;
1152585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com    dst_v += dst_stride_v;
1153585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  }
1154585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  if (height & 1) {
1155bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RAWTOYROW_NEON)
115695730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RAWToUVRow(src_raw, 0, dst_u, dst_v, width);
1157bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RAWToYRow(src_raw, dst_y, width);
1158bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
115995730719503137a7db61a105bec02220f9ed159efbarchard@google.com    RAWToARGBRow(src_raw, row, width);
116095730719503137a7db61a105bec02220f9ed159efbarchard@google.com    ARGBToUVRow(row, 0, dst_u, dst_v, width);
1161ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1162bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1163585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  }
1164d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#if !defined(HAS_RAWTOYROW_NEON)
1165d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  free_aligned_buffer_64(row);
1166d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#endif
1167585a126140be298e60a4daa26140ead0e94eaaa1fbarchard@google.com  return 0;
1168aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org}
1169aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org
1170bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com// Convert RGB565 to I420.
1171d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API
1172b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint RGB565ToI420(const uint8* src_rgb565, int src_stride_rgb565,
1173a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com                 uint8* dst_y, int dst_stride_y,
1174a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com                 uint8* dst_u, int dst_stride_u,
1175a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com                 uint8* dst_v, int dst_stride_v,
1176a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com                 int width, int height) {
1177a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
1178a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#if defined(HAS_RGB565TOYROW_NEON)
1179a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB565ToUVRow)(const uint8* src_rgb565, int src_stride_rgb565,
1180a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = RGB565ToUVRow_C;
1181a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB565ToYRow)(const uint8* src_rgb565, uint8* dst_y, int pix) =
1182a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RGB565ToYRow_C;
1183a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#else
1184a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*RGB565ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
1185a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      RGB565ToARGBRow_C;
1186a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
11878798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
1188a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
1189a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
1190a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  // Allocate 2 rows of ARGB.
1191a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  const int kRowSize = (width * 4 + 15) & ~15;
1192a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  align_buffer_64(row, kRowSize * 2);
1193a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#endif
1194bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (!src_rgb565 || !dst_y || !dst_u || !dst_v ||
1195d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com      width <= 0 || height == 0) {
1196b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    return -1;
1197b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
119825ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
1199a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height < 0) {
1200a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    height = -height;
1201b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
1202b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_rgb565 = -src_stride_rgb565;
1203a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1204f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com
1205f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com#if defined(HAS_RGB565TOYROW_NEON)
1206f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1207f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    RGB565ToYRow = RGB565ToYRow_Any_NEON;
1208f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
1209f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com      RGB565ToYRow = RGB565ToYRow_NEON;
1210f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    }
1211f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    if (width >= 16) {
1212f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com      RGB565ToUVRow = RGB565ToUVRow_Any_NEON;
1213f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com      if (IS_ALIGNED(width, 16)) {
1214f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com        RGB565ToUVRow = RGB565ToUVRow_NEON;
1215f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com      }
1216f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    }
1217f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com  }
1218f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com#else  // HAS_RGB565TOYROW_NEON
1219d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com
1220ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#if defined(HAS_RGB565TOARGBROW_SSE2)
1221bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
1222bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
1223bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
1224bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
1225bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1226bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1227b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
1228bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1229bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1230bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1231bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1232bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com      ARGBToUVRow = ARGBToUVRow_SSSE3;
1233bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    }
1234bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  }
1235bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1236bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1237bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1238e5f3fd4cc870b9b22112b3b2f25af06e067c8b7dfbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1239b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1240b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
1241b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1242b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToYRow = ARGBToYRow_SSSE3;
1243b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
1244b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    }
1245a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1246bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_ARGBTOUVROW_SSSE3
1247bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif  // HAS_RGB565TOYROW_NEON
1248a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
1249a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
1250bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RGB565TOYROW_NEON)
1251f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    RGB565ToUVRow(src_rgb565, src_stride_rgb565, dst_u, dst_v, width);
1252bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToYRow(src_rgb565, dst_y, width);
1253bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToYRow(src_rgb565 + src_stride_rgb565, dst_y + dst_stride_y, width);
1254bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
1255f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    RGB565ToARGBRow(src_rgb565, row, width);
1256d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    RGB565ToARGBRow(src_rgb565 + src_stride_rgb565, row + kRowSize, width);
1257d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
1258ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1259d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
1260bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1261b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_rgb565 += src_stride_rgb565 * 2;
1262a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_y += dst_stride_y * 2;
1263a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_u += dst_stride_u;
1264a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_v += dst_stride_v;
1265a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1266a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height & 1) {
1267bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#if defined(HAS_RGB565TOYROW_NEON)
1268f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    RGB565ToUVRow(src_rgb565, 0, dst_u, dst_v, width);
1269bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    RGB565ToYRow(src_rgb565, dst_y, width);
1270bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#else
1271f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    RGB565ToARGBRow(src_rgb565, row, width);
1272f1daa3db65a41d5d0766c8309ce5a2ef43bf8bb1fbarchard@google.com    ARGBToUVRow(row, 0, dst_u, dst_v, width);
1273ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1274bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com#endif
1275a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1276d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#if !defined(HAS_RGB565TOYROW_NEON)
1277d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  free_aligned_buffer_64(row);
1278d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#endif
1279a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  return 0;
1280a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com}
1281a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
12821dee6250936424ced8722329369da75935d61580fbarchard@google.com// Convert ARGB1555 to I420.
1283d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API
1284b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint ARGB1555ToI420(const uint8* src_argb1555, int src_stride_argb1555,
12858798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_y, int dst_stride_y,
12868798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_u, int dst_stride_u,
12878798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_v, int dst_stride_v,
12888798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   int width, int height) {
1289a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
1290a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#if defined(HAS_ARGB1555TOYROW_NEON)
1291a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB1555ToUVRow)(const uint8* src_argb1555, int src_stride_argb1555,
1292a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGB1555ToUVRow_C;
1293a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB1555ToYRow)(const uint8* src_argb1555, uint8* dst_y, int pix) =
1294a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGB1555ToYRow_C;
1295a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#else
1296a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB1555ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
1297a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGB1555ToARGBRow_C;
1298a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
12998798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
1300a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
1301a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
1302a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  // Allocate 2 rows of ARGB.
1303a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  const int kRowSize = (width * 4 + 15) & ~15;
1304a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  align_buffer_64(row, kRowSize * 2);
1305a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#endif
1306bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (!src_argb1555 || !dst_y || !dst_u || !dst_v ||
1307d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com      width <= 0 || height == 0) {
1308b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    return -1;
1309b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
131025ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
1311a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height < 0) {
1312a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    height = -height;
1313b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
1314b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_argb1555 = -src_stride_argb1555;
1315a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1316522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com
1317522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com#if defined(HAS_ARGB1555TOYROW_NEON)
1318522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1319522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB1555ToYRow = ARGB1555ToYRow_Any_NEON;
1320522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
1321522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      ARGB1555ToYRow = ARGB1555ToYRow_NEON;
1322522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    }
1323522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    if (width >= 16) {
1324522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      ARGB1555ToUVRow = ARGB1555ToUVRow_Any_NEON;
1325522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      if (IS_ALIGNED(width, 16)) {
1326522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com        ARGB1555ToUVRow = ARGB1555ToUVRow_NEON;
1327522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      }
1328522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    }
1329522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com  }
1330522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com#else  // HAS_ARGB1555TOYROW_NEON
1331d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com
1332ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#if defined(HAS_ARGB1555TOARGBROW_SSE2)
13331dee6250936424ced8722329369da75935d61580fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
13341dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
13351dee6250936424ced8722329369da75935d61580fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
13361dee6250936424ced8722329369da75935d61580fbarchard@google.com      ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
13371dee6250936424ced8722329369da75935d61580fbarchard@google.com    }
13381dee6250936424ced8722329369da75935d61580fbarchard@google.com  }
1339b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
13401dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1341bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1342bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1343b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1344b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ARGBToUVRow = ARGBToUVRow_SSSE3;
13451dee6250936424ced8722329369da75935d61580fbarchard@google.com    }
13461dee6250936424ced8722329369da75935d61580fbarchard@google.com  }
13471dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
13481dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
13491dee6250936424ced8722329369da75935d61580fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
13501dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
13511dee6250936424ced8722329369da75935d61580fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1352b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
1353b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1354b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToYRow = ARGBToYRow_SSSE3;
1355b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
1356b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    }
1357a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
13581dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif  // HAS_ARGBTOUVROW_SSSE3
13591dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif  // HAS_ARGB1555TOYROW_NEON
1360a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
1361a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
13621dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGB1555TOYROW_NEON)
1363522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB1555ToUVRow(src_argb1555, src_stride_argb1555, dst_u, dst_v, width);
13641dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB1555ToYRow(src_argb1555, dst_y, width);
136595730719503137a7db61a105bec02220f9ed159efbarchard@google.com    ARGB1555ToYRow(src_argb1555 + src_stride_argb1555, dst_y + dst_stride_y,
136695730719503137a7db61a105bec02220f9ed159efbarchard@google.com                   width);
13671dee6250936424ced8722329369da75935d61580fbarchard@google.com#else
1368522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB1555ToARGBRow(src_argb1555, row, width);
1369d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGB1555ToARGBRow(src_argb1555 + src_stride_argb1555, row + kRowSize,
137095730719503137a7db61a105bec02220f9ed159efbarchard@google.com                      width);
1371d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
1372ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1373d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
13741dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
1375b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb1555 += src_stride_argb1555 * 2;
1376a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_y += dst_stride_y * 2;
1377a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_u += dst_stride_u;
1378a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_v += dst_stride_v;
1379a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1380a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height & 1) {
13811dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGB1555TOYROW_NEON)
1382522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB1555ToUVRow(src_argb1555, 0, dst_u, dst_v, width);
13831dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB1555ToYRow(src_argb1555, dst_y, width);
13841dee6250936424ced8722329369da75935d61580fbarchard@google.com#else
1385522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB1555ToARGBRow(src_argb1555, row, width);
1386522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGBToUVRow(row, 0, dst_u, dst_v, width);
1387ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
13881dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
1389a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1390d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#if !defined(HAS_ARGB1555TOYROW_NEON)
1391d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  free_aligned_buffer_64(row);
1392d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#endif
1393a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  return 0;
1394a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com}
1395a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
13961dee6250936424ced8722329369da75935d61580fbarchard@google.com// Convert ARGB4444 to I420.
1397d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API
1398b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.comint ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444,
13998798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_y, int dst_stride_y,
14008798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_u, int dst_stride_u,
14018798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   uint8* dst_v, int dst_stride_v,
14028798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com                   int width, int height) {
1403a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  int y;
1404a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#if defined(HAS_ARGB4444TOYROW_NEON)
1405a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB4444ToUVRow)(const uint8* src_argb4444, int src_stride_argb4444,
1406a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGB4444ToUVRow_C;
1407a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB4444ToYRow)(const uint8* src_argb4444, uint8* dst_y, int pix) =
1408a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGB4444ToYRow_C;
1409a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#else
1410a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGB4444ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
1411a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGB4444ToARGBRow_C;
1412a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
14138798e040758f2cd8f61342a3690446d72070bfb1fbarchard@google.com      uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
1414a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
1415a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com      ARGBToYRow_C;
1416a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  // Allocate 2 rows of ARGB.
1417a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  const int kRowSize = (width * 4 + 15) & ~15;
1418a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  align_buffer_64(row, kRowSize * 2);
1419a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com#endif
1420bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (!src_argb4444 || !dst_y || !dst_u || !dst_v ||
1421d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com      width <= 0 || height == 0) {
1422b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    return -1;
1423b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com  }
142425ba0211486c7fccd3d5bd024ee1ccece4f56a1bmikhal@webrtc.org  // Negative height means invert the image.
1425a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height < 0) {
1426a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    height = -height;
1427b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
1428b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_stride_argb4444 = -src_stride_argb4444;
1429a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1430522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com
1431522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com#if defined(HAS_ARGB4444TOYROW_NEON)
1432522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1433522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToYRow = ARGB4444ToYRow_Any_NEON;
1434522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
1435522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      ARGB4444ToYRow = ARGB4444ToYRow_NEON;
1436522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    }
1437522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    if (width >= 16) {
1438522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      ARGB4444ToUVRow = ARGB4444ToUVRow_Any_NEON;
1439522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      if (IS_ALIGNED(width, 16)) {
1440522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com        ARGB4444ToUVRow = ARGB4444ToUVRow_NEON;
1441522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com      }
1442522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    }
1443522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com  }
1444522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com#else  // HAS_ARGB4444TOYROW_NEON
1445d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com
1446ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#if defined(HAS_ARGB4444TOARGBROW_SSE2)
14471dee6250936424ced8722329369da75935d61580fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
14481dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
14491dee6250936424ced8722329369da75935d61580fbarchard@google.com    if (IS_ALIGNED(width, 8)) {
14501dee6250936424ced8722329369da75935d61580fbarchard@google.com      ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
14511dee6250936424ced8722329369da75935d61580fbarchard@google.com    }
14521dee6250936424ced8722329369da75935d61580fbarchard@google.com  }
1453b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com#endif
14541dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
1455bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1456bdf7cb591452611090922e690d5104a7d8c6b1e5fbarchard@google.com    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1457b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1458b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      ARGBToUVRow = ARGBToUVRow_SSSE3;
14591dee6250936424ced8722329369da75935d61580fbarchard@google.com    }
14601dee6250936424ced8722329369da75935d61580fbarchard@google.com  }
14611dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
14621dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGBTOUVROW_SSSE3)
14631dee6250936424ced8722329369da75935d61580fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
14641dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGBToYRow = ARGBToYRow_Any_SSSE3;
14651dee6250936424ced8722329369da75935d61580fbarchard@google.com    if (IS_ALIGNED(width, 16)) {
1466b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com      ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
1467b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1468b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com        ARGBToYRow = ARGBToYRow_SSSE3;
1469b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com      }
1470b1dd02d66cbda3e0c571bf81c247f850cdb3e2fdfbarchard@google.com    }
1471a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
14721dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif  // HAS_ARGBTOUVROW_SSSE3
14731dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif  // HAS_ARGB4444TOYROW_NEON
1474a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
1475a2fbf9dee675e2334f824fa908b2c946fe18382bfbarchard@google.com  for (y = 0; y < height - 1; y += 2) {
14761dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGB4444TOYROW_NEON)
1477522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToUVRow(src_argb4444, src_stride_argb4444, dst_u, dst_v, width);
14781dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB4444ToYRow(src_argb4444, dst_y, width);
1479522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToYRow(src_argb4444 + src_stride_argb4444, dst_y + dst_stride_y,
1480522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com                   width);
14811dee6250936424ced8722329369da75935d61580fbarchard@google.com#else
1482522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToARGBRow(src_argb4444, row, width);
1483d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGB4444ToARGBRow(src_argb4444 + src_stride_argb4444, row + kRowSize,
1484522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com                      width);
1485d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
1486ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
1487d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com    ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
14881dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
1489b95dbf24951d8b7118f680d75c7456a5f5d57bfffbarchard@google.com    src_argb4444 += src_stride_argb4444 * 2;
1490a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_y += dst_stride_y * 2;
1491a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_u += dst_stride_u;
1492a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com    dst_v += dst_stride_v;
1493a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1494a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  if (height & 1) {
14951dee6250936424ced8722329369da75935d61580fbarchard@google.com#if defined(HAS_ARGB4444TOYROW_NEON)
1496522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToUVRow(src_argb4444, 0, dst_u, dst_v, width);
14971dee6250936424ced8722329369da75935d61580fbarchard@google.com    ARGB4444ToYRow(src_argb4444, dst_y, width);
14981dee6250936424ced8722329369da75935d61580fbarchard@google.com#else
1499522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGB4444ToARGBRow(src_argb4444, row, width);
1500522d757c9257056020f058acc5a7c63e401ce019fbarchard@google.com    ARGBToUVRow(row, 0, dst_u, dst_v, width);
1501ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com    ARGBToYRow(row, dst_y, width);
15021dee6250936424ced8722329369da75935d61580fbarchard@google.com#endif
1503a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  }
1504d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#if !defined(HAS_ARGB4444TOYROW_NEON)
1505d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com  free_aligned_buffer_64(row);
1506d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com#endif
1507a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com  return 0;
1508a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com}
1509a7d977ceae6215332f359ab289a93460a24dc1e0fbarchard@google.com
1510fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#ifdef __cplusplus
1511fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com}  // extern "C"
1512fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com}  // namespace libyuv
1513fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#endif
1514