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