Parent Directory | Revision Log
Revision 195 -
(view)
(download)
Original Path: trunk/xvidcore/src/image/colorspace.c
1 : | edgomez | 195 | /************************************************************************** |
2 : | * | ||
3 : | * XVID MPEG-4 VIDEO CODEC | ||
4 : | * colorspace conversions | ||
5 : | * | ||
6 : | * This program is free software; you can redistribute it and/or modify | ||
7 : | * it under the terms of the GNU General Public License as published by | ||
8 : | * the Free Software Foundation; either version 2 of the License, or | ||
9 : | * (at your option) any later version. | ||
10 : | * | ||
11 : | * This program is distributed in the hope that it will be useful, | ||
12 : | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 : | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 : | * GNU General Public License for more details. | ||
15 : | * | ||
16 : | * You should have received a copy of the GNU General Public License | ||
17 : | * along with this program; if not, write to the Free Software | ||
18 : | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 : | * | ||
20 : | *************************************************************************/ | ||
21 : | |||
22 : | /************************************************************************** | ||
23 : | * | ||
24 : | * History: | ||
25 : | * | ||
26 : | * 14.04.2002 added user_to_yuv_c() | ||
27 : | * 30.02.2002 out_yuv dst_stride2 fix | ||
28 : | * 26.02.2002 rgb555, rgb565 | ||
29 : | * 24.11.2001 accuracy improvement to yuyv/vyuy conversion | ||
30 : | * 28.10.2001 total rewrite <pross@cs.rmit.edu.au> | ||
31 : | * | ||
32 : | **************************************************************************/ | ||
33 : | |||
34 : | #include <string.h> // memcpy | ||
35 : | |||
36 : | #include "colorspace.h" | ||
37 : | #include "../divx4.h" // DEC_PICTURE | ||
38 : | |||
39 : | // function pointers | ||
40 : | |||
41 : | /* input */ | ||
42 : | color_inputFuncPtr rgb555_to_yv12; | ||
43 : | color_inputFuncPtr rgb565_to_yv12; | ||
44 : | color_inputFuncPtr rgb24_to_yv12; | ||
45 : | color_inputFuncPtr rgb32_to_yv12; | ||
46 : | color_inputFuncPtr yuv_to_yv12; | ||
47 : | color_inputFuncPtr yuyv_to_yv12; | ||
48 : | color_inputFuncPtr uyvy_to_yv12; | ||
49 : | |||
50 : | /* output */ | ||
51 : | color_outputFuncPtr yv12_to_rgb555; | ||
52 : | color_outputFuncPtr yv12_to_rgb565; | ||
53 : | color_outputFuncPtr yv12_to_rgb24; | ||
54 : | color_outputFuncPtr yv12_to_rgb32; | ||
55 : | color_outputFuncPtr yv12_to_yuv; | ||
56 : | color_outputFuncPtr yv12_to_yuyv; | ||
57 : | color_outputFuncPtr yv12_to_uyvy; | ||
58 : | |||
59 : | #define MIN(A,B) ((A)<(B)?(A):(B)) | ||
60 : | #define MAX(A,B) ((A)>(B)?(A):(B)) | ||
61 : | |||
62 : | /* rgb -> yuv def's | ||
63 : | |||
64 : | this following constants are "official spec" | ||
65 : | Video Demystified" (ISBN 1-878707-09-4) | ||
66 : | |||
67 : | rgb<->yuv _is_ lossy, since most programs do the conversion differently | ||
68 : | |||
69 : | SCALEBITS/FIX taken from ffmpeg | ||
70 : | */ | ||
71 : | |||
72 : | #define Y_R_IN 0.257 | ||
73 : | #define Y_G_IN 0.504 | ||
74 : | #define Y_B_IN 0.098 | ||
75 : | #define Y_ADD_IN 16 | ||
76 : | |||
77 : | #define U_R_IN 0.148 | ||
78 : | #define U_G_IN 0.291 | ||
79 : | #define U_B_IN 0.439 | ||
80 : | #define U_ADD_IN 128 | ||
81 : | |||
82 : | #define V_R_IN 0.439 | ||
83 : | #define V_G_IN 0.368 | ||
84 : | #define V_B_IN 0.071 | ||
85 : | #define V_ADD_IN 128 | ||
86 : | |||
87 : | #define SCALEBITS_IN 8 | ||
88 : | #define FIX_IN(x) ((uint16_t) ((x) * (1L<<SCALEBITS_IN) + 0.5)) | ||
89 : | |||
90 : | |||
91 : | int32_t RGB_Y_tab[256]; | ||
92 : | int32_t B_U_tab[256]; | ||
93 : | int32_t G_U_tab[256]; | ||
94 : | int32_t G_V_tab[256]; | ||
95 : | int32_t R_V_tab[256]; | ||
96 : | |||
97 : | |||
98 : | /* rgb555 -> yuv 4:2:0 planar */ | ||
99 : | void | ||
100 : | rgb555_to_yv12_c(uint8_t * y_out, | ||
101 : | uint8_t * u_out, | ||
102 : | uint8_t * v_out, | ||
103 : | uint8_t * src, | ||
104 : | int width, | ||
105 : | int height, | ||
106 : | int y_stride) | ||
107 : | { | ||
108 : | int32_t src_stride = width * 2; | ||
109 : | uint32_t y_dif = y_stride - width; | ||
110 : | uint32_t uv_dif = (y_stride - width) / 2; | ||
111 : | uint32_t x, y; | ||
112 : | |||
113 : | if (height < 0) { | ||
114 : | height = -height; | ||
115 : | src += (height - 1) * src_stride; | ||
116 : | src_stride = -src_stride; | ||
117 : | } | ||
118 : | |||
119 : | |||
120 : | for (y = height / 2; y; y--) { | ||
121 : | // process one 2x2 block per iteration | ||
122 : | for (x = 0; x < (uint32_t) width; x += 2) { | ||
123 : | int rgb, r, g, b, r4, g4, b4; | ||
124 : | |||
125 : | rgb = *(uint16_t *) (src + x * 2); | ||
126 : | b4 = b = (rgb << 3) & 0xf8; | ||
127 : | g4 = g = (rgb >> 2) & 0xf8; | ||
128 : | r4 = r = (rgb >> 7) & 0xf8; | ||
129 : | y_out[0] = | ||
130 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
131 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
132 : | |||
133 : | rgb = *(uint16_t *) (src + x * 2 + src_stride); | ||
134 : | b4 += b = (rgb << 3) & 0xf8; | ||
135 : | g4 += g = (rgb >> 2) & 0xf8; | ||
136 : | r4 += r = (rgb >> 7) & 0xf8; | ||
137 : | y_out[y_stride] = | ||
138 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
139 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
140 : | |||
141 : | rgb = *(uint16_t *) (src + x * 2 + 2); | ||
142 : | b4 += b = (rgb << 3) & 0xf8; | ||
143 : | g4 += g = (rgb >> 2) & 0xf8; | ||
144 : | r4 += r = (rgb >> 7) & 0xf8; | ||
145 : | y_out[1] = | ||
146 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
147 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
148 : | |||
149 : | rgb = *(uint16_t *) (src + x * 2 + src_stride + 2); | ||
150 : | b4 += b = (rgb << 3) & 0xf8; | ||
151 : | g4 += g = (rgb >> 2) & 0xf8; | ||
152 : | r4 += r = (rgb >> 7) & 0xf8; | ||
153 : | y_out[y_stride + 1] = | ||
154 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
155 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
156 : | |||
157 : | *u_out++ = | ||
158 : | (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + | ||
159 : | FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
160 : | U_ADD_IN; | ||
161 : | |||
162 : | |||
163 : | *v_out++ = | ||
164 : | (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - | ||
165 : | FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
166 : | V_ADD_IN; | ||
167 : | |||
168 : | y_out += 2; | ||
169 : | } | ||
170 : | src += src_stride * 2; | ||
171 : | y_out += y_dif + y_stride; | ||
172 : | u_out += uv_dif; | ||
173 : | v_out += uv_dif; | ||
174 : | } | ||
175 : | } | ||
176 : | |||
177 : | |||
178 : | |||
179 : | /* rgb565_to_yuv_c | ||
180 : | NOTE: identical to rgb555 except for shift/mask | ||
181 : | not tested */ | ||
182 : | |||
183 : | void | ||
184 : | rgb565_to_yv12_c(uint8_t * y_out, | ||
185 : | uint8_t * u_out, | ||
186 : | uint8_t * v_out, | ||
187 : | uint8_t * src, | ||
188 : | int width, | ||
189 : | int height, | ||
190 : | int y_stride) | ||
191 : | { | ||
192 : | int32_t src_stride = width * 2; | ||
193 : | |||
194 : | uint32_t y_dif = y_stride - width; | ||
195 : | uint32_t uv_dif = (y_stride - width) / 2; | ||
196 : | uint32_t x, y; | ||
197 : | |||
198 : | if (height < 0) { | ||
199 : | height = -height; | ||
200 : | src += (height - 1) * src_stride; | ||
201 : | src_stride = -src_stride; | ||
202 : | } | ||
203 : | |||
204 : | |||
205 : | for (y = height / 2; y; y--) { | ||
206 : | // process one 2x2 block per iteration | ||
207 : | for (x = 0; x < (uint32_t) width; x += 2) { | ||
208 : | int rgb, r, g, b, r4, g4, b4; | ||
209 : | |||
210 : | rgb = *(uint16_t *) (src + x * 2); | ||
211 : | b4 = b = (rgb << 3) & 0xf8; | ||
212 : | g4 = g = (rgb >> 3) & 0xfc; | ||
213 : | r4 = r = (rgb >> 8) & 0xf8; | ||
214 : | y_out[0] = | ||
215 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
216 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
217 : | |||
218 : | rgb = *(uint16_t *) (src + x * 2 + src_stride); | ||
219 : | b4 += b = (rgb << 3) & 0xf8; | ||
220 : | g4 += g = (rgb >> 3) & 0xfc; | ||
221 : | r4 += r = (rgb >> 8) & 0xf8; | ||
222 : | y_out[y_stride] = | ||
223 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
224 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
225 : | |||
226 : | rgb = *(uint16_t *) (src + x * 2 + 2); | ||
227 : | b4 += b = (rgb << 3) & 0xf8; | ||
228 : | g4 += g = (rgb >> 3) & 0xfc; | ||
229 : | r4 += r = (rgb >> 8) & 0xf8; | ||
230 : | y_out[1] = | ||
231 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
232 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
233 : | |||
234 : | rgb = *(uint16_t *) (src + x * 2 + src_stride + 2); | ||
235 : | b4 += b = (rgb << 3) & 0xf8; | ||
236 : | g4 += g = (rgb >> 3) & 0xfc; | ||
237 : | r4 += r = (rgb >> 8) & 0xf8; | ||
238 : | y_out[y_stride + 1] = | ||
239 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
240 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
241 : | |||
242 : | *u_out++ = | ||
243 : | (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + | ||
244 : | FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
245 : | U_ADD_IN; | ||
246 : | |||
247 : | |||
248 : | *v_out++ = | ||
249 : | (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - | ||
250 : | FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
251 : | V_ADD_IN; | ||
252 : | |||
253 : | y_out += 2; | ||
254 : | } | ||
255 : | src += src_stride * 2; | ||
256 : | y_out += y_dif + y_stride; | ||
257 : | u_out += uv_dif; | ||
258 : | v_out += uv_dif; | ||
259 : | } | ||
260 : | } | ||
261 : | |||
262 : | |||
263 : | |||
264 : | |||
265 : | /* rgb24 -> yuv 4:2:0 planar | ||
266 : | |||
267 : | NOTE: always flips. | ||
268 : | */ | ||
269 : | |||
270 : | void | ||
271 : | rgb24_to_yv12_c(uint8_t * y_out, | ||
272 : | uint8_t * u_out, | ||
273 : | uint8_t * v_out, | ||
274 : | uint8_t * src, | ||
275 : | int width, | ||
276 : | int height, | ||
277 : | int stride) | ||
278 : | { | ||
279 : | uint32_t width3 = (width << 1) + width; /* width * 3 */ | ||
280 : | uint32_t src_dif = (width << 3) + width; /* width3 * 3 */ | ||
281 : | uint32_t y_dif = (stride << 1) - width; | ||
282 : | uint32_t uv_dif = (stride - width) >> 1; | ||
283 : | uint32_t x, y; | ||
284 : | |||
285 : | src += (height - 2) * width3; | ||
286 : | |||
287 : | |||
288 : | for (y = height >> 1; y; y--) { | ||
289 : | for (x = width >> 1; x; x--) { | ||
290 : | uint32_t r, g, b, r4, g4, b4; | ||
291 : | |||
292 : | b4 = b = src[0]; | ||
293 : | g4 = g = src[1]; | ||
294 : | r4 = r = src[2]; | ||
295 : | y_out[stride + 0] = | ||
296 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
297 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
298 : | |||
299 : | b4 += (b = src[3]); | ||
300 : | g4 += (g = src[4]); | ||
301 : | r4 += (r = src[5]); | ||
302 : | y_out[stride + 1] = | ||
303 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
304 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
305 : | |||
306 : | b4 += (b = src[width3 + 0]); | ||
307 : | g4 += (g = src[width3 + 1]); | ||
308 : | r4 += (r = src[width3 + 2]); | ||
309 : | y_out[0] = | ||
310 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
311 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
312 : | |||
313 : | b4 += (b = src[width3 + 3]); | ||
314 : | g4 += (g = src[width3 + 4]); | ||
315 : | r4 += (r = src[width3 + 5]); | ||
316 : | y_out[1] = | ||
317 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
318 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
319 : | |||
320 : | *u_out++ = | ||
321 : | (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + | ||
322 : | FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
323 : | U_ADD_IN; | ||
324 : | |||
325 : | |||
326 : | *v_out++ = | ||
327 : | (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - | ||
328 : | FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
329 : | V_ADD_IN; | ||
330 : | |||
331 : | |||
332 : | src += 6; | ||
333 : | y_out += 2; | ||
334 : | } | ||
335 : | src -= src_dif; | ||
336 : | y_out += y_dif; | ||
337 : | u_out += uv_dif; | ||
338 : | v_out += uv_dif; | ||
339 : | } | ||
340 : | } | ||
341 : | |||
342 : | |||
343 : | /* rgb32 -> yuv 4:2:0 planar | ||
344 : | |||
345 : | NOTE: always flips | ||
346 : | */ | ||
347 : | |||
348 : | void | ||
349 : | rgb32_to_yv12_c(uint8_t * y_out, | ||
350 : | uint8_t * u_out, | ||
351 : | uint8_t * v_out, | ||
352 : | uint8_t * src, | ||
353 : | int width, | ||
354 : | int height, | ||
355 : | int stride) | ||
356 : | { | ||
357 : | uint32_t width4 = (width << 2); /* width * 4 */ | ||
358 : | uint32_t src_dif = 3 * width4; | ||
359 : | uint32_t y_dif = (stride << 1) - width; | ||
360 : | uint32_t uv_dif = (stride - width) >> 1; | ||
361 : | uint32_t x, y; | ||
362 : | |||
363 : | src += (height - 2) * width4; | ||
364 : | |||
365 : | for (y = height >> 1; y; y--) { | ||
366 : | for (x = width >> 1; x; x--) { | ||
367 : | uint32_t r, g, b, r4, g4, b4; | ||
368 : | |||
369 : | b4 = b = src[0]; | ||
370 : | g4 = g = src[1]; | ||
371 : | r4 = r = src[2]; | ||
372 : | y_out[stride + 0] = | ||
373 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
374 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
375 : | |||
376 : | b4 += (b = src[4]); | ||
377 : | g4 += (g = src[5]); | ||
378 : | r4 += (r = src[6]); | ||
379 : | y_out[stride + 1] = | ||
380 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
381 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
382 : | |||
383 : | b4 += (b = src[width4 + 0]); | ||
384 : | g4 += (g = src[width4 + 1]); | ||
385 : | r4 += (r = src[width4 + 2]); | ||
386 : | |||
387 : | y_out[0] = | ||
388 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
389 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
390 : | |||
391 : | b4 += (b = src[width4 + 4]); | ||
392 : | g4 += (g = src[width4 + 5]); | ||
393 : | r4 += (r = src[width4 + 6]); | ||
394 : | y_out[1] = | ||
395 : | (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + | ||
396 : | FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; | ||
397 : | |||
398 : | *u_out++ = | ||
399 : | (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + | ||
400 : | FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
401 : | U_ADD_IN; | ||
402 : | |||
403 : | *v_out++ = | ||
404 : | (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - | ||
405 : | FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + | ||
406 : | V_ADD_IN; | ||
407 : | |||
408 : | src += 8; | ||
409 : | y_out += 2; | ||
410 : | } | ||
411 : | src -= src_dif; | ||
412 : | y_out += y_dif; | ||
413 : | u_out += uv_dif; | ||
414 : | v_out += uv_dif; | ||
415 : | } | ||
416 : | } | ||
417 : | |||
418 : | /* yuv planar -> yuv 4:2:0 planar | ||
419 : | |||
420 : | NOTE: does not flip */ | ||
421 : | |||
422 : | void | ||
423 : | yuv_to_yv12_c(uint8_t * y_out, | ||
424 : | uint8_t * u_out, | ||
425 : | uint8_t * v_out, | ||
426 : | uint8_t * src, | ||
427 : | int width, | ||
428 : | int height, | ||
429 : | int stride) | ||
430 : | { | ||
431 : | uint32_t stride2 = stride >> 1; | ||
432 : | uint32_t width2 = width >> 1; | ||
433 : | uint32_t y; | ||
434 : | |||
435 : | for (y = height; y; y--) { | ||
436 : | memcpy(y_out, src, width); | ||
437 : | src += width; | ||
438 : | y_out += stride; | ||
439 : | } | ||
440 : | |||
441 : | for (y = height >> 1; y; y--) { | ||
442 : | memcpy(u_out, src, width2); | ||
443 : | src += width2; | ||
444 : | u_out += stride2; | ||
445 : | } | ||
446 : | |||
447 : | for (y = height >> 1; y; y--) { | ||
448 : | memcpy(v_out, src, width2); | ||
449 : | src += width2; | ||
450 : | v_out += stride2; | ||
451 : | } | ||
452 : | } | ||
453 : | |||
454 : | |||
455 : | |||
456 : | /* yuyv (yuv2) packed -> yuv 4:2:0 planar | ||
457 : | |||
458 : | NOTE: does not flip */ | ||
459 : | |||
460 : | void | ||
461 : | yuyv_to_yv12_c(uint8_t * y_out, | ||
462 : | uint8_t * u_out, | ||
463 : | uint8_t * v_out, | ||
464 : | uint8_t * src, | ||
465 : | int width, | ||
466 : | int height, | ||
467 : | int stride) | ||
468 : | { | ||
469 : | uint32_t width2 = width + width; | ||
470 : | uint32_t y_dif = stride - width; | ||
471 : | uint32_t uv_dif = y_dif >> 1; | ||
472 : | uint32_t x, y; | ||
473 : | |||
474 : | for (y = height >> 1; y; y--) { | ||
475 : | |||
476 : | for (x = width >> 1; x; x--) { | ||
477 : | *y_out++ = *src++; | ||
478 : | //*u_out++ = *src++; | ||
479 : | *u_out++ = (*(src + width2) + *src) >> 1; | ||
480 : | src++; | ||
481 : | *y_out++ = *src++; | ||
482 : | //*v_out++ = *src++; | ||
483 : | *v_out++ = (*(src + width2) + *src) >> 1; | ||
484 : | src++; | ||
485 : | |||
486 : | } | ||
487 : | |||
488 : | y_out += y_dif; | ||
489 : | u_out += uv_dif; | ||
490 : | v_out += uv_dif; | ||
491 : | |||
492 : | for (x = width >> 1; x; x--) { | ||
493 : | *y_out++ = *src++; | ||
494 : | src++; | ||
495 : | *y_out++ = *src++; | ||
496 : | src++; | ||
497 : | } | ||
498 : | |||
499 : | y_out += y_dif; | ||
500 : | |||
501 : | } | ||
502 : | |||
503 : | } | ||
504 : | |||
505 : | |||
506 : | |||
507 : | /* uyvy packed -> yuv 4:2:0 planar | ||
508 : | |||
509 : | NOTE: does not flip */ | ||
510 : | |||
511 : | |||
512 : | void | ||
513 : | uyvy_to_yv12_c(uint8_t * y_out, | ||
514 : | uint8_t * u_out, | ||
515 : | uint8_t * v_out, | ||
516 : | uint8_t * src, | ||
517 : | int width, | ||
518 : | int height, | ||
519 : | int stride) | ||
520 : | { | ||
521 : | uint32_t width2 = width + width; | ||
522 : | uint32_t y_dif = stride - width; | ||
523 : | uint32_t uv_dif = y_dif >> 1; | ||
524 : | uint32_t x, y; | ||
525 : | |||
526 : | for (y = height >> 1; y; y--) { | ||
527 : | |||
528 : | for (x = width >> 1; x; x--) { | ||
529 : | *u_out++ = *src++; | ||
530 : | // *u_out++ = (*(src+width2) + *src++) >> 1; | ||
531 : | *y_out++ = *src++; | ||
532 : | //*v_out++ = *src++; | ||
533 : | *v_out++ = (*(src + width2) + *src) >> 1; | ||
534 : | src++; | ||
535 : | *y_out++ = *src++; | ||
536 : | } | ||
537 : | |||
538 : | y_out += y_dif; | ||
539 : | u_out += uv_dif;; | ||
540 : | v_out += uv_dif;; | ||
541 : | |||
542 : | for (x = width >> 1; x; x--) { | ||
543 : | src++; | ||
544 : | *y_out++ = *src++; | ||
545 : | src++; | ||
546 : | *y_out++ = *src++; | ||
547 : | } | ||
548 : | |||
549 : | y_out += y_dif; | ||
550 : | } | ||
551 : | } | ||
552 : | |||
553 : | |||
554 : | /* yuv -> rgb def's */ | ||
555 : | |||
556 : | #define RGB_Y_OUT 1.164 | ||
557 : | #define B_U_OUT 2.018 | ||
558 : | #define Y_ADD_OUT 16 | ||
559 : | |||
560 : | #define G_U_OUT 0.391 | ||
561 : | #define G_V_OUT 0.813 | ||
562 : | #define U_ADD_OUT 128 | ||
563 : | |||
564 : | #define R_V_OUT 1.596 | ||
565 : | #define V_ADD_OUT 128 | ||
566 : | |||
567 : | |||
568 : | #define SCALEBITS_OUT 13 | ||
569 : | #define FIX_OUT(x) ((uint16_t) ((x) * (1L<<SCALEBITS_OUT) + 0.5)) | ||
570 : | |||
571 : | |||
572 : | /* initialize rgb lookup tables */ | ||
573 : | |||
574 : | void | ||
575 : | colorspace_init(void) | ||
576 : | { | ||
577 : | int32_t i; | ||
578 : | |||
579 : | for (i = 0; i < 256; i++) { | ||
580 : | RGB_Y_tab[i] = FIX_OUT(RGB_Y_OUT) * (i - Y_ADD_OUT); | ||
581 : | B_U_tab[i] = FIX_OUT(B_U_OUT) * (i - U_ADD_OUT); | ||
582 : | G_U_tab[i] = FIX_OUT(G_U_OUT) * (i - U_ADD_OUT); | ||
583 : | G_V_tab[i] = FIX_OUT(G_V_OUT) * (i - V_ADD_OUT); | ||
584 : | R_V_tab[i] = FIX_OUT(R_V_OUT) * (i - V_ADD_OUT); | ||
585 : | } | ||
586 : | } | ||
587 : | |||
588 : | /* yuv 4:2:0 planar -> rgb555 + very simple error diffusion | ||
589 : | */ | ||
590 : | |||
591 : | #define MK_RGB555(R,G,B) ((MAX(0,MIN(255, R)) << 7) & 0x7c00) | \ | ||
592 : | ((MAX(0,MIN(255, G)) << 2) & 0x03e0) | \ | ||
593 : | ((MAX(0,MIN(255, B)) >> 3) & 0x001f) | ||
594 : | |||
595 : | |||
596 : | void | ||
597 : | yv12_to_rgb555_c(uint8_t * dst, | ||
598 : | int dst_stride, | ||
599 : | uint8_t * y_src, | ||
600 : | uint8_t * u_src, | ||
601 : | uint8_t * v_src, | ||
602 : | int y_stride, | ||
603 : | int uv_stride, | ||
604 : | int width, | ||
605 : | int height) | ||
606 : | { | ||
607 : | const uint32_t dst_dif = 4 * dst_stride - 2 * width; | ||
608 : | int32_t y_dif = 2 * y_stride - width; | ||
609 : | |||
610 : | uint8_t *dst2 = dst + 2 * dst_stride; | ||
611 : | uint8_t *y_src2 = y_src + y_stride; | ||
612 : | uint32_t x, y; | ||
613 : | |||
614 : | if (height < 0) { | ||
615 : | height = -height; | ||
616 : | y_src += (height - 1) * y_stride; | ||
617 : | y_src2 = y_src - y_stride; | ||
618 : | u_src += (height / 2 - 1) * uv_stride; | ||
619 : | v_src += (height / 2 - 1) * uv_stride; | ||
620 : | y_dif = -width - 2 * y_stride; | ||
621 : | uv_stride = -uv_stride; | ||
622 : | } | ||
623 : | |||
624 : | for (y = height / 2; y; y--) { | ||
625 : | int r, g, b; | ||
626 : | int r2, g2, b2; | ||
627 : | |||
628 : | r = g = b = 0; | ||
629 : | r2 = g2 = b2 = 0; | ||
630 : | |||
631 : | // process one 2x2 block per iteration | ||
632 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
633 : | int u, v; | ||
634 : | int b_u, g_uv, r_v, rgb_y; | ||
635 : | |||
636 : | u = u_src[x]; | ||
637 : | v = v_src[x]; | ||
638 : | |||
639 : | b_u = B_U_tab[u]; | ||
640 : | g_uv = G_U_tab[u] + G_V_tab[v]; | ||
641 : | r_v = R_V_tab[v]; | ||
642 : | |||
643 : | rgb_y = RGB_Y_tab[*y_src]; | ||
644 : | b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
645 : | g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
646 : | r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
647 : | *(uint16_t *) dst = MK_RGB555(r, g, b); | ||
648 : | |||
649 : | y_src++; | ||
650 : | rgb_y = RGB_Y_tab[*y_src]; | ||
651 : | b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
652 : | g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
653 : | r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
654 : | *(uint16_t *) (dst + 2) = MK_RGB555(r, g, b); | ||
655 : | y_src++; | ||
656 : | |||
657 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
658 : | b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
659 : | g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
660 : | r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
661 : | *(uint16_t *) (dst2) = MK_RGB555(r2, g2, b2); | ||
662 : | y_src2++; | ||
663 : | |||
664 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
665 : | b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
666 : | g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
667 : | r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
668 : | *(uint16_t *) (dst2 + 2) = MK_RGB555(r2, g2, b2); | ||
669 : | y_src2++; | ||
670 : | |||
671 : | dst += 4; | ||
672 : | dst2 += 4; | ||
673 : | } | ||
674 : | |||
675 : | dst += dst_dif; | ||
676 : | dst2 += dst_dif; | ||
677 : | |||
678 : | y_src += y_dif; | ||
679 : | y_src2 += y_dif; | ||
680 : | |||
681 : | u_src += uv_stride; | ||
682 : | v_src += uv_stride; | ||
683 : | } | ||
684 : | } | ||
685 : | |||
686 : | |||
687 : | /* yuv 4:2:0 planar -> rgb565 + very simple error diffusion | ||
688 : | NOTE: identical to rgb555 except for shift/mask */ | ||
689 : | |||
690 : | |||
691 : | #define MK_RGB565(R,G,B) ((MAX(0,MIN(255, R)) << 8) & 0xf800) | \ | ||
692 : | ((MAX(0,MIN(255, G)) << 3) & 0x07e0) | \ | ||
693 : | ((MAX(0,MIN(255, B)) >> 3) & 0x001f) | ||
694 : | |||
695 : | void | ||
696 : | yv12_to_rgb565_c(uint8_t * dst, | ||
697 : | int dst_stride, | ||
698 : | uint8_t * y_src, | ||
699 : | uint8_t * u_src, | ||
700 : | uint8_t * v_src, | ||
701 : | int y_stride, | ||
702 : | int uv_stride, | ||
703 : | int width, | ||
704 : | int height) | ||
705 : | { | ||
706 : | const uint32_t dst_dif = 4 * dst_stride - 2 * width; | ||
707 : | int32_t y_dif = 2 * y_stride - width; | ||
708 : | |||
709 : | uint8_t *dst2 = dst + 2 * dst_stride; | ||
710 : | uint8_t *y_src2 = y_src + y_stride; | ||
711 : | uint32_t x, y; | ||
712 : | |||
713 : | if (height < 0) { // flip image? | ||
714 : | height = -height; | ||
715 : | y_src += (height - 1) * y_stride; | ||
716 : | y_src2 = y_src - y_stride; | ||
717 : | u_src += (height / 2 - 1) * uv_stride; | ||
718 : | v_src += (height / 2 - 1) * uv_stride; | ||
719 : | y_dif = -width - 2 * y_stride; | ||
720 : | uv_stride = -uv_stride; | ||
721 : | } | ||
722 : | |||
723 : | for (y = height / 2; y; y--) { | ||
724 : | int r, g, b; | ||
725 : | int r2, g2, b2; | ||
726 : | |||
727 : | r = g = b = 0; | ||
728 : | r2 = g2 = b2 = 0; | ||
729 : | |||
730 : | // process one 2x2 block per iteration | ||
731 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
732 : | int u, v; | ||
733 : | int b_u, g_uv, r_v, rgb_y; | ||
734 : | |||
735 : | u = u_src[x]; | ||
736 : | v = v_src[x]; | ||
737 : | |||
738 : | b_u = B_U_tab[u]; | ||
739 : | g_uv = G_U_tab[u] + G_V_tab[v]; | ||
740 : | r_v = R_V_tab[v]; | ||
741 : | |||
742 : | rgb_y = RGB_Y_tab[*y_src]; | ||
743 : | b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
744 : | g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
745 : | r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
746 : | *(uint16_t *) dst = MK_RGB565(r, g, b); | ||
747 : | |||
748 : | y_src++; | ||
749 : | rgb_y = RGB_Y_tab[*y_src]; | ||
750 : | b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
751 : | g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
752 : | r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
753 : | *(uint16_t *) (dst + 2) = MK_RGB565(r, g, b); | ||
754 : | y_src++; | ||
755 : | |||
756 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
757 : | b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
758 : | g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
759 : | r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
760 : | *(uint16_t *) (dst2) = MK_RGB565(r2, g2, b2); | ||
761 : | y_src2++; | ||
762 : | |||
763 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
764 : | b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT); | ||
765 : | g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT); | ||
766 : | r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT); | ||
767 : | *(uint16_t *) (dst2 + 2) = MK_RGB565(r2, g2, b2); | ||
768 : | y_src2++; | ||
769 : | |||
770 : | dst += 4; | ||
771 : | dst2 += 4; | ||
772 : | } | ||
773 : | |||
774 : | dst += dst_dif; | ||
775 : | dst2 += dst_dif; | ||
776 : | |||
777 : | y_src += y_dif; | ||
778 : | y_src2 += y_dif; | ||
779 : | |||
780 : | u_src += uv_stride; | ||
781 : | v_src += uv_stride; | ||
782 : | } | ||
783 : | } | ||
784 : | |||
785 : | |||
786 : | |||
787 : | /* yuv 4:2:0 planar -> rgb24 */ | ||
788 : | |||
789 : | void | ||
790 : | yv12_to_rgb24_c(uint8_t * dst, | ||
791 : | int dst_stride, | ||
792 : | uint8_t * y_src, | ||
793 : | uint8_t * u_src, | ||
794 : | uint8_t * v_src, | ||
795 : | int y_stride, | ||
796 : | int uv_stride, | ||
797 : | int width, | ||
798 : | int height) | ||
799 : | { | ||
800 : | const uint32_t dst_dif = 6 * dst_stride - 3 * width; | ||
801 : | int32_t y_dif = 2 * y_stride - width; | ||
802 : | |||
803 : | uint8_t *dst2 = dst + 3 * dst_stride; | ||
804 : | uint8_t *y_src2 = y_src + y_stride; | ||
805 : | uint32_t x, y; | ||
806 : | |||
807 : | if (height < 0) { // flip image? | ||
808 : | height = -height; | ||
809 : | y_src += (height - 1) * y_stride; | ||
810 : | y_src2 = y_src - y_stride; | ||
811 : | u_src += (height / 2 - 1) * uv_stride; | ||
812 : | v_src += (height / 2 - 1) * uv_stride; | ||
813 : | y_dif = -width - 2 * y_stride; | ||
814 : | uv_stride = -uv_stride; | ||
815 : | } | ||
816 : | |||
817 : | for (y = height / 2; y; y--) { | ||
818 : | // process one 2x2 block per iteration | ||
819 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
820 : | int u, v; | ||
821 : | int b_u, g_uv, r_v, rgb_y; | ||
822 : | int r, g, b; | ||
823 : | |||
824 : | u = u_src[x]; | ||
825 : | v = v_src[x]; | ||
826 : | |||
827 : | b_u = B_U_tab[u]; | ||
828 : | g_uv = G_U_tab[u] + G_V_tab[v]; | ||
829 : | r_v = R_V_tab[v]; | ||
830 : | |||
831 : | rgb_y = RGB_Y_tab[*y_src]; | ||
832 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
833 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
834 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
835 : | dst[0] = MAX(0, MIN(255, b)); | ||
836 : | dst[1] = MAX(0, MIN(255, g)); | ||
837 : | dst[2] = MAX(0, MIN(255, r)); | ||
838 : | |||
839 : | y_src++; | ||
840 : | rgb_y = RGB_Y_tab[*y_src]; | ||
841 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
842 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
843 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
844 : | dst[3] = MAX(0, MIN(255, b)); | ||
845 : | dst[4] = MAX(0, MIN(255, g)); | ||
846 : | dst[5] = MAX(0, MIN(255, r)); | ||
847 : | y_src++; | ||
848 : | |||
849 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
850 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
851 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
852 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
853 : | dst2[0] = MAX(0, MIN(255, b)); | ||
854 : | dst2[1] = MAX(0, MIN(255, g)); | ||
855 : | dst2[2] = MAX(0, MIN(255, r)); | ||
856 : | y_src2++; | ||
857 : | |||
858 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
859 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
860 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
861 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
862 : | dst2[3] = MAX(0, MIN(255, b)); | ||
863 : | dst2[4] = MAX(0, MIN(255, g)); | ||
864 : | dst2[5] = MAX(0, MIN(255, r)); | ||
865 : | y_src2++; | ||
866 : | |||
867 : | dst += 6; | ||
868 : | dst2 += 6; | ||
869 : | } | ||
870 : | |||
871 : | dst += dst_dif; | ||
872 : | dst2 += dst_dif; | ||
873 : | |||
874 : | y_src += y_dif; | ||
875 : | y_src2 += y_dif; | ||
876 : | |||
877 : | u_src += uv_stride; | ||
878 : | v_src += uv_stride; | ||
879 : | } | ||
880 : | } | ||
881 : | |||
882 : | |||
883 : | |||
884 : | /* yuv 4:2:0 planar -> rgb32 */ | ||
885 : | |||
886 : | void | ||
887 : | yv12_to_rgb32_c(uint8_t * dst, | ||
888 : | int dst_stride, | ||
889 : | uint8_t * y_src, | ||
890 : | uint8_t * v_src, | ||
891 : | uint8_t * u_src, | ||
892 : | int y_stride, | ||
893 : | int uv_stride, | ||
894 : | int width, | ||
895 : | int height) | ||
896 : | { | ||
897 : | const uint32_t dst_dif = 8 * dst_stride - 4 * width; | ||
898 : | int32_t y_dif = 2 * y_stride - width; | ||
899 : | |||
900 : | uint8_t *dst2 = dst + 4 * dst_stride; | ||
901 : | uint8_t *y_src2 = y_src + y_stride; | ||
902 : | uint32_t x, y; | ||
903 : | |||
904 : | if (height < 0) { // flip image? | ||
905 : | height = -height; | ||
906 : | y_src += (height - 1) * y_stride; | ||
907 : | y_src2 = y_src - y_stride; | ||
908 : | u_src += (height / 2 - 1) * uv_stride; | ||
909 : | v_src += (height / 2 - 1) * uv_stride; | ||
910 : | y_dif = -width - 2 * y_stride; | ||
911 : | uv_stride = -uv_stride; | ||
912 : | } | ||
913 : | |||
914 : | for (y = height / 2; y; y--) { | ||
915 : | // process one 2x2 block per iteration | ||
916 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
917 : | int u, v; | ||
918 : | int b_u, g_uv, r_v, rgb_y; | ||
919 : | int r, g, b; | ||
920 : | |||
921 : | u = u_src[x]; | ||
922 : | v = v_src[x]; | ||
923 : | |||
924 : | b_u = B_U_tab[u]; | ||
925 : | g_uv = G_U_tab[u] + G_V_tab[v]; | ||
926 : | r_v = R_V_tab[v]; | ||
927 : | |||
928 : | rgb_y = RGB_Y_tab[*y_src]; | ||
929 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
930 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
931 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
932 : | dst[0] = MAX(0, MIN(255, r)); | ||
933 : | dst[1] = MAX(0, MIN(255, g)); | ||
934 : | dst[2] = MAX(0, MIN(255, b)); | ||
935 : | dst[3] = 0; | ||
936 : | |||
937 : | y_src++; | ||
938 : | rgb_y = RGB_Y_tab[*y_src]; | ||
939 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
940 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
941 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
942 : | dst[4] = MAX(0, MIN(255, r)); | ||
943 : | dst[5] = MAX(0, MIN(255, g)); | ||
944 : | dst[6] = MAX(0, MIN(255, b)); | ||
945 : | dst[7] = 0; | ||
946 : | y_src++; | ||
947 : | |||
948 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
949 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
950 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
951 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
952 : | dst2[0] = MAX(0, MIN(255, r)); | ||
953 : | dst2[1] = MAX(0, MIN(255, g)); | ||
954 : | dst2[2] = MAX(0, MIN(255, b)); | ||
955 : | dst2[3] = 0; | ||
956 : | y_src2++; | ||
957 : | |||
958 : | rgb_y = RGB_Y_tab[*y_src2]; | ||
959 : | b = (rgb_y + b_u) >> SCALEBITS_OUT; | ||
960 : | g = (rgb_y - g_uv) >> SCALEBITS_OUT; | ||
961 : | r = (rgb_y + r_v) >> SCALEBITS_OUT; | ||
962 : | dst2[4] = MAX(0, MIN(255, r)); | ||
963 : | dst2[5] = MAX(0, MIN(255, g)); | ||
964 : | dst2[6] = MAX(0, MIN(255, b)); | ||
965 : | dst2[7] = 0; | ||
966 : | y_src2++; | ||
967 : | |||
968 : | dst += 8; | ||
969 : | dst2 += 8; | ||
970 : | } | ||
971 : | |||
972 : | dst += dst_dif; | ||
973 : | dst2 += dst_dif; | ||
974 : | |||
975 : | y_src += y_dif; | ||
976 : | y_src2 += y_dif; | ||
977 : | |||
978 : | u_src += uv_stride; | ||
979 : | v_src += uv_stride; | ||
980 : | } | ||
981 : | } | ||
982 : | |||
983 : | |||
984 : | |||
985 : | /* yuv 4:2:0 planar -> yuv planar */ | ||
986 : | |||
987 : | void | ||
988 : | yv12_to_yuv_c(uint8_t * dst, | ||
989 : | int dst_stride, | ||
990 : | uint8_t * y_src, | ||
991 : | uint8_t * u_src, | ||
992 : | uint8_t * v_src, | ||
993 : | int y_stride, | ||
994 : | int uv_stride, | ||
995 : | int width, | ||
996 : | int height) | ||
997 : | { | ||
998 : | uint32_t dst_stride2 = dst_stride >> 1; | ||
999 : | uint32_t width2 = width >> 1; | ||
1000 : | uint32_t y; | ||
1001 : | |||
1002 : | if (height < 0) { | ||
1003 : | height = -height; | ||
1004 : | y_src += (height - 1) * y_stride; | ||
1005 : | u_src += (height / 2 - 1) * uv_stride; | ||
1006 : | v_src += (height / 2 - 1) * uv_stride; | ||
1007 : | y_stride = -y_stride; | ||
1008 : | uv_stride = -uv_stride; | ||
1009 : | } | ||
1010 : | |||
1011 : | for (y = height; y; y--) { | ||
1012 : | memcpy(dst, y_src, width); | ||
1013 : | dst += dst_stride; | ||
1014 : | y_src += y_stride; | ||
1015 : | } | ||
1016 : | |||
1017 : | for (y = height >> 1; y; y--) { | ||
1018 : | memcpy(dst, u_src, width2); | ||
1019 : | dst += dst_stride2; | ||
1020 : | u_src += uv_stride; | ||
1021 : | } | ||
1022 : | |||
1023 : | for (y = height >> 1; y; y--) { | ||
1024 : | memcpy(dst, v_src, width2); | ||
1025 : | dst += dst_stride2; | ||
1026 : | v_src += uv_stride; | ||
1027 : | } | ||
1028 : | } | ||
1029 : | |||
1030 : | |||
1031 : | |||
1032 : | |||
1033 : | /* yuv 4:2:0 planar -> yuyv (yuv2) packed */ | ||
1034 : | |||
1035 : | void | ||
1036 : | yv12_to_yuyv_c(uint8_t * dst, | ||
1037 : | int dst_stride, | ||
1038 : | uint8_t * y_src, | ||
1039 : | uint8_t * u_src, | ||
1040 : | uint8_t * v_src, | ||
1041 : | int y_stride, | ||
1042 : | int uv_stride, | ||
1043 : | int width, | ||
1044 : | int height) | ||
1045 : | { | ||
1046 : | const uint32_t dst_dif = 2 * (dst_stride - width); | ||
1047 : | uint32_t x, y; | ||
1048 : | |||
1049 : | if (height < 0) { | ||
1050 : | height = -height; | ||
1051 : | y_src += (height - 1) * y_stride; | ||
1052 : | u_src += (height / 2 - 1) * uv_stride; | ||
1053 : | v_src += (height / 2 - 1) * uv_stride; | ||
1054 : | y_stride = -y_stride; | ||
1055 : | uv_stride = -uv_stride; | ||
1056 : | } | ||
1057 : | |||
1058 : | for (y = 0; y < (uint32_t) height; y++) { | ||
1059 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
1060 : | dst[0] = y_src[2 * x]; | ||
1061 : | dst[1] = u_src[x]; | ||
1062 : | dst[2] = y_src[2 * x + 1]; | ||
1063 : | dst[3] = v_src[x]; | ||
1064 : | dst += 4; | ||
1065 : | } | ||
1066 : | dst += dst_dif; | ||
1067 : | y_src += y_stride; | ||
1068 : | if (y & 1) { | ||
1069 : | u_src += uv_stride; | ||
1070 : | v_src += uv_stride; | ||
1071 : | } | ||
1072 : | } | ||
1073 : | } | ||
1074 : | |||
1075 : | |||
1076 : | |||
1077 : | /* yuv 4:2:0 planar -> uyvy packed */ | ||
1078 : | |||
1079 : | void | ||
1080 : | yv12_to_uyvy_c(uint8_t * dst, | ||
1081 : | int dst_stride, | ||
1082 : | uint8_t * y_src, | ||
1083 : | uint8_t * u_src, | ||
1084 : | uint8_t * v_src, | ||
1085 : | int y_stride, | ||
1086 : | int uv_stride, | ||
1087 : | int width, | ||
1088 : | int height) | ||
1089 : | { | ||
1090 : | const uint32_t dst_dif = 2 * (dst_stride - width); | ||
1091 : | uint32_t x, y; | ||
1092 : | |||
1093 : | if (height < 0) { | ||
1094 : | height = -height; | ||
1095 : | y_src += (height - 1) * y_stride; | ||
1096 : | u_src += (height / 2 - 1) * uv_stride; | ||
1097 : | v_src += (height / 2 - 1) * uv_stride; | ||
1098 : | y_stride = -y_stride; | ||
1099 : | uv_stride = -uv_stride; | ||
1100 : | } | ||
1101 : | |||
1102 : | for (y = 0; y < (uint32_t) height; y++) { | ||
1103 : | for (x = 0; x < (uint32_t) width / 2; x++) { | ||
1104 : | dst[0] = u_src[x]; | ||
1105 : | dst[1] = y_src[2 * x]; | ||
1106 : | dst[2] = v_src[x]; | ||
1107 : | dst[3] = y_src[2 * x + 1]; | ||
1108 : | dst += 4; | ||
1109 : | } | ||
1110 : | dst += dst_dif; | ||
1111 : | y_src += y_stride; | ||
1112 : | if (y & 1) { | ||
1113 : | u_src += uv_stride; | ||
1114 : | v_src += uv_stride; | ||
1115 : | } | ||
1116 : | } | ||
1117 : | } | ||
1118 : | |||
1119 : | |||
1120 : | /* user yuv planar -> yuv 4:2:0 planar | ||
1121 : | |||
1122 : | NOTE: does not flip */ | ||
1123 : | |||
1124 : | void | ||
1125 : | user_to_yuv_c(uint8_t * y_out, | ||
1126 : | uint8_t * u_out, | ||
1127 : | uint8_t * v_out, | ||
1128 : | int stride, | ||
1129 : | DEC_PICTURE * picture, | ||
1130 : | int width, | ||
1131 : | int height) | ||
1132 : | { | ||
1133 : | uint32_t stride2 = stride >> 1; | ||
1134 : | uint32_t width2 = width >> 1; | ||
1135 : | uint32_t y; | ||
1136 : | uint8_t *src; | ||
1137 : | |||
1138 : | src = picture->y; | ||
1139 : | for (y = height; y; y--) { | ||
1140 : | memcpy(y_out, src, width); | ||
1141 : | src += picture->stride_y; | ||
1142 : | y_out += stride; | ||
1143 : | } | ||
1144 : | |||
1145 : | src = picture->u; | ||
1146 : | for (y = height >> 1; y; y--) { | ||
1147 : | memcpy(u_out, src, width2); | ||
1148 : | src += picture->stride_uv; | ||
1149 : | u_out += stride2; | ||
1150 : | } | ||
1151 : | |||
1152 : | src = picture->v; | ||
1153 : | for (y = height >> 1; y; y--) { | ||
1154 : | memcpy(v_out, src, width2); | ||
1155 : | src += picture->stride_uv; | ||
1156 : | v_out += stride2; | ||
1157 : | } | ||
1158 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |