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