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