blob: ed12de88db1c67283a707803751c63dceb52587e [file] [log] [blame]
Shri Borde7cd81492011-11-02 13:20:24 -07001/*
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -08002 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
Shri Borde7cd81492011-11-02 13:20:24 -07003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080011#include "libyuv/format_conversion.h"
Shri Borde7cd81492011-11-02 13:20:24 -070012
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080013#include "libyuv/basic_types.h"
Shri Borde7cd81492011-11-02 13:20:24 -070014#include "libyuv/cpu_id.h"
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080015#include "libyuv/video_common.h"
16#include "libyuv/row.h"
Shri Borde7cd81492011-11-02 13:20:24 -070017
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080018#ifdef __cplusplus
Shri Borde7cd81492011-11-02 13:20:24 -070019namespace libyuv {
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080020extern "C" {
21#endif
Shri Borde7cd81492011-11-02 13:20:24 -070022
23// Note: to do this with Neon vld4.8 would load ARGB values into 4 registers
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080024// and vst would select which 2 components to write. The low level would need
Shri Borde7cd81492011-11-02 13:20:24 -070025// to be ARGBToBG, ARGBToGB, ARGBToRG, ARGBToGR
26
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080027#if !defined(YUV_DISABLE_ASM) && defined(_M_IX86)
Shri Borde7cd81492011-11-02 13:20:24 -070028#define HAS_ARGBTOBAYERROW_SSSE3
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080029__declspec(naked) __declspec(align(16))
Shri Borde7cd81492011-11-02 13:20:24 -070030static void ARGBToBayerRow_SSSE3(const uint8* src_argb,
31 uint8* dst_bayer, uint32 selector, int pix) {
32 __asm {
33 mov eax, [esp + 4] // src_argb
34 mov edx, [esp + 8] // dst_bayer
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080035 movd xmm5, [esp + 12] // selector
Shri Borde7cd81492011-11-02 13:20:24 -070036 mov ecx, [esp + 16] // pix
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080037 pshufd xmm5, xmm5, 0
Shri Borde7cd81492011-11-02 13:20:24 -070038
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080039 align 16
Shri Borde7cd81492011-11-02 13:20:24 -070040 wloop:
41 movdqa xmm0, [eax]
42 lea eax, [eax + 16]
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080043 pshufb xmm0, xmm5
44 sub ecx, 4
Shri Borde7cd81492011-11-02 13:20:24 -070045 movd [edx], xmm0
46 lea edx, [edx + 4]
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080047 jg wloop
Shri Borde7cd81492011-11-02 13:20:24 -070048 ret
49 }
50}
51
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080052#elif !defined(YUV_DISABLE_ASM) && (defined(__x86_64__) || defined(__i386__))
Shri Borde7cd81492011-11-02 13:20:24 -070053
54#define HAS_ARGBTOBAYERROW_SSSE3
55static void ARGBToBayerRow_SSSE3(const uint8* src_argb, uint8* dst_bayer,
56 uint32 selector, int pix) {
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080057 asm volatile (
58 "movd %3,%%xmm5 \n"
59 "pshufd $0x0,%%xmm5,%%xmm5 \n"
60 ".p2align 4 \n"
61"1: \n"
62 "movdqa (%0),%%xmm0 \n"
63 "lea 0x10(%0),%0 \n"
64 "pshufb %%xmm5,%%xmm0 \n"
65 "sub $0x4,%2 \n"
66 "movd %%xmm0,(%1) \n"
67 "lea 0x4(%1),%1 \n"
68 "jg 1b \n"
Shri Borde7cd81492011-11-02 13:20:24 -070069 : "+r"(src_argb), // %0
70 "+r"(dst_bayer), // %1
71 "+r"(pix) // %2
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080072 : "g"(selector) // %3
73 : "memory", "cc"
74#if defined(__SSE2__)
75 , "xmm0", "xmm5"
76#endif
77
Shri Borde7cd81492011-11-02 13:20:24 -070078);
79}
80#endif
81
82static void ARGBToBayerRow_C(const uint8* src_argb,
83 uint8* dst_bayer, uint32 selector, int pix) {
84 int index0 = selector & 0xff;
85 int index1 = (selector >> 8) & 0xff;
86 // Copy a row of Bayer.
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -080087 for (int x = 0; x < pix - 1; x += 2) {
Shri Borde7cd81492011-11-02 13:20:24 -070088 dst_bayer[0] = src_argb[index0];
89 dst_bayer[1] = src_argb[index1];
90 src_argb += 8;
91 dst_bayer += 2;
92 }
93 if (pix & 1) {
94 dst_bayer[0] = src_argb[index0];
95 }
96}
97
98// generate a selector mask useful for pshufb
99static uint32 GenerateSelector(int select0, int select1) {
100 return static_cast<uint32>(select0) |
101 static_cast<uint32>((select1 + 4) << 8) |
102 static_cast<uint32>((select0 + 8) << 16) |
103 static_cast<uint32>((select1 + 12) << 24);
104}
105
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800106static int MakeSelectors(const int blue_index,
107 const int green_index,
108 const int red_index,
109 uint32 dst_fourcc_bayer,
110 uint32 *index_map) {
Shri Borde7cd81492011-11-02 13:20:24 -0700111 // Now build a lookup table containing the indices for the four pixels in each
112 // 2x2 Bayer grid.
Shri Borde7cd81492011-11-02 13:20:24 -0700113 switch (dst_fourcc_bayer) {
Shri Borde7cd81492011-11-02 13:20:24 -0700114 case FOURCC_BGGR:
115 index_map[0] = GenerateSelector(blue_index, green_index);
116 index_map[1] = GenerateSelector(green_index, red_index);
117 break;
Shri Borde7cd81492011-11-02 13:20:24 -0700118 case FOURCC_GBRG:
119 index_map[0] = GenerateSelector(green_index, blue_index);
120 index_map[1] = GenerateSelector(red_index, green_index);
121 break;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800122 case FOURCC_RGGB:
123 index_map[0] = GenerateSelector(red_index, green_index);
124 index_map[1] = GenerateSelector(green_index, blue_index);
125 break;
126 case FOURCC_GRBG:
127 index_map[0] = GenerateSelector(green_index, red_index);
128 index_map[1] = GenerateSelector(blue_index, green_index);
129 break;
130 default:
131 return -1; // Bad FourCC
132 }
133 return 0;
134}
135
136// Converts 32 bit ARGB to Bayer RGB formats.
137LIBYUV_API
138int ARGBToBayer(const uint8* src_argb, int src_stride_argb,
139 uint8* dst_bayer, int dst_stride_bayer,
140 int width, int height,
141 uint32 dst_fourcc_bayer) {
142 if (height < 0) {
143 height = -height;
144 src_argb = src_argb + (height - 1) * src_stride_argb;
145 src_stride_argb = -src_stride_argb;
146 }
147 void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer,
148 uint32 selector, int pix) = ARGBToBayerRow_C;
149#if defined(HAS_ARGBTOBAYERROW_SSSE3)
150 if (TestCpuFlag(kCpuHasSSSE3) &&
151 IS_ALIGNED(width, 4) &&
152 IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
153 ARGBToBayerRow = ARGBToBayerRow_SSSE3;
154 }
155#endif
156 const int blue_index = 0; // Offsets for ARGB format
157 const int green_index = 1;
158 const int red_index = 2;
159 uint32 index_map[2];
160 if (MakeSelectors(blue_index, green_index, red_index,
161 dst_fourcc_bayer, index_map)) {
162 return -1; // Bad FourCC
Shri Borde7cd81492011-11-02 13:20:24 -0700163 }
164
Shri Borde7cd81492011-11-02 13:20:24 -0700165 for (int y = 0; y < height; ++y) {
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800166 ARGBToBayerRow(src_argb, dst_bayer, index_map[y & 1], width);
167 src_argb += src_stride_argb;
Shri Borde7cd81492011-11-02 13:20:24 -0700168 dst_bayer += dst_stride_bayer;
169 }
170 return 0;
171}
172
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800173#define AVG(a, b) (((a) + (b)) >> 1)
Shri Borde7cd81492011-11-02 13:20:24 -0700174
175static void BayerRowBG(const uint8* src_bayer0, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800176 uint8* dst_argb, int pix) {
Shri Borde7cd81492011-11-02 13:20:24 -0700177 const uint8* src_bayer1 = src_bayer0 + src_stride_bayer;
178 uint8 g = src_bayer0[1];
179 uint8 r = src_bayer1[1];
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800180 for (int x = 0; x < pix - 2; x += 2) {
181 dst_argb[0] = src_bayer0[0];
182 dst_argb[1] = AVG(g, src_bayer0[1]);
183 dst_argb[2] = AVG(r, src_bayer1[1]);
184 dst_argb[3] = 255U;
185 dst_argb[4] = AVG(src_bayer0[0], src_bayer0[2]);
186 dst_argb[5] = src_bayer0[1];
187 dst_argb[6] = src_bayer1[1];
188 dst_argb[7] = 255U;
Shri Borde7cd81492011-11-02 13:20:24 -0700189 g = src_bayer0[1];
190 r = src_bayer1[1];
191 src_bayer0 += 2;
192 src_bayer1 += 2;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800193 dst_argb += 8;
Shri Borde7cd81492011-11-02 13:20:24 -0700194 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800195 dst_argb[0] = src_bayer0[0];
196 dst_argb[1] = AVG(g, src_bayer0[1]);
197 dst_argb[2] = AVG(r, src_bayer1[1]);
198 dst_argb[3] = 255U;
199 if (!(pix & 1)) {
200 dst_argb[4] = src_bayer0[0];
201 dst_argb[5] = src_bayer0[1];
202 dst_argb[6] = src_bayer1[1];
203 dst_argb[7] = 255U;
204 }
Shri Borde7cd81492011-11-02 13:20:24 -0700205}
206
207static void BayerRowRG(const uint8* src_bayer0, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800208 uint8* dst_argb, int pix) {
Shri Borde7cd81492011-11-02 13:20:24 -0700209 const uint8* src_bayer1 = src_bayer0 + src_stride_bayer;
210 uint8 g = src_bayer0[1];
211 uint8 b = src_bayer1[1];
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800212 for (int x = 0; x < pix - 2; x += 2) {
213 dst_argb[0] = AVG(b, src_bayer1[1]);
214 dst_argb[1] = AVG(g, src_bayer0[1]);
215 dst_argb[2] = src_bayer0[0];
216 dst_argb[3] = 255U;
217 dst_argb[4] = src_bayer1[1];
218 dst_argb[5] = src_bayer0[1];
219 dst_argb[6] = AVG(src_bayer0[0], src_bayer0[2]);
220 dst_argb[7] = 255U;
Shri Borde7cd81492011-11-02 13:20:24 -0700221 g = src_bayer0[1];
222 b = src_bayer1[1];
223 src_bayer0 += 2;
224 src_bayer1 += 2;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800225 dst_argb += 8;
Shri Borde7cd81492011-11-02 13:20:24 -0700226 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800227 dst_argb[0] = AVG(b, src_bayer1[1]);
228 dst_argb[1] = AVG(g, src_bayer0[1]);
229 dst_argb[2] = src_bayer0[0];
230 dst_argb[3] = 255U;
231 if (!(pix & 1)) {
232 dst_argb[4] = src_bayer1[1];
233 dst_argb[5] = src_bayer0[1];
234 dst_argb[6] = src_bayer0[0];
235 dst_argb[7] = 255U;
236 }
Shri Borde7cd81492011-11-02 13:20:24 -0700237}
238
239static void BayerRowGB(const uint8* src_bayer0, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800240 uint8* dst_argb, int pix) {
Shri Borde7cd81492011-11-02 13:20:24 -0700241 const uint8* src_bayer1 = src_bayer0 + src_stride_bayer;
242 uint8 b = src_bayer0[1];
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800243 for (int x = 0; x < pix - 2; x += 2) {
244 dst_argb[0] = AVG(b, src_bayer0[1]);
245 dst_argb[1] = src_bayer0[0];
246 dst_argb[2] = src_bayer1[0];
247 dst_argb[3] = 255U;
248 dst_argb[4] = src_bayer0[1];
249 dst_argb[5] = AVG(src_bayer0[0], src_bayer0[2]);
250 dst_argb[6] = AVG(src_bayer1[0], src_bayer1[2]);
251 dst_argb[7] = 255U;
Shri Borde7cd81492011-11-02 13:20:24 -0700252 b = src_bayer0[1];
253 src_bayer0 += 2;
254 src_bayer1 += 2;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800255 dst_argb += 8;
Shri Borde7cd81492011-11-02 13:20:24 -0700256 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800257 dst_argb[0] = AVG(b, src_bayer0[1]);
258 dst_argb[1] = src_bayer0[0];
259 dst_argb[2] = src_bayer1[0];
260 dst_argb[3] = 255U;
261 if (!(pix & 1)) {
262 dst_argb[4] = src_bayer0[1];
263 dst_argb[5] = src_bayer0[0];
264 dst_argb[6] = src_bayer1[0];
265 dst_argb[7] = 255U;
266 }
Shri Borde7cd81492011-11-02 13:20:24 -0700267}
268
269static void BayerRowGR(const uint8* src_bayer0, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800270 uint8* dst_argb, int pix) {
Shri Borde7cd81492011-11-02 13:20:24 -0700271 const uint8* src_bayer1 = src_bayer0 + src_stride_bayer;
272 uint8 r = src_bayer0[1];
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800273 for (int x = 0; x < pix - 2; x += 2) {
274 dst_argb[0] = src_bayer1[0];
275 dst_argb[1] = src_bayer0[0];
276 dst_argb[2] = AVG(r, src_bayer0[1]);
277 dst_argb[3] = 255U;
278 dst_argb[4] = AVG(src_bayer1[0], src_bayer1[2]);
279 dst_argb[5] = AVG(src_bayer0[0], src_bayer0[2]);
280 dst_argb[6] = src_bayer0[1];
281 dst_argb[7] = 255U;
Shri Borde7cd81492011-11-02 13:20:24 -0700282 r = src_bayer0[1];
283 src_bayer0 += 2;
284 src_bayer1 += 2;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800285 dst_argb += 8;
Shri Borde7cd81492011-11-02 13:20:24 -0700286 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800287 dst_argb[0] = src_bayer1[0];
288 dst_argb[1] = src_bayer0[0];
289 dst_argb[2] = AVG(r, src_bayer0[1]);
290 dst_argb[3] = 255U;
291 if (!(pix & 1)) {
292 dst_argb[4] = src_bayer1[0];
293 dst_argb[5] = src_bayer0[0];
294 dst_argb[6] = src_bayer0[1];
295 dst_argb[7] = 255U;
296 }
Shri Borde7cd81492011-11-02 13:20:24 -0700297}
298
299// Converts any Bayer RGB format to ARGB.
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800300LIBYUV_API
301int BayerToARGB(const uint8* src_bayer, int src_stride_bayer,
302 uint8* dst_argb, int dst_stride_argb,
303 int width, int height,
304 uint32 src_fourcc_bayer) {
Shri Borde7cd81492011-11-02 13:20:24 -0700305 if (height < 0) {
306 height = -height;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800307 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
308 dst_stride_argb = -dst_stride_argb;
Shri Borde7cd81492011-11-02 13:20:24 -0700309 }
310 void (*BayerRow0)(const uint8* src_bayer, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800311 uint8* dst_argb, int pix);
Shri Borde7cd81492011-11-02 13:20:24 -0700312 void (*BayerRow1)(const uint8* src_bayer, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800313 uint8* dst_argb, int pix);
Shri Borde7cd81492011-11-02 13:20:24 -0700314 switch (src_fourcc_bayer) {
Shri Borde7cd81492011-11-02 13:20:24 -0700315 case FOURCC_BGGR:
316 BayerRow0 = BayerRowBG;
317 BayerRow1 = BayerRowGR;
318 break;
Shri Borde7cd81492011-11-02 13:20:24 -0700319 case FOURCC_GBRG:
320 BayerRow0 = BayerRowGB;
321 BayerRow1 = BayerRowRG;
322 break;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800323 case FOURCC_GRBG:
324 BayerRow0 = BayerRowGR;
325 BayerRow1 = BayerRowBG;
326 break;
327 case FOURCC_RGGB:
328 BayerRow0 = BayerRowRG;
329 BayerRow1 = BayerRowGB;
330 break;
331 default:
332 return -1; // Bad FourCC
Shri Borde7cd81492011-11-02 13:20:24 -0700333 }
334
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800335 for (int y = 0; y < height - 1; y += 2) {
336 BayerRow0(src_bayer, src_stride_bayer, dst_argb, width);
Shri Borde7cd81492011-11-02 13:20:24 -0700337 BayerRow1(src_bayer + src_stride_bayer, -src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800338 dst_argb + dst_stride_argb, width);
Shri Borde7cd81492011-11-02 13:20:24 -0700339 src_bayer += src_stride_bayer * 2;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800340 dst_argb += dst_stride_argb * 2;
Shri Borde7cd81492011-11-02 13:20:24 -0700341 }
342 if (height & 1) {
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800343 BayerRow0(src_bayer, -src_stride_bayer, dst_argb, width);
Shri Borde7cd81492011-11-02 13:20:24 -0700344 }
345 return 0;
346}
347
348// Converts any Bayer RGB format to ARGB.
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800349LIBYUV_API
350int BayerToI420(const uint8* src_bayer, int src_stride_bayer,
351 uint8* dst_y, int dst_stride_y,
352 uint8* dst_u, int dst_stride_u,
353 uint8* dst_v, int dst_stride_v,
354 int width, int height,
355 uint32 src_fourcc_bayer) {
Shri Borde7cd81492011-11-02 13:20:24 -0700356 if (width * 4 > kMaxStride) {
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800357 return -1; // Size too large for row buffer
Shri Borde7cd81492011-11-02 13:20:24 -0700358 }
359 // Negative height means invert the image.
360 if (height < 0) {
361 height = -height;
362 int halfheight = (height + 1) >> 1;
363 dst_y = dst_y + (height - 1) * dst_stride_y;
364 dst_u = dst_u + (halfheight - 1) * dst_stride_u;
365 dst_v = dst_v + (halfheight - 1) * dst_stride_v;
366 dst_stride_y = -dst_stride_y;
367 dst_stride_u = -dst_stride_u;
368 dst_stride_v = -dst_stride_v;
369 }
370 void (*BayerRow0)(const uint8* src_bayer, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800371 uint8* dst_argb, int pix);
Shri Borde7cd81492011-11-02 13:20:24 -0700372 void (*BayerRow1)(const uint8* src_bayer, int src_stride_bayer,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800373 uint8* dst_argb, int pix);
374 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
375 ARGBToYRow_C;
Shri Borde7cd81492011-11-02 13:20:24 -0700376 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800377 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
Shri Borde7cd81492011-11-02 13:20:24 -0700378 SIMD_ALIGNED(uint8 row[kMaxStride * 2]);
379
380#if defined(HAS_ARGBTOYROW_SSSE3)
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800381 if (TestCpuFlag(kCpuHasSSSE3) &&
382 IS_ALIGNED(width, 16) &&
383 IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
Shri Borde7cd81492011-11-02 13:20:24 -0700384 ARGBToYRow = ARGBToYRow_SSSE3;
Shri Borde7cd81492011-11-02 13:20:24 -0700385 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800386#endif
Shri Borde7cd81492011-11-02 13:20:24 -0700387#if defined(HAS_ARGBTOUVROW_SSSE3)
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800388 if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16)) {
Shri Borde7cd81492011-11-02 13:20:24 -0700389 ARGBToUVRow = ARGBToUVRow_SSSE3;
Shri Borde7cd81492011-11-02 13:20:24 -0700390 }
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800391#endif
Shri Borde7cd81492011-11-02 13:20:24 -0700392
393 switch (src_fourcc_bayer) {
Shri Borde7cd81492011-11-02 13:20:24 -0700394 case FOURCC_BGGR:
395 BayerRow0 = BayerRowBG;
396 BayerRow1 = BayerRowGR;
397 break;
Shri Borde7cd81492011-11-02 13:20:24 -0700398 case FOURCC_GBRG:
399 BayerRow0 = BayerRowGB;
400 BayerRow1 = BayerRowRG;
401 break;
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800402 case FOURCC_GRBG:
403 BayerRow0 = BayerRowGR;
404 BayerRow1 = BayerRowBG;
405 break;
406 case FOURCC_RGGB:
407 BayerRow0 = BayerRowRG;
408 BayerRow1 = BayerRowGB;
409 break;
410 default:
411 return -1; // Bad FourCC
Shri Borde7cd81492011-11-02 13:20:24 -0700412 }
413
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800414 for (int y = 0; y < height - 1; y += 2) {
Shri Borde7cd81492011-11-02 13:20:24 -0700415 BayerRow0(src_bayer, src_stride_bayer, row, width);
416 BayerRow1(src_bayer + src_stride_bayer, -src_stride_bayer,
417 row + kMaxStride, width);
418 ARGBToUVRow(row, kMaxStride, dst_u, dst_v, width);
419 ARGBToYRow(row, dst_y, width);
420 ARGBToYRow(row + kMaxStride, dst_y + dst_stride_y, width);
421 src_bayer += src_stride_bayer * 2;
422 dst_y += dst_stride_y * 2;
423 dst_u += dst_stride_u;
424 dst_v += dst_stride_v;
425 }
Shri Borde7cd81492011-11-02 13:20:24 -0700426 if (height & 1) {
427 BayerRow0(src_bayer, src_stride_bayer, row, width);
428 ARGBToUVRow(row, 0, dst_u, dst_v, width);
429 ARGBToYRow(row, dst_y, width);
430 }
431 return 0;
432}
433
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800434// Convert I420 to Bayer.
435LIBYUV_API
436int I420ToBayer(const uint8* src_y, int src_stride_y,
437 const uint8* src_u, int src_stride_u,
438 const uint8* src_v, int src_stride_v,
439 uint8* dst_bayer, int dst_stride_bayer,
440 int width, int height,
441 uint32 dst_fourcc_bayer) {
442 // Negative height means invert the image.
443 if (height < 0) {
444 height = -height;
445 int halfheight = (height + 1) >> 1;
446 src_y = src_y + (height - 1) * src_stride_y;
447 src_u = src_u + (halfheight - 1) * src_stride_u;
448 src_v = src_v + (halfheight - 1) * src_stride_v;
449 src_stride_y = -src_stride_y;
450 src_stride_u = -src_stride_u;
451 src_stride_v = -src_stride_v;
452 }
453 void (*I422ToARGBRow)(const uint8* y_buf,
454 const uint8* u_buf,
455 const uint8* v_buf,
456 uint8* rgb_buf,
457 int width) = I422ToARGBRow_C;
458#if defined(HAS_I422TOARGBROW_NEON)
459 if (TestCpuFlag(kCpuHasNEON)) {
460 I422ToARGBRow = I422ToARGBRow_NEON;
461 }
462#elif defined(HAS_I422TOARGBROW_SSSE3)
463 if (TestCpuFlag(kCpuHasSSSE3)) {
464 I422ToARGBRow = I422ToARGBRow_SSSE3;
465 }
466#endif
467 SIMD_ALIGNED(uint8 row[kMaxStride]);
468 void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer,
469 uint32 selector, int pix) = ARGBToBayerRow_C;
470#if defined(HAS_ARGBTOBAYERROW_SSSE3)
471 if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4)) {
472 ARGBToBayerRow = ARGBToBayerRow_SSSE3;
473 }
474#endif
475 const int blue_index = 0; // Offsets for ARGB format
476 const int green_index = 1;
477 const int red_index = 2;
478 uint32 index_map[2];
479 if (MakeSelectors(blue_index, green_index, red_index,
480 dst_fourcc_bayer, index_map)) {
481 return -1; // Bad FourCC
482 }
483
484 for (int y = 0; y < height; ++y) {
485 I422ToARGBRow(src_y, src_u, src_v, row, width);
486 ARGBToBayerRow(row, dst_bayer, index_map[y & 1], width);
487 dst_bayer += dst_stride_bayer;
488 src_y += src_stride_y;
489 if (y & 1) {
490 src_u += src_stride_u;
491 src_v += src_stride_v;
492 }
493 }
494 return 0;
495}
496
497#define MAKEBAYERFOURCC(BAYER) \
498LIBYUV_API \
499int Bayer##BAYER##ToI420(const uint8* src_bayer, int src_stride_bayer, \
500 uint8* dst_y, int dst_stride_y, \
501 uint8* dst_u, int dst_stride_u, \
502 uint8* dst_v, int dst_stride_v, \
503 int width, int height) { \
504 return BayerToI420(src_bayer, src_stride_bayer, \
505 dst_y, dst_stride_y, \
506 dst_u, dst_stride_u, \
507 dst_v, dst_stride_v, \
508 width, height, \
509 FOURCC_##BAYER); \
510} \
511 \
512LIBYUV_API \
513int I420ToBayer##BAYER(const uint8* src_y, int src_stride_y, \
514 const uint8* src_u, int src_stride_u, \
515 const uint8* src_v, int src_stride_v, \
516 uint8* dst_bayer, int dst_stride_bayer, \
517 int width, int height) { \
518 return I420ToBayer(src_y, src_stride_y, \
519 src_u, src_stride_u, \
520 src_v, src_stride_v, \
521 dst_bayer, dst_stride_bayer, \
522 width, height, \
523 FOURCC_##BAYER); \
524} \
525 \
526LIBYUV_API \
527int ARGBToBayer##BAYER(const uint8* src_argb, int src_stride_argb, \
528 uint8* dst_bayer, int dst_stride_bayer, \
529 int width, int height) { \
530 return ARGBToBayer(src_argb, src_stride_argb, \
531 dst_bayer, dst_stride_bayer, \
532 width, height, \
533 FOURCC_##BAYER); \
534} \
535 \
536LIBYUV_API \
537int Bayer##BAYER##ToARGB(const uint8* src_bayer, int src_stride_bayer, \
538 uint8* dst_argb, int dst_stride_argb, \
539 int width, int height) { \
540 return BayerToARGB(src_bayer, src_stride_bayer, \
541 dst_argb, dst_stride_argb, \
542 width, height, \
543 FOURCC_##BAYER); \
544}
545
546MAKEBAYERFOURCC(BGGR)
547MAKEBAYERFOURCC(GBRG)
548MAKEBAYERFOURCC(GRBG)
549MAKEBAYERFOURCC(RGGB)
550
551#ifdef __cplusplus
552} // extern "C"
Shri Borde7cd81492011-11-02 13:20:24 -0700553} // namespace libyuv
Hendrik Dahlkamp33cfdeb2013-01-23 18:27:37 -0800554#endif