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