Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / 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 GST_DEBUG_CATEGORY_EXTERN (ffmpegcolorspace_performance);
39
40 #define xglue(x, y) x ## y
41 #define glue(x, y) xglue(x, y)
42
43 /* this table gives more information about formats */
44 /* FIXME, this table is also in ffmpegcodecmap */
45 static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
46   /* YUV formats */
47   /* [PIX_FMT_YUV420P] = */ {
48         /* .format         = */ PIX_FMT_YUV420P,
49         /* .name           = */ "yuv420p",
50         /* .nb_channels    = */ 3,
51         /* .color_type     = */ FF_COLOR_YUV,
52         /* .pixel_type     = */ FF_PIXEL_PLANAR,
53         /* .is_alpha       = */ 0,
54         /* .x_chroma_shift = */ 1,
55         /* .y_chroma_shift = */ 1,
56         /* .depth          = */ 8,
57       },
58   /* [PIX_FMT_YVU420P] = */ {
59         /* .format         = */ PIX_FMT_YVU420P,
60         /* .name           = */ "yvu420p",
61         /* .nb_channels    = */ 3,
62         /* .color_type     = */ FF_COLOR_YUV,
63         /* .pixel_type     = */ FF_PIXEL_PLANAR,
64         /* .is_alpha       = */ 0,
65         /* .x_chroma_shift = */ 1,
66         /* .y_chroma_shift = */ 1,
67         /* .depth          = */ 8,
68       },
69   /* [PIX_FMT_NV12] = */ {
70         /* .format         = */ PIX_FMT_NV12,
71         /* .name           = */ "nv12",
72         /* .nb_channels    = */ 2,
73         /* .color_type     = */ FF_COLOR_YUV,
74         /* .pixel_type     = */ FF_PIXEL_PACKED,
75         /* .is_alpha       = */ 0,
76         /* .x_chroma_shift = */ 1,
77         /* .y_chroma_shift = */ 1,
78         /* .depth          = */ 8,
79       },
80   /* [PIX_FMT_NV21] = */ {
81         /* .format         = */ PIX_FMT_NV21,
82         /* .name           = */ "nv21",
83         /* .nb_channels    = */ 2,
84         /* .color_type     = */ FF_COLOR_YUV,
85         /* .pixel_type     = */ FF_PIXEL_PACKED,
86         /* .is_alpha       = */ 0,
87         /* .x_chroma_shift = */ 1,
88         /* .y_chroma_shift = */ 1,
89         /* .depth          = */ 8,
90       },
91   /* [PIX_FMT_YUV422P] = */ {
92         /* .format         = */ PIX_FMT_YUV422P,
93         /* .name           = */ "yuv422p",
94         /* .nb_channels    = */ 3,
95         /* .color_type     = */ FF_COLOR_YUV,
96         /* .pixel_type     = */ FF_PIXEL_PLANAR,
97         /* .is_alpha       = */ 0,
98         /* .x_chroma_shift = */ 1,
99         /* .y_chroma_shift = */ 0,
100         /* .depth          = */ 8,
101       },
102   /* [PIX_FMT_YUV444P] = */ {
103         /* .format         = */ PIX_FMT_YUV444P,
104         /* .name           = */ "yuv444p",
105         /* .nb_channels    = */ 3,
106         /* .color_type     = */ FF_COLOR_YUV,
107         /* .pixel_type     = */ FF_PIXEL_PLANAR,
108         /* .is_alpha       = */ 0,
109         /* .x_chroma_shift = */ 0,
110         /* .y_chroma_shift = */ 0,
111         /* .depth          = */ 8,
112       },
113   /* [PIX_FMT_YUV422] = */ {
114         /* .format         = */ PIX_FMT_YUV422,
115         /* .name           = */ "yuv422",
116         /* .nb_channels    = */ 1,
117         /* .color_type     = */ FF_COLOR_YUV,
118         /* .pixel_type     = */ FF_PIXEL_PACKED,
119         /* .is_alpha       = */ 0,
120         /* .x_chroma_shift = */ 1,
121         /* .y_chroma_shift = */ 0,
122         /* .depth          = */ 8,
123       },
124   /* [PIX_FMT_UYVY422] = */ {
125         /* .format         = */ PIX_FMT_UYVY422,
126         /* .name           = */ "uyvy422",
127         /* .nb_channels    = */ 1,
128         /* .color_type     = */ FF_COLOR_YUV,
129         /* .pixel_type     = */ FF_PIXEL_PACKED,
130         /* .is_alpha       = */ 0,
131         /* .x_chroma_shift = */ 1,
132         /* .y_chroma_shift = */ 0,
133         /* .depth          = */ 8,
134       },
135   /* [PIX_FMT_YVYU422] = */ {
136         /* .format         = */ PIX_FMT_YVYU422,
137         /* .name           = */ "yvyu422",
138         /* .nb_channels    = */ 1,
139         /* .color_type     = */ FF_COLOR_YUV,
140         /* .pixel_type     = */ FF_PIXEL_PACKED,
141         /* .is_alpha       = */ 0,
142         /* .x_chroma_shift = */ 1,
143         /* .y_chroma_shift = */ 0,
144         /* .depth          = */ 8,
145       },
146   /* [PIX_FMT_V308] = */ {
147         /* .format         = */ PIX_FMT_V308,
148         /* .name           = */ "v308",
149         /* .nb_channels    = */ 1,
150         /* .color_type     = */ FF_COLOR_YUV,
151         /* .pixel_type     = */ FF_PIXEL_PACKED,
152         /* .is_alpha       = */ 0,
153         /* .x_chroma_shift = */ 0,
154         /* .y_chroma_shift = */ 0,
155         /* .depth          = */ 8,
156       },
157   /* [PIX_FMT_YUV410P] = */ {
158         /* .format         = */ PIX_FMT_YUV410P,
159         /* .name           = */ "yuv410p",
160         /* .nb_channels    = */ 3,
161         /* .color_type     = */ FF_COLOR_YUV,
162         /* .pixel_type     = */ FF_PIXEL_PLANAR,
163         /* .is_alpha       = */ 0,
164         /* .x_chroma_shift = */ 2,
165         /* .y_chroma_shift = */ 2,
166         /* .depth          = */ 8,
167       },
168   /* [PIX_FMT_YVU410P] = */ {
169         /* .format         = */ PIX_FMT_YVU410P,
170         /* .name           = */ "yvu410p",
171         /* .nb_channels    = */ 3,
172         /* .color_type     = */ FF_COLOR_YUV,
173         /* .pixel_type     = */ FF_PIXEL_PLANAR,
174         /* .is_alpha       = */ 0,
175         /* .x_chroma_shift = */ 2,
176         /* .y_chroma_shift = */ 2,
177         /* .depth          = */ 8,
178       },
179   /* [PIX_FMT_YUV411P] = */ {
180         /* .format         = */ PIX_FMT_YUV411P,
181         /* .name           = */ "yuv411p",
182         /* .nb_channels    = */ 3,
183         /* .color_type     = */ FF_COLOR_YUV,
184         /* .pixel_type     = */ FF_PIXEL_PLANAR,
185         /* .is_alpha       = */ 0,
186         /* .x_chroma_shift = */ 2,
187         /* .y_chroma_shift = */ 0,
188         /* .depth          = */ 8,
189       },
190   /* [PIX_FMT_Y800] = */ {
191         /* .format         = */ PIX_FMT_Y800,
192         /* .name           = */ "y800",
193         /* .nb_channels    = */ 1,
194         /* .color_type     = */ FF_COLOR_YUV,
195         /* .pixel_type     = */ FF_PIXEL_PLANAR,
196         /* .is_alpha       = */ 0,
197         /* .x_chroma_shift = */ 0,
198         /* .y_chroma_shift = */ 0,
199         /* .depth          = */ 8,
200       },
201   /* [PIX_FMT_Y16] = */ {
202         /* .format         = */ PIX_FMT_Y16,
203         /* .name           = */ "y16",
204         /* .nb_channels    = */ 1,
205         /* .color_type     = */ FF_COLOR_YUV,
206         /* .pixel_type     = */ FF_PIXEL_PLANAR,
207         /* .is_alpha       = */ 0,
208         /* .x_chroma_shift = */ 0,
209         /* .y_chroma_shift = */ 0,
210         /* .depth          = */ 16,
211       },
212
213   /* JPEG YUV */
214   /* [PIX_FMT_YUVJ420P] = */ {
215         /* .format         = */ PIX_FMT_YUVJ420P,
216         /* .name           = */ "yuvj420p",
217         /* .nb_channels    = */ 3,
218         /* .color_type     = */ FF_COLOR_YUV_JPEG,
219         /* .pixel_type     = */ FF_PIXEL_PLANAR,
220         /* .is_alpha       = */ 0,
221         /* .x_chroma_shift = */ 1,
222         /* .y_chroma_shift = */ 1,
223         /* .depth          = */ 8,
224       },
225   /* [PIX_FMT_YUVJ422P] = */ {
226         /* .format         = */ PIX_FMT_YUVJ422P,
227         /* .name           = */ "yuvj422p",
228         /* .nb_channels    = */ 3,
229         /* .color_type     = */ FF_COLOR_YUV_JPEG,
230         /* .pixel_type     = */ FF_PIXEL_PLANAR,
231         /* .is_alpha       = */ 0,
232         /* .x_chroma_shift = */ 1,
233         /* .y_chroma_shift = */ 0,
234         /* .depth          = */ 8,
235       },
236   /* [PIX_FMT_YUVJ444P] = */ {
237         /* .format         = */ PIX_FMT_YUVJ444P,
238         /* .name           = */ "yuvj444p",
239         /* .nb_channels    = */ 3,
240         /* .color_type     = */ FF_COLOR_YUV_JPEG,
241         /* .pixel_type     = */ FF_PIXEL_PLANAR,
242         /* .is_alpha       = */ 0,
243         /* .x_chroma_shift = */ 0,
244         /* .y_chroma_shift = */ 0,
245         /* .depth          = */ 8,
246       },
247
248   /* RGB formats */
249   /* [PIX_FMT_RGB24] = */ {
250         /* .format         = */ PIX_FMT_RGB24,
251         /* .name           = */ "rgb24",
252         /* .nb_channels    = */ 3,
253         /* .color_type     = */ FF_COLOR_RGB,
254         /* .pixel_type     = */ FF_PIXEL_PACKED,
255         /* .is_alpha       = */ 0,
256         /* .x_chroma_shift = */ 0,
257         /* .y_chroma_shift = */ 0,
258         /* .depth          = */ 8,
259       },
260   /* [PIX_FMT_BGR24] = */ {
261         /* .format         = */ PIX_FMT_BGR24,
262         /* .name           = */ "bgr24",
263         /* .nb_channels    = */ 3,
264         /* .color_type     = */ FF_COLOR_RGB,
265         /* .pixel_type     = */ FF_PIXEL_PACKED,
266         /* .is_alpha       = */ 0,
267         /* .x_chroma_shift = */ 0,
268         /* .y_chroma_shift = */ 0,
269         /* .depth          = */ 8,
270       },
271   /* [PIX_FMT_RGB32] = */ {
272         /* .format         = */ PIX_FMT_RGB32,
273         /* .name           = */ "rgb32",
274         /* .nb_channels    = */ 4,
275         /* .color_type     = */ FF_COLOR_RGB,
276         /* .pixel_type     = */ FF_PIXEL_PACKED,
277         /* .is_alpha       = */ 0,
278         /* .x_chroma_shift = */ 0,
279         /* .y_chroma_shift = */ 0,
280         /* .depth          = */ 8,
281       },
282   /* [PIX_FMT_BGR32] = */ {
283         /* .format         = */ PIX_FMT_BGR32,
284         /* .name           = */ "bgr32",
285         /* .nb_channels    = */ 4,
286         /* .color_type     = */ FF_COLOR_RGB,
287         /* .pixel_type     = */ FF_PIXEL_PACKED,
288         /* .is_alpha       = */ 0,
289         /* .x_chroma_shift = */ 0,
290         /* .y_chroma_shift = */ 0,
291         /* .depth          = */ 8,
292       },
293   /* [PIX_FMT_RGB32] = */ {
294         /* .format         = */ PIX_FMT_xRGB32,
295         /* .name           = */ "xrgb32",
296         /* .nb_channels    = */ 4,
297         /* .color_type     = */ FF_COLOR_RGB,
298         /* .pixel_type     = */ FF_PIXEL_PACKED,
299         /* .is_alpha       = */ 0,
300         /* .x_chroma_shift = */ 0,
301         /* .y_chroma_shift = */ 0,
302         /* .depth          = */ 8,
303       },
304   /* [PIX_FMT_BGR32] = */ {
305         /* .format         = */ PIX_FMT_BGRx32,
306         /* .name           = */ "bgrx32",
307         /* .nb_channels    = */ 4,
308         /* .color_type     = */ FF_COLOR_RGB,
309         /* .pixel_type     = */ FF_PIXEL_PACKED,
310         /* .is_alpha       = */ 0,
311         /* .x_chroma_shift = */ 0,
312         /* .y_chroma_shift = */ 0,
313         /* .depth          = */ 8,
314       },
315   /* [PIX_FMT_RGBA32] = */ {
316         /* .format         = */ PIX_FMT_RGBA32,
317         /* .name           = */ "rgba32",
318         /* .nb_channels    = */ 4,
319         /* .color_type     = */ FF_COLOR_RGB,
320         /* .pixel_type     = */ FF_PIXEL_PACKED,
321         /* .is_alpha       = */ 1,
322         /* .x_chroma_shift = */ 0,
323         /* .y_chroma_shift = */ 0,
324         /* .depth          = */ 8,
325       },
326   /* [PIX_FMT_BGRA32] = */ {
327         /* .format         = */ PIX_FMT_BGRA32,
328         /* .name           = */ "bgra32",
329         /* .nb_channels    = */ 4,
330         /* .color_type     = */ FF_COLOR_RGB,
331         /* .pixel_type     = */ FF_PIXEL_PACKED,
332         /* .is_alpha       = */ 1,
333         /* .x_chroma_shift = */ 0,
334         /* .y_chroma_shift = */ 0,
335         /* .depth          = */ 8,
336       },
337   /* [PIX_FMT_ARGB32] = */ {
338         /* .format         = */ PIX_FMT_ARGB32,
339         /* .name           = */ "argb32",
340         /* .nb_channels    = */ 4,
341         /* .color_type     = */ FF_COLOR_RGB,
342         /* .pixel_type     = */ FF_PIXEL_PACKED,
343         /* .is_alpha       = */ 1,
344         /* .x_chroma_shift = */ 0,
345         /* .y_chroma_shift = */ 0,
346         /* .depth          = */ 8,
347       },
348   /* [PIX_FMT_ABGR32] = */ {
349         /* .format         = */ PIX_FMT_ABGR32,
350         /* .name           = */ "abgr32",
351         /* .nb_channels    = */ 4,
352         /* .color_type     = */ FF_COLOR_RGB,
353         /* .pixel_type     = */ FF_PIXEL_PACKED,
354         /* .is_alpha       = */ 1,
355         /* .x_chroma_shift = */ 0,
356         /* .y_chroma_shift = */ 0,
357         /* .depth          = */ 8,
358       },
359   /* [PIX_FMT_RGB565] = */ {
360         /* .format         = */ PIX_FMT_RGB565,
361         /* .name           = */ "rgb565",
362         /* .nb_channels    = */ 3,
363         /* .color_type     = */ FF_COLOR_RGB,
364         /* .pixel_type     = */ FF_PIXEL_PACKED,
365         /* .is_alpha       = */ 0,
366         /* .x_chroma_shift = */ 0,
367         /* .y_chroma_shift = */ 0,
368         /* .depth          = */ 5,
369       },
370   /* [PIX_FMT_RGB555] = */ {
371         /* .format         = */ PIX_FMT_RGB555,
372         /* .name           = */ "rgb555",
373         /* .nb_channels    = */ 4,
374         /* .color_type     = */ FF_COLOR_RGB,
375         /* .pixel_type     = */ FF_PIXEL_PACKED,
376         /* .is_alpha       = */ 1,
377         /* .x_chroma_shift = */ 0,
378         /* .y_chroma_shift = */ 0,
379         /* .depth          = */ 5,
380       },
381
382   /* gray / mono formats */
383   /* [PIX_FMT_GRAY8] = */ {
384         /* .format         = */ PIX_FMT_GRAY8,
385         /* .name           = */ "gray",
386         /* .nb_channels    = */ 1,
387         /* .color_type     = */ FF_COLOR_GRAY,
388         /* .pixel_type     = */ FF_PIXEL_PLANAR,
389         /* .is_alpha       = */ 0,
390         /* .x_chroma_shift = */ 0,
391         /* .y_chroma_shift = */ 0,
392         /* .depth          = */ 8,
393       },
394   /* [PIX_FMT_GRAY16_L] = */ {
395         /* .format         = */ PIX_FMT_GRAY16_L,
396         /* .name           = */ "gray",
397         /* .nb_channels    = */ 1,
398         /* .color_type     = */ FF_COLOR_GRAY,
399         /* .pixel_type     = */ FF_PIXEL_PLANAR,
400         /* .is_alpha       = */ 0,
401         /* .x_chroma_shift = */ 0,
402         /* .y_chroma_shift = */ 0,
403         /* .depth          = */ 16,
404       },
405   /* [PIX_FMT_GRAY16_B] = */ {
406         /* .format         = */ PIX_FMT_GRAY16_B,
407         /* .name           = */ "gray",
408         /* .nb_channels    = */ 1,
409         /* .color_type     = */ FF_COLOR_GRAY,
410         /* .pixel_type     = */ FF_PIXEL_PLANAR,
411         /* .is_alpha       = */ 0,
412         /* .x_chroma_shift = */ 0,
413         /* .y_chroma_shift = */ 0,
414         /* .depth          = */ 16,
415       },
416   /* [PIX_FMT_MONOWHITE] = */ {
417         /* .format         = */ PIX_FMT_MONOWHITE,
418         /* .name           = */ "monow",
419         /* .nb_channels    = */ 1,
420         /* .color_type     = */ FF_COLOR_GRAY,
421         /* .pixel_type     = */ FF_PIXEL_PLANAR,
422         /* .is_alpha       = */ 0,
423         /* .x_chroma_shift = */ 0,
424         /* .y_chroma_shift = */ 0,
425         /* .depth          = */ 1,
426       },
427   /* [PIX_FMT_MONOBLACK] = */ {
428         /* .format         = */ PIX_FMT_MONOBLACK,
429         /* .name           = */ "monob",
430         /* .nb_channels    = */ 1,
431         /* .color_type     = */ FF_COLOR_GRAY,
432         /* .pixel_type     = */ FF_PIXEL_PLANAR,
433         /* .is_alpha       = */ 0,
434         /* .x_chroma_shift = */ 0,
435         /* .y_chroma_shift = */ 0,
436         /* .depth          = */ 1,
437       },
438
439   /* paletted formats */
440   /* [PIX_FMT_PAL8] = */ {
441         /* .format         = */ PIX_FMT_PAL8,
442         /* .name           = */ "pal8",
443         /* .nb_channels    = */ 4,
444         /* .color_type     = */ FF_COLOR_RGB,
445         /* .pixel_type     = */ FF_PIXEL_PALETTE,
446         /* .is_alpha       = */ 1,
447         /* .x_chroma_shift = */ 0,
448         /* .y_chroma_shift = */ 0,
449         /* .depth          = */ 8,
450       },
451   /* [PIX_FMT_XVMC_MPEG2_MC] = */ {
452         /* .format         = */ PIX_FMT_XVMC_MPEG2_MC,
453         /* .name           = */ "xvmcmc",
454       },
455   /* [PIX_FMT_XVMC_MPEG2_IDCT] = */ {
456         /* .format         = */ PIX_FMT_XVMC_MPEG2_IDCT,
457         /* .name           = */ "xvmcidct",
458       },
459   /* [PIX_FMT_UYVY411] = */ {
460         /* .format         = */ PIX_FMT_UYVY411,
461         /* .name           = */ "uyvy411",
462         /* .nb_channels    = */ 1,
463         /* .color_type     = */ FF_COLOR_YUV,
464         /* .pixel_type     = */ FF_PIXEL_PACKED,
465         /* .is_alpha       = */ 0,
466         /* .x_chroma_shift = */ 2,
467         /* .y_chroma_shift = */ 0,
468         /* .depth          = */ 8,
469       },
470   /* [PIX_FMT_AYUV4444] = */ {
471         /* .format         = */ PIX_FMT_AYUV4444,
472         /* .name           = */ "ayuv4444",
473         /* .nb_channels    = */ 1,
474         /* .color_type     = */ FF_COLOR_YUV,
475         /* .pixel_type     = */ FF_PIXEL_PACKED,
476         /* .is_alpha       = */ 1,
477         /* .x_chroma_shift = */ 0,
478         /* .y_chroma_shift = */ 0,
479         /*.depth = */ 8
480       },
481   /* [PIX_FMT_YUVA420P] = */ {
482         /* .format         = */ PIX_FMT_YUVA420P,
483         /* .name           = */ "yuva420p",
484         /* .nb_channels    = */ 4,
485         /* .color_type     = */ FF_COLOR_YUV,
486         /* .pixel_type     = */ FF_PIXEL_PLANAR,
487         /* .is_alpha       = */ 1,
488         /* .x_chroma_shift = */ 1,
489         /* .y_chroma_shift = */ 1,
490         /* .depth          = */ 8,
491       }
492 };
493
494 /* returns NULL if not found */
495 /* undid static since this is also used in gstffmpegcodecmap.c */
496 PixFmtInfo *
497 get_pix_fmt_info (enum PixelFormat format)
498 {
499   int i;
500
501   for (i = 0; i < sizeof (pix_fmt_info) / sizeof (pix_fmt_info[0]); i++) {
502     if (pix_fmt_info[i].format == format) {
503       return pix_fmt_info + i;
504     }
505   }
506
507   /* since this doesn't get checked *anywhere*, we might as well warn
508      here if we return NULL so you have *some* idea what's going on */
509   g_warning
510       ("Could not find info for pixel format %d out of %d known pixel formats. One segfault coming up",
511       format, PIX_FMT_NB);
512   return NULL;
513 }
514
515 void
516 avcodec_get_chroma_sub_sample (int pix_fmt, int *h_shift, int *v_shift)
517 {
518   *h_shift = get_pix_fmt_info (pix_fmt)->x_chroma_shift;
519   *v_shift = get_pix_fmt_info (pix_fmt)->y_chroma_shift;
520 }
521
522 const char *
523 avcodec_get_pix_fmt_name (int pix_fmt)
524 {
525   if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
526     return "???";
527   else
528     return get_pix_fmt_info (pix_fmt)->name;
529 }
530
531 enum PixelFormat
532 avcodec_get_pix_fmt (const char *name)
533 {
534   int i;
535
536   for (i = 0; i < PIX_FMT_NB; i++)
537     if (!strcmp (pix_fmt_info[i].name, name))
538       break;
539   return pix_fmt_info[i].format;
540 }
541
542 #if 0
543 static int
544 avpicture_layout (const AVPicture * src, int pix_fmt, int width, int height,
545     unsigned char *dest, int dest_size)
546 {
547   PixFmtInfo *pf = get_pix_fmt_info (pix_fmt);
548   int i, j, w, h, data_planes;
549   const unsigned char *s;
550   int size = avpicture_get_size (pix_fmt, width, height);
551
552   if (size > dest_size)
553     return -1;
554
555   if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
556     if (pix_fmt == PIX_FMT_YUV422 ||
557         pix_fmt == PIX_FMT_UYVY422 ||
558         pix_fmt == PIX_FMT_RGB565 || pix_fmt == PIX_FMT_RGB555)
559       w = width * 2;
560     else if (pix_fmt == PIX_FMT_UYVY411)
561       w = width + width / 2;
562     else if (pix_fmt == PIX_FMT_PAL8)
563       w = width;
564     else
565       w = width * (pf->depth * pf->nb_channels / 8);
566
567     data_planes = 1;
568     h = height;
569   } else {
570     data_planes = pf->nb_channels;
571     w = (width * pf->depth + 7) / 8;
572     h = height;
573   }
574
575   for (i = 0; i < data_planes; i++) {
576     if (i == 1) {
577       w = width >> pf->x_chroma_shift;
578       h = height >> pf->y_chroma_shift;
579     }
580     s = src->data[i];
581     for (j = 0; j < h; j++) {
582       memcpy (dest, s, w);
583       dest += w;
584       s += src->linesize[i];
585     }
586   }
587
588   if (pf->pixel_type == FF_PIXEL_PALETTE)
589     memcpy ((unsigned char *) (((size_t) dest + 3) & ~3), src->data[1],
590         256 * 4);
591
592   return size;
593 }
594 #endif
595
596 int
597 avpicture_get_size (int pix_fmt, int width, int height)
598 {
599   AVPicture dummy_pict;
600
601   return gst_ffmpegcsp_avpicture_fill (&dummy_pict, NULL, pix_fmt, width,
602       height, FALSE);
603 }
604
605 /**
606  * compute the loss when converting from a pixel format to another 
607  */
608 int
609 avcodec_get_pix_fmt_loss (int dst_pix_fmt, int src_pix_fmt, int has_alpha)
610 {
611   const PixFmtInfo *pf, *ps;
612   int loss;
613
614   ps = get_pix_fmt_info (src_pix_fmt);
615   pf = get_pix_fmt_info (dst_pix_fmt);
616
617   /* compute loss */
618   loss = 0;
619   if (pf->depth < ps->depth ||
620       (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
621     loss |= FF_LOSS_DEPTH;
622   if (pf->x_chroma_shift > ps->x_chroma_shift ||
623       pf->y_chroma_shift > ps->y_chroma_shift)
624     loss |= FF_LOSS_RESOLUTION;
625   switch (pf->color_type) {
626     case FF_COLOR_RGB:
627       if (ps->color_type != FF_COLOR_RGB && ps->color_type != FF_COLOR_GRAY)
628         loss |= FF_LOSS_COLORSPACE;
629       break;
630     case FF_COLOR_GRAY:
631       if (ps->color_type != FF_COLOR_GRAY)
632         loss |= FF_LOSS_COLORSPACE;
633       break;
634     case FF_COLOR_YUV:
635       if (ps->color_type != FF_COLOR_YUV)
636         loss |= FF_LOSS_COLORSPACE;
637       break;
638     case FF_COLOR_YUV_JPEG:
639       if (ps->color_type != FF_COLOR_YUV_JPEG &&
640           ps->color_type != FF_COLOR_YUV && ps->color_type != FF_COLOR_GRAY)
641         loss |= FF_LOSS_COLORSPACE;
642       break;
643     default:
644       /* fail safe test */
645       if (ps->color_type != pf->color_type)
646         loss |= FF_LOSS_COLORSPACE;
647       break;
648   }
649   if (pf->color_type == FF_COLOR_GRAY && ps->color_type != FF_COLOR_GRAY)
650     loss |= FF_LOSS_CHROMA;
651   if (!pf->is_alpha && (ps->is_alpha && has_alpha))
652     loss |= FF_LOSS_ALPHA;
653   if (pf->pixel_type == FF_PIXEL_PALETTE &&
654       (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
655     loss |= FF_LOSS_COLORQUANT;
656   return loss;
657 }
658
659 static int
660 avg_bits_per_pixel (int pix_fmt)
661 {
662   int bits;
663   const PixFmtInfo *pf;
664
665   pf = get_pix_fmt_info (pix_fmt);
666   switch (pf->pixel_type) {
667     case FF_PIXEL_PACKED:
668       switch (pix_fmt) {
669         case PIX_FMT_YUV422:
670         case PIX_FMT_UYVY422:
671         case PIX_FMT_YVYU422:
672         case PIX_FMT_RGB565:
673         case PIX_FMT_RGB555:
674           bits = 16;
675           break;
676         case PIX_FMT_UYVY411:
677           bits = 12;
678           break;
679         default:
680           bits = pf->depth * pf->nb_channels;
681           break;
682       }
683       break;
684     case FF_PIXEL_PLANAR:
685       if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
686         bits = pf->depth * pf->nb_channels;
687       } else {
688         bits = pf->depth + ((2 * pf->depth) >>
689             (pf->x_chroma_shift + pf->y_chroma_shift));
690       }
691       break;
692     case FF_PIXEL_PALETTE:
693       bits = 8;
694       break;
695     default:
696       bits = -1;
697       break;
698   }
699   return bits;
700 }
701
702 static int
703 avcodec_find_best_pix_fmt1 (int pix_fmt_mask,
704     int src_pix_fmt, int has_alpha, int loss_mask)
705 {
706   int dist, i, loss, min_dist, dst_pix_fmt;
707
708   /* find exact color match with smallest size */
709   dst_pix_fmt = -1;
710   min_dist = 0x7fffffff;
711   for (i = 0; i < PIX_FMT_NB; i++) {
712     if (pix_fmt_mask & (1 << i)) {
713       loss = avcodec_get_pix_fmt_loss (i, src_pix_fmt, has_alpha) & loss_mask;
714       if (loss == 0) {
715         dist = avg_bits_per_pixel (i);
716         if (dist < min_dist) {
717           min_dist = dist;
718           dst_pix_fmt = i;
719         }
720       }
721     }
722   }
723   return dst_pix_fmt;
724 }
725
726 /** 
727  * find best pixel format to convert to. Return -1 if none found 
728  */
729 int
730 avcodec_find_best_pix_fmt (int pix_fmt_mask, int src_pix_fmt,
731     int has_alpha, int *loss_ptr)
732 {
733   int dst_pix_fmt, loss_mask, i;
734   static const int loss_mask_order[] = {
735     ~0,                         /* no loss first */
736     ~FF_LOSS_ALPHA,
737     ~FF_LOSS_RESOLUTION,
738     ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
739     ~FF_LOSS_COLORQUANT,
740     ~FF_LOSS_DEPTH,
741     0,
742   };
743
744   /* try with successive loss */
745   i = 0;
746   for (;;) {
747     loss_mask = loss_mask_order[i++];
748     dst_pix_fmt = avcodec_find_best_pix_fmt1 (pix_fmt_mask, src_pix_fmt,
749         has_alpha, loss_mask);
750     if (dst_pix_fmt >= 0)
751       goto found;
752     if (loss_mask == 0)
753       break;
754   }
755   return -1;
756 found:
757   if (loss_ptr)
758     *loss_ptr = avcodec_get_pix_fmt_loss (dst_pix_fmt, src_pix_fmt, has_alpha);
759   return dst_pix_fmt;
760 }
761
762 static void
763 img_copy_plane (uint8_t * dst, int dst_wrap,
764     const uint8_t * src, int src_wrap, int width, int height)
765 {
766   for (; height > 0; height--) {
767     memcpy (dst, src, width);
768     dst += dst_wrap;
769     src += src_wrap;
770   }
771 }
772
773 /**
774  * Copy image 'src' to 'dst'.
775  */
776 static void
777 img_copy (AVPicture * dst, const AVPicture * src,
778     int pix_fmt, int width, int height)
779 {
780   int bwidth, bits, i;
781   const PixFmtInfo *pf;
782
783   pf = get_pix_fmt_info (pix_fmt);
784   switch (pf->pixel_type) {
785     case FF_PIXEL_PACKED:
786       switch (pix_fmt) {
787         case PIX_FMT_YUV422:
788         case PIX_FMT_UYVY422:
789         case PIX_FMT_YVYU422:
790         case PIX_FMT_RGB565:
791         case PIX_FMT_RGB555:
792           bits = 16;
793           break;
794         case PIX_FMT_UYVY411:
795           bits = 12;
796           break;
797         default:
798           bits = pf->depth * pf->nb_channels;
799           break;
800       }
801       bwidth = (width * bits + 7) >> 3;
802       img_copy_plane (dst->data[0], dst->linesize[0],
803           src->data[0], src->linesize[0], bwidth, height);
804       break;
805     case FF_PIXEL_PLANAR:
806       for (i = 0; i < pf->nb_channels; i++) {
807         int w, h;
808
809         w = width;
810         h = height;
811         if (i == 1 || i == 2) {
812           w >>= pf->x_chroma_shift;
813           h >>= pf->y_chroma_shift;
814         }
815         bwidth = (w * pf->depth + 7) >> 3;
816         img_copy_plane (dst->data[i], dst->linesize[i],
817             src->data[i], src->linesize[i], bwidth, h);
818       }
819       break;
820     case FF_PIXEL_PALETTE:
821       img_copy_plane (dst->data[0], dst->linesize[0],
822           src->data[0], src->linesize[0], width, height);
823       /* copy the palette */
824       img_copy_plane (dst->data[1], dst->linesize[1],
825           src->data[1], src->linesize[1], 4, 256);
826       break;
827   }
828 }
829
830 /* XXX: totally non optimized */
831
832 static void
833 yuv422_to_yuv420p (AVPicture * dst, const AVPicture * src,
834     int width, int height)
835 {
836   const uint8_t *p, *p1;
837   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
838   int w;
839
840   p1 = src->data[0];
841   lum1 = dst->data[0];
842   cb1 = dst->data[1];
843   cr1 = dst->data[2];
844
845   for (; height >= 1; height -= 2) {
846     p = p1;
847     lum = lum1;
848     cb = cb1;
849     cr = cr1;
850     for (w = width; w >= 2; w -= 2) {
851       lum[0] = p[0];
852       cb[0] = p[1];
853       lum[1] = p[2];
854       cr[0] = p[3];
855       p += 4;
856       lum += 2;
857       cb++;
858       cr++;
859     }
860     if (w) {
861       lum[0] = p[0];
862       cb[0] = p[1];
863       cr[0] = p[3];
864     }
865     p1 += src->linesize[0];
866     lum1 += dst->linesize[0];
867     if (height > 1) {
868       p = p1;
869       lum = lum1;
870       for (w = width; w >= 2; w -= 2) {
871         lum[0] = p[0];
872         lum[1] = p[2];
873         p += 4;
874         lum += 2;
875       }
876       if (w) {
877         lum[0] = p[0];
878       }
879       p1 += src->linesize[0];
880       lum1 += dst->linesize[0];
881     }
882     cb1 += dst->linesize[1];
883     cr1 += dst->linesize[2];
884   }
885 }
886
887 static void
888 uyvy422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
889 {
890   const uint8_t *p, *p1;
891   uint8_t *lum, *lum1;
892   int w;
893
894   p1 = src->data[0];
895   lum1 = dst->data[0];
896   for (; height > 0; height--) {
897     p = p1;
898     lum = lum1;
899
900     for (w = width; w >= 2; w -= 2) {
901       lum[0] = p[1];
902       lum[1] = p[3];
903       p += 4;
904       lum += 2;
905     }
906
907     if (w)
908       lum[0] = p[1];
909
910     p1 += src->linesize[0];
911     lum1 += dst->linesize[0];
912   }
913 }
914
915
916 static void
917 uyvy422_to_yuv420p (AVPicture * dst, const AVPicture * src,
918     int width, int height)
919 {
920   const uint8_t *p, *p1;
921   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
922   int w;
923
924   p1 = src->data[0];
925
926   lum1 = dst->data[0];
927   cb1 = dst->data[1];
928   cr1 = dst->data[2];
929
930   for (; height >= 1; height -= 2) {
931     p = p1;
932     lum = lum1;
933     cb = cb1;
934     cr = cr1;
935     for (w = width; w >= 2; w -= 2) {
936       lum[0] = p[1];
937       cb[0] = p[0];
938       lum[1] = p[3];
939       cr[0] = p[2];
940       p += 4;
941       lum += 2;
942       cb++;
943       cr++;
944     }
945     if (w) {
946       lum[0] = p[1];
947       cb[0] = p[0];
948       cr[0] = p[2];
949     }
950     p1 += src->linesize[0];
951     lum1 += dst->linesize[0];
952     if (height > 1) {
953       p = p1;
954       lum = lum1;
955       for (w = width; w >= 2; w -= 2) {
956         lum[0] = p[1];
957         lum[1] = p[3];
958         p += 4;
959         lum += 2;
960       }
961       if (w) {
962         lum[0] = p[1];
963       }
964       p1 += src->linesize[0];
965       lum1 += dst->linesize[0];
966     }
967     cb1 += dst->linesize[1];
968     cr1 += dst->linesize[2];
969   }
970 }
971
972
973 static void
974 uyvy422_to_yuv422p (AVPicture * dst, const AVPicture * src,
975     int width, int height)
976 {
977   const uint8_t *p, *p1;
978   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
979   int w;
980
981   p1 = src->data[0];
982   lum1 = dst->data[0];
983   cb1 = dst->data[1];
984   cr1 = dst->data[2];
985   for (; height > 0; height--) {
986     p = p1;
987     lum = lum1;
988     cb = cb1;
989     cr = cr1;
990     for (w = width; w >= 2; w -= 2) {
991       lum[0] = p[1];
992       cb[0] = p[0];
993       lum[1] = p[3];
994       cr[0] = p[2];
995       p += 4;
996       lum += 2;
997       cb++;
998       cr++;
999     }
1000     if (w) {
1001       lum[0] = p[1];
1002       cb[0] = p[0];
1003       cr[0] = p[2];
1004     }
1005     p1 += src->linesize[0];
1006     lum1 += dst->linesize[0];
1007     cb1 += dst->linesize[1];
1008     cr1 += dst->linesize[2];
1009   }
1010 }
1011
1012 static void
1013 yvyu422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
1014 {
1015   const uint8_t *p, *p1;
1016   uint8_t *lum, *lum1;
1017   int w;
1018
1019   p1 = src->data[0];
1020   lum1 = dst->data[0];
1021   for (; height > 0; height--) {
1022     p = p1;
1023     lum = lum1;
1024
1025     for (w = width; w >= 2; w -= 2) {
1026       lum[0] = p[0];
1027       lum[1] = p[2];
1028       p += 4;
1029       lum += 2;
1030     }
1031
1032     if (w)
1033       lum[0] = p[0];
1034
1035     p1 += src->linesize[0];
1036     lum1 += dst->linesize[0];
1037   }
1038 }
1039
1040 static void
1041 yvyu422_to_yuv420p (AVPicture * dst, const AVPicture * src,
1042     int width, int height)
1043 {
1044   const uint8_t *p, *p1;
1045   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1046   int w;
1047
1048   p1 = src->data[0];
1049
1050   lum1 = dst->data[0];
1051   cb1 = dst->data[1];
1052   cr1 = dst->data[2];
1053
1054   for (; height >= 1; height -= 2) {
1055     p = p1;
1056     lum = lum1;
1057     cb = cb1;
1058     cr = cr1;
1059     for (w = width; w >= 2; w -= 2) {
1060       lum[0] = p[0];
1061       cb[0] = p[3];
1062       lum[1] = p[2];
1063       cr[0] = p[1];
1064       p += 4;
1065       lum += 2;
1066       cb++;
1067       cr++;
1068     }
1069     if (w) {
1070       lum[0] = p[0];
1071       cb[0] = p[3];
1072       cr[0] = p[1];
1073     }
1074     p1 += src->linesize[0];
1075     lum1 += dst->linesize[0];
1076     if (height > 1) {
1077       p = p1;
1078       lum = lum1;
1079       for (w = width; w >= 2; w -= 2) {
1080         lum[0] = p[0];
1081         lum[1] = p[2];
1082         p += 4;
1083         lum += 2;
1084       }
1085       if (w) {
1086         lum[0] = p[0];
1087       }
1088       p1 += src->linesize[0];
1089       lum1 += dst->linesize[0];
1090     }
1091     cb1 += dst->linesize[1];
1092     cr1 += dst->linesize[2];
1093   }
1094 }
1095
1096 static void
1097 yvyu422_to_yuv422p (AVPicture * dst, const AVPicture * src,
1098     int width, int height)
1099 {
1100   const uint8_t *p, *p1;
1101   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1102   int w;
1103
1104   p1 = src->data[0];
1105   lum1 = dst->data[0];
1106   cb1 = dst->data[1];
1107   cr1 = dst->data[2];
1108   for (; height > 0; height--) {
1109     p = p1;
1110     lum = lum1;
1111     cb = cb1;
1112     cr = cr1;
1113     for (w = width; w >= 2; w -= 2) {
1114       lum[0] = p[0];
1115       cb[0] = p[3];
1116       lum[1] = p[2];
1117       cr[0] = p[1];
1118       p += 4;
1119       lum += 2;
1120       cb++;
1121       cr++;
1122     }
1123     if (w) {
1124       lum[0] = p[0];
1125       cb[0] = p[3];
1126       cr[0] = p[1];
1127     }
1128     p1 += src->linesize[0];
1129     lum1 += dst->linesize[0];
1130     cb1 += dst->linesize[1];
1131     cr1 += dst->linesize[2];
1132   }
1133 }
1134
1135 static void
1136 yuv422_to_yuv422p (AVPicture * dst, const AVPicture * src,
1137     int width, int height)
1138 {
1139   const uint8_t *p, *p1;
1140   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1141   int w;
1142
1143   p1 = src->data[0];
1144   lum1 = dst->data[0];
1145   cb1 = dst->data[1];
1146   cr1 = dst->data[2];
1147   for (; height > 0; height--) {
1148     p = p1;
1149     lum = lum1;
1150     cb = cb1;
1151     cr = cr1;
1152     for (w = width; w >= 2; w -= 2) {
1153       lum[0] = p[0];
1154       cb[0] = p[1];
1155       lum[1] = p[2];
1156       cr[0] = p[3];
1157       p += 4;
1158       lum += 2;
1159       cb++;
1160       cr++;
1161     }
1162     if (w) {
1163       lum[0] = p[0];
1164       cb[0] = p[1];
1165       cr[0] = p[3];
1166     }
1167     p1 += src->linesize[0];
1168     lum1 += dst->linesize[0];
1169     cb1 += dst->linesize[1];
1170     cr1 += dst->linesize[2];
1171   }
1172 }
1173
1174 static void
1175 yuv422p_to_yuv422 (AVPicture * dst, const AVPicture * src,
1176     int width, int height)
1177 {
1178   uint8_t *p, *p1;
1179   const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1180   int w;
1181
1182   p1 = dst->data[0];
1183   lum1 = src->data[0];
1184   cb1 = src->data[1];
1185   cr1 = src->data[2];
1186   for (; height > 0; height--) {
1187     p = p1;
1188     lum = lum1;
1189     cb = cb1;
1190     cr = cr1;
1191     for (w = width; w >= 2; w -= 2) {
1192       p[0] = lum[0];
1193       p[1] = cb[0];
1194       p[2] = lum[1];
1195       p[3] = cr[0];
1196       p += 4;
1197       lum += 2;
1198       cb++;
1199       cr++;
1200     }
1201     if (w) {
1202       p[0] = lum[0];
1203       p[1] = cb[0];
1204       p[3] = cr[0];
1205     }
1206     p1 += dst->linesize[0];
1207     lum1 += src->linesize[0];
1208     cb1 += src->linesize[1];
1209     cr1 += src->linesize[2];
1210   }
1211 }
1212
1213 static void
1214 yuv422p_to_uyvy422 (AVPicture * dst, const AVPicture * src,
1215     int width, int height)
1216 {
1217   uint8_t *p, *p1;
1218   const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1219   int w;
1220
1221   p1 = dst->data[0];
1222   lum1 = src->data[0];
1223   cb1 = src->data[1];
1224   cr1 = src->data[2];
1225   for (; height > 0; height--) {
1226     p = p1;
1227     lum = lum1;
1228     cb = cb1;
1229     cr = cr1;
1230     for (w = width; w >= 2; w -= 2) {
1231       p[1] = lum[0];
1232       p[0] = cb[0];
1233       p[3] = lum[1];
1234       p[2] = cr[0];
1235       p += 4;
1236       lum += 2;
1237       cb++;
1238       cr++;
1239     }
1240     if (w) {
1241       p[1] = lum[0];
1242       p[0] = cb[0];
1243       p[2] = cr[0];
1244     }
1245     p1 += dst->linesize[0];
1246     lum1 += src->linesize[0];
1247     cb1 += src->linesize[1];
1248     cr1 += src->linesize[2];
1249   }
1250 }
1251
1252 static void
1253 yuv422p_to_yvyu422 (AVPicture * dst, const AVPicture * src,
1254     int width, int height)
1255 {
1256   uint8_t *p, *p1;
1257   const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1258   int w;
1259
1260   p1 = dst->data[0];
1261   lum1 = src->data[0];
1262   cb1 = src->data[1];
1263   cr1 = src->data[2];
1264   for (; height > 0; height--) {
1265     p = p1;
1266     lum = lum1;
1267     cb = cb1;
1268     cr = cr1;
1269     for (w = width; w >= 2; w -= 2) {
1270       p[0] = lum[0];
1271       p[3] = cb[0];
1272       p[2] = lum[1];
1273       p[1] = cr[0];
1274       p += 4;
1275       lum += 2;
1276       cb++;
1277       cr++;
1278     }
1279     if (w) {
1280       p[0] = lum[0];
1281       p[3] = cb[0];
1282       p[1] = cr[0];
1283     }
1284     p1 += dst->linesize[0];
1285     lum1 += src->linesize[0];
1286     cb1 += src->linesize[1];
1287     cr1 += src->linesize[2];
1288   }
1289 }
1290
1291 static void
1292 uyvy411_to_yuv411p (AVPicture * dst, const AVPicture * src,
1293     int width, int height)
1294 {
1295   const uint8_t *p, *p1;
1296   uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1297   int w;
1298
1299   p1 = src->data[0];
1300   lum1 = dst->data[0];
1301   cb1 = dst->data[1];
1302   cr1 = dst->data[2];
1303   for (; height > 0; height--) {
1304     p = p1;
1305     lum = lum1;
1306     cb = cb1;
1307     cr = cr1;
1308     for (w = width; w >= 4; w -= 4) {
1309       cb[0] = p[0];
1310       lum[0] = p[1];
1311       lum[1] = p[2];
1312       cr[0] = p[3];
1313       lum[2] = p[4];
1314       lum[3] = p[5];
1315       p += 6;
1316       lum += 4;
1317       cb++;
1318       cr++;
1319     }
1320     p1 += src->linesize[0];
1321     lum1 += dst->linesize[0];
1322     cb1 += dst->linesize[1];
1323     cr1 += dst->linesize[2];
1324   }
1325 }
1326
1327 static void
1328 yuv411p_to_uyvy411 (AVPicture * dst, const AVPicture * src,
1329     int width, int height)
1330 {
1331   uint8_t *p, *p1;
1332   const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
1333   int w;
1334
1335   p1 = dst->data[0];
1336   lum1 = src->data[0];
1337   cb1 = src->data[1];
1338   cr1 = src->data[2];
1339   for (; height > 0; height--) {
1340     p = p1;
1341     lum = lum1;
1342     cb = cb1;
1343     cr = cr1;
1344     for (w = width; w >= 4; w -= 4) {
1345       p[0] = cb[0];
1346       p[1] = lum[0];
1347       p[2] = lum[1];
1348       p[3] = cr[0];
1349       p[4] = lum[2];
1350       p[5] = lum[3];
1351       p += 6;
1352       lum += 4;
1353       cb++;
1354       cr++;
1355     }
1356     p1 += dst->linesize[0];
1357     lum1 += src->linesize[0];
1358     cb1 += src->linesize[1];
1359     cr1 += src->linesize[2];
1360   }
1361 }
1362
1363 static void
1364 yuv420p_to_yuv422 (AVPicture * dst, const AVPicture * src,
1365     int width, int height)
1366 {
1367   int w, h;
1368   uint8_t *line1, *line2, *linesrc = dst->data[0];
1369   uint8_t *lum1, *lum2, *lumsrc = src->data[0];
1370   uint8_t *cb1, *cb2 = src->data[1];
1371   uint8_t *cr1, *cr2 = src->data[2];
1372
1373   for (h = height / 2; h--;) {
1374     line1 = linesrc;
1375     line2 = linesrc + dst->linesize[0];
1376
1377     lum1 = lumsrc;
1378     lum2 = lumsrc + src->linesize[0];
1379
1380     cb1 = cb2;
1381     cr1 = cr2;
1382
1383     for (w = width / 2; w--;) {
1384       *line1++ = *lum1++;
1385       *line2++ = *lum2++;
1386       *line1++ = *line2++ = *cb1++;
1387       *line1++ = *lum1++;
1388       *line2++ = *lum2++;
1389       *line1++ = *line2++ = *cr1++;
1390     }
1391     /* odd width */
1392     if (width % 2 != 0) {
1393       *line1++ = *lum1++;
1394       *line2++ = *lum2++;
1395       *line1++ = *line2++ = *cb1++;
1396     }
1397
1398     linesrc += dst->linesize[0] * 2;
1399     lumsrc += src->linesize[0] * 2;
1400     cb2 += src->linesize[1];
1401     cr2 += src->linesize[2];
1402   }
1403   /* odd height */
1404   if (height % 2 != 0) {
1405     line1 = linesrc;
1406     lum1 = lumsrc;
1407     cb1 = cb2;
1408     cr1 = cr2;
1409
1410     for (w = width / 2; w--;) {
1411       *line1++ = *lum1++;
1412       *line1++ = *cb1++;
1413       *line1++ = *lum1++;
1414       *line1++ = *cr1++;
1415     }
1416     /* odd width */
1417     if (width % 2 != 0) {
1418       *line1++ = *lum1++;
1419       *line1++ = *cb1++;
1420     }
1421   }
1422 }
1423
1424 static void
1425 nv12_to_nv21 (AVPicture * dst, const AVPicture * src, int width, int height)
1426 {
1427   const uint8_t *s_c_ptr;
1428   uint8_t *d_c_ptr;
1429   int w, c_wrap;
1430
1431   memcpy (dst->data[0], src->data[0], src->linesize[0] * height);
1432
1433   s_c_ptr = src->data[1];
1434   d_c_ptr = dst->data[1];
1435   c_wrap = src->linesize[1] - ((width + 1) & ~0x01);
1436
1437   for (; height >= 2; height -= 2) {
1438     for (w = width; w >= 2; w -= 2) {
1439       d_c_ptr[0] = s_c_ptr[1];
1440       d_c_ptr[1] = s_c_ptr[0];
1441       s_c_ptr += 2;
1442       d_c_ptr += 2;
1443     }
1444
1445     /* handle odd width */
1446     if (w) {
1447       d_c_ptr[0] = s_c_ptr[1];
1448       d_c_ptr[1] = s_c_ptr[0];
1449       s_c_ptr += 2;
1450       d_c_ptr += 2;
1451     }
1452     s_c_ptr += c_wrap;
1453     d_c_ptr += c_wrap;
1454   }
1455
1456   /* handle odd height */
1457   if (height) {
1458     for (w = width; w >= 2; w -= 2) {
1459       d_c_ptr[0] = s_c_ptr[1];
1460       d_c_ptr[1] = s_c_ptr[0];
1461       s_c_ptr += 2;
1462       d_c_ptr += 2;
1463     }
1464
1465     /* handle odd width */
1466     if (w) {
1467       d_c_ptr[0] = s_c_ptr[1];
1468       d_c_ptr[1] = s_c_ptr[0];
1469       s_c_ptr += 2;
1470       d_c_ptr += 2;
1471     }
1472   }
1473 }
1474
1475 static void
1476 nv12_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height)
1477 {
1478   int w, h;
1479   uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0];
1480   uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1];
1481   uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2];
1482   uint8_t *lum1, *lum2, *src_lum_line = src->data[0];
1483   uint8_t *src_c1, *src_c_line = src->data[1];
1484   uint8_t cb, cr;
1485
1486   for (h = height / 2; h--;) {
1487     dst_lum1 = dst_line;
1488     dst_lum2 = dst_line + dst->linesize[0];
1489
1490     dst_cb1 = dst_cb_line;
1491     dst_cb2 = dst_cb_line + dst->linesize[1];
1492     dst_cr1 = dst_cr_line;
1493     dst_cr2 = dst_cr_line + dst->linesize[2];
1494
1495     lum1 = src_lum_line;
1496     lum2 = src_lum_line + src->linesize[0];
1497
1498     src_c1 = src_c_line;
1499
1500     for (w = width / 2; w--;) {
1501       cb = *src_c1++;
1502       cr = *src_c1++;
1503       *dst_lum1++ = *lum1++;
1504       *dst_lum2++ = *lum2++;
1505       *dst_cb1++ = *dst_cb2++ = cb;
1506       *dst_cr1++ = *dst_cr2++ = cr;
1507       *dst_lum1++ = *lum1++;
1508       *dst_lum2++ = *lum2++;
1509       *dst_cb1++ = *dst_cb2++ = cb;
1510       *dst_cr1++ = *dst_cr2++ = cr;
1511     }
1512     /* odd width */
1513     if (width % 2 != 0) {
1514       cb = *src_c1++;
1515       cr = *src_c1++;
1516       *dst_lum1++ = *lum1++;
1517       *dst_lum2++ = *lum2++;
1518       *dst_cb1++ = *dst_cb2++ = *src_c1++;
1519       *dst_cr1++ = *dst_cr2++ = *src_c1++;
1520     }
1521
1522     dst_line += dst->linesize[0] * 2;
1523     dst_cb_line += dst->linesize[1] * 2;
1524     dst_cr_line += dst->linesize[2] * 2;
1525     src_lum_line += src->linesize[0] * 2;
1526     src_c_line += src->linesize[1];
1527   }
1528
1529   /* odd height */
1530   if (height % 2 != 0) {
1531     dst_lum1 = dst_line;
1532     lum1 = src_lum_line;
1533     src_c1 = src_c_line;
1534     dst_cb1 = dst_cb_line;
1535     dst_cr1 = dst_cr_line;
1536
1537     for (w = width / 2; w--;) {
1538       cb = *src_c1++;
1539       cr = *src_c1++;
1540       *dst_lum1++ = *lum1++;
1541       *dst_cb1++ = cb;
1542       *dst_cr1++ = cr;
1543       *dst_lum1++ = *lum1++;
1544       *dst_cb1++ = cb;
1545       *dst_cr1++ = cr;
1546     }
1547     /* odd width */
1548     if (width % 2 != 0) {
1549       cb = *src_c1++;
1550       cr = *src_c1++;
1551       *dst_lum1++ = *lum1++;
1552       *dst_cb1++ = cb;
1553       *dst_cr1++ = cr;
1554     }
1555   }
1556 }
1557
1558 #define nv21_to_nv12 nv12_to_nv21
1559
1560 static void
1561 nv21_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height)
1562 {
1563   int w, h;
1564   uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0];
1565   uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1];
1566   uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2];
1567   uint8_t *lum1, *lum2, *src_lum_line = src->data[0];
1568   uint8_t *src_c1, *src_c_line = src->data[1];
1569   uint8_t cb, cr;
1570
1571   for (h = height / 2; h--;) {
1572     dst_lum1 = dst_line;
1573     dst_lum2 = dst_line + dst->linesize[0];
1574
1575     dst_cb1 = dst_cb_line;
1576     dst_cb2 = dst_cb_line + dst->linesize[1];
1577     dst_cr1 = dst_cr_line;
1578     dst_cr2 = dst_cr_line + dst->linesize[2];
1579
1580     lum1 = src_lum_line;
1581     lum2 = src_lum_line + src->linesize[0];
1582
1583     src_c1 = src_c_line;
1584
1585     for (w = width / 2; w--;) {
1586       cr = *src_c1++;
1587       cb = *src_c1++;
1588       *dst_lum1++ = *lum1++;
1589       *dst_lum2++ = *lum2++;
1590       *dst_cb1++ = *dst_cb2++ = cb;
1591       *dst_cr1++ = *dst_cr2++ = cr;
1592       *dst_lum1++ = *lum1++;
1593       *dst_lum2++ = *lum2++;
1594       *dst_cb1++ = *dst_cb2++ = cb;
1595       *dst_cr1++ = *dst_cr2++ = cr;
1596     }
1597     /* odd width */
1598     if (width % 2 != 0) {
1599       cr = *src_c1++;
1600       cb = *src_c1++;
1601       *dst_lum1++ = *lum1++;
1602       *dst_lum2++ = *lum2++;
1603       *dst_cb1++ = *dst_cb2++ = *src_c1++;
1604       *dst_cr1++ = *dst_cr2++ = *src_c1++;
1605     }
1606
1607     dst_line += dst->linesize[0] * 2;
1608     dst_cb_line += dst->linesize[1] * 2;
1609     dst_cr_line += dst->linesize[2] * 2;
1610     src_lum_line += src->linesize[0] * 2;
1611     src_c_line += src->linesize[1];
1612   }
1613
1614   /* odd height */
1615   if (height % 2 != 0) {
1616     dst_lum1 = dst_line;
1617     lum1 = src_lum_line;
1618     src_c1 = src_c_line;
1619
1620     dst_cb1 = dst_cb_line;
1621     dst_cr1 = dst_cr_line;
1622
1623     for (w = width / 2; w--;) {
1624       cr = *src_c1++;
1625       cb = *src_c1++;
1626       *dst_lum1++ = *lum1++;
1627       *dst_cb1++ = cb;
1628       *dst_cr1++ = cr;
1629       *dst_lum1++ = *lum1++;
1630       *dst_cb1++ = cb;
1631       *dst_cr1++ = cr;
1632     }
1633     /* odd width */
1634     if (width % 2 != 0) {
1635       cr = *src_c1++;
1636       cb = *src_c1++;
1637       *dst_lum1++ = *lum1++;
1638       *dst_cb1++ = cb;
1639       *dst_cr1++ = cr;
1640     }
1641   }
1642 }
1643
1644 static void
1645 yuva420p_to_yuv420p (AVPicture * dst, const AVPicture * src, int width,
1646     int height)
1647 {
1648   memcpy (dst->data[0], src->data[0], dst->linesize[0] * height);
1649   memcpy (dst->data[1], src->data[1], dst->linesize[1] * ((height + 1) / 2));
1650   memcpy (dst->data[2], src->data[2], dst->linesize[2] * ((height + 1) / 2));
1651 }
1652
1653 static void
1654 yuva420p_to_yuv422 (AVPicture * dst, const AVPicture * src,
1655     int width, int height)
1656 {
1657   int w, h;
1658   uint8_t *line1, *line2, *linesrc = dst->data[0];
1659   uint8_t *lum1, *lum2, *lumsrc = src->data[0];
1660   uint8_t *cb1, *cb2 = src->data[1];
1661   uint8_t *cr1, *cr2 = src->data[2];
1662
1663   for (h = height / 2; h--;) {
1664     line1 = linesrc;
1665     line2 = linesrc + dst->linesize[0];
1666
1667     lum1 = lumsrc;
1668     lum2 = lumsrc + src->linesize[0];
1669
1670     cb1 = cb2;
1671     cr1 = cr2;
1672
1673     for (w = width / 2; w--;) {
1674       *line1++ = *lum1++;
1675       *line2++ = *lum2++;
1676       *line1++ = *line2++ = *cb1++;
1677       *line1++ = *lum1++;
1678       *line2++ = *lum2++;
1679       *line1++ = *line2++ = *cr1++;
1680     }
1681     /* odd width */
1682     if (width % 2 != 0) {
1683       *line1++ = *lum1++;
1684       *line2++ = *lum2++;
1685       *line1++ = *line2++ = *cb1++;
1686     }
1687
1688     linesrc += dst->linesize[0] * 2;
1689     lumsrc += src->linesize[0] * 2;
1690     cb2 += src->linesize[1];
1691     cr2 += src->linesize[2];
1692   }
1693   /* odd height */
1694   if (height % 2 != 0) {
1695     line1 = linesrc;
1696     lum1 = lumsrc;
1697     cb1 = cb2;
1698     cr1 = cr2;
1699
1700     for (w = width / 2; w--;) {
1701       *line1++ = *lum1++;
1702       *line1++ = *cb1++;
1703       *line1++ = *lum1++;
1704       *line1++ = *cr1++;
1705     }
1706     /* odd width */
1707     if (width % 2 != 0) {
1708       *line1++ = *lum1++;
1709       *line1++ = *cb1++;
1710     }
1711   }
1712 }
1713
1714 #define SCALEBITS 10
1715 #define ONE_HALF  (1 << (SCALEBITS - 1))
1716 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
1717
1718 #define YUV_TO_RGB1_CCIR(cb1, cr1)\
1719 {\
1720     cb = (cb1) - 128;\
1721     cr = (cr1) - 128;\
1722     r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
1723     g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
1724             ONE_HALF;\
1725     b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
1726 }
1727
1728 #define YUV_TO_RGB2_CCIR(r, g, b, y1)\
1729 {\
1730     y = ((y1) - 16) * FIX(255.0/219.0);\
1731     r = cm[(y + r_add) >> SCALEBITS];\
1732     g = cm[(y + g_add) >> SCALEBITS];\
1733     b = cm[(y + b_add) >> SCALEBITS];\
1734 }
1735
1736 #define YUV_TO_RGB1(cb1, cr1)\
1737 {\
1738     cb = (cb1) - 128;\
1739     cr = (cr1) - 128;\
1740     r_add = FIX(1.40200) * cr + ONE_HALF;\
1741     g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
1742     b_add = FIX(1.77200) * cb + ONE_HALF;\
1743 }
1744
1745 #define YUV_TO_RGB2(r, g, b, y1)\
1746 {\
1747     y = (y1) << SCALEBITS;\
1748     r = cm[(y + r_add) >> SCALEBITS];\
1749     g = cm[(y + g_add) >> SCALEBITS];\
1750     b = cm[(y + b_add) >> SCALEBITS];\
1751 }
1752
1753 #define Y_CCIR_TO_JPEG(y)\
1754  cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
1755
1756 #define Y_JPEG_TO_CCIR(y)\
1757  (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
1758
1759 #define C_CCIR_TO_JPEG(y)\
1760  cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
1761
1762 /* NOTE: the clamp is really necessary! */
1763 static inline int
1764 C_JPEG_TO_CCIR (int y)
1765 {
1766   y = (((y - 128) * FIX (112.0 / 127.0) + (ONE_HALF +
1767               (128 << SCALEBITS))) >> SCALEBITS);
1768   if (y < 16)
1769     y = 16;
1770   return y;
1771 }
1772
1773
1774 #define RGB_TO_Y(r, g, b) \
1775 ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
1776   FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
1777
1778 #define RGB_TO_U(r1, g1, b1, shift)\
1779 (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +         \
1780      FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
1781
1782 #define RGB_TO_V(r1, g1, b1, shift)\
1783 (((FIX(0.50000) * r1 - FIX(0.41869) * g1 -           \
1784    FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
1785
1786 #define RGB_TO_Y_CCIR(r, g, b) \
1787 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
1788   FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
1789
1790 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
1791 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
1792      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
1793
1794 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
1795 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
1796    FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
1797
1798 static uint8_t y_ccir_to_jpeg[256];
1799 static uint8_t y_jpeg_to_ccir[256];
1800 static uint8_t c_ccir_to_jpeg[256];
1801 static uint8_t c_jpeg_to_ccir[256];
1802
1803 /* init various conversion tables */
1804 static void
1805 img_convert_init (void)
1806 {
1807   int i;
1808   uint8_t *cm = cropTbl + MAX_NEG_CROP;
1809
1810   for (i = 0; i < 256; i++) {
1811     y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG (i);
1812     y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR (i);
1813     c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG (i);
1814     c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR (i);
1815   }
1816 }
1817
1818 /* apply to each pixel the given table */
1819 static void
1820 img_apply_table (uint8_t * dst, int dst_wrap,
1821     const uint8_t * src, int src_wrap,
1822     int width, int height, const uint8_t * table1)
1823 {
1824   int n;
1825   const uint8_t *s;
1826   uint8_t *d;
1827   const uint8_t *table;
1828
1829   table = table1;
1830   for (; height > 0; height--) {
1831     s = src;
1832     d = dst;
1833     n = width;
1834     while (n >= 4) {
1835       d[0] = table[s[0]];
1836       d[1] = table[s[1]];
1837       d[2] = table[s[2]];
1838       d[3] = table[s[3]];
1839       d += 4;
1840       s += 4;
1841       n -= 4;
1842     }
1843     while (n > 0) {
1844       d[0] = table[s[0]];
1845       d++;
1846       s++;
1847       n--;
1848     }
1849     dst += dst_wrap;
1850     src += src_wrap;
1851   }
1852 }
1853
1854 /* XXX: use generic filter ? */
1855 /* XXX: in most cases, the sampling position is incorrect */
1856
1857 static void
1858 img_copy_plane_resize (uint8_t * dst, int dst_wrap, int dst_width,
1859     int dst_height, const uint8_t * src, int src_wrap, int src_width,
1860     int src_height)
1861 {
1862   img_copy_plane (dst, dst_wrap, src, src_wrap, dst_width, dst_height);
1863 }
1864
1865 /* 4x1 -> 1x1 */
1866 static void
1867 shrink41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
1868     const uint8_t * src, int src_wrap, int src_width, int src_height)
1869 {
1870   int w, s_w;
1871   const uint8_t *s;
1872   uint8_t *d;
1873
1874   for (; dst_height > 0; dst_height--) {
1875     s = src;
1876     d = dst;
1877     for (s_w = src_width, w = dst_width; w > 0 && s_w > 3; w--, s_w -= 4) {
1878       d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
1879       s += 4;
1880       d++;
1881     }
1882
1883     if (w) {
1884       if (s_w == 3)
1885         d[0] = (s[0] + s[1] + s[2]) / 3;
1886       else if (s_w == 2)
1887         d[0] = (s[0] + s[1]) / 2;
1888       else                      /* s_w == 1 */
1889         d[0] = s[0];
1890     }
1891
1892     src += src_wrap;
1893     dst += dst_wrap;
1894   }
1895 }
1896
1897 /* 2x1 -> 1x1 */
1898 static void
1899 shrink21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
1900     const uint8_t * src, int src_wrap, int src_width, int src_height)
1901 {
1902   int w, s_w;
1903   const uint8_t *s;
1904   uint8_t *d;
1905
1906   for (; dst_height > 0; dst_height--) {
1907     s = src;
1908     d = dst;
1909     for (s_w = src_width, w = dst_width; w > 0 && s_w > 1; w--, s_w -= 2) {
1910       d[0] = (s[0] + s[1]) >> 1;
1911       s += 2;
1912       d++;
1913     }
1914
1915     if (w)                      /* s_w == 1 */
1916       d[0] = s[0];
1917
1918     src += src_wrap;
1919     dst += dst_wrap;
1920   }
1921 }
1922
1923 /* 1x2 -> 1x1 */
1924 static void
1925 shrink12 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
1926     const uint8_t * src, int src_wrap, int src_width, int src_height)
1927 {
1928   int w;
1929   uint8_t *d;
1930   const uint8_t *s1, *s2;
1931
1932   for (; dst_height > 0; dst_height--, src_height -= 2) {
1933     s1 = src;
1934     s2 = s1 + (src_height > 1 ? src_wrap : 0);
1935     d = dst;
1936     for (w = dst_width; w >= 4; w -= 4) {
1937       d[0] = (s1[0] + s2[0]) >> 1;
1938       d[1] = (s1[1] + s2[1]) >> 1;
1939       d[2] = (s1[2] + s2[2]) >> 1;
1940       d[3] = (s1[3] + s2[3]) >> 1;
1941       s1 += 4;
1942       s2 += 4;
1943       d += 4;
1944     }
1945     for (; w > 0; w--) {
1946       d[0] = (s1[0] + s2[0]) >> 1;
1947       s1++;
1948       s2++;
1949       d++;
1950     }
1951     src += 2 * src_wrap;
1952     dst += dst_wrap;
1953   }
1954 }
1955
1956 /* 2x2 -> 1x1 */
1957 static void
1958 shrink22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
1959     const uint8_t * src, int src_wrap, int src_width, int src_height)
1960 {
1961   int w, s_w;
1962   const uint8_t *s1, *s2;
1963   uint8_t *d;
1964
1965   for (; dst_height > 0; dst_height--, src_height -= 2) {
1966     s1 = src;
1967     s2 = s1 + (src_height > 1 ? src_wrap : 0);
1968     d = dst;
1969     for (s_w = src_width, w = dst_width; w >= 4; w -= 4, s_w -= 8) {
1970       d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
1971       d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
1972       d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
1973       d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
1974       s1 += 8;
1975       s2 += 8;
1976       d += 4;
1977     }
1978     for (; w > 0 && s_w > 1; w--, s_w -= 2) {
1979       d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
1980       s1 += 2;
1981       s2 += 2;
1982       d++;
1983     }
1984
1985     if (w)
1986       d[0] = (s1[0] + s2[0] + 1) >> 1;
1987
1988     src += 2 * src_wrap;
1989     dst += dst_wrap;
1990   }
1991 }
1992
1993 /* 4x4 -> 1x1 */
1994 static void
1995 shrink44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
1996     const uint8_t * src, int src_wrap, int src_width, int src_height)
1997 {
1998   int s_w, w;
1999   const uint8_t *s1, *s2, *s3, *s4;
2000   uint8_t *d;
2001
2002   for (; dst_height > 0; dst_height--, src_height -= 4) {
2003     s1 = src;
2004     s2 = s1 + (src_height > 1 ? src_wrap : 0);
2005     s3 = s2 + (src_height > 2 ? src_wrap : 0);
2006     s4 = s3 + (src_height > 3 ? src_wrap : 0);
2007     d = dst;
2008     for (s_w = src_width, w = dst_width; s_w > 3 && w > 0; w--, s_w -= 4) {
2009       d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
2010           s2[0] + s2[1] + s2[2] + s2[3] +
2011           s3[0] + s3[1] + s3[2] + s3[3] +
2012           s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
2013       s1 += 4;
2014       s2 += 4;
2015       s3 += 4;
2016       s4 += 4;
2017       d++;
2018     }
2019
2020     if (w) {
2021       if (s_w == 3)
2022         d[0] = (s1[0] + s1[1] + s1[2] +
2023             s2[0] + s2[1] + s2[2] +
2024             s3[0] + s3[1] + s3[2] + s4[0] + s4[1] + s4[2]) / 12;
2025       else if (s_w == 2)
2026         d[0] = (s1[0] + s1[1] +
2027             s2[0] + s2[1] + s3[0] + s3[1] + s4[0] + s4[1]) / 8;
2028       else                      /* s_w == 1 */
2029         d[0] = (s1[0] + s2[0] + s3[0] + s4[0]) / 4;
2030     }
2031
2032     src += 4 * src_wrap;
2033     dst += dst_wrap;
2034   }
2035 }
2036
2037 static void
2038 grow21_line (uint8_t * dst, const uint8_t * src, int width)
2039 {
2040   int w;
2041   const uint8_t *s1;
2042   uint8_t *d;
2043
2044   s1 = src;
2045   d = dst;
2046   for (w = width; w >= 4; w -= 4) {
2047     d[1] = d[0] = s1[0];
2048     d[3] = d[2] = s1[1];
2049     s1 += 2;
2050     d += 4;
2051   }
2052   for (; w >= 2; w -= 2) {
2053     d[1] = d[0] = s1[0];
2054     s1++;
2055     d += 2;
2056   }
2057   /* only needed if width is not a multiple of two */
2058   if (w) {
2059     d[0] = s1[0];
2060   }
2061 }
2062
2063 static void
2064 grow41_line (uint8_t * dst, const uint8_t * src, int width)
2065 {
2066   int w, v;
2067   const uint8_t *s1;
2068   uint8_t *d;
2069
2070   s1 = src;
2071   d = dst;
2072   for (w = width; w >= 4; w -= 4) {
2073     v = s1[0];
2074     d[0] = v;
2075     d[1] = v;
2076     d[2] = v;
2077     d[3] = v;
2078     s1++;
2079     d += 4;
2080   }
2081   for (; w > 0; w--) {
2082     d[0] = s1[0];
2083     d++;
2084   }
2085 }
2086
2087 /* 1x1 -> 2x1 */
2088 static void
2089 grow21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
2090     const uint8_t * src, int src_wrap, int src_width, int src_height)
2091 {
2092   for (; dst_height > 0; dst_height--) {
2093     grow21_line (dst, src, dst_width);
2094     src += src_wrap;
2095     dst += dst_wrap;
2096   }
2097 }
2098
2099 /* 1x1 -> 2x2 */
2100 static void
2101 grow22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
2102     const uint8_t * src, int src_wrap, int src_width, int src_height)
2103 {
2104   for (; dst_height > 0; dst_height--) {
2105     grow21_line (dst, src, dst_width);
2106     if (dst_height % 2)
2107       src += src_wrap;
2108     dst += dst_wrap;
2109   }
2110 }
2111
2112 /* 1x1 -> 4x1 */
2113 static void
2114 grow41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
2115     const uint8_t * src, int src_wrap, int src_width, int src_height)
2116 {
2117   for (; dst_height > 0; dst_height--) {
2118     grow41_line (dst, src, dst_width);
2119     src += src_wrap;
2120     dst += dst_wrap;
2121   }
2122 }
2123
2124 /* 1x1 -> 4x4 */
2125 static void
2126 grow44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
2127     const uint8_t * src, int src_wrap, int src_width, int src_height)
2128 {
2129   for (; dst_height > 0; dst_height--) {
2130     grow41_line (dst, src, dst_width);
2131     if ((dst_height & 3) == 1)
2132       src += src_wrap;
2133     dst += dst_wrap;
2134   }
2135 }
2136
2137 /* 1x2 -> 2x1 */
2138 static void
2139 conv411 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height,
2140     const uint8_t * src, int src_wrap, int src_width, int src_height)
2141 {
2142   int w, c;
2143   const uint8_t *s1, *s2;
2144   uint8_t *d;
2145
2146   for (; dst_height > 0; dst_height--, src_height -= 2) {
2147     s1 = src;
2148     s2 = src + (src_height > 1 ? src_wrap : 0);
2149     d = dst;
2150     for (w = dst_width; w > 1; w -= 2) {
2151       c = (s1[0] + s2[0]) >> 1;
2152       d[0] = c;
2153       d[1] = c;
2154       s1++;
2155       s2++;
2156       d += 2;
2157     }
2158
2159     if (w) {
2160       d[0] = (s1[0] + s2[0]) >> 1;
2161     }
2162
2163     src += src_wrap * 2;
2164     dst += dst_wrap;
2165   }
2166 }
2167
2168 /* XXX: add jpeg quantize code */
2169
2170 #define TRANSP_INDEX (6*6*6)
2171
2172 /* this is maybe slow, but allows for extensions */
2173 static inline unsigned char
2174 gif_clut_index (uint8_t r, uint8_t g, uint8_t b)
2175 {
2176   return ((((r) / 47) % 6) * 6 * 6 + (((g) / 47) % 6) * 6 + (((b) / 47) % 6));
2177 }
2178
2179 static void
2180 build_rgb_palette (uint8_t * palette, int has_alpha)
2181 {
2182   uint32_t *pal;
2183   static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
2184   int i, r, g, b;
2185
2186   pal = (uint32_t *) palette;
2187   i = 0;
2188   for (r = 0; r < 6; r++) {
2189     for (g = 0; g < 6; g++) {
2190       for (b = 0; b < 6; b++) {
2191         pal[i++] = (0xffU << 24) | (pal_value[r] << 16) |
2192             (pal_value[g] << 8) | pal_value[b];
2193       }
2194     }
2195   }
2196   if (has_alpha)
2197     pal[i++] = 0;
2198   while (i < 256)
2199     pal[i++] = 0xff000000;
2200 }
2201
2202 /* copy bit n to bits 0 ... n - 1 */
2203 static inline unsigned int
2204 bitcopy_n (unsigned int a, int n)
2205 {
2206   int mask;
2207
2208   mask = (1 << n) - 1;
2209   return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
2210 }
2211
2212 /* rgb555 handling */
2213
2214 #define RGB_NAME rgb555
2215
2216 #define RGB_IN(r, g, b, s)\
2217 {\
2218     unsigned int v = ((const uint16_t *)(s))[0];\
2219     r = bitcopy_n(v >> (10 - 3), 3);\
2220     g = bitcopy_n(v >> (5 - 3), 3);\
2221     b = bitcopy_n(v << 3, 3);\
2222 }
2223
2224 #define RGBA_IN(r, g, b, a, s)\
2225 {\
2226     unsigned int v = ((const uint16_t *)(s))[0];\
2227     r = bitcopy_n(v >> (10 - 3), 3);\
2228     g = bitcopy_n(v >> (5 - 3), 3);\
2229     b = bitcopy_n(v << 3, 3);\
2230     a = (-(v >> 15)) & 0xff;\
2231 }
2232
2233 #define RGBA_OUT(d, r, g, b, a)\
2234 {\
2235     ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \
2236                            ((a << 8) & 0x8000);\
2237 }
2238
2239 #define BPP 2
2240
2241 #include "imgconvert_template.h"
2242
2243 /* rgb565 handling */
2244
2245 #define RGB_NAME rgb565
2246
2247 #define RGB_IN(r, g, b, s)\
2248 {\
2249     unsigned int v = ((const uint16_t *)(s))[0];\
2250     r = bitcopy_n(v >> (11 - 3), 3);\
2251     g = bitcopy_n(v >> (5 - 2), 2);\
2252     b = bitcopy_n(v << 3, 3);\
2253 }
2254
2255 #define RGB_OUT(d, r, g, b)\
2256 {\
2257     ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
2258 }
2259
2260 #define BPP 2
2261
2262 #include "imgconvert_template.h"
2263
2264 /* bgr24 handling */
2265
2266 #define RGB_NAME bgr24
2267
2268 #define RGB_IN(r, g, b, s)\
2269 {\
2270     b = (s)[0];\
2271     g = (s)[1];\
2272     r = (s)[2];\
2273 }
2274
2275 #define RGB_OUT(d, r, g, b)\
2276 {\
2277     (d)[0] = b;\
2278     (d)[1] = g;\
2279     (d)[2] = r;\
2280 }
2281
2282 #define BPP 3
2283
2284 #include "imgconvert_template.h"
2285
2286 #undef RGB_IN
2287 #undef RGB_OUT
2288 #undef BPP
2289
2290 /* rgb24 handling */
2291
2292 #define RGB_NAME rgb24
2293 #define FMT_RGB24
2294
2295 #define RGB_IN(r, g, b, s)\
2296 {\
2297     r = (s)[0];\
2298     g = (s)[1];\
2299     b = (s)[2];\
2300 }
2301
2302 #define RGB_OUT(d, r, g, b)\
2303 {\
2304     (d)[0] = r;\
2305     (d)[1] = g;\
2306     (d)[2] = b;\
2307 }
2308
2309 #define BPP 3
2310
2311 #include "imgconvert_template.h"
2312
2313 /* rgb32 handling */
2314
2315 #define RGB_NAME rgb32
2316 #define FMT_RGBA32
2317
2318 #define RGB_IN(r, g, b, s)\
2319 {\
2320     unsigned int v = ((const uint32_t *)(s))[0];\
2321     r = (v >> 16) & 0xff;\
2322     g = (v >> 8) & 0xff;\
2323     b = v & 0xff;\
2324 }
2325
2326 #define RGBA_IN(r, g, b, a, s)\
2327 {\
2328     unsigned int v = ((const uint32_t *)(s))[0];\
2329     a = 0xff;\
2330     r = (v >> 16) & 0xff;\
2331     g = (v >> 8) & 0xff;\
2332     b = v & 0xff;\
2333 }
2334
2335 #define RGBA_OUT(d, r, g, b, a)\
2336 {\
2337     ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
2338 }
2339
2340 #define BPP 4
2341
2342 #include "imgconvert_template.h"
2343
2344 /* bgr32 handling */
2345
2346 #define RGB_NAME bgr32
2347
2348 #define RGB_IN(r, g, b, s)\
2349 {\
2350     unsigned int v = ((const uint32_t *)(s))[0];\
2351     r = (v >> 8) & 0xff;\
2352     g = (v >> 16) & 0xff;\
2353     b = (v >> 24) & 0xff;\
2354 }
2355
2356 #define RGBA_IN(r, g, b, a, s)\
2357 {\
2358     unsigned int v = ((const uint32_t *)(s))[0];\
2359     a = 0xff;\
2360     r = (v >> 8) & 0xff;\
2361     g = (v >> 16) & 0xff;\
2362     b = (v >> 24) & 0xff;\
2363 }
2364
2365 #define RGBA_OUT(d, r, g, b, a)\
2366 {\
2367     ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24);\
2368 }
2369
2370 #define BPP 4
2371
2372 #include "imgconvert_template.h"
2373
2374 /* xrgb32 handling */
2375
2376 #define RGB_NAME xrgb32
2377 #define FMT_RGBA32
2378
2379 #define RGB_IN(r, g, b, s)\
2380 {\
2381     unsigned int v = ((const uint32_t *)(s))[0];\
2382     r = (v >> 24) & 0xff;\
2383     g = (v >> 16) & 0xff;\
2384     b = (v >> 8) & 0xff;\
2385 }
2386
2387 #define RGBA_IN(r, g, b, a, s)\
2388 {\
2389     unsigned int v = ((const uint32_t *)(s))[0];\
2390     a = 0xff;\
2391     r = (v >> 24) & 0xff;\
2392     g = (v >> 16) & 0xff;\
2393     b = (v >> 8) & 0xff;\
2394 }
2395
2396 #define RGBA_OUT(d, r, g, b, a)\
2397 {\
2398     ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\
2399 }
2400
2401 #define BPP 4
2402
2403 #include "imgconvert_template.h"
2404
2405 /* bgrx32 handling */
2406
2407 #define RGB_NAME bgrx32
2408
2409 #define RGB_IN(r, g, b, s)\
2410 {\
2411     unsigned int v = ((const uint32_t *)(s))[0];\
2412     r = (v) & 0xff;\
2413     g = (v >> 8) & 0xff;\
2414     b = (v >> 16) & 0xff;\
2415 }
2416
2417 #define RGBA_IN(r, g, b, a, s)\
2418 {\
2419     unsigned int v = ((const uint32_t *)(s))[0];\
2420     a = 0xff;\
2421     r = (v) & 0xff;\
2422     g = (v >> 8) & 0xff;\
2423     b = (v >> 16) & 0xff;\
2424 }
2425
2426 #define RGBA_OUT(d, r, g, b, a)\
2427 {\
2428     ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24);\
2429 }
2430
2431 #define BPP 4
2432
2433 #include "imgconvert_template.h"
2434
2435 /* rgba32 handling */
2436
2437 #define RGB_NAME rgba32
2438 #define FMT_RGBA32
2439
2440 #define RGB_IN(r, g, b, s)\
2441 {\
2442     unsigned int v = ((const uint32_t *)(s))[0];\
2443     r = (v >> 16) & 0xff;\
2444     g = (v >> 8) & 0xff;\
2445     b = v & 0xff;\
2446 }
2447
2448 #define RGBA_IN(r, g, b, a, s)\
2449 {\
2450     unsigned int v = ((const uint32_t *)(s))[0];\
2451     a = (v >> 24) & 0xff;\
2452     r = (v >> 16) & 0xff;\
2453     g = (v >> 8) & 0xff;\
2454     b = v & 0xff;\
2455 }
2456
2457 #define RGBA_OUT(d, r, g, b, a)\
2458 {\
2459     ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
2460 }
2461
2462 #define BPP 4
2463
2464 #include "imgconvert_template.h"
2465
2466 /* bgra32 handling */
2467
2468 #define RGB_NAME bgra32
2469 #define FMT_BGRA32
2470
2471 #define RGB_IN(r, g, b, s)\
2472 {\
2473     unsigned int v = ((const uint32_t *)(s))[0];\
2474     r = (v >> 8) & 0xff;\
2475     g = (v >> 16) & 0xff;\
2476     b = (v >> 24) & 0xff;\
2477 }
2478
2479 #define RGBA_IN(r, g, b, a, s)\
2480 {\
2481     unsigned int v = ((const uint32_t *)(s))[0];\
2482     a = v & 0xff;\
2483     r = (v >> 8) & 0xff;\
2484     g = (v >> 16) & 0xff;\
2485     b = (v >> 24) & 0xff;\
2486 }
2487
2488 #define RGBA_OUT(d, r, g, b, a)\
2489 {\
2490     ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24 );\
2491 }
2492
2493 #define BPP 4
2494
2495 #include "imgconvert_template.h"
2496
2497 /* argb32 handling */
2498
2499 #define RGB_NAME argb32
2500 #define FMT_ARGB32
2501
2502 #define RGB_IN(r, g, b, s)\
2503 {\
2504     unsigned int v = ((const uint32_t *)(s))[0];\
2505     r = (v >> 24) & 0xff;\
2506     g = (v >> 16) & 0xff;\
2507     b = (v >> 8) & 0xff;\
2508 }
2509
2510 #define RGBA_IN(r, g, b, a, s)\
2511 {\
2512     unsigned int v = ((const uint32_t *)(s))[0];\
2513     r = (v >> 24) & 0xff;\
2514     g = (v >> 16) & 0xff;\
2515     b = (v >> 8) & 0xff;\
2516     a = v & 0xff;\
2517 }
2518
2519 #define RGBA_OUT(d, r, g, b, a)\
2520 {\
2521     ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\
2522 }
2523
2524 #define BPP 4
2525
2526 #include "imgconvert_template.h"
2527
2528 /* abgr32 handling */
2529
2530 #define RGB_NAME abgr32
2531 #define FMT_ABGR32
2532
2533 #define RGB_IN(r, g, b, s)\
2534 {\
2535     unsigned int v = ((const uint32_t *)(s))[0];\
2536     r = v & 0xff;\
2537     g = (v >> 8) & 0xff;\
2538     b = (v >> 16) & 0xff;\
2539 }
2540
2541 #define RGBA_IN(r, g, b, a, s)\
2542 {\
2543     unsigned int v = ((const uint32_t *)(s))[0];\
2544     r = v & 0xff;\
2545     g = (v >> 8) & 0xff;\
2546     b = (v >> 16) & 0xff;\
2547     a = (v >> 24) & 0xff;\
2548 }
2549
2550 #define RGBA_OUT(d, r, g, b, a)\
2551 {\
2552     ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24 );\
2553 }
2554
2555 #define BPP 4
2556
2557 #include "imgconvert_template.h"
2558
2559 static void
2560 gray_to_gray16_l (AVPicture * dst, const AVPicture * src, int width, int height)
2561 {
2562   const unsigned char *p;
2563   unsigned char *q;
2564   int dst_wrap, src_wrap;
2565   int x, y;
2566
2567   p = src->data[0];
2568   src_wrap = src->linesize[0] - width;
2569
2570   q = dst->data[0];
2571   dst_wrap = dst->linesize[0] - 2 * width;
2572
2573   for (y = 0; y < height; y++) {
2574     for (x = 0; x < width; x++) {
2575       GST_WRITE_UINT16_LE (q, (*p << 8));
2576       q += 2;
2577       p++;
2578     }
2579     p += src_wrap;
2580     q += dst_wrap;
2581   }
2582 }
2583
2584 static void
2585 gray_to_gray16_b (AVPicture * dst, const AVPicture * src, int width, int height)
2586 {
2587   const unsigned char *p;
2588   unsigned char *q;
2589   int dst_wrap, src_wrap;
2590   int x, y;
2591
2592   p = src->data[0];
2593   src_wrap = src->linesize[0] - width;
2594
2595   q = dst->data[0];
2596   dst_wrap = dst->linesize[0] - 2 * width;
2597
2598   for (y = 0; y < height; y++) {
2599     for (x = 0; x < width; x++) {
2600       GST_WRITE_UINT16_BE (q, (*p << 8));
2601       q += 2;
2602       p++;
2603     }
2604     p += src_wrap;
2605     q += dst_wrap;
2606   }
2607 }
2608
2609 static void
2610 gray16_l_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
2611 {
2612   const unsigned char *p;
2613   unsigned char *q;
2614   int dst_wrap, src_wrap;
2615   int x, y;
2616
2617   p = src->data[0];
2618   src_wrap = src->linesize[0] - 2 * width;
2619
2620   q = dst->data[0];
2621   dst_wrap = dst->linesize[0] - width;
2622
2623   for (y = 0; y < height; y++) {
2624     for (x = 0; x < width; x++) {
2625       q[0] = GST_READ_UINT16_LE (p) >> 8;
2626       q++;
2627       p += 2;
2628     }
2629     p += src_wrap;
2630     q += dst_wrap;
2631   }
2632 }
2633
2634 static void
2635 gray16_b_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
2636 {
2637   const unsigned char *p;
2638   unsigned char *q;
2639   int dst_wrap, src_wrap;
2640   int x, y;
2641
2642   p = src->data[0];
2643   src_wrap = src->linesize[0] - 2 * width;
2644
2645   q = dst->data[0];
2646   dst_wrap = dst->linesize[0] - width;
2647
2648   for (y = 0; y < height; y++) {
2649     for (x = 0; x < width; x++) {
2650       q[0] = GST_READ_UINT16_BE (p) >> 8;
2651       q++;
2652       p += 2;
2653     }
2654     p += src_wrap;
2655     q += dst_wrap;
2656   }
2657 }
2658
2659 static void
2660 gray16_b_to_gray16_l (AVPicture * dst, const AVPicture * src,
2661     int width, int height)
2662 {
2663   const unsigned char *p;
2664   unsigned char *q;
2665   int dst_wrap, src_wrap;
2666   int x, y;
2667
2668   p = src->data[0];
2669   src_wrap = src->linesize[0] - 2 * width;
2670
2671   q = dst->data[0];
2672   dst_wrap = dst->linesize[0] - 2 * width;
2673
2674   for (y = 0; y < height; y++) {
2675     for (x = 0; x < width; x++) {
2676       q[0] = p[1];
2677       q[1] = p[0];
2678       q += 2;
2679       p += 2;
2680     }
2681     p += src_wrap;
2682     q += dst_wrap;
2683   }
2684 }
2685
2686 static void
2687 mono_to_gray (AVPicture * dst, const AVPicture * src,
2688     int width, int height, int xor_mask)
2689 {
2690   const unsigned char *p;
2691   unsigned char *q;
2692   int v, dst_wrap, src_wrap;
2693   int y, w;
2694
2695   p = src->data[0];
2696   src_wrap = src->linesize[0] - ((width + 7) >> 3);
2697
2698   q = dst->data[0];
2699   dst_wrap = dst->linesize[0] - width;
2700   for (y = 0; y < height; y++) {
2701     w = width;
2702     while (w >= 8) {
2703       v = *p++ ^ xor_mask;
2704       q[0] = -(v >> 7);
2705       q[1] = -((v >> 6) & 1);
2706       q[2] = -((v >> 5) & 1);
2707       q[3] = -((v >> 4) & 1);
2708       q[4] = -((v >> 3) & 1);
2709       q[5] = -((v >> 2) & 1);
2710       q[6] = -((v >> 1) & 1);
2711       q[7] = -((v >> 0) & 1);
2712       w -= 8;
2713       q += 8;
2714     }
2715     if (w > 0) {
2716       v = *p++ ^ xor_mask;
2717       do {
2718         q[0] = -((v >> 7) & 1);
2719         q++;
2720         v <<= 1;
2721       } while (--w);
2722     }
2723     p += src_wrap;
2724     q += dst_wrap;
2725   }
2726 }
2727
2728 static void
2729 monowhite_to_gray (AVPicture * dst, const AVPicture * src,
2730     int width, int height)
2731 {
2732   mono_to_gray (dst, src, width, height, 0xff);
2733 }
2734
2735 static void
2736 monoblack_to_gray (AVPicture * dst, const AVPicture * src,
2737     int width, int height)
2738 {
2739   mono_to_gray (dst, src, width, height, 0x00);
2740 }
2741
2742 static void
2743 gray_to_mono (AVPicture * dst, const AVPicture * src,
2744     int width, int height, int xor_mask)
2745 {
2746   int n;
2747   const uint8_t *s;
2748   uint8_t *d;
2749   int j, b, v, n1, src_wrap, dst_wrap, y;
2750
2751   s = src->data[0];
2752   src_wrap = src->linesize[0] - width;
2753
2754   d = dst->data[0];
2755   dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
2756
2757   for (y = 0; y < height; y++) {
2758     n = width;
2759     while (n >= 8) {
2760       v = 0;
2761       for (j = 0; j < 8; j++) {
2762         b = s[0];
2763         s++;
2764         v = (v << 1) | (b >> 7);
2765       }
2766       d[0] = v ^ xor_mask;
2767       d++;
2768       n -= 8;
2769     }
2770     if (n > 0) {
2771       n1 = n;
2772       v = 0;
2773       while (n > 0) {
2774         b = s[0];
2775         s++;
2776         v = (v << 1) | (b >> 7);
2777         n--;
2778       }
2779       d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
2780       d++;
2781     }
2782     s += src_wrap;
2783     d += dst_wrap;
2784   }
2785 }
2786
2787 static void
2788 gray_to_monowhite (AVPicture * dst, const AVPicture * src,
2789     int width, int height)
2790 {
2791   gray_to_mono (dst, src, width, height, 0xff);
2792 }
2793
2794 static void
2795 gray_to_monoblack (AVPicture * dst, const AVPicture * src,
2796     int width, int height)
2797 {
2798   gray_to_mono (dst, src, width, height, 0x00);
2799 }
2800
2801 static void
2802 y800_to_y16 (AVPicture * dst, const AVPicture * src, int width, int height)
2803 {
2804   const unsigned char *p;
2805   unsigned char *q;
2806   int dst_wrap, src_wrap;
2807   int x, y;
2808
2809   p = src->data[0];
2810   src_wrap = src->linesize[0] - width;
2811
2812   q = dst->data[0];
2813   dst_wrap = dst->linesize[0] - 2 * width;
2814
2815   for (y = 0; y < height; y++) {
2816     for (x = 0; x < width; x++) {
2817       GST_WRITE_UINT16_LE (q, (*p << 8));
2818       q += 2;
2819       p++;
2820     }
2821     p += src_wrap;
2822     q += dst_wrap;
2823   }
2824 }
2825
2826 static void
2827 y16_to_y800 (AVPicture * dst, const AVPicture * src, int width, int height)
2828 {
2829   const unsigned char *p;
2830   unsigned char *q;
2831   int dst_wrap, src_wrap;
2832   int x, y;
2833
2834   p = src->data[0];
2835   src_wrap = src->linesize[0] - 2 * width;
2836
2837   q = dst->data[0];
2838   dst_wrap = dst->linesize[0] - width;
2839
2840   for (y = 0; y < height; y++) {
2841     for (x = 0; x < width; x++) {
2842       q[0] = GST_READ_UINT16_LE (p) >> 8;
2843       q++;
2844       p += 2;
2845     }
2846     p += src_wrap;
2847     q += dst_wrap;
2848   }
2849 }
2850
2851 static void
2852 yuva420p_to_ayuv4444 (AVPicture * dst, const AVPicture * src,
2853     int width, int height)
2854 {
2855   const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *a1_ptr, *a2_ptr;
2856   uint8_t *d, *d1, *d2;
2857   int w, width2;
2858
2859   d = dst->data[0];
2860   y1_ptr = src->data[0];
2861   cb_ptr = src->data[1];
2862   cr_ptr = src->data[2];
2863   a1_ptr = src->data[3];
2864   width2 = (width + 1) >> 1;
2865   for (; height >= 2; height -= 2) {
2866     d1 = d;
2867     d2 = d + dst->linesize[0];
2868     y2_ptr = y1_ptr + src->linesize[0];
2869     a2_ptr = a1_ptr + src->linesize[3];
2870     for (w = width; w >= 2; w -= 2) {
2871       d1[0] = a1_ptr[0];
2872       d1[1] = y1_ptr[0];
2873       d1[2] = cb_ptr[0];
2874       d1[3] = cr_ptr[0];
2875
2876       d1[4 + 0] = a1_ptr[1];
2877       d1[4 + 1] = y1_ptr[1];
2878       d1[4 + 2] = cb_ptr[0];
2879       d1[4 + 3] = cr_ptr[0];
2880
2881       d2[0] = a2_ptr[0];
2882       d2[1] = y2_ptr[0];
2883       d2[2] = cb_ptr[0];
2884       d2[3] = cr_ptr[0];
2885
2886       d2[4 + 0] = a2_ptr[1];
2887       d2[4 + 1] = y2_ptr[1];
2888       d2[4 + 2] = cb_ptr[0];
2889       d2[4 + 3] = cr_ptr[0];
2890
2891       d1 += 2 * 4;
2892       d2 += 2 * 4;
2893
2894       y1_ptr += 2;
2895       y2_ptr += 2;
2896       cb_ptr++;
2897       cr_ptr++;
2898       a1_ptr += 2;
2899       a2_ptr += 2;
2900     }
2901     /* handle odd width */
2902     if (w) {
2903       d1[0] = a1_ptr[0];
2904       d1[1] = y1_ptr[0];
2905       d1[2] = cb_ptr[0];
2906       d1[3] = cr_ptr[0];
2907
2908       d2[0] = a2_ptr[0];
2909       d2[1] = y2_ptr[0];
2910       d2[2] = cb_ptr[0];
2911       d2[3] = cr_ptr[0];
2912
2913       d1 += 4;
2914       d2 += 4;
2915       y1_ptr++;
2916       y2_ptr++;
2917       cb_ptr++;
2918       cr_ptr++;
2919       a1_ptr++;
2920       a2_ptr++;
2921     }
2922     d += 2 * dst->linesize[0];
2923     y1_ptr += 2 * src->linesize[0] - width;
2924     cb_ptr += src->linesize[1] - width2;
2925     cr_ptr += src->linesize[2] - width2;
2926     a1_ptr += 2 * src->linesize[3] - width;
2927   }
2928   /* handle odd height */
2929   if (height) {
2930     d1 = d;
2931     for (w = width; w >= 2; w -= 2) {
2932       d1[0] = a1_ptr[0];
2933       d1[1] = y1_ptr[0];
2934       d1[2] = cb_ptr[0];
2935       d1[3] = cr_ptr[0];
2936
2937       d1[4 + 0] = a1_ptr[1];
2938       d1[4 + 1] = y1_ptr[1];
2939       d1[4 + 2] = cb_ptr[0];
2940       d1[4 + 3] = cr_ptr[0];
2941
2942       d1 += 2 * 4;
2943
2944       y1_ptr += 2;
2945       cb_ptr++;
2946       cr_ptr++;
2947       a1_ptr += 2;
2948     }
2949     /* handle width */
2950     if (w) {
2951       d1[0] = a1_ptr[0];
2952       d1[1] = y1_ptr[0];
2953       d1[2] = cb_ptr[0];
2954       d1[3] = cr_ptr[0];
2955       d1 += 4;
2956
2957       y1_ptr++;
2958       cb_ptr++;
2959       cr_ptr++;
2960       a1_ptr++;
2961     }
2962   }
2963 }
2964
2965 static void
2966 ayuv4444_to_yuva420p (AVPicture * dst,
2967     const AVPicture * src, int width, int height)
2968 {
2969   int wrap, wrap3, width2;
2970   int u1, v1, w;
2971   uint8_t *lum, *cb, *cr, *a;
2972   const uint8_t *p;
2973
2974   lum = dst->data[0];
2975   cb = dst->data[1];
2976   cr = dst->data[2];
2977   a = dst->data[3];
2978
2979   width2 = (width + 1) >> 1;
2980   wrap = dst->linesize[0];
2981   wrap3 = src->linesize[0];
2982   p = src->data[0];
2983   for (; height >= 2; height -= 2) {
2984     for (w = width; w >= 2; w -= 2) {
2985       a[0] = p[0];
2986       lum[0] = p[1];
2987       u1 = p[2];
2988       v1 = p[3];
2989
2990       a[1] = p[4 + 0];
2991       lum[1] = p[4 + 1];
2992       u1 += p[4 + 2];
2993       v1 += p[4 + 3];
2994       p += wrap3;
2995       lum += wrap;
2996       a += wrap;
2997
2998       a[0] = p[0];
2999       lum[0] = p[1];
3000       u1 += p[2];
3001       v1 += p[3];
3002
3003       a[1] = p[4 + 0];
3004       lum[1] = p[4 + 1];
3005       u1 += p[4 + 2];
3006       v1 += p[4 + 3];
3007
3008       cb[0] = u1 >> 2;
3009       cr[0] = v1 >> 2;
3010
3011       cb++;
3012       cr++;
3013       p += -wrap3 + 2 * 4;
3014       lum += -wrap + 2;
3015       a += -wrap + 2;
3016     }
3017     if (w) {
3018       a[0] = p[0];
3019       lum[0] = p[1];
3020       u1 = p[2];
3021       v1 = p[3];
3022       p += wrap3;
3023       lum += wrap;
3024       a += wrap;
3025
3026       a[0] = p[0];
3027       lum[0] = p[1];
3028       u1 += p[2];
3029       v1 += p[3];
3030
3031       cb[0] = u1 >> 1;
3032       cr[0] = v1 >> 1;
3033       cb++;
3034       cr++;
3035       p += -wrap3 + 4;
3036       lum += -wrap + 1;
3037       a += -wrap + 1;
3038     }
3039     p += wrap3 + (wrap3 - width * 4);
3040     lum += wrap + (wrap - width);
3041     a += wrap + (wrap - width);
3042     cb += dst->linesize[1] - width2;
3043     cr += dst->linesize[2] - width2;
3044   }
3045   /* handle odd height */
3046   if (height) {
3047     for (w = width; w >= 2; w -= 2) {
3048       a[0] = p[0];
3049       lum[0] = p[1];
3050       u1 = p[2];
3051       v1 = p[3];
3052
3053       a[1] = p[4 + 0];
3054       lum[1] = p[4 + 1];
3055       u1 += p[4 + 2];
3056       v1 += p[4 + 3];
3057       cb[0] = u1 >> 1;
3058       cr[0] = v1 >> 1;
3059       cb++;
3060       cr++;
3061       p += 2 * 4;
3062       lum += 2;
3063       a += 2;
3064     }
3065     if (w) {
3066       a[0] = p[0];
3067       lum[0] = p[1];
3068       cb[0] = p[2];
3069       cr[0] = p[3];
3070     }
3071   }
3072 }
3073
3074 typedef struct ConvertEntry
3075 {
3076   enum PixelFormat src;
3077   enum PixelFormat dest;
3078   void (*convert) (AVPicture * dst,
3079       const AVPicture * src, int width, int height);
3080 } ConvertEntry;
3081
3082 /* Add each new convertion function in this table. In order to be able
3083    to convert from any format to any format, the following constraints
3084    must be satisfied:
3085
3086    - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24 
3087
3088    - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
3089
3090    - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32
3091
3092    - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
3093      PIX_FMT_RGB24.
3094
3095    - PIX_FMT_422 must convert to and from PIX_FMT_422P.
3096
3097    The other conversion functions are just optimisations for common cases.
3098 */
3099 static ConvertEntry convert_table[] = {
3100   {PIX_FMT_YUV420P, PIX_FMT_YUV422, yuv420p_to_yuv422},
3101   {PIX_FMT_YUV420P, PIX_FMT_RGB555, yuv420p_to_rgb555},
3102   {PIX_FMT_YUV420P, PIX_FMT_RGB565, yuv420p_to_rgb565},
3103   {PIX_FMT_YUV420P, PIX_FMT_BGR24, yuv420p_to_bgr24},
3104   {PIX_FMT_YUV420P, PIX_FMT_RGB24, yuv420p_to_rgb24},
3105   {PIX_FMT_YUV420P, PIX_FMT_RGB32, yuv420p_to_rgb32},
3106   {PIX_FMT_YUV420P, PIX_FMT_BGR32, yuv420p_to_bgr32},
3107   {PIX_FMT_YUV420P, PIX_FMT_xRGB32, yuv420p_to_xrgb32},
3108   {PIX_FMT_YUV420P, PIX_FMT_BGRx32, yuv420p_to_bgrx32},
3109   {PIX_FMT_YUV420P, PIX_FMT_RGBA32, yuv420p_to_rgba32},
3110   {PIX_FMT_YUV420P, PIX_FMT_BGRA32, yuv420p_to_bgra32},
3111   {PIX_FMT_YUV420P, PIX_FMT_ARGB32, yuv420p_to_argb32},
3112   {PIX_FMT_YUV420P, PIX_FMT_ABGR32, yuv420p_to_abgr32},
3113
3114   {PIX_FMT_NV12, PIX_FMT_RGB555, nv12_to_rgb555},
3115   {PIX_FMT_NV12, PIX_FMT_RGB565, nv12_to_rgb565},
3116   {PIX_FMT_NV12, PIX_FMT_BGR24, nv12_to_bgr24},
3117   {PIX_FMT_NV12, PIX_FMT_RGB24, nv12_to_rgb24},
3118   {PIX_FMT_NV12, PIX_FMT_RGB32, nv12_to_rgb32},
3119   {PIX_FMT_NV12, PIX_FMT_BGR32, nv12_to_bgr32},
3120   {PIX_FMT_NV12, PIX_FMT_xRGB32, nv12_to_xrgb32},
3121   {PIX_FMT_NV12, PIX_FMT_BGRx32, nv12_to_bgrx32},
3122   {PIX_FMT_NV12, PIX_FMT_RGBA32, nv12_to_rgba32},
3123   {PIX_FMT_NV12, PIX_FMT_BGRA32, nv12_to_bgra32},
3124   {PIX_FMT_NV12, PIX_FMT_ARGB32, nv12_to_argb32},
3125   {PIX_FMT_NV12, PIX_FMT_ABGR32, nv12_to_abgr32},
3126   {PIX_FMT_NV12, PIX_FMT_NV21, nv12_to_nv21},
3127   {PIX_FMT_NV12, PIX_FMT_YUV444P, nv12_to_yuv444p},
3128
3129   {PIX_FMT_NV21, PIX_FMT_RGB555, nv21_to_rgb555},
3130   {PIX_FMT_NV21, PIX_FMT_RGB565, nv21_to_rgb565},
3131   {PIX_FMT_NV21, PIX_FMT_BGR24, nv21_to_bgr24},
3132   {PIX_FMT_NV21, PIX_FMT_RGB24, nv21_to_rgb24},
3133   {PIX_FMT_NV21, PIX_FMT_RGB32, nv21_to_rgb32},
3134   {PIX_FMT_NV21, PIX_FMT_BGR32, nv21_to_bgr32},
3135   {PIX_FMT_NV21, PIX_FMT_xRGB32, nv21_to_xrgb32},
3136   {PIX_FMT_NV21, PIX_FMT_BGRx32, nv21_to_bgrx32},
3137   {PIX_FMT_NV21, PIX_FMT_RGBA32, nv21_to_rgba32},
3138   {PIX_FMT_NV21, PIX_FMT_BGRA32, nv21_to_bgra32},
3139   {PIX_FMT_NV21, PIX_FMT_ARGB32, nv21_to_argb32},
3140   {PIX_FMT_NV21, PIX_FMT_ABGR32, nv21_to_abgr32},
3141   {PIX_FMT_NV21, PIX_FMT_YUV444P, nv21_to_yuv444p},
3142   {PIX_FMT_NV21, PIX_FMT_NV12, nv21_to_nv12},
3143
3144   {PIX_FMT_YUV422P, PIX_FMT_YUV422, yuv422p_to_yuv422},
3145   {PIX_FMT_YUV422P, PIX_FMT_UYVY422, yuv422p_to_uyvy422},
3146   {PIX_FMT_YUV422P, PIX_FMT_YVYU422, yuv422p_to_yvyu422},
3147
3148   {PIX_FMT_YUV444P, PIX_FMT_RGB24, yuv444p_to_rgb24},
3149
3150   {PIX_FMT_YUVJ420P, PIX_FMT_RGB555, yuvj420p_to_rgb555},
3151   {PIX_FMT_YUVJ420P, PIX_FMT_RGB565, yuvj420p_to_rgb565},
3152   {PIX_FMT_YUVJ420P, PIX_FMT_BGR24, yuvj420p_to_bgr24},
3153   {PIX_FMT_YUVJ420P, PIX_FMT_RGB24, yuvj420p_to_rgb24},
3154   {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_rgb32},
3155   {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgr32},
3156   {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_xrgb32},
3157   {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgrx32},
3158   {PIX_FMT_YUVJ420P, PIX_FMT_RGBA32, yuvj420p_to_rgba32},
3159   {PIX_FMT_YUVJ420P, PIX_FMT_BGRA32, yuvj420p_to_bgra32},
3160   {PIX_FMT_YUVJ420P, PIX_FMT_ARGB32, yuvj420p_to_argb32},
3161   {PIX_FMT_YUVJ420P, PIX_FMT_ABGR32, yuvj420p_to_abgr32},
3162
3163   {PIX_FMT_YUVJ444P, PIX_FMT_RGB24, yuvj444p_to_rgb24},
3164
3165   {PIX_FMT_YUV422, PIX_FMT_YUV420P, yuv422_to_yuv420p},
3166   {PIX_FMT_YUV422, PIX_FMT_YUV422P, yuv422_to_yuv422p},
3167   {PIX_FMT_YUV422, PIX_FMT_GRAY8, yvyu422_to_gray},
3168   {PIX_FMT_YUV422, PIX_FMT_RGB555, yuv422_to_rgb555},
3169   {PIX_FMT_YUV422, PIX_FMT_RGB565, yuv422_to_rgb565},
3170   {PIX_FMT_YUV422, PIX_FMT_BGR24, yuv422_to_bgr24},
3171   {PIX_FMT_YUV422, PIX_FMT_RGB24, yuv422_to_rgb24},
3172   {PIX_FMT_YUV422, PIX_FMT_BGR32, yuv422_to_bgr32},
3173   {PIX_FMT_YUV422, PIX_FMT_RGB32, yuv422_to_rgb32},
3174   {PIX_FMT_YUV422, PIX_FMT_xRGB32, yuv422_to_xrgb32},
3175   {PIX_FMT_YUV422, PIX_FMT_BGRx32, yuv422_to_bgrx32},
3176   {PIX_FMT_YUV422, PIX_FMT_BGRA32, yuv422_to_bgra32},
3177   {PIX_FMT_YUV422, PIX_FMT_RGBA32, yuv422_to_rgba32},
3178   {PIX_FMT_YUV422, PIX_FMT_ABGR32, yuv422_to_abgr32},
3179   {PIX_FMT_YUV422, PIX_FMT_ARGB32, yuv422_to_argb32},
3180
3181   {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p},
3182   {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p},
3183   {PIX_FMT_UYVY422, PIX_FMT_GRAY8, uyvy422_to_gray},
3184   {PIX_FMT_UYVY422, PIX_FMT_RGB555, uyvy422_to_rgb555},
3185   {PIX_FMT_UYVY422, PIX_FMT_RGB565, uyvy422_to_rgb565},
3186   {PIX_FMT_UYVY422, PIX_FMT_BGR24, uyvy422_to_bgr24},
3187   {PIX_FMT_UYVY422, PIX_FMT_RGB24, uyvy422_to_rgb24},
3188   {PIX_FMT_UYVY422, PIX_FMT_RGB32, uyvy422_to_rgb32},
3189   {PIX_FMT_UYVY422, PIX_FMT_BGR32, uyvy422_to_bgr32},
3190   {PIX_FMT_UYVY422, PIX_FMT_xRGB32, uyvy422_to_xrgb32},
3191   {PIX_FMT_UYVY422, PIX_FMT_BGRx32, uyvy422_to_bgrx32},
3192   {PIX_FMT_UYVY422, PIX_FMT_RGBA32, uyvy422_to_rgba32},
3193   {PIX_FMT_UYVY422, PIX_FMT_BGRA32, uyvy422_to_bgra32},
3194   {PIX_FMT_UYVY422, PIX_FMT_ARGB32, uyvy422_to_argb32},
3195   {PIX_FMT_UYVY422, PIX_FMT_ABGR32, uyvy422_to_abgr32},
3196
3197   {PIX_FMT_YVYU422, PIX_FMT_YUV420P, yvyu422_to_yuv420p},
3198   {PIX_FMT_YVYU422, PIX_FMT_YUV422P, yvyu422_to_yuv422p},
3199   {PIX_FMT_YVYU422, PIX_FMT_GRAY8, yvyu422_to_gray},
3200   {PIX_FMT_YVYU422, PIX_FMT_RGB555, yvyu422_to_rgb555},
3201   {PIX_FMT_YVYU422, PIX_FMT_RGB565, yvyu422_to_rgb565},
3202   {PIX_FMT_YVYU422, PIX_FMT_BGR24, yvyu422_to_bgr24},
3203   {PIX_FMT_YVYU422, PIX_FMT_RGB24, yvyu422_to_rgb24},
3204   {PIX_FMT_YVYU422, PIX_FMT_BGR32, yvyu422_to_bgr32},
3205   {PIX_FMT_YVYU422, PIX_FMT_RGB32, yvyu422_to_rgb32},
3206   {PIX_FMT_YVYU422, PIX_FMT_xRGB32, yvyu422_to_xrgb32},
3207   {PIX_FMT_YVYU422, PIX_FMT_BGRx32, yvyu422_to_bgrx32},
3208   {PIX_FMT_YVYU422, PIX_FMT_BGRA32, yvyu422_to_bgra32},
3209   {PIX_FMT_YVYU422, PIX_FMT_RGBA32, yvyu422_to_rgba32},
3210   {PIX_FMT_YVYU422, PIX_FMT_ABGR32, yvyu422_to_abgr32},
3211   {PIX_FMT_YVYU422, PIX_FMT_ARGB32, yvyu422_to_argb32},
3212
3213   {PIX_FMT_RGB24, PIX_FMT_YUV420P, rgb24_to_yuv420p},
3214   {PIX_FMT_RGB24, PIX_FMT_YUVA420P, rgb24_to_yuva420p},
3215   {PIX_FMT_RGB24, PIX_FMT_NV12, rgb24_to_nv12},
3216   {PIX_FMT_RGB24, PIX_FMT_NV21, rgb24_to_nv21},
3217   {PIX_FMT_RGB24, PIX_FMT_RGB565, rgb24_to_rgb565},
3218   {PIX_FMT_RGB24, PIX_FMT_RGB555, rgb24_to_rgb555},
3219   {PIX_FMT_RGB24, PIX_FMT_RGB32, rgb24_to_rgb32},
3220   {PIX_FMT_RGB24, PIX_FMT_BGR32, rgb24_to_bgr32},
3221   {PIX_FMT_RGB24, PIX_FMT_xRGB32, rgb24_to_xrgb32},
3222   {PIX_FMT_RGB24, PIX_FMT_BGRx32, rgb24_to_bgrx32},
3223   {PIX_FMT_RGB24, PIX_FMT_RGBA32, rgb24_to_rgba32},
3224   {PIX_FMT_RGB24, PIX_FMT_BGR24, rgb24_to_bgr24},
3225   {PIX_FMT_RGB24, PIX_FMT_BGRA32, rgb24_to_bgra32},
3226   {PIX_FMT_RGB24, PIX_FMT_ARGB32, rgb24_to_argb32},
3227   {PIX_FMT_RGB24, PIX_FMT_ABGR32, rgb24_to_abgr32},
3228   {PIX_FMT_RGB24, PIX_FMT_Y800, rgb24_to_y800},
3229   {PIX_FMT_RGB24, PIX_FMT_Y16, rgb24_to_y16},
3230   {PIX_FMT_RGB24, PIX_FMT_GRAY8, rgb24_to_gray},
3231   {PIX_FMT_RGB24, PIX_FMT_GRAY16_L, rgb24_to_gray16_l},
3232   {PIX_FMT_RGB24, PIX_FMT_GRAY16_B, rgb24_to_gray16_b},
3233   {PIX_FMT_RGB24, PIX_FMT_PAL8, rgb24_to_pal8},
3234   {PIX_FMT_RGB24, PIX_FMT_YUV444P, rgb24_to_yuv444p},
3235   {PIX_FMT_RGB24, PIX_FMT_YUVJ420P, rgb24_to_yuvj420p},
3236   {PIX_FMT_RGB24, PIX_FMT_YUVJ444P, rgb24_to_yuvj444p},
3237   {PIX_FMT_RGB24, PIX_FMT_AYUV4444, rgb24_to_ayuv4444},
3238   {PIX_FMT_RGB24, PIX_FMT_V308, rgb24_to_v308},
3239
3240   {PIX_FMT_RGB32, PIX_FMT_RGB24, rgb32_to_rgb24},
3241   {PIX_FMT_RGB32, PIX_FMT_RGB555, rgba32_to_rgb555},
3242   {PIX_FMT_RGB32, PIX_FMT_PAL8, rgb32_to_pal8},
3243   {PIX_FMT_RGB32, PIX_FMT_YUV420P, rgb32_to_yuv420p},
3244   {PIX_FMT_RGB32, PIX_FMT_YUVA420P, rgb32_to_yuva420p},
3245   {PIX_FMT_RGB32, PIX_FMT_NV12, rgb32_to_nv12},
3246   {PIX_FMT_RGB32, PIX_FMT_NV21, rgb32_to_nv21},
3247   {PIX_FMT_RGB32, PIX_FMT_Y800, rgb32_to_y800},
3248   {PIX_FMT_RGB32, PIX_FMT_Y16, rgb32_to_y16},
3249   {PIX_FMT_RGB32, PIX_FMT_GRAY8, rgb32_to_gray},
3250   {PIX_FMT_RGB32, PIX_FMT_GRAY16_L, rgb32_to_gray16_l},
3251   {PIX_FMT_RGB32, PIX_FMT_GRAY16_B, rgb32_to_gray16_b},
3252
3253   {PIX_FMT_xRGB32, PIX_FMT_RGB24, xrgb32_to_rgb24},
3254   {PIX_FMT_xRGB32, PIX_FMT_PAL8, xrgb32_to_pal8},
3255   {PIX_FMT_xRGB32, PIX_FMT_YUV420P, xrgb32_to_yuv420p},
3256   {PIX_FMT_xRGB32, PIX_FMT_YUVA420P, xrgb32_to_yuva420p},
3257   {PIX_FMT_xRGB32, PIX_FMT_NV12, xrgb32_to_nv12},
3258   {PIX_FMT_xRGB32, PIX_FMT_NV21, xrgb32_to_nv21},
3259   {PIX_FMT_xRGB32, PIX_FMT_Y800, xrgb32_to_y800},
3260   {PIX_FMT_xRGB32, PIX_FMT_Y16, xrgb32_to_y16},
3261   {PIX_FMT_xRGB32, PIX_FMT_GRAY8, xrgb32_to_gray},
3262   {PIX_FMT_xRGB32, PIX_FMT_GRAY16_L, xrgb32_to_gray16_l},
3263   {PIX_FMT_xRGB32, PIX_FMT_GRAY16_B, xrgb32_to_gray16_b},
3264
3265   {PIX_FMT_RGBA32, PIX_FMT_BGRA32, rgba32_to_bgra32},
3266   {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32},
3267   {PIX_FMT_RGBA32, PIX_FMT_ARGB32, rgba32_to_argb32},
3268   {PIX_FMT_RGBA32, PIX_FMT_BGR32, rgba32_to_bgr32},
3269   {PIX_FMT_RGBA32, PIX_FMT_BGRx32, rgba32_to_bgrx32},
3270   {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32},
3271   {PIX_FMT_RGBA32, PIX_FMT_RGB24, rgba32_to_rgb24},
3272   {PIX_FMT_RGBA32, PIX_FMT_RGB555, rgba32_to_rgb555},
3273   {PIX_FMT_RGBA32, PIX_FMT_PAL8, rgba32_to_pal8},
3274   {PIX_FMT_RGBA32, PIX_FMT_YUV420P, rgba32_to_yuv420p},
3275   {PIX_FMT_RGBA32, PIX_FMT_YUVA420P, rgba32_to_yuva420p},
3276   {PIX_FMT_RGBA32, PIX_FMT_NV12, rgba32_to_nv12},
3277   {PIX_FMT_RGBA32, PIX_FMT_NV21, rgba32_to_nv21},
3278   {PIX_FMT_RGBA32, PIX_FMT_Y800, rgba32_to_y800},
3279   {PIX_FMT_RGBA32, PIX_FMT_Y16, rgba32_to_y16},
3280   {PIX_FMT_RGBA32, PIX_FMT_GRAY8, rgba32_to_gray},
3281   {PIX_FMT_RGBA32, PIX_FMT_GRAY16_L, rgba32_to_gray16_l},
3282   {PIX_FMT_RGBA32, PIX_FMT_GRAY16_B, rgba32_to_gray16_b},
3283   {PIX_FMT_RGBA32, PIX_FMT_AYUV4444, rgba32_to_ayuv4444},
3284
3285   {PIX_FMT_BGR24, PIX_FMT_RGB24, bgr24_to_rgb24},
3286   {PIX_FMT_BGR24, PIX_FMT_YUV420P, bgr24_to_yuv420p},
3287   {PIX_FMT_BGR24, PIX_FMT_YUVA420P, bgr24_to_yuva420p},
3288   {PIX_FMT_BGR24, PIX_FMT_NV12, bgr24_to_nv12},
3289   {PIX_FMT_BGR24, PIX_FMT_NV21, bgr24_to_nv21},
3290   {PIX_FMT_BGR24, PIX_FMT_Y800, bgr24_to_y800},
3291   {PIX_FMT_BGR24, PIX_FMT_Y16, bgr24_to_y16},
3292   {PIX_FMT_BGR24, PIX_FMT_GRAY8, bgr24_to_gray},
3293   {PIX_FMT_BGR24, PIX_FMT_GRAY16_L, bgr24_to_gray16_l},
3294   {PIX_FMT_BGR24, PIX_FMT_GRAY16_B, bgr24_to_gray16_b},
3295
3296   {PIX_FMT_BGR32, PIX_FMT_RGB24, bgr32_to_rgb24},
3297   {PIX_FMT_BGR32, PIX_FMT_RGBA32, bgr32_to_rgba32},
3298   {PIX_FMT_BGR32, PIX_FMT_YUV420P, bgr32_to_yuv420p},
3299   {PIX_FMT_BGR32, PIX_FMT_YUVA420P, bgr32_to_yuva420p},
3300   {PIX_FMT_BGR32, PIX_FMT_NV12, bgr32_to_nv12},
3301   {PIX_FMT_BGR32, PIX_FMT_NV21, bgr32_to_nv21},
3302   {PIX_FMT_BGR32, PIX_FMT_Y800, bgr32_to_y800},
3303   {PIX_FMT_BGR32, PIX_FMT_Y16, bgr32_to_y16},
3304   {PIX_FMT_BGR32, PIX_FMT_GRAY8, bgr32_to_gray},
3305   {PIX_FMT_BGR32, PIX_FMT_GRAY16_L, bgr32_to_gray16_l},
3306   {PIX_FMT_BGR32, PIX_FMT_GRAY16_B, bgr32_to_gray16_b},
3307
3308   {PIX_FMT_BGRx32, PIX_FMT_RGB24, bgrx32_to_rgb24},
3309   {PIX_FMT_BGRx32, PIX_FMT_RGBA32, bgrx32_to_rgba32},
3310   {PIX_FMT_BGRx32, PIX_FMT_YUV420P, bgrx32_to_yuv420p},
3311   {PIX_FMT_BGRx32, PIX_FMT_YUVA420P, bgrx32_to_yuva420p},
3312   {PIX_FMT_BGRx32, PIX_FMT_NV12, bgrx32_to_nv12},
3313   {PIX_FMT_BGRx32, PIX_FMT_NV21, bgrx32_to_nv21},
3314   {PIX_FMT_BGRx32, PIX_FMT_Y800, bgrx32_to_y800},
3315   {PIX_FMT_BGRx32, PIX_FMT_Y16, bgrx32_to_y16},
3316   {PIX_FMT_BGRx32, PIX_FMT_GRAY8, bgrx32_to_gray},
3317   {PIX_FMT_BGRx32, PIX_FMT_GRAY16_L, bgrx32_to_gray16_l},
3318   {PIX_FMT_BGRx32, PIX_FMT_GRAY16_B, bgrx32_to_gray16_b},
3319
3320   {PIX_FMT_BGRA32, PIX_FMT_RGB24, bgra32_to_rgb24},
3321   {PIX_FMT_BGRA32, PIX_FMT_RGBA32, bgra32_to_rgba32},
3322   {PIX_FMT_BGRA32, PIX_FMT_YUV420P, bgra32_to_yuv420p},
3323   {PIX_FMT_BGRA32, PIX_FMT_YUVA420P, bgra32_to_yuva420p},
3324   {PIX_FMT_BGRA32, PIX_FMT_NV12, bgra32_to_nv12},
3325   {PIX_FMT_BGRA32, PIX_FMT_NV21, bgra32_to_nv21},
3326   {PIX_FMT_BGRA32, PIX_FMT_Y800, bgra32_to_y800},
3327   {PIX_FMT_BGRA32, PIX_FMT_Y16, bgra32_to_y16},
3328   {PIX_FMT_BGRA32, PIX_FMT_GRAY8, bgra32_to_gray},
3329   {PIX_FMT_BGRA32, PIX_FMT_GRAY16_L, bgra32_to_gray16_l},
3330   {PIX_FMT_BGRA32, PIX_FMT_GRAY16_B, bgra32_to_gray16_b},
3331   {PIX_FMT_BGRA32, PIX_FMT_AYUV4444, bgra32_to_ayuv4444},
3332
3333   {PIX_FMT_ABGR32, PIX_FMT_RGB24, abgr32_to_rgb24},
3334   {PIX_FMT_ABGR32, PIX_FMT_RGBA32, abgr32_to_rgba32},
3335   {PIX_FMT_ABGR32, PIX_FMT_YUV420P, abgr32_to_yuv420p},
3336   {PIX_FMT_ABGR32, PIX_FMT_YUVA420P, abgr32_to_yuva420p},
3337   {PIX_FMT_ABGR32, PIX_FMT_NV12, abgr32_to_nv12},
3338   {PIX_FMT_ABGR32, PIX_FMT_NV21, abgr32_to_nv21},
3339   {PIX_FMT_ABGR32, PIX_FMT_Y800, abgr32_to_y800},
3340   {PIX_FMT_ABGR32, PIX_FMT_Y16, abgr32_to_y16},
3341   {PIX_FMT_ABGR32, PIX_FMT_GRAY8, abgr32_to_gray},
3342   {PIX_FMT_ABGR32, PIX_FMT_GRAY16_L, abgr32_to_gray16_l},
3343   {PIX_FMT_ABGR32, PIX_FMT_GRAY16_B, abgr32_to_gray16_b},
3344   {PIX_FMT_ABGR32, PIX_FMT_AYUV4444, abgr32_to_ayuv4444},
3345
3346   {PIX_FMT_ARGB32, PIX_FMT_RGB24, argb32_to_rgb24},
3347   {PIX_FMT_ARGB32, PIX_FMT_RGBA32, argb32_to_rgba32},
3348   {PIX_FMT_ARGB32, PIX_FMT_YUV420P, argb32_to_yuv420p},
3349   {PIX_FMT_ARGB32, PIX_FMT_YUVA420P, argb32_to_yuva420p},
3350   {PIX_FMT_ARGB32, PIX_FMT_NV12, argb32_to_nv12},
3351   {PIX_FMT_ARGB32, PIX_FMT_NV21, argb32_to_nv21},
3352   {PIX_FMT_ARGB32, PIX_FMT_Y800, argb32_to_y800},
3353   {PIX_FMT_ARGB32, PIX_FMT_Y16, argb32_to_y16},
3354   {PIX_FMT_ARGB32, PIX_FMT_GRAY8, argb32_to_gray},
3355   {PIX_FMT_ARGB32, PIX_FMT_GRAY16_L, argb32_to_gray16_l},
3356   {PIX_FMT_ARGB32, PIX_FMT_GRAY16_B, argb32_to_gray16_b},
3357   {PIX_FMT_ARGB32, PIX_FMT_AYUV4444, argb32_to_ayuv4444},
3358
3359   {PIX_FMT_RGB555, PIX_FMT_RGB24, rgb555_to_rgb24},
3360   {PIX_FMT_RGB555, PIX_FMT_RGB32, rgb555_to_rgba32},
3361   {PIX_FMT_RGB555, PIX_FMT_RGBA32, rgb555_to_rgba32},
3362   {PIX_FMT_RGB555, PIX_FMT_YUV420P, rgb555_to_yuv420p},
3363   {PIX_FMT_RGB555, PIX_FMT_YUVA420P, rgb555_to_yuva420p},
3364   {PIX_FMT_RGB555, PIX_FMT_NV12, rgb555_to_nv12},
3365   {PIX_FMT_RGB555, PIX_FMT_NV21, rgb555_to_nv21},
3366   {PIX_FMT_RGB555, PIX_FMT_Y800, rgb555_to_y800},
3367   {PIX_FMT_RGB555, PIX_FMT_Y16, rgb555_to_y16},
3368   {PIX_FMT_RGB555, PIX_FMT_GRAY8, rgb555_to_gray},
3369   {PIX_FMT_RGB555, PIX_FMT_GRAY16_L, rgb555_to_gray16_l},
3370   {PIX_FMT_RGB555, PIX_FMT_GRAY16_B, rgb555_to_gray16_b},
3371
3372   {PIX_FMT_RGB565, PIX_FMT_RGB24, rgb565_to_rgb24},
3373   {PIX_FMT_RGB565, PIX_FMT_YUV420P, rgb565_to_yuv420p},
3374   {PIX_FMT_RGB565, PIX_FMT_YUVA420P, rgb565_to_yuva420p},
3375   {PIX_FMT_RGB565, PIX_FMT_NV12, rgb565_to_nv12},
3376   {PIX_FMT_RGB565, PIX_FMT_NV21, rgb565_to_nv21},
3377   {PIX_FMT_RGB565, PIX_FMT_Y800, rgb565_to_y800},
3378   {PIX_FMT_RGB565, PIX_FMT_Y16, rgb565_to_y16},
3379   {PIX_FMT_RGB565, PIX_FMT_GRAY8, rgb565_to_gray},
3380   {PIX_FMT_RGB565, PIX_FMT_GRAY16_L, rgb565_to_gray16_l},
3381   {PIX_FMT_RGB565, PIX_FMT_GRAY16_B, rgb565_to_gray16_b},
3382
3383   {PIX_FMT_Y800, PIX_FMT_RGB555, y800_to_rgb555},
3384   {PIX_FMT_Y800, PIX_FMT_RGB565, y800_to_rgb565},
3385   {PIX_FMT_Y800, PIX_FMT_BGR24, y800_to_bgr24},
3386   {PIX_FMT_Y800, PIX_FMT_RGB24, y800_to_rgb24},
3387   {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_rgb32},
3388   {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgr32},
3389   {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_xrgb32},
3390   {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgrx32},
3391   {PIX_FMT_Y800, PIX_FMT_RGBA32, y800_to_rgba32},
3392   {PIX_FMT_Y800, PIX_FMT_BGRA32, y800_to_bgra32},
3393   {PIX_FMT_Y800, PIX_FMT_ARGB32, y800_to_argb32},
3394   {PIX_FMT_Y800, PIX_FMT_ABGR32, y800_to_abgr32},
3395   {PIX_FMT_Y800, PIX_FMT_Y16, y800_to_y16},
3396
3397   {PIX_FMT_Y16, PIX_FMT_RGB555, y16_to_rgb555},
3398   {PIX_FMT_Y16, PIX_FMT_RGB565, y16_to_rgb565},
3399   {PIX_FMT_Y16, PIX_FMT_BGR24, y16_to_bgr24},
3400   {PIX_FMT_Y16, PIX_FMT_RGB24, y16_to_rgb24},
3401   {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_rgb32},
3402   {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgr32},
3403   {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_xrgb32},
3404   {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgrx32},
3405   {PIX_FMT_Y16, PIX_FMT_RGBA32, y16_to_rgba32},
3406   {PIX_FMT_Y16, PIX_FMT_BGRA32, y16_to_bgra32},
3407   {PIX_FMT_Y16, PIX_FMT_ARGB32, y16_to_argb32},
3408   {PIX_FMT_Y16, PIX_FMT_ABGR32, y16_to_abgr32},
3409   {PIX_FMT_Y16, PIX_FMT_Y800, y16_to_y800},
3410
3411   {PIX_FMT_GRAY8, PIX_FMT_RGB555, gray_to_rgb555},
3412   {PIX_FMT_GRAY8, PIX_FMT_RGB565, gray_to_rgb565},
3413   {PIX_FMT_GRAY8, PIX_FMT_RGB24, gray_to_rgb24},
3414   {PIX_FMT_GRAY8, PIX_FMT_BGR24, gray_to_bgr24},
3415   {PIX_FMT_GRAY8, PIX_FMT_RGB32, gray_to_rgb32},
3416   {PIX_FMT_GRAY8, PIX_FMT_BGR32, gray_to_bgr32},
3417   {PIX_FMT_GRAY8, PIX_FMT_xRGB32, gray_to_xrgb32},
3418   {PIX_FMT_GRAY8, PIX_FMT_BGRx32, gray_to_bgrx32},
3419   {PIX_FMT_GRAY8, PIX_FMT_RGBA32, gray_to_rgba32},
3420   {PIX_FMT_GRAY8, PIX_FMT_BGRA32, gray_to_bgra32},
3421   {PIX_FMT_GRAY8, PIX_FMT_ARGB32, gray_to_argb32},
3422   {PIX_FMT_GRAY8, PIX_FMT_ABGR32, gray_to_abgr32},
3423   {PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, gray_to_monowhite},
3424   {PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, gray_to_monoblack},
3425   {PIX_FMT_GRAY8, PIX_FMT_GRAY16_L, gray_to_gray16_l},
3426   {PIX_FMT_GRAY8, PIX_FMT_GRAY16_B, gray_to_gray16_b},
3427
3428   {PIX_FMT_MONOWHITE, PIX_FMT_GRAY8, monowhite_to_gray},
3429
3430   {PIX_FMT_MONOBLACK, PIX_FMT_GRAY8, monoblack_to_gray},
3431
3432   {PIX_FMT_GRAY16_L, PIX_FMT_GRAY8, gray16_l_to_gray},
3433   {PIX_FMT_GRAY16_L, PIX_FMT_RGB555, gray16_l_to_rgb555},
3434   {PIX_FMT_GRAY16_L, PIX_FMT_RGB565, gray16_l_to_rgb565},
3435   {PIX_FMT_GRAY16_L, PIX_FMT_BGR24, gray16_l_to_bgr24},
3436   {PIX_FMT_GRAY16_L, PIX_FMT_RGB24, gray16_l_to_rgb24},
3437   {PIX_FMT_GRAY16_L, PIX_FMT_BGR32, gray16_l_to_bgr32},
3438   {PIX_FMT_GRAY16_L, PIX_FMT_RGB32, gray16_l_to_rgb32},
3439   {PIX_FMT_GRAY16_L, PIX_FMT_xRGB32, gray16_l_to_xrgb32},
3440   {PIX_FMT_GRAY16_L, PIX_FMT_BGRx32, gray16_l_to_bgrx32},
3441   {PIX_FMT_GRAY16_L, PIX_FMT_ABGR32, gray16_l_to_abgr32},
3442   {PIX_FMT_GRAY16_L, PIX_FMT_ARGB32, gray16_l_to_argb32},
3443   {PIX_FMT_GRAY16_L, PIX_FMT_BGRA32, gray16_l_to_bgra32},
3444   {PIX_FMT_GRAY16_L, PIX_FMT_RGBA32, gray16_l_to_rgba32},
3445   {PIX_FMT_GRAY16_L, PIX_FMT_GRAY16_B, gray16_b_to_gray16_l},
3446
3447   {PIX_FMT_GRAY16_B, PIX_FMT_GRAY8, gray16_b_to_gray},
3448   {PIX_FMT_GRAY16_B, PIX_FMT_RGB555, gray16_b_to_rgb555},
3449   {PIX_FMT_GRAY16_B, PIX_FMT_RGB565, gray16_b_to_rgb565},
3450   {PIX_FMT_GRAY16_B, PIX_FMT_BGR24, gray16_b_to_bgr24},
3451   {PIX_FMT_GRAY16_B, PIX_FMT_RGB24, gray16_b_to_rgb24},
3452   {PIX_FMT_GRAY16_B, PIX_FMT_BGR32, gray16_b_to_bgr32},
3453   {PIX_FMT_GRAY16_B, PIX_FMT_RGB32, gray16_b_to_rgb32},
3454   {PIX_FMT_GRAY16_B, PIX_FMT_xRGB32, gray16_b_to_xrgb32},
3455   {PIX_FMT_GRAY16_B, PIX_FMT_BGRx32, gray16_b_to_bgrx32},
3456   {PIX_FMT_GRAY16_B, PIX_FMT_ABGR32, gray16_b_to_abgr32},
3457   {PIX_FMT_GRAY16_B, PIX_FMT_ARGB32, gray16_b_to_argb32},
3458   {PIX_FMT_GRAY16_B, PIX_FMT_BGRA32, gray16_b_to_bgra32},
3459   {PIX_FMT_GRAY16_B, PIX_FMT_RGBA32, gray16_b_to_rgba32},
3460   {PIX_FMT_GRAY16_B, PIX_FMT_GRAY16_L, gray16_b_to_gray16_l},
3461
3462   {PIX_FMT_PAL8, PIX_FMT_RGB555, pal8_to_rgb555},
3463   {PIX_FMT_PAL8, PIX_FMT_RGB565, pal8_to_rgb565},
3464   {PIX_FMT_PAL8, PIX_FMT_BGR24, pal8_to_bgr24},
3465   {PIX_FMT_PAL8, PIX_FMT_RGB24, pal8_to_rgb24},
3466   {PIX_FMT_PAL8, PIX_FMT_RGB32, pal8_to_rgb32},
3467   {PIX_FMT_PAL8, PIX_FMT_BGR32, pal8_to_bgr32},
3468   {PIX_FMT_PAL8, PIX_FMT_xRGB32, pal8_to_xrgb32},
3469   {PIX_FMT_PAL8, PIX_FMT_BGRx32, pal8_to_bgrx32},
3470   {PIX_FMT_PAL8, PIX_FMT_RGBA32, pal8_to_rgba32},
3471   {PIX_FMT_PAL8, PIX_FMT_BGRA32, pal8_to_bgra32},
3472   {PIX_FMT_PAL8, PIX_FMT_ARGB32, pal8_to_argb32},
3473   {PIX_FMT_PAL8, PIX_FMT_ABGR32, pal8_to_abgr32},
3474
3475   {PIX_FMT_UYVY411, PIX_FMT_YUV411P, uyvy411_to_yuv411p},
3476   {PIX_FMT_YUV411P, PIX_FMT_UYVY411, yuv411p_to_uyvy411},
3477
3478   {PIX_FMT_V308, PIX_FMT_RGB24, v308_to_rgb24},
3479
3480   {PIX_FMT_AYUV4444, PIX_FMT_RGBA32, ayuv4444_to_rgba32},
3481   {PIX_FMT_AYUV4444, PIX_FMT_ARGB32, ayuv4444_to_argb32},
3482   {PIX_FMT_AYUV4444, PIX_FMT_BGRA32, ayuv4444_to_bgra32},
3483   {PIX_FMT_AYUV4444, PIX_FMT_ABGR32, ayuv4444_to_abgr32},
3484   {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24},
3485   {PIX_FMT_AYUV4444, PIX_FMT_YUVA420P, ayuv4444_to_yuva420p},
3486
3487   {PIX_FMT_YUVA420P, PIX_FMT_YUV420P, yuva420p_to_yuv420p},
3488   {PIX_FMT_YUVA420P, PIX_FMT_YUV422, yuva420p_to_yuv422},
3489   {PIX_FMT_YUVA420P, PIX_FMT_AYUV4444, yuva420p_to_ayuv4444},
3490   {PIX_FMT_YUVA420P, PIX_FMT_RGB555, yuva420p_to_rgb555},
3491   {PIX_FMT_YUVA420P, PIX_FMT_RGB565, yuva420p_to_rgb565},
3492   {PIX_FMT_YUVA420P, PIX_FMT_BGR24, yuva420p_to_bgr24},
3493   {PIX_FMT_YUVA420P, PIX_FMT_RGB24, yuva420p_to_rgb24},
3494   {PIX_FMT_YUVA420P, PIX_FMT_RGB32, yuva420p_to_rgb32},
3495   {PIX_FMT_YUVA420P, PIX_FMT_BGR32, yuva420p_to_bgr32},
3496   {PIX_FMT_YUVA420P, PIX_FMT_xRGB32, yuva420p_to_xrgb32},
3497   {PIX_FMT_YUVA420P, PIX_FMT_BGRx32, yuva420p_to_bgrx32},
3498   {PIX_FMT_YUVA420P, PIX_FMT_RGBA32, yuva420p_to_rgba32},
3499   {PIX_FMT_YUVA420P, PIX_FMT_BGRA32, yuva420p_to_bgra32},
3500   {PIX_FMT_YUVA420P, PIX_FMT_ARGB32, yuva420p_to_argb32},
3501   {PIX_FMT_YUVA420P, PIX_FMT_ABGR32, yuva420p_to_abgr32},
3502 };
3503
3504 static ConvertEntry *
3505 get_convert_table_entry (int src_pix_fmt, int dst_pix_fmt)
3506 {
3507   int i;
3508
3509   for (i = 0; i < sizeof (convert_table) / sizeof (convert_table[0]); i++) {
3510     if (convert_table[i].src == src_pix_fmt &&
3511         convert_table[i].dest == dst_pix_fmt) {
3512       return convert_table + i;
3513     }
3514   }
3515
3516   return NULL;
3517 }
3518
3519 static int
3520 avpicture_alloc (AVPicture * picture, int pix_fmt, int width, int height,
3521     int interlaced)
3522 {
3523   unsigned int size;
3524   void *ptr;
3525
3526   size = avpicture_get_size (pix_fmt, width, height);
3527   ptr = av_malloc (size);
3528   if (!ptr)
3529     goto fail;
3530   gst_ffmpegcsp_avpicture_fill (picture, ptr, pix_fmt, width, height,
3531       interlaced);
3532   return 0;
3533 fail:
3534   memset (picture, 0, sizeof (AVPicture));
3535   return -1;
3536 }
3537
3538 static void
3539 avpicture_free (AVPicture * picture)
3540 {
3541   av_free (picture->data[0]);
3542 }
3543
3544 /* return true if yuv planar */
3545 static inline int
3546 is_yuv_planar (PixFmtInfo * ps)
3547 {
3548   return (ps->color_type == FF_COLOR_YUV ||
3549       ps->color_type == FF_COLOR_YUV_JPEG) && ps->pixel_type == FF_PIXEL_PLANAR;
3550 }
3551
3552 /* XXX: always use linesize. Return -1 if not supported */
3553 int
3554 img_convert (AVPicture * dst, int dst_pix_fmt,
3555     const AVPicture * src, int src_pix_fmt, int src_width, int src_height)
3556 {
3557   static int inited;
3558   int i, ret, dst_width, dst_height, int_pix_fmt;
3559   PixFmtInfo *src_pix, *dst_pix;
3560   ConvertEntry *ce;
3561   AVPicture tmp1, *tmp = &tmp1;
3562
3563   if (G_UNLIKELY (src_width <= 0 || src_height <= 0))
3564     return 0;
3565
3566   if (G_UNLIKELY (!inited)) {
3567     inited = 1;
3568     img_convert_init ();
3569   }
3570
3571   dst_width = src_width;
3572   dst_height = src_height;
3573
3574   dst_pix = get_pix_fmt_info (dst_pix_fmt);
3575   src_pix = get_pix_fmt_info (src_pix_fmt);
3576   if (G_UNLIKELY (src_pix_fmt == dst_pix_fmt)) {
3577     /* no conversion needed: just copy */
3578     img_copy (dst, src, dst_pix_fmt, dst_width, dst_height);
3579     return 0;
3580   }
3581
3582   ce = get_convert_table_entry (src_pix_fmt, dst_pix_fmt);
3583   if (ce && ce->convert) {
3584     /* specific conversion routine */
3585     ce->convert (dst, src, dst_width, dst_height);
3586     return 0;
3587   }
3588
3589   /* gray to YUV */
3590   if (is_yuv_planar (dst_pix) && dst_pix_fmt != PIX_FMT_Y16
3591       && src_pix_fmt == PIX_FMT_GRAY8) {
3592     int w, h, y;
3593     uint8_t *d;
3594
3595     if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
3596       img_copy_plane (dst->data[0], dst->linesize[0],
3597           src->data[0], src->linesize[0], dst_width, dst_height);
3598     } else {
3599       img_apply_table (dst->data[0], dst->linesize[0],
3600           src->data[0], src->linesize[0],
3601           dst_width, dst_height, y_jpeg_to_ccir);
3602     }
3603     /* fill U and V with 128 */
3604     w = dst_width;
3605     h = dst_height;
3606     w >>= dst_pix->x_chroma_shift;
3607     h >>= dst_pix->y_chroma_shift;
3608     for (i = 1; i <= 2; i++) {
3609       d = dst->data[i];
3610       if (!d)
3611         continue;
3612       for (y = 0; y < h; y++) {
3613         memset (d, 128, w);
3614         d += dst->linesize[i];
3615       }
3616     }
3617     return 0;
3618   }
3619
3620   /* YUV to gray */
3621   if (is_yuv_planar (src_pix) && src_pix_fmt != PIX_FMT_Y16
3622       && dst_pix_fmt == PIX_FMT_GRAY8) {
3623     if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
3624       img_copy_plane (dst->data[0], dst->linesize[0],
3625           src->data[0], src->linesize[0], dst_width, dst_height);
3626     } else {
3627       img_apply_table (dst->data[0], dst->linesize[0],
3628           src->data[0], src->linesize[0],
3629           dst_width, dst_height, y_ccir_to_jpeg);
3630     }
3631     return 0;
3632   }
3633
3634   /* YUV to YUV planar */
3635   if (is_yuv_planar (dst_pix) && is_yuv_planar (src_pix) &&
3636       dst_pix->depth == src_pix->depth) {
3637     int x_shift, y_shift, xy_shift;
3638     void (*resize_func) (uint8_t * dst, int dst_wrap, int dst_width,
3639         int dst_height, const uint8_t * src, int src_wrap, int src_width,
3640         int src_height);
3641
3642     x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
3643     y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
3644     xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
3645
3646     /* there must be filters for conversion at least from and to
3647        YUV444 format */
3648     switch (xy_shift) {
3649       case 0x00:
3650         resize_func = img_copy_plane_resize;
3651         break;
3652       case 0x10:
3653         resize_func = shrink21;
3654         break;
3655       case 0x20:
3656         resize_func = shrink41;
3657         break;
3658       case 0x01:
3659         resize_func = shrink12;
3660         break;
3661       case 0x11:
3662         resize_func = shrink22;
3663         break;
3664       case 0x22:
3665         resize_func = shrink44;
3666         break;
3667       case 0xf0:
3668         resize_func = grow21;
3669         break;
3670       case 0xe0:
3671         resize_func = grow41;
3672         break;
3673       case 0xff:
3674         resize_func = grow22;
3675         break;
3676       case 0xee:
3677         resize_func = grow44;
3678         break;
3679       case 0xf1:
3680         resize_func = conv411;
3681         break;
3682       default:
3683         /* currently not handled */
3684         goto no_chroma_filter;
3685     }
3686
3687     img_copy_plane (dst->data[0], dst->linesize[0],
3688         src->data[0], src->linesize[0], dst_width, dst_height);
3689
3690 #define GEN_MASK(x) ((1<<(x))-1)
3691 #define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x))
3692
3693     for (i = 1; i <= 2; i++) {
3694       gint w, h;
3695       gint s_w, s_h;
3696
3697       w = DIV_ROUND_UP_X (dst_width, dst_pix->x_chroma_shift);
3698       h = DIV_ROUND_UP_X (dst_height, dst_pix->y_chroma_shift);
3699
3700       s_w = DIV_ROUND_UP_X (src_width, src_pix->x_chroma_shift);
3701       s_h = DIV_ROUND_UP_X (src_height, src_pix->y_chroma_shift);
3702
3703       if (src->data[i] != NULL && dst->data[i] != NULL) {
3704         resize_func (dst->data[i], dst->linesize[i], w, h,
3705             src->data[i], src->linesize[i], s_w, s_h);
3706       } else if (dst->data[i] != NULL) {
3707         memset (dst->data[i], 128, dst->linesize[i] * h);
3708       }
3709     }
3710     /* if yuv color space conversion is needed, we do it here on
3711        the destination image */
3712     if (dst_pix->color_type != src_pix->color_type) {
3713       const uint8_t *y_table, *c_table;
3714
3715       if (dst_pix->color_type == FF_COLOR_YUV) {
3716         y_table = y_jpeg_to_ccir;
3717         c_table = c_jpeg_to_ccir;
3718       } else {
3719         y_table = y_ccir_to_jpeg;
3720         c_table = c_ccir_to_jpeg;
3721       }
3722       img_apply_table (dst->data[0], dst->linesize[0],
3723           dst->data[0], dst->linesize[0], dst_width, dst_height, y_table);
3724
3725       for (i = 1; i <= 2; i++)
3726         img_apply_table (dst->data[i], dst->linesize[i],
3727             dst->data[i], dst->linesize[i],
3728             dst_width >> dst_pix->x_chroma_shift,
3729             dst_height >> dst_pix->y_chroma_shift, c_table);
3730     }
3731     return 0;
3732   }
3733 no_chroma_filter:
3734   GST_CAT_INFO (ffmpegcolorspace_performance,
3735       "no direct path to convert colorspace from %s -> %s", src_pix->name,
3736       dst_pix->name);
3737
3738   /* try to use an intermediate format */
3739   if (src_pix_fmt == PIX_FMT_YUV422 || dst_pix_fmt == PIX_FMT_YUV422) {
3740     /* specific case: convert to YUV422P first */
3741     int_pix_fmt = PIX_FMT_YUV422P;
3742   } else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422 ||
3743       src_pix_fmt == PIX_FMT_YVYU422 || dst_pix_fmt == PIX_FMT_YVYU422) {
3744     /* specific case: convert to YUV422P first */
3745     int_pix_fmt = PIX_FMT_YUV422P;
3746   } else if (src_pix_fmt == PIX_FMT_UYVY411 || dst_pix_fmt == PIX_FMT_UYVY411) {
3747     /* specific case: convert to YUV411P first */
3748     int_pix_fmt = PIX_FMT_YUV411P;
3749   } else if ((src_pix->color_type == FF_COLOR_GRAY &&
3750           src_pix_fmt != PIX_FMT_GRAY8) ||
3751       (dst_pix->color_type == FF_COLOR_GRAY && dst_pix_fmt != PIX_FMT_GRAY8)) {
3752     /* gray8 is the normalized format */
3753     int_pix_fmt = PIX_FMT_GRAY8;
3754   } else if (src_pix_fmt == PIX_FMT_Y16 || dst_pix_fmt == PIX_FMT_Y16) {
3755     /* y800 is the normalized format */
3756     int_pix_fmt = PIX_FMT_Y800;
3757   } else if ((is_yuv_planar (src_pix) &&
3758           src_pix_fmt != PIX_FMT_YUV444P && src_pix_fmt != PIX_FMT_YUVJ444P)) {
3759     /* yuv444 is the normalized format */
3760     if (src_pix->color_type == FF_COLOR_YUV_JPEG)
3761       int_pix_fmt = PIX_FMT_YUVJ444P;
3762     else
3763       int_pix_fmt = PIX_FMT_YUV444P;
3764   } else if ((is_yuv_planar (dst_pix) &&
3765           dst_pix_fmt != PIX_FMT_YUV444P && dst_pix_fmt != PIX_FMT_YUVJ444P)) {
3766     /* yuv444 is the normalized format */
3767     if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
3768       int_pix_fmt = PIX_FMT_YUVJ444P;
3769     else
3770       int_pix_fmt = PIX_FMT_YUV444P;
3771   } else {
3772     /* the two formats are rgb or gray8 or yuv[j]444p */
3773     if (src_pix->is_alpha && dst_pix->is_alpha)
3774       int_pix_fmt = PIX_FMT_RGBA32;
3775     else
3776       int_pix_fmt = PIX_FMT_RGB24;
3777   }
3778   if (avpicture_alloc (tmp, int_pix_fmt, dst_width, dst_height,
3779           dst->interlaced) < 0)
3780     return -1;
3781   ret = -1;
3782   if (img_convert (tmp, int_pix_fmt,
3783           src, src_pix_fmt, src_width, src_height) < 0)
3784     goto fail1;
3785
3786   if (img_convert (dst, dst_pix_fmt,
3787           tmp, int_pix_fmt, dst_width, dst_height) < 0)
3788     goto fail1;
3789   ret = 0;
3790 fail1:
3791   avpicture_free (tmp);
3792   return ret;
3793 }
3794
3795 /* NOTE: we scan all the pixels to have an exact information */
3796 static int
3797 get_alpha_info_pal8 (const AVPicture * src, int width, int height)
3798 {
3799   const unsigned char *p;
3800   int src_wrap, ret, x, y;
3801   unsigned int a;
3802   uint32_t *palette = (uint32_t *) src->data[1];
3803
3804   p = src->data[0];
3805   src_wrap = src->linesize[0] - width;
3806   ret = 0;
3807   for (y = 0; y < height; y++) {
3808     for (x = 0; x < width; x++) {
3809       a = palette[p[0]] >> 24;
3810       if (a == 0x00) {
3811         ret |= FF_ALPHA_TRANSP;
3812       } else if (a != 0xff) {
3813         ret |= FF_ALPHA_SEMI_TRANSP;
3814       }
3815       p++;
3816     }
3817     p += src_wrap;
3818   }
3819   return ret;
3820 }
3821
3822 /**
3823  * Tell if an image really has transparent alpha values.
3824  * @return ored mask of FF_ALPHA_xxx constants
3825  */
3826 int
3827 img_get_alpha_info (const AVPicture * src, int pix_fmt, int width, int height)
3828 {
3829   const PixFmtInfo *pf;
3830   int ret;
3831
3832   pf = get_pix_fmt_info (pix_fmt);
3833   /* no alpha can be represented in format */
3834   if (!pf->is_alpha)
3835     return 0;
3836   switch (pix_fmt) {
3837     case PIX_FMT_RGB32:
3838       ret = get_alpha_info_rgb32 (src, width, height);
3839       break;
3840     case PIX_FMT_BGR32:
3841       ret = get_alpha_info_bgr32 (src, width, height);
3842       break;
3843     case PIX_FMT_xRGB32:
3844       ret = get_alpha_info_xrgb32 (src, width, height);
3845       break;
3846     case PIX_FMT_BGRx32:
3847       ret = get_alpha_info_bgrx32 (src, width, height);
3848       break;
3849     case PIX_FMT_RGBA32:
3850       ret = get_alpha_info_rgba32 (src, width, height);
3851       break;
3852     case PIX_FMT_BGRA32:
3853       ret = get_alpha_info_bgra32 (src, width, height);
3854       break;
3855     case PIX_FMT_ARGB32:
3856       ret = get_alpha_info_argb32 (src, width, height);
3857       break;
3858     case PIX_FMT_ABGR32:
3859       ret = get_alpha_info_abgr32 (src, width, height);
3860       break;
3861     case PIX_FMT_RGB555:
3862       ret = get_alpha_info_rgb555 (src, width, height);
3863       break;
3864     case PIX_FMT_PAL8:
3865       ret = get_alpha_info_pal8 (src, width, height);
3866       break;
3867     default:
3868       /* we do not know, so everything is indicated */
3869       ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
3870       break;
3871   }
3872   return ret;
3873 }
3874
3875 #ifdef HAVE_MMX
3876 #define DEINT_INPLACE_LINE_LUM \
3877                     movd_m2r(lum_m4[0],mm0);\
3878                     movd_m2r(lum_m3[0],mm1);\
3879                     movd_m2r(lum_m2[0],mm2);\
3880                     movd_m2r(lum_m1[0],mm3);\
3881                     movd_m2r(lum[0],mm4);\
3882                     punpcklbw_r2r(mm7,mm0);\
3883                     movd_r2m(mm2,lum_m4[0]);\
3884                     punpcklbw_r2r(mm7,mm1);\
3885                     punpcklbw_r2r(mm7,mm2);\
3886                     punpcklbw_r2r(mm7,mm3);\
3887                     punpcklbw_r2r(mm7,mm4);\
3888                     paddw_r2r(mm3,mm1);\
3889                     psllw_i2r(1,mm2);\
3890                     paddw_r2r(mm4,mm0);\
3891                     psllw_i2r(2,mm1);\
3892                     paddw_r2r(mm6,mm2);\
3893                     paddw_r2r(mm2,mm1);\
3894                     psubusw_r2r(mm0,mm1);\
3895                     psrlw_i2r(3,mm1);\
3896                     packuswb_r2r(mm7,mm1);\
3897                     movd_r2m(mm1,lum_m2[0]);
3898
3899 #define DEINT_LINE_LUM \
3900                     movd_m2r(lum_m4[0],mm0);\
3901                     movd_m2r(lum_m3[0],mm1);\
3902                     movd_m2r(lum_m2[0],mm2);\
3903                     movd_m2r(lum_m1[0],mm3);\
3904                     movd_m2r(lum[0],mm4);\
3905                     punpcklbw_r2r(mm7,mm0);\
3906                     punpcklbw_r2r(mm7,mm1);\
3907                     punpcklbw_r2r(mm7,mm2);\
3908                     punpcklbw_r2r(mm7,mm3);\
3909                     punpcklbw_r2r(mm7,mm4);\
3910                     paddw_r2r(mm3,mm1);\
3911                     psllw_i2r(1,mm2);\
3912                     paddw_r2r(mm4,mm0);\
3913                     psllw_i2r(2,mm1);\
3914                     paddw_r2r(mm6,mm2);\
3915                     paddw_r2r(mm2,mm1);\
3916                     psubusw_r2r(mm0,mm1);\
3917                     psrlw_i2r(3,mm1);\
3918                     packuswb_r2r(mm7,mm1);\
3919                     movd_r2m(mm1,dst[0]);
3920 #endif
3921
3922 /* filter parameters: [-1 4 2 4 -1] // 8 */
3923 #if 0
3924 static void
3925 deinterlace_line (uint8_t * dst,
3926     const uint8_t * lum_m4, const uint8_t * lum_m3,
3927     const uint8_t * lum_m2, const uint8_t * lum_m1,
3928     const uint8_t * lum, int size)
3929 {
3930 #ifndef HAVE_MMX
3931   uint8_t *cm = cropTbl + MAX_NEG_CROP;
3932   int sum;
3933
3934   for (; size > 0; size--) {
3935     sum = -lum_m4[0];
3936     sum += lum_m3[0] << 2;
3937     sum += lum_m2[0] << 1;
3938     sum += lum_m1[0] << 2;
3939     sum += -lum[0];
3940     dst[0] = cm[(sum + 4) >> 3];
3941     lum_m4++;
3942     lum_m3++;
3943     lum_m2++;
3944     lum_m1++;
3945     lum++;
3946     dst++;
3947   }
3948 #else
3949
3950   {
3951     mmx_t rounder;
3952
3953     rounder.uw[0] = 4;
3954     rounder.uw[1] = 4;
3955     rounder.uw[2] = 4;
3956     rounder.uw[3] = 4;
3957     pxor_r2r (mm7, mm7);
3958     movq_m2r (rounder, mm6);
3959   }
3960   for (; size > 3; size -= 4) {
3961     DEINT_LINE_LUM lum_m4 += 4;
3962
3963     lum_m3 += 4;
3964     lum_m2 += 4;
3965     lum_m1 += 4;
3966     lum += 4;
3967     dst += 4;
3968   }
3969 #endif
3970 }
3971
3972 static void
3973 deinterlace_line_inplace (uint8_t * lum_m4, uint8_t * lum_m3, uint8_t * lum_m2,
3974     uint8_t * lum_m1, uint8_t * lum, int size)
3975 {
3976 #ifndef HAVE_MMX
3977   uint8_t *cm = cropTbl + MAX_NEG_CROP;
3978   int sum;
3979
3980   for (; size > 0; size--) {
3981     sum = -lum_m4[0];
3982     sum += lum_m3[0] << 2;
3983     sum += lum_m2[0] << 1;
3984     lum_m4[0] = lum_m2[0];
3985     sum += lum_m1[0] << 2;
3986     sum += -lum[0];
3987     lum_m2[0] = cm[(sum + 4) >> 3];
3988     lum_m4++;
3989     lum_m3++;
3990     lum_m2++;
3991     lum_m1++;
3992     lum++;
3993   }
3994 #else
3995
3996   {
3997     mmx_t rounder;
3998
3999     rounder.uw[0] = 4;
4000     rounder.uw[1] = 4;
4001     rounder.uw[2] = 4;
4002     rounder.uw[3] = 4;
4003     pxor_r2r (mm7, mm7);
4004     movq_m2r (rounder, mm6);
4005   }
4006   for (; size > 3; size -= 4) {
4007     DEINT_INPLACE_LINE_LUM lum_m4 += 4;
4008
4009     lum_m3 += 4;
4010     lum_m2 += 4;
4011     lum_m1 += 4;
4012     lum += 4;
4013   }
4014 #endif
4015 }
4016 #endif
4017
4018 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
4019    top field is copied as is, but the bottom field is deinterlaced
4020    against the top field. */
4021 #if 0
4022 static void
4023 deinterlace_bottom_field (uint8_t * dst, int dst_wrap,
4024     const uint8_t * src1, int src_wrap, int width, int height)
4025 {
4026   const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
4027   int y;
4028
4029   src_m2 = src1;
4030   src_m1 = src1;
4031   src_0 = &src_m1[src_wrap];
4032   src_p1 = &src_0[src_wrap];
4033   src_p2 = &src_p1[src_wrap];
4034   for (y = 0; y < (height - 2); y += 2) {
4035     memcpy (dst, src_m1, width);
4036     dst += dst_wrap;
4037     deinterlace_line (dst, src_m2, src_m1, src_0, src_p1, src_p2, width);
4038     src_m2 = src_0;
4039     src_m1 = src_p1;
4040     src_0 = src_p2;
4041     src_p1 += 2 * src_wrap;
4042     src_p2 += 2 * src_wrap;
4043     dst += dst_wrap;
4044   }
4045   memcpy (dst, src_m1, width);
4046   dst += dst_wrap;
4047   /* do last line */
4048   deinterlace_line (dst, src_m2, src_m1, src_0, src_0, src_0, width);
4049 }
4050
4051 static void
4052 deinterlace_bottom_field_inplace (uint8_t * src1, int src_wrap,
4053     int width, int height)
4054 {
4055   uint8_t *src_m1, *src_0, *src_p1, *src_p2;
4056   int y;
4057   uint8_t *buf;
4058
4059   buf = (uint8_t *) av_malloc (width);
4060
4061   src_m1 = src1;
4062   memcpy (buf, src_m1, width);
4063   src_0 = &src_m1[src_wrap];
4064   src_p1 = &src_0[src_wrap];
4065   src_p2 = &src_p1[src_wrap];
4066   for (y = 0; y < (height - 2); y += 2) {
4067     deinterlace_line_inplace (buf, src_m1, src_0, src_p1, src_p2, width);
4068     src_m1 = src_p1;
4069     src_0 = src_p2;
4070     src_p1 += 2 * src_wrap;
4071     src_p2 += 2 * src_wrap;
4072   }
4073   /* do last line */
4074   deinterlace_line_inplace (buf, src_m1, src_0, src_0, src_0, width);
4075   av_free (buf);
4076 }
4077 #endif
4078
4079 /* deinterlace - if not supported return -1 */
4080 #if 0
4081 static int
4082 avpicture_deinterlace (AVPicture * dst, const AVPicture * src,
4083     int pix_fmt, int width, int height)
4084 {
4085   int i;
4086
4087   if (pix_fmt != PIX_FMT_YUV420P &&
4088       pix_fmt != PIX_FMT_YUV422P &&
4089       pix_fmt != PIX_FMT_YUV444P && pix_fmt != PIX_FMT_YUV411P)
4090     return -1;
4091   if ((width & 3) != 0 || (height & 3) != 0)
4092     return -1;
4093
4094   for (i = 0; i < 3; i++) {
4095     if (i == 1) {
4096       switch (pix_fmt) {
4097         case PIX_FMT_YUV420P:
4098           width >>= 1;
4099           height >>= 1;
4100           break;
4101         case PIX_FMT_YUV422P:
4102           width >>= 1;
4103           break;
4104         case PIX_FMT_YUV411P:
4105           width >>= 2;
4106           break;
4107         default:
4108           break;
4109       }
4110     }
4111     if (src == dst) {
4112       deinterlace_bottom_field_inplace (dst->data[i], dst->linesize[i],
4113           width, height);
4114     } else {
4115       deinterlace_bottom_field (dst->data[i], dst->linesize[i],
4116           src->data[i], src->linesize[i], width, height);
4117     }
4118   }
4119 #ifdef HAVE_MMX
4120   emms ();
4121 #endif
4122   return 0;
4123 }
4124 #endif
4125
4126 #undef FIX