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