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