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/planar_functions.h"
12ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
13ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <string.h>  // for memset()
14ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
15ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/cpu_id.h"
16ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef HAVE_JPEG
17ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/mjpeg_decoder.h"
18ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
19ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/row.h"
20ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
21ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
22ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramaniannamespace libyuv {
23ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianextern "C" {
24ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
25ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
26ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy a plane of data
27ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
28ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid CopyPlane(const uint8* src_y, int src_stride_y,
29ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
30ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
31ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
32ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
33ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
34ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
35ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width) {
36ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
37ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
38ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_y = 0;
39ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
40ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Nothing to do.
41ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_y == dst_y && src_stride_y == dst_stride_y) {
42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
44da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_COPYROW_SSE2)
45da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
46da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2;
47ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
48ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
49da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_COPYROW_AVX)
50da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX)) {
51da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX;
52ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
53ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
54ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_ERMS)
55ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasERMS)) {
56ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_ERMS;
57ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
58ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
59ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_NEON)
60da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
61da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON;
62ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
63ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
64ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_MIPS)
65ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS)) {
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_MIPS;
67ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
68ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
69ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
70ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Copy plane
71ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
72ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow(src_y, dst_y, width);
73ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
74ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
75ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
76ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
77ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
78ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
79ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid CopyPlane_16(const uint16* src_y, int src_stride_y,
80ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint16* dst_y, int dst_stride_y,
81ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
82ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
83ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CopyRow)(const uint16* src, uint16* dst, int width) = CopyRow_16_C;
84ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
85ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
86ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width) {
87ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
88ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
89ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_y = 0;
90ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
91ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_SSE2)
92da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32)) {
93ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_SSE2;
94ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
96ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_ERMS)
97ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasERMS)) {
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_ERMS;
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_NEON)
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_NEON;
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_MIPS)
107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS)) {
108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_MIPS;
109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Copy plane
113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow(src_y, dst_y, width);
115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I422.
121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422Copy(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  int halfwidth = (width + 1) >> 1;
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_y || !dst_u || !dst_v ||
132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (height - 1) * src_stride_u;
140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (height - 1) * src_stride_v;
141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I444.
152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I444Copy(const uint8* src_y, int src_stride_y,
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_u, int src_stride_u,
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_v, int src_stride_v,
156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_y, int dst_stride_y,
157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_u, int dst_stride_u,
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_v, int dst_stride_v,
159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height) {
160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_y || !dst_u || !dst_v ||
162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (height - 1) * src_stride_u;
170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (height - 1) * src_stride_v;
171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I400.
183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I400ToI400(const uint8* src_y, int src_stride_y,
185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y || width <= 0 || height == 0) {
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I420 to I400.
201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420ToI400(const uint8* src_y, int src_stride_y,
203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y || width <= 0 || height == 0) {
208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror a plane of data.
221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid MirrorPlane(const uint8* src_y, int src_stride_y,
222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_y, int dst_stride_y,
223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*MirrorRow)(const uint8* src, uint8* dst, int width) = MirrorRow_C;
226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_NEON)
233da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
234da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    MirrorRow = MirrorRow_Any_NEON;
235da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
236da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      MirrorRow = MirrorRow_NEON;
237da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_SSE2)
241da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
242da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    MirrorRow = MirrorRow_Any_SSE2;
243da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
244da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      MirrorRow = MirrorRow_SSE2;
245da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_SSSE3)
249da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
250da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    MirrorRow = MirrorRow_Any_SSSE3;
251da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
252da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      MirrorRow = MirrorRow_SSSE3;
253da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_AVX2)
257da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
258da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    MirrorRow = MirrorRow_Any_AVX2;
259da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
260da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      MirrorRow = MirrorRow_AVX2;
261da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
262da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
263da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
264da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian// TODO(fbarchard): Mirror on mips handle unaligned memory.
265da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_MIPS_DSPR2)
266da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) &&
267da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
268da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 4) && IS_ALIGNED(dst_stride_y, 4)) {
269da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    MirrorRow = MirrorRow_MIPS_DSPR2;
270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Mirror plane
274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow(src_y, dst_y, width);
276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert YUY2 to I422.
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2,
284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*YUY2ToUV422Row)(const uint8* src_yuy2,
290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         uint8* dst_u, uint8* dst_v, int pix) =
291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row_C;
292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) =
293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow_C;
294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_yuy2 = -src_stride_yuy2;
299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_yuy2 == width * 2 &&
302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width &&
303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_u * 2 == width &&
304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_v * 2 == width) {
305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_yuy2 = dst_stride_y = dst_stride_u = dst_stride_v = 0;
308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_SSE2)
310da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2;
312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_SSE2;
313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
314da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_SSE2;
315da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_SSE2;
316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_AVX2)
320da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2;
322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_AVX2;
323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_AVX2;
325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_AVX2;
326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_NEON)
330da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_NEON;
332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (width >= 16) {
333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON;
334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_NEON;
337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_NEON;
338ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
344ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow(src_yuy2, dst_y, width);
345ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_yuy2 += src_stride_yuy2;
346ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
347ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_u += dst_stride_u;
348ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_v += dst_stride_v;
349ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
350ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
351ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
352ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
353ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert UYVY to I422.
354ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
355ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy,
356ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
357ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
358ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
359ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
360ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
361ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*UYVYToUV422Row)(const uint8* src_uyvy,
362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         uint8* dst_u, uint8* dst_v, int pix) =
363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row_C;
364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*UYVYToYRow)(const uint8* src_uyvy,
365ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_y, int pix) = UYVYToYRow_C;
366ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
367ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_uyvy = -src_stride_uyvy;
371ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
372ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
373ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_uyvy == width * 2 &&
374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width &&
375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_u * 2 == width &&
376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_v * 2 == width) {
377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
379ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_uyvy = dst_stride_y = dst_stride_u = dst_stride_v = 0;
380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
381ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_SSE2)
382da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
383ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row = UYVYToUV422Row_Any_SSE2;
384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_SSE2;
385ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
386da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_SSE2;
387da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_SSE2;
388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
389ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
390ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
391ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_AVX2)
392da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
393ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row = UYVYToUV422Row_Any_AVX2;
394ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_AVX2;
395ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_AVX2;
397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_AVX2;
398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
399ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
401ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_NEON)
402da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
403ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_NEON;
404ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (width >= 16) {
405ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_Any_NEON;
406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
407ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
408ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_NEON;
409ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_NEON;
410ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
414ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
415ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row(src_uyvy, dst_u, dst_v, width);
416ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow(src_uyvy, dst_y, width);
417ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_uyvy += src_stride_uyvy;
418ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
419ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_u += dst_stride_u;
420ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_v += dst_stride_v;
421ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
424ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
425ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror I400 with optional flipping
426ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
427ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I400Mirror(const uint8* src_y, int src_stride_y,
428ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y ||
431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
434ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
436ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
438ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
439ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
440ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
441ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
442ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
443ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
444ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror I420 with optional flipping
446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420Mirror(const uint8* src_y, int src_stride_y,
448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
449ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
450ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
452ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
453ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
454ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfheight = (height + 1) >> 1;
456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v || !dst_y || !dst_u || !dst_v ||
457ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    halfheight = (height + 1) >> 1;
464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
465ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (halfheight - 1) * src_stride_u;
466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (halfheight - 1) * src_stride_v;
467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_y) {
473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
478ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ARGB mirror.
481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
482ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBMirror(const uint8* src_argb, int src_stride_argb,
483ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_argb, int dst_stride_argb,
484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) =
487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMirrorRow_C;
488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
494ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
495ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
497da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_NEON)
498da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
499da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_Any_NEON;
500da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
501da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBMirrorRow = ARGBMirrorRow_NEON;
502da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
505da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_SSE2)
506da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
507da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_Any_SSE2;
508da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
509da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBMirrorRow = ARGBMirrorRow_SSE2;
510da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
513da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_AVX2)
514da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
515da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_Any_AVX2;
516da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
517da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBMirrorRow = ARGBMirrorRow_AVX2;
518da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
521ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
522ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Mirror plane
523ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
524ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMirrorRow(src_argb, dst_argb, width);
525ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
530ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
531da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian// Get a blender that optimized for the CPU and pixel count.
532ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// As there are 6 blenders to choose from, the caller should try to use
533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// the same blend function for all pixels if possible.
534ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianARGBBlendRow GetARGBBlend() {
536ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
537ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int width) = ARGBBlendRow_C;
538ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_SSSE3)
539ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_SSSE3;
541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return ARGBBlendRow;
542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
543ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
544ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_SSE2)
545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_SSE2;
547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_NEON)
550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_NEON;
552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBBlendRow;
555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Alpha Blend 2 ARGB images and store to destination.
558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
559ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBBlend(const uint8* src_argb0, int src_stride_argb0,
560ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              const uint8* src_argb1, int src_stride_argb1,
561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height) {
563ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
564ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
565ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int width) = GetARGBBlend();
566ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
567ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
568ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
570ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
576ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
578ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
579ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
580ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
581ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
582ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
584ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
585ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow(src_argb0, src_argb1, dst_argb, width);
586ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
591ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
592ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
593ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Multiply 2 ARGB images and store to destination.
594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
595ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBMultiply(const uint8* src_argb0, int src_stride_argb0,
596ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_argb1, int src_stride_argb1,
597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_argb, int dst_stride_argb,
598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBMultiplyRow)(const uint8* src0, const uint8* src1, uint8* dst,
601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = ARGBMultiplyRow_C;
602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
605ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
606ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
610ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
611ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
618ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_SSE2)
620da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
621ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_SSE2;
622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_SSE2;
624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
626ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
627ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_AVX2)
628da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
629ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_AVX2;
630ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
631ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_AVX2;
632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
633ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
634ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
635ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_NEON)
636da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
637ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_NEON;
638ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
639ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_NEON;
640ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
641ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
642ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
643ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Multiply plane
645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
646ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow(src_argb0, src_argb1, dst_argb, width);
647ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
648ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
649ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
650ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
651ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
652ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
653ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
654ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Add 2 ARGB images and store to destination.
655ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
656ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBAdd(const uint8* src_argb0, int src_stride_argb0,
657ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            const uint8* src_argb1, int src_stride_argb1,
658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            uint8* dst_argb, int dst_stride_argb,
659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            int width, int height) {
660ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
661ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBAddRow)(const uint8* src0, const uint8* src1, uint8* dst,
662ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width) = ARGBAddRow_C;
663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
664ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
665ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
666ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
667ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
668ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
669ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
670ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
677ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
678ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
679ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
680da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_SSE2) && (defined(_MSC_VER) && !defined(__clang__))
681ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
682ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_SSE2;
683ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
684ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
685da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_SSE2) && !(defined(_MSC_VER) && !defined(__clang__))
686da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
687ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_SSE2;
688ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
689ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_SSE2;
690ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
691ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
692ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_AVX2)
694da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
695ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_AVX2;
696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
697ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_AVX2;
698ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
699ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
700ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
701ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_NEON)
702da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
703ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_NEON;
704ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_NEON;
706ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
709ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
710ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Add plane
711ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
712ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow(src_argb0, src_argb1, dst_argb, width);
713ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
714ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
715ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
716ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
717ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
718ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
719ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
720ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Subtract 2 ARGB images and store to destination.
721ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
722ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSubtract(const uint8* src_argb0, int src_stride_argb0,
723ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_argb1, int src_stride_argb1,
724ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_argb, int dst_stride_argb,
725ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
727ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBSubtractRow)(const uint8* src0, const uint8* src1, uint8* dst,
728ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = ARGBSubtractRow_C;
729ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
730ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
731ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
732ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
733ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
734ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
735ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
736ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
737ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
738ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
739ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
740ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
742ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
744ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
745ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
746ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_SSE2)
747da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
748ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_SSE2;
749ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
750ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_SSE2;
751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
752ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
753ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
754ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_AVX2)
755da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
756ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_AVX2;
757ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_AVX2;
759ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
760ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
761ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
762ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_NEON)
763da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
764ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_NEON;
765ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
766ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_NEON;
767ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
768ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Subtract plane
772ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
773ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow(src_argb0, src_argb1, dst_argb, width);
774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
775ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
776ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
777ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
778ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
779ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
780ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
781ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to BGRA.
782ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
783ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToBGRA(const uint8* src_y, int src_stride_y,
784ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
785ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_bgra, int dst_stride_bgra,
787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
788ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
789ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToBGRARow)(const uint8* y_buf,
790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
792ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
793ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToBGRARow_C;
794ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
795ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_bgra ||
796ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
797ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
798ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
799ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
801ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra;
803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_bgra = -dst_stride_bgra;
804ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
807ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
808ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
809ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_bgra == width * 4) {
810ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
812ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_bgra = 0;
813ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
814da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOBGRAROW_SSSE3)
815da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
816da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_Any_SSSE3;
817da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
818da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToBGRARow = I422ToBGRARow_SSSE3;
819da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
820da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
821da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
822da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOBGRAROW_AVX2)
823da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
824da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_Any_AVX2;
825ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
826da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToBGRARow = I422ToBGRARow_AVX2;
827ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
828ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
829da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
830da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOBGRAROW_NEON)
831da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
832da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_Any_NEON;
833ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
834da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToBGRARow = I422ToBGRARow_NEON;
835ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
836ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
837da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
838da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOBGRAROW_MIPS_DSPR2)
839ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
840ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
841ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
842ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
843ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) {
844ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2;
845ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
846ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
847ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
848ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
849ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width);
850ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_bgra += dst_stride_bgra;
851ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
852ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
853ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
854ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
855ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
856ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
857ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
858ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to ABGR.
859ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
860ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToABGR(const uint8* src_y, int src_stride_y,
861ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
863ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_abgr, int dst_stride_abgr,
864ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
865ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
866ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToABGRRow)(const uint8* y_buf,
867ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
868ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
869ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
870ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToABGRRow_C;
871ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
872ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_abgr ||
873ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
874ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
875ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
876ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
877ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
878ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
879ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr;
880ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_abgr = -dst_stride_abgr;
881ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
882ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
883ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
884ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
885ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
886ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_abgr == width * 4) {
887ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
888ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
889ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0;
890ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
891ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOABGRROW_NEON)
892da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
893ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow = I422ToABGRRow_Any_NEON;
894da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
895ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToABGRRow = I422ToABGRRow_NEON;
896ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
897ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
898da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
899da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOABGRROW_SSSE3)
900da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
901ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow = I422ToABGRRow_Any_SSSE3;
902ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
903da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToABGRRow = I422ToABGRRow_SSSE3;
904da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
905da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
906da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
907da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TOABGRROW_AVX2)
908da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
909da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    I422ToABGRRow = I422ToABGRRow_Any_AVX2;
910da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
911da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToABGRRow = I422ToABGRRow_AVX2;
912ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
913ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
914ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
915ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
916ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
917ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width);
918ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_abgr += dst_stride_abgr;
919ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
920ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
921ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
922ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
923ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
924ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
925ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
926ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to RGBA.
927ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
928ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToRGBA(const uint8* src_y, int src_stride_y,
929ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
930ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
931ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_rgba, int dst_stride_rgba,
932ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
933ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
934ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToRGBARow)(const uint8* y_buf,
935ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
936ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
937ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
938ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToRGBARow_C;
939ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
940ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_rgba ||
941ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
942ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
943ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
944ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
945ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
946ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
947ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
948ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgba = -dst_stride_rgba;
949ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
950ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
951ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
952ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
953ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
954ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_rgba == width * 4) {
955ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
956ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
957ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_rgba = 0;
958ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
959ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TORGBAROW_NEON)
960da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
961ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow = I422ToRGBARow_Any_NEON;
962da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
963ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToRGBARow = I422ToRGBARow_NEON;
964ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
965ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
966da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
967da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TORGBAROW_SSSE3)
968da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
969ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
970ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
971da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToRGBARow = I422ToRGBARow_SSSE3;
972da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
973da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
974da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
975da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_I422TORGBAROW_AVX2)
976da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
977da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    I422ToRGBARow = I422ToRGBARow_Any_AVX2;
978da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
979da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      I422ToRGBARow = I422ToRGBARow_AVX2;
980ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
981ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
982ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
983ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
984ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
985ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width);
986ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgba += dst_stride_rgba;
987ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
988ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
989ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
990ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
991ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
992ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
994ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert NV12 to RGB565.
995ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
996ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint NV12ToRGB565(const uint8* src_y, int src_stride_y,
997ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_uv, int src_stride_uv,
998ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_rgb565, int dst_stride_rgb565,
999ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
1000ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1001ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*NV12ToRGB565Row)(const uint8* y_buf,
1002ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          const uint8* uv_buf,
1003ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* rgb_buf,
1004ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = NV12ToRGB565Row_C;
1005ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_uv || !dst_rgb565 ||
1006ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
1007ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1008ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1009ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1010ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1011ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1012ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
1013ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgb565 = -dst_stride_rgb565;
1014ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1015ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_NV12TORGB565ROW_SSSE3)
1016da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1017ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
1018ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1019ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
1020ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1021ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1022da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1023da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_NV12TORGB565ROW_AVX2)
1024da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1025da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
1026da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
1027da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
1028da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
1029da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1030da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1031da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_NV12TORGB565ROW_NEON)
1032da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1033ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
1034ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1035ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV12ToRGB565Row = NV12ToRGB565Row_NEON;
1036ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1037ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1038ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1039ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1040ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1041ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row(src_y, src_uv, dst_rgb565, width);
1042ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 += dst_stride_rgb565;
1043ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
1044ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (y & 1) {
1045ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_uv += src_stride_uv;
1046ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1047ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1048ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1049ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1050ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1051ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert NV21 to RGB565.
1052ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1053ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint NV21ToRGB565(const uint8* src_y, int src_stride_y,
1054ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_vu, int src_stride_vu,
1055ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_rgb565, int dst_stride_rgb565,
1056ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
1057ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1058ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*NV21ToRGB565Row)(const uint8* y_buf,
1059ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          const uint8* src_vu,
1060ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* rgb_buf,
1061ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = NV21ToRGB565Row_C;
1062ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_vu || !dst_rgb565 ||
1063ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
1064ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1065ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1066ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1067ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1068ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1069ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
1070ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgb565 = -dst_stride_rgb565;
1071ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1072ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_NV21TORGB565ROW_SSSE3)
1073da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1074ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row = NV21ToRGB565Row_Any_SSSE3;
1075ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1076ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV21ToRGB565Row = NV21ToRGB565Row_SSSE3;
1077ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1078ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1079da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1080da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_NV21TORGB565ROW_AVX2)
1081da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1082da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    NV21ToRGB565Row = NV21ToRGB565Row_Any_AVX2;
1083da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
1084da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      NV21ToRGB565Row = NV21ToRGB565Row_AVX2;
1085da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
1086da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1087da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1088da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_NV21TORGB565ROW_NEON)
1089da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1090ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row = NV21ToRGB565Row_Any_NEON;
1091ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1092ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV21ToRGB565Row = NV21ToRGB565Row_NEON;
1093ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1094ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1095ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1096ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1097ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1098ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row(src_y, src_vu, dst_rgb565, width);
1099ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 += dst_stride_rgb565;
1100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
1101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (y & 1) {
1102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_vu += src_stride_vu;
1103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid SetPlane(uint8* dst_y, int dst_stride_y,
1110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height,
1111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint32 value) {
1112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1113da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*SetRow)(uint8* dst, uint8 value, int pix) = SetRow_C;
1114da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (height < 0) {
1115da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    height = -height;
1116da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    dst_y = dst_y + (height - 1) * dst_stride_y;
1117da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    dst_stride_y = -dst_stride_y;
1118da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_y == width) {
1121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_y = 0;
1124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_NEON)
1126da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1127da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SetRow = SetRow_Any_NEON;
1128da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
1129da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SetRow = SetRow_NEON;
1130da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
1131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_X86)
1134da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1135da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SetRow = SetRow_Any_X86;
1136da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1137da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SetRow = SetRow_X86;
1138da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
1139da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1140da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1141da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SETROW_ERMS)
1142da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasERMS)) {
1143da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SetRow = SetRow_ERMS;
1144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Set plane
1148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1149da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SetRow(dst_y, value, width);
1150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
1151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Draw a rectangle into I420
1155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420Rect(uint8* dst_y, int dst_stride_y,
1157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_u, int dst_stride_u,
1158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_v, int dst_stride_v,
1159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int x, int y,
1160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height,
1161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int value_y, int value_u, int value_v) {
1162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
1163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfheight = (height + 1) >> 1;
1164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_y = dst_y + y * dst_stride_y + x;
1165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2);
1166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2);
1167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_y || !dst_u || !dst_v ||
1168da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      width <= 0 || height == 0 ||
1169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      x < 0 || y < 0 ||
1170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_y < 0 || value_y > 255 ||
1171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_u < 0 || value_u > 255 ||
1172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_v < 0 || value_v > 255) {
1173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_y, dst_stride_y, width, height, value_y);
1177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u);
1178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v);
1179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Draw a rectangle into ARGB
1183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBRect(uint8* dst_argb, int dst_stride_argb,
1185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int dst_x, int dst_y,
1186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height,
1187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint32 value) {
1188da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  int y;
1189da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*ARGBSetRow)(uint8* dst_argb, uint32 value, int pix) = ARGBSetRow_C;
1190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb ||
1191da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      width <= 0 || height == 0 ||
1192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1195da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (height < 0) {
1196da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    height = -height;
1197da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1198da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
1199da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  dst_argb += dst_y * dst_stride_argb + dst_x * 4;
1201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1207da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
1208da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBSETROW_NEON)
1209da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1210da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBSetRow = ARGBSetRow_Any_NEON;
1211da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1212da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBSetRow = ARGBSetRow_NEON;
1213da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
1214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1216da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBSETROW_X86)
1217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1218da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBSetRow = ARGBSetRow_X86;
1219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1221da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
1222da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  // Set plane
1223da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1224da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBSetRow(dst_argb, value, width);
1225da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1226da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
1227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert unattentuated ARGB to preattenuated ARGB.
1231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// An unattenutated ARGB alpha blend uses the formula
1232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// p = a * f + (1 - a) * b
1233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where
1234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   p is output pixel
1235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   f is foreground pixel
1236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   b is background pixel
1237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   a is alpha value from foreground pixel
1238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// An preattenutated ARGB alpha blend uses the formula
1239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// p = f + (1 - a) * b
1240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where
1241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   f is foreground pixel premultiplied by alpha
1242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
1245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* dst_argb, int dst_stride_argb,
1246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
1247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb,
1249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int width) = ARGBAttenuateRow_C;
1250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_SSE2)
1266da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSE2;
1268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_SSE2;
1270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_SSSE3)
1274da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_AVX2)
1282da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_NEON)
1290da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow(src_argb, dst_argb, width);
1300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert preattentuated ARGB to unattenuated ARGB.
1307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
1309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1310ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height) {
1311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBUnattenuateRow)(const uint8* src_argb, uint8* dst_argb,
1313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int width) = ARGBUnattenuateRow_C;
1314ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1315ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1320ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBUNATTENUATEROW_SSE2)
1330da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_SSE2;
1332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBUnattenuateRow = ARGBUnattenuateRow_SSE2;
1334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBUNATTENUATEROW_AVX2)
1338da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_AVX2;
1340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBUnattenuateRow = ARGBUnattenuateRow_AVX2;
1342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1344ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1345ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// TODO(fbarchard): Neon version.
1346ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1347ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1348ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow(src_argb, dst_argb, width);
1349ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1350ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1351ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1352ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1353ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1354ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1355ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert ARGB to Grayed ARGB.
1356ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1357ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBGrayTo(const uint8* src_argb, int src_stride_argb,
1358ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_argb, int dst_stride_argb,
1359ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
1360ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1361ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
1362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int width) = ARGBGrayRow_C;
1363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1365ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1366ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1367ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1371ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1372ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1373ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_SSSE3)
1379da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) {
1380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_SSSE3;
1381ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1382da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1383da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_NEON)
1384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1385ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_NEON;
1386ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1387ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1389ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1390ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow(src_argb, dst_argb, width);
1391ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1392ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1393ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1394ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1395ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Make a rectangle of ARGB gray scale.
1398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1399ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBGray(uint8* dst_argb, int dst_stride_argb,
1400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int dst_x, int dst_y,
1401ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height) {
1402ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1403ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
1404ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int width) = ARGBGrayRow_C;
1405ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
1407ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1408ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1409ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1410ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1414ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1415ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_SSSE3)
1416da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) {
1417ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_SSSE3;
1418ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1419da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1420da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_NEON)
1421ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_NEON;
1423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1424ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1425ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1426ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow(dst, dst, width);
1427ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1428ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Make a rectangle of ARGB Sepia tone.
1433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1434ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSepia(uint8* dst_argb, int dst_stride_argb,
1435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int dst_x, int dst_y, int width, int height) {
1436ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBSepiaRow)(uint8* dst_argb, int width) = ARGBSepiaRow_C;
1438ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1439ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
1440ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1441ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1442ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1443ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1444ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSEPIAROW_SSSE3)
1449da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) {
1450ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow = ARGBSepiaRow_SSSE3;
1451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1452da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1453da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBSEPIAROW_NEON)
1454ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow = ARGBSepiaRow_NEON;
1456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1457ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow(dst, width);
1460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1465ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x4 matrix to each ARGB pixel.
1466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Note: Normally for shading, but can be used to swizzle or invert.
1467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBColorMatrix(const uint8* src_argb, int src_stride_argb,
1469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const int8* matrix_argb,
1471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height) {
1472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBColorMatrixRow)(const uint8* src_argb, uint8* dst_argb,
1474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int8* matrix_argb, int width) = ARGBColorMatrixRow_C;
1475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !matrix_argb || width <= 0 || height == 0) {
1476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1478ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1482ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1483ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOLORMATRIXROW_SSSE3)
1491da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) {
1492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow = ARGBColorMatrixRow_SSSE3;
1493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1494da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1495da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBCOLORMATRIXROW_NEON)
1496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1497ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow = ARGBColorMatrixRow_NEON;
1498ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1499ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1501ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow(src_argb, dst_argb, matrix_argb, width);
1502ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1505ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1506ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1507ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1508ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x3 matrix to each ARGB pixel.
1509ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Deprecated.
1510ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint RGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
1512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const int8* matrix_rgb,
1513ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int dst_x, int dst_y, int width, int height) {
1514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SIMD_ALIGNED(int8 matrix_argb[16]);
1515ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1516ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !matrix_rgb || width <= 0 || height <= 0 ||
1517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1521ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Convert 4x3 7 bit matrix to 4x4 6 bit matrix.
1522ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[0] = matrix_rgb[0] / 2;
1523ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[1] = matrix_rgb[1] / 2;
1524ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[2] = matrix_rgb[2] / 2;
1525ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[3] = matrix_rgb[3] / 2;
1526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[4] = matrix_rgb[4] / 2;
1527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[5] = matrix_rgb[5] / 2;
1528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[6] = matrix_rgb[6] / 2;
1529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[7] = matrix_rgb[7] / 2;
1530ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[8] = matrix_rgb[8] / 2;
1531ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[9] = matrix_rgb[9] / 2;
1532ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[10] = matrix_rgb[10] / 2;
1533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[11] = matrix_rgb[11] / 2;
1534ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[14] = matrix_argb[13] = matrix_argb[12] = 0;
1535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[15] = 64;  // 1.0
1536ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1537ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBColorMatrix((const uint8*)(dst), dst_stride_argb,
1538ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         dst, dst_stride_argb,
1539ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         &matrix_argb[0], width, height);
1540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a color table each ARGB pixel.
1543ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Table contains 256 ARGB values.
1544ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBColorTable(uint8* dst_argb, int dst_stride_argb,
1546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const uint8* table_argb,
1547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int dst_x, int dst_y, int width, int height) {
1548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
1550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int width) = ARGBColorTableRow_C;
1551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
1553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1559ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1560ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOLORTABLEROW_X86)
1563ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1564ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorTableRow = ARGBColorTableRow_X86;
1565ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1566ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1567ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1568ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorTableRow(dst, table_argb, width);
1569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1570ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a color table each ARGB pixel but preserve destination alpha.
1575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Table contains 256 ARGB values.
1576ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint RGBColorTable(uint8* dst_argb, int dst_stride_argb,
1578ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  const uint8* table_argb,
1579ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int dst_x, int dst_y, int width, int height) {
1580ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1581ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*RGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
1582ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int width) = RGBColorTableRow_C;
1583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1584ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
1585ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1586ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1591ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1592ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1593ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_RGBCOLORTABLEROW_X86)
1595ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1596ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    RGBColorTableRow = RGBColorTableRow_X86;
1597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    RGBColorTableRow(dst, table_argb, width);
1601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1605ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1606ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ARGBQuantize is used to posterize art.
1607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// e.g. rgb / qvalue * qvalue + qvalue / 2
1608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// But the low levels implement efficiently with 3 parameters, and could be
1609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// used for other high level operations.
1610ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset;
1611ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where scale is 1 / interval_size as a fixed point value.
1612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// The divide is replaces with a multiply by reciprocal fixed point multiply.
1613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Caveat - although SSE2 saturates, the C function does not and should be used
1614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// with care if doing anything but quantization.
1615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBQuantize(uint8* dst_argb, int dst_stride_argb,
1617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int scale, int interval_size, int interval_offset,
1618ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int dst_x, int dst_y, int width, int height) {
1619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1620ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBQuantizeRow)(uint8* dst_argb, int scale, int interval_size,
1621ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int interval_offset, int width) = ARGBQuantizeRow_C;
1622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0 ||
1624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      interval_size < 1 || interval_size > 255) {
1625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1626ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1627ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1628ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1629ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1630ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1631ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1633ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBQUANTIZEROW_SSE2)
1634da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4)) {
1635ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow = ARGBQuantizeRow_SSE2;
1636ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1637da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1638da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBQUANTIZEROW_NEON)
1639ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1640ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow = ARGBQuantizeRow_NEON;
1641ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1642ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1643ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow(dst, scale, interval_size, interval_offset, width);
1645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1646ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1647ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1648ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1649ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1650ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Computes table of cumulative sum for image where the value is the sum
1651ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// of all values above and to the left of the entry. Used by ARGBBlur.
1652ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1653ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb,
1654ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int32* dst_cumsum, int dst_stride32_cumsum,
1655ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int width, int height) {
1656ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1657ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ComputeCumulativeSumRow)(const uint8* row, int32* cumsum,
1658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
1659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* previous_cumsum = dst_cumsum;
1660ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_cumsum || !src_argb || width <= 0 || height <= 0) {
1661ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1662ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
1664ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1665ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
1666ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1667ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1668ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  memset(dst_cumsum, 0, width * sizeof(dst_cumsum[0]) * 4);  // 4 int per pixel.
1669ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1670ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow(src_argb, dst_cumsum, previous_cumsum, width);
1671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    previous_cumsum = dst_cumsum;
1672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_cumsum += dst_stride32_cumsum;
1673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1677ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1678ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Blur ARGB image.
1679ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Caller should allocate CumulativeSum table of width * height * 16 bytes
1680ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// aligned to 16 byte boundary. height can be radius * 2 + 2 to save memory
1681ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// as the buffer is treated as circular.
1682ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1683ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBBlur(const uint8* src_argb, int src_stride_argb,
1684ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_argb, int dst_stride_argb,
1685ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int32* dst_cumsum, int dst_stride32_cumsum,
1686ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height, int radius) {
1687ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1688ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ComputeCumulativeSumRow)(const uint8 *row, int32 *cumsum,
1689ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
1690ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CumulativeSumToAverageRow)(const int32* topleft, const int32* botleft,
1691ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int width, int area, uint8* dst, int count) = CumulativeSumToAverageRow_C;
1692ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* cumsum_bot_row;
1693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* max_cumsum_bot_row;
1694ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* cumsum_top_row;
1695ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1697ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1698ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1699ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1700ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1701ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1702ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1703ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1704ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius > height) {
1705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    radius = height;
1706ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius > (width / 2 - 1)) {
1708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    radius = width / 2 - 1;
1709ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1710ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius <= 0) {
1711ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1712ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1713ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
1714ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1715ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
1716ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CumulativeSumToAverageRow = CumulativeSumToAverageRow_SSE2;
1717ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1718ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1719ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Compute enough CumulativeSum for first row to be blurred. After this
1720ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // one row of CumulativeSum is updated at a time.
1721ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ARGBComputeCumulativeSum(src_argb, src_stride_argb,
1722ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           dst_cumsum, dst_stride32_cumsum,
1723ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           width, radius);
1724ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1725ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_argb = src_argb + radius * src_stride_argb;
1726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  cumsum_bot_row = &dst_cumsum[(radius - 1) * dst_stride32_cumsum];
1727ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1728ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  max_cumsum_bot_row = &dst_cumsum[(radius * 2 + 2) * dst_stride32_cumsum];
1729ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  cumsum_top_row = &dst_cumsum[0];
1730ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1731ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1732ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int top_y = ((y - radius - 1) >= 0) ? (y - radius - 1) : 0;
1733ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int bot_y = ((y + radius) < height) ? (y + radius) : (height - 1);
1734ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int area = radius * (bot_y - top_y);
1735ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int boxwidth = radius * 4;
1736ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int x;
1737ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int n;
1738ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1739ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Increment cumsum_top_row pointer with circular buffer wrap around.
1740ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (top_y) {
1741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      cumsum_top_row += dst_stride32_cumsum;
1742ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (cumsum_top_row >= max_cumsum_bot_row) {
1743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        cumsum_top_row = dst_cumsum;
1744ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1745ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1746ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Increment cumsum_bot_row pointer with circular buffer wrap around and
1747ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // then fill in a row of CumulativeSum.
1748ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if ((y + radius) < height) {
1749ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* prev_cumsum_bot_row = cumsum_bot_row;
1750ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      cumsum_bot_row += dst_stride32_cumsum;
1751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (cumsum_bot_row >= max_cumsum_bot_row) {
1752ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        cumsum_bot_row = dst_cumsum;
1753ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1754ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ComputeCumulativeSumRow(src_argb, cumsum_bot_row, prev_cumsum_bot_row,
1755ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              width);
1756ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_argb += src_stride_argb;
1757ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1759ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Left clipped.
1760ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (x = 0; x < radius + 1; ++x) {
1761ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
1762ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                boxwidth, area, &dst_argb[x * 4], 1);
1763ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      area += (bot_y - top_y);
1764ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      boxwidth += 4;
1765ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1766ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1767ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Middle unclipped.
1768ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    n = (width - 1) - radius - x + 1;
1769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
1770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              boxwidth, area, &dst_argb[x * 4], n);
1771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1772ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Right clipped.
1773ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (x += n; x <= width - 1; ++x) {
1774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      area -= (bot_y - top_y);
1775ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      boxwidth -= 4;
1776ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      CumulativeSumToAverageRow(cumsum_top_row + (x - radius - 1) * 4,
1777ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                cumsum_bot_row + (x - radius - 1) * 4,
1778ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                boxwidth, area, &dst_argb[x * 4], 1);
1779ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1780ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1781ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1782ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1783ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1784ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1785ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Multiply ARGB image by a specified ARGB value.
1786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBShade(const uint8* src_argb, int src_stride_argb,
1788ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
1789ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height, uint32 value) {
1790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBShadeRow)(const uint8* src_argb, uint8* dst_argb,
1792ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       int width, uint32 value) = ARGBShadeRow_C;
1793ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0 || value == 0u) {
1794ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1795ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1796ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1797ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1798ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1799ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1801ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1804ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1807ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1808ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHADEROW_SSE2)
1809da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4)) {
1810ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow = ARGBShadeRow_SSE2;
1811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1812da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
1813da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBSHADEROW_NEON)
1814ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1815ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow = ARGBShadeRow_NEON;
1816ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1817ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1818ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1819ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1820ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow(src_argb, dst_argb, width, value);
1821ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1822ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1823ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1824ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1825ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1826ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1827ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Interpolate 2 ARGB images by specified amount (0 to 255).
1828ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1829ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
1830ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const uint8* src_argb1, int src_stride_argb1,
1831ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1832ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height, int interpolation) {
1833ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1834ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
1835ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         ptrdiff_t src_stride, int dst_width,
1836ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         int source_y_fraction) = InterpolateRow_C;
1837ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
1838ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1839ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1840ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1841ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1842ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1843ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1844ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
1845ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1846ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1847ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
1848ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
1849ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1850ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1851ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1852ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
1853ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1854ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
1855da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1856ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
1857ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1858da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSE2;
1859ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1860ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1861ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
1863da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1864ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
1865ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1866da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSSE3;
1867ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1868ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1869ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1870ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
1871da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1872ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
1873ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1874ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
1875ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1876ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1877ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1878ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
1879da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1880ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
1881ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1882ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
1883ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1884ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1885ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1886da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2)
1887da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) &&
1888ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) &&
1889ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) &&
1890ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
1891da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_MIPS_DSPR2;
1892ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1893ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1894ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1895ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1896ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0,
1897ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   width * 4, interpolation);
1898ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
1899ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
1900ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1901ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1902ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1903ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1904ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1905ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Shuffle ARGB channel order.  e.g. BGRA to ARGB.
1906ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1907ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBShuffle(const uint8* src_bgra, int src_stride_bgra,
1908ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                uint8* dst_argb, int dst_stride_argb,
1909ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                const uint8* shuffler, int width, int height) {
1910ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1911ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb,
1912ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         const uint8* shuffler, int pix) = ARGBShuffleRow_C;
1913ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_bgra || !dst_argb ||
1914ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
1915ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1916ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1917ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1918ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1919ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1920ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_bgra = src_bgra + (height - 1) * src_stride_bgra;
1921ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_bgra = -src_stride_bgra;
1922ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1923ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1924ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_bgra == width * 4 &&
1925ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1926ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1927ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1928ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_bgra = dst_stride_argb = 0;
1929ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1930ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_SSE2)
1931da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1932ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_SSE2;
1933ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1934ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_SSE2;
1935ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1936ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1937ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1938ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_SSSE3)
1939da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1940ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_SSSE3;
1941ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1942da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_SSSE3;
1943ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1944ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1945ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1946ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_AVX2)
1947da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
1948ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_AVX2;
1949ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
1950ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_AVX2;
1951ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1952ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1953ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1954ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_NEON)
1955da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1956ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_NEON;
1957ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1958ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_NEON;
1959ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1960ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1961ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1962ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1963ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1964ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow(src_bgra, dst_argb, shuffler, width);
1965ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_bgra += src_stride_bgra;
1966ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1967ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1968ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1969ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1970ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1971ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect.
1972ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int ARGBSobelize(const uint8* src_argb, int src_stride_argb,
1973ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* dst_argb, int dst_stride_argb,
1974ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width, int height,
1975ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        void (*SobelRow)(const uint8* src_sobelx,
1976ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         const uint8* src_sobely,
1977ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         uint8* dst, int width)) {
1978ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1979da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_g, int pix) =
1980da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBToYJRow_C;
1981ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1,
1982ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_sobely, int width) = SobelYRow_C;
1983ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1,
1984ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const uint8* src_y2, uint8* dst_sobely, int width) =
1985ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelXRow_C;
1986ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int kEdge = 16;  // Extra pixels at start of row for extrude/align.
1987ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb  || !dst_argb || width <= 0 || height == 0) {
1988ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1989ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1990ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1991ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1992ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
1994ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1995ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1996da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
1997da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBTOYJROW_SSSE3)
1998da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
1999da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2000da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2001da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBToYJRow = ARGBToYJRow_SSSE3;
2002ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
2003ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2004ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2005da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBTOYJROW_AVX2)
2006da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
2007da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2008da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
2009da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBToYJRow = ARGBToYJRow_AVX2;
2010ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
2011ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2012ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2013da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_ARGBTOYJROW_NEON)
2014da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2015da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBToYJRow = ARGBToYJRow_Any_NEON;
2016ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
2017da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBToYJRow = ARGBToYJRow_NEON;
2018ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
2019ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2020ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2021da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2022ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELYROW_SSE2)
2023ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2024ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelYRow = SobelYRow_SSE2;
2025ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2026ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2027ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELYROW_NEON)
2028ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2029ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelYRow = SobelYRow_NEON;
2030ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2031ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2032ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXROW_SSE2)
2033ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2034ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXRow = SobelXRow_SSE2;
2035ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2036ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2037ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXROW_NEON)
2038ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2039ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXRow = SobelXRow_NEON;
2040ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2041ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2042ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  {
2043ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // 3 rows with edges before/after.
2044da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    const int kRowSize = (width + kEdge + 31) & ~31;
2045ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge));
2046ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_sobelx = rows;
2047ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_sobely = rows + kRowSize;
2048ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y = rows + kRowSize * 2;
2049ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2050ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Convert first row.
2051ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y0 = row_y + kEdge;
2052ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y1 = row_y0 + kRowSize;
2053ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y2 = row_y1 + kRowSize;
2054da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBToYJRow(src_argb, row_y0, width);
2055ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    row_y0[-1] = row_y0[0];
2056ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y0 + width, row_y0[width - 1], 16);  // Extrude 16 for valgrind.
2057da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    ARGBToYJRow(src_argb, row_y1, width);
2058ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    row_y1[-1] = row_y1[0];
2059ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y1 + width, row_y1[width - 1], 16);
2060ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y2 + width, 0, 16);
2061ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2062ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (y = 0; y < height; ++y) {
2063da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      // Convert next row of ARGB to G.
2064ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (y < (height - 1)) {
2065ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_argb += src_stride_argb;
2066ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
2067da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      ARGBToYJRow(src_argb, row_y2, width);
2068ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      row_y2[-1] = row_y2[0];
2069ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      row_y2[width] = row_y2[width - 1];
2070ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2071ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width);
2072ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width);
2073ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelRow(row_sobelx, row_sobely, dst_argb, width);
2074ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2075ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Cycle thru circular queue of 3 row_y buffers.
2076ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      {
2077ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        uint8* row_yt = row_y0;
2078ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y0 = row_y1;
2079ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y1 = row_y2;
2080ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y2 = row_yt;
2081ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
2082ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2083ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_argb += dst_stride_argb;
2084ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
2085ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    free_aligned_buffer_64(rows);
2086ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2087ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2088ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2089ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2090ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect.
2091ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2092ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobel(const uint8* src_argb, int src_stride_argb,
2093ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
2094ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height) {
2095ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely,
2096ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   uint8* dst_argb, int width) = SobelRow_C;
2097ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELROW_SSE2)
2098da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2099da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelRow = SobelRow_Any_SSE2;
2100da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2101da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelRow = SobelRow_SSE2;
2102da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELROW_NEON)
2106da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2107da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelRow = SobelRow_Any_NEON;
2108da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
2109da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelRow = SobelRow_NEON;
2110da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
2114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelRow);
2115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect with planar output.
2118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb,
2120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_y, int dst_stride_y,
2121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width, int height) {
2122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely,
2123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* dst_, int width) = SobelToPlaneRow_C;
2124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELTOPLANEROW_SSE2)
2125da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2126da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelToPlaneRow = SobelToPlaneRow_Any_SSE2;
2127da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2128da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelToPlaneRow = SobelToPlaneRow_SSE2;
2129da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELTOPLANEROW_NEON)
2133da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2134da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelToPlaneRow = SobelToPlaneRow_Any_NEON;
2135da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2136da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelToPlaneRow = SobelToPlaneRow_NEON;
2137da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y,
2141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelToPlaneRow);
2142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// SobelXY ARGB effect.
2145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Similar to Sobel, but also stores Sobel X in R and Sobel Y in B.  G = Sobel.
2146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobelXY(const uint8* src_argb, int src_stride_argb,
2148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                uint8* dst_argb, int dst_stride_argb,
2149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                int width, int height) {
2150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely,
2151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_argb, int width) = SobelXYRow_C;
2152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXYROW_SSE2)
2153da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2154da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelXYRow = SobelXYRow_Any_SSE2;
2155da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2156da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelXYRow = SobelXYRow_SSE2;
2157da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXYROW_NEON)
2161da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2162da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SobelXYRow = SobelXYRow_Any_NEON;
2163da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
2164da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SobelXYRow = SobelXYRow_NEON;
2165da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
2169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelXYRow);
2170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x4 polynomial to each ARGB pixel.
2173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBPolynomial(const uint8* src_argb, int src_stride_argb,
2175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   uint8* dst_argb, int dst_stride_argb,
2176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const float* poly,
2177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int width, int height) {
2178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBPolynomialRow)(const uint8* src_argb,
2180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            uint8* dst_argb, const float* poly,
2181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int width) = ARGBPolynomialRow_C;
2182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !poly || width <= 0 || height == 0) {
2183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
2189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBPOLYNOMIALROW_SSE2)
2199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 2)) {
2200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow = ARGBPolynomialRow_SSE2;
2201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBPOLYNOMIALROW_AVX2)
2204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && TestCpuFlag(kCpuHasFMA3) &&
2205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(width, 2)) {
2206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow = ARGBPolynomialRow_AVX2;
2207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow(src_argb, dst_argb, poly, width);
2212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a lumacolortable to each ARGB pixel.
2219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb,
2221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int dst_stride_argb,
2222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       const uint8* luma,
2223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       int width, int height) {
2224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBLumaColorTableRow)(const uint8* src_argb, uint8* dst_argb,
2226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int width, const uint8* luma, const uint32 lumacoeff) =
2227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBLumaColorTableRow_C;
2228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !luma || width <= 0 || height == 0) {
2229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
2235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBLUMACOLORTABLEROW_SSSE3)
2245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4)) {
2246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3;
2247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f);
2252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy Alpha from one ARGB image to another.
2259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb,
2261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* dst_argb, int dst_stride_argb,
2262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
2263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBCopyAlphaRow)(const uint8* src_argb, uint8* dst_argb, int width) =
2265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBCopyAlphaRow_C;
2266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
2267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
2273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYALPHAROW_SSE2)
2283da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 8)) {
2284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2;
2285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYALPHAROW_AVX2)
2288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
2289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2;
2290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow(src_argb, dst_argb, width);
2295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy a planar Y channel to the alpha channel of a destination ARGB image.
2302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y,
2304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_argb, int dst_stride_argb,
2305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width, int height) {
2306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBCopyYToAlphaRow)(const uint8* src_y, uint8* dst_argb, int width) =
2308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBCopyYToAlphaRow_C;
2309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_argb || width <= 0 || height == 0) {
2310ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2314ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2315ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
2316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
2317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
2320ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_argb = 0;
2324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYYTOALPHAROW_SSE2)
2326da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 8)) {
2327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2;
2328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2330ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYYTOALPHAROW_AVX2)
2331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
2332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2;
2333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow(src_y, dst_argb, width);
2338ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
2339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2344da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh VenkatasubramanianLIBYUV_API
2345da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianint YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2,
2346da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
2347da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               uint8* dst_uv, int dst_stride_uv,
2348da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               int width, int height) {
2349da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  int y;
2350da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
2351da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) =
2352da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow_C;
2353da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
2354da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                         ptrdiff_t src_stride, int dst_width,
2355da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                         int source_y_fraction) = InterpolateRow_C;
2356da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (!src_yuy2 ||
2357da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      !dst_y || !dst_uv ||
2358da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      width <= 0 || height == 0) {
2359da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    return -1;
2360da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2361da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  // Negative height means invert the image.
2362da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (height < 0) {
2363da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    height = -height;
2364da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
2365da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    src_stride_yuy2 = -src_stride_yuy2;
2366da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2367da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_SSE2)
2368da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2369da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_SSE2;
2370da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2371da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_SSE2;
2372da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2373da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2374da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2375da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_AVX2)
2376da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
2377da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_AVX2;
2378da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
2379da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_AVX2;
2380da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2381da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2382da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2383da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_NEON)
2384da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2385da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_NEON;
2386da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2387da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_NEON;
2388da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2389da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2390da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2391da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
2392da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2393da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
2394da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2395da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSE2;
2396da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2397da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2398da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2399da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
2400da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
2401da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
2402da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2403da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSSE3;
2404da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2405da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2406da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2407da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
2408da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
2409da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
2410da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
2411da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
2412da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2413da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2414da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2415da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
2416da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2417da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
2418da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2419da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
2420da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2421da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2422da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2423da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2424da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  {
2425da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    int awidth = halfwidth * 2;
2426da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    // 2 rows of uv
2427da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    align_buffer_64(rows, awidth * 2);
2428da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2429da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    for (y = 0; y < height - 1; y += 2) {
2430da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      // Split Y from UV.
2431da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_yuy2, dst_y, rows, awidth);
2432da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y,
2433da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                 rows + awidth, awidth);
2434da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow(dst_uv, rows, awidth, awidth, 128);
2435da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src_yuy2 += src_stride_yuy2 * 2;
2436da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      dst_y += dst_stride_y * 2;
2437da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      dst_uv += dst_stride_uv;
2438da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2439da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (height & 1) {
2440da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      // Split Y from UV.
2441da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_yuy2, dst_y, dst_uv, width);
2442da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2443da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    free_aligned_buffer_64(rows);
2444da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2445da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  return 0;
2446da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian}
2447da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2448da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh VenkatasubramanianLIBYUV_API
2449da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianint UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy,
2450da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
2451da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               uint8* dst_uv, int dst_stride_uv,
2452da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian               int width, int height) {
2453da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  int y;
2454da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
2455da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) =
2456da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow_C;
2457da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
2458da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                         ptrdiff_t src_stride, int dst_width,
2459da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                         int source_y_fraction) = InterpolateRow_C;
2460da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (!src_uyvy ||
2461da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      !dst_y || !dst_uv ||
2462da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      width <= 0 || height == 0) {
2463da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    return -1;
2464da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2465da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  // Negative height means invert the image.
2466da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (height < 0) {
2467da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    height = -height;
2468da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
2469da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    src_stride_uyvy = -src_stride_uyvy;
2470da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2471da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_SSE2)
2472da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2473da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_SSE2;
2474da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2475da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_SSE2;
2476da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2477da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2478da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2479da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_AVX2)
2480da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
2481da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_AVX2;
2482da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
2483da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_AVX2;
2484da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2485da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2486da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2487da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_SPLITUVROW_NEON)
2488da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2489da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    SplitUVRow = SplitUVRow_Any_NEON;
2490da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2491da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow = SplitUVRow_NEON;
2492da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2493da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2494da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2495da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
2496da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
2497da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
2498da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2499da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSE2;
2500da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2501da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2502da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2503da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
2504da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
2505da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
2506da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2507da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_SSSE3;
2508da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2509da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2510da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2511da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
2512da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2)) {
2513da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
2514da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
2515da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
2516da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2517da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2518da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2519da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
2520da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
2521da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
2522da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
2523da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
2524da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2525da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2526da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif
2527da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2528da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  {
2529da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    int awidth = halfwidth * 2;
2530da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    // 2 rows of uv
2531da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    align_buffer_64(rows, awidth * 2);
2532da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2533da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    for (y = 0; y < height - 1; y += 2) {
2534da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      // Split Y from UV.
2535da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_uyvy, rows, dst_y, awidth);
2536da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_uyvy + src_stride_uyvy, rows + awidth,
2537da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                 dst_y + dst_stride_y, awidth);
2538da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      InterpolateRow(dst_uv, rows, awidth, awidth, 128);
2539da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src_uyvy += src_stride_uyvy * 2;
2540da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      dst_y += dst_stride_y * 2;
2541da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      dst_uv += dst_stride_uv;
2542da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2543da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (height & 1) {
2544da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      // Split Y from UV.
2545da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      SplitUVRow(src_uyvy, dst_y, dst_uv, width);
2546da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
2547da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    free_aligned_buffer_64(rows);
2548da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  }
2549da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  return 0;
2550da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian}
2551da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
2553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // extern "C"
2554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // namespace libyuv
2555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2556