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