transparency support
[libav.git] / libavcodec / imgconvert.c
CommitLineData
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
7e7e5940
FB
42#define xglue(x, y) x ## y
43#define glue(x, y) xglue(x, y)
44
b6147995
FB
45#define FF_COLOR_RGB 0 /* RGB color space */
46#define FF_COLOR_GRAY 1 /* gray color space */
47#define FF_COLOR_YUV 2 /* YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
48#define FF_COLOR_YUV_JPEG 3 /* YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
49
7e7e5940
FB
50#define FF_PIXEL_PLANAR 0 /* each channel has one component in AVPicture */
51#define FF_PIXEL_PACKED 1 /* only one components containing all the channels */
52#define FF_PIXEL_PALETTE 2 /* one components containing indexes for a palette */
53
524c6b63
FB
54typedef struct PixFmtInfo {
55 const char *name;
7e7e5940
FB
56 uint8_t nb_channels; /* number of channels (including alpha) */
57 uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */
58 uint8_t pixel_type; /* pixel storage type (see FF_PIXEL_xxx constants) */
0c1a9eda 59 uint8_t is_alpha : 1; /* true if alpha can be specified */
7e7e5940
FB
60 uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
61 uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
62 uint8_t depth; /* bit depth of the color components */
524c6b63
FB
63} PixFmtInfo;
64
65/* this table gives more information about formats */
66static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
67 /* YUV formats */
68 [PIX_FMT_YUV420P] = {
ef9f7306 69 .name = "yuv420p",
7e7e5940 70 .nb_channels = 3,
b6147995 71 .color_type = FF_COLOR_YUV,
7e7e5940 72 .pixel_type = FF_PIXEL_PLANAR,
b6147995 73 .depth = 8,
ef9f7306 74 .x_chroma_shift = 1, .y_chroma_shift = 1,
524c6b63
FB
75 },
76 [PIX_FMT_YUV422P] = {
ef9f7306 77 .name = "yuv422p",
7e7e5940 78 .nb_channels = 3,
b6147995 79 .color_type = FF_COLOR_YUV,
7e7e5940 80 .pixel_type = FF_PIXEL_PLANAR,
b6147995 81 .depth = 8,
ef9f7306 82 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
83 },
84 [PIX_FMT_YUV444P] = {
ef9f7306 85 .name = "yuv444p",
7e7e5940 86 .nb_channels = 3,
b6147995 87 .color_type = FF_COLOR_YUV,
7e7e5940 88 .pixel_type = FF_PIXEL_PLANAR,
b6147995 89 .depth = 8,
ef9f7306 90 .x_chroma_shift = 0, .y_chroma_shift = 0,
524c6b63
FB
91 },
92 [PIX_FMT_YUV422] = {
ef9f7306 93 .name = "yuv422",
7e7e5940 94 .nb_channels = 1,
b6147995 95 .color_type = FF_COLOR_YUV,
7e7e5940 96 .pixel_type = FF_PIXEL_PACKED,
b6147995 97 .depth = 8,
ef9f7306 98 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
99 },
100 [PIX_FMT_YUV410P] = {
ef9f7306 101 .name = "yuv410p",
7e7e5940 102 .nb_channels = 3,
b6147995 103 .color_type = FF_COLOR_YUV,
7e7e5940 104 .pixel_type = FF_PIXEL_PLANAR,
b6147995 105 .depth = 8,
ef9f7306 106 .x_chroma_shift = 2, .y_chroma_shift = 2,
524c6b63
FB
107 },
108 [PIX_FMT_YUV411P] = {
ef9f7306 109 .name = "yuv411p",
7e7e5940 110 .nb_channels = 3,
b6147995 111 .color_type = FF_COLOR_YUV,
7e7e5940 112 .pixel_type = FF_PIXEL_PLANAR,
b6147995 113 .depth = 8,
ef9f7306 114 .x_chroma_shift = 2, .y_chroma_shift = 0,
524c6b63
FB
115 },
116
b6147995
FB
117 /* JPEG YUV */
118 [PIX_FMT_YUVJ420P] = {
119 .name = "yuvj420p",
7e7e5940 120 .nb_channels = 3,
b6147995 121 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 122 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
123 .depth = 8,
124 .x_chroma_shift = 1, .y_chroma_shift = 1,
125 },
126 [PIX_FMT_YUVJ422P] = {
127 .name = "yuvj422p",
7e7e5940 128 .nb_channels = 3,
b6147995 129 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 130 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
131 .depth = 8,
132 .x_chroma_shift = 1, .y_chroma_shift = 0,
133 },
134 [PIX_FMT_YUVJ444P] = {
135 .name = "yuvj444p",
7e7e5940 136 .nb_channels = 3,
b6147995 137 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 138 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
139 .depth = 8,
140 .x_chroma_shift = 0, .y_chroma_shift = 0,
141 },
142
524c6b63
FB
143 /* RGB formats */
144 [PIX_FMT_RGB24] = {
ef9f7306 145 .name = "rgb24",
7e7e5940 146 .nb_channels = 3,
b6147995 147 .color_type = FF_COLOR_RGB,
7e7e5940 148 .pixel_type = FF_PIXEL_PACKED,
b6147995 149 .depth = 8,
524c6b63
FB
150 },
151 [PIX_FMT_BGR24] = {
ef9f7306 152 .name = "bgr24",
7e7e5940 153 .nb_channels = 3,
b6147995 154 .color_type = FF_COLOR_RGB,
7e7e5940 155 .pixel_type = FF_PIXEL_PACKED,
b6147995 156 .depth = 8,
524c6b63
FB
157 },
158 [PIX_FMT_RGBA32] = {
ef9f7306 159 .name = "rgba32",
7e7e5940 160 .nb_channels = 4, .is_alpha = 1,
b6147995 161 .color_type = FF_COLOR_RGB,
7e7e5940 162 .pixel_type = FF_PIXEL_PACKED,
b6147995 163 .depth = 8,
524c6b63
FB
164 },
165 [PIX_FMT_RGB565] = {
ef9f7306 166 .name = "rgb565",
7e7e5940 167 .nb_channels = 3,
b6147995 168 .color_type = FF_COLOR_RGB,
7e7e5940 169 .pixel_type = FF_PIXEL_PACKED,
b6147995 170 .depth = 5,
524c6b63
FB
171 },
172 [PIX_FMT_RGB555] = {
ef9f7306 173 .name = "rgb555",
7e7e5940 174 .nb_channels = 4, .is_alpha = 1,
b6147995 175 .color_type = FF_COLOR_RGB,
7e7e5940 176 .pixel_type = FF_PIXEL_PACKED,
b6147995 177 .depth = 5,
524c6b63
FB
178 },
179
180 /* gray / mono formats */
181 [PIX_FMT_GRAY8] = {
ef9f7306 182 .name = "gray",
7e7e5940 183 .nb_channels = 1,
b6147995 184 .color_type = FF_COLOR_GRAY,
7e7e5940 185 .pixel_type = FF_PIXEL_PLANAR,
b6147995 186 .depth = 8,
524c6b63
FB
187 },
188 [PIX_FMT_MONOWHITE] = {
ef9f7306 189 .name = "monow",
7e7e5940 190 .nb_channels = 1,
b6147995 191 .color_type = FF_COLOR_GRAY,
7e7e5940 192 .pixel_type = FF_PIXEL_PLANAR,
b6147995 193 .depth = 1,
524c6b63
FB
194 },
195 [PIX_FMT_MONOBLACK] = {
ef9f7306 196 .name = "monob",
7e7e5940 197 .nb_channels = 1,
b6147995 198 .color_type = FF_COLOR_GRAY,
7e7e5940 199 .pixel_type = FF_PIXEL_PLANAR,
b6147995 200 .depth = 1,
524c6b63 201 },
7e6d70d0
FB
202
203 /* paletted formats */
204 [PIX_FMT_PAL8] = {
205 .name = "pal8",
7e7e5940 206 .nb_channels = 4, .is_alpha = 1,
b6147995 207 .color_type = FF_COLOR_RGB,
7e7e5940 208 .pixel_type = FF_PIXEL_PALETTE,
b6147995 209 .depth = 8,
7e6d70d0 210 },
524c6b63
FB
211};
212
213void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
214{
b6147995
FB
215 *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
216 *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
524c6b63
FB
217}
218
219const char *avcodec_get_pix_fmt_name(int pix_fmt)
220{
221 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
222 return "???";
223 else
224 return pix_fmt_info[pix_fmt].name;
225}
226
2a877875 227/* Picture field are filled with 'ptr' addresses. Also return size */
0c1a9eda 228int avpicture_fill(AVPicture *picture, uint8_t *ptr,
2a877875
FB
229 int pix_fmt, int width, int height)
230{
4c7e8619
FB
231 int size, w2, h2, size2;
232 PixFmtInfo *pinfo;
233
234 pinfo = &pix_fmt_info[pix_fmt];
2a877875
FB
235 size = width * height;
236 switch(pix_fmt) {
237 case PIX_FMT_YUV420P:
4c7e8619
FB
238 case PIX_FMT_YUV422P:
239 case PIX_FMT_YUV444P:
240 case PIX_FMT_YUV410P:
241 case PIX_FMT_YUV411P:
c50c0bc8
FB
242 case PIX_FMT_YUVJ420P:
243 case PIX_FMT_YUVJ422P:
244 case PIX_FMT_YUVJ444P:
4c7e8619
FB
245 w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
246 h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
247 size2 = w2 * h2;
2a877875
FB
248 picture->data[0] = ptr;
249 picture->data[1] = picture->data[0] + size;
4c7e8619 250 picture->data[2] = picture->data[1] + size2;
2a877875 251 picture->linesize[0] = width;
4c7e8619
FB
252 picture->linesize[1] = w2;
253 picture->linesize[2] = w2;
254 return size + 2 * size2;
2a877875
FB
255 case PIX_FMT_RGB24:
256 case PIX_FMT_BGR24:
257 picture->data[0] = ptr;
258 picture->data[1] = NULL;
259 picture->data[2] = NULL;
260 picture->linesize[0] = width * 3;
261 return size * 3;
2a877875
FB
262 case PIX_FMT_RGBA32:
263 picture->data[0] = ptr;
264 picture->data[1] = NULL;
265 picture->data[2] = NULL;
266 picture->linesize[0] = width * 4;
267 return size * 4;
2a877875
FB
268 case PIX_FMT_RGB555:
269 case PIX_FMT_RGB565:
270 case PIX_FMT_YUV422:
271 picture->data[0] = ptr;
272 picture->data[1] = NULL;
273 picture->data[2] = NULL;
274 picture->linesize[0] = width * 2;
275 return size * 2;
276 case PIX_FMT_GRAY8:
277 picture->data[0] = ptr;
278 picture->data[1] = NULL;
279 picture->data[2] = NULL;
280 picture->linesize[0] = width;
281 return size;
282 case PIX_FMT_MONOWHITE:
283 case PIX_FMT_MONOBLACK:
284 picture->data[0] = ptr;
285 picture->data[1] = NULL;
286 picture->data[2] = NULL;
287 picture->linesize[0] = (width + 7) >> 3;
288 return picture->linesize[0] * height;
7e6d70d0
FB
289 case PIX_FMT_PAL8:
290 size2 = (size + 3) & ~3;
291 picture->data[0] = ptr;
292 picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
293 picture->data[2] = NULL;
294 picture->linesize[0] = width;
295 picture->linesize[1] = 4;
296 return size2 + 256 * 4;
2a877875
FB
297 default:
298 picture->data[0] = NULL;
299 picture->data[1] = NULL;
300 picture->data[2] = NULL;
7e6d70d0 301 picture->data[3] = NULL;
2a877875
FB
302 return -1;
303 }
304}
305
306int avpicture_get_size(int pix_fmt, int width, int height)
307{
308 AVPicture dummy_pict;
309 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
310}
311
b6147995
FB
312/**
313 * compute the loss when converting from a pixel format to another
314 */
315int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
316 int has_alpha)
317{
318 const PixFmtInfo *pf, *ps;
319 int loss;
320
321 ps = &pix_fmt_info[src_pix_fmt];
322 pf = &pix_fmt_info[dst_pix_fmt];
323
324 /* compute loss */
325 loss = 0;
326 pf = &pix_fmt_info[dst_pix_fmt];
0a9ad8d1
FB
327 if (pf->depth < ps->depth ||
328 (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
b6147995 329 loss |= FF_LOSS_DEPTH;
0a9ad8d1
FB
330 if (pf->x_chroma_shift > ps->x_chroma_shift ||
331 pf->y_chroma_shift > ps->y_chroma_shift)
b6147995
FB
332 loss |= FF_LOSS_RESOLUTION;
333 switch(pf->color_type) {
334 case FF_COLOR_RGB:
335 if (ps->color_type != FF_COLOR_RGB &&
336 ps->color_type != FF_COLOR_GRAY)
337 loss |= FF_LOSS_COLORSPACE;
338 break;
339 case FF_COLOR_GRAY:
340 if (ps->color_type != FF_COLOR_GRAY)
341 loss |= FF_LOSS_COLORSPACE;
342 break;
343 case FF_COLOR_YUV:
344 if (ps->color_type != FF_COLOR_YUV)
345 loss |= FF_LOSS_COLORSPACE;
346 break;
347 case FF_COLOR_YUV_JPEG:
348 if (ps->color_type != FF_COLOR_YUV_JPEG &&
0a9ad8d1
FB
349 ps->color_type != FF_COLOR_YUV &&
350 ps->color_type != FF_COLOR_GRAY)
b6147995
FB
351 loss |= FF_LOSS_COLORSPACE;
352 break;
353 default:
354 /* fail safe test */
355 if (ps->color_type != pf->color_type)
356 loss |= FF_LOSS_COLORSPACE;
357 break;
358 }
359 if (pf->color_type == FF_COLOR_GRAY &&
360 ps->color_type != FF_COLOR_GRAY)
361 loss |= FF_LOSS_CHROMA;
362 if (!pf->is_alpha && (ps->is_alpha && has_alpha))
363 loss |= FF_LOSS_ALPHA;
7e7e5940
FB
364 if (pf->pixel_type == FF_PIXEL_PALETTE &&
365 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
b6147995
FB
366 loss |= FF_LOSS_COLORQUANT;
367 return loss;
368}
369
370static int avg_bits_per_pixel(int pix_fmt)
371{
372 int bits;
373 const PixFmtInfo *pf;
374
375 pf = &pix_fmt_info[pix_fmt];
7e7e5940
FB
376 switch(pf->pixel_type) {
377 case FF_PIXEL_PACKED:
b6147995 378 switch(pix_fmt) {
7e7e5940 379 case PIX_FMT_YUV422:
b6147995
FB
380 case PIX_FMT_RGB565:
381 case PIX_FMT_RGB555:
382 bits = 16;
b6147995
FB
383 break;
384 default:
7e7e5940 385 bits = pf->depth * pf->nb_channels;
b6147995
FB
386 break;
387 }
7e7e5940
FB
388 break;
389 case FF_PIXEL_PLANAR:
390 if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
391 bits = pf->depth * pf->nb_channels;
392 } else {
393 bits = pf->depth + ((2 * pf->depth) >>
394 (pf->x_chroma_shift + pf->y_chroma_shift));
395 }
396 break;
397 case FF_PIXEL_PALETTE:
398 bits = 8;
399 break;
400 default:
401 bits = -1;
402 break;
b6147995
FB
403 }
404 return bits;
405}
406
407static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
408 int src_pix_fmt,
409 int has_alpha,
410 int loss_mask)
411{
412 int dist, i, loss, min_dist, dst_pix_fmt;
413
414 /* find exact color match with smallest size */
415 dst_pix_fmt = -1;
416 min_dist = 0x7fffffff;
417 for(i = 0;i < PIX_FMT_NB; i++) {
418 if (pix_fmt_mask & (1 << i)) {
419 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
420 if (loss == 0) {
421 dist = avg_bits_per_pixel(i);
422 if (dist < min_dist) {
423 min_dist = dist;
424 dst_pix_fmt = i;
425 }
426 }
427 }
428 }
429 return dst_pix_fmt;
430}
431
432/**
433 * find best pixel format to convert to. Return -1 if none found
434 */
435int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
436 int has_alpha, int *loss_ptr)
437{
438 int dst_pix_fmt, loss_mask, i;
439 static const int loss_mask_order[] = {
440 ~0, /* no loss first */
441 ~FF_LOSS_ALPHA,
442 ~FF_LOSS_RESOLUTION,
443 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
444 ~FF_LOSS_COLORQUANT,
445 ~FF_LOSS_DEPTH,
446 0,
447 };
448
449 /* try with successive loss */
450 i = 0;
451 for(;;) {
452 loss_mask = loss_mask_order[i++];
453 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
454 has_alpha, loss_mask);
455 if (dst_pix_fmt >= 0)
456 goto found;
457 if (loss_mask == 0)
458 break;
459 }
460 return -1;
461 found:
462 if (loss_ptr)
463 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
464 return dst_pix_fmt;
465}
466
7e7e5940 467static void img_copy_plane(uint8_t *dst, int dst_wrap,
e352ff08
FB
468 const uint8_t *src, int src_wrap,
469 int width, int height)
7e7e5940
FB
470{
471 for(;height > 0; height--) {
472 memcpy(dst, src, width);
473 dst += dst_wrap;
474 src += src_wrap;
475 }
476}
477
478/* copy image 'src' to 'dst' */
479void img_copy(AVPicture *dst, AVPicture *src,
480 int pix_fmt, int width, int height)
481{
482 int bwidth, bits, i;
483 PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
484
485 pf = &pix_fmt_info[pix_fmt];
486 switch(pf->pixel_type) {
487 case FF_PIXEL_PACKED:
488 switch(pix_fmt) {
489 case PIX_FMT_YUV422:
490 case PIX_FMT_RGB565:
491 case PIX_FMT_RGB555:
492 bits = 16;
493 break;
494 default:
495 bits = pf->depth * pf->nb_channels;
496 break;
497 }
498 bwidth = (width * bits + 7) >> 3;
499 img_copy_plane(dst->data[0], dst->linesize[0],
500 src->data[0], src->linesize[0],
501 bwidth, height);
502 break;
503 case FF_PIXEL_PLANAR:
504 for(i = 0; i < pf->nb_channels; i++) {
505 int w, h;
506 w = width;
507 h = height;
508 if (i == 1 || i == 2) {
509 w >>= pf->x_chroma_shift;
510 h >>= pf->y_chroma_shift;
511 }
512 bwidth = (w * pf->depth + 7) >> 3;
513 img_copy_plane(dst->data[i], dst->linesize[i],
514 src->data[i], src->linesize[i],
515 bwidth, h);
516 }
517 break;
518 case FF_PIXEL_PALETTE:
519 img_copy_plane(dst->data[0], dst->linesize[0],
520 src->data[0], src->linesize[0],
521 width, height);
522 /* copy the palette */
523 img_copy_plane(dst->data[1], dst->linesize[1],
524 src->data[1], src->linesize[1],
525 4, 256);
526 break;
527 }
528}
2a877875 529
de6d9b64
FB
530/* XXX: totally non optimized */
531
524c6b63
FB
532static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
533 int width, int height)
de6d9b64 534{
c50c0bc8
FB
535 const uint8_t *p, *p1;
536 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
537 int x;
524c6b63 538
c50c0bc8
FB
539 p1 = src->data[0];
540 lum1 = dst->data[0];
0a05e494
FB
541 cb1 = dst->data[1];
542 cr1 = dst->data[2];
c50c0bc8
FB
543
544 for(;height >= 2; height -= 2) {
545 p = p1;
546 lum = lum1;
547 cb = cb1;
548 cr = cr1;
de6d9b64 549 for(x=0;x<width;x+=2) {
e78df699
MN
550 lum[0] = p[0];
551 cb[0] = p[1];
552 lum[1] = p[2];
553 cr[0] = p[3];
de6d9b64
FB
554 p += 4;
555 lum += 2;
556 cb++;
557 cr++;
558 }
c50c0bc8
FB
559 p1 += src->linesize[0];
560 lum1 += dst->linesize[0];
561 p = p1;
562 lum = lum1;
de6d9b64 563 for(x=0;x<width;x+=2) {
e78df699
MN
564 lum[0] = p[0];
565 lum[1] = p[2];
de6d9b64
FB
566 p += 4;
567 lum += 2;
568 }
c50c0bc8
FB
569 p1 += src->linesize[0];
570 lum1 += dst->linesize[0];
571 cb1 += dst->linesize[1];
572 cr1 += dst->linesize[2];
573 }
574}
575
576static void yuv422_to_yuv422p(AVPicture *dst, AVPicture *src,
577 int width, int height)
578{
579 const uint8_t *p, *p1;
580 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
581 int w;
582
583 p1 = src->data[0];
584 lum1 = dst->data[0];
0a05e494
FB
585 cb1 = dst->data[1];
586 cr1 = dst->data[2];
587 for(;height > 0; height--) {
c50c0bc8
FB
588 p = p1;
589 lum = lum1;
590 cb = cb1;
591 cr = cr1;
592 for(w = width; w >= 2; w -= 2) {
593 lum[0] = p[0];
594 cb[0] = p[1];
595 lum[1] = p[2];
596 cr[0] = p[3];
597 p += 4;
598 lum += 2;
599 cb++;
600 cr++;
601 }
602 p1 += src->linesize[0];
603 lum1 += dst->linesize[0];
604 cb1 += dst->linesize[1];
605 cr1 += dst->linesize[2];
de6d9b64
FB
606 }
607}
608
c50c0bc8
FB
609static void yuv422p_to_yuv422(AVPicture *dst, AVPicture *src,
610 int width, int height)
611{
612 uint8_t *p, *p1;
613 const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
614 int w;
615
616 p1 = dst->data[0];
617 lum1 = src->data[0];
0a05e494
FB
618 cb1 = src->data[1];
619 cr1 = src->data[2];
620 for(;height > 0; height--) {
c50c0bc8
FB
621 p = p1;
622 lum = lum1;
623 cb = cb1;
624 cr = cr1;
625 for(w = width; w >= 2; w -= 2) {
626 p[0] = lum[0];
627 p[1] = cb[0];
628 p[2] = lum[1];
629 p[3] = cr[0];
630 p += 4;
631 lum += 2;
632 cb++;
633 cr++;
634 }
0a05e494
FB
635 p1 += dst->linesize[0];
636 lum1 += src->linesize[0];
637 cb1 += src->linesize[1];
638 cr1 += src->linesize[2];
c50c0bc8
FB
639 }
640}
641
642#define SCALEBITS 10
de6d9b64 643#define ONE_HALF (1 << (SCALEBITS - 1))
c50c0bc8 644#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
de6d9b64 645
c50c0bc8
FB
646#define YUV_TO_RGB1_CCIR(cb1, cr1)\
647{\
648 cb = (cb1) - 128;\
649 cr = (cr1) - 128;\
650 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
651 g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
652 ONE_HALF;\
653 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
654}
b6147995 655
c50c0bc8
FB
656#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
657{\
658 y = ((y1) - 16) * FIX(255.0/219.0);\
659 r = cm[(y + r_add) >> SCALEBITS];\
660 g = cm[(y + g_add) >> SCALEBITS];\
661 b = cm[(y + b_add) >> SCALEBITS];\
662}
663
664#define YUV_TO_RGB1(cb1, cr1)\
665{\
666 cb = (cb1) - 128;\
667 cr = (cr1) - 128;\
668 r_add = FIX(1.40200) * cr + ONE_HALF;\
669 g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
670 b_add = FIX(1.77200) * cb + ONE_HALF;\
671}
b6147995
FB
672
673#define YUV_TO_RGB2(r, g, b, y1)\
674{\
c50c0bc8
FB
675 y = (y1) << SCALEBITS;\
676 r = cm[(y + r_add) >> SCALEBITS];\
677 g = cm[(y + g_add) >> SCALEBITS];\
678 b = cm[(y + b_add) >> SCALEBITS];\
b6147995
FB
679}
680
c50c0bc8 681#define Y_CCIR_TO_JPEG(y)\
b6147995
FB
682 cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
683
c50c0bc8 684#define Y_JPEG_TO_CCIR(y)\
b6147995
FB
685 (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
686
c50c0bc8
FB
687#define C_CCIR_TO_JPEG(y)\
688 cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
689
690/* NOTE: the clamp is really necessary! */
691#define C_JPEG_TO_CCIR(y)\
692({\
693 int __y;\
694 __y = ((((y) - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);\
695 if (__y < 16)\
696 __y = 16;\
697 __y;\
698})
699
b6147995
FB
700#define RGB_TO_Y(r, g, b) \
701((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
702 FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
703
c50c0bc8 704#define RGB_TO_U(r1, g1, b1, shift)\
b6147995 705(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
c50c0bc8 706 FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 707
c50c0bc8 708#define RGB_TO_V(r1, g1, b1, shift)\
b6147995 709(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
c50c0bc8 710 FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995
FB
711
712#define RGB_TO_Y_CCIR(r, g, b) \
713((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
714 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
715
c50c0bc8 716#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
b6147995 717(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
c50c0bc8 718 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 719
c50c0bc8 720#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
b6147995 721(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
c50c0bc8 722 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 723
c50c0bc8
FB
724static uint8_t y_ccir_to_jpeg[256];
725static uint8_t y_jpeg_to_ccir[256];
726static uint8_t c_ccir_to_jpeg[256];
727static uint8_t c_jpeg_to_ccir[256];
728
729/* init various conversion tables */
730static void img_convert_init(void)
b6147995 731{
c50c0bc8 732 int i;
b6147995
FB
733 uint8_t *cm = cropTbl + MAX_NEG_CROP;
734
c50c0bc8
FB
735 for(i = 0;i < 256; i++) {
736 y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
737 y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
738 c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
739 c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
b6147995
FB
740 }
741}
742
c50c0bc8
FB
743/* apply to each pixel the given table */
744static void img_apply_table(uint8_t *dst, int dst_wrap,
745 const uint8_t *src, int src_wrap,
746 int width, int height, const uint8_t *table1)
b6147995
FB
747{
748 int n;
749 const uint8_t *s;
750 uint8_t *d;
c50c0bc8 751 const uint8_t *table;
b6147995 752
c50c0bc8 753 table = table1;
b6147995
FB
754 for(;height > 0; height--) {
755 s = src;
756 d = dst;
757 n = width;
758 while (n >= 4) {
c50c0bc8
FB
759 d[0] = table[s[0]];
760 d[1] = table[s[1]];
761 d[2] = table[s[2]];
762 d[3] = table[s[3]];
b6147995
FB
763 d += 4;
764 s += 4;
765 n -= 4;
766 }
767 while (n > 0) {
c50c0bc8 768 d[0] = table[s[0]];
b6147995
FB
769 d++;
770 s++;
771 n--;
772 }
773 dst += dst_wrap;
774 src += src_wrap;
775 }
776}
777
85c242d8 778/* XXX: use generic filter ? */
e352ff08
FB
779/* XXX: in most cases, the sampling position is incorrect */
780
781/* 4x1 -> 1x1 */
782static void shrink41(uint8_t *dst, int dst_wrap,
783 const uint8_t *src, int src_wrap,
784 int width, int height)
785{
786 int w;
787 const uint8_t *s;
788 uint8_t *d;
789
790 for(;height > 0; height--) {
791 s = src;
792 d = dst;
793 for(w = width;w > 0; w--) {
794 d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
795 s += 4;
796 d++;
797 }
798 src += src_wrap;
799 dst += dst_wrap;
800 }
801}
802
803/* 2x1 -> 1x1 */
804static void shrink21(uint8_t *dst, int dst_wrap,
805 const uint8_t *src, int src_wrap,
806 int width, int height)
807{
808 int w;
809 const uint8_t *s;
810 uint8_t *d;
811
812 for(;height > 0; height--) {
813 s = src;
814 d = dst;
815 for(w = width;w > 0; w--) {
816 d[0] = (s[0] + s[1]) >> 1;
817 s += 2;
818 d++;
819 }
820 src += src_wrap;
821 dst += dst_wrap;
822 }
823}
824
85c242d8 825/* 1x2 -> 1x1 */
e352ff08
FB
826static void shrink12(uint8_t *dst, int dst_wrap,
827 const uint8_t *src, int src_wrap,
828 int width, int height)
85c242d8
FB
829{
830 int w;
e352ff08
FB
831 uint8_t *d;
832 const uint8_t *s1, *s2;
85c242d8
FB
833
834 for(;height > 0; height--) {
835 s1 = src;
836 s2 = s1 + src_wrap;
837 d = dst;
838 for(w = width;w >= 4; w-=4) {
839 d[0] = (s1[0] + s2[0]) >> 1;
840 d[1] = (s1[1] + s2[1]) >> 1;
841 d[2] = (s1[2] + s2[2]) >> 1;
842 d[3] = (s1[3] + s2[3]) >> 1;
843 s1 += 4;
844 s2 += 4;
845 d += 4;
846 }
847 for(;w > 0; w--) {
848 d[0] = (s1[0] + s2[0]) >> 1;
849 s1++;
850 s2++;
851 d++;
852 }
853 src += 2 * src_wrap;
854 dst += dst_wrap;
855 }
856}
857
858/* 2x2 -> 1x1 */
0c1a9eda 859static void shrink22(uint8_t *dst, int dst_wrap,
e352ff08 860 const uint8_t *src, int src_wrap,
85c242d8
FB
861 int width, int height)
862{
863 int w;
e352ff08
FB
864 const uint8_t *s1, *s2;
865 uint8_t *d;
85c242d8
FB
866
867 for(;height > 0; height--) {
868 s1 = src;
869 s2 = s1 + src_wrap;
870 d = dst;
871 for(w = width;w >= 4; w-=4) {
0a9ad8d1
FB
872 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
873 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
874 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
875 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
85c242d8
FB
876 s1 += 8;
877 s2 += 8;
878 d += 4;
879 }
880 for(;w > 0; w--) {
0a9ad8d1 881 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
85c242d8
FB
882 s1 += 2;
883 s2 += 2;
884 d++;
885 }
886 src += 2 * src_wrap;
887 dst += dst_wrap;
888 }
889}
890
e352ff08
FB
891/* 4x4 -> 1x1 */
892static void shrink44(uint8_t *dst, int dst_wrap,
893 const uint8_t *src, int src_wrap,
6742d95d
FR
894 int width, int height)
895{
896 int w;
e352ff08
FB
897 const uint8_t *s1, *s2, *s3, *s4;
898 uint8_t *d;
6742d95d
FR
899
900 for(;height > 0; height--) {
901 s1 = src;
e352ff08
FB
902 s2 = s1 + src_wrap;
903 s3 = s2 + src_wrap;
904 s4 = s3 + src_wrap;
6742d95d 905 d = dst;
e352ff08
FB
906 for(w = width;w > 0; w--) {
907 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
908 s2[0] + s2[1] + s2[2] + s2[3] +
909 s3[0] + s3[1] + s3[2] + s3[3] +
910 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
911 s1 += 4;
912 s2 += 4;
913 s3 += 4;
914 s4 += 4;
6742d95d
FR
915 d++;
916 }
e352ff08
FB
917 src += 4 * src_wrap;
918 dst += dst_wrap;
919 }
920}
921
922static void grow21_line(uint8_t *dst, const uint8_t *src,
923 int width)
924{
925 int w;
926 const uint8_t *s1;
927 uint8_t *d;
928
929 s1 = src;
930 d = dst;
931 for(w = width;w >= 4; w-=4) {
932 d[1] = d[0] = s1[0];
933 d[3] = d[2] = s1[1];
934 s1 += 2;
935 d += 4;
936 }
937 for(;w >= 2; w -= 2) {
938 d[1] = d[0] = s1[0];
939 s1 ++;
940 d += 2;
941 }
942 /* only needed if width is not a multiple of two */
943 /* XXX: veryfy that */
944 if (w) {
945 d[0] = s1[0];
946 }
947}
948
949static void grow41_line(uint8_t *dst, const uint8_t *src,
950 int width)
951{
952 int w, v;
953 const uint8_t *s1;
954 uint8_t *d;
955
956 s1 = src;
957 d = dst;
958 for(w = width;w >= 4; w-=4) {
959 v = s1[0];
960 d[0] = v;
961 d[1] = v;
962 d[2] = v;
963 d[3] = v;
964 s1 ++;
965 d += 4;
966 }
967}
968
969/* 1x1 -> 2x1 */
970static void grow21(uint8_t *dst, int dst_wrap,
971 const uint8_t *src, int src_wrap,
972 int width, int height)
973{
974 for(;height > 0; height--) {
975 grow21_line(dst, src, width);
976 src += src_wrap;
977 dst += dst_wrap;
978 }
979}
980
981/* 1x1 -> 2x2 */
982static void grow22(uint8_t *dst, int dst_wrap,
983 const uint8_t *src, int src_wrap,
984 int width, int height)
985{
986 for(;height > 0; height--) {
987 grow21_line(dst, src, width);
6742d95d
FR
988 if (height%2)
989 src += src_wrap;
990 dst += dst_wrap;
991 }
992}
993
e352ff08
FB
994/* 1x1 -> 4x1 */
995static void grow41(uint8_t *dst, int dst_wrap,
996 const uint8_t *src, int src_wrap,
997 int width, int height)
998{
999 for(;height > 0; height--) {
1000 grow41_line(dst, src, width);
1001 src += src_wrap;
1002 dst += dst_wrap;
1003 }
1004}
1005
1006/* 1x1 -> 4x4 */
1007static void grow44(uint8_t *dst, int dst_wrap,
1008 const uint8_t *src, int src_wrap,
1009 int width, int height)
1010{
1011 for(;height > 0; height--) {
1012 grow41_line(dst, src, width);
1013 if ((height & 3) == 1)
1014 src += src_wrap;
1015 dst += dst_wrap;
1016 }
1017}
1018
524c6b63 1019/* 1x2 -> 2x1 */
0c1a9eda 1020static void conv411(uint8_t *dst, int dst_wrap,
e352ff08 1021 const uint8_t *src, int src_wrap,
789587d5
FB
1022 int width, int height)
1023{
1024 int w, c;
e352ff08
FB
1025 const uint8_t *s1, *s2;
1026 uint8_t *d;
789587d5 1027
50643575
MN
1028 width>>=1;
1029
524c6b63 1030 for(;height > 0; height--) {
789587d5
FB
1031 s1 = src;
1032 s2 = src + src_wrap;
1033 d = dst;
1034 for(w = width;w > 0; w--) {
1035 c = (s1[0] + s2[0]) >> 1;
1036 d[0] = c;
1037 d[1] = c;
1038 s1++;
1039 s2++;
1040 d += 2;
1041 }
1042 src += src_wrap * 2;
1043 dst += dst_wrap;
1044 }
1045}
1046
7e7e5940
FB
1047/* XXX: add jpeg quantize code */
1048
1049#define TRANSP_INDEX (6*6*6)
1050
1051/* this is maybe slow, but allows for extensions */
1052static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
85c242d8 1053{
7e7e5940 1054 return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
85c242d8
FB
1055}
1056
7e7e5940
FB
1057static void build_rgb_palette(uint8_t *palette, int has_alpha)
1058{
1059 uint32_t *pal;
1060 static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
1061 int i, r, g, b;
1062
1063 pal = (uint32_t *)palette;
1064 i = 0;
1065 for(r = 0; r < 6; r++) {
1066 for(g = 0; g < 6; g++) {
1067 for(b = 0; b < 6; b++) {
1068 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
1069 (pal_value[g] << 8) | pal_value[b];
1070 }
1071 }
1072 }
1073 if (has_alpha)
1074 pal[i++] = 0;
1075 while (i < 256)
1076 pal[i++] = 0xff000000;
524c6b63
FB
1077}
1078
1079/* copy bit n to bits 0 ... n - 1 */
1080static inline unsigned int bitcopy_n(unsigned int a, int n)
b71472eb 1081{
524c6b63
FB
1082 int mask;
1083 mask = (1 << n) - 1;
1084 return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
1085}
1086
1087/* rgb555 handling */
1088
7e7e5940
FB
1089#define RGB_NAME rgb555
1090
524c6b63
FB
1091#define RGB_IN(r, g, b, s)\
1092{\
0c1a9eda 1093 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
1094 r = bitcopy_n(v >> (10 - 3), 3);\
1095 g = bitcopy_n(v >> (5 - 3), 3);\
1096 b = bitcopy_n(v << 3, 3);\
1097}
1098
7e7e5940 1099#define RGBA_IN(r, g, b, a, s)\
524c6b63 1100{\
7e7e5940
FB
1101 unsigned int v = ((const uint16_t *)(s))[0];\
1102 r = bitcopy_n(v >> (10 - 3), 3);\
1103 g = bitcopy_n(v >> (5 - 3), 3);\
1104 b = bitcopy_n(v << 3, 3);\
1105 a = bitcopy_n(v >> 15, 7);\
1106}
1107
1108#define RGBA_OUT(d, r, g, b, a)\
1109{\
1110 ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \
1111 ((a << 8) & 0x8000);\
524c6b63
FB
1112}
1113
1114#define BPP 2
1115
7e7e5940 1116#include "imgconvert_template.h"
524c6b63
FB
1117
1118/* rgb565 handling */
1119
7e7e5940
FB
1120#define RGB_NAME rgb565
1121
524c6b63
FB
1122#define RGB_IN(r, g, b, s)\
1123{\
0c1a9eda 1124 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
1125 r = bitcopy_n(v >> (11 - 3), 3);\
1126 g = bitcopy_n(v >> (5 - 2), 2);\
1127 b = bitcopy_n(v << 3, 3);\
1128}
1129
1130#define RGB_OUT(d, r, g, b)\
1131{\
0c1a9eda 1132 ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
524c6b63
FB
1133}
1134
1135#define BPP 2
1136
7e7e5940 1137#include "imgconvert_template.h"
524c6b63
FB
1138
1139/* bgr24 handling */
1140
7e7e5940
FB
1141#define RGB_NAME bgr24
1142
524c6b63
FB
1143#define RGB_IN(r, g, b, s)\
1144{\
1145 b = (s)[0];\
1146 g = (s)[1];\
1147 r = (s)[2];\
1148}
1149
1150#define RGB_OUT(d, r, g, b)\
1151{\
1152 (d)[0] = b;\
1153 (d)[1] = g;\
1154 (d)[2] = r;\
1155}
1156
1157#define BPP 3
1158
7e7e5940 1159#include "imgconvert_template.h"
524c6b63
FB
1160
1161#undef RGB_IN
1162#undef RGB_OUT
1163#undef BPP
1164
1165/* rgb24 handling */
1166
7e7e5940
FB
1167#define RGB_NAME rgb24
1168#define FMT_RGB24
1169
524c6b63
FB
1170#define RGB_IN(r, g, b, s)\
1171{\
1172 r = (s)[0];\
1173 g = (s)[1];\
1174 b = (s)[2];\
1175}
1176
1177#define RGB_OUT(d, r, g, b)\
1178{\
1179 (d)[0] = r;\
1180 (d)[1] = g;\
1181 (d)[2] = b;\
1182}
1183
1184#define BPP 3
1185
7e7e5940 1186#include "imgconvert_template.h"
524c6b63
FB
1187
1188/* rgba32 handling */
1189
7e7e5940
FB
1190#define RGB_NAME rgba32
1191#define FMT_RGBA32
1192
524c6b63
FB
1193#define RGB_IN(r, g, b, s)\
1194{\
0c1a9eda 1195 unsigned int v = ((const uint32_t *)(s))[0];\
524c6b63
FB
1196 r = (v >> 16) & 0xff;\
1197 g = (v >> 8) & 0xff;\
1198 b = v & 0xff;\
1199}
1200
7e7e5940 1201#define RGBA_IN(r, g, b, a, s)\
524c6b63 1202{\
7e7e5940
FB
1203 unsigned int v = ((const uint32_t *)(s))[0];\
1204 a = (v >> 24) & 0xff;\
1205 r = (v >> 16) & 0xff;\
1206 g = (v >> 8) & 0xff;\
1207 b = v & 0xff;\
524c6b63
FB
1208}
1209
7e7e5940
FB
1210#define RGBA_OUT(d, r, g, b, a)\
1211{\
1212 ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
b71472eb
PG
1213}
1214
7e7e5940 1215#define BPP 4
524c6b63 1216
7e7e5940 1217#include "imgconvert_template.h"
b71472eb 1218
2a877875
FB
1219static void mono_to_gray(AVPicture *dst, AVPicture *src,
1220 int width, int height, int xor_mask)
524c6b63
FB
1221{
1222 const unsigned char *p;
1223 unsigned char *q;
1224 int v, dst_wrap, src_wrap;
1225 int y, w;
1226
1227 p = src->data[0];
1228 src_wrap = src->linesize[0] - ((width + 7) >> 3);
1229
1230 q = dst->data[0];
2a877875 1231 dst_wrap = dst->linesize[0] - width;
524c6b63
FB
1232 for(y=0;y<height;y++) {
1233 w = width;
1234 while (w >= 8) {
2a877875
FB
1235 v = *p++ ^ xor_mask;
1236 q[0] = -(v >> 7);
1237 q[1] = -((v >> 6) & 1);
1238 q[2] = -((v >> 5) & 1);
1239 q[3] = -((v >> 4) & 1);
1240 q[4] = -((v >> 3) & 1);
1241 q[5] = -((v >> 2) & 1);
1242 q[6] = -((v >> 1) & 1);
1243 q[7] = -((v >> 0) & 1);
524c6b63 1244 w -= 8;
2a877875 1245 q += 8;
524c6b63
FB
1246 }
1247 if (w > 0) {
2a877875 1248 v = *p++ ^ xor_mask;
524c6b63 1249 do {
2a877875
FB
1250 q[0] = -((v >> 7) & 1);
1251 q++;
524c6b63
FB
1252 v <<= 1;
1253 } while (--w);
85c242d8 1254 }
524c6b63
FB
1255 p += src_wrap;
1256 q += dst_wrap;
85c242d8
FB
1257 }
1258}
1259
2a877875 1260static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
524c6b63
FB
1261 int width, int height)
1262{
2a877875
FB
1263 mono_to_gray(dst, src, width, height, 0xff);
1264}
524c6b63 1265
2a877875
FB
1266static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
1267 int width, int height)
1268{
1269 mono_to_gray(dst, src, width, height, 0x00);
1270}
524c6b63 1271
2a877875
FB
1272static void gray_to_mono(AVPicture *dst, AVPicture *src,
1273 int width, int height, int xor_mask)
1274{
1275 int n;
0c1a9eda
ZK
1276 const uint8_t *s;
1277 uint8_t *d;
2a877875
FB
1278 int j, b, v, n1, src_wrap, dst_wrap, y;
1279
1280 s = src->data[0];
1281 src_wrap = src->linesize[0] - width;
1282
1283 d = dst->data[0];
1284 dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
524c6b63
FB
1285
1286 for(y=0;y<height;y++) {
2a877875
FB
1287 n = width;
1288 while (n >= 8) {
1289 v = 0;
1290 for(j=0;j<8;j++) {
1291 b = s[0];
1292 s++;
1293 v = (v << 1) | (b >> 7);
1294 }
1295 d[0] = v ^ xor_mask;
1296 d++;
1297 n -= 8;
524c6b63 1298 }
2a877875
FB
1299 if (n > 0) {
1300 n1 = n;
1301 v = 0;
1302 while (n > 0) {
1303 b = s[0];
1304 s++;
1305 v = (v << 1) | (b >> 7);
1306 n--;
1307 }
1308 d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
1309 d++;
524c6b63 1310 }
2a877875
FB
1311 s += src_wrap;
1312 d += dst_wrap;
524c6b63
FB
1313 }
1314}
1315
2a877875
FB
1316static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
1317 int width, int height)
1318{
1319 gray_to_mono(dst, src, width, height, 0xff);
1320}
1321
1322static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
1323 int width, int height)
1324{
1325 gray_to_mono(dst, src, width, height, 0x00);
1326}
1327
524c6b63
FB
1328typedef struct ConvertEntry {
1329 void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
1330} ConvertEntry;
1331
c50c0bc8
FB
1332/* Add each new convertion function in this table. In order to be able
1333 to convert from any format to any format, the following constraints
1334 must be satisfied:
1335
1336 - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
1337
1338 - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
1339
1340 - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32
1341
e352ff08 1342 - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
c50c0bc8
FB
1343 PIX_FMT_RGB24.
1344
1345 - PIX_FMT_422 must convert to and from PIX_FMT_422P.
e352ff08
FB
1346
1347 The other conversion functions are just optimisations for common cases.
524c6b63
FB
1348*/
1349static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1350 [PIX_FMT_YUV420P] = {
1351 [PIX_FMT_RGB555] = {
ef9f7306 1352 .convert = yuv420p_to_rgb555
524c6b63
FB
1353 },
1354 [PIX_FMT_RGB565] = {
ef9f7306 1355 .convert = yuv420p_to_rgb565
524c6b63
FB
1356 },
1357 [PIX_FMT_BGR24] = {
ef9f7306 1358 .convert = yuv420p_to_bgr24
524c6b63
FB
1359 },
1360 [PIX_FMT_RGB24] = {
ef9f7306 1361 .convert = yuv420p_to_rgb24
524c6b63
FB
1362 },
1363 [PIX_FMT_RGBA32] = {
ef9f7306 1364 .convert = yuv420p_to_rgba32
524c6b63
FB
1365 },
1366 },
c50c0bc8
FB
1367 [PIX_FMT_YUV422P] = {
1368 [PIX_FMT_YUV422] = {
1369 .convert = yuv422p_to_yuv422,
1370 },
1371 },
1372 [PIX_FMT_YUV444P] = {
1373 [PIX_FMT_RGB24] = {
1374 .convert = yuv444p_to_rgb24
1375 },
1376 },
1377 [PIX_FMT_YUVJ420P] = {
524c6b63 1378 [PIX_FMT_RGB555] = {
c50c0bc8 1379 .convert = yuvj420p_to_rgb555
524c6b63
FB
1380 },
1381 [PIX_FMT_RGB565] = {
c50c0bc8 1382 .convert = yuvj420p_to_rgb565
524c6b63
FB
1383 },
1384 [PIX_FMT_BGR24] = {
c50c0bc8 1385 .convert = yuvj420p_to_bgr24
524c6b63
FB
1386 },
1387 [PIX_FMT_RGB24] = {
c50c0bc8 1388 .convert = yuvj420p_to_rgb24
524c6b63
FB
1389 },
1390 [PIX_FMT_RGBA32] = {
c50c0bc8
FB
1391 .convert = yuvj420p_to_rgba32
1392 },
1393 },
1394 [PIX_FMT_YUVJ444P] = {
1395 [PIX_FMT_RGB24] = {
1396 .convert = yuvj444p_to_rgb24
524c6b63
FB
1397 },
1398 },
1399 [PIX_FMT_YUV422] = {
1400 [PIX_FMT_YUV420P] = {
ef9f7306 1401 .convert = yuv422_to_yuv420p,
524c6b63 1402 },
c50c0bc8
FB
1403 [PIX_FMT_YUV422P] = {
1404 .convert = yuv422_to_yuv422p,
1405 },
524c6b63
FB
1406 },
1407
1408 [PIX_FMT_RGB24] = {
1409 [PIX_FMT_YUV420P] = {
ef9f7306 1410 .convert = rgb24_to_yuv420p
524c6b63
FB
1411 },
1412 [PIX_FMT_RGB565] = {
ef9f7306 1413 .convert = rgb24_to_rgb565
524c6b63
FB
1414 },
1415 [PIX_FMT_RGB555] = {
ef9f7306 1416 .convert = rgb24_to_rgb555
524c6b63 1417 },
7e7e5940
FB
1418 [PIX_FMT_RGBA32] = {
1419 .convert = rgb24_to_rgba32
1420 },
1421 [PIX_FMT_BGR24] = {
1422 .convert = rgb24_to_bgr24
1423 },
524c6b63 1424 [PIX_FMT_GRAY8] = {
ef9f7306 1425 .convert = rgb24_to_gray
524c6b63 1426 },
7e7e5940 1427 [PIX_FMT_PAL8] = {
7e6d70d0
FB
1428 .convert = rgb24_to_pal8
1429 },
c50c0bc8
FB
1430 [PIX_FMT_YUV444P] = {
1431 .convert = rgb24_to_yuv444p
1432 },
1433 [PIX_FMT_YUVJ420P] = {
1434 .convert = rgb24_to_yuvj420p
1435 },
1436 [PIX_FMT_YUVJ444P] = {
1437 .convert = rgb24_to_yuvj444p
1438 },
524c6b63
FB
1439 },
1440 [PIX_FMT_RGBA32] = {
7e7e5940
FB
1441 [PIX_FMT_RGB24] = {
1442 .convert = rgba32_to_rgb24
1443 },
1444 [PIX_FMT_RGB555] = {
1445 .convert = rgba32_to_rgb555
1446 },
1447 [PIX_FMT_PAL8] = {
1448 .convert = rgba32_to_pal8
1449 },
524c6b63 1450 [PIX_FMT_YUV420P] = {
ef9f7306 1451 .convert = rgba32_to_yuv420p
524c6b63 1452 },
69572401
FB
1453 [PIX_FMT_GRAY8] = {
1454 .convert = rgba32_to_gray
1455 },
524c6b63
FB
1456 },
1457 [PIX_FMT_BGR24] = {
7e7e5940
FB
1458 [PIX_FMT_RGB24] = {
1459 .convert = bgr24_to_rgb24
1460 },
524c6b63 1461 [PIX_FMT_YUV420P] = {
ef9f7306 1462 .convert = bgr24_to_yuv420p
524c6b63 1463 },
69572401
FB
1464 [PIX_FMT_GRAY8] = {
1465 .convert = bgr24_to_gray
1466 },
524c6b63
FB
1467 },
1468 [PIX_FMT_RGB555] = {
7e7e5940
FB
1469 [PIX_FMT_RGB24] = {
1470 .convert = rgb555_to_rgb24
1471 },
1472 [PIX_FMT_RGBA32] = {
1473 .convert = rgb555_to_rgba32
1474 },
524c6b63 1475 [PIX_FMT_YUV420P] = {
ef9f7306 1476 .convert = rgb555_to_yuv420p
524c6b63 1477 },
69572401
FB
1478 [PIX_FMT_GRAY8] = {
1479 .convert = rgb555_to_gray
1480 },
524c6b63
FB
1481 },
1482 [PIX_FMT_RGB565] = {
7e7e5940
FB
1483 [PIX_FMT_RGB24] = {
1484 .convert = rgb565_to_rgb24
1485 },
524c6b63 1486 [PIX_FMT_YUV420P] = {
ef9f7306 1487 .convert = rgb565_to_yuv420p
524c6b63 1488 },
69572401
FB
1489 [PIX_FMT_GRAY8] = {
1490 .convert = rgb565_to_gray
1491 },
524c6b63
FB
1492 },
1493 [PIX_FMT_GRAY8] = {
69572401
FB
1494 [PIX_FMT_RGB555] = {
1495 .convert = gray_to_rgb555
1496 },
1497 [PIX_FMT_RGB565] = {
1498 .convert = gray_to_rgb565
1499 },
524c6b63 1500 [PIX_FMT_RGB24] = {
ef9f7306 1501 .convert = gray_to_rgb24
524c6b63 1502 },
69572401
FB
1503 [PIX_FMT_BGR24] = {
1504 .convert = gray_to_bgr24
1505 },
1506 [PIX_FMT_RGBA32] = {
1507 .convert = gray_to_rgba32
1508 },
2a877875 1509 [PIX_FMT_MONOWHITE] = {
ef9f7306 1510 .convert = gray_to_monowhite
2a877875
FB
1511 },
1512 [PIX_FMT_MONOBLACK] = {
ef9f7306 1513 .convert = gray_to_monoblack
2a877875 1514 },
524c6b63
FB
1515 },
1516 [PIX_FMT_MONOWHITE] = {
2a877875 1517 [PIX_FMT_GRAY8] = {
ef9f7306 1518 .convert = monowhite_to_gray
524c6b63
FB
1519 },
1520 },
1521 [PIX_FMT_MONOBLACK] = {
2a877875 1522 [PIX_FMT_GRAY8] = {
ef9f7306 1523 .convert = monoblack_to_gray
524c6b63
FB
1524 },
1525 },
7e6d70d0
FB
1526 [PIX_FMT_PAL8] = {
1527 [PIX_FMT_RGB555] = {
1528 .convert = pal8_to_rgb555
1529 },
1530 [PIX_FMT_RGB565] = {
1531 .convert = pal8_to_rgb565
1532 },
1533 [PIX_FMT_BGR24] = {
1534 .convert = pal8_to_bgr24
1535 },
1536 [PIX_FMT_RGB24] = {
1537 .convert = pal8_to_rgb24
1538 },
1539 [PIX_FMT_RGBA32] = {
1540 .convert = pal8_to_rgba32
1541 },
1542 },
524c6b63
FB
1543};
1544
1545static int avpicture_alloc(AVPicture *picture,
1546 int pix_fmt, int width, int height)
1547{
5c91a675 1548 unsigned int size;
524c6b63
FB
1549 void *ptr;
1550
1551 size = avpicture_get_size(pix_fmt, width, height);
1552 if (size < 0)
1553 goto fail;
1554 ptr = av_malloc(size);
1555 if (!ptr)
1556 goto fail;
1557 avpicture_fill(picture, ptr, pix_fmt, width, height);
1558 return 0;
1559 fail:
1560 memset(picture, 0, sizeof(AVPicture));
1561 return -1;
1562}
1563
1564static void avpicture_free(AVPicture *picture)
1565{
8e1e6f31 1566 av_free(picture->data[0]);
524c6b63
FB
1567}
1568
c50c0bc8
FB
1569/* return true if yuv planar */
1570static inline int is_yuv_planar(PixFmtInfo *ps)
1571{
1572 return (ps->color_type == FF_COLOR_YUV ||
7e7e5940
FB
1573 ps->color_type == FF_COLOR_YUV_JPEG) &&
1574 ps->pixel_type == FF_PIXEL_PLANAR;
c50c0bc8
FB
1575}
1576
85c242d8
FB
1577/* XXX: always use linesize. Return -1 if not supported */
1578int img_convert(AVPicture *dst, int dst_pix_fmt,
524c6b63
FB
1579 AVPicture *src, int src_pix_fmt,
1580 int src_width, int src_height)
85c242d8 1581{
c50c0bc8 1582 static int inited;
2a877875 1583 int i, ret, dst_width, dst_height, int_pix_fmt;
524c6b63
FB
1584 PixFmtInfo *src_pix, *dst_pix;
1585 ConvertEntry *ce;
1586 AVPicture tmp1, *tmp = &tmp1;
1587
1588 if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
1589 dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
1590 return -1;
1591 if (src_width <= 0 || src_height <= 0)
1592 return 0;
69572401 1593
c50c0bc8
FB
1594 if (!inited) {
1595 inited = 1;
1596 img_convert_init();
1597 }
1598
524c6b63
FB
1599 dst_width = src_width;
1600 dst_height = src_height;
69572401 1601
524c6b63
FB
1602 dst_pix = &pix_fmt_info[dst_pix_fmt];
1603 src_pix = &pix_fmt_info[src_pix_fmt];
1604 if (src_pix_fmt == dst_pix_fmt) {
7e7e5940
FB
1605 /* no conversion needed: just copy */
1606 img_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
524c6b63
FB
1607 return 0;
1608 }
1609
1610 ce = &convert_table[src_pix_fmt][dst_pix_fmt];
1611 if (ce->convert) {
1612 /* specific convertion routine */
1613 ce->convert(dst, src, dst_width, dst_height);
1614 return 0;
1615 }
1616
524c6b63 1617 /* gray to YUV */
c50c0bc8 1618 if (is_yuv_planar(dst_pix) &&
b6147995 1619 src_pix_fmt == PIX_FMT_GRAY8) {
524c6b63
FB
1620 int w, h, y;
1621 uint8_t *d;
1622
b6147995 1623 if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
7e7e5940 1624 img_copy_plane(dst->data[0], dst->linesize[0],
b6147995
FB
1625 src->data[0], src->linesize[0],
1626 dst_width, dst_height);
1627 } else {
c50c0bc8
FB
1628 img_apply_table(dst->data[0], dst->linesize[0],
1629 src->data[0], src->linesize[0],
1630 dst_width, dst_height,
1631 y_jpeg_to_ccir);
b6147995 1632 }
524c6b63
FB
1633 /* fill U and V with 128 */
1634 w = dst_width;
1635 h = dst_height;
1636 w >>= dst_pix->x_chroma_shift;
1637 h >>= dst_pix->y_chroma_shift;
1638 for(i = 1; i <= 2; i++) {
1639 d = dst->data[i];
2a877875
FB
1640 for(y = 0; y< h; y++) {
1641 memset(d, 128, w);
524c6b63
FB
1642 d += dst->linesize[i];
1643 }
b71472eb 1644 }
524c6b63
FB
1645 return 0;
1646 }
1647
1648 /* YUV to gray */
c50c0bc8 1649 if (is_yuv_planar(src_pix) &&
b6147995
FB
1650 dst_pix_fmt == PIX_FMT_GRAY8) {
1651 if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
7e7e5940 1652 img_copy_plane(dst->data[0], dst->linesize[0],
b6147995
FB
1653 src->data[0], src->linesize[0],
1654 dst_width, dst_height);
1655 } else {
c50c0bc8
FB
1656 img_apply_table(dst->data[0], dst->linesize[0],
1657 src->data[0], src->linesize[0],
1658 dst_width, dst_height,
1659 y_ccir_to_jpeg);
b6147995 1660 }
524c6b63
FB
1661 return 0;
1662 }
1663
c50c0bc8
FB
1664 /* YUV to YUV planar */
1665 if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
e352ff08 1666 int x_shift, y_shift, w, h, xy_shift;
0c1a9eda 1667 void (*resize_func)(uint8_t *dst, int dst_wrap,
e352ff08 1668 const uint8_t *src, int src_wrap,
524c6b63
FB
1669 int width, int height);
1670
1671 /* compute chroma size of the smallest dimensions */
1672 w = dst_width;
1673 h = dst_height;
1674 if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
1675 w >>= dst_pix->x_chroma_shift;
1676 else
1677 w >>= src_pix->x_chroma_shift;
1678 if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
1679 h >>= dst_pix->y_chroma_shift;
1680 else
1681 h >>= src_pix->y_chroma_shift;
1682
1683 x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
1684 y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
e352ff08
FB
1685 xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
1686 /* there must be filters for conversion at least from and to
1687 YUV444 format */
1688 switch(xy_shift) {
1689 case 0x00:
7e7e5940 1690 resize_func = img_copy_plane;
e352ff08
FB
1691 break;
1692 case 0x10:
1693 resize_func = shrink21;
1694 break;
1695 case 0x20:
1696 resize_func = shrink41;
1697 break;
1698 case 0x01:
1699 resize_func = shrink12;
1700 break;
1701 case 0x11:
524c6b63 1702 resize_func = shrink22;
e352ff08
FB
1703 break;
1704 case 0x22:
1705 resize_func = shrink44;
1706 break;
1707 case 0xf0:
1708 resize_func = grow21;
1709 break;
1710 case 0xe0:
1711 resize_func = grow41;
1712 break;
1713 case 0xff:
524c6b63 1714 resize_func = grow22;
e352ff08
FB
1715 break;
1716 case 0xee:
1717 resize_func = grow44;
1718 break;
1719 case 0xf1:
524c6b63 1720 resize_func = conv411;
e352ff08
FB
1721 break;
1722 default:
524c6b63 1723 /* currently not handled */
e352ff08 1724 goto no_chroma_filter;
85c242d8 1725 }
524c6b63 1726
7e7e5940
FB
1727 img_copy_plane(dst->data[0], dst->linesize[0],
1728 src->data[0], src->linesize[0],
1729 dst_width, dst_height);
566986ee 1730
524c6b63 1731 for(i = 1;i <= 2; i++)
566986ee
MK
1732 resize_func(dst->data[i], dst->linesize[i],
1733 src->data[i], src->linesize[i],
185fdc54 1734 dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
c50c0bc8
FB
1735 /* if yuv color space conversion is needed, we do it here on
1736 the destination image */
1737 if (dst_pix->color_type != src_pix->color_type) {
1738 const uint8_t *y_table, *c_table;
1739 if (dst_pix->color_type == FF_COLOR_YUV) {
1740 y_table = y_jpeg_to_ccir;
1741 c_table = c_jpeg_to_ccir;
1742 } else {
1743 y_table = y_ccir_to_jpeg;
1744 c_table = c_ccir_to_jpeg;
1745 }
1746 img_apply_table(dst->data[0], dst->linesize[0],
1747 dst->data[0], dst->linesize[0],
1748 dst_width, dst_height,
1749 y_table);
1750
1751 for(i = 1;i <= 2; i++)
1752 img_apply_table(dst->data[i], dst->linesize[i],
1753 dst->data[i], dst->linesize[i],
1754 dst_width>>dst_pix->x_chroma_shift,
1755 dst_height>>dst_pix->y_chroma_shift,
1756 c_table);
1757 }
1758 return 0;
85c242d8 1759 }
e352ff08 1760 no_chroma_filter:
524c6b63 1761
2a877875 1762 /* try to use an intermediate format */
c50c0bc8
FB
1763 if (src_pix_fmt == PIX_FMT_YUV422 ||
1764 dst_pix_fmt == PIX_FMT_YUV422) {
1765 /* specific case: convert to YUV422P first */
1766 int_pix_fmt = PIX_FMT_YUV422P;
1767 } else if ((src_pix->color_type == FF_COLOR_GRAY &&
1768 src_pix_fmt != PIX_FMT_GRAY8) ||
1769 (dst_pix->color_type == FF_COLOR_GRAY &&
1770 dst_pix_fmt != PIX_FMT_GRAY8)) {
1771 /* gray8 is the normalized format */
2a877875 1772 int_pix_fmt = PIX_FMT_GRAY8;
c50c0bc8
FB
1773 } else if ((is_yuv_planar(src_pix) &&
1774 src_pix_fmt != PIX_FMT_YUV444P &&
1775 src_pix_fmt != PIX_FMT_YUVJ444P)) {
1776 /* yuv444 is the normalized format */
1777 if (src_pix->color_type == FF_COLOR_YUV_JPEG)
1778 int_pix_fmt = PIX_FMT_YUVJ444P;
1779 else
1780 int_pix_fmt = PIX_FMT_YUV444P;
1781 } else if ((is_yuv_planar(dst_pix) &&
1782 dst_pix_fmt != PIX_FMT_YUV444P &&
1783 dst_pix_fmt != PIX_FMT_YUVJ444P)) {
1784 /* yuv444 is the normalized format */
1785 if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
1786 int_pix_fmt = PIX_FMT_YUVJ444P;
1787 else
1788 int_pix_fmt = PIX_FMT_YUV444P;
2a877875 1789 } else {
c50c0bc8
FB
1790 /* the two formats are rgb or gray8 or yuv[j]444p */
1791 if (src_pix->is_alpha && dst_pix->is_alpha)
1792 int_pix_fmt = PIX_FMT_RGBA32;
1793 else
1794 int_pix_fmt = PIX_FMT_RGB24;
2a877875
FB
1795 }
1796 if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
1797 return -1;
1798 ret = -1;
1799 if (img_convert(tmp, int_pix_fmt,
1800 src, src_pix_fmt, src_width, src_height) < 0)
1801 goto fail1;
1802 if (img_convert(dst, dst_pix_fmt,
1803 tmp, int_pix_fmt, dst_width, dst_height) < 0)
1804 goto fail1;
1805 ret = 0;
1806 fail1:
1807 avpicture_free(tmp);
1808 return ret;
85c242d8
FB
1809}
1810
5981f4e6
F
1811
1812#ifdef HAVE_MMX
1813#define DEINT_INPLACE_LINE_LUM \
1814 movd_m2r(lum_m4[0],mm0);\
1815 movd_m2r(lum_m3[0],mm1);\
1816 movd_m2r(lum_m2[0],mm2);\
1817 movd_m2r(lum_m1[0],mm3);\
1818 movd_m2r(lum[0],mm4);\
1819 punpcklbw_r2r(mm7,mm0);\
1820 movd_r2m(mm2,lum_m4[0]);\
1821 punpcklbw_r2r(mm7,mm1);\
1822 punpcklbw_r2r(mm7,mm2);\
1823 punpcklbw_r2r(mm7,mm3);\
1824 punpcklbw_r2r(mm7,mm4);\
1825 paddw_r2r(mm3,mm1);\
1826 psllw_i2r(1,mm2);\
1827 paddw_r2r(mm4,mm0);\
1828 psllw_i2r(2,mm1);\
1829 paddw_r2r(mm6,mm2);\
1830 paddw_r2r(mm2,mm1);\
1831 psubusw_r2r(mm0,mm1);\
1832 psrlw_i2r(3,mm1);\
1833 packuswb_r2r(mm7,mm1);\
1834 movd_r2m(mm1,lum_m2[0]);
1835
1836#define DEINT_LINE_LUM \
1837 movd_m2r(lum_m4[0],mm0);\
1838 movd_m2r(lum_m3[0],mm1);\
1839 movd_m2r(lum_m2[0],mm2);\
1840 movd_m2r(lum_m1[0],mm3);\
1841 movd_m2r(lum[0],mm4);\
1842 punpcklbw_r2r(mm7,mm0);\
1843 punpcklbw_r2r(mm7,mm1);\
1844 punpcklbw_r2r(mm7,mm2);\
1845 punpcklbw_r2r(mm7,mm3);\
1846 punpcklbw_r2r(mm7,mm4);\
1847 paddw_r2r(mm3,mm1);\
1848 psllw_i2r(1,mm2);\
1849 paddw_r2r(mm4,mm0);\
1850 psllw_i2r(2,mm1);\
1851 paddw_r2r(mm6,mm2);\
1852 paddw_r2r(mm2,mm1);\
1853 psubusw_r2r(mm0,mm1);\
1854 psrlw_i2r(3,mm1);\
1855 packuswb_r2r(mm7,mm1);\
1856 movd_r2m(mm1,dst[0]);
1857#endif
1858
85c242d8 1859/* filter parameters: [-1 4 2 4 -1] // 8 */
0c1a9eda 1860static 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 1861 int size)
85c242d8 1862{
5981f4e6 1863#ifndef HAVE_MMX
0c1a9eda 1864 uint8_t *cm = cropTbl + MAX_NEG_CROP;
85c242d8 1865 int sum;
85c242d8
FB
1866
1867 for(;size > 0;size--) {
5981f4e6
F
1868 sum = -lum_m4[0];
1869 sum += lum_m3[0] << 2;
1870 sum += lum_m2[0] << 1;
1871 sum += lum_m1[0] << 2;
1872 sum += -lum[0];
85c242d8 1873 dst[0] = cm[(sum + 4) >> 3];
5981f4e6
F
1874 lum_m4++;
1875 lum_m3++;
1876 lum_m2++;
1877 lum_m1++;
1878 lum++;
85c242d8 1879 dst++;
85c242d8 1880 }
5981f4e6
F
1881#else
1882
782c5984
MN
1883 {
1884 mmx_t rounder;
1885 rounder.uw[0]=4;
1886 rounder.uw[1]=4;
1887 rounder.uw[2]=4;
1888 rounder.uw[3]=4;
1889 pxor_r2r(mm7,mm7);
1890 movq_m2r(rounder,mm6);
1891 }
5981f4e6
F
1892 for (;size > 3; size-=4) {
1893 DEINT_LINE_LUM
1894 lum_m4+=4;
1895 lum_m3+=4;
1896 lum_m2+=4;
1897 lum_m1+=4;
1898 lum+=4;
1899 dst+=4;
1900 }
1901#endif
1902}
0c1a9eda 1903static 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
1904 int size)
1905{
1906#ifndef HAVE_MMX
0c1a9eda 1907 uint8_t *cm = cropTbl + MAX_NEG_CROP;
5981f4e6
F
1908 int sum;
1909
1910 for(;size > 0;size--) {
1911 sum = -lum_m4[0];
1912 sum += lum_m3[0] << 2;
1913 sum += lum_m2[0] << 1;
1914 lum_m4[0]=lum_m2[0];
1915 sum += lum_m1[0] << 2;
1916 sum += -lum[0];
1917 lum_m2[0] = cm[(sum + 4) >> 3];
1918 lum_m4++;
1919 lum_m3++;
1920 lum_m2++;
1921 lum_m1++;
1922 lum++;
1923 }
1924#else
1925
782c5984
MN
1926 {
1927 mmx_t rounder;
1928 rounder.uw[0]=4;
1929 rounder.uw[1]=4;
1930 rounder.uw[2]=4;
1931 rounder.uw[3]=4;
1932 pxor_r2r(mm7,mm7);
1933 movq_m2r(rounder,mm6);
1934 }
5981f4e6
F
1935 for (;size > 3; size-=4) {
1936 DEINT_INPLACE_LINE_LUM
1937 lum_m4+=4;
1938 lum_m3+=4;
1939 lum_m2+=4;
1940 lum_m1+=4;
1941 lum+=4;
1942 }
1943#endif
85c242d8
FB
1944}
1945
1946/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
1947 top field is copied as is, but the bottom field is deinterlaced
1948 against the top field. */
0c1a9eda
ZK
1949static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
1950 uint8_t *src1, int src_wrap,
5981f4e6 1951 int width, int height)
85c242d8 1952{
0c1a9eda 1953 uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6
F
1954 int y;
1955
1956 src_m2 = src1;
1957 src_m1 = src1;
1958 src_0=&src_m1[src_wrap];
1959 src_p1=&src_0[src_wrap];
1960 src_p2=&src_p1[src_wrap];
1961 for(y=0;y<(height-2);y+=2) {
1962 memcpy(dst,src_m1,width);
85c242d8 1963 dst += dst_wrap;
5981f4e6
F
1964 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
1965 src_m2 = src_0;
1966 src_m1 = src_p1;
1967 src_0 = src_p2;
1968 src_p1 += 2*src_wrap;
1969 src_p2 += 2*src_wrap;
85c242d8 1970 dst += dst_wrap;
85c242d8 1971 }
5981f4e6
F
1972 memcpy(dst,src_m1,width);
1973 dst += dst_wrap;
1974 /* do last line */
1975 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
1976}
1977
0c1a9eda 1978static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
5981f4e6
F
1979 int width, int height)
1980{
0c1a9eda 1981 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6 1982 int y;
0c1a9eda
ZK
1983 uint8_t *buf;
1984 buf = (uint8_t*)av_malloc(width);
5981f4e6
F
1985
1986 src_m1 = src1;
1987 memcpy(buf,src_m1,width);
1988 src_0=&src_m1[src_wrap];
1989 src_p1=&src_0[src_wrap];
1990 src_p2=&src_p1[src_wrap];
1991 for(y=0;y<(height-2);y+=2) {
1992 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1993 src_m1 = src_p1;
1994 src_0 = src_p2;
1995 src_p1 += 2*src_wrap;
1996 src_p2 += 2*src_wrap;
1997 }
1998 /* do last line */
1999 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
6000abfa 2000 av_free(buf);
85c242d8
FB
2001}
2002
2003
5981f4e6 2004/* deinterlace - if not supported return -1 */
85c242d8 2005int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
de6d9b64
FB
2006 int pix_fmt, int width, int height)
2007{
85c242d8
FB
2008 int i;
2009
2010 if (pix_fmt != PIX_FMT_YUV420P &&
2011 pix_fmt != PIX_FMT_YUV422P &&
2012 pix_fmt != PIX_FMT_YUV444P)
2013 return -1;
5981f4e6 2014 if ((width & 3) != 0 || (height & 3) != 0)
85c242d8 2015 return -1;
5981f4e6 2016
85c242d8
FB
2017 for(i=0;i<3;i++) {
2018 if (i == 1) {
2019 switch(pix_fmt) {
2020 case PIX_FMT_YUV420P:
2021 width >>= 1;
2022 height >>= 1;
2023 break;
2024 case PIX_FMT_YUV422P:
2025 width >>= 1;
2026 break;
2027 default:
2028 break;
2029 }
2030 }
5981f4e6
F
2031 if (src == dst) {
2032 deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
85c242d8 2033 width, height);
5981f4e6
F
2034 } else {
2035 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
2036 src->data[i], src->linesize[i],
2037 width, height);
2038 }
de6d9b64 2039 }
5981f4e6
F
2040#ifdef HAVE_MMX
2041 emms();
2042#endif
85c242d8 2043 return 0;
de6d9b64 2044}
cd4af68a
ZK
2045
2046#undef FIX