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