]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/imgconvert.c
add YUV440P and YUVJ440P support
[frescor/ffmpeg.git] / libavcodec / imgconvert.c
1 /*
2  * Misc image conversion routines
3  * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file imgconvert.c
24  * misc image conversion routines
25  */
26
27 /* TODO:
28  * - write 'ffimg' program to test all the image related stuff
29  * - move all api to slice based system
30  * - integrate deinterlacing, postprocessing and scaling in the conversion process
31  */
32
33 #include "avcodec.h"
34 #include "dsputil.h"
35 #include "colorspace.h"
36
37 #ifdef HAVE_MMX
38 #include "i386/mmx.h"
39 #endif
40
41 #define xglue(x, y) x ## y
42 #define glue(x, y) xglue(x, y)
43
44 #define FF_COLOR_RGB      0 /**< RGB color space */
45 #define FF_COLOR_GRAY     1 /**< gray color space */
46 #define FF_COLOR_YUV      2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
47 #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
48
49 #define FF_PIXEL_PLANAR   0 /**< each channel has one component in AVPicture */
50 #define FF_PIXEL_PACKED   1 /**< only one components containing all the channels */
51 #define FF_PIXEL_PALETTE  2  /**< one components containing indexes for a palette */
52
53 typedef struct PixFmtInfo {
54     const char *name;
55     uint8_t nb_channels;     /**< number of channels (including alpha) */
56     uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
57     uint8_t pixel_type;      /**< pixel storage type (see FF_PIXEL_xxx constants) */
58     uint8_t is_alpha : 1;    /**< true if alpha can be specified */
59     uint8_t x_chroma_shift;  /**< X chroma subsampling factor is 2 ^ shift */
60     uint8_t y_chroma_shift;  /**< Y chroma subsampling factor is 2 ^ shift */
61     uint8_t depth;           /**< bit depth of the color components */
62 } PixFmtInfo;
63
64 /* this table gives more information about formats */
65 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
66     /* YUV formats */
67     [PIX_FMT_YUV420P] = {
68         .name = "yuv420p",
69         .nb_channels = 3,
70         .color_type = FF_COLOR_YUV,
71         .pixel_type = FF_PIXEL_PLANAR,
72         .depth = 8,
73         .x_chroma_shift = 1, .y_chroma_shift = 1,
74     },
75     [PIX_FMT_YUV422P] = {
76         .name = "yuv422p",
77         .nb_channels = 3,
78         .color_type = FF_COLOR_YUV,
79         .pixel_type = FF_PIXEL_PLANAR,
80         .depth = 8,
81         .x_chroma_shift = 1, .y_chroma_shift = 0,
82     },
83     [PIX_FMT_YUV444P] = {
84         .name = "yuv444p",
85         .nb_channels = 3,
86         .color_type = FF_COLOR_YUV,
87         .pixel_type = FF_PIXEL_PLANAR,
88         .depth = 8,
89         .x_chroma_shift = 0, .y_chroma_shift = 0,
90     },
91     [PIX_FMT_YUYV422] = {
92         .name = "yuyv422",
93         .nb_channels = 1,
94         .color_type = FF_COLOR_YUV,
95         .pixel_type = FF_PIXEL_PACKED,
96         .depth = 8,
97         .x_chroma_shift = 1, .y_chroma_shift = 0,
98     },
99     [PIX_FMT_UYVY422] = {
100         .name = "uyvy422",
101         .nb_channels = 1,
102         .color_type = FF_COLOR_YUV,
103         .pixel_type = FF_PIXEL_PACKED,
104         .depth = 8,
105         .x_chroma_shift = 1, .y_chroma_shift = 0,
106     },
107     [PIX_FMT_YUV410P] = {
108         .name = "yuv410p",
109         .nb_channels = 3,
110         .color_type = FF_COLOR_YUV,
111         .pixel_type = FF_PIXEL_PLANAR,
112         .depth = 8,
113         .x_chroma_shift = 2, .y_chroma_shift = 2,
114     },
115     [PIX_FMT_YUV411P] = {
116         .name = "yuv411p",
117         .nb_channels = 3,
118         .color_type = FF_COLOR_YUV,
119         .pixel_type = FF_PIXEL_PLANAR,
120         .depth = 8,
121         .x_chroma_shift = 2, .y_chroma_shift = 0,
122     },
123     [PIX_FMT_YUV440P] = {
124         .name = "yuv440p",
125         .nb_channels = 3,
126         .color_type = FF_COLOR_YUV,
127         .pixel_type = FF_PIXEL_PLANAR,
128         .depth = 8,
129         .x_chroma_shift = 0, .y_chroma_shift = 1,
130     },
131
132     /* JPEG YUV */
133     [PIX_FMT_YUVJ420P] = {
134         .name = "yuvj420p",
135         .nb_channels = 3,
136         .color_type = FF_COLOR_YUV_JPEG,
137         .pixel_type = FF_PIXEL_PLANAR,
138         .depth = 8,
139         .x_chroma_shift = 1, .y_chroma_shift = 1,
140     },
141     [PIX_FMT_YUVJ422P] = {
142         .name = "yuvj422p",
143         .nb_channels = 3,
144         .color_type = FF_COLOR_YUV_JPEG,
145         .pixel_type = FF_PIXEL_PLANAR,
146         .depth = 8,
147         .x_chroma_shift = 1, .y_chroma_shift = 0,
148     },
149     [PIX_FMT_YUVJ444P] = {
150         .name = "yuvj444p",
151         .nb_channels = 3,
152         .color_type = FF_COLOR_YUV_JPEG,
153         .pixel_type = FF_PIXEL_PLANAR,
154         .depth = 8,
155         .x_chroma_shift = 0, .y_chroma_shift = 0,
156     },
157     [PIX_FMT_YUVJ440P] = {
158         .name = "yuvj440p",
159         .nb_channels = 3,
160         .color_type = FF_COLOR_YUV_JPEG,
161         .pixel_type = FF_PIXEL_PLANAR,
162         .depth = 8,
163         .x_chroma_shift = 0, .y_chroma_shift = 1,
164     },
165
166     /* RGB formats */
167     [PIX_FMT_RGB24] = {
168         .name = "rgb24",
169         .nb_channels = 3,
170         .color_type = FF_COLOR_RGB,
171         .pixel_type = FF_PIXEL_PACKED,
172         .depth = 8,
173         .x_chroma_shift = 0, .y_chroma_shift = 0,
174     },
175     [PIX_FMT_BGR24] = {
176         .name = "bgr24",
177         .nb_channels = 3,
178         .color_type = FF_COLOR_RGB,
179         .pixel_type = FF_PIXEL_PACKED,
180         .depth = 8,
181         .x_chroma_shift = 0, .y_chroma_shift = 0,
182     },
183     [PIX_FMT_RGB32] = {
184         .name = "rgb32",
185         .nb_channels = 4, .is_alpha = 1,
186         .color_type = FF_COLOR_RGB,
187         .pixel_type = FF_PIXEL_PACKED,
188         .depth = 8,
189         .x_chroma_shift = 0, .y_chroma_shift = 0,
190     },
191     [PIX_FMT_RGB565] = {
192         .name = "rgb565",
193         .nb_channels = 3,
194         .color_type = FF_COLOR_RGB,
195         .pixel_type = FF_PIXEL_PACKED,
196         .depth = 5,
197         .x_chroma_shift = 0, .y_chroma_shift = 0,
198     },
199     [PIX_FMT_RGB555] = {
200         .name = "rgb555",
201         .nb_channels = 3,
202         .color_type = FF_COLOR_RGB,
203         .pixel_type = FF_PIXEL_PACKED,
204         .depth = 5,
205         .x_chroma_shift = 0, .y_chroma_shift = 0,
206     },
207
208     /* gray / mono formats */
209     [PIX_FMT_GRAY16BE] = {
210         .name = "gray16be",
211         .nb_channels = 1,
212         .color_type = FF_COLOR_GRAY,
213         .pixel_type = FF_PIXEL_PLANAR,
214         .depth = 16,
215     },
216     [PIX_FMT_GRAY16LE] = {
217         .name = "gray16le",
218         .nb_channels = 1,
219         .color_type = FF_COLOR_GRAY,
220         .pixel_type = FF_PIXEL_PLANAR,
221         .depth = 16,
222     },
223     [PIX_FMT_GRAY8] = {
224         .name = "gray",
225         .nb_channels = 1,
226         .color_type = FF_COLOR_GRAY,
227         .pixel_type = FF_PIXEL_PLANAR,
228         .depth = 8,
229     },
230     [PIX_FMT_MONOWHITE] = {
231         .name = "monow",
232         .nb_channels = 1,
233         .color_type = FF_COLOR_GRAY,
234         .pixel_type = FF_PIXEL_PLANAR,
235         .depth = 1,
236     },
237     [PIX_FMT_MONOBLACK] = {
238         .name = "monob",
239         .nb_channels = 1,
240         .color_type = FF_COLOR_GRAY,
241         .pixel_type = FF_PIXEL_PLANAR,
242         .depth = 1,
243     },
244
245     /* paletted formats */
246     [PIX_FMT_PAL8] = {
247         .name = "pal8",
248         .nb_channels = 4, .is_alpha = 1,
249         .color_type = FF_COLOR_RGB,
250         .pixel_type = FF_PIXEL_PALETTE,
251         .depth = 8,
252     },
253     [PIX_FMT_XVMC_MPEG2_MC] = {
254         .name = "xvmcmc",
255     },
256     [PIX_FMT_XVMC_MPEG2_IDCT] = {
257         .name = "xvmcidct",
258     },
259     [PIX_FMT_UYYVYY411] = {
260         .name = "uyyvyy411",
261         .nb_channels = 1,
262         .color_type = FF_COLOR_YUV,
263         .pixel_type = FF_PIXEL_PACKED,
264         .depth = 8,
265         .x_chroma_shift = 2, .y_chroma_shift = 0,
266     },
267     [PIX_FMT_BGR32] = {
268         .name = "bgr32",
269         .nb_channels = 4, .is_alpha = 1,
270         .color_type = FF_COLOR_RGB,
271         .pixel_type = FF_PIXEL_PACKED,
272         .depth = 8,
273         .x_chroma_shift = 0, .y_chroma_shift = 0,
274     },
275     [PIX_FMT_BGR565] = {
276         .name = "bgr565",
277         .nb_channels = 3,
278         .color_type = FF_COLOR_RGB,
279         .pixel_type = FF_PIXEL_PACKED,
280         .depth = 5,
281         .x_chroma_shift = 0, .y_chroma_shift = 0,
282     },
283     [PIX_FMT_BGR555] = {
284         .name = "bgr555",
285         .nb_channels = 3,
286         .color_type = FF_COLOR_RGB,
287         .pixel_type = FF_PIXEL_PACKED,
288         .depth = 5,
289         .x_chroma_shift = 0, .y_chroma_shift = 0,
290     },
291     [PIX_FMT_RGB8] = {
292         .name = "rgb8",
293         .nb_channels = 1,
294         .color_type = FF_COLOR_RGB,
295         .pixel_type = FF_PIXEL_PACKED,
296         .depth = 8,
297         .x_chroma_shift = 0, .y_chroma_shift = 0,
298     },
299     [PIX_FMT_RGB4] = {
300         .name = "rgb4",
301         .nb_channels = 1,
302         .color_type = FF_COLOR_RGB,
303         .pixel_type = FF_PIXEL_PACKED,
304         .depth = 4,
305         .x_chroma_shift = 0, .y_chroma_shift = 0,
306     },
307     [PIX_FMT_RGB4_BYTE] = {
308         .name = "rgb4_byte",
309         .nb_channels = 1,
310         .color_type = FF_COLOR_RGB,
311         .pixel_type = FF_PIXEL_PACKED,
312         .depth = 8,
313         .x_chroma_shift = 0, .y_chroma_shift = 0,
314     },
315     [PIX_FMT_BGR8] = {
316         .name = "bgr8",
317         .nb_channels = 1,
318         .color_type = FF_COLOR_RGB,
319         .pixel_type = FF_PIXEL_PACKED,
320         .depth = 8,
321         .x_chroma_shift = 0, .y_chroma_shift = 0,
322     },
323     [PIX_FMT_BGR4] = {
324         .name = "bgr4",
325         .nb_channels = 1,
326         .color_type = FF_COLOR_RGB,
327         .pixel_type = FF_PIXEL_PACKED,
328         .depth = 4,
329         .x_chroma_shift = 0, .y_chroma_shift = 0,
330     },
331     [PIX_FMT_BGR4_BYTE] = {
332         .name = "bgr4_byte",
333         .nb_channels = 1,
334         .color_type = FF_COLOR_RGB,
335         .pixel_type = FF_PIXEL_PACKED,
336         .depth = 8,
337         .x_chroma_shift = 0, .y_chroma_shift = 0,
338     },
339     [PIX_FMT_NV12] = {
340         .name = "nv12",
341         .nb_channels = 2,
342         .color_type = FF_COLOR_YUV,
343         .pixel_type = FF_PIXEL_PLANAR,
344         .depth = 8,
345         .x_chroma_shift = 1, .y_chroma_shift = 1,
346     },
347     [PIX_FMT_NV21] = {
348         .name = "nv12",
349         .nb_channels = 2,
350         .color_type = FF_COLOR_YUV,
351         .pixel_type = FF_PIXEL_PLANAR,
352         .depth = 8,
353         .x_chroma_shift = 1, .y_chroma_shift = 1,
354     },
355
356     [PIX_FMT_BGR32_1] = {
357         .name = "bgr32_1",
358         .nb_channels = 4, .is_alpha = 1,
359         .color_type = FF_COLOR_RGB,
360         .pixel_type = FF_PIXEL_PACKED,
361         .depth = 8,
362         .x_chroma_shift = 0, .y_chroma_shift = 0,
363     },
364     [PIX_FMT_RGB32_1] = {
365         .name = "rgb32_1",
366         .nb_channels = 4, .is_alpha = 1,
367         .color_type = FF_COLOR_RGB,
368         .pixel_type = FF_PIXEL_PACKED,
369         .depth = 8,
370         .x_chroma_shift = 0, .y_chroma_shift = 0,
371     },
372 };
373
374 void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
375 {
376     *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
377     *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
378 }
379
380 const char *avcodec_get_pix_fmt_name(int pix_fmt)
381 {
382     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
383         return "???";
384     else
385         return pix_fmt_info[pix_fmt].name;
386 }
387
388 enum PixelFormat avcodec_get_pix_fmt(const char* name)
389 {
390     int i;
391
392     for (i=0; i < PIX_FMT_NB; i++)
393          if (!strcmp(pix_fmt_info[i].name, name))
394              break;
395     return i;
396 }
397
398 void avcodec_pix_fmt_string (char *buf, int buf_size, int pix_fmt)
399 {
400     PixFmtInfo info= pix_fmt_info[pix_fmt];
401
402     char is_alpha_char= info.is_alpha ? 'y' : 'n';
403
404     /* print header */
405     if (pix_fmt < 0)
406         snprintf (buf, buf_size,
407                   "name      " " nb_channels" " depth" " is_alpha"
408             );
409     else
410         snprintf (buf, buf_size,
411                   "%-10s" "      %1d     " "   %2d " "     %c   ",
412                   info.name,
413                   info.nb_channels,
414                   info.depth,
415                   is_alpha_char
416             );
417 }
418
419 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
420                    int pix_fmt, int width, int height)
421 {
422     int size, w2, h2, size2;
423     const PixFmtInfo *pinfo;
424
425     if(avcodec_check_dimensions(NULL, width, height))
426         goto fail;
427
428     pinfo = &pix_fmt_info[pix_fmt];
429     size = width * height;
430     switch(pix_fmt) {
431     case PIX_FMT_YUV420P:
432     case PIX_FMT_YUV422P:
433     case PIX_FMT_YUV444P:
434     case PIX_FMT_YUV410P:
435     case PIX_FMT_YUV411P:
436     case PIX_FMT_YUV440P:
437     case PIX_FMT_YUVJ420P:
438     case PIX_FMT_YUVJ422P:
439     case PIX_FMT_YUVJ444P:
440     case PIX_FMT_YUVJ440P:
441         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
442         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
443         size2 = w2 * h2;
444         picture->data[0] = ptr;
445         picture->data[1] = picture->data[0] + size;
446         picture->data[2] = picture->data[1] + size2;
447         picture->linesize[0] = width;
448         picture->linesize[1] = w2;
449         picture->linesize[2] = w2;
450         return size + 2 * size2;
451     case PIX_FMT_NV12:
452     case PIX_FMT_NV21:
453         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
454         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
455         size2 = w2 * h2 * 2;
456         picture->data[0] = ptr;
457         picture->data[1] = picture->data[0] + size;
458         picture->data[2] = NULL;
459         picture->linesize[0] = width;
460         picture->linesize[1] = w2;
461         picture->linesize[2] = 0;
462         return size + 2 * size2;
463     case PIX_FMT_RGB24:
464     case PIX_FMT_BGR24:
465         picture->data[0] = ptr;
466         picture->data[1] = NULL;
467         picture->data[2] = NULL;
468         picture->linesize[0] = width * 3;
469         return size * 3;
470     case PIX_FMT_RGB32:
471     case PIX_FMT_BGR32:
472     case PIX_FMT_RGB32_1:
473     case PIX_FMT_BGR32_1:
474         picture->data[0] = ptr;
475         picture->data[1] = NULL;
476         picture->data[2] = NULL;
477         picture->linesize[0] = width * 4;
478         return size * 4;
479     case PIX_FMT_GRAY16BE:
480     case PIX_FMT_GRAY16LE:
481     case PIX_FMT_BGR555:
482     case PIX_FMT_BGR565:
483     case PIX_FMT_RGB555:
484     case PIX_FMT_RGB565:
485     case PIX_FMT_YUYV422:
486         picture->data[0] = ptr;
487         picture->data[1] = NULL;
488         picture->data[2] = NULL;
489         picture->linesize[0] = width * 2;
490         return size * 2;
491     case PIX_FMT_UYVY422:
492         picture->data[0] = ptr;
493         picture->data[1] = NULL;
494         picture->data[2] = NULL;
495         picture->linesize[0] = width * 2;
496         return size * 2;
497     case PIX_FMT_UYYVYY411:
498         picture->data[0] = ptr;
499         picture->data[1] = NULL;
500         picture->data[2] = NULL;
501         picture->linesize[0] = width + width/2;
502         return size + size/2;
503     case PIX_FMT_RGB8:
504     case PIX_FMT_BGR8:
505     case PIX_FMT_RGB4_BYTE:
506     case PIX_FMT_BGR4_BYTE:
507     case PIX_FMT_GRAY8:
508         picture->data[0] = ptr;
509         picture->data[1] = NULL;
510         picture->data[2] = NULL;
511         picture->linesize[0] = width;
512         return size;
513     case PIX_FMT_RGB4:
514     case PIX_FMT_BGR4:
515         picture->data[0] = ptr;
516         picture->data[1] = NULL;
517         picture->data[2] = NULL;
518         picture->linesize[0] = width / 2;
519         return size / 2;
520     case PIX_FMT_MONOWHITE:
521     case PIX_FMT_MONOBLACK:
522         picture->data[0] = ptr;
523         picture->data[1] = NULL;
524         picture->data[2] = NULL;
525         picture->linesize[0] = (width + 7) >> 3;
526         return picture->linesize[0] * height;
527     case PIX_FMT_PAL8:
528         size2 = (size + 3) & ~3;
529         picture->data[0] = ptr;
530         picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
531         picture->data[2] = NULL;
532         picture->linesize[0] = width;
533         picture->linesize[1] = 4;
534         return size2 + 256 * 4;
535     default:
536 fail:
537         picture->data[0] = NULL;
538         picture->data[1] = NULL;
539         picture->data[2] = NULL;
540         picture->data[3] = NULL;
541         return -1;
542     }
543 }
544
545 int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
546                      unsigned char *dest, int dest_size)
547 {
548     const PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
549     int i, j, w, h, data_planes;
550     const unsigned char* s;
551     int size = avpicture_get_size(pix_fmt, width, height);
552
553     if (size > dest_size || size < 0)
554         return -1;
555
556     if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
557         if (pix_fmt == PIX_FMT_YUYV422 ||
558             pix_fmt == PIX_FMT_UYVY422 ||
559             pix_fmt == PIX_FMT_BGR565 ||
560             pix_fmt == PIX_FMT_BGR555 ||
561             pix_fmt == PIX_FMT_RGB565 ||
562             pix_fmt == PIX_FMT_RGB555)
563             w = width * 2;
564         else if (pix_fmt == PIX_FMT_UYYVYY411)
565           w = width + width/2;
566         else if (pix_fmt == PIX_FMT_PAL8)
567           w = width;
568         else
569           w = width * (pf->depth * pf->nb_channels / 8);
570
571         data_planes = 1;
572         h = height;
573     } else {
574         data_planes = pf->nb_channels;
575         w = (width*pf->depth + 7)/8;
576         h = height;
577     }
578
579     for (i=0; i<data_planes; i++) {
580          if (i == 1) {
581              w = width >> pf->x_chroma_shift;
582              h = height >> pf->y_chroma_shift;
583          }
584          s = src->data[i];
585          for(j=0; j<h; j++) {
586              memcpy(dest, s, w);
587              dest += w;
588              s += src->linesize[i];
589          }
590     }
591
592     if (pf->pixel_type == FF_PIXEL_PALETTE)
593         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
594
595     return size;
596 }
597
598 int avpicture_get_size(int pix_fmt, int width, int height)
599 {
600     AVPicture dummy_pict;
601     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
602 }
603
604 int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
605                              int has_alpha)
606 {
607     const PixFmtInfo *pf, *ps;
608     int loss;
609
610     ps = &pix_fmt_info[src_pix_fmt];
611     pf = &pix_fmt_info[dst_pix_fmt];
612
613     /* compute loss */
614     loss = 0;
615     pf = &pix_fmt_info[dst_pix_fmt];
616     if (pf->depth < ps->depth ||
617         (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
618         loss |= FF_LOSS_DEPTH;
619     if (pf->x_chroma_shift > ps->x_chroma_shift ||
620         pf->y_chroma_shift > ps->y_chroma_shift)
621         loss |= FF_LOSS_RESOLUTION;
622     switch(pf->color_type) {
623     case FF_COLOR_RGB:
624         if (ps->color_type != FF_COLOR_RGB &&
625             ps->color_type != FF_COLOR_GRAY)
626             loss |= FF_LOSS_COLORSPACE;
627         break;
628     case FF_COLOR_GRAY:
629         if (ps->color_type != FF_COLOR_GRAY)
630             loss |= FF_LOSS_COLORSPACE;
631         break;
632     case FF_COLOR_YUV:
633         if (ps->color_type != FF_COLOR_YUV)
634             loss |= FF_LOSS_COLORSPACE;
635         break;
636     case FF_COLOR_YUV_JPEG:
637         if (ps->color_type != FF_COLOR_YUV_JPEG &&
638             ps->color_type != FF_COLOR_YUV &&
639             ps->color_type != FF_COLOR_GRAY)
640             loss |= FF_LOSS_COLORSPACE;
641         break;
642     default:
643         /* fail safe test */
644         if (ps->color_type != pf->color_type)
645             loss |= FF_LOSS_COLORSPACE;
646         break;
647     }
648     if (pf->color_type == FF_COLOR_GRAY &&
649         ps->color_type != FF_COLOR_GRAY)
650         loss |= FF_LOSS_CHROMA;
651     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
652         loss |= FF_LOSS_ALPHA;
653     if (pf->pixel_type == FF_PIXEL_PALETTE &&
654         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
655         loss |= FF_LOSS_COLORQUANT;
656     return loss;
657 }
658
659 static int avg_bits_per_pixel(int pix_fmt)
660 {
661     int bits;
662     const PixFmtInfo *pf;
663
664     pf = &pix_fmt_info[pix_fmt];
665     switch(pf->pixel_type) {
666     case FF_PIXEL_PACKED:
667         switch(pix_fmt) {
668         case PIX_FMT_YUYV422:
669         case PIX_FMT_UYVY422:
670         case PIX_FMT_RGB565:
671         case PIX_FMT_RGB555:
672         case PIX_FMT_BGR565:
673         case PIX_FMT_BGR555:
674             bits = 16;
675             break;
676         case PIX_FMT_UYYVYY411:
677             bits = 12;
678             break;
679         default:
680             bits = pf->depth * pf->nb_channels;
681             break;
682         }
683         break;
684     case FF_PIXEL_PLANAR:
685         if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
686             bits = pf->depth * pf->nb_channels;
687         } else {
688             bits = pf->depth + ((2 * pf->depth) >>
689                                 (pf->x_chroma_shift + pf->y_chroma_shift));
690         }
691         break;
692     case FF_PIXEL_PALETTE:
693         bits = 8;
694         break;
695     default:
696         bits = -1;
697         break;
698     }
699     return bits;
700 }
701
702 static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
703                                       int src_pix_fmt,
704                                       int has_alpha,
705                                       int loss_mask)
706 {
707     int dist, i, loss, min_dist, dst_pix_fmt;
708
709     /* find exact color match with smallest size */
710     dst_pix_fmt = -1;
711     min_dist = 0x7fffffff;
712     for(i = 0;i < PIX_FMT_NB; i++) {
713         if (pix_fmt_mask & (1 << i)) {
714             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
715             if (loss == 0) {
716                 dist = avg_bits_per_pixel(i);
717                 if (dist < min_dist) {
718                     min_dist = dist;
719                     dst_pix_fmt = i;
720                 }
721             }
722         }
723     }
724     return dst_pix_fmt;
725 }
726
727 int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
728                               int has_alpha, int *loss_ptr)
729 {
730     int dst_pix_fmt, loss_mask, i;
731     static const int loss_mask_order[] = {
732         ~0, /* no loss first */
733         ~FF_LOSS_ALPHA,
734         ~FF_LOSS_RESOLUTION,
735         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
736         ~FF_LOSS_COLORQUANT,
737         ~FF_LOSS_DEPTH,
738         0,
739     };
740
741     /* try with successive loss */
742     i = 0;
743     for(;;) {
744         loss_mask = loss_mask_order[i++];
745         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
746                                                  has_alpha, loss_mask);
747         if (dst_pix_fmt >= 0)
748             goto found;
749         if (loss_mask == 0)
750             break;
751     }
752     return -1;
753  found:
754     if (loss_ptr)
755         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
756     return dst_pix_fmt;
757 }
758
759 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
760                            const uint8_t *src, int src_wrap,
761                            int width, int height)
762 {
763     if((!dst) || (!src))
764         return;
765     for(;height > 0; height--) {
766         memcpy(dst, src, width);
767         dst += dst_wrap;
768         src += src_wrap;
769     }
770 }
771
772 void av_picture_copy(AVPicture *dst, const AVPicture *src,
773               int pix_fmt, int width, int height)
774 {
775     int bwidth, bits, i;
776     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
777
778     pf = &pix_fmt_info[pix_fmt];
779     switch(pf->pixel_type) {
780     case FF_PIXEL_PACKED:
781         switch(pix_fmt) {
782         case PIX_FMT_YUYV422:
783         case PIX_FMT_UYVY422:
784         case PIX_FMT_RGB565:
785         case PIX_FMT_RGB555:
786         case PIX_FMT_BGR565:
787         case PIX_FMT_BGR555:
788             bits = 16;
789             break;
790         case PIX_FMT_UYYVYY411:
791             bits = 12;
792             break;
793         default:
794             bits = pf->depth * pf->nb_channels;
795             break;
796         }
797         bwidth = (width * bits + 7) >> 3;
798         ff_img_copy_plane(dst->data[0], dst->linesize[0],
799                        src->data[0], src->linesize[0],
800                        bwidth, height);
801         break;
802     case FF_PIXEL_PLANAR:
803         for(i = 0; i < pf->nb_channels; i++) {
804             int w, h;
805             w = width;
806             h = height;
807             if (i == 1 || i == 2) {
808                 w >>= pf->x_chroma_shift;
809                 h >>= pf->y_chroma_shift;
810             }
811             bwidth = (w * pf->depth + 7) >> 3;
812             ff_img_copy_plane(dst->data[i], dst->linesize[i],
813                            src->data[i], src->linesize[i],
814                            bwidth, h);
815         }
816         break;
817     case FF_PIXEL_PALETTE:
818         ff_img_copy_plane(dst->data[0], dst->linesize[0],
819                        src->data[0], src->linesize[0],
820                        width, height);
821         /* copy the palette */
822         ff_img_copy_plane(dst->data[1], dst->linesize[1],
823                        src->data[1], src->linesize[1],
824                        4, 256);
825         break;
826     }
827 }
828
829 /* XXX: totally non optimized */
830
831 static void yuyv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
832                               int width, int height)
833 {
834     const uint8_t *p, *p1;
835     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
836     int w;
837
838     p1 = src->data[0];
839     lum1 = dst->data[0];
840     cb1 = dst->data[1];
841     cr1 = dst->data[2];
842
843     for(;height >= 1; height -= 2) {
844         p = p1;
845         lum = lum1;
846         cb = cb1;
847         cr = cr1;
848         for(w = width; w >= 2; w -= 2) {
849             lum[0] = p[0];
850             cb[0] = p[1];
851             lum[1] = p[2];
852             cr[0] = p[3];
853             p += 4;
854             lum += 2;
855             cb++;
856             cr++;
857         }
858         if (w) {
859             lum[0] = p[0];
860             cb[0] = p[1];
861             cr[0] = p[3];
862             cb++;
863             cr++;
864         }
865         p1 += src->linesize[0];
866         lum1 += dst->linesize[0];
867         if (height>1) {
868             p = p1;
869             lum = lum1;
870             for(w = width; w >= 2; w -= 2) {
871                 lum[0] = p[0];
872                 lum[1] = p[2];
873                 p += 4;
874                 lum += 2;
875             }
876             if (w) {
877                 lum[0] = p[0];
878             }
879             p1 += src->linesize[0];
880             lum1 += dst->linesize[0];
881         }
882         cb1 += dst->linesize[1];
883         cr1 += dst->linesize[2];
884     }
885 }
886
887 static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src,
888                               int width, int height)
889 {
890     const uint8_t *p, *p1;
891     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
892     int w;
893
894     p1 = src->data[0];
895
896     lum1 = dst->data[0];
897     cb1 = dst->data[1];
898     cr1 = dst->data[2];
899
900     for(;height >= 1; height -= 2) {
901         p = p1;
902         lum = lum1;
903         cb = cb1;
904         cr = cr1;
905         for(w = width; w >= 2; w -= 2) {
906             lum[0] = p[1];
907             cb[0] = p[0];
908             lum[1] = p[3];
909             cr[0] = p[2];
910             p += 4;
911             lum += 2;
912             cb++;
913             cr++;
914         }
915         if (w) {
916             lum[0] = p[1];
917             cb[0] = p[0];
918             cr[0] = p[2];
919             cb++;
920             cr++;
921         }
922         p1 += src->linesize[0];
923         lum1 += dst->linesize[0];
924         if (height>1) {
925             p = p1;
926             lum = lum1;
927             for(w = width; w >= 2; w -= 2) {
928                 lum[0] = p[1];
929                 lum[1] = p[3];
930                 p += 4;
931                 lum += 2;
932             }
933             if (w) {
934                 lum[0] = p[1];
935             }
936             p1 += src->linesize[0];
937             lum1 += dst->linesize[0];
938         }
939         cb1 += dst->linesize[1];
940         cr1 += dst->linesize[2];
941     }
942 }
943
944
945 static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src,
946                               int width, int height)
947 {
948     const uint8_t *p, *p1;
949     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
950     int w;
951
952     p1 = src->data[0];
953     lum1 = dst->data[0];
954     cb1 = dst->data[1];
955     cr1 = dst->data[2];
956     for(;height > 0; height--) {
957         p = p1;
958         lum = lum1;
959         cb = cb1;
960         cr = cr1;
961         for(w = width; w >= 2; w -= 2) {
962             lum[0] = p[1];
963             cb[0] = p[0];
964             lum[1] = p[3];
965             cr[0] = p[2];
966             p += 4;
967             lum += 2;
968             cb++;
969             cr++;
970         }
971         p1 += src->linesize[0];
972         lum1 += dst->linesize[0];
973         cb1 += dst->linesize[1];
974         cr1 += dst->linesize[2];
975     }
976 }
977
978
979 static void yuyv422_to_yuv422p(AVPicture *dst, const AVPicture *src,
980                               int width, int height)
981 {
982     const uint8_t *p, *p1;
983     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
984     int w;
985
986     p1 = src->data[0];
987     lum1 = dst->data[0];
988     cb1 = dst->data[1];
989     cr1 = dst->data[2];
990     for(;height > 0; height--) {
991         p = p1;
992         lum = lum1;
993         cb = cb1;
994         cr = cr1;
995         for(w = width; w >= 2; w -= 2) {
996             lum[0] = p[0];
997             cb[0] = p[1];
998             lum[1] = p[2];
999             cr[0] = p[3];
1000             p += 4;
1001             lum += 2;
1002             cb++;
1003             cr++;
1004         }
1005         p1 += src->linesize[0];
1006         lum1 += dst->linesize[0];
1007         cb1 += dst->linesize[1];
1008         cr1 += dst->linesize[2];
1009     }
1010 }
1011
1012 static void yuv422p_to_yuyv422(AVPicture *dst, const AVPicture *src,
1013                               int width, int height)
1014 {
1015     uint8_t *p, *p1;
1016     const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1017     int w;
1018
1019     p1 = dst->data[0];
1020     lum1 = src->data[0];
1021     cb1 = src->data[1];
1022     cr1 = src->data[2];
1023     for(;height > 0; height--) {
1024         p = p1;
1025         lum = lum1;
1026         cb = cb1;
1027         cr = cr1;
1028         for(w = width; w >= 2; w -= 2) {
1029             p[0] = lum[0];
1030             p[1] = cb[0];
1031             p[2] = lum[1];
1032             p[3] = cr[0];
1033             p += 4;
1034             lum += 2;
1035             cb++;
1036             cr++;
1037         }
1038         p1 += dst->linesize[0];
1039         lum1 += src->linesize[0];
1040         cb1 += src->linesize[1];
1041         cr1 += src->linesize[2];
1042     }
1043 }
1044
1045 static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
1046                               int width, int height)
1047 {
1048     uint8_t *p, *p1;
1049     const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1050     int w;
1051
1052     p1 = dst->data[0];
1053     lum1 = src->data[0];
1054     cb1 = src->data[1];
1055     cr1 = src->data[2];
1056     for(;height > 0; height--) {
1057         p = p1;
1058         lum = lum1;
1059         cb = cb1;
1060         cr = cr1;
1061         for(w = width; w >= 2; w -= 2) {
1062             p[1] = lum[0];
1063             p[0] = cb[0];
1064             p[3] = lum[1];
1065             p[2] = cr[0];
1066             p += 4;
1067             lum += 2;
1068             cb++;
1069             cr++;
1070         }
1071         p1 += dst->linesize[0];
1072         lum1 += src->linesize[0];
1073         cb1 += src->linesize[1];
1074         cr1 += src->linesize[2];
1075     }
1076 }
1077
1078 static void uyyvyy411_to_yuv411p(AVPicture *dst, const AVPicture *src,
1079                               int width, int height)
1080 {
1081     const uint8_t *p, *p1;
1082     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1083     int w;
1084
1085     p1 = src->data[0];
1086     lum1 = dst->data[0];
1087     cb1 = dst->data[1];
1088     cr1 = dst->data[2];
1089     for(;height > 0; height--) {
1090         p = p1;
1091         lum = lum1;
1092         cb = cb1;
1093         cr = cr1;
1094         for(w = width; w >= 4; w -= 4) {
1095             cb[0] = p[0];
1096             lum[0] = p[1];
1097             lum[1] = p[2];
1098             cr[0] = p[3];
1099             lum[2] = p[4];
1100             lum[3] = p[5];
1101             p += 6;
1102             lum += 4;
1103             cb++;
1104             cr++;
1105         }
1106         p1 += src->linesize[0];
1107         lum1 += dst->linesize[0];
1108         cb1 += dst->linesize[1];
1109         cr1 += dst->linesize[2];
1110     }
1111 }
1112
1113
1114 static void yuv420p_to_yuyv422(AVPicture *dst, const AVPicture *src,
1115                               int width, int height)
1116 {
1117     int w, h;
1118     uint8_t *line1, *line2, *linesrc = dst->data[0];
1119     uint8_t *lum1, *lum2, *lumsrc = src->data[0];
1120     uint8_t *cb1, *cb2 = src->data[1];
1121     uint8_t *cr1, *cr2 = src->data[2];
1122
1123     for(h = height / 2; h--;) {
1124         line1 = linesrc;
1125         line2 = linesrc + dst->linesize[0];
1126
1127         lum1 = lumsrc;
1128         lum2 = lumsrc + src->linesize[0];
1129
1130         cb1 = cb2;
1131         cr1 = cr2;
1132
1133         for(w = width / 2; w--;) {
1134                 *line1++ = *lum1++; *line2++ = *lum2++;
1135                 *line1++ =          *line2++ = *cb1++;
1136                 *line1++ = *lum1++; *line2++ = *lum2++;
1137                 *line1++ =          *line2++ = *cr1++;
1138         }
1139
1140         linesrc += dst->linesize[0] * 2;
1141         lumsrc += src->linesize[0] * 2;
1142         cb2 += src->linesize[1];
1143         cr2 += src->linesize[2];
1144     }
1145 }
1146
1147 static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src,
1148                               int width, int height)
1149 {
1150     int w, h;
1151     uint8_t *line1, *line2, *linesrc = dst->data[0];
1152     uint8_t *lum1, *lum2, *lumsrc = src->data[0];
1153     uint8_t *cb1, *cb2 = src->data[1];
1154     uint8_t *cr1, *cr2 = src->data[2];
1155
1156     for(h = height / 2; h--;) {
1157         line1 = linesrc;
1158         line2 = linesrc + dst->linesize[0];
1159
1160         lum1 = lumsrc;
1161         lum2 = lumsrc + src->linesize[0];
1162
1163         cb1 = cb2;
1164         cr1 = cr2;
1165
1166         for(w = width / 2; w--;) {
1167                 *line1++ =          *line2++ = *cb1++;
1168                 *line1++ = *lum1++; *line2++ = *lum2++;
1169                 *line1++ =          *line2++ = *cr1++;
1170                 *line1++ = *lum1++; *line2++ = *lum2++;
1171         }
1172
1173         linesrc += dst->linesize[0] * 2;
1174         lumsrc += src->linesize[0] * 2;
1175         cb2 += src->linesize[1];
1176         cr2 += src->linesize[2];
1177     }
1178 }
1179
1180 static uint8_t y_ccir_to_jpeg[256];
1181 static uint8_t y_jpeg_to_ccir[256];
1182 static uint8_t c_ccir_to_jpeg[256];
1183 static uint8_t c_jpeg_to_ccir[256];
1184
1185 /* init various conversion tables */
1186 static void img_convert_init(void)
1187 {
1188     int i;
1189     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
1190
1191     for(i = 0;i < 256; i++) {
1192         y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
1193         y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
1194         c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
1195         c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
1196     }
1197 }
1198
1199 /* apply to each pixel the given table */
1200 static void img_apply_table(uint8_t *dst, int dst_wrap,
1201                             const uint8_t *src, int src_wrap,
1202                             int width, int height, const uint8_t *table1)
1203 {
1204     int n;
1205     const uint8_t *s;
1206     uint8_t *d;
1207     const uint8_t *table;
1208
1209     table = table1;
1210     for(;height > 0; height--) {
1211         s = src;
1212         d = dst;
1213         n = width;
1214         while (n >= 4) {
1215             d[0] = table[s[0]];
1216             d[1] = table[s[1]];
1217             d[2] = table[s[2]];
1218             d[3] = table[s[3]];
1219             d += 4;
1220             s += 4;
1221             n -= 4;
1222         }
1223         while (n > 0) {
1224             d[0] = table[s[0]];
1225             d++;
1226             s++;
1227             n--;
1228         }
1229         dst += dst_wrap;
1230         src += src_wrap;
1231     }
1232 }
1233
1234 /* XXX: use generic filter ? */
1235 /* XXX: in most cases, the sampling position is incorrect */
1236
1237 /* 4x1 -> 1x1 */
1238 static void shrink41(uint8_t *dst, int dst_wrap,
1239                      const uint8_t *src, int src_wrap,
1240                      int width, int height)
1241 {
1242     int w;
1243     const uint8_t *s;
1244     uint8_t *d;
1245
1246     for(;height > 0; height--) {
1247         s = src;
1248         d = dst;
1249         for(w = width;w > 0; w--) {
1250             d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
1251             s += 4;
1252             d++;
1253         }
1254         src += src_wrap;
1255         dst += dst_wrap;
1256     }
1257 }
1258
1259 /* 2x1 -> 1x1 */
1260 static void shrink21(uint8_t *dst, int dst_wrap,
1261                      const uint8_t *src, int src_wrap,
1262                      int width, int height)
1263 {
1264     int w;
1265     const uint8_t *s;
1266     uint8_t *d;
1267
1268     for(;height > 0; height--) {
1269         s = src;
1270         d = dst;
1271         for(w = width;w > 0; w--) {
1272             d[0] = (s[0] + s[1]) >> 1;
1273             s += 2;
1274             d++;
1275         }
1276         src += src_wrap;
1277         dst += dst_wrap;
1278     }
1279 }
1280
1281 /* 1x2 -> 1x1 */
1282 static void shrink12(uint8_t *dst, int dst_wrap,
1283                      const uint8_t *src, int src_wrap,
1284                      int width, int height)
1285 {
1286     int w;
1287     uint8_t *d;
1288     const uint8_t *s1, *s2;
1289
1290     for(;height > 0; height--) {
1291         s1 = src;
1292         s2 = s1 + src_wrap;
1293         d = dst;
1294         for(w = width;w >= 4; w-=4) {
1295             d[0] = (s1[0] + s2[0]) >> 1;
1296             d[1] = (s1[1] + s2[1]) >> 1;
1297             d[2] = (s1[2] + s2[2]) >> 1;
1298             d[3] = (s1[3] + s2[3]) >> 1;
1299             s1 += 4;
1300             s2 += 4;
1301             d += 4;
1302         }
1303         for(;w > 0; w--) {
1304             d[0] = (s1[0] + s2[0]) >> 1;
1305             s1++;
1306             s2++;
1307             d++;
1308         }
1309         src += 2 * src_wrap;
1310         dst += dst_wrap;
1311     }
1312 }
1313
1314 /* 2x2 -> 1x1 */
1315 void ff_shrink22(uint8_t *dst, int dst_wrap,
1316                      const uint8_t *src, int src_wrap,
1317                      int width, int height)
1318 {
1319     int w;
1320     const uint8_t *s1, *s2;
1321     uint8_t *d;
1322
1323     for(;height > 0; height--) {
1324         s1 = src;
1325         s2 = s1 + src_wrap;
1326         d = dst;
1327         for(w = width;w >= 4; w-=4) {
1328             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
1329             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
1330             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
1331             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
1332             s1 += 8;
1333             s2 += 8;
1334             d += 4;
1335         }
1336         for(;w > 0; w--) {
1337             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
1338             s1 += 2;
1339             s2 += 2;
1340             d++;
1341         }
1342         src += 2 * src_wrap;
1343         dst += dst_wrap;
1344     }
1345 }
1346
1347 /* 4x4 -> 1x1 */
1348 void ff_shrink44(uint8_t *dst, int dst_wrap,
1349                      const uint8_t *src, int src_wrap,
1350                      int width, int height)
1351 {
1352     int w;
1353     const uint8_t *s1, *s2, *s3, *s4;
1354     uint8_t *d;
1355
1356     for(;height > 0; height--) {
1357         s1 = src;
1358         s2 = s1 + src_wrap;
1359         s3 = s2 + src_wrap;
1360         s4 = s3 + src_wrap;
1361         d = dst;
1362         for(w = width;w > 0; w--) {
1363             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
1364                     s2[0] + s2[1] + s2[2] + s2[3] +
1365                     s3[0] + s3[1] + s3[2] + s3[3] +
1366                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
1367             s1 += 4;
1368             s2 += 4;
1369             s3 += 4;
1370             s4 += 4;
1371             d++;
1372         }
1373         src += 4 * src_wrap;
1374         dst += dst_wrap;
1375     }
1376 }
1377
1378 /* 8x8 -> 1x1 */
1379 void ff_shrink88(uint8_t *dst, int dst_wrap,
1380                      const uint8_t *src, int src_wrap,
1381                      int width, int height)
1382 {
1383     int w, i;
1384
1385     for(;height > 0; height--) {
1386         for(w = width;w > 0; w--) {
1387             int tmp=0;
1388             for(i=0; i<8; i++){
1389                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
1390                 src += src_wrap;
1391             }
1392             *(dst++) = (tmp + 32)>>6;
1393             src += 8 - 8*src_wrap;
1394         }
1395         src += 8*src_wrap - 8*width;
1396         dst += dst_wrap - width;
1397     }
1398 }
1399
1400 static void grow21_line(uint8_t *dst, const uint8_t *src,
1401                         int width)
1402 {
1403     int w;
1404     const uint8_t *s1;
1405     uint8_t *d;
1406
1407     s1 = src;
1408     d = dst;
1409     for(w = width;w >= 4; w-=4) {
1410         d[1] = d[0] = s1[0];
1411         d[3] = d[2] = s1[1];
1412         s1 += 2;
1413         d += 4;
1414     }
1415     for(;w >= 2; w -= 2) {
1416         d[1] = d[0] = s1[0];
1417         s1 ++;
1418         d += 2;
1419     }
1420     /* only needed if width is not a multiple of two */
1421     /* XXX: veryfy that */
1422     if (w) {
1423         d[0] = s1[0];
1424     }
1425 }
1426
1427 static void grow41_line(uint8_t *dst, const uint8_t *src,
1428                         int width)
1429 {
1430     int w, v;
1431     const uint8_t *s1;
1432     uint8_t *d;
1433
1434     s1 = src;
1435     d = dst;
1436     for(w = width;w >= 4; w-=4) {
1437         v = s1[0];
1438         d[0] = v;
1439         d[1] = v;
1440         d[2] = v;
1441         d[3] = v;
1442         s1 ++;
1443         d += 4;
1444     }
1445 }
1446
1447 /* 1x1 -> 2x1 */
1448 static void grow21(uint8_t *dst, int dst_wrap,
1449                    const uint8_t *src, int src_wrap,
1450                    int width, int height)
1451 {
1452     for(;height > 0; height--) {
1453         grow21_line(dst, src, width);
1454         src += src_wrap;
1455         dst += dst_wrap;
1456     }
1457 }
1458
1459 /* 1x1 -> 1x2 */
1460 static void grow12(uint8_t *dst, int dst_wrap,
1461                    const uint8_t *src, int src_wrap,
1462                    int width, int height)
1463 {
1464     for(;height > 0; height-=2) {
1465         memcpy(dst, src, width);
1466         dst += dst_wrap;
1467         memcpy(dst, src, width);
1468         dst += dst_wrap;
1469         src += src_wrap;
1470     }
1471 }
1472
1473 /* 1x1 -> 2x2 */
1474 static void grow22(uint8_t *dst, int dst_wrap,
1475                    const uint8_t *src, int src_wrap,
1476                    int width, int height)
1477 {
1478     for(;height > 0; height--) {
1479         grow21_line(dst, src, width);
1480         if (height%2)
1481             src += src_wrap;
1482         dst += dst_wrap;
1483     }
1484 }
1485
1486 /* 1x1 -> 4x1 */
1487 static void grow41(uint8_t *dst, int dst_wrap,
1488                    const uint8_t *src, int src_wrap,
1489                    int width, int height)
1490 {
1491     for(;height > 0; height--) {
1492         grow41_line(dst, src, width);
1493         src += src_wrap;
1494         dst += dst_wrap;
1495     }
1496 }
1497
1498 /* 1x1 -> 4x4 */
1499 static void grow44(uint8_t *dst, int dst_wrap,
1500                    const uint8_t *src, int src_wrap,
1501                    int width, int height)
1502 {
1503     for(;height > 0; height--) {
1504         grow41_line(dst, src, width);
1505         if ((height & 3) == 1)
1506             src += src_wrap;
1507         dst += dst_wrap;
1508     }
1509 }
1510
1511 /* 1x2 -> 2x1 */
1512 static void conv411(uint8_t *dst, int dst_wrap,
1513                     const uint8_t *src, int src_wrap,
1514                     int width, int height)
1515 {
1516     int w, c;
1517     const uint8_t *s1, *s2;
1518     uint8_t *d;
1519
1520     width>>=1;
1521
1522     for(;height > 0; height--) {
1523         s1 = src;
1524         s2 = src + src_wrap;
1525         d = dst;
1526         for(w = width;w > 0; w--) {
1527             c = (s1[0] + s2[0]) >> 1;
1528             d[0] = c;
1529             d[1] = c;
1530             s1++;
1531             s2++;
1532             d += 2;
1533         }
1534         src += src_wrap * 2;
1535         dst += dst_wrap;
1536     }
1537 }
1538
1539 /* XXX: add jpeg quantize code */
1540
1541 #define TRANSP_INDEX (6*6*6)
1542
1543 /* this is maybe slow, but allows for extensions */
1544 static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
1545 {
1546     return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
1547 }
1548
1549 static void build_rgb_palette(uint8_t *palette, int has_alpha)
1550 {
1551     uint32_t *pal;
1552     static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
1553     int i, r, g, b;
1554
1555     pal = (uint32_t *)palette;
1556     i = 0;
1557     for(r = 0; r < 6; r++) {
1558         for(g = 0; g < 6; g++) {
1559             for(b = 0; b < 6; b++) {
1560                 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
1561                     (pal_value[g] << 8) | pal_value[b];
1562             }
1563         }
1564     }
1565     if (has_alpha)
1566         pal[i++] = 0;
1567     while (i < 256)
1568         pal[i++] = 0xff000000;
1569 }
1570
1571 /* copy bit n to bits 0 ... n - 1 */
1572 static inline unsigned int bitcopy_n(unsigned int a, int n)
1573 {
1574     int mask;
1575     mask = (1 << n) - 1;
1576     return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
1577 }
1578
1579 /* rgb555 handling */
1580
1581 #define RGB_NAME rgb555
1582
1583 #define RGB_IN(r, g, b, s)\
1584 {\
1585     unsigned int v = ((const uint16_t *)(s))[0];\
1586     r = bitcopy_n(v >> (10 - 3), 3);\
1587     g = bitcopy_n(v >> (5 - 3), 3);\
1588     b = bitcopy_n(v << 3, 3);\
1589 }
1590
1591
1592 #define RGB_OUT(d, r, g, b)\
1593 {\
1594     ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);\
1595 }
1596
1597 #define BPP 2
1598
1599 #include "imgconvert_template.h"
1600
1601 /* rgb565 handling */
1602
1603 #define RGB_NAME rgb565
1604
1605 #define RGB_IN(r, g, b, s)\
1606 {\
1607     unsigned int v = ((const uint16_t *)(s))[0];\
1608     r = bitcopy_n(v >> (11 - 3), 3);\
1609     g = bitcopy_n(v >> (5 - 2), 2);\
1610     b = bitcopy_n(v << 3, 3);\
1611 }
1612
1613 #define RGB_OUT(d, r, g, b)\
1614 {\
1615     ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
1616 }
1617
1618 #define BPP 2
1619
1620 #include "imgconvert_template.h"
1621
1622 /* bgr24 handling */
1623
1624 #define RGB_NAME bgr24
1625
1626 #define RGB_IN(r, g, b, s)\
1627 {\
1628     b = (s)[0];\
1629     g = (s)[1];\
1630     r = (s)[2];\
1631 }
1632
1633 #define RGB_OUT(d, r, g, b)\
1634 {\
1635     (d)[0] = b;\
1636     (d)[1] = g;\
1637     (d)[2] = r;\
1638 }
1639
1640 #define BPP 3
1641
1642 #include "imgconvert_template.h"
1643
1644 #undef RGB_IN
1645 #undef RGB_OUT
1646 #undef BPP
1647
1648 /* rgb24 handling */
1649
1650 #define RGB_NAME rgb24
1651 #define FMT_RGB24
1652
1653 #define RGB_IN(r, g, b, s)\
1654 {\
1655     r = (s)[0];\
1656     g = (s)[1];\
1657     b = (s)[2];\
1658 }
1659
1660 #define RGB_OUT(d, r, g, b)\
1661 {\
1662     (d)[0] = r;\
1663     (d)[1] = g;\
1664     (d)[2] = b;\
1665 }
1666
1667 #define BPP 3
1668
1669 #include "imgconvert_template.h"
1670
1671 /* rgb32 handling */
1672
1673 #define RGB_NAME rgb32
1674 #define FMT_RGB32
1675
1676 #define RGB_IN(r, g, b, s)\
1677 {\
1678     unsigned int v = ((const uint32_t *)(s))[0];\
1679     r = (v >> 16) & 0xff;\
1680     g = (v >> 8) & 0xff;\
1681     b = v & 0xff;\
1682 }
1683
1684 #define RGBA_IN(r, g, b, a, s)\
1685 {\
1686     unsigned int v = ((const uint32_t *)(s))[0];\
1687     a = (v >> 24) & 0xff;\
1688     r = (v >> 16) & 0xff;\
1689     g = (v >> 8) & 0xff;\
1690     b = v & 0xff;\
1691 }
1692
1693 #define RGBA_OUT(d, r, g, b, a)\
1694 {\
1695     ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
1696 }
1697
1698 #define BPP 4
1699
1700 #include "imgconvert_template.h"
1701
1702 static void mono_to_gray(AVPicture *dst, const AVPicture *src,
1703                          int width, int height, int xor_mask)
1704 {
1705     const unsigned char *p;
1706     unsigned char *q;
1707     int v, dst_wrap, src_wrap;
1708     int y, w;
1709
1710     p = src->data[0];
1711     src_wrap = src->linesize[0] - ((width + 7) >> 3);
1712
1713     q = dst->data[0];
1714     dst_wrap = dst->linesize[0] - width;
1715     for(y=0;y<height;y++) {
1716         w = width;
1717         while (w >= 8) {
1718             v = *p++ ^ xor_mask;
1719             q[0] = -(v >> 7);
1720             q[1] = -((v >> 6) & 1);
1721             q[2] = -((v >> 5) & 1);
1722             q[3] = -((v >> 4) & 1);
1723             q[4] = -((v >> 3) & 1);
1724             q[5] = -((v >> 2) & 1);
1725             q[6] = -((v >> 1) & 1);
1726             q[7] = -((v >> 0) & 1);
1727             w -= 8;
1728             q += 8;
1729         }
1730         if (w > 0) {
1731             v = *p++ ^ xor_mask;
1732             do {
1733                 q[0] = -((v >> 7) & 1);
1734                 q++;
1735                 v <<= 1;
1736             } while (--w);
1737         }
1738         p += src_wrap;
1739         q += dst_wrap;
1740     }
1741 }
1742
1743 static void monowhite_to_gray(AVPicture *dst, const AVPicture *src,
1744                                int width, int height)
1745 {
1746     mono_to_gray(dst, src, width, height, 0xff);
1747 }
1748
1749 static void monoblack_to_gray(AVPicture *dst, const AVPicture *src,
1750                                int width, int height)
1751 {
1752     mono_to_gray(dst, src, width, height, 0x00);
1753 }
1754
1755 static void gray_to_mono(AVPicture *dst, const AVPicture *src,
1756                          int width, int height, int xor_mask)
1757 {
1758     int n;
1759     const uint8_t *s;
1760     uint8_t *d;
1761     int j, b, v, n1, src_wrap, dst_wrap, y;
1762
1763     s = src->data[0];
1764     src_wrap = src->linesize[0] - width;
1765
1766     d = dst->data[0];
1767     dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
1768
1769     for(y=0;y<height;y++) {
1770         n = width;
1771         while (n >= 8) {
1772             v = 0;
1773             for(j=0;j<8;j++) {
1774                 b = s[0];
1775                 s++;
1776                 v = (v << 1) | (b >> 7);
1777             }
1778             d[0] = v ^ xor_mask;
1779             d++;
1780             n -= 8;
1781         }
1782         if (n > 0) {
1783             n1 = n;
1784             v = 0;
1785             while (n > 0) {
1786                 b = s[0];
1787                 s++;
1788                 v = (v << 1) | (b >> 7);
1789                 n--;
1790             }
1791             d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
1792             d++;
1793         }
1794         s += src_wrap;
1795         d += dst_wrap;
1796     }
1797 }
1798
1799 static void gray_to_monowhite(AVPicture *dst, const AVPicture *src,
1800                               int width, int height)
1801 {
1802     gray_to_mono(dst, src, width, height, 0xff);
1803 }
1804
1805 static void gray_to_monoblack(AVPicture *dst, const AVPicture *src,
1806                               int width, int height)
1807 {
1808     gray_to_mono(dst, src, width, height, 0x00);
1809 }
1810
1811 static void gray_to_gray16(AVPicture *dst, const AVPicture *src,
1812                               int width, int height)
1813 {
1814     int x, y, src_wrap, dst_wrap;
1815     uint8_t *s, *d;
1816     s = src->data[0];
1817     src_wrap = src->linesize[0] - width;
1818     d = dst->data[0];
1819     dst_wrap = dst->linesize[0] - width * 2;
1820     for(y=0; y<height; y++){
1821         for(x=0; x<width; x++){
1822             *d++ = *s;
1823             *d++ = *s++;
1824         }
1825         s += src_wrap;
1826         d += dst_wrap;
1827     }
1828 }
1829
1830 static void gray16_to_gray(AVPicture *dst, const AVPicture *src,
1831                               int width, int height)
1832 {
1833     int x, y, src_wrap, dst_wrap;
1834     uint8_t *s, *d;
1835     s = src->data[0];
1836     src_wrap = src->linesize[0] - width * 2;
1837     d = dst->data[0];
1838     dst_wrap = dst->linesize[0] - width;
1839     for(y=0; y<height; y++){
1840         for(x=0; x<width; x++){
1841             *d++ = *s;
1842             s += 2;
1843         }
1844         s += src_wrap;
1845         d += dst_wrap;
1846     }
1847 }
1848
1849 static void gray16be_to_gray(AVPicture *dst, const AVPicture *src,
1850                               int width, int height)
1851 {
1852     gray16_to_gray(dst, src, width, height);
1853 }
1854
1855 static void gray16le_to_gray(AVPicture *dst, const AVPicture *src,
1856                               int width, int height)
1857 {
1858     AVPicture tmpsrc = *src;
1859     tmpsrc.data[0]++;
1860     gray16_to_gray(dst, &tmpsrc, width, height);
1861 }
1862
1863 static void gray16_to_gray16(AVPicture *dst, const AVPicture *src,
1864                               int width, int height)
1865 {
1866     int x, y, src_wrap, dst_wrap;
1867     uint16_t *s, *d;
1868     s = src->data[0];
1869     src_wrap = (src->linesize[0] - width * 2)/2;
1870     d = dst->data[0];
1871     dst_wrap = (dst->linesize[0] - width * 2)/2;
1872     for(y=0; y<height; y++){
1873         for(x=0; x<width; x++){
1874             *d++ = bswap_16(*s++);
1875         }
1876         s += src_wrap;
1877         d += dst_wrap;
1878     }
1879 }
1880
1881
1882 typedef struct ConvertEntry {
1883     void (*convert)(AVPicture *dst,
1884                     const AVPicture *src, int width, int height);
1885 } ConvertEntry;
1886
1887 /* Add each new conversion function in this table. In order to be able
1888    to convert from any format to any format, the following constraints
1889    must be satisfied:
1890
1891    - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
1892
1893    - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
1894
1895    - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGB32
1896
1897    - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
1898      PIX_FMT_RGB24.
1899
1900    - PIX_FMT_422 must convert to and from PIX_FMT_422P.
1901
1902    The other conversion functions are just optimisations for common cases.
1903 */
1904 static const ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1905     [PIX_FMT_YUV420P] = {
1906         [PIX_FMT_YUYV422] = {
1907             .convert = yuv420p_to_yuyv422,
1908         },
1909         [PIX_FMT_RGB555] = {
1910             .convert = yuv420p_to_rgb555
1911         },
1912         [PIX_FMT_RGB565] = {
1913             .convert = yuv420p_to_rgb565
1914         },
1915         [PIX_FMT_BGR24] = {
1916             .convert = yuv420p_to_bgr24
1917         },
1918         [PIX_FMT_RGB24] = {
1919             .convert = yuv420p_to_rgb24
1920         },
1921         [PIX_FMT_RGB32] = {
1922             .convert = yuv420p_to_rgb32
1923         },
1924         [PIX_FMT_UYVY422] = {
1925             .convert = yuv420p_to_uyvy422,
1926         },
1927     },
1928     [PIX_FMT_YUV422P] = {
1929         [PIX_FMT_YUYV422] = {
1930             .convert = yuv422p_to_yuyv422,
1931         },
1932         [PIX_FMT_UYVY422] = {
1933             .convert = yuv422p_to_uyvy422,
1934         },
1935     },
1936     [PIX_FMT_YUV444P] = {
1937         [PIX_FMT_RGB24] = {
1938             .convert = yuv444p_to_rgb24
1939         },
1940     },
1941     [PIX_FMT_YUVJ420P] = {
1942         [PIX_FMT_RGB555] = {
1943             .convert = yuvj420p_to_rgb555
1944         },
1945         [PIX_FMT_RGB565] = {
1946             .convert = yuvj420p_to_rgb565
1947         },
1948         [PIX_FMT_BGR24] = {
1949             .convert = yuvj420p_to_bgr24
1950         },
1951         [PIX_FMT_RGB24] = {
1952             .convert = yuvj420p_to_rgb24
1953         },
1954         [PIX_FMT_RGB32] = {
1955             .convert = yuvj420p_to_rgb32
1956         },
1957     },
1958     [PIX_FMT_YUVJ444P] = {
1959         [PIX_FMT_RGB24] = {
1960             .convert = yuvj444p_to_rgb24
1961         },
1962     },
1963     [PIX_FMT_YUYV422] = {
1964         [PIX_FMT_YUV420P] = {
1965             .convert = yuyv422_to_yuv420p,
1966         },
1967         [PIX_FMT_YUV422P] = {
1968             .convert = yuyv422_to_yuv422p,
1969         },
1970     },
1971     [PIX_FMT_UYVY422] = {
1972         [PIX_FMT_YUV420P] = {
1973             .convert = uyvy422_to_yuv420p,
1974         },
1975         [PIX_FMT_YUV422P] = {
1976             .convert = uyvy422_to_yuv422p,
1977         },
1978     },
1979     [PIX_FMT_RGB24] = {
1980         [PIX_FMT_YUV420P] = {
1981             .convert = rgb24_to_yuv420p
1982         },
1983         [PIX_FMT_RGB565] = {
1984             .convert = rgb24_to_rgb565
1985         },
1986         [PIX_FMT_RGB555] = {
1987             .convert = rgb24_to_rgb555
1988         },
1989         [PIX_FMT_RGB32] = {
1990             .convert = rgb24_to_rgb32
1991         },
1992         [PIX_FMT_BGR24] = {
1993             .convert = rgb24_to_bgr24
1994         },
1995         [PIX_FMT_GRAY8] = {
1996             .convert = rgb24_to_gray
1997         },
1998         [PIX_FMT_PAL8] = {
1999             .convert = rgb24_to_pal8
2000         },
2001         [PIX_FMT_YUV444P] = {
2002             .convert = rgb24_to_yuv444p
2003         },
2004         [PIX_FMT_YUVJ420P] = {
2005             .convert = rgb24_to_yuvj420p
2006         },
2007         [PIX_FMT_YUVJ444P] = {
2008             .convert = rgb24_to_yuvj444p
2009         },
2010     },
2011     [PIX_FMT_RGB32] = {
2012         [PIX_FMT_RGB24] = {
2013             .convert = rgb32_to_rgb24
2014         },
2015         [PIX_FMT_BGR24] = {
2016             .convert = rgb32_to_bgr24
2017         },
2018         [PIX_FMT_RGB565] = {
2019             .convert = rgb32_to_rgb565
2020         },
2021         [PIX_FMT_RGB555] = {
2022             .convert = rgb32_to_rgb555
2023         },
2024         [PIX_FMT_PAL8] = {
2025             .convert = rgb32_to_pal8
2026         },
2027         [PIX_FMT_YUV420P] = {
2028             .convert = rgb32_to_yuv420p
2029         },
2030         [PIX_FMT_GRAY8] = {
2031             .convert = rgb32_to_gray
2032         },
2033     },
2034     [PIX_FMT_BGR24] = {
2035         [PIX_FMT_RGB32] = {
2036             .convert = bgr24_to_rgb32
2037         },
2038         [PIX_FMT_RGB24] = {
2039             .convert = bgr24_to_rgb24
2040         },
2041         [PIX_FMT_YUV420P] = {
2042             .convert = bgr24_to_yuv420p
2043         },
2044         [PIX_FMT_GRAY8] = {
2045             .convert = bgr24_to_gray
2046         },
2047     },
2048     [PIX_FMT_RGB555] = {
2049         [PIX_FMT_RGB24] = {
2050             .convert = rgb555_to_rgb24
2051         },
2052         [PIX_FMT_RGB32] = {
2053             .convert = rgb555_to_rgb32
2054         },
2055         [PIX_FMT_YUV420P] = {
2056             .convert = rgb555_to_yuv420p
2057         },
2058         [PIX_FMT_GRAY8] = {
2059             .convert = rgb555_to_gray
2060         },
2061     },
2062     [PIX_FMT_RGB565] = {
2063         [PIX_FMT_RGB32] = {
2064             .convert = rgb565_to_rgb32
2065         },
2066         [PIX_FMT_RGB24] = {
2067             .convert = rgb565_to_rgb24
2068         },
2069         [PIX_FMT_YUV420P] = {
2070             .convert = rgb565_to_yuv420p
2071         },
2072         [PIX_FMT_GRAY8] = {
2073             .convert = rgb565_to_gray
2074         },
2075     },
2076     [PIX_FMT_GRAY16BE] = {
2077         [PIX_FMT_GRAY8] = {
2078             .convert = gray16be_to_gray
2079         },
2080         [PIX_FMT_GRAY16LE] = {
2081             .convert = gray16_to_gray16
2082         },
2083     },
2084     [PIX_FMT_GRAY16LE] = {
2085         [PIX_FMT_GRAY8] = {
2086             .convert = gray16le_to_gray
2087         },
2088         [PIX_FMT_GRAY16BE] = {
2089             .convert = gray16_to_gray16
2090         },
2091     },
2092     [PIX_FMT_GRAY8] = {
2093         [PIX_FMT_RGB555] = {
2094             .convert = gray_to_rgb555
2095         },
2096         [PIX_FMT_RGB565] = {
2097             .convert = gray_to_rgb565
2098         },
2099         [PIX_FMT_RGB24] = {
2100             .convert = gray_to_rgb24
2101         },
2102         [PIX_FMT_BGR24] = {
2103             .convert = gray_to_bgr24
2104         },
2105         [PIX_FMT_RGB32] = {
2106             .convert = gray_to_rgb32
2107         },
2108         [PIX_FMT_MONOWHITE] = {
2109             .convert = gray_to_monowhite
2110         },
2111         [PIX_FMT_MONOBLACK] = {
2112             .convert = gray_to_monoblack
2113         },
2114         [PIX_FMT_GRAY16LE] = {
2115             .convert = gray_to_gray16
2116         },
2117         [PIX_FMT_GRAY16BE] = {
2118             .convert = gray_to_gray16
2119         },
2120     },
2121     [PIX_FMT_MONOWHITE] = {
2122         [PIX_FMT_GRAY8] = {
2123             .convert = monowhite_to_gray
2124         },
2125     },
2126     [PIX_FMT_MONOBLACK] = {
2127         [PIX_FMT_GRAY8] = {
2128             .convert = monoblack_to_gray
2129         },
2130     },
2131     [PIX_FMT_PAL8] = {
2132         [PIX_FMT_RGB555] = {
2133             .convert = pal8_to_rgb555
2134         },
2135         [PIX_FMT_RGB565] = {
2136             .convert = pal8_to_rgb565
2137         },
2138         [PIX_FMT_BGR24] = {
2139             .convert = pal8_to_bgr24
2140         },
2141         [PIX_FMT_RGB24] = {
2142             .convert = pal8_to_rgb24
2143         },
2144         [PIX_FMT_RGB32] = {
2145             .convert = pal8_to_rgb32
2146         },
2147     },
2148     [PIX_FMT_UYYVYY411] = {
2149         [PIX_FMT_YUV411P] = {
2150             .convert = uyyvyy411_to_yuv411p,
2151         },
2152     },
2153
2154 };
2155
2156 int avpicture_alloc(AVPicture *picture,
2157                            int pix_fmt, int width, int height)
2158 {
2159     int size;
2160     void *ptr;
2161
2162     size = avpicture_get_size(pix_fmt, width, height);
2163     if(size<0)
2164         goto fail;
2165     ptr = av_malloc(size);
2166     if (!ptr)
2167         goto fail;
2168     avpicture_fill(picture, ptr, pix_fmt, width, height);
2169     return 0;
2170  fail:
2171     memset(picture, 0, sizeof(AVPicture));
2172     return -1;
2173 }
2174
2175 void avpicture_free(AVPicture *picture)
2176 {
2177     av_free(picture->data[0]);
2178 }
2179
2180 /* return true if yuv planar */
2181 static inline int is_yuv_planar(const PixFmtInfo *ps)
2182 {
2183     return (ps->color_type == FF_COLOR_YUV ||
2184             ps->color_type == FF_COLOR_YUV_JPEG) &&
2185         ps->pixel_type == FF_PIXEL_PLANAR;
2186 }
2187
2188 int av_picture_crop(AVPicture *dst, const AVPicture *src,
2189               int pix_fmt, int top_band, int left_band)
2190 {
2191     int y_shift;
2192     int x_shift;
2193
2194     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
2195         return -1;
2196
2197     y_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
2198     x_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
2199
2200     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
2201     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
2202     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
2203
2204     dst->linesize[0] = src->linesize[0];
2205     dst->linesize[1] = src->linesize[1];
2206     dst->linesize[2] = src->linesize[2];
2207     return 0;
2208 }
2209
2210 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
2211             int pix_fmt, int padtop, int padbottom, int padleft, int padright,
2212             int *color)
2213 {
2214     uint8_t *optr;
2215     int y_shift;
2216     int x_shift;
2217     int yheight;
2218     int i, y;
2219
2220     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
2221         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
2222
2223     for (i = 0; i < 3; i++) {
2224         x_shift = i ? pix_fmt_info[pix_fmt].x_chroma_shift : 0;
2225         y_shift = i ? pix_fmt_info[pix_fmt].y_chroma_shift : 0;
2226
2227         if (padtop || padleft) {
2228             memset(dst->data[i], color[i],
2229                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
2230         }
2231
2232         if (padleft || padright) {
2233             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
2234                 (dst->linesize[i] - (padright >> x_shift));
2235             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
2236             for (y = 0; y < yheight; y++) {
2237                 memset(optr, color[i], (padleft + padright) >> x_shift);
2238                 optr += dst->linesize[i];
2239             }
2240         }
2241
2242         if (src) { /* first line */
2243             uint8_t *iptr = src->data[i];
2244             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
2245                     (padleft >> x_shift);
2246             memcpy(optr, iptr, src->linesize[i]);
2247             iptr += src->linesize[i];
2248             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
2249                 (dst->linesize[i] - (padright >> x_shift));
2250             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
2251             for (y = 0; y < yheight; y++) {
2252                 memset(optr, color[i], (padleft + padright) >> x_shift);
2253                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
2254                     src->linesize[i]);
2255                 iptr += src->linesize[i];
2256                 optr += dst->linesize[i];
2257             }
2258         }
2259
2260         if (padbottom || padright) {
2261             optr = dst->data[i] + dst->linesize[i] *
2262                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
2263             memset(optr, color[i],dst->linesize[i] *
2264                 (padbottom >> y_shift) + (padright >> x_shift));
2265         }
2266     }
2267     return 0;
2268 }
2269
2270 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
2271 void img_copy(AVPicture *dst, const AVPicture *src,
2272               int pix_fmt, int width, int height)
2273 {
2274     av_picture_copy(dst, src, pix_fmt, width, height);
2275 }
2276
2277 int img_crop(AVPicture *dst, const AVPicture *src,
2278               int pix_fmt, int top_band, int left_band)
2279 {
2280     return av_picture_crop(dst, src, pix_fmt, top_band, left_band);
2281 }
2282
2283 int img_pad(AVPicture *dst, const AVPicture *src, int height, int width,
2284             int pix_fmt, int padtop, int padbottom, int padleft, int padright,
2285             int *color)
2286 {
2287     return av_picture_pad(dst, src, height, width, pix_fmt, padtop, padbottom, padleft, padright, color);
2288 }
2289 #endif
2290
2291 #ifndef CONFIG_SWSCALER
2292 /* XXX: always use linesize. Return -1 if not supported */
2293 int img_convert(AVPicture *dst, int dst_pix_fmt,
2294                 const AVPicture *src, int src_pix_fmt,
2295                 int src_width, int src_height)
2296 {
2297     static int inited;
2298     int i, ret, dst_width, dst_height, int_pix_fmt;
2299     const PixFmtInfo *src_pix, *dst_pix;
2300     const ConvertEntry *ce;
2301     AVPicture tmp1, *tmp = &tmp1;
2302
2303     if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
2304         dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
2305         return -1;
2306     if (src_width <= 0 || src_height <= 0)
2307         return 0;
2308
2309     if (!inited) {
2310         inited = 1;
2311         img_convert_init();
2312     }
2313
2314     dst_width = src_width;
2315     dst_height = src_height;
2316
2317     dst_pix = &pix_fmt_info[dst_pix_fmt];
2318     src_pix = &pix_fmt_info[src_pix_fmt];
2319     if (src_pix_fmt == dst_pix_fmt) {
2320         /* no conversion needed: just copy */
2321         av_picture_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
2322         return 0;
2323     }
2324
2325     ce = &convert_table[src_pix_fmt][dst_pix_fmt];
2326     if (ce->convert) {
2327         /* specific conversion routine */
2328         ce->convert(dst, src, dst_width, dst_height);
2329         return 0;
2330     }
2331
2332     /* gray to YUV */
2333     if (is_yuv_planar(dst_pix) &&
2334         src_pix_fmt == PIX_FMT_GRAY8) {
2335         int w, h, y;
2336         uint8_t *d;
2337
2338         if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
2339             ff_img_copy_plane(dst->data[0], dst->linesize[0],
2340                      src->data[0], src->linesize[0],
2341                      dst_width, dst_height);
2342         } else {
2343             img_apply_table(dst->data[0], dst->linesize[0],
2344                             src->data[0], src->linesize[0],
2345                             dst_width, dst_height,
2346                             y_jpeg_to_ccir);
2347         }
2348         /* fill U and V with 128 */
2349         w = dst_width;
2350         h = dst_height;
2351         w >>= dst_pix->x_chroma_shift;
2352         h >>= dst_pix->y_chroma_shift;
2353         for(i = 1; i <= 2; i++) {
2354             d = dst->data[i];
2355             for(y = 0; y< h; y++) {
2356                 memset(d, 128, w);
2357                 d += dst->linesize[i];
2358             }
2359         }
2360         return 0;
2361     }
2362
2363     /* YUV to gray */
2364     if (is_yuv_planar(src_pix) &&
2365         dst_pix_fmt == PIX_FMT_GRAY8) {
2366         if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
2367             ff_img_copy_plane(dst->data[0], dst->linesize[0],
2368                      src->data[0], src->linesize[0],
2369                      dst_width, dst_height);
2370         } else {
2371             img_apply_table(dst->data[0], dst->linesize[0],
2372                             src->data[0], src->linesize[0],
2373                             dst_width, dst_height,
2374                             y_ccir_to_jpeg);
2375         }
2376         return 0;
2377     }
2378
2379     /* YUV to YUV planar */
2380     if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
2381         int x_shift, y_shift, w, h, xy_shift;
2382         void (*resize_func)(uint8_t *dst, int dst_wrap,
2383                             const uint8_t *src, int src_wrap,
2384                             int width, int height);
2385
2386         /* compute chroma size of the smallest dimensions */
2387         w = dst_width;
2388         h = dst_height;
2389         if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
2390             w >>= dst_pix->x_chroma_shift;
2391         else
2392             w >>= src_pix->x_chroma_shift;
2393         if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
2394             h >>= dst_pix->y_chroma_shift;
2395         else
2396             h >>= src_pix->y_chroma_shift;
2397
2398         x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
2399         y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
2400         xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
2401         /* there must be filters for conversion at least from and to
2402            YUV444 format */
2403         switch(xy_shift) {
2404         case 0x00:
2405             resize_func = ff_img_copy_plane;
2406             break;
2407         case 0x10:
2408             resize_func = shrink21;
2409             break;
2410         case 0x20:
2411             resize_func = shrink41;
2412             break;
2413         case 0x01:
2414             resize_func = shrink12;
2415             break;
2416         case 0x11:
2417             resize_func = ff_shrink22;
2418             break;
2419         case 0x22:
2420             resize_func = ff_shrink44;
2421             break;
2422         case 0xf0:
2423             resize_func = grow21;
2424             break;
2425         case 0x0f:
2426             resize_func = grow12;
2427             break;
2428         case 0xe0:
2429             resize_func = grow41;
2430             break;
2431         case 0xff:
2432             resize_func = grow22;
2433             break;
2434         case 0xee:
2435             resize_func = grow44;
2436             break;
2437         case 0xf1:
2438             resize_func = conv411;
2439             break;
2440         default:
2441             /* currently not handled */
2442             goto no_chroma_filter;
2443         }
2444
2445         ff_img_copy_plane(dst->data[0], dst->linesize[0],
2446                        src->data[0], src->linesize[0],
2447                        dst_width, dst_height);
2448
2449         for(i = 1;i <= 2; i++)
2450             resize_func(dst->data[i], dst->linesize[i],
2451                         src->data[i], src->linesize[i],
2452                         dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
2453         /* if yuv color space conversion is needed, we do it here on
2454            the destination image */
2455         if (dst_pix->color_type != src_pix->color_type) {
2456             const uint8_t *y_table, *c_table;
2457             if (dst_pix->color_type == FF_COLOR_YUV) {
2458                 y_table = y_jpeg_to_ccir;
2459                 c_table = c_jpeg_to_ccir;
2460             } else {
2461                 y_table = y_ccir_to_jpeg;
2462                 c_table = c_ccir_to_jpeg;
2463             }
2464             img_apply_table(dst->data[0], dst->linesize[0],
2465                             dst->data[0], dst->linesize[0],
2466                             dst_width, dst_height,
2467                             y_table);
2468
2469             for(i = 1;i <= 2; i++)
2470                 img_apply_table(dst->data[i], dst->linesize[i],
2471                                 dst->data[i], dst->linesize[i],
2472                                 dst_width>>dst_pix->x_chroma_shift,
2473                                 dst_height>>dst_pix->y_chroma_shift,
2474                                 c_table);
2475         }
2476         return 0;
2477     }
2478  no_chroma_filter:
2479
2480     /* try to use an intermediate format */
2481     if (src_pix_fmt == PIX_FMT_YUYV422 ||
2482         dst_pix_fmt == PIX_FMT_YUYV422) {
2483         /* specific case: convert to YUV422P first */
2484         int_pix_fmt = PIX_FMT_YUV422P;
2485     } else if (src_pix_fmt == PIX_FMT_UYVY422 ||
2486         dst_pix_fmt == PIX_FMT_UYVY422) {
2487         /* specific case: convert to YUV422P first */
2488         int_pix_fmt = PIX_FMT_YUV422P;
2489     } else if (src_pix_fmt == PIX_FMT_UYYVYY411 ||
2490         dst_pix_fmt == PIX_FMT_UYYVYY411) {
2491         /* specific case: convert to YUV411P first */
2492         int_pix_fmt = PIX_FMT_YUV411P;
2493     } else if ((src_pix->color_type == FF_COLOR_GRAY &&
2494                 src_pix_fmt != PIX_FMT_GRAY8) ||
2495                (dst_pix->color_type == FF_COLOR_GRAY &&
2496                 dst_pix_fmt != PIX_FMT_GRAY8)) {
2497         /* gray8 is the normalized format */
2498         int_pix_fmt = PIX_FMT_GRAY8;
2499     } else if ((is_yuv_planar(src_pix) &&
2500                 src_pix_fmt != PIX_FMT_YUV444P &&
2501                 src_pix_fmt != PIX_FMT_YUVJ444P)) {
2502         /* yuv444 is the normalized format */
2503         if (src_pix->color_type == FF_COLOR_YUV_JPEG)
2504             int_pix_fmt = PIX_FMT_YUVJ444P;
2505         else
2506             int_pix_fmt = PIX_FMT_YUV444P;
2507     } else if ((is_yuv_planar(dst_pix) &&
2508                 dst_pix_fmt != PIX_FMT_YUV444P &&
2509                 dst_pix_fmt != PIX_FMT_YUVJ444P)) {
2510         /* yuv444 is the normalized format */
2511         if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
2512             int_pix_fmt = PIX_FMT_YUVJ444P;
2513         else
2514             int_pix_fmt = PIX_FMT_YUV444P;
2515     } else {
2516         /* the two formats are rgb or gray8 or yuv[j]444p */
2517         if (src_pix->is_alpha && dst_pix->is_alpha)
2518             int_pix_fmt = PIX_FMT_RGB32;
2519         else
2520             int_pix_fmt = PIX_FMT_RGB24;
2521     }
2522     if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
2523         return -1;
2524     ret = -1;
2525     if (img_convert(tmp, int_pix_fmt,
2526                     src, src_pix_fmt, src_width, src_height) < 0)
2527         goto fail1;
2528     if (img_convert(dst, dst_pix_fmt,
2529                     tmp, int_pix_fmt, dst_width, dst_height) < 0)
2530         goto fail1;
2531     ret = 0;
2532  fail1:
2533     avpicture_free(tmp);
2534     return ret;
2535 }
2536 #endif
2537
2538 /* NOTE: we scan all the pixels to have an exact information */
2539 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
2540 {
2541     const unsigned char *p;
2542     int src_wrap, ret, x, y;
2543     unsigned int a;
2544     uint32_t *palette = (uint32_t *)src->data[1];
2545
2546     p = src->data[0];
2547     src_wrap = src->linesize[0] - width;
2548     ret = 0;
2549     for(y=0;y<height;y++) {
2550         for(x=0;x<width;x++) {
2551             a = palette[p[0]] >> 24;
2552             if (a == 0x00) {
2553                 ret |= FF_ALPHA_TRANSP;
2554             } else if (a != 0xff) {
2555                 ret |= FF_ALPHA_SEMI_TRANSP;
2556             }
2557             p++;
2558         }
2559         p += src_wrap;
2560     }
2561     return ret;
2562 }
2563
2564 int img_get_alpha_info(const AVPicture *src,
2565                        int pix_fmt, int width, int height)
2566 {
2567     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
2568     int ret;
2569
2570     pf = &pix_fmt_info[pix_fmt];
2571     /* no alpha can be represented in format */
2572     if (!pf->is_alpha)
2573         return 0;
2574     switch(pix_fmt) {
2575     case PIX_FMT_RGB32:
2576         ret = get_alpha_info_rgb32(src, width, height);
2577         break;
2578     case PIX_FMT_PAL8:
2579         ret = get_alpha_info_pal8(src, width, height);
2580         break;
2581     default:
2582         /* we do not know, so everything is indicated */
2583         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
2584         break;
2585     }
2586     return ret;
2587 }
2588
2589 #ifdef HAVE_MMX
2590 #define DEINT_INPLACE_LINE_LUM \
2591                     movd_m2r(lum_m4[0],mm0);\
2592                     movd_m2r(lum_m3[0],mm1);\
2593                     movd_m2r(lum_m2[0],mm2);\
2594                     movd_m2r(lum_m1[0],mm3);\
2595                     movd_m2r(lum[0],mm4);\
2596                     punpcklbw_r2r(mm7,mm0);\
2597                     movd_r2m(mm2,lum_m4[0]);\
2598                     punpcklbw_r2r(mm7,mm1);\
2599                     punpcklbw_r2r(mm7,mm2);\
2600                     punpcklbw_r2r(mm7,mm3);\
2601                     punpcklbw_r2r(mm7,mm4);\
2602                     paddw_r2r(mm3,mm1);\
2603                     psllw_i2r(1,mm2);\
2604                     paddw_r2r(mm4,mm0);\
2605                     psllw_i2r(2,mm1);\
2606                     paddw_r2r(mm6,mm2);\
2607                     paddw_r2r(mm2,mm1);\
2608                     psubusw_r2r(mm0,mm1);\
2609                     psrlw_i2r(3,mm1);\
2610                     packuswb_r2r(mm7,mm1);\
2611                     movd_r2m(mm1,lum_m2[0]);
2612
2613 #define DEINT_LINE_LUM \
2614                     movd_m2r(lum_m4[0],mm0);\
2615                     movd_m2r(lum_m3[0],mm1);\
2616                     movd_m2r(lum_m2[0],mm2);\
2617                     movd_m2r(lum_m1[0],mm3);\
2618                     movd_m2r(lum[0],mm4);\
2619                     punpcklbw_r2r(mm7,mm0);\
2620                     punpcklbw_r2r(mm7,mm1);\
2621                     punpcklbw_r2r(mm7,mm2);\
2622                     punpcklbw_r2r(mm7,mm3);\
2623                     punpcklbw_r2r(mm7,mm4);\
2624                     paddw_r2r(mm3,mm1);\
2625                     psllw_i2r(1,mm2);\
2626                     paddw_r2r(mm4,mm0);\
2627                     psllw_i2r(2,mm1);\
2628                     paddw_r2r(mm6,mm2);\
2629                     paddw_r2r(mm2,mm1);\
2630                     psubusw_r2r(mm0,mm1);\
2631                     psrlw_i2r(3,mm1);\
2632                     packuswb_r2r(mm7,mm1);\
2633                     movd_r2m(mm1,dst[0]);
2634 #endif
2635
2636 /* filter parameters: [-1 4 2 4 -1] // 8 */
2637 static void deinterlace_line(uint8_t *dst,
2638                              const uint8_t *lum_m4, const uint8_t *lum_m3,
2639                              const uint8_t *lum_m2, const uint8_t *lum_m1,
2640                              const uint8_t *lum,
2641                              int size)
2642 {
2643 #ifndef HAVE_MMX
2644     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
2645     int sum;
2646
2647     for(;size > 0;size--) {
2648         sum = -lum_m4[0];
2649         sum += lum_m3[0] << 2;
2650         sum += lum_m2[0] << 1;
2651         sum += lum_m1[0] << 2;
2652         sum += -lum[0];
2653         dst[0] = cm[(sum + 4) >> 3];
2654         lum_m4++;
2655         lum_m3++;
2656         lum_m2++;
2657         lum_m1++;
2658         lum++;
2659         dst++;
2660     }
2661 #else
2662
2663     {
2664         mmx_t rounder;
2665         rounder.uw[0]=4;
2666         rounder.uw[1]=4;
2667         rounder.uw[2]=4;
2668         rounder.uw[3]=4;
2669         pxor_r2r(mm7,mm7);
2670         movq_m2r(rounder,mm6);
2671     }
2672     for (;size > 3; size-=4) {
2673         DEINT_LINE_LUM
2674         lum_m4+=4;
2675         lum_m3+=4;
2676         lum_m2+=4;
2677         lum_m1+=4;
2678         lum+=4;
2679         dst+=4;
2680     }
2681 #endif
2682 }
2683 static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
2684                              int size)
2685 {
2686 #ifndef HAVE_MMX
2687     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
2688     int sum;
2689
2690     for(;size > 0;size--) {
2691         sum = -lum_m4[0];
2692         sum += lum_m3[0] << 2;
2693         sum += lum_m2[0] << 1;
2694         lum_m4[0]=lum_m2[0];
2695         sum += lum_m1[0] << 2;
2696         sum += -lum[0];
2697         lum_m2[0] = cm[(sum + 4) >> 3];
2698         lum_m4++;
2699         lum_m3++;
2700         lum_m2++;
2701         lum_m1++;
2702         lum++;
2703     }
2704 #else
2705
2706     {
2707         mmx_t rounder;
2708         rounder.uw[0]=4;
2709         rounder.uw[1]=4;
2710         rounder.uw[2]=4;
2711         rounder.uw[3]=4;
2712         pxor_r2r(mm7,mm7);
2713         movq_m2r(rounder,mm6);
2714     }
2715     for (;size > 3; size-=4) {
2716         DEINT_INPLACE_LINE_LUM
2717         lum_m4+=4;
2718         lum_m3+=4;
2719         lum_m2+=4;
2720         lum_m1+=4;
2721         lum+=4;
2722     }
2723 #endif
2724 }
2725
2726 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
2727    top field is copied as is, but the bottom field is deinterlaced
2728    against the top field. */
2729 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
2730                                     const uint8_t *src1, int src_wrap,
2731                                     int width, int height)
2732 {
2733     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
2734     int y;
2735
2736     src_m2 = src1;
2737     src_m1 = src1;
2738     src_0=&src_m1[src_wrap];
2739     src_p1=&src_0[src_wrap];
2740     src_p2=&src_p1[src_wrap];
2741     for(y=0;y<(height-2);y+=2) {
2742         memcpy(dst,src_m1,width);
2743         dst += dst_wrap;
2744         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
2745         src_m2 = src_0;
2746         src_m1 = src_p1;
2747         src_0 = src_p2;
2748         src_p1 += 2*src_wrap;
2749         src_p2 += 2*src_wrap;
2750         dst += dst_wrap;
2751     }
2752     memcpy(dst,src_m1,width);
2753     dst += dst_wrap;
2754     /* do last line */
2755     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
2756 }
2757
2758 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
2759                                              int width, int height)
2760 {
2761     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
2762     int y;
2763     uint8_t *buf;
2764     buf = (uint8_t*)av_malloc(width);
2765
2766     src_m1 = src1;
2767     memcpy(buf,src_m1,width);
2768     src_0=&src_m1[src_wrap];
2769     src_p1=&src_0[src_wrap];
2770     src_p2=&src_p1[src_wrap];
2771     for(y=0;y<(height-2);y+=2) {
2772         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
2773         src_m1 = src_p1;
2774         src_0 = src_p2;
2775         src_p1 += 2*src_wrap;
2776         src_p2 += 2*src_wrap;
2777     }
2778     /* do last line */
2779     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
2780     av_free(buf);
2781 }
2782
2783 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
2784                           int pix_fmt, int width, int height)
2785 {
2786     int i;
2787
2788     if (pix_fmt != PIX_FMT_YUV420P &&
2789         pix_fmt != PIX_FMT_YUV422P &&
2790         pix_fmt != PIX_FMT_YUV444P &&
2791         pix_fmt != PIX_FMT_YUV411P)
2792         return -1;
2793     if ((width & 3) != 0 || (height & 3) != 0)
2794         return -1;
2795
2796     for(i=0;i<3;i++) {
2797         if (i == 1) {
2798             switch(pix_fmt) {
2799             case PIX_FMT_YUV420P:
2800                 width >>= 1;
2801                 height >>= 1;
2802                 break;
2803             case PIX_FMT_YUV422P:
2804                 width >>= 1;
2805                 break;
2806             case PIX_FMT_YUV411P:
2807                 width >>= 2;
2808                 break;
2809             default:
2810                 break;
2811             }
2812         }
2813         if (src == dst) {
2814             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
2815                                  width, height);
2816         } else {
2817             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
2818                                         src->data[i], src->linesize[i],
2819                                         width, height);
2820         }
2821     }
2822 #ifdef HAVE_MMX
2823     emms();
2824 #endif
2825     return 0;
2826 }
2827