1 /*****************************************************************************
2  *
3  *  XVID MPEG-4 VIDEO CODEC
4  *  - Colorspace conversion functions -
5  *
6  *  Copyright(C) 2001-2003 Peter Ross <pross@xvid.org>
7  *
8  *  This program is free software ; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation ; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program ; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  * $Id: colorspace.c 2180 2019-11-12 14:48:35Z Isibaar $
23  *
24  ****************************************************************************/
25 
26 #include <string.h>				/* memcpy */
27 
28 #include "../global.h"
29 #include "colorspace.h"
30 
31 /* function pointers */
32 
33 /* input */
34 packedFuncPtr rgb555_to_yv12;
35 packedFuncPtr rgb565_to_yv12;
36 packedFuncPtr rgb_to_yv12;
37 packedFuncPtr bgr_to_yv12;
38 packedFuncPtr bgra_to_yv12;
39 packedFuncPtr abgr_to_yv12;
40 packedFuncPtr rgba_to_yv12;
41 packedFuncPtr argb_to_yv12;
42 packedFuncPtr yuyv_to_yv12;
43 packedFuncPtr uyvy_to_yv12;
44 
45 packedFuncPtr rgb555i_to_yv12;
46 packedFuncPtr rgb565i_to_yv12;
47 packedFuncPtr rgbi_to_yv12;
48 packedFuncPtr bgri_to_yv12;
49 packedFuncPtr bgrai_to_yv12;
50 packedFuncPtr abgri_to_yv12;
51 packedFuncPtr rgbai_to_yv12;
52 packedFuncPtr argbi_to_yv12;
53 packedFuncPtr yuyvi_to_yv12;
54 packedFuncPtr uyvyi_to_yv12;
55 
56 /* output */
57 packedFuncPtr yv12_to_rgb555;
58 packedFuncPtr yv12_to_rgb565;
59 packedFuncPtr yv12_to_bgr;
60 packedFuncPtr yv12_to_bgra;
61 packedFuncPtr yv12_to_abgr;
62 packedFuncPtr yv12_to_rgb;
63 packedFuncPtr yv12_to_rgba;
64 packedFuncPtr yv12_to_argb;
65 packedFuncPtr yv12_to_yuyv;
66 packedFuncPtr yv12_to_uyvy;
67 
68 packedFuncPtr yv12_to_rgb555i;
69 packedFuncPtr yv12_to_rgb565i;
70 packedFuncPtr yv12_to_bgri;
71 packedFuncPtr yv12_to_bgrai;
72 packedFuncPtr yv12_to_abgri;
73 packedFuncPtr yv12_to_rgbi;
74 packedFuncPtr yv12_to_rgbai;
75 packedFuncPtr yv12_to_argbi;
76 packedFuncPtr yv12_to_yuyvi;
77 packedFuncPtr yv12_to_uyvyi;
78 
79 planarFuncPtr yv12_to_yv12;
80 
81 
82 static int32_t RGB_Y_tab[256];
83 static int32_t B_U_tab[256];
84 static int32_t G_U_tab[256];
85 static int32_t G_V_tab[256];
86 static int32_t R_V_tab[256];
87 
88 
89 
90 /********** generic colorspace macro **********/
91 
92 
93 #define MAKE_COLORSPACE(NAME,SIZE,PIXELS,VPIXELS,FUNC,C1,C2,C3,C4) \
94 void	\
95 NAME(uint8_t * x_ptr, int x_stride,	\
96 				 uint8_t * y_ptr, uint8_t * u_ptr, uint8_t * v_ptr,	\
97 				 int y_stride, int uv_stride,	\
98 				 int width, int height, int vflip)	\
99 {	\
100 	int fixed_width = (width + 1) & ~1;				\
101 	int x_dif = x_stride - (SIZE)*fixed_width;		\
102 	int y_dif = y_stride - fixed_width;				\
103 	int uv_dif = uv_stride - (fixed_width / 2);		\
104 	int x, y;										\
105 	if ((x_ptr == NULL) || (x_dif < 0)) return;		\
106 	if (vflip) {								\
107 		x_ptr += (height - 1) * x_stride;			\
108 		x_dif = -(SIZE)*fixed_width - x_stride;		\
109 		x_stride = -x_stride;						\
110 	}												\
111 	for (y = 0; y < height; y+=(VPIXELS)) {			\
112 		FUNC##_ROW(SIZE,C1,C2,C3,C4);				\
113 		for (x = 0; x < fixed_width; x+=(PIXELS)) {	\
114 			FUNC(SIZE,C1,C2,C3,C4);				\
115 			x_ptr += (PIXELS)*(SIZE);				\
116 			y_ptr += (PIXELS);						\
117 			u_ptr += (PIXELS)/2;					\
118 			v_ptr += (PIXELS)/2;					\
119 		}											\
120 		x_ptr += x_dif + (VPIXELS-1)*x_stride;		\
121 		y_ptr += y_dif + (VPIXELS-1)*y_stride;		\
122 		u_ptr += uv_dif + ((VPIXELS/2)-1)*uv_stride;	\
123 		v_ptr += uv_dif + ((VPIXELS/2)-1)*uv_stride;	\
124 	}												\
125 }
126 
127 
128 
129 /********** colorspace input (xxx_to_yv12) functions **********/
130 
131 /*	rgb -> yuv def's
132 
133 	this following constants are "official spec"
134 	Video Demystified" (ISBN 1-878707-09-4)
135 
136 	rgb<->yuv _is_ lossy, since most programs do the conversion differently
137 
138 	SCALEBITS/FIX taken from  ffmpeg
139 */
140 
141 #define Y_R_IN			0.257
142 #define Y_G_IN			0.504
143 #define Y_B_IN			0.098
144 #define Y_ADD_IN		16
145 
146 #define U_R_IN			0.148
147 #define U_G_IN			0.291
148 #define U_B_IN			0.439
149 #define U_ADD_IN		128
150 
151 #define V_R_IN			0.439
152 #define V_G_IN			0.368
153 #define V_B_IN			0.071
154 #define V_ADD_IN		128
155 
156 #define SCALEBITS_IN		13
157 #define FIX_IN(x)		((uint16_t) ((x) * (1L<<SCALEBITS_IN) + 0.5))
158 #define FIX_ROUND		(1L<<(SCALEBITS_IN-1))
159 
160 /* rgb16/rgb16i input */
161 
162 #define MK_RGB555_B(RGB)  ((RGB) << 3) & 0xf8
163 #define MK_RGB555_G(RGB)  ((RGB) >> 2) & 0xf8
164 #define MK_RGB555_R(RGB)  ((RGB) >> 7) & 0xf8
165 
166 #define MK_RGB565_B(RGB)  ((RGB) << 3) & 0xf8
167 #define MK_RGB565_G(RGB)  ((RGB) >> 3) & 0xfc
168 #define MK_RGB565_R(RGB)  ((RGB) >> 8) & 0xf8
169 
170 
171 #define READ_RGB16_Y(ROW, UVID, C1,C2,C3,C4)	\
172 	rgb = *(uint16_t *) (x_ptr + ((ROW)*x_stride) + 0);	\
173 	b##UVID += b = C1##_B(rgb);				\
174 	g##UVID += g = C1##_G(rgb);				\
175 	r##UVID += r = C1##_R(rgb);				\
176 	y_ptr[(ROW)*y_stride+0] =				\
177 		(uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +	\
178 					FIX_IN(Y_B_IN) * b + FIX_ROUND) >> SCALEBITS_IN) + Y_ADD_IN;	\
179 	rgb = *(uint16_t *) (x_ptr + ((ROW)*x_stride) + 2);	\
180 	b##UVID += b = C1##_B(rgb);				\
181 	g##UVID += g = C1##_G(rgb);				\
182 	r##UVID += r = C1##_R(rgb);				\
183 	y_ptr[(ROW)*y_stride+1] =				\
184 		(uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +			\
185 					FIX_IN(Y_B_IN) * b + FIX_ROUND) >> SCALEBITS_IN) + Y_ADD_IN;
186 
187 #define READ_RGB16_UV(UV_ROW,UVID)	\
188 	u_ptr[(UV_ROW)*uv_stride] =														\
189 		(uint8_t) ((-FIX_IN(U_R_IN) * r##UVID - FIX_IN(U_G_IN) * g##UVID +			\
190 					FIX_IN(U_B_IN) * b##UVID + 4*FIX_ROUND) >> (SCALEBITS_IN + 2)) + U_ADD_IN;	\
191 	v_ptr[(UV_ROW)*uv_stride] =														\
192 		(uint8_t) ((FIX_IN(V_R_IN) * r##UVID - FIX_IN(V_G_IN) * g##UVID -			\
193 					FIX_IN(V_B_IN) * b##UVID + 4*FIX_ROUND) >> (SCALEBITS_IN + 2)) + V_ADD_IN;
194 
195 #define RGB16_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
196 	/* nothing */
197 #define RGB16_TO_YV12(SIZE,C1,C2,C3,C4)	\
198 	uint32_t rgb, r, g, b, r0, g0, b0;	\
199 	r0 = g0 = b0 = 0;					\
200 	READ_RGB16_Y (0, 0, C1,C2,C3,C4)	\
201 	READ_RGB16_Y (1, 0, C1,C2,C3,C4)	\
202 	READ_RGB16_UV(0, 0)
203 
204 
205 #define RGB16I_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
206 	/* nothing */
207 #define RGB16I_TO_YV12(SIZE,C1,C2,C3,C4)	\
208 	uint32_t rgb, r, g, b, r0, g0, b0, r1, g1, b1;	\
209 	r0 = g0 = b0 = r1 = g1 = b1 = 0;	\
210 	READ_RGB16_Y (0, 0, C1,C2,C3,C4)	\
211 	READ_RGB16_Y (1, 1, C1,C2,C3,C4)	\
212 	READ_RGB16_Y (2, 0, C1,C2,C3,C4)	\
213 	READ_RGB16_Y (3, 1, C1,C2,C3,C4)	\
214 	READ_RGB16_UV(0, 0)					\
215 	READ_RGB16_UV(1, 1)
216 
217 
218 /* rgb/rgbi input */
219 
220 #define READ_RGB_Y(SIZE, ROW, UVID, C1,C2,C3,C4)	\
221 	r##UVID += r = x_ptr[(ROW)*x_stride+(C1)];						\
222 	g##UVID += g = x_ptr[(ROW)*x_stride+(C2)];						\
223 	b##UVID += b = x_ptr[(ROW)*x_stride+(C3)];						\
224 	y_ptr[(ROW)*y_stride+0] =									\
225 		(uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +	\
226 					FIX_IN(Y_B_IN) * b + FIX_ROUND) >> SCALEBITS_IN) + Y_ADD_IN;	\
227 	r##UVID += r = x_ptr[(ROW)*x_stride+(SIZE)+(C1)];				\
228 	g##UVID += g = x_ptr[(ROW)*x_stride+(SIZE)+(C2)];				\
229 	b##UVID += b = x_ptr[(ROW)*x_stride+(SIZE)+(C3)];				\
230 	y_ptr[(ROW)*y_stride+1] =									\
231 		(uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +	\
232 					FIX_IN(Y_B_IN) * b + FIX_ROUND) >> SCALEBITS_IN) + Y_ADD_IN;
233 
234 #define READ_RGB_UV(UV_ROW,UVID)	\
235 	u_ptr[(UV_ROW)*uv_stride] =														\
236 		(uint8_t) ((-FIX_IN(U_R_IN) * r##UVID - FIX_IN(U_G_IN) * g##UVID +			\
237 					FIX_IN(U_B_IN) * b##UVID + 4*FIX_ROUND) >> (SCALEBITS_IN + 2)) + U_ADD_IN;	\
238 	v_ptr[(UV_ROW)*uv_stride] =														\
239 		(uint8_t) ((FIX_IN(V_R_IN) * r##UVID - FIX_IN(V_G_IN) * g##UVID -			\
240 					FIX_IN(V_B_IN) * b##UVID + 4*FIX_ROUND) >> (SCALEBITS_IN + 2)) + V_ADD_IN;
241 
242 
243 #define RGB_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
244 	/* nothing */
245 #define RGB_TO_YV12(SIZE,C1,C2,C3,C4)	\
246 	uint32_t r, g, b, r0, g0, b0;		\
247 	r0 = g0 = b0 = 0;					\
248 	READ_RGB_Y(SIZE, 0, 0, C1,C2,C3,C4)	\
249 	READ_RGB_Y(SIZE, 1, 0, C1,C2,C3,C4)	\
250 	READ_RGB_UV(     0, 0)
251 
252 #define RGBI_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
253 	/* nothing */
254 #define RGBI_TO_YV12(SIZE,C1,C2,C3,C4)	\
255 	uint32_t r, g, b, r0, g0, b0, r1, g1, b1;	\
256 	r0 = g0 = b0 = r1 = g1 = b1 = 0;	\
257 	READ_RGB_Y(SIZE, 0, 0, C1,C2,C3,C4)	\
258 	READ_RGB_Y(SIZE, 1, 1, C1,C2,C3,C4)	\
259 	READ_RGB_Y(SIZE, 2, 0, C1,C2,C3,C4)	\
260 	READ_RGB_Y(SIZE, 3, 1, C1,C2,C3,C4)	\
261 	READ_RGB_UV(     0, 0)				\
262 	READ_RGB_UV(     1, 1)
263 
264 
265 /* yuyv/yuyvi input */
266 
267 #define READ_YUYV_Y(ROW,C1,C2,C3,C4)	\
268 	y_ptr[(ROW)*y_stride+0] = x_ptr[(ROW)*x_stride+(C1)];	\
269 	y_ptr[(ROW)*y_stride+1] = x_ptr[(ROW)*x_stride+(C3)];
270 #define READ_YUYV_UV(UV_ROW,ROW1,ROW2,C1,C2,C3,C4) \
271 	u_ptr[(UV_ROW)*uv_stride] = (x_ptr[(ROW1)*x_stride+(C2)] + x_ptr[(ROW2)*x_stride+(C2)] + 1) / 2;	\
272 	v_ptr[(UV_ROW)*uv_stride] = (x_ptr[(ROW1)*x_stride+(C4)] + x_ptr[(ROW2)*x_stride+(C4)] + 1) / 2;
273 
274 #define YUYV_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
275 	/* nothing */
276 #define YUYV_TO_YV12(SIZE,C1,C2,C3,C4)	\
277 	READ_YUYV_Y (0,      C1,C2,C3,C4)	\
278 	READ_YUYV_Y (1,      C1,C2,C3,C4)	\
279 	READ_YUYV_UV(0, 0,1, C1,C2,C3,C4)
280 
281 #define YUYVI_TO_YV12_ROW(SIZE,C1,C2,C3,C4) \
282 	/* nothing */
283 #define YUYVI_TO_YV12(SIZE,C1,C2,C3,C4)	\
284 	READ_YUYV_Y (0, C1,C2,C3,C4)	\
285 	READ_YUYV_Y (1, C1,C2,C3,C4)	\
286 	READ_YUYV_Y (2, C1,C2,C3,C4)	\
287 	READ_YUYV_Y (3, C1,C2,C3,C4)	\
288 	READ_YUYV_UV(0, 0,2, C1,C2,C3,C4)	\
289 	READ_YUYV_UV(1, 1,3, C1,C2,C3,C4)
290 
291 
292 MAKE_COLORSPACE(rgb555_to_yv12_c,  2,2,2, RGB16_TO_YV12,  MK_RGB555, 0,0,0)
293 MAKE_COLORSPACE(rgb565_to_yv12_c,  2,2,2, RGB16_TO_YV12,  MK_RGB565, 0,0,0)
294 MAKE_COLORSPACE(bgr_to_yv12_c,     3,2,2, RGB_TO_YV12,    2,1,0, 0)
295 MAKE_COLORSPACE(bgra_to_yv12_c,    4,2,2, RGB_TO_YV12,    2,1,0, 0)
296 MAKE_COLORSPACE(rgb_to_yv12_c,     3,2,2, RGB_TO_YV12,    0,1,2, 0)
297 MAKE_COLORSPACE(abgr_to_yv12_c,    4,2,2, RGB_TO_YV12,    3,2,1, 0)
298 MAKE_COLORSPACE(rgba_to_yv12_c,    4,2,2, RGB_TO_YV12,    0,1,2, 0)
299 MAKE_COLORSPACE(argb_to_yv12_c,    4,2,2, RGB_TO_YV12,    1,2,3, 0)
300 MAKE_COLORSPACE(yuyv_to_yv12_c,    2,2,2, YUYV_TO_YV12,   0,1,2,3)
301 MAKE_COLORSPACE(uyvy_to_yv12_c,    2,2,2, YUYV_TO_YV12,   1,0,3,2)
302 
303 MAKE_COLORSPACE(rgb555i_to_yv12_c, 2,2,4, RGB16I_TO_YV12, MK_RGB555, 0,0,0)
304 MAKE_COLORSPACE(rgb565i_to_yv12_c, 2,2,4, RGB16I_TO_YV12, MK_RGB565, 0,0,0)
305 MAKE_COLORSPACE(bgri_to_yv12_c,    3,2,4, RGBI_TO_YV12,   2,1,0, 0)
306 MAKE_COLORSPACE(bgrai_to_yv12_c,   4,2,4, RGBI_TO_YV12,   2,1,0, 0)
307 MAKE_COLORSPACE(abgri_to_yv12_c,   4,2,4, RGBI_TO_YV12,   3,2,1, 0)
308 MAKE_COLORSPACE(rgbi_to_yv12_c,    3,2,4, RGBI_TO_YV12,   0,1,2, 0)
309 MAKE_COLORSPACE(rgbai_to_yv12_c,   4,2,4, RGBI_TO_YV12,   0,1,2, 0)
310 MAKE_COLORSPACE(argbi_to_yv12_c,   4,2,4, RGBI_TO_YV12,   1,2,3, 0)
311 MAKE_COLORSPACE(yuyvi_to_yv12_c,   2,2,4, YUYVI_TO_YV12,  0,1,2,3)
312 MAKE_COLORSPACE(uyvyi_to_yv12_c,   2,2,4, YUYVI_TO_YV12,  1,0,3,2)
313 
314 
315 /********** colorspace output (yv12_to_xxx) functions **********/
316 
317 /* yuv -> rgb def's */
318 
319 #define RGB_Y_OUT		1.164
320 #define B_U_OUT			2.018
321 #define Y_ADD_OUT		16
322 
323 #define G_U_OUT			0.391
324 #define G_V_OUT			0.813
325 #define U_ADD_OUT		128
326 
327 #define R_V_OUT			1.596
328 #define V_ADD_OUT		128
329 
330 #define SCALEBITS_OUT		13
331 #define FIX_OUT(x)		((uint16_t) ((x) * (1L<<SCALEBITS_OUT) + 0.5))
332 
333 
334 /* rgb16/rgb16i output */
335 
336 #define MK_RGB555(R,G,B)	\
337 	((MAX(0,MIN(255, R)) << 7) & 0x7c00) | \
338 	((MAX(0,MIN(255, G)) << 2) & 0x03e0) | \
339 	((MAX(0,MIN(255, B)) >> 3) & 0x001f)
340 
341 #define MK_RGB565(R,G,B)	\
342 	((MAX(0,MIN(255, R)) << 8) & 0xf800) | \
343 	((MAX(0,MIN(255, G)) << 3) & 0x07e0) | \
344 	((MAX(0,MIN(255, B)) >> 3) & 0x001f)
345 
346 #define WRITE_RGB16(ROW,UV_ROW,C1)	\
347 	rgb_y = RGB_Y_tab[ y_ptr[y_stride*(ROW) + 0] ];						\
348 	b[ROW] = (b[ROW] & 0x7) + ((rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT);	\
349 	g[ROW] = (g[ROW] & 0x7) + ((rgb_y - g_uv##UV_ROW) >> SCALEBITS_OUT);	\
350 	r[ROW] = (r[ROW] & 0x7) + ((rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT);		\
351 	*(uint16_t *) (x_ptr+((ROW)*x_stride)+0) = C1(r[ROW], g[ROW], b[ROW]);	\
352 	rgb_y = RGB_Y_tab[ y_ptr[y_stride*(ROW) + 1] ];				\
353 	b[ROW] = (b[ROW] & 0x7) + ((rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT);		\
354 	g[ROW] = (g[ROW] & 0x7) + ((rgb_y - g_uv##UV_ROW) >> SCALEBITS_OUT);	\
355 	r[ROW] = (r[ROW] & 0x7) + ((rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT);		\
356 	*(uint16_t *) (x_ptr+((ROW)*x_stride)+2) = C1(r[ROW], g[ROW], b[ROW]);
357 
358 #define YV12_TO_RGB16_ROW(SIZE,C1,C2,C3,C4) \
359 	int r[2], g[2], b[2];					\
360 	r[0] = r[1] = g[0] = g[1] = b[0] = b[1] = 0;
361 #define YV12_TO_RGB16(SIZE,C1,C2,C3,C4)		\
362 	int rgb_y; 												\
363 	int b_u0 = B_U_tab[ u_ptr[0] ];								\
364 	int g_uv0 = G_U_tab[ u_ptr[0] ] + G_V_tab[ v_ptr[0] ];		\
365 	int r_v0 = R_V_tab[ v_ptr[0] ];								\
366 	WRITE_RGB16(0, 0, C1)										\
367 	WRITE_RGB16(1, 0, C1)
368 
369 #define YV12_TO_RGB16I_ROW(SIZE,C1,C2,C3,C4) \
370 	int r[4], g[4], b[4];					\
371 	r[0] = r[1] = r[2] = r[3] = 0;			\
372 	g[0] = g[1] = g[2] = g[3] = 0;			\
373 	b[0] = b[1] = b[2] = b[3] = 0;
374 #define YV12_TO_RGB16I(SIZE,C1,C2,C3,C4)		\
375 	int rgb_y; 													\
376 	int b_u0 = B_U_tab[ u_ptr[0] ];								\
377 	int g_uv0 = G_U_tab[ u_ptr[0] ] + G_V_tab[ v_ptr[0] ];		\
378 	int r_v0 = R_V_tab[ v_ptr[0] ];								\
379     int b_u1 = B_U_tab[ u_ptr[uv_stride] ];						\
380 	int g_uv1 = G_U_tab[ u_ptr[uv_stride] ] + G_V_tab[ v_ptr[uv_stride] ];	\
381 	int r_v1 = R_V_tab[ v_ptr[uv_stride] ];						\
382     WRITE_RGB16(0, 0, C1)										\
383 	WRITE_RGB16(1, 1, C1)										\
384     WRITE_RGB16(2, 0, C1)										\
385 	WRITE_RGB16(3, 1, C1)										\
386 
387 
388 /* rgb/rgbi output */
389 
390 #define WRITE_RGB(SIZE,ROW,UV_ROW,C1,C2,C3,C4)	\
391 	rgb_y = RGB_Y_tab[ y_ptr[(ROW)*y_stride + 0] ];						\
392 	x_ptr[(ROW)*x_stride+(C3)] = MAX(0, MIN(255, (rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT));	\
393 	x_ptr[(ROW)*x_stride+(C2)] = MAX(0, MIN(255, (rgb_y - g_uv##UV_ROW) >> SCALEBITS_OUT));	\
394 	x_ptr[(ROW)*x_stride+(C1)] = MAX(0, MIN(255, (rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT));	\
395 	if ((SIZE)>3) x_ptr[(ROW)*x_stride+(C4)] = 0;									\
396 	rgb_y = RGB_Y_tab[ y_ptr[(ROW)*y_stride + 1] ];									\
397 	x_ptr[(ROW)*x_stride+(SIZE)+(C3)] = MAX(0, MIN(255, (rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT));	\
398 	x_ptr[(ROW)*x_stride+(SIZE)+(C2)] = MAX(0, MIN(255, (rgb_y - g_uv##UV_ROW) >> SCALEBITS_OUT));	\
399 	x_ptr[(ROW)*x_stride+(SIZE)+(C1)] = MAX(0, MIN(255, (rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT));	\
400 	if ((SIZE)>3) x_ptr[(ROW)*x_stride+(SIZE)+(C4)] = 0;
401 
402 
403 #define YV12_TO_RGB_ROW(SIZE,C1,C2,C3,C4) 	/* nothing */
404 #define YV12_TO_RGB(SIZE,C1,C2,C3,C4)				\
405 	int rgb_y;												\
406 	int b_u0 = B_U_tab[ u_ptr[0] ];							\
407 	int g_uv0 = G_U_tab[ u_ptr[0] ] + G_V_tab[ v_ptr[0] ];	\
408 	int r_v0 = R_V_tab[ v_ptr[0] ];							\
409 	WRITE_RGB(SIZE, 0, 0, C1,C2,C3,C4)						\
410 	WRITE_RGB(SIZE, 1, 0, C1,C2,C3,C4)
411 
412 #define YV12_TO_RGBI_ROW(SIZE,C1,C2,C3,C4) 	/* nothing */
413 #define YV12_TO_RGBI(SIZE,C1,C2,C3,C4)				\
414 	int rgb_y;												\
415 	int b_u0 = B_U_tab[ u_ptr[0] ];							\
416 	int g_uv0 = G_U_tab[ u_ptr[0] ] + G_V_tab[ v_ptr[0] ];	\
417 	int r_v0 = R_V_tab[ v_ptr[0] ];							\
418     int b_u1 = B_U_tab[ u_ptr[uv_stride] ];					\
419 	int g_uv1 = G_U_tab[ u_ptr[uv_stride] ] + G_V_tab[ v_ptr[uv_stride] ];	\
420 	int r_v1 = R_V_tab[ v_ptr[uv_stride] ];					\
421 	WRITE_RGB(SIZE, 0, 0, C1,C2,C3,C4)		\
422 	WRITE_RGB(SIZE, 1, 1, C1,C2,C3,C4)		\
423 	WRITE_RGB(SIZE, 2, 0, C1,C2,C3,C4)		\
424 	WRITE_RGB(SIZE, 3, 1, C1,C2,C3,C4)
425 
426 
427 /* yuyv/yuyvi output */
428 
429 #define WRITE_YUYV(ROW,UV_ROW,C1,C2,C3,C4)	\
430 	x_ptr[(ROW)*x_stride+(C1)] = y_ptr[   (ROW)*y_stride +0];	\
431 	x_ptr[(ROW)*x_stride+(C2)] = u_ptr[(UV_ROW)*uv_stride+0];	\
432 	x_ptr[(ROW)*x_stride+(C3)] = y_ptr[   (ROW)*y_stride +1];	\
433 	x_ptr[(ROW)*x_stride+(C4)] = v_ptr[(UV_ROW)*uv_stride+0];	\
434 
435 #define YV12_TO_YUYV_ROW(SIZE,C1,C2,C3,C4) 	/* nothing */
436 #define YV12_TO_YUYV(SIZE,C1,C2,C3,C4)	\
437 	WRITE_YUYV(0, 0, C1,C2,C3,C4)		\
438 	WRITE_YUYV(1, 0, C1,C2,C3,C4)
439 
440 #define YV12_TO_YUYVI_ROW(SIZE,C1,C2,C3,C4) /* nothing */
441 #define YV12_TO_YUYVI(SIZE,C1,C2,C3,C4)	\
442 	WRITE_YUYV(0, 0, C1,C2,C3,C4)		\
443 	WRITE_YUYV(1, 1, C1,C2,C3,C4)		\
444 	WRITE_YUYV(2, 0, C1,C2,C3,C4)		\
445 	WRITE_YUYV(3, 1, C1,C2,C3,C4)
446 
447 
448 MAKE_COLORSPACE(yv12_to_rgb555_c,  2,2,2, YV12_TO_RGB16,  MK_RGB555, 0,0,0)
449 MAKE_COLORSPACE(yv12_to_rgb565_c,  2,2,2, YV12_TO_RGB16,  MK_RGB565, 0,0,0)
450 MAKE_COLORSPACE(yv12_to_bgr_c,     3,2,2, YV12_TO_RGB,    2,1,0,0)
451 MAKE_COLORSPACE(yv12_to_bgra_c,    4,2,2, YV12_TO_RGB,	  2,1,0,3)
452 MAKE_COLORSPACE(yv12_to_abgr_c,    4,2,2, YV12_TO_RGB,    3,2,1,0)
453 MAKE_COLORSPACE(yv12_to_rgb_c,     3,2,2, YV12_TO_RGB,    0,1,2,0)
454 MAKE_COLORSPACE(yv12_to_rgba_c,    4,2,2, YV12_TO_RGB,    0,1,2,3)
455 MAKE_COLORSPACE(yv12_to_argb_c,    4,2,2, YV12_TO_RGB,    1,2,3,0)
456 MAKE_COLORSPACE(yv12_to_yuyv_c,    2,2,2, YV12_TO_YUYV,   0,1,2,3)
457 MAKE_COLORSPACE(yv12_to_uyvy_c,    2,2,2, YV12_TO_YUYV,   1,0,3,2)
458 
459 MAKE_COLORSPACE(yv12_to_rgb555i_c, 2,2,4, YV12_TO_RGB16I, MK_RGB555, 0,0,0)
460 MAKE_COLORSPACE(yv12_to_rgb565i_c, 2,2,4, YV12_TO_RGB16I, MK_RGB565, 0,0,0)
461 MAKE_COLORSPACE(yv12_to_bgri_c,    3,2,4, YV12_TO_RGBI,   2,1,0, 0)
462 MAKE_COLORSPACE(yv12_to_bgrai_c,   4,2,4, YV12_TO_RGBI,	  2,1,0,3)
463 MAKE_COLORSPACE(yv12_to_abgri_c,   4,2,4, YV12_TO_RGBI,   3,2,1,0)
464 MAKE_COLORSPACE(yv12_to_rgbi_c,    3,2,4, YV12_TO_RGBI,   0,1,2,0)
465 MAKE_COLORSPACE(yv12_to_rgbai_c,   4,2,4, YV12_TO_RGBI,   0,1,2,3)
466 MAKE_COLORSPACE(yv12_to_argbi_c,   4,2,4, YV12_TO_RGBI,   1,2,3,0)
467 MAKE_COLORSPACE(yv12_to_yuyvi_c,   2,2,4, YV12_TO_YUYVI,  0,1,2,3)
468 MAKE_COLORSPACE(yv12_to_uyvyi_c,   2,2,4, YV12_TO_YUYVI,  1,0,3,2)
469 
470 
471 
472 /* yv12 to yv12 copy function */
473 
474 void
yv12_to_yv12_c(uint8_t * y_dst,uint8_t * u_dst,uint8_t * v_dst,int y_dst_stride,int uv_dst_stride,uint8_t * y_src,uint8_t * u_src,uint8_t * v_src,int y_src_stride,int uv_src_stride,int width,int height,int vflip)475 yv12_to_yv12_c(uint8_t * y_dst, uint8_t * u_dst, uint8_t * v_dst,
476 				int y_dst_stride, int uv_dst_stride,
477 				uint8_t * y_src, uint8_t * u_src, uint8_t * v_src,
478 				int y_src_stride, int uv_src_stride,
479 				int width, int height, int vflip)
480 {
481 	int width2 = width / 2;
482 	int height2 = height / 2;
483 	int y;
484 	const int with_uv = (u_src!=0 && v_src!=0);
485 
486 	if (vflip) {
487 		y_src += (height - 1) * y_src_stride;
488 		if (with_uv) {
489 			u_src += (height2 - 1) * uv_src_stride;
490 			v_src += (height2 - 1) * uv_src_stride;
491 		}
492 		y_src_stride = -y_src_stride;
493 		uv_src_stride = -uv_src_stride;
494 	}
495 
496 	for (y = height; y; y--) {
497 		memcpy(y_dst, y_src, width);
498 		y_src += y_src_stride;
499 		y_dst += y_dst_stride;
500 	}
501 
502 	if (with_uv) {
503 		for (y = height2; y; y--) {
504 			memcpy(u_dst, u_src, width2);
505 			memcpy(v_dst, v_src, width2);
506 			u_src += uv_src_stride;
507 			u_dst += uv_dst_stride;
508 			v_src += uv_src_stride;
509 			v_dst += uv_dst_stride;
510 		}
511 	}
512 	else {
513 		for (y = height2; y; y--) {
514 			memset(u_dst, 0x80, width2);
515 			memset(v_dst, 0x80, width2);
516 			u_dst += uv_dst_stride;
517 			v_dst += uv_dst_stride;
518 		}
519 	}
520 }
521 
522 
523 
524 /* initialize rgb lookup tables */
525 
526 void
colorspace_init(void)527 colorspace_init(void)
528 {
529 	int32_t i;
530 
531 	for (i = 0; i < 256; i++) {
532 		RGB_Y_tab[i] = FIX_OUT(RGB_Y_OUT) * (i - Y_ADD_OUT);
533 		B_U_tab[i] = FIX_OUT(B_U_OUT) * (i - U_ADD_OUT);
534 		G_U_tab[i] = FIX_OUT(G_U_OUT) * (i - U_ADD_OUT);
535 		G_V_tab[i] = FIX_OUT(G_V_OUT) * (i - V_ADD_OUT);
536 		R_V_tab[i] = FIX_OUT(R_V_OUT) * (i - V_ADD_OUT);
537 	}
538 }
539