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