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