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