Commit | Line | Data |
---|---|---|
de6d9b64 FB |
1 | /* |
2 | * Misc image convertion routines | |
524c6b63 | 3 | * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. |
de6d9b64 | 4 | * |
ff4ec49e FB |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
de6d9b64 | 9 | * |
ff4ec49e | 10 | * This library is distributed in the hope that it will be useful, |
de6d9b64 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
ff4ec49e FB |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. | |
de6d9b64 | 14 | * |
ff4ec49e FB |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
de6d9b64 | 18 | */ |
983e3246 MN |
19 | |
20 | /** | |
1ab3d669 | 21 | * @file imgconvert.c |
983e3246 MN |
22 | * Misc image convertion routines. |
23 | */ | |
24 | ||
c50c0bc8 FB |
25 | /* TODO: |
26 | * - write 'ffimg' program to test all the image related stuff | |
27 | * - move all api to slice based system | |
28 | * - integrate deinterlacing, postprocessing and scaling in the conversion process | |
29 | */ | |
983e3246 | 30 | |
de6d9b64 | 31 | #include "avcodec.h" |
85c242d8 | 32 | #include "dsputil.h" |
de6d9b64 | 33 | |
54329dd5 NK |
34 | #ifdef USE_FASTMEMCPY |
35 | #include "fastmemcpy.h" | |
36 | #endif | |
5981f4e6 F |
37 | |
38 | #ifdef HAVE_MMX | |
39 | #include "i386/mmx.h" | |
40 | #endif | |
524c6b63 | 41 | |
b6147995 FB |
42 | #define FF_COLOR_RGB 0 /* RGB color space */ |
43 | #define FF_COLOR_GRAY 1 /* gray color space */ | |
44 | #define FF_COLOR_YUV 2 /* YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ | |
45 | #define FF_COLOR_YUV_JPEG 3 /* YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ | |
46 | ||
524c6b63 FB |
47 | typedef struct PixFmtInfo { |
48 | const char *name; | |
0c1a9eda | 49 | uint8_t nb_components; /* number of components in AVPicture array */ |
b6147995 | 50 | uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */ |
0c1a9eda ZK |
51 | uint8_t is_packed : 1; /* true if multiple components in same word */ |
52 | uint8_t is_paletted : 1; /* true if paletted */ | |
53 | uint8_t is_alpha : 1; /* true if alpha can be specified */ | |
0c1a9eda ZK |
54 | uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */ |
55 | uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */ | |
b6147995 | 56 | uint8_t depth; /* bit depth of the color components */ |
524c6b63 FB |
57 | } PixFmtInfo; |
58 | ||
59 | /* this table gives more information about formats */ | |
60 | static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { | |
61 | /* YUV formats */ | |
62 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 63 | .name = "yuv420p", |
b6147995 FB |
64 | .nb_components = 3, |
65 | .color_type = FF_COLOR_YUV, | |
66 | .depth = 8, | |
ef9f7306 | 67 | .x_chroma_shift = 1, .y_chroma_shift = 1, |
524c6b63 FB |
68 | }, |
69 | [PIX_FMT_YUV422P] = { | |
ef9f7306 | 70 | .name = "yuv422p", |
b6147995 FB |
71 | .nb_components = 3, |
72 | .color_type = FF_COLOR_YUV, | |
73 | .depth = 8, | |
ef9f7306 | 74 | .x_chroma_shift = 1, .y_chroma_shift = 0, |
524c6b63 FB |
75 | }, |
76 | [PIX_FMT_YUV444P] = { | |
ef9f7306 | 77 | .name = "yuv444p", |
b6147995 FB |
78 | .nb_components = 3, |
79 | .color_type = FF_COLOR_YUV, | |
80 | .depth = 8, | |
ef9f7306 | 81 | .x_chroma_shift = 0, .y_chroma_shift = 0, |
524c6b63 FB |
82 | }, |
83 | [PIX_FMT_YUV422] = { | |
ef9f7306 | 84 | .name = "yuv422", |
b6147995 FB |
85 | .nb_components = 1, .is_packed = 1, |
86 | .color_type = FF_COLOR_YUV, | |
87 | .depth = 8, | |
ef9f7306 | 88 | .x_chroma_shift = 1, .y_chroma_shift = 0, |
524c6b63 FB |
89 | }, |
90 | [PIX_FMT_YUV410P] = { | |
ef9f7306 | 91 | .name = "yuv410p", |
b6147995 FB |
92 | .nb_components = 3, |
93 | .color_type = FF_COLOR_YUV, | |
94 | .depth = 8, | |
ef9f7306 | 95 | .x_chroma_shift = 2, .y_chroma_shift = 2, |
524c6b63 FB |
96 | }, |
97 | [PIX_FMT_YUV411P] = { | |
ef9f7306 | 98 | .name = "yuv411p", |
b6147995 FB |
99 | .nb_components = 3, |
100 | .color_type = FF_COLOR_YUV, | |
101 | .depth = 8, | |
ef9f7306 | 102 | .x_chroma_shift = 2, .y_chroma_shift = 0, |
524c6b63 FB |
103 | }, |
104 | ||
b6147995 FB |
105 | /* JPEG YUV */ |
106 | [PIX_FMT_YUVJ420P] = { | |
107 | .name = "yuvj420p", | |
108 | .nb_components = 3, | |
109 | .color_type = FF_COLOR_YUV_JPEG, | |
110 | .depth = 8, | |
111 | .x_chroma_shift = 1, .y_chroma_shift = 1, | |
112 | }, | |
113 | [PIX_FMT_YUVJ422P] = { | |
114 | .name = "yuvj422p", | |
115 | .nb_components = 3, | |
116 | .color_type = FF_COLOR_YUV_JPEG, | |
117 | .depth = 8, | |
118 | .x_chroma_shift = 1, .y_chroma_shift = 0, | |
119 | }, | |
120 | [PIX_FMT_YUVJ444P] = { | |
121 | .name = "yuvj444p", | |
122 | .nb_components = 3, | |
123 | .color_type = FF_COLOR_YUV_JPEG, | |
124 | .depth = 8, | |
125 | .x_chroma_shift = 0, .y_chroma_shift = 0, | |
126 | }, | |
127 | ||
524c6b63 FB |
128 | /* RGB formats */ |
129 | [PIX_FMT_RGB24] = { | |
ef9f7306 MR |
130 | .name = "rgb24", |
131 | .nb_components = 1, .is_packed = 1, | |
b6147995 FB |
132 | .color_type = FF_COLOR_RGB, |
133 | .depth = 8, | |
524c6b63 FB |
134 | }, |
135 | [PIX_FMT_BGR24] = { | |
ef9f7306 MR |
136 | .name = "bgr24", |
137 | .nb_components = 1, .is_packed = 1, | |
b6147995 FB |
138 | .color_type = FF_COLOR_RGB, |
139 | .depth = 8, | |
524c6b63 FB |
140 | }, |
141 | [PIX_FMT_RGBA32] = { | |
ef9f7306 MR |
142 | .name = "rgba32", |
143 | .nb_components = 1, .is_packed = 1, .is_alpha = 1, | |
b6147995 FB |
144 | .color_type = FF_COLOR_RGB, |
145 | .depth = 8, | |
524c6b63 FB |
146 | }, |
147 | [PIX_FMT_RGB565] = { | |
ef9f7306 MR |
148 | .name = "rgb565", |
149 | .nb_components = 1, .is_packed = 1, | |
b6147995 FB |
150 | .color_type = FF_COLOR_RGB, |
151 | .depth = 5, | |
524c6b63 FB |
152 | }, |
153 | [PIX_FMT_RGB555] = { | |
ef9f7306 MR |
154 | .name = "rgb555", |
155 | .nb_components = 1, .is_packed = 1, .is_alpha = 1, | |
b6147995 FB |
156 | .color_type = FF_COLOR_RGB, |
157 | .depth = 5, | |
524c6b63 FB |
158 | }, |
159 | ||
160 | /* gray / mono formats */ | |
161 | [PIX_FMT_GRAY8] = { | |
ef9f7306 | 162 | .name = "gray", |
b6147995 FB |
163 | .nb_components = 1, |
164 | .color_type = FF_COLOR_GRAY, | |
165 | .depth = 8, | |
524c6b63 FB |
166 | }, |
167 | [PIX_FMT_MONOWHITE] = { | |
ef9f7306 | 168 | .name = "monow", |
b6147995 FB |
169 | .nb_components = 1, |
170 | .color_type = FF_COLOR_GRAY, | |
171 | .depth = 1, | |
524c6b63 FB |
172 | }, |
173 | [PIX_FMT_MONOBLACK] = { | |
ef9f7306 | 174 | .name = "monob", |
b6147995 FB |
175 | .nb_components = 1, |
176 | .color_type = FF_COLOR_GRAY, | |
177 | .depth = 1, | |
524c6b63 | 178 | }, |
7e6d70d0 FB |
179 | |
180 | /* paletted formats */ | |
181 | [PIX_FMT_PAL8] = { | |
182 | .name = "pal8", | |
6d93f194 | 183 | .nb_components = 1, .is_packed = 1, .is_alpha = 1, .is_paletted = 1, |
b6147995 FB |
184 | .color_type = FF_COLOR_RGB, |
185 | .depth = 8, | |
7e6d70d0 | 186 | }, |
524c6b63 FB |
187 | }; |
188 | ||
189 | void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift) | |
190 | { | |
b6147995 FB |
191 | *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift; |
192 | *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift; | |
524c6b63 FB |
193 | } |
194 | ||
195 | const char *avcodec_get_pix_fmt_name(int pix_fmt) | |
196 | { | |
197 | if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) | |
198 | return "???"; | |
199 | else | |
200 | return pix_fmt_info[pix_fmt].name; | |
201 | } | |
202 | ||
2a877875 | 203 | /* Picture field are filled with 'ptr' addresses. Also return size */ |
0c1a9eda | 204 | int avpicture_fill(AVPicture *picture, uint8_t *ptr, |
2a877875 FB |
205 | int pix_fmt, int width, int height) |
206 | { | |
4c7e8619 FB |
207 | int size, w2, h2, size2; |
208 | PixFmtInfo *pinfo; | |
209 | ||
210 | pinfo = &pix_fmt_info[pix_fmt]; | |
2a877875 FB |
211 | size = width * height; |
212 | switch(pix_fmt) { | |
213 | case PIX_FMT_YUV420P: | |
4c7e8619 FB |
214 | case PIX_FMT_YUV422P: |
215 | case PIX_FMT_YUV444P: | |
216 | case PIX_FMT_YUV410P: | |
217 | case PIX_FMT_YUV411P: | |
c50c0bc8 FB |
218 | case PIX_FMT_YUVJ420P: |
219 | case PIX_FMT_YUVJ422P: | |
220 | case PIX_FMT_YUVJ444P: | |
4c7e8619 FB |
221 | w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; |
222 | h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; | |
223 | size2 = w2 * h2; | |
2a877875 FB |
224 | picture->data[0] = ptr; |
225 | picture->data[1] = picture->data[0] + size; | |
4c7e8619 | 226 | picture->data[2] = picture->data[1] + size2; |
2a877875 | 227 | picture->linesize[0] = width; |
4c7e8619 FB |
228 | picture->linesize[1] = w2; |
229 | picture->linesize[2] = w2; | |
230 | return size + 2 * size2; | |
2a877875 FB |
231 | case PIX_FMT_RGB24: |
232 | case PIX_FMT_BGR24: | |
233 | picture->data[0] = ptr; | |
234 | picture->data[1] = NULL; | |
235 | picture->data[2] = NULL; | |
236 | picture->linesize[0] = width * 3; | |
237 | return size * 3; | |
2a877875 FB |
238 | case PIX_FMT_RGBA32: |
239 | picture->data[0] = ptr; | |
240 | picture->data[1] = NULL; | |
241 | picture->data[2] = NULL; | |
242 | picture->linesize[0] = width * 4; | |
243 | return size * 4; | |
2a877875 FB |
244 | case PIX_FMT_RGB555: |
245 | case PIX_FMT_RGB565: | |
246 | case PIX_FMT_YUV422: | |
247 | picture->data[0] = ptr; | |
248 | picture->data[1] = NULL; | |
249 | picture->data[2] = NULL; | |
250 | picture->linesize[0] = width * 2; | |
251 | return size * 2; | |
252 | case PIX_FMT_GRAY8: | |
253 | picture->data[0] = ptr; | |
254 | picture->data[1] = NULL; | |
255 | picture->data[2] = NULL; | |
256 | picture->linesize[0] = width; | |
257 | return size; | |
258 | case PIX_FMT_MONOWHITE: | |
259 | case PIX_FMT_MONOBLACK: | |
260 | picture->data[0] = ptr; | |
261 | picture->data[1] = NULL; | |
262 | picture->data[2] = NULL; | |
263 | picture->linesize[0] = (width + 7) >> 3; | |
264 | return picture->linesize[0] * height; | |
7e6d70d0 FB |
265 | case PIX_FMT_PAL8: |
266 | size2 = (size + 3) & ~3; | |
267 | picture->data[0] = ptr; | |
268 | picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */ | |
269 | picture->data[2] = NULL; | |
270 | picture->linesize[0] = width; | |
271 | picture->linesize[1] = 4; | |
272 | return size2 + 256 * 4; | |
2a877875 FB |
273 | default: |
274 | picture->data[0] = NULL; | |
275 | picture->data[1] = NULL; | |
276 | picture->data[2] = NULL; | |
7e6d70d0 | 277 | picture->data[3] = NULL; |
2a877875 FB |
278 | return -1; |
279 | } | |
280 | } | |
281 | ||
282 | int avpicture_get_size(int pix_fmt, int width, int height) | |
283 | { | |
284 | AVPicture dummy_pict; | |
285 | return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); | |
286 | } | |
287 | ||
b6147995 FB |
288 | /** |
289 | * compute the loss when converting from a pixel format to another | |
290 | */ | |
291 | int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt, | |
292 | int has_alpha) | |
293 | { | |
294 | const PixFmtInfo *pf, *ps; | |
295 | int loss; | |
296 | ||
297 | ps = &pix_fmt_info[src_pix_fmt]; | |
298 | pf = &pix_fmt_info[dst_pix_fmt]; | |
299 | ||
300 | /* compute loss */ | |
301 | loss = 0; | |
302 | pf = &pix_fmt_info[dst_pix_fmt]; | |
303 | if (pf->depth < ps->depth) | |
304 | loss |= FF_LOSS_DEPTH; | |
305 | if (pf->x_chroma_shift >= ps->x_chroma_shift || | |
306 | pf->y_chroma_shift >= ps->y_chroma_shift) | |
307 | loss |= FF_LOSS_RESOLUTION; | |
308 | switch(pf->color_type) { | |
309 | case FF_COLOR_RGB: | |
310 | if (ps->color_type != FF_COLOR_RGB && | |
311 | ps->color_type != FF_COLOR_GRAY) | |
312 | loss |= FF_LOSS_COLORSPACE; | |
313 | break; | |
314 | case FF_COLOR_GRAY: | |
315 | if (ps->color_type != FF_COLOR_GRAY) | |
316 | loss |= FF_LOSS_COLORSPACE; | |
317 | break; | |
318 | case FF_COLOR_YUV: | |
319 | if (ps->color_type != FF_COLOR_YUV) | |
320 | loss |= FF_LOSS_COLORSPACE; | |
321 | break; | |
322 | case FF_COLOR_YUV_JPEG: | |
323 | if (ps->color_type != FF_COLOR_YUV_JPEG && | |
324 | ps->color_type != FF_COLOR_YUV) | |
325 | loss |= FF_LOSS_COLORSPACE; | |
326 | break; | |
327 | default: | |
328 | /* fail safe test */ | |
329 | if (ps->color_type != pf->color_type) | |
330 | loss |= FF_LOSS_COLORSPACE; | |
331 | break; | |
332 | } | |
333 | if (pf->color_type == FF_COLOR_GRAY && | |
334 | ps->color_type != FF_COLOR_GRAY) | |
335 | loss |= FF_LOSS_CHROMA; | |
336 | if (!pf->is_alpha && (ps->is_alpha && has_alpha)) | |
337 | loss |= FF_LOSS_ALPHA; | |
338 | if (pf->is_paletted && (!ps->is_paletted && ps->color_type != FF_COLOR_GRAY)) | |
339 | loss |= FF_LOSS_COLORQUANT; | |
340 | return loss; | |
341 | } | |
342 | ||
343 | static int avg_bits_per_pixel(int pix_fmt) | |
344 | { | |
345 | int bits; | |
346 | const PixFmtInfo *pf; | |
347 | ||
348 | pf = &pix_fmt_info[pix_fmt]; | |
349 | if (pf->is_packed) { | |
350 | switch(pix_fmt) { | |
351 | case PIX_FMT_RGB24: | |
352 | case PIX_FMT_BGR24: | |
353 | bits = 24; | |
354 | break; | |
355 | case PIX_FMT_RGBA32: | |
356 | bits = 32; | |
357 | break; | |
358 | case PIX_FMT_RGB565: | |
359 | case PIX_FMT_RGB555: | |
360 | bits = 16; | |
361 | break; | |
362 | case PIX_FMT_PAL8: | |
363 | bits = 8; | |
364 | break; | |
365 | default: | |
366 | bits = 32; | |
367 | break; | |
368 | } | |
369 | } else { | |
370 | bits = pf->depth; | |
371 | bits += (2 * pf->depth >> | |
372 | (pf->x_chroma_shift + pf->x_chroma_shift)); | |
373 | } | |
374 | return bits; | |
375 | } | |
376 | ||
377 | static int avcodec_find_best_pix_fmt1(int pix_fmt_mask, | |
378 | int src_pix_fmt, | |
379 | int has_alpha, | |
380 | int loss_mask) | |
381 | { | |
382 | int dist, i, loss, min_dist, dst_pix_fmt; | |
383 | ||
384 | /* find exact color match with smallest size */ | |
385 | dst_pix_fmt = -1; | |
386 | min_dist = 0x7fffffff; | |
387 | for(i = 0;i < PIX_FMT_NB; i++) { | |
388 | if (pix_fmt_mask & (1 << i)) { | |
389 | loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask; | |
390 | if (loss == 0) { | |
391 | dist = avg_bits_per_pixel(i); | |
392 | if (dist < min_dist) { | |
393 | min_dist = dist; | |
394 | dst_pix_fmt = i; | |
395 | } | |
396 | } | |
397 | } | |
398 | } | |
399 | return dst_pix_fmt; | |
400 | } | |
401 | ||
402 | /** | |
403 | * find best pixel format to convert to. Return -1 if none found | |
404 | */ | |
405 | int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt, | |
406 | int has_alpha, int *loss_ptr) | |
407 | { | |
408 | int dst_pix_fmt, loss_mask, i; | |
409 | static const int loss_mask_order[] = { | |
410 | ~0, /* no loss first */ | |
411 | ~FF_LOSS_ALPHA, | |
412 | ~FF_LOSS_RESOLUTION, | |
413 | ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), | |
414 | ~FF_LOSS_COLORQUANT, | |
415 | ~FF_LOSS_DEPTH, | |
416 | 0, | |
417 | }; | |
418 | ||
419 | /* try with successive loss */ | |
420 | i = 0; | |
421 | for(;;) { | |
422 | loss_mask = loss_mask_order[i++]; | |
423 | dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt, | |
424 | has_alpha, loss_mask); | |
425 | if (dst_pix_fmt >= 0) | |
426 | goto found; | |
427 | if (loss_mask == 0) | |
428 | break; | |
429 | } | |
430 | return -1; | |
431 | found: | |
432 | if (loss_ptr) | |
433 | *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); | |
434 | return dst_pix_fmt; | |
435 | } | |
436 | ||
2a877875 | 437 | |
de6d9b64 FB |
438 | /* XXX: totally non optimized */ |
439 | ||
524c6b63 FB |
440 | static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src, |
441 | int width, int height) | |
de6d9b64 | 442 | { |
c50c0bc8 FB |
443 | const uint8_t *p, *p1; |
444 | uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; | |
445 | int x; | |
524c6b63 | 446 | |
c50c0bc8 FB |
447 | p1 = src->data[0]; |
448 | lum1 = dst->data[0]; | |
449 | cb1 = dst->data[0]; | |
450 | cr1 = dst->data[0]; | |
451 | ||
452 | for(;height >= 2; height -= 2) { | |
453 | p = p1; | |
454 | lum = lum1; | |
455 | cb = cb1; | |
456 | cr = cr1; | |
de6d9b64 | 457 | for(x=0;x<width;x+=2) { |
e78df699 MN |
458 | lum[0] = p[0]; |
459 | cb[0] = p[1]; | |
460 | lum[1] = p[2]; | |
461 | cr[0] = p[3]; | |
de6d9b64 FB |
462 | p += 4; |
463 | lum += 2; | |
464 | cb++; | |
465 | cr++; | |
466 | } | |
c50c0bc8 FB |
467 | p1 += src->linesize[0]; |
468 | lum1 += dst->linesize[0]; | |
469 | p = p1; | |
470 | lum = lum1; | |
de6d9b64 | 471 | for(x=0;x<width;x+=2) { |
e78df699 MN |
472 | lum[0] = p[0]; |
473 | lum[1] = p[2]; | |
de6d9b64 FB |
474 | p += 4; |
475 | lum += 2; | |
476 | } | |
c50c0bc8 FB |
477 | p1 += src->linesize[0]; |
478 | lum1 += dst->linesize[0]; | |
479 | cb1 += dst->linesize[1]; | |
480 | cr1 += dst->linesize[2]; | |
481 | } | |
482 | } | |
483 | ||
484 | static void yuv422_to_yuv422p(AVPicture *dst, AVPicture *src, | |
485 | int width, int height) | |
486 | { | |
487 | const uint8_t *p, *p1; | |
488 | uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; | |
489 | int w; | |
490 | ||
491 | p1 = src->data[0]; | |
492 | lum1 = dst->data[0]; | |
493 | cb1 = dst->data[0]; | |
494 | cr1 = dst->data[0]; | |
495 | for(;height >= 2; height -= 2) { | |
496 | p = p1; | |
497 | lum = lum1; | |
498 | cb = cb1; | |
499 | cr = cr1; | |
500 | for(w = width; w >= 2; w -= 2) { | |
501 | lum[0] = p[0]; | |
502 | cb[0] = p[1]; | |
503 | lum[1] = p[2]; | |
504 | cr[0] = p[3]; | |
505 | p += 4; | |
506 | lum += 2; | |
507 | cb++; | |
508 | cr++; | |
509 | } | |
510 | p1 += src->linesize[0]; | |
511 | lum1 += dst->linesize[0]; | |
512 | cb1 += dst->linesize[1]; | |
513 | cr1 += dst->linesize[2]; | |
de6d9b64 FB |
514 | } |
515 | } | |
516 | ||
c50c0bc8 FB |
517 | static void yuv422p_to_yuv422(AVPicture *dst, AVPicture *src, |
518 | int width, int height) | |
519 | { | |
520 | uint8_t *p, *p1; | |
521 | const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; | |
522 | int w; | |
523 | ||
524 | p1 = dst->data[0]; | |
525 | lum1 = src->data[0]; | |
526 | cb1 = src->data[0]; | |
527 | cr1 = src->data[0]; | |
528 | for(;height >= 2; height -= 2) { | |
529 | p = p1; | |
530 | lum = lum1; | |
531 | cb = cb1; | |
532 | cr = cr1; | |
533 | for(w = width; w >= 2; w -= 2) { | |
534 | p[0] = lum[0]; | |
535 | p[1] = cb[0]; | |
536 | p[2] = lum[1]; | |
537 | p[3] = cr[0]; | |
538 | p += 4; | |
539 | lum += 2; | |
540 | cb++; | |
541 | cr++; | |
542 | } | |
543 | p1 += src->linesize[0]; | |
544 | lum1 += dst->linesize[0]; | |
545 | cb1 += dst->linesize[1]; | |
546 | cr1 += dst->linesize[2]; | |
547 | } | |
548 | } | |
549 | ||
550 | #define SCALEBITS 10 | |
de6d9b64 | 551 | #define ONE_HALF (1 << (SCALEBITS - 1)) |
c50c0bc8 | 552 | #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) |
de6d9b64 | 553 | |
c50c0bc8 FB |
554 | #define YUV_TO_RGB1_CCIR(cb1, cr1)\ |
555 | {\ | |
556 | cb = (cb1) - 128;\ | |
557 | cr = (cr1) - 128;\ | |
558 | r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\ | |
559 | g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \ | |
560 | ONE_HALF;\ | |
561 | b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\ | |
562 | } | |
b6147995 | 563 | |
c50c0bc8 FB |
564 | #define YUV_TO_RGB2_CCIR(r, g, b, y1)\ |
565 | {\ | |
566 | y = ((y1) - 16) * FIX(255.0/219.0);\ | |
567 | r = cm[(y + r_add) >> SCALEBITS];\ | |
568 | g = cm[(y + g_add) >> SCALEBITS];\ | |
569 | b = cm[(y + b_add) >> SCALEBITS];\ | |
570 | } | |
571 | ||
572 | #define YUV_TO_RGB1(cb1, cr1)\ | |
573 | {\ | |
574 | cb = (cb1) - 128;\ | |
575 | cr = (cr1) - 128;\ | |
576 | r_add = FIX(1.40200) * cr + ONE_HALF;\ | |
577 | g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ | |
578 | b_add = FIX(1.77200) * cb + ONE_HALF;\ | |
579 | } | |
b6147995 FB |
580 | |
581 | #define YUV_TO_RGB2(r, g, b, y1)\ | |
582 | {\ | |
c50c0bc8 FB |
583 | y = (y1) << SCALEBITS;\ |
584 | r = cm[(y + r_add) >> SCALEBITS];\ | |
585 | g = cm[(y + g_add) >> SCALEBITS];\ | |
586 | b = cm[(y + b_add) >> SCALEBITS];\ | |
b6147995 FB |
587 | } |
588 | ||
c50c0bc8 | 589 | #define Y_CCIR_TO_JPEG(y)\ |
b6147995 FB |
590 | cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] |
591 | ||
c50c0bc8 | 592 | #define Y_JPEG_TO_CCIR(y)\ |
b6147995 FB |
593 | (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) |
594 | ||
c50c0bc8 FB |
595 | #define C_CCIR_TO_JPEG(y)\ |
596 | cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] | |
597 | ||
598 | /* NOTE: the clamp is really necessary! */ | |
599 | #define C_JPEG_TO_CCIR(y)\ | |
600 | ({\ | |
601 | int __y;\ | |
602 | __y = ((((y) - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);\ | |
603 | if (__y < 16)\ | |
604 | __y = 16;\ | |
605 | __y;\ | |
606 | }) | |
607 | ||
b6147995 FB |
608 | #define RGB_TO_Y(r, g, b) \ |
609 | ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ | |
610 | FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) | |
611 | ||
c50c0bc8 | 612 | #define RGB_TO_U(r1, g1, b1, shift)\ |
b6147995 | 613 | (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ |
c50c0bc8 | 614 | FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
b6147995 | 615 | |
c50c0bc8 | 616 | #define RGB_TO_V(r1, g1, b1, shift)\ |
b6147995 | 617 | (((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ |
c50c0bc8 | 618 | FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
b6147995 FB |
619 | |
620 | #define RGB_TO_Y_CCIR(r, g, b) \ | |
621 | ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ | |
622 | FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) | |
623 | ||
c50c0bc8 | 624 | #define RGB_TO_U_CCIR(r1, g1, b1, shift)\ |
b6147995 | 625 | (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ |
c50c0bc8 | 626 | FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
b6147995 | 627 | |
c50c0bc8 | 628 | #define RGB_TO_V_CCIR(r1, g1, b1, shift)\ |
b6147995 | 629 | (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ |
c50c0bc8 | 630 | FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
b6147995 | 631 | |
c50c0bc8 FB |
632 | static uint8_t y_ccir_to_jpeg[256]; |
633 | static uint8_t y_jpeg_to_ccir[256]; | |
634 | static uint8_t c_ccir_to_jpeg[256]; | |
635 | static uint8_t c_jpeg_to_ccir[256]; | |
636 | ||
637 | /* init various conversion tables */ | |
638 | static void img_convert_init(void) | |
b6147995 | 639 | { |
c50c0bc8 | 640 | int i; |
b6147995 FB |
641 | uint8_t *cm = cropTbl + MAX_NEG_CROP; |
642 | ||
c50c0bc8 FB |
643 | for(i = 0;i < 256; i++) { |
644 | y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i); | |
645 | y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i); | |
646 | c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i); | |
647 | c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i); | |
b6147995 FB |
648 | } |
649 | } | |
650 | ||
c50c0bc8 FB |
651 | /* apply to each pixel the given table */ |
652 | static void img_apply_table(uint8_t *dst, int dst_wrap, | |
653 | const uint8_t *src, int src_wrap, | |
654 | int width, int height, const uint8_t *table1) | |
b6147995 FB |
655 | { |
656 | int n; | |
657 | const uint8_t *s; | |
658 | uint8_t *d; | |
c50c0bc8 | 659 | const uint8_t *table; |
b6147995 | 660 | |
c50c0bc8 | 661 | table = table1; |
b6147995 FB |
662 | for(;height > 0; height--) { |
663 | s = src; | |
664 | d = dst; | |
665 | n = width; | |
666 | while (n >= 4) { | |
c50c0bc8 FB |
667 | d[0] = table[s[0]]; |
668 | d[1] = table[s[1]]; | |
669 | d[2] = table[s[2]]; | |
670 | d[3] = table[s[3]]; | |
b6147995 FB |
671 | d += 4; |
672 | s += 4; | |
673 | n -= 4; | |
674 | } | |
675 | while (n > 0) { | |
c50c0bc8 | 676 | d[0] = table[s[0]]; |
b6147995 FB |
677 | d++; |
678 | s++; | |
679 | n--; | |
680 | } | |
681 | dst += dst_wrap; | |
682 | src += src_wrap; | |
683 | } | |
684 | } | |
685 | ||
85c242d8 FB |
686 | /* XXX: use generic filter ? */ |
687 | /* 1x2 -> 1x1 */ | |
0c1a9eda ZK |
688 | static void shrink2(uint8_t *dst, int dst_wrap, |
689 | uint8_t *src, int src_wrap, | |
85c242d8 FB |
690 | int width, int height) |
691 | { | |
692 | int w; | |
0c1a9eda | 693 | uint8_t *s1, *s2, *d; |
85c242d8 FB |
694 | |
695 | for(;height > 0; height--) { | |
696 | s1 = src; | |
697 | s2 = s1 + src_wrap; | |
698 | d = dst; | |
699 | for(w = width;w >= 4; w-=4) { | |
700 | d[0] = (s1[0] + s2[0]) >> 1; | |
701 | d[1] = (s1[1] + s2[1]) >> 1; | |
702 | d[2] = (s1[2] + s2[2]) >> 1; | |
703 | d[3] = (s1[3] + s2[3]) >> 1; | |
704 | s1 += 4; | |
705 | s2 += 4; | |
706 | d += 4; | |
707 | } | |
708 | for(;w > 0; w--) { | |
709 | d[0] = (s1[0] + s2[0]) >> 1; | |
710 | s1++; | |
711 | s2++; | |
712 | d++; | |
713 | } | |
714 | src += 2 * src_wrap; | |
715 | dst += dst_wrap; | |
716 | } | |
717 | } | |
718 | ||
719 | /* 2x2 -> 1x1 */ | |
0c1a9eda ZK |
720 | static void shrink22(uint8_t *dst, int dst_wrap, |
721 | uint8_t *src, int src_wrap, | |
85c242d8 FB |
722 | int width, int height) |
723 | { | |
724 | int w; | |
0c1a9eda | 725 | uint8_t *s1, *s2, *d; |
85c242d8 FB |
726 | |
727 | for(;height > 0; height--) { | |
728 | s1 = src; | |
729 | s2 = s1 + src_wrap; | |
730 | d = dst; | |
731 | for(w = width;w >= 4; w-=4) { | |
732 | d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1; | |
733 | d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1; | |
734 | d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1; | |
735 | d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1; | |
736 | s1 += 8; | |
737 | s2 += 8; | |
738 | d += 4; | |
739 | } | |
740 | for(;w > 0; w--) { | |
741 | d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1; | |
742 | s1 += 2; | |
743 | s2 += 2; | |
744 | d++; | |
745 | } | |
746 | src += 2 * src_wrap; | |
747 | dst += dst_wrap; | |
748 | } | |
749 | } | |
750 | ||
6742d95d | 751 | /* 1x1 -> 2x2 */ |
0c1a9eda ZK |
752 | static void grow22(uint8_t *dst, int dst_wrap, |
753 | uint8_t *src, int src_wrap, | |
6742d95d FR |
754 | int width, int height) |
755 | { | |
756 | int w; | |
0c1a9eda | 757 | uint8_t *s1, *d; |
6742d95d FR |
758 | |
759 | for(;height > 0; height--) { | |
760 | s1 = src; | |
761 | d = dst; | |
762 | for(w = width;w >= 4; w-=4) { | |
763 | d[1] = d[0] = s1[0]; | |
764 | d[3] = d[2] = s1[1]; | |
765 | s1 += 2; | |
766 | d += 4; | |
767 | } | |
768 | for(;w > 0; w--) { | |
769 | d[0] = s1[0]; | |
770 | s1 ++; | |
771 | d++; | |
772 | } | |
773 | if (height%2) | |
774 | src += src_wrap; | |
775 | dst += dst_wrap; | |
776 | } | |
777 | } | |
778 | ||
524c6b63 | 779 | /* 1x2 -> 2x1 */ |
0c1a9eda ZK |
780 | static void conv411(uint8_t *dst, int dst_wrap, |
781 | uint8_t *src, int src_wrap, | |
789587d5 FB |
782 | int width, int height) |
783 | { | |
784 | int w, c; | |
0c1a9eda | 785 | uint8_t *s1, *s2, *d; |
789587d5 | 786 | |
50643575 MN |
787 | width>>=1; |
788 | ||
524c6b63 | 789 | for(;height > 0; height--) { |
789587d5 FB |
790 | s1 = src; |
791 | s2 = src + src_wrap; | |
792 | d = dst; | |
793 | for(w = width;w > 0; w--) { | |
794 | c = (s1[0] + s2[0]) >> 1; | |
795 | d[0] = c; | |
796 | d[1] = c; | |
797 | s1++; | |
798 | s2++; | |
799 | d += 2; | |
800 | } | |
801 | src += src_wrap * 2; | |
802 | dst += dst_wrap; | |
803 | } | |
804 | } | |
805 | ||
0c1a9eda ZK |
806 | static void img_copy(uint8_t *dst, int dst_wrap, |
807 | uint8_t *src, int src_wrap, | |
85c242d8 FB |
808 | int width, int height) |
809 | { | |
810 | for(;height > 0; height--) { | |
811 | memcpy(dst, src, width); | |
812 | dst += dst_wrap; | |
813 | src += src_wrap; | |
814 | } | |
815 | } | |
816 | ||
85c242d8 | 817 | /* XXX: no chroma interpolating is done */ |
524c6b63 FB |
818 | #define RGB_FUNCTIONS(rgb_name) \ |
819 | \ | |
820 | static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \ | |
821 | int width, int height) \ | |
822 | { \ | |
0c1a9eda | 823 | uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \ |
524c6b63 | 824 | int w, y, cb, cr, r_add, g_add, b_add, width2; \ |
0c1a9eda | 825 | uint8_t *cm = cropTbl + MAX_NEG_CROP; \ |
524c6b63 FB |
826 | unsigned int r, g, b; \ |
827 | \ | |
828 | d = dst->data[0]; \ | |
829 | y1_ptr = src->data[0]; \ | |
830 | cb_ptr = src->data[1]; \ | |
831 | cr_ptr = src->data[2]; \ | |
4c7e8619 FB |
832 | width2 = (width + 1) >> 1; \ |
833 | for(;height >= 2; height -= 2) { \ | |
524c6b63 FB |
834 | d1 = d; \ |
835 | d2 = d + dst->linesize[0]; \ | |
836 | y2_ptr = y1_ptr + src->linesize[0]; \ | |
4c7e8619 | 837 | for(w = width; w >= 2; w -= 2) { \ |
c50c0bc8 | 838 | YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); \ |
524c6b63 | 839 | /* output 4 pixels */ \ |
c50c0bc8 | 840 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); \ |
524c6b63 FB |
841 | RGB_OUT(d1, r, g, b); \ |
842 | \ | |
c50c0bc8 | 843 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]); \ |
524c6b63 FB |
844 | RGB_OUT(d1 + BPP, r, g, b); \ |
845 | \ | |
c50c0bc8 | 846 | YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]); \ |
524c6b63 FB |
847 | RGB_OUT(d2, r, g, b); \ |
848 | \ | |
c50c0bc8 | 849 | YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]); \ |
524c6b63 FB |
850 | RGB_OUT(d2 + BPP, r, g, b); \ |
851 | \ | |
852 | d1 += 2 * BPP; \ | |
853 | d2 += 2 * BPP; \ | |
854 | \ | |
855 | y1_ptr += 2; \ | |
856 | y2_ptr += 2; \ | |
857 | cb_ptr++; \ | |
858 | cr_ptr++; \ | |
859 | } \ | |
4c7e8619 FB |
860 | /* handle odd width */ \ |
861 | if (w) { \ | |
c50c0bc8 FB |
862 | YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); \ |
863 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); \ | |
4c7e8619 FB |
864 | RGB_OUT(d1, r, g, b); \ |
865 | \ | |
c50c0bc8 | 866 | YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]); \ |
4c7e8619 FB |
867 | RGB_OUT(d2, r, g, b); \ |
868 | d1 += BPP; \ | |
869 | d2 += BPP; \ | |
870 | y1_ptr++; \ | |
871 | y2_ptr++; \ | |
872 | cb_ptr++; \ | |
873 | cr_ptr++; \ | |
874 | } \ | |
524c6b63 FB |
875 | d += 2 * dst->linesize[0]; \ |
876 | y1_ptr += 2 * src->linesize[0] - width; \ | |
877 | cb_ptr += src->linesize[1] - width2; \ | |
878 | cr_ptr += src->linesize[2] - width2; \ | |
879 | } \ | |
4c7e8619 FB |
880 | /* handle odd height */ \ |
881 | if (height) { \ | |
882 | d1 = d; \ | |
883 | for(w = width; w >= 2; w -= 2) { \ | |
c50c0bc8 | 884 | YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); \ |
4c7e8619 | 885 | /* output 2 pixels */ \ |
c50c0bc8 | 886 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); \ |
4c7e8619 FB |
887 | RGB_OUT(d1, r, g, b); \ |
888 | \ | |
c50c0bc8 | 889 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]); \ |
4c7e8619 FB |
890 | RGB_OUT(d1 + BPP, r, g, b); \ |
891 | \ | |
892 | d1 += 2 * BPP; \ | |
893 | \ | |
894 | y1_ptr += 2; \ | |
895 | cb_ptr++; \ | |
896 | cr_ptr++; \ | |
897 | } \ | |
898 | /* handle width */ \ | |
899 | if (w) { \ | |
c50c0bc8 | 900 | YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); \ |
4c7e8619 | 901 | /* output 2 pixels */ \ |
c50c0bc8 | 902 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); \ |
4c7e8619 FB |
903 | RGB_OUT(d1, r, g, b); \ |
904 | d1 += BPP; \ | |
905 | \ | |
906 | y1_ptr++; \ | |
907 | cb_ptr++; \ | |
908 | cr_ptr++; \ | |
909 | } \ | |
910 | } \ | |
524c6b63 FB |
911 | } \ |
912 | \ | |
c50c0bc8 FB |
913 | static void yuvj420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \ |
914 | int width, int height) \ | |
524c6b63 | 915 | { \ |
c50c0bc8 | 916 | uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \ |
524c6b63 | 917 | int w, y, cb, cr, r_add, g_add, b_add, width2; \ |
0c1a9eda | 918 | uint8_t *cm = cropTbl + MAX_NEG_CROP; \ |
524c6b63 FB |
919 | unsigned int r, g, b; \ |
920 | \ | |
921 | d = dst->data[0]; \ | |
922 | y1_ptr = src->data[0]; \ | |
923 | cb_ptr = src->data[1]; \ | |
924 | cr_ptr = src->data[2]; \ | |
4c7e8619 | 925 | width2 = (width + 1) >> 1; \ |
c50c0bc8 | 926 | for(;height >= 2; height -= 2) { \ |
524c6b63 | 927 | d1 = d; \ |
c50c0bc8 FB |
928 | d2 = d + dst->linesize[0]; \ |
929 | y2_ptr = y1_ptr + src->linesize[0]; \ | |
4c7e8619 | 930 | for(w = width; w >= 2; w -= 2) { \ |
c50c0bc8 FB |
931 | YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); \ |
932 | /* output 4 pixels */ \ | |
933 | YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ | |
934 | RGB_OUT(d1, r, g, b); \ | |
935 | \ | |
936 | YUV_TO_RGB2(r, g, b, y1_ptr[1]); \ | |
937 | RGB_OUT(d1 + BPP, r, g, b); \ | |
938 | \ | |
939 | YUV_TO_RGB2(r, g, b, y2_ptr[0]); \ | |
940 | RGB_OUT(d2, r, g, b); \ | |
941 | \ | |
942 | YUV_TO_RGB2(r, g, b, y2_ptr[1]); \ | |
943 | RGB_OUT(d2 + BPP, r, g, b); \ | |
524c6b63 | 944 | \ |
c50c0bc8 FB |
945 | d1 += 2 * BPP; \ |
946 | d2 += 2 * BPP; \ | |
947 | \ | |
948 | y1_ptr += 2; \ | |
949 | y2_ptr += 2; \ | |
950 | cb_ptr++; \ | |
951 | cr_ptr++; \ | |
952 | } \ | |
953 | /* handle odd width */ \ | |
954 | if (w) { \ | |
955 | YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); \ | |
956 | YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ | |
957 | RGB_OUT(d1, r, g, b); \ | |
958 | \ | |
959 | YUV_TO_RGB2(r, g, b, y2_ptr[0]); \ | |
960 | RGB_OUT(d2, r, g, b); \ | |
961 | d1 += BPP; \ | |
962 | d2 += BPP; \ | |
963 | y1_ptr++; \ | |
964 | y2_ptr++; \ | |
965 | cb_ptr++; \ | |
966 | cr_ptr++; \ | |
967 | } \ | |
968 | d += 2 * dst->linesize[0]; \ | |
969 | y1_ptr += 2 * src->linesize[0] - width; \ | |
970 | cb_ptr += src->linesize[1] - width2; \ | |
971 | cr_ptr += src->linesize[2] - width2; \ | |
972 | } \ | |
973 | /* handle odd height */ \ | |
974 | if (height) { \ | |
975 | d1 = d; \ | |
976 | for(w = width; w >= 2; w -= 2) { \ | |
977 | YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); \ | |
524c6b63 | 978 | /* output 2 pixels */ \ |
c50c0bc8 | 979 | YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ |
4c7e8619 | 980 | RGB_OUT(d1, r, g, b); \ |
524c6b63 | 981 | \ |
c50c0bc8 | 982 | YUV_TO_RGB2(r, g, b, y1_ptr[1]); \ |
4c7e8619 | 983 | RGB_OUT(d1 + BPP, r, g, b); \ |
524c6b63 | 984 | \ |
4c7e8619 | 985 | d1 += 2 * BPP; \ |
524c6b63 FB |
986 | \ |
987 | y1_ptr += 2; \ | |
988 | cb_ptr++; \ | |
989 | cr_ptr++; \ | |
990 | } \ | |
4c7e8619 FB |
991 | /* handle width */ \ |
992 | if (w) { \ | |
c50c0bc8 | 993 | YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); \ |
4c7e8619 | 994 | /* output 2 pixels */ \ |
c50c0bc8 | 995 | YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ |
4c7e8619 FB |
996 | RGB_OUT(d1, r, g, b); \ |
997 | d1 += BPP; \ | |
998 | \ | |
999 | y1_ptr++; \ | |
1000 | cb_ptr++; \ | |
1001 | cr_ptr++; \ | |
1002 | } \ | |
524c6b63 FB |
1003 | } \ |
1004 | } \ | |
1005 | \ | |
1006 | static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \ | |
1007 | int width, int height) \ | |
1008 | { \ | |
c50c0bc8 FB |
1009 | int wrap, wrap3, width2; \ |
1010 | int r, g, b, r1, g1, b1, w; \ | |
0c1a9eda ZK |
1011 | uint8_t *lum, *cb, *cr; \ |
1012 | const uint8_t *p; \ | |
524c6b63 FB |
1013 | \ |
1014 | lum = dst->data[0]; \ | |
1015 | cb = dst->data[1]; \ | |
1016 | cr = dst->data[2]; \ | |
1017 | \ | |
c50c0bc8 | 1018 | width2 = (width + 1) >> 1; \ |
16e83cbb PG |
1019 | wrap = dst->linesize[0]; \ |
1020 | wrap3 = src->linesize[0]; \ | |
524c6b63 | 1021 | p = src->data[0]; \ |
c50c0bc8 FB |
1022 | for(;height>=2;height -= 2) { \ |
1023 | for(w = width; w >= 2; w -= 2) { \ | |
524c6b63 FB |
1024 | RGB_IN(r, g, b, p); \ |
1025 | r1 = r; \ | |
1026 | g1 = g; \ | |
1027 | b1 = b; \ | |
b6147995 FB |
1028 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ |
1029 | \ | |
524c6b63 FB |
1030 | RGB_IN(r, g, b, p + BPP); \ |
1031 | r1 += r; \ | |
1032 | g1 += g; \ | |
1033 | b1 += b; \ | |
b6147995 | 1034 | lum[1] = RGB_TO_Y_CCIR(r, g, b); \ |
524c6b63 FB |
1035 | p += wrap3; \ |
1036 | lum += wrap; \ | |
1037 | \ | |
1038 | RGB_IN(r, g, b, p); \ | |
1039 | r1 += r; \ | |
1040 | g1 += g; \ | |
1041 | b1 += b; \ | |
b6147995 FB |
1042 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ |
1043 | \ | |
524c6b63 FB |
1044 | RGB_IN(r, g, b, p + BPP); \ |
1045 | r1 += r; \ | |
1046 | g1 += g; \ | |
1047 | b1 += b; \ | |
b6147995 | 1048 | lum[1] = RGB_TO_Y_CCIR(r, g, b); \ |
524c6b63 | 1049 | \ |
c50c0bc8 FB |
1050 | cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 2); \ |
1051 | cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 2); \ | |
524c6b63 FB |
1052 | \ |
1053 | cb++; \ | |
1054 | cr++; \ | |
69572401 | 1055 | p += -wrap3 + 2 * BPP; \ |
524c6b63 FB |
1056 | lum += -wrap + 2; \ |
1057 | } \ | |
c50c0bc8 FB |
1058 | if (w) { \ |
1059 | RGB_IN(r, g, b, p); \ | |
1060 | r1 = r; \ | |
1061 | g1 = g; \ | |
1062 | b1 = b; \ | |
1063 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ | |
1064 | p += wrap3; \ | |
1065 | lum += wrap; \ | |
1066 | RGB_IN(r, g, b, p); \ | |
1067 | r1 += r; \ | |
1068 | g1 += g; \ | |
1069 | b1 += b; \ | |
1070 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ | |
1071 | cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1); \ | |
1072 | cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1); \ | |
1073 | cb++; \ | |
1074 | cr++; \ | |
1075 | p += -wrap3 + BPP; \ | |
1076 | lum += -wrap + 1; \ | |
1077 | } \ | |
16e83cbb PG |
1078 | p += wrap3 + (wrap3 - width * BPP); \ |
1079 | lum += wrap + (wrap - width); \ | |
c50c0bc8 FB |
1080 | cb += dst->linesize[1] - width2; \ |
1081 | cr += dst->linesize[2] - width2; \ | |
1082 | } \ | |
1083 | /* handle odd height */ \ | |
1084 | if (height) { \ | |
1085 | for(w = width; w >= 2; w -= 2) { \ | |
1086 | RGB_IN(r, g, b, p); \ | |
1087 | r1 = r; \ | |
1088 | g1 = g; \ | |
1089 | b1 = b; \ | |
1090 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ | |
1091 | \ | |
1092 | RGB_IN(r, g, b, p + BPP); \ | |
1093 | r1 += r; \ | |
1094 | g1 += g; \ | |
1095 | b1 += b; \ | |
1096 | lum[1] = RGB_TO_Y_CCIR(r, g, b); \ | |
1097 | cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1); \ | |
1098 | cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1); \ | |
1099 | cb++; \ | |
1100 | cr++; \ | |
1101 | p += 2 * BPP;\ | |
1102 | lum += 2;\ | |
1103 | } \ | |
1104 | if (w) { \ | |
1105 | RGB_IN(r, g, b, p); \ | |
1106 | lum[0] = RGB_TO_Y_CCIR(r, g, b); \ | |
1107 | cb[0] = RGB_TO_U_CCIR(r, g, b, 0); \ | |
1108 | cr[0] = RGB_TO_V_CCIR(r, g, b, 0); \ | |
1109 | } \ | |
524c6b63 | 1110 | } \ |
69572401 FB |
1111 | } \ |
1112 | \ | |
1113 | static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src, \ | |
1114 | int width, int height) \ | |
1115 | { \ | |
1116 | const unsigned char *p; \ | |
1117 | unsigned char *q; \ | |
1118 | int r, g, b, dst_wrap, src_wrap; \ | |
1119 | int x, y; \ | |
1120 | \ | |
1121 | p = src->data[0]; \ | |
1122 | src_wrap = src->linesize[0] - BPP * width; \ | |
1123 | \ | |
1124 | q = dst->data[0]; \ | |
1125 | dst_wrap = dst->linesize[0] - width; \ | |
1126 | \ | |
1127 | for(y=0;y<height;y++) { \ | |
1128 | for(x=0;x<width;x++) { \ | |
1129 | RGB_IN(r, g, b, p); \ | |
b6147995 | 1130 | q[0] = RGB_TO_Y(r, g, b); \ |
69572401 FB |
1131 | q++; \ |
1132 | p += BPP; \ | |
1133 | } \ | |
1134 | p += src_wrap; \ | |
1135 | q += dst_wrap; \ | |
1136 | } \ | |
1137 | } \ | |
1138 | \ | |
1139 | static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \ | |
1140 | int width, int height) \ | |
1141 | { \ | |
1142 | const unsigned char *p; \ | |
1143 | unsigned char *q; \ | |
1144 | int r, dst_wrap, src_wrap; \ | |
1145 | int x, y; \ | |
1146 | \ | |
1147 | p = src->data[0]; \ | |
1148 | src_wrap = src->linesize[0] - width; \ | |
1149 | \ | |
1150 | q = dst->data[0]; \ | |
1151 | dst_wrap = dst->linesize[0] - BPP * width; \ | |
1152 | \ | |
1153 | for(y=0;y<height;y++) { \ | |
1154 | for(x=0;x<width;x++) { \ | |
1155 | r = p[0]; \ | |
1156 | RGB_OUT(q, r, r, r); \ | |
1157 | q += BPP; \ | |
1158 | p ++; \ | |
1159 | } \ | |
1160 | p += src_wrap; \ | |
1161 | q += dst_wrap; \ | |
1162 | } \ | |
7e6d70d0 FB |
1163 | } \ |
1164 | \ | |
1165 | static void pal8_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \ | |
1166 | int width, int height) \ | |
1167 | { \ | |
1168 | const unsigned char *p; \ | |
1169 | unsigned char *q; \ | |
1170 | int r, g, b, dst_wrap, src_wrap; \ | |
1171 | int x, y; \ | |
1172 | uint32_t v;\ | |
1173 | const uint32_t *palette;\ | |
1174 | \ | |
1175 | p = src->data[0]; \ | |
1176 | src_wrap = src->linesize[0] - width; \ | |
1177 | palette = (uint32_t *)src->data[1];\ | |
1178 | \ | |
1179 | q = dst->data[0]; \ | |
1180 | dst_wrap = dst->linesize[0] - BPP * width; \ | |
1181 | \ | |
1182 | for(y=0;y<height;y++) { \ | |
1183 | for(x=0;x<width;x++) { \ | |
1184 | v = palette[p[0]];\ | |
1185 | r = (v >> 16) & 0xff;\ | |
1186 | g = (v >> 8) & 0xff;\ | |
1187 | b = (v) & 0xff;\ | |
1188 | RGB_OUT(q, r, g, b); \ | |
1189 | q += BPP; \ | |
1190 | p ++; \ | |
1191 | } \ | |
1192 | p += src_wrap; \ | |
1193 | q += dst_wrap; \ | |
1194 | } \ | |
524c6b63 FB |
1195 | } |
1196 | ||
1197 | /* copy bit n to bits 0 ... n - 1 */ | |
1198 | static inline unsigned int bitcopy_n(unsigned int a, int n) | |
b71472eb | 1199 | { |
524c6b63 FB |
1200 | int mask; |
1201 | mask = (1 << n) - 1; | |
1202 | return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask); | |
1203 | } | |
1204 | ||
1205 | /* rgb555 handling */ | |
1206 | ||
1207 | #define RGB_IN(r, g, b, s)\ | |
1208 | {\ | |
0c1a9eda | 1209 | unsigned int v = ((const uint16_t *)(s))[0];\ |
524c6b63 FB |
1210 | r = bitcopy_n(v >> (10 - 3), 3);\ |
1211 | g = bitcopy_n(v >> (5 - 3), 3);\ | |
1212 | b = bitcopy_n(v << 3, 3);\ | |
1213 | } | |
1214 | ||
1215 | #define RGB_OUT(d, r, g, b)\ | |
1216 | {\ | |
0c1a9eda | 1217 | ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\ |
524c6b63 FB |
1218 | } |
1219 | ||
1220 | #define BPP 2 | |
1221 | ||
1222 | RGB_FUNCTIONS(rgb555) | |
1223 | ||
1224 | #undef RGB_IN | |
1225 | #undef RGB_OUT | |
1226 | #undef BPP | |
1227 | ||
1228 | /* rgb565 handling */ | |
1229 | ||
1230 | #define RGB_IN(r, g, b, s)\ | |
1231 | {\ | |
0c1a9eda | 1232 | unsigned int v = ((const uint16_t *)(s))[0];\ |
524c6b63 FB |
1233 | r = bitcopy_n(v >> (11 - 3), 3);\ |
1234 | g = bitcopy_n(v >> (5 - 2), 2);\ | |
1235 | b = bitcopy_n(v << 3, 3);\ | |
1236 | } | |
1237 | ||
1238 | #define RGB_OUT(d, r, g, b)\ | |
1239 | {\ | |
0c1a9eda | 1240 | ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ |
524c6b63 FB |
1241 | } |
1242 | ||
1243 | #define BPP 2 | |
1244 | ||
1245 | RGB_FUNCTIONS(rgb565) | |
1246 | ||
1247 | #undef RGB_IN | |
1248 | #undef RGB_OUT | |
1249 | #undef BPP | |
1250 | ||
1251 | /* bgr24 handling */ | |
1252 | ||
1253 | #define RGB_IN(r, g, b, s)\ | |
1254 | {\ | |
1255 | b = (s)[0];\ | |
1256 | g = (s)[1];\ | |
1257 | r = (s)[2];\ | |
1258 | } | |
1259 | ||
1260 | #define RGB_OUT(d, r, g, b)\ | |
1261 | {\ | |
1262 | (d)[0] = b;\ | |
1263 | (d)[1] = g;\ | |
1264 | (d)[2] = r;\ | |
1265 | } | |
1266 | ||
1267 | #define BPP 3 | |
1268 | ||
1269 | RGB_FUNCTIONS(bgr24) | |
1270 | ||
1271 | #undef RGB_IN | |
1272 | #undef RGB_OUT | |
1273 | #undef BPP | |
1274 | ||
1275 | /* rgb24 handling */ | |
1276 | ||
1277 | #define RGB_IN(r, g, b, s)\ | |
1278 | {\ | |
1279 | r = (s)[0];\ | |
1280 | g = (s)[1];\ | |
1281 | b = (s)[2];\ | |
1282 | } | |
1283 | ||
1284 | #define RGB_OUT(d, r, g, b)\ | |
1285 | {\ | |
1286 | (d)[0] = r;\ | |
1287 | (d)[1] = g;\ | |
1288 | (d)[2] = b;\ | |
1289 | } | |
1290 | ||
1291 | #define BPP 3 | |
1292 | ||
1293 | RGB_FUNCTIONS(rgb24) | |
1294 | ||
c50c0bc8 FB |
1295 | static void yuv444p_to_rgb24(AVPicture *dst, AVPicture *src, |
1296 | int width, int height) | |
1297 | { | |
1298 | uint8_t *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; | |
1299 | int w, y, cb, cr, r_add, g_add, b_add; | |
1300 | uint8_t *cm = cropTbl + MAX_NEG_CROP; | |
1301 | unsigned int r, g, b; | |
1302 | ||
1303 | d = dst->data[0]; | |
1304 | y1_ptr = src->data[0]; | |
1305 | cb_ptr = src->data[1]; | |
1306 | cr_ptr = src->data[2]; | |
1307 | for(;height > 0; height --) { | |
1308 | d1 = d; | |
1309 | for(w = width; w > 0; w--) { | |
1310 | YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); | |
1311 | ||
1312 | YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); | |
1313 | RGB_OUT(d1, r, g, b); | |
1314 | d1 += BPP; | |
1315 | ||
1316 | y1_ptr++; | |
1317 | cb_ptr++; | |
1318 | cr_ptr++; | |
1319 | } | |
1320 | d += dst->linesize[0]; | |
1321 | y1_ptr += src->linesize[0] - width; | |
1322 | cb_ptr += src->linesize[1] - width; | |
1323 | cr_ptr += src->linesize[2] - width; | |
1324 | } | |
1325 | } | |
1326 | ||
1327 | static void yuvj444p_to_rgb24(AVPicture *dst, AVPicture *src, | |
1328 | int width, int height) | |
1329 | { | |
1330 | uint8_t *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; | |
1331 | int w, y, cb, cr, r_add, g_add, b_add; | |
1332 | uint8_t *cm = cropTbl + MAX_NEG_CROP; | |
1333 | unsigned int r, g, b; | |
1334 | ||
1335 | d = dst->data[0]; | |
1336 | y1_ptr = src->data[0]; | |
1337 | cb_ptr = src->data[1]; | |
1338 | cr_ptr = src->data[2]; | |
1339 | for(;height > 0; height --) { | |
1340 | d1 = d; | |
1341 | for(w = width; w > 0; w--) { | |
1342 | YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); | |
1343 | ||
1344 | YUV_TO_RGB2(r, g, b, y1_ptr[0]); | |
1345 | RGB_OUT(d1, r, g, b); | |
1346 | d1 += BPP; | |
1347 | ||
1348 | y1_ptr++; | |
1349 | cb_ptr++; | |
1350 | cr_ptr++; | |
1351 | } | |
1352 | d += dst->linesize[0]; | |
1353 | y1_ptr += src->linesize[0] - width; | |
1354 | cb_ptr += src->linesize[1] - width; | |
1355 | cr_ptr += src->linesize[2] - width; | |
1356 | } | |
1357 | } | |
1358 | ||
1359 | static void rgb24_to_yuv444p(AVPicture *dst, AVPicture *src, | |
1360 | int width, int height) | |
1361 | { | |
1362 | int src_wrap, x, y; | |
1363 | int r, g, b; | |
1364 | uint8_t *lum, *cb, *cr; | |
1365 | const uint8_t *p; | |
1366 | ||
1367 | lum = dst->data[0]; | |
1368 | cb = dst->data[1]; | |
1369 | cr = dst->data[2]; | |
1370 | ||
1371 | src_wrap = src->linesize[0] - width * BPP; | |
1372 | p = src->data[0]; | |
1373 | for(y=0;y<height;y++) { | |
1374 | for(x=0;x<width;x++) { | |
1375 | RGB_IN(r, g, b, p); | |
1376 | lum[0] = RGB_TO_Y_CCIR(r, g, b); | |
1377 | cb[0] = RGB_TO_U_CCIR(r, g, b, 0); | |
1378 | cr[0] = RGB_TO_V_CCIR(r, g, b, 0); | |
1379 | cb++; | |
1380 | cr++; | |
1381 | lum++; | |
1382 | } | |
1383 | p += src_wrap; | |
1384 | lum += dst->linesize[0] - width; | |
1385 | cb += dst->linesize[1] - width; | |
1386 | cr += dst->linesize[2] - width; | |
1387 | } | |
1388 | } | |
1389 | ||
1390 | static void rgb24_to_yuvj420p(AVPicture *dst, AVPicture *src, | |
1391 | int width, int height) | |
1392 | { | |
1393 | int wrap, wrap3, width2; | |
1394 | int r, g, b, r1, g1, b1, w; | |
1395 | uint8_t *lum, *cb, *cr; | |
1396 | const uint8_t *p; | |
1397 | ||
1398 | lum = dst->data[0]; | |
1399 | cb = dst->data[1]; | |
1400 | cr = dst->data[2]; | |
1401 | ||
1402 | width2 = (width + 1) >> 1; | |
1403 | wrap = dst->linesize[0]; | |
1404 | wrap3 = src->linesize[0]; | |
1405 | p = src->data[0]; | |
1406 | for(;height>=2;height -= 2) { | |
1407 | for(w = width; w >= 2; w -= 2) { | |
1408 | RGB_IN(r, g, b, p); | |
1409 | r1 = r; | |
1410 | g1 = g; | |
1411 | b1 = b; | |
1412 | lum[0] = RGB_TO_Y(r, g, b); | |
1413 | ||
1414 | RGB_IN(r, g, b, p + BPP); | |
1415 | r1 += r; | |
1416 | g1 += g; | |
1417 | b1 += b; | |
1418 | lum[1] = RGB_TO_Y(r, g, b); | |
1419 | p += wrap3; | |
1420 | lum += wrap; | |
1421 | ||
1422 | RGB_IN(r, g, b, p); | |
1423 | r1 += r; | |
1424 | g1 += g; | |
1425 | b1 += b; | |
1426 | lum[0] = RGB_TO_Y(r, g, b); | |
1427 | ||
1428 | RGB_IN(r, g, b, p + BPP); | |
1429 | r1 += r; | |
1430 | g1 += g; | |
1431 | b1 += b; | |
1432 | lum[1] = RGB_TO_Y(r, g, b); | |
1433 | ||
1434 | cb[0] = RGB_TO_U(r1, g1, b1, 2); | |
1435 | cr[0] = RGB_TO_V(r1, g1, b1, 2); | |
1436 | ||
1437 | cb++; | |
1438 | cr++; | |
1439 | p += -wrap3 + 2 * BPP; | |
1440 | lum += -wrap + 2; | |
1441 | } | |
1442 | if (w) { | |
1443 | RGB_IN(r, g, b, p); | |
1444 | r1 = r; | |
1445 | g1 = g; | |
1446 | b1 = b; | |
1447 | lum[0] = RGB_TO_Y(r, g, b); | |
1448 | p += wrap3; | |
1449 | lum += wrap; | |
1450 | RGB_IN(r, g, b, p); | |
1451 | r1 += r; | |
1452 | g1 += g; | |
1453 | b1 += b; | |
1454 | lum[0] = RGB_TO_Y(r, g, b); | |
1455 | cb[0] = RGB_TO_U(r1, g1, b1, 1); | |
1456 | cr[0] = RGB_TO_V(r1, g1, b1, 1); | |
1457 | cb++; | |
1458 | cr++; | |
1459 | p += -wrap3 + BPP; | |
1460 | lum += -wrap + 1; | |
1461 | } | |
1462 | p += wrap3 + (wrap3 - width * BPP); | |
1463 | lum += wrap + (wrap - width); | |
1464 | cb += dst->linesize[1] - width2; | |
1465 | cr += dst->linesize[2] - width2; | |
1466 | } | |
1467 | /* handle odd height */ | |
1468 | if (height) { | |
1469 | for(w = width; w >= 2; w -= 2) { | |
1470 | RGB_IN(r, g, b, p); | |
1471 | r1 = r; | |
1472 | g1 = g; | |
1473 | b1 = b; | |
1474 | lum[0] = RGB_TO_Y(r, g, b); | |
1475 | ||
1476 | RGB_IN(r, g, b, p + BPP); | |
1477 | r1 += r; | |
1478 | g1 += g; | |
1479 | b1 += b; | |
1480 | lum[1] = RGB_TO_Y(r, g, b); | |
1481 | cb[0] = RGB_TO_U(r1, g1, b1, 1); | |
1482 | cr[0] = RGB_TO_V(r1, g1, b1, 1); | |
1483 | cb++; | |
1484 | cr++; | |
1485 | p += 2 * BPP; | |
1486 | lum += 2; | |
1487 | } | |
1488 | if (w) { | |
1489 | RGB_IN(r, g, b, p); | |
1490 | lum[0] = RGB_TO_Y(r, g, b); | |
1491 | cb[0] = RGB_TO_U(r, g, b, 0); | |
1492 | cr[0] = RGB_TO_V(r, g, b, 0); | |
1493 | } | |
1494 | } | |
1495 | } | |
1496 | ||
1497 | static void rgb24_to_yuvj444p(AVPicture *dst, AVPicture *src, | |
1498 | int width, int height) | |
1499 | { | |
1500 | int src_wrap, x, y; | |
1501 | int r, g, b; | |
1502 | uint8_t *lum, *cb, *cr; | |
1503 | const uint8_t *p; | |
1504 | ||
1505 | lum = dst->data[0]; | |
1506 | cb = dst->data[1]; | |
1507 | cr = dst->data[2]; | |
1508 | ||
1509 | src_wrap = src->linesize[0] - width * BPP; | |
1510 | p = src->data[0]; | |
1511 | for(y=0;y<height;y++) { | |
1512 | for(x=0;x<width;x++) { | |
1513 | RGB_IN(r, g, b, p); | |
1514 | lum[0] = RGB_TO_Y(r, g, b); | |
1515 | cb[0] = RGB_TO_U(r, g, b, 0); | |
1516 | cr[0] = RGB_TO_V(r, g, b, 0); | |
1517 | cb++; | |
1518 | cr++; | |
1519 | lum++; | |
1520 | } | |
1521 | p += src_wrap; | |
1522 | lum += dst->linesize[0] - width; | |
1523 | cb += dst->linesize[1] - width; | |
1524 | cr += dst->linesize[2] - width; | |
1525 | } | |
1526 | } | |
1527 | ||
524c6b63 FB |
1528 | #undef RGB_IN |
1529 | #undef RGB_OUT | |
1530 | #undef BPP | |
1531 | ||
1532 | /* rgba32 handling */ | |
1533 | ||
1534 | #define RGB_IN(r, g, b, s)\ | |
1535 | {\ | |
0c1a9eda | 1536 | unsigned int v = ((const uint32_t *)(s))[0];\ |
524c6b63 FB |
1537 | r = (v >> 16) & 0xff;\ |
1538 | g = (v >> 8) & 0xff;\ | |
1539 | b = v & 0xff;\ | |
1540 | } | |
1541 | ||
1542 | #define RGB_OUT(d, r, g, b)\ | |
1543 | {\ | |
0c1a9eda | 1544 | ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\ |
524c6b63 FB |
1545 | } |
1546 | ||
1547 | #define BPP 4 | |
1548 | ||
1549 | RGB_FUNCTIONS(rgba32) | |
1550 | ||
1551 | #undef RGB_IN | |
1552 | #undef RGB_OUT | |
1553 | #undef BPP | |
1554 | ||
1555 | ||
1556 | static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src, | |
1557 | int width, int height) | |
1558 | { | |
1559 | const unsigned char *p; | |
1560 | unsigned char *q; | |
1561 | int r, g, b, dst_wrap, src_wrap; | |
1562 | int x, y; | |
1563 | ||
1564 | p = src->data[0]; | |
1565 | src_wrap = src->linesize[0] - 3 * width; | |
1566 | ||
1567 | q = dst->data[0]; | |
1568 | dst_wrap = dst->linesize[0] - 2 * width; | |
1569 | ||
1570 | for(y=0;y<height;y++) { | |
1571 | for(x=0;x<width;x++) { | |
1572 | r = p[0]; | |
1573 | g = p[1]; | |
1574 | b = p[2]; | |
1575 | ||
1576 | ((unsigned short *)q)[0] = | |
1577 | ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); | |
1578 | q += 2; | |
1579 | p += 3; | |
b71472eb | 1580 | } |
524c6b63 FB |
1581 | p += src_wrap; |
1582 | q += dst_wrap; | |
b71472eb PG |
1583 | } |
1584 | } | |
1585 | ||
524c6b63 FB |
1586 | /* NOTE: we also add a dummy alpha bit */ |
1587 | static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src, | |
1588 | int width, int height) | |
b71472eb | 1589 | { |
524c6b63 FB |
1590 | const unsigned char *p; |
1591 | unsigned char *q; | |
1592 | int r, g, b, dst_wrap, src_wrap; | |
1593 | int x, y; | |
1594 | ||
1595 | p = src->data[0]; | |
1596 | src_wrap = src->linesize[0] - 3 * width; | |
1597 | ||
1598 | q = dst->data[0]; | |
1599 | dst_wrap = dst->linesize[0] - 2 * width; | |
1600 | ||
1601 | for(y=0;y<height;y++) { | |
1602 | for(x=0;x<width;x++) { | |
1603 | r = p[0]; | |
1604 | g = p[1]; | |
1605 | b = p[2]; | |
1606 | ||
1607 | ((unsigned short *)q)[0] = | |
1608 | ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000; | |
1609 | q += 2; | |
1610 | p += 3; | |
b71472eb | 1611 | } |
524c6b63 FB |
1612 | p += src_wrap; |
1613 | q += dst_wrap; | |
b71472eb PG |
1614 | } |
1615 | } | |
1616 | ||
2a877875 FB |
1617 | static void mono_to_gray(AVPicture *dst, AVPicture *src, |
1618 | int width, int height, int xor_mask) | |
524c6b63 FB |
1619 | { |
1620 | const unsigned char *p; | |
1621 | unsigned char *q; | |
1622 | int v, dst_wrap, src_wrap; | |
1623 | int y, w; | |
1624 | ||
1625 | p = src->data[0]; | |
1626 | src_wrap = src->linesize[0] - ((width + 7) >> 3); | |
1627 | ||
1628 | q = dst->data[0]; | |
2a877875 | 1629 | dst_wrap = dst->linesize[0] - width; |
524c6b63 FB |
1630 | for(y=0;y<height;y++) { |
1631 | w = width; | |
1632 | while (w >= 8) { | |
2a877875 FB |
1633 | v = *p++ ^ xor_mask; |
1634 | q[0] = -(v >> 7); | |
1635 | q[1] = -((v >> 6) & 1); | |
1636 | q[2] = -((v >> 5) & 1); | |
1637 | q[3] = -((v >> 4) & 1); | |
1638 | q[4] = -((v >> 3) & 1); | |
1639 | q[5] = -((v >> 2) & 1); | |
1640 | q[6] = -((v >> 1) & 1); | |
1641 | q[7] = -((v >> 0) & 1); | |
524c6b63 | 1642 | w -= 8; |
2a877875 | 1643 | q += 8; |
524c6b63 FB |
1644 | } |
1645 | if (w > 0) { | |
2a877875 | 1646 | v = *p++ ^ xor_mask; |
524c6b63 | 1647 | do { |
2a877875 FB |
1648 | q[0] = -((v >> 7) & 1); |
1649 | q++; | |
524c6b63 FB |
1650 | v <<= 1; |
1651 | } while (--w); | |
85c242d8 | 1652 | } |
524c6b63 FB |
1653 | p += src_wrap; |
1654 | q += dst_wrap; | |
85c242d8 FB |
1655 | } |
1656 | } | |
1657 | ||
2a877875 | 1658 | static void monowhite_to_gray(AVPicture *dst, AVPicture *src, |
524c6b63 FB |
1659 | int width, int height) |
1660 | { | |
2a877875 FB |
1661 | mono_to_gray(dst, src, width, height, 0xff); |
1662 | } | |
524c6b63 | 1663 | |
2a877875 FB |
1664 | static void monoblack_to_gray(AVPicture *dst, AVPicture *src, |
1665 | int width, int height) | |
1666 | { | |
1667 | mono_to_gray(dst, src, width, height, 0x00); | |
1668 | } | |
524c6b63 | 1669 | |
2a877875 FB |
1670 | static void gray_to_mono(AVPicture *dst, AVPicture *src, |
1671 | int width, int height, int xor_mask) | |
1672 | { | |
1673 | int n; | |
0c1a9eda ZK |
1674 | const uint8_t *s; |
1675 | uint8_t *d; | |
2a877875 FB |
1676 | int j, b, v, n1, src_wrap, dst_wrap, y; |
1677 | ||
1678 | s = src->data[0]; | |
1679 | src_wrap = src->linesize[0] - width; | |
1680 | ||
1681 | d = dst->data[0]; | |
1682 | dst_wrap = dst->linesize[0] - ((width + 7) >> 3); | |
524c6b63 FB |
1683 | |
1684 | for(y=0;y<height;y++) { | |
2a877875 FB |
1685 | n = width; |
1686 | while (n >= 8) { | |
1687 | v = 0; | |
1688 | for(j=0;j<8;j++) { | |
1689 | b = s[0]; | |
1690 | s++; | |
1691 | v = (v << 1) | (b >> 7); | |
1692 | } | |
1693 | d[0] = v ^ xor_mask; | |
1694 | d++; | |
1695 | n -= 8; | |
524c6b63 | 1696 | } |
2a877875 FB |
1697 | if (n > 0) { |
1698 | n1 = n; | |
1699 | v = 0; | |
1700 | while (n > 0) { | |
1701 | b = s[0]; | |
1702 | s++; | |
1703 | v = (v << 1) | (b >> 7); | |
1704 | n--; | |
1705 | } | |
1706 | d[0] = (v << (8 - (n1 & 7))) ^ xor_mask; | |
1707 | d++; | |
524c6b63 | 1708 | } |
2a877875 FB |
1709 | s += src_wrap; |
1710 | d += dst_wrap; | |
524c6b63 FB |
1711 | } |
1712 | } | |
1713 | ||
2a877875 FB |
1714 | static void gray_to_monowhite(AVPicture *dst, AVPicture *src, |
1715 | int width, int height) | |
1716 | { | |
1717 | gray_to_mono(dst, src, width, height, 0xff); | |
1718 | } | |
1719 | ||
1720 | static void gray_to_monoblack(AVPicture *dst, AVPicture *src, | |
1721 | int width, int height) | |
1722 | { | |
1723 | gray_to_mono(dst, src, width, height, 0x00); | |
1724 | } | |
1725 | ||
7e6d70d0 | 1726 | /* this is maybe slow, but allows for extensions */ |
0c1a9eda | 1727 | static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b) |
7e6d70d0 FB |
1728 | { |
1729 | return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6)); | |
1730 | } | |
1731 | ||
1732 | /* XXX: put jpeg quantize code instead */ | |
1733 | static void rgb24_to_pal8(AVPicture *dst, AVPicture *src, | |
1734 | int width, int height) | |
1735 | { | |
1736 | const unsigned char *p; | |
1737 | unsigned char *q; | |
1738 | int r, g, b, dst_wrap, src_wrap; | |
1739 | int x, y, i; | |
1740 | static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; | |
1741 | uint32_t *pal; | |
1742 | ||
1743 | p = src->data[0]; | |
1744 | src_wrap = src->linesize[0] - 3 * width; | |
1745 | ||
1746 | q = dst->data[0]; | |
1747 | dst_wrap = dst->linesize[0] - width; | |
1748 | ||
1749 | for(y=0;y<height;y++) { | |
1750 | for(x=0;x<width;x++) { | |
1751 | r = p[0]; | |
1752 | g = p[1]; | |
1753 | b = p[2]; | |
1754 | ||
1755 | q[0] = gif_clut_index(r, g, b); | |
1756 | q++; | |
1757 | p += 3; | |
1758 | } | |
1759 | p += src_wrap; | |
1760 | q += dst_wrap; | |
1761 | } | |
1762 | ||
1763 | /* build palette */ | |
1764 | pal = (uint32_t *)dst->data[1]; | |
1765 | i = 0; | |
1766 | for(r = 0; r < 6; r++) { | |
1767 | for(g = 0; g < 6; g++) { | |
1768 | for(b = 0; b < 6; b++) { | |
1769 | pal[i++] = (0xff << 24) | (pal_value[r] << 16) | | |
1770 | (pal_value[g] << 8) | pal_value[b]; | |
1771 | } | |
1772 | } | |
1773 | } | |
1774 | while (i < 256) | |
1775 | pal[i++] = 0; | |
1776 | } | |
1777 | ||
6d93f194 FB |
1778 | static void rgba32_to_rgb24(AVPicture *dst, AVPicture *src, |
1779 | int width, int height) | |
1780 | { | |
1781 | const uint8_t *s; | |
1782 | uint8_t *d; | |
1783 | int src_wrap, dst_wrap, j, y; | |
1784 | unsigned int v; | |
1785 | ||
1786 | s = src->data[0]; | |
1787 | src_wrap = src->linesize[0] - width * 4; | |
1788 | ||
1789 | d = dst->data[0]; | |
1790 | dst_wrap = dst->linesize[0] - width * 3; | |
1791 | ||
1792 | for(y=0;y<height;y++) { | |
1793 | for(j = 0;j < width; j++) { | |
1794 | v = *(uint32_t *)s; | |
1795 | s += 4; | |
1796 | d[0] = v >> 16; | |
1797 | d[1] = v >> 8; | |
1798 | d[2] = v; | |
1799 | d += 3; | |
1800 | } | |
1801 | s += src_wrap; | |
1802 | d += dst_wrap; | |
1803 | } | |
1804 | } | |
1805 | ||
524c6b63 FB |
1806 | typedef struct ConvertEntry { |
1807 | void (*convert)(AVPicture *dst, AVPicture *src, int width, int height); | |
1808 | } ConvertEntry; | |
1809 | ||
c50c0bc8 FB |
1810 | /* Add each new convertion function in this table. In order to be able |
1811 | to convert from any format to any format, the following constraints | |
1812 | must be satisfied: | |
1813 | ||
1814 | - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24 | |
1815 | ||
1816 | - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8 | |
1817 | ||
1818 | - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32 | |
1819 | ||
1820 | - all PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from | |
1821 | PIX_FMT_RGB24. | |
1822 | ||
1823 | - PIX_FMT_422 must convert to and from PIX_FMT_422P. | |
524c6b63 FB |
1824 | */ |
1825 | static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = { | |
1826 | [PIX_FMT_YUV420P] = { | |
1827 | [PIX_FMT_RGB555] = { | |
ef9f7306 | 1828 | .convert = yuv420p_to_rgb555 |
524c6b63 FB |
1829 | }, |
1830 | [PIX_FMT_RGB565] = { | |
ef9f7306 | 1831 | .convert = yuv420p_to_rgb565 |
524c6b63 FB |
1832 | }, |
1833 | [PIX_FMT_BGR24] = { | |
ef9f7306 | 1834 | .convert = yuv420p_to_bgr24 |
524c6b63 FB |
1835 | }, |
1836 | [PIX_FMT_RGB24] = { | |
ef9f7306 | 1837 | .convert = yuv420p_to_rgb24 |
524c6b63 FB |
1838 | }, |
1839 | [PIX_FMT_RGBA32] = { | |
ef9f7306 | 1840 | .convert = yuv420p_to_rgba32 |
524c6b63 FB |
1841 | }, |
1842 | }, | |
c50c0bc8 FB |
1843 | [PIX_FMT_YUV422P] = { |
1844 | [PIX_FMT_YUV422] = { | |
1845 | .convert = yuv422p_to_yuv422, | |
1846 | }, | |
1847 | }, | |
1848 | [PIX_FMT_YUV444P] = { | |
1849 | [PIX_FMT_RGB24] = { | |
1850 | .convert = yuv444p_to_rgb24 | |
1851 | }, | |
1852 | }, | |
1853 | [PIX_FMT_YUVJ420P] = { | |
524c6b63 | 1854 | [PIX_FMT_RGB555] = { |
c50c0bc8 | 1855 | .convert = yuvj420p_to_rgb555 |
524c6b63 FB |
1856 | }, |
1857 | [PIX_FMT_RGB565] = { | |
c50c0bc8 | 1858 | .convert = yuvj420p_to_rgb565 |
524c6b63 FB |
1859 | }, |
1860 | [PIX_FMT_BGR24] = { | |
c50c0bc8 | 1861 | .convert = yuvj420p_to_bgr24 |
524c6b63 FB |
1862 | }, |
1863 | [PIX_FMT_RGB24] = { | |
c50c0bc8 | 1864 | .convert = yuvj420p_to_rgb24 |
524c6b63 FB |
1865 | }, |
1866 | [PIX_FMT_RGBA32] = { | |
c50c0bc8 FB |
1867 | .convert = yuvj420p_to_rgba32 |
1868 | }, | |
1869 | }, | |
1870 | [PIX_FMT_YUVJ444P] = { | |
1871 | [PIX_FMT_RGB24] = { | |
1872 | .convert = yuvj444p_to_rgb24 | |
524c6b63 FB |
1873 | }, |
1874 | }, | |
1875 | [PIX_FMT_YUV422] = { | |
1876 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1877 | .convert = yuv422_to_yuv420p, |
524c6b63 | 1878 | }, |
c50c0bc8 FB |
1879 | [PIX_FMT_YUV422P] = { |
1880 | .convert = yuv422_to_yuv422p, | |
1881 | }, | |
524c6b63 FB |
1882 | }, |
1883 | ||
1884 | [PIX_FMT_RGB24] = { | |
1885 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1886 | .convert = rgb24_to_yuv420p |
524c6b63 FB |
1887 | }, |
1888 | [PIX_FMT_RGB565] = { | |
ef9f7306 | 1889 | .convert = rgb24_to_rgb565 |
524c6b63 FB |
1890 | }, |
1891 | [PIX_FMT_RGB555] = { | |
ef9f7306 | 1892 | .convert = rgb24_to_rgb555 |
524c6b63 FB |
1893 | }, |
1894 | [PIX_FMT_GRAY8] = { | |
ef9f7306 | 1895 | .convert = rgb24_to_gray |
524c6b63 | 1896 | }, |
7e6d70d0 FB |
1897 | [PIX_FMT_PAL8] = { |
1898 | .convert = rgb24_to_pal8 | |
1899 | }, | |
c50c0bc8 FB |
1900 | [PIX_FMT_YUV444P] = { |
1901 | .convert = rgb24_to_yuv444p | |
1902 | }, | |
1903 | [PIX_FMT_YUVJ420P] = { | |
1904 | .convert = rgb24_to_yuvj420p | |
1905 | }, | |
1906 | [PIX_FMT_YUVJ444P] = { | |
1907 | .convert = rgb24_to_yuvj444p | |
1908 | }, | |
524c6b63 FB |
1909 | }, |
1910 | [PIX_FMT_RGBA32] = { | |
1911 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1912 | .convert = rgba32_to_yuv420p |
524c6b63 | 1913 | }, |
69572401 FB |
1914 | [PIX_FMT_GRAY8] = { |
1915 | .convert = rgba32_to_gray | |
1916 | }, | |
6d93f194 FB |
1917 | [PIX_FMT_RGB24] = { |
1918 | .convert = rgba32_to_rgb24 | |
1919 | }, | |
524c6b63 FB |
1920 | }, |
1921 | [PIX_FMT_BGR24] = { | |
1922 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1923 | .convert = bgr24_to_yuv420p |
524c6b63 | 1924 | }, |
69572401 FB |
1925 | [PIX_FMT_GRAY8] = { |
1926 | .convert = bgr24_to_gray | |
1927 | }, | |
524c6b63 FB |
1928 | }, |
1929 | [PIX_FMT_RGB555] = { | |
1930 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1931 | .convert = rgb555_to_yuv420p |
524c6b63 | 1932 | }, |
69572401 FB |
1933 | [PIX_FMT_GRAY8] = { |
1934 | .convert = rgb555_to_gray | |
1935 | }, | |
524c6b63 FB |
1936 | }, |
1937 | [PIX_FMT_RGB565] = { | |
1938 | [PIX_FMT_YUV420P] = { | |
ef9f7306 | 1939 | .convert = rgb565_to_yuv420p |
524c6b63 | 1940 | }, |
69572401 FB |
1941 | [PIX_FMT_GRAY8] = { |
1942 | .convert = rgb565_to_gray | |
1943 | }, | |
524c6b63 FB |
1944 | }, |
1945 | [PIX_FMT_GRAY8] = { | |
69572401 FB |
1946 | [PIX_FMT_RGB555] = { |
1947 | .convert = gray_to_rgb555 | |
1948 | }, | |
1949 | [PIX_FMT_RGB565] = { | |
1950 | .convert = gray_to_rgb565 | |
1951 | }, | |
524c6b63 | 1952 | [PIX_FMT_RGB24] = { |
ef9f7306 | 1953 | .convert = gray_to_rgb24 |
524c6b63 | 1954 | }, |
69572401 FB |
1955 | [PIX_FMT_BGR24] = { |
1956 | .convert = gray_to_bgr24 | |
1957 | }, | |
1958 | [PIX_FMT_RGBA32] = { | |
1959 | .convert = gray_to_rgba32 | |
1960 | }, | |
2a877875 | 1961 | [PIX_FMT_MONOWHITE] = { |
ef9f7306 | 1962 | .convert = gray_to_monowhite |
2a877875 FB |
1963 | }, |
1964 | [PIX_FMT_MONOBLACK] = { | |
ef9f7306 | 1965 | .convert = gray_to_monoblack |
2a877875 | 1966 | }, |
524c6b63 FB |
1967 | }, |
1968 | [PIX_FMT_MONOWHITE] = { | |
2a877875 | 1969 | [PIX_FMT_GRAY8] = { |
ef9f7306 | 1970 | .convert = monowhite_to_gray |
524c6b63 FB |
1971 | }, |
1972 | }, | |
1973 | [PIX_FMT_MONOBLACK] = { | |
2a877875 | 1974 | [PIX_FMT_GRAY8] = { |
ef9f7306 | 1975 | .convert = monoblack_to_gray |
524c6b63 FB |
1976 | }, |
1977 | }, | |
7e6d70d0 FB |
1978 | [PIX_FMT_PAL8] = { |
1979 | [PIX_FMT_RGB555] = { | |
1980 | .convert = pal8_to_rgb555 | |
1981 | }, | |
1982 | [PIX_FMT_RGB565] = { | |
1983 | .convert = pal8_to_rgb565 | |
1984 | }, | |
1985 | [PIX_FMT_BGR24] = { | |
1986 | .convert = pal8_to_bgr24 | |
1987 | }, | |
1988 | [PIX_FMT_RGB24] = { | |
1989 | .convert = pal8_to_rgb24 | |
1990 | }, | |
1991 | [PIX_FMT_RGBA32] = { | |
1992 | .convert = pal8_to_rgba32 | |
1993 | }, | |
1994 | }, | |
524c6b63 FB |
1995 | }; |
1996 | ||
1997 | static int avpicture_alloc(AVPicture *picture, | |
1998 | int pix_fmt, int width, int height) | |
1999 | { | |
5c91a675 | 2000 | unsigned int size; |
524c6b63 FB |
2001 | void *ptr; |
2002 | ||
2003 | size = avpicture_get_size(pix_fmt, width, height); | |
2004 | if (size < 0) | |
2005 | goto fail; | |
2006 | ptr = av_malloc(size); | |
2007 | if (!ptr) | |
2008 | goto fail; | |
2009 | avpicture_fill(picture, ptr, pix_fmt, width, height); | |
2010 | return 0; | |
2011 | fail: | |
2012 | memset(picture, 0, sizeof(AVPicture)); | |
2013 | return -1; | |
2014 | } | |
2015 | ||
2016 | static void avpicture_free(AVPicture *picture) | |
2017 | { | |
8e1e6f31 | 2018 | av_free(picture->data[0]); |
524c6b63 FB |
2019 | } |
2020 | ||
c50c0bc8 FB |
2021 | /* return true if yuv planar */ |
2022 | static inline int is_yuv_planar(PixFmtInfo *ps) | |
2023 | { | |
2024 | return (ps->color_type == FF_COLOR_YUV || | |
2025 | ps->color_type == FF_COLOR_YUV_JPEG) && !ps->is_packed; | |
2026 | } | |
2027 | ||
85c242d8 FB |
2028 | /* XXX: always use linesize. Return -1 if not supported */ |
2029 | int img_convert(AVPicture *dst, int dst_pix_fmt, | |
524c6b63 FB |
2030 | AVPicture *src, int src_pix_fmt, |
2031 | int src_width, int src_height) | |
85c242d8 | 2032 | { |
c50c0bc8 | 2033 | static int inited; |
2a877875 | 2034 | int i, ret, dst_width, dst_height, int_pix_fmt; |
524c6b63 FB |
2035 | PixFmtInfo *src_pix, *dst_pix; |
2036 | ConvertEntry *ce; | |
2037 | AVPicture tmp1, *tmp = &tmp1; | |
2038 | ||
2039 | if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB || | |
2040 | dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB) | |
2041 | return -1; | |
2042 | if (src_width <= 0 || src_height <= 0) | |
2043 | return 0; | |
69572401 | 2044 | |
c50c0bc8 FB |
2045 | if (!inited) { |
2046 | inited = 1; | |
2047 | img_convert_init(); | |
2048 | } | |
2049 | ||
524c6b63 FB |
2050 | dst_width = src_width; |
2051 | dst_height = src_height; | |
69572401 | 2052 | |
524c6b63 FB |
2053 | dst_pix = &pix_fmt_info[dst_pix_fmt]; |
2054 | src_pix = &pix_fmt_info[src_pix_fmt]; | |
2055 | if (src_pix_fmt == dst_pix_fmt) { | |
2a877875 | 2056 | /* XXX: incorrect */ |
524c6b63 FB |
2057 | /* same format: just copy */ |
2058 | for(i = 0; i < dst_pix->nb_components; i++) { | |
2059 | int w, h; | |
2060 | w = dst_width; | |
2061 | h = dst_height; | |
c50c0bc8 | 2062 | if (is_yuv_planar(dst_pix) && (i == 1 || i == 2)) { |
524c6b63 FB |
2063 | w >>= dst_pix->x_chroma_shift; |
2064 | h >>= dst_pix->y_chroma_shift; | |
85c242d8 | 2065 | } |
524c6b63 FB |
2066 | img_copy(dst->data[i], dst->linesize[i], |
2067 | src->data[i], src->linesize[i], | |
2068 | w, h); | |
85c242d8 | 2069 | } |
524c6b63 FB |
2070 | return 0; |
2071 | } | |
2072 | ||
2073 | ce = &convert_table[src_pix_fmt][dst_pix_fmt]; | |
2074 | if (ce->convert) { | |
2075 | /* specific convertion routine */ | |
2076 | ce->convert(dst, src, dst_width, dst_height); | |
2077 | return 0; | |
2078 | } | |
2079 | ||
524c6b63 | 2080 | /* gray to YUV */ |
c50c0bc8 | 2081 | if (is_yuv_planar(dst_pix) && |
b6147995 | 2082 | src_pix_fmt == PIX_FMT_GRAY8) { |
524c6b63 FB |
2083 | int w, h, y; |
2084 | uint8_t *d; | |
2085 | ||
b6147995 FB |
2086 | if (dst_pix->color_type == FF_COLOR_YUV_JPEG) { |
2087 | img_copy(dst->data[0], dst->linesize[0], | |
2088 | src->data[0], src->linesize[0], | |
2089 | dst_width, dst_height); | |
2090 | } else { | |
c50c0bc8 FB |
2091 | img_apply_table(dst->data[0], dst->linesize[0], |
2092 | src->data[0], src->linesize[0], | |
2093 | dst_width, dst_height, | |
2094 | y_jpeg_to_ccir); | |
b6147995 | 2095 | } |
524c6b63 FB |
2096 | /* fill U and V with 128 */ |
2097 | w = dst_width; | |
2098 | h = dst_height; | |
2099 | w >>= dst_pix->x_chroma_shift; | |
2100 | h >>= dst_pix->y_chroma_shift; | |
2101 | for(i = 1; i <= 2; i++) { | |
2102 | d = dst->data[i]; | |
2a877875 FB |
2103 | for(y = 0; y< h; y++) { |
2104 | memset(d, 128, w); | |
524c6b63 FB |
2105 | d += dst->linesize[i]; |
2106 | } | |
b71472eb | 2107 | } |
524c6b63 FB |
2108 | return 0; |
2109 | } | |
2110 | ||
2111 | /* YUV to gray */ | |
c50c0bc8 | 2112 | if (is_yuv_planar(src_pix) && |
b6147995 FB |
2113 | dst_pix_fmt == PIX_FMT_GRAY8) { |
2114 | if (src_pix->color_type == FF_COLOR_YUV_JPEG) { | |
2115 | img_copy(dst->data[0], dst->linesize[0], | |
2116 | src->data[0], src->linesize[0], | |
2117 | dst_width, dst_height); | |
2118 | } else { | |
c50c0bc8 FB |
2119 | img_apply_table(dst->data[0], dst->linesize[0], |
2120 | src->data[0], src->linesize[0], | |
2121 | dst_width, dst_height, | |
2122 | y_ccir_to_jpeg); | |
b6147995 | 2123 | } |
524c6b63 FB |
2124 | return 0; |
2125 | } | |
2126 | ||
c50c0bc8 FB |
2127 | /* YUV to YUV planar */ |
2128 | if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) { | |
524c6b63 | 2129 | int x_shift, y_shift, w, h; |
0c1a9eda ZK |
2130 | void (*resize_func)(uint8_t *dst, int dst_wrap, |
2131 | uint8_t *src, int src_wrap, | |
524c6b63 FB |
2132 | int width, int height); |
2133 | ||
2134 | /* compute chroma size of the smallest dimensions */ | |
2135 | w = dst_width; | |
2136 | h = dst_height; | |
2137 | if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift) | |
2138 | w >>= dst_pix->x_chroma_shift; | |
2139 | else | |
2140 | w >>= src_pix->x_chroma_shift; | |
2141 | if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift) | |
2142 | h >>= dst_pix->y_chroma_shift; | |
2143 | else | |
2144 | h >>= src_pix->y_chroma_shift; | |
2145 | ||
2146 | x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); | |
2147 | y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); | |
c50c0bc8 | 2148 | |
524c6b63 | 2149 | if (x_shift == 0 && y_shift == 0) { |
c50c0bc8 | 2150 | resize_func = img_copy; |
524c6b63 FB |
2151 | } else if (x_shift == 0 && y_shift == 1) { |
2152 | resize_func = shrink2; | |
2153 | } else if (x_shift == 1 && y_shift == 1) { | |
2154 | resize_func = shrink22; | |
2155 | } else if (x_shift == -1 && y_shift == -1) { | |
2156 | resize_func = grow22; | |
2157 | } else if (x_shift == -1 && y_shift == 1) { | |
2158 | resize_func = conv411; | |
2159 | } else { | |
2160 | /* currently not handled */ | |
85c242d8 FB |
2161 | return -1; |
2162 | } | |
524c6b63 FB |
2163 | |
2164 | img_copy(dst->data[0], dst->linesize[0], | |
2165 | src->data[0], src->linesize[0], | |
2166 | dst_width, dst_height); | |
566986ee | 2167 | |
524c6b63 | 2168 | for(i = 1;i <= 2; i++) |
566986ee MK |
2169 | resize_func(dst->data[i], dst->linesize[i], |
2170 | src->data[i], src->linesize[i], | |
185fdc54 | 2171 | dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift); |
c50c0bc8 FB |
2172 | /* if yuv color space conversion is needed, we do it here on |
2173 | the destination image */ | |
2174 | if (dst_pix->color_type != src_pix->color_type) { | |
2175 | const uint8_t *y_table, *c_table; | |
2176 | if (dst_pix->color_type == FF_COLOR_YUV) { | |
2177 | y_table = y_jpeg_to_ccir; | |
2178 | c_table = c_jpeg_to_ccir; | |
2179 | } else { | |
2180 | y_table = y_ccir_to_jpeg; | |
2181 | c_table = c_ccir_to_jpeg; | |
2182 | } | |
2183 | img_apply_table(dst->data[0], dst->linesize[0], | |
2184 | dst->data[0], dst->linesize[0], | |
2185 | dst_width, dst_height, | |
2186 | y_table); | |
2187 | ||
2188 | for(i = 1;i <= 2; i++) | |
2189 | img_apply_table(dst->data[i], dst->linesize[i], | |
2190 | dst->data[i], dst->linesize[i], | |
2191 | dst_width>>dst_pix->x_chroma_shift, | |
2192 | dst_height>>dst_pix->y_chroma_shift, | |
2193 | c_table); | |
2194 | } | |
2195 | return 0; | |
85c242d8 | 2196 | } |
524c6b63 | 2197 | |
2a877875 | 2198 | /* try to use an intermediate format */ |
c50c0bc8 FB |
2199 | if (src_pix_fmt == PIX_FMT_YUV422 || |
2200 | dst_pix_fmt == PIX_FMT_YUV422) { | |
2201 | /* specific case: convert to YUV422P first */ | |
2202 | int_pix_fmt = PIX_FMT_YUV422P; | |
2203 | } else if ((src_pix->color_type == FF_COLOR_GRAY && | |
2204 | src_pix_fmt != PIX_FMT_GRAY8) || | |
2205 | (dst_pix->color_type == FF_COLOR_GRAY && | |
2206 | dst_pix_fmt != PIX_FMT_GRAY8)) { | |
2207 | /* gray8 is the normalized format */ | |
2a877875 | 2208 | int_pix_fmt = PIX_FMT_GRAY8; |
c50c0bc8 FB |
2209 | } else if ((is_yuv_planar(src_pix) && |
2210 | src_pix_fmt != PIX_FMT_YUV444P && | |
2211 | src_pix_fmt != PIX_FMT_YUVJ444P)) { | |
2212 | /* yuv444 is the normalized format */ | |
2213 | if (src_pix->color_type == FF_COLOR_YUV_JPEG) | |
2214 | int_pix_fmt = PIX_FMT_YUVJ444P; | |
2215 | else | |
2216 | int_pix_fmt = PIX_FMT_YUV444P; | |
2217 | } else if ((is_yuv_planar(dst_pix) && | |
2218 | dst_pix_fmt != PIX_FMT_YUV444P && | |
2219 | dst_pix_fmt != PIX_FMT_YUVJ444P)) { | |
2220 | /* yuv444 is the normalized format */ | |
2221 | if (dst_pix->color_type == FF_COLOR_YUV_JPEG) | |
2222 | int_pix_fmt = PIX_FMT_YUVJ444P; | |
2223 | else | |
2224 | int_pix_fmt = PIX_FMT_YUV444P; | |
2a877875 | 2225 | } else { |
c50c0bc8 FB |
2226 | /* the two formats are rgb or gray8 or yuv[j]444p */ |
2227 | if (src_pix->is_alpha && dst_pix->is_alpha) | |
2228 | int_pix_fmt = PIX_FMT_RGBA32; | |
2229 | else | |
2230 | int_pix_fmt = PIX_FMT_RGB24; | |
2a877875 FB |
2231 | } |
2232 | if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0) | |
2233 | return -1; | |
2234 | ret = -1; | |
2235 | if (img_convert(tmp, int_pix_fmt, | |
2236 | src, src_pix_fmt, src_width, src_height) < 0) | |
2237 | goto fail1; | |
2238 | if (img_convert(dst, dst_pix_fmt, | |
2239 | tmp, int_pix_fmt, dst_width, dst_height) < 0) | |
2240 | goto fail1; | |
2241 | ret = 0; | |
2242 | fail1: | |
2243 | avpicture_free(tmp); | |
2244 | return ret; | |
85c242d8 FB |
2245 | } |
2246 | ||
5981f4e6 F |
2247 | |
2248 | #ifdef HAVE_MMX | |
2249 | #define DEINT_INPLACE_LINE_LUM \ | |
2250 | movd_m2r(lum_m4[0],mm0);\ | |
2251 | movd_m2r(lum_m3[0],mm1);\ | |
2252 | movd_m2r(lum_m2[0],mm2);\ | |
2253 | movd_m2r(lum_m1[0],mm3);\ | |
2254 | movd_m2r(lum[0],mm4);\ | |
2255 | punpcklbw_r2r(mm7,mm0);\ | |
2256 | movd_r2m(mm2,lum_m4[0]);\ | |
2257 | punpcklbw_r2r(mm7,mm1);\ | |
2258 | punpcklbw_r2r(mm7,mm2);\ | |
2259 | punpcklbw_r2r(mm7,mm3);\ | |
2260 | punpcklbw_r2r(mm7,mm4);\ | |
2261 | paddw_r2r(mm3,mm1);\ | |
2262 | psllw_i2r(1,mm2);\ | |
2263 | paddw_r2r(mm4,mm0);\ | |
2264 | psllw_i2r(2,mm1);\ | |
2265 | paddw_r2r(mm6,mm2);\ | |
2266 | paddw_r2r(mm2,mm1);\ | |
2267 | psubusw_r2r(mm0,mm1);\ | |
2268 | psrlw_i2r(3,mm1);\ | |
2269 | packuswb_r2r(mm7,mm1);\ | |
2270 | movd_r2m(mm1,lum_m2[0]); | |
2271 | ||
2272 | #define DEINT_LINE_LUM \ | |
2273 | movd_m2r(lum_m4[0],mm0);\ | |
2274 | movd_m2r(lum_m3[0],mm1);\ | |
2275 | movd_m2r(lum_m2[0],mm2);\ | |
2276 | movd_m2r(lum_m1[0],mm3);\ | |
2277 | movd_m2r(lum[0],mm4);\ | |
2278 | punpcklbw_r2r(mm7,mm0);\ | |
2279 | punpcklbw_r2r(mm7,mm1);\ | |
2280 | punpcklbw_r2r(mm7,mm2);\ | |
2281 | punpcklbw_r2r(mm7,mm3);\ | |
2282 | punpcklbw_r2r(mm7,mm4);\ | |
2283 | paddw_r2r(mm3,mm1);\ | |
2284 | psllw_i2r(1,mm2);\ | |
2285 | paddw_r2r(mm4,mm0);\ | |
2286 | psllw_i2r(2,mm1);\ | |
2287 | paddw_r2r(mm6,mm2);\ | |
2288 | paddw_r2r(mm2,mm1);\ | |
2289 | psubusw_r2r(mm0,mm1);\ | |
2290 | psrlw_i2r(3,mm1);\ | |
2291 | packuswb_r2r(mm7,mm1);\ | |
2292 | movd_r2m(mm1,dst[0]); | |
2293 | #endif | |
2294 | ||
85c242d8 | 2295 | /* filter parameters: [-1 4 2 4 -1] // 8 */ |
0c1a9eda | 2296 | static void deinterlace_line(uint8_t *dst, uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum, |
5981f4e6 | 2297 | int size) |
85c242d8 | 2298 | { |
5981f4e6 | 2299 | #ifndef HAVE_MMX |
0c1a9eda | 2300 | uint8_t *cm = cropTbl + MAX_NEG_CROP; |
85c242d8 | 2301 | int sum; |
85c242d8 FB |
2302 | |
2303 | for(;size > 0;size--) { | |
5981f4e6 F |
2304 | sum = -lum_m4[0]; |
2305 | sum += lum_m3[0] << 2; | |
2306 | sum += lum_m2[0] << 1; | |
2307 | sum += lum_m1[0] << 2; | |
2308 | sum += -lum[0]; | |
85c242d8 | 2309 | dst[0] = cm[(sum + 4) >> 3]; |
5981f4e6 F |
2310 | lum_m4++; |
2311 | lum_m3++; | |
2312 | lum_m2++; | |
2313 | lum_m1++; | |
2314 | lum++; | |
85c242d8 | 2315 | dst++; |
85c242d8 | 2316 | } |
5981f4e6 F |
2317 | #else |
2318 | ||
782c5984 MN |
2319 | { |
2320 | mmx_t rounder; | |
2321 | rounder.uw[0]=4; | |
2322 | rounder.uw[1]=4; | |
2323 | rounder.uw[2]=4; | |
2324 | rounder.uw[3]=4; | |
2325 | pxor_r2r(mm7,mm7); | |
2326 | movq_m2r(rounder,mm6); | |
2327 | } | |
5981f4e6 F |
2328 | for (;size > 3; size-=4) { |
2329 | DEINT_LINE_LUM | |
2330 | lum_m4+=4; | |
2331 | lum_m3+=4; | |
2332 | lum_m2+=4; | |
2333 | lum_m1+=4; | |
2334 | lum+=4; | |
2335 | dst+=4; | |
2336 | } | |
2337 | #endif | |
2338 | } | |
0c1a9eda | 2339 | static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum, |
5981f4e6 F |
2340 | int size) |
2341 | { | |
2342 | #ifndef HAVE_MMX | |
0c1a9eda | 2343 | uint8_t *cm = cropTbl + MAX_NEG_CROP; |
5981f4e6 F |
2344 | int sum; |
2345 | ||
2346 | for(;size > 0;size--) { | |
2347 | sum = -lum_m4[0]; | |
2348 | sum += lum_m3[0] << 2; | |
2349 | sum += lum_m2[0] << 1; | |
2350 | lum_m4[0]=lum_m2[0]; | |
2351 | sum += lum_m1[0] << 2; | |
2352 | sum += -lum[0]; | |
2353 | lum_m2[0] = cm[(sum + 4) >> 3]; | |
2354 | lum_m4++; | |
2355 | lum_m3++; | |
2356 | lum_m2++; | |
2357 | lum_m1++; | |
2358 | lum++; | |
2359 | } | |
2360 | #else | |
2361 | ||
782c5984 MN |
2362 | { |
2363 | mmx_t rounder; | |
2364 | rounder.uw[0]=4; | |
2365 | rounder.uw[1]=4; | |
2366 | rounder.uw[2]=4; | |
2367 | rounder.uw[3]=4; | |
2368 | pxor_r2r(mm7,mm7); | |
2369 | movq_m2r(rounder,mm6); | |
2370 | } | |
5981f4e6 F |
2371 | for (;size > 3; size-=4) { |
2372 | DEINT_INPLACE_LINE_LUM | |
2373 | lum_m4+=4; | |
2374 | lum_m3+=4; | |
2375 | lum_m2+=4; | |
2376 | lum_m1+=4; | |
2377 | lum+=4; | |
2378 | } | |
2379 | #endif | |
85c242d8 FB |
2380 | } |
2381 | ||
2382 | /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The | |
2383 | top field is copied as is, but the bottom field is deinterlaced | |
2384 | against the top field. */ | |
0c1a9eda ZK |
2385 | static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, |
2386 | uint8_t *src1, int src_wrap, | |
5981f4e6 | 2387 | int width, int height) |
85c242d8 | 2388 | { |
0c1a9eda | 2389 | uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; |
5981f4e6 F |
2390 | int y; |
2391 | ||
2392 | src_m2 = src1; | |
2393 | src_m1 = src1; | |
2394 | src_0=&src_m1[src_wrap]; | |
2395 | src_p1=&src_0[src_wrap]; | |
2396 | src_p2=&src_p1[src_wrap]; | |
2397 | for(y=0;y<(height-2);y+=2) { | |
2398 | memcpy(dst,src_m1,width); | |
85c242d8 | 2399 | dst += dst_wrap; |
5981f4e6 F |
2400 | deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width); |
2401 | src_m2 = src_0; | |
2402 | src_m1 = src_p1; | |
2403 | src_0 = src_p2; | |
2404 | src_p1 += 2*src_wrap; | |
2405 | src_p2 += 2*src_wrap; | |
85c242d8 | 2406 | dst += dst_wrap; |
85c242d8 | 2407 | } |
5981f4e6 F |
2408 | memcpy(dst,src_m1,width); |
2409 | dst += dst_wrap; | |
2410 | /* do last line */ | |
2411 | deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width); | |
2412 | } | |
2413 | ||
0c1a9eda | 2414 | static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, |
5981f4e6 F |
2415 | int width, int height) |
2416 | { | |
0c1a9eda | 2417 | uint8_t *src_m1, *src_0, *src_p1, *src_p2; |
5981f4e6 | 2418 | int y; |
0c1a9eda ZK |
2419 | uint8_t *buf; |
2420 | buf = (uint8_t*)av_malloc(width); | |
5981f4e6 F |
2421 | |
2422 | src_m1 = src1; | |
2423 | memcpy(buf,src_m1,width); | |
2424 | src_0=&src_m1[src_wrap]; | |
2425 | src_p1=&src_0[src_wrap]; | |
2426 | src_p2=&src_p1[src_wrap]; | |
2427 | for(y=0;y<(height-2);y+=2) { | |
2428 | deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width); | |
2429 | src_m1 = src_p1; | |
2430 | src_0 = src_p2; | |
2431 | src_p1 += 2*src_wrap; | |
2432 | src_p2 += 2*src_wrap; | |
2433 | } | |
2434 | /* do last line */ | |
2435 | deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width); | |
6000abfa | 2436 | av_free(buf); |
85c242d8 FB |
2437 | } |
2438 | ||
2439 | ||
5981f4e6 | 2440 | /* deinterlace - if not supported return -1 */ |
85c242d8 | 2441 | int avpicture_deinterlace(AVPicture *dst, AVPicture *src, |
de6d9b64 FB |
2442 | int pix_fmt, int width, int height) |
2443 | { | |
85c242d8 FB |
2444 | int i; |
2445 | ||
2446 | if (pix_fmt != PIX_FMT_YUV420P && | |
2447 | pix_fmt != PIX_FMT_YUV422P && | |
2448 | pix_fmt != PIX_FMT_YUV444P) | |
2449 | return -1; | |
5981f4e6 | 2450 | if ((width & 3) != 0 || (height & 3) != 0) |
85c242d8 | 2451 | return -1; |
5981f4e6 | 2452 | |
85c242d8 FB |
2453 | for(i=0;i<3;i++) { |
2454 | if (i == 1) { | |
2455 | switch(pix_fmt) { | |
2456 | case PIX_FMT_YUV420P: | |
2457 | width >>= 1; | |
2458 | height >>= 1; | |
2459 | break; | |
2460 | case PIX_FMT_YUV422P: | |
2461 | width >>= 1; | |
2462 | break; | |
2463 | default: | |
2464 | break; | |
2465 | } | |
2466 | } | |
5981f4e6 F |
2467 | if (src == dst) { |
2468 | deinterlace_bottom_field_inplace(src->data[i], src->linesize[i], | |
85c242d8 | 2469 | width, height); |
5981f4e6 F |
2470 | } else { |
2471 | deinterlace_bottom_field(dst->data[i],dst->linesize[i], | |
2472 | src->data[i], src->linesize[i], | |
2473 | width, height); | |
2474 | } | |
de6d9b64 | 2475 | } |
5981f4e6 F |
2476 | #ifdef HAVE_MMX |
2477 | emms(); | |
2478 | #endif | |
85c242d8 | 2479 | return 0; |
de6d9b64 | 2480 | } |
cd4af68a ZK |
2481 | |
2482 | #undef FIX |