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