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