Statistics
| Branch: | Revision:

ffmpeg / libavcodec / imgconvert.c @ 6d93f194

History | View | Annotate | Download (57.4 KB)

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

    
26
#include "avcodec.h"
27
#include "dsputil.h"
28

    
29
#ifdef USE_FASTMEMCPY
30
#include "fastmemcpy.h"
31
#endif
32

    
33
#ifdef HAVE_MMX
34
#include "i386/mmx.h"
35
#endif
36

    
37
typedef struct PixFmtInfo {
38
    const char *name;
39
    uint8_t nb_components;     /* number of components in AVPicture array  */
40
    uint8_t is_yuv : 1;    /* true if YUV instead of RGB color space */
41
    uint8_t is_packed : 1; /* true if multiple components in same word */
42
    uint8_t is_paletted : 1; /* true if paletted */
43
    uint8_t is_alpha : 1;    /* true if alpha can be specified */
44
    uint8_t is_gray : 1;     /* true if gray or monochrome format */
45
    uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
46
    uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
47
} PixFmtInfo;
48

    
49
/* this table gives more information about formats */
50
static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
51
    /* YUV formats */
52
    [PIX_FMT_YUV420P] = {
53
        .name = "yuv420p",
54
        .nb_components = 3, .is_yuv = 1,
55
        .x_chroma_shift = 1, .y_chroma_shift = 1, 
56
    },
57
    [PIX_FMT_YUV422P] = {
58
        .name = "yuv422p",
59
        .nb_components = 3, .is_yuv = 1,
60
        .x_chroma_shift = 1, .y_chroma_shift = 0, 
61
    },
62
    [PIX_FMT_YUV444P] = {
63
        .name = "yuv444p",
64
        .nb_components = 3, .is_yuv = 1,
65
        .x_chroma_shift = 0, .y_chroma_shift = 0, 
66
    },
67
    [PIX_FMT_YUV422] = {
68
        .name = "yuv422",
69
        .nb_components = 1, .is_yuv = 1, .is_packed = 1,
70
        .x_chroma_shift = 1, .y_chroma_shift = 0,
71
    },
72
    [PIX_FMT_YUV410P] = {
73
        .name = "yuv410p",
74
        .nb_components = 3, .is_yuv = 1,
75
        .x_chroma_shift = 2, .y_chroma_shift = 2,
76
    },
77
    [PIX_FMT_YUV411P] = {
78
        .name = "yuv411p",
79
        .nb_components = 3, .is_yuv = 1,
80
        .x_chroma_shift = 2, .y_chroma_shift = 0,
81
    },
82

    
83
    /* RGB formats */
84
    [PIX_FMT_RGB24] = {
85
        .name = "rgb24",
86
        .nb_components = 1, .is_packed = 1,
87
    },
88
    [PIX_FMT_BGR24] = {
89
        .name = "bgr24",
90
        .nb_components = 1, .is_packed = 1,
91
    },
92
    [PIX_FMT_RGBA32] = {
93
        .name = "rgba32",
94
        .nb_components = 1, .is_packed = 1, .is_alpha = 1,
95
    },
96
    [PIX_FMT_RGB565] = {
97
        .name = "rgb565",
98
        .nb_components = 1, .is_packed = 1,
99
    },
100
    [PIX_FMT_RGB555] = {
101
        .name = "rgb555",
102
        .nb_components = 1, .is_packed = 1, .is_alpha = 1,
103
    },
104

    
105
    /* gray / mono formats */
106
    [PIX_FMT_GRAY8] = {
107
        .name = "gray",
108
        .nb_components = 1, .is_gray = 1,
109
    },
110
    [PIX_FMT_MONOWHITE] = {
111
        .name = "monow",
112
        .nb_components = 1, .is_packed = 1, .is_gray = 1,
113
    },
114
    [PIX_FMT_MONOBLACK] = {
115
        .name = "monob",
116
        .nb_components = 1, .is_packed = 1, .is_gray = 1,
117
    },
118

    
119
    /* paletted formats */
120
    [PIX_FMT_PAL8] = {
121
        .name = "pal8",
122
        .nb_components = 1, .is_packed = 1, .is_alpha = 1, .is_paletted = 1,
123
    },
124
};
125

    
126
void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
127
{
128
    if (pix_fmt_info[pix_fmt].is_yuv) {
129
        *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
130
        *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
131
    } else {
132
        *h_shift=0;
133
        *v_shift=0;
134
    }
135
}
136

    
137
const char *avcodec_get_pix_fmt_name(int pix_fmt)
138
{
139
    if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
140
        return "???";
141
    else
142
        return pix_fmt_info[pix_fmt].name;
143
}
144

    
145
/* Picture field are filled with 'ptr' addresses. Also return size */
146
int avpicture_fill(AVPicture *picture, uint8_t *ptr,
147
                   int pix_fmt, int width, int height)
148
{
149
    int size, w2, h2, size2;
150
    PixFmtInfo *pinfo;
151
    
152
    pinfo = &pix_fmt_info[pix_fmt];
153
    size = width * height;
154
    switch(pix_fmt) {
155
    case PIX_FMT_YUV420P:
156
    case PIX_FMT_YUV422P:
157
    case PIX_FMT_YUV444P:
158
    case PIX_FMT_YUV410P:
159
    case PIX_FMT_YUV411P:
160
        w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
161
        h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
162
        size2 = w2 * h2;
163
        picture->data[0] = ptr;
164
        picture->data[1] = picture->data[0] + size;
165
        picture->data[2] = picture->data[1] + size2;
166
        picture->linesize[0] = width;
167
        picture->linesize[1] = w2;
168
        picture->linesize[2] = w2;
169
        return size + 2 * size2;
170
    case PIX_FMT_RGB24:
171
    case PIX_FMT_BGR24:
172
        picture->data[0] = ptr;
173
        picture->data[1] = NULL;
174
        picture->data[2] = NULL;
175
        picture->linesize[0] = width * 3;
176
        return size * 3;
177
    case PIX_FMT_RGBA32:
178
        picture->data[0] = ptr;
179
        picture->data[1] = NULL;
180
        picture->data[2] = NULL;
181
        picture->linesize[0] = width * 4;
182
        return size * 4;
183
    case PIX_FMT_RGB555:
184
    case PIX_FMT_RGB565:
185
    case PIX_FMT_YUV422:
186
        picture->data[0] = ptr;
187
        picture->data[1] = NULL;
188
        picture->data[2] = NULL;
189
        picture->linesize[0] = width * 2;
190
        return size * 2;
191
    case PIX_FMT_GRAY8:
192
        picture->data[0] = ptr;
193
        picture->data[1] = NULL;
194
        picture->data[2] = NULL;
195
        picture->linesize[0] = width;
196
        return size;
197
    case PIX_FMT_MONOWHITE:
198
    case PIX_FMT_MONOBLACK:
199
        picture->data[0] = ptr;
200
        picture->data[1] = NULL;
201
        picture->data[2] = NULL;
202
        picture->linesize[0] = (width + 7) >> 3;
203
        return picture->linesize[0] * height;
204
    case PIX_FMT_PAL8:
205
        size2 = (size + 3) & ~3;
206
        picture->data[0] = ptr;
207
        picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
208
        picture->data[2] = NULL;
209
        picture->linesize[0] = width;
210
        picture->linesize[1] = 4;
211
        return size2 + 256 * 4;
212
    default:
213
        picture->data[0] = NULL;
214
        picture->data[1] = NULL;
215
        picture->data[2] = NULL;
216
        picture->data[3] = NULL;
217
        return -1;
218
    }
219
}
220

    
221
int avpicture_get_size(int pix_fmt, int width, int height)
222
{
223
    AVPicture dummy_pict;
224
    return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
225
}
226

    
227

    
228
/* XXX: totally non optimized */
229

    
230
static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
231
                              int width, int height)
232
{
233
    uint8_t *lum, *cb, *cr;
234
    int x, y;
235
    const uint8_t *p;
236
 
237
    lum = dst->data[0];
238
    cb = dst->data[1];
239
    cr = dst->data[2];
240
    p = src->data[0];
241
   
242
    for(y=0;y<height;y+=2) {
243
        for(x=0;x<width;x+=2) {
244
            lum[0] = p[0];
245
            cb[0] = p[1];
246
            lum[1] = p[2];
247
            cr[0] = p[3];
248
            p += 4;
249
            lum += 2;
250
            cb++;
251
            cr++;
252
        }
253
        for(x=0;x<width;x+=2) {
254
            lum[0] = p[0];
255
            lum[1] = p[2];
256
            p += 4;
257
            lum += 2;
258
        }
259
    }
260
}
261

    
262
#define SCALEBITS 8
263
#define ONE_HALF  (1 << (SCALEBITS - 1))
264
#define FIX(x)                ((int) ((x) * (1L<<SCALEBITS) + 0.5))
265

    
266
/* XXX: use generic filter ? */
267
/* 1x2 -> 1x1 */
268
static void shrink2(uint8_t *dst, int dst_wrap, 
269
                    uint8_t *src, int src_wrap,
270
                    int width, int height)
271
{
272
    int w;
273
    uint8_t *s1, *s2, *d;
274

    
275
    for(;height > 0; height--) {
276
        s1 = src;
277
        s2 = s1 + src_wrap;
278
        d = dst;
279
        for(w = width;w >= 4; w-=4) {
280
            d[0] = (s1[0] + s2[0]) >> 1;
281
            d[1] = (s1[1] + s2[1]) >> 1;
282
            d[2] = (s1[2] + s2[2]) >> 1;
283
            d[3] = (s1[3] + s2[3]) >> 1;
284
            s1 += 4;
285
            s2 += 4;
286
            d += 4;
287
        }
288
        for(;w > 0; w--) {
289
            d[0] = (s1[0] + s2[0]) >> 1;
290
            s1++;
291
            s2++;
292
            d++;
293
        }
294
        src += 2 * src_wrap;
295
        dst += dst_wrap;
296
    }
297
}
298

    
299
/* 2x2 -> 1x1 */
300
static void shrink22(uint8_t *dst, int dst_wrap, 
301
                     uint8_t *src, int src_wrap,
302
                     int width, int height)
303
{
304
    int w;
305
    uint8_t *s1, *s2, *d;
306

    
307
    for(;height > 0; height--) {
308
        s1 = src;
309
        s2 = s1 + src_wrap;
310
        d = dst;
311
        for(w = width;w >= 4; w-=4) {
312
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
313
            d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
314
            d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
315
            d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
316
            s1 += 8;
317
            s2 += 8;
318
            d += 4;
319
        }
320
        for(;w > 0; w--) {
321
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
322
            s1 += 2;
323
            s2 += 2;
324
            d++;
325
        }
326
        src += 2 * src_wrap;
327
        dst += dst_wrap;
328
    }
329
}
330

    
331
/* 1x1 -> 2x2 */
332
static void grow22(uint8_t *dst, int dst_wrap,
333
                     uint8_t *src, int src_wrap,
334
                     int width, int height)
335
{
336
    int w;
337
    uint8_t *s1, *d;
338

    
339
    for(;height > 0; height--) {
340
        s1 = src;
341
        d = dst;
342
        for(w = width;w >= 4; w-=4) {
343
            d[1] = d[0] = s1[0];
344
            d[3] = d[2] = s1[1];
345
            s1 += 2;
346
            d += 4;
347
        }
348
        for(;w > 0; w--) {
349
            d[0] = s1[0];
350
            s1 ++;
351
            d++;
352
        }
353
        if (height%2)
354
            src += src_wrap;
355
        dst += dst_wrap;
356
    }
357
}
358

    
359
/* 1x2 -> 2x1 */
360
static void conv411(uint8_t *dst, int dst_wrap, 
361
                    uint8_t *src, int src_wrap,
362
                    int width, int height)
363
{
364
    int w, c;
365
    uint8_t *s1, *s2, *d;
366

    
367
    width>>=1;
368

    
369
    for(;height > 0; height--) {
370
        s1 = src;
371
        s2 = src + src_wrap;
372
        d = dst;
373
        for(w = width;w > 0; w--) {
374
            c = (s1[0] + s2[0]) >> 1;
375
            d[0] = c;
376
            d[1] = c;
377
            s1++;
378
            s2++;
379
            d += 2;
380
        }
381
        src += src_wrap * 2;
382
        dst += dst_wrap;
383
    }
384
}
385

    
386
static void img_copy(uint8_t *dst, int dst_wrap, 
387
                     uint8_t *src, int src_wrap,
388
                     int width, int height)
389
{
390
    for(;height > 0; height--) {
391
        memcpy(dst, src, width);
392
        dst += dst_wrap;
393
        src += src_wrap;
394
    }
395
}
396

    
397
#define SCALE_BITS 10
398

    
399
#define C_Y  (76309 >> (16 - SCALE_BITS))
400
#define C_RV (117504 >> (16 - SCALE_BITS))
401
#define C_BU (138453 >> (16 - SCALE_BITS))
402
#define C_GU (13954 >> (16 - SCALE_BITS))
403
#define C_GV (34903 >> (16 - SCALE_BITS))
404

    
405
#define YUV_TO_RGB2(r, g, b, y1)\
406
{\
407
    y = (y1 - 16) * C_Y;\
408
    r = cm[(y + r_add) >> SCALE_BITS];\
409
    g = cm[(y + g_add) >> SCALE_BITS];\
410
    b = cm[(y + b_add) >> SCALE_BITS];\
411
}
412

    
413
/* XXX: no chroma interpolating is done */
414
#define RGB_FUNCTIONS(rgb_name)                                         \
415
                                                                        \
416
static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
417
                                     int width, int height)             \
418
{                                                                       \
419
    uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;             \
420
    int w, y, cb, cr, r_add, g_add, b_add, width2;                      \
421
    uint8_t *cm = cropTbl + MAX_NEG_CROP;                                 \
422
    unsigned int r, g, b;                                               \
423
                                                                        \
424
    d = dst->data[0];                                                   \
425
    y1_ptr = src->data[0];                                              \
426
    cb_ptr = src->data[1];                                              \
427
    cr_ptr = src->data[2];                                              \
428
    width2 = (width + 1) >> 1;                                          \
429
    for(;height >= 2; height -= 2) {                                    \
430
        d1 = d;                                                         \
431
        d2 = d + dst->linesize[0];                                      \
432
        y2_ptr = y1_ptr + src->linesize[0];                             \
433
        for(w = width; w >= 2; w -= 2) {                                \
434
            cb = cb_ptr[0] - 128;                                       \
435
            cr = cr_ptr[0] - 128;                                       \
436
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
437
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
438
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
439
                                                                        \
440
            /* output 4 pixels */                                       \
441
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
442
            RGB_OUT(d1, r, g, b);                                       \
443
                                                                        \
444
            YUV_TO_RGB2(r, g, b, y1_ptr[1]);                            \
445
            RGB_OUT(d1 + BPP, r, g, b);                                 \
446
                                                                        \
447
            YUV_TO_RGB2(r, g, b, y2_ptr[0]);                            \
448
            RGB_OUT(d2, r, g, b);                                       \
449
                                                                        \
450
            YUV_TO_RGB2(r, g, b, y2_ptr[1]);                            \
451
            RGB_OUT(d2 + BPP, r, g, b);                                 \
452
                                                                        \
453
            d1 += 2 * BPP;                                              \
454
            d2 += 2 * BPP;                                              \
455
                                                                        \
456
            y1_ptr += 2;                                                \
457
            y2_ptr += 2;                                                \
458
            cb_ptr++;                                                   \
459
            cr_ptr++;                                                   \
460
        }                                                               \
461
        /* handle odd width */                                          \
462
        if (w) {                                                        \
463
            cb = cb_ptr[0] - 128;                                       \
464
            cr = cr_ptr[0] - 128;                                       \
465
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
466
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
467
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
468
                                                                        \
469
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
470
            RGB_OUT(d1, r, g, b);                                       \
471
                                                                        \
472
            YUV_TO_RGB2(r, g, b, y2_ptr[0]);                            \
473
            RGB_OUT(d2, r, g, b);                                       \
474
            d1 += BPP;                                                  \
475
            d2 += BPP;                                                  \
476
            y1_ptr++;                                                   \
477
            y2_ptr++;                                                   \
478
            cb_ptr++;                                                   \
479
            cr_ptr++;                                                   \
480
        }                                                               \
481
        d += 2 * dst->linesize[0];                                      \
482
        y1_ptr += 2 * src->linesize[0] - width;                         \
483
        cb_ptr += src->linesize[1] - width2;                            \
484
        cr_ptr += src->linesize[2] - width2;                            \
485
    }                                                                   \
486
    /* handle odd height */                                             \
487
    if (height) {                                                       \
488
        d1 = d;                                                         \
489
        for(w = width; w >= 2; w -= 2) {                                \
490
            cb = cb_ptr[0] - 128;                                       \
491
            cr = cr_ptr[0] - 128;                                       \
492
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
493
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
494
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
495
                                                                        \
496
            /* output 2 pixels */                                       \
497
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
498
            RGB_OUT(d1, r, g, b);                                       \
499
                                                                        \
500
            YUV_TO_RGB2(r, g, b, y1_ptr[1]);                            \
501
            RGB_OUT(d1 + BPP, r, g, b);                                 \
502
                                                                        \
503
            d1 += 2 * BPP;                                              \
504
                                                                        \
505
            y1_ptr += 2;                                                \
506
            cb_ptr++;                                                   \
507
            cr_ptr++;                                                   \
508
        }                                                               \
509
        /* handle width */                                              \
510
        if (w) {                                                        \
511
            cb = cb_ptr[0] - 128;                                       \
512
            cr = cr_ptr[0] - 128;                                       \
513
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
514
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
515
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
516
                                                                        \
517
            /* output 2 pixels */                                       \
518
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
519
            RGB_OUT(d1, r, g, b);                                       \
520
            d1 += BPP;                                                  \
521
                                                                        \
522
            y1_ptr++;                                                   \
523
            cb_ptr++;                                                   \
524
            cr_ptr++;                                                   \
525
        }                                                               \
526
    }                                                                   \
527
}                                                                       \
528
                                                                        \
529
/* XXX: no chroma interpolating is done */                              \
530
static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
531
                                    int width, int height)              \
532
{                                                                       \
533
    uint8_t *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;                           \
534
    int w, y, cb, cr, r_add, g_add, b_add, width2;                      \
535
    uint8_t *cm = cropTbl + MAX_NEG_CROP;                                 \
536
    unsigned int r, g, b;                                               \
537
                                                                        \
538
    d = dst->data[0];                                                   \
539
    y1_ptr = src->data[0];                                              \
540
    cb_ptr = src->data[1];                                              \
541
    cr_ptr = src->data[2];                                              \
542
    width2 = (width + 1) >> 1;                                          \
543
    for(;height > 0; height --) {                                       \
544
        d1 = d;                                                         \
545
        for(w = width; w >= 2; w -= 2) {                                \
546
            cb = cb_ptr[0] - 128;                                       \
547
            cr = cr_ptr[0] - 128;                                       \
548
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
549
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
550
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
551
                                                                        \
552
            /* output 2 pixels */                                       \
553
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
554
            RGB_OUT(d1, r, g, b);                                       \
555
                                                                        \
556
            YUV_TO_RGB2(r, g, b, y1_ptr[1]);                            \
557
            RGB_OUT(d1 + BPP, r, g, b);                                 \
558
                                                                        \
559
            d1 += 2 * BPP;                                              \
560
                                                                        \
561
            y1_ptr += 2;                                                \
562
            cb_ptr++;                                                   \
563
            cr_ptr++;                                                   \
564
        }                                                               \
565
        /* handle width */                                              \
566
        if (w) {                                                        \
567
            cb = cb_ptr[0] - 128;                                       \
568
            cr = cr_ptr[0] - 128;                                       \
569
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
570
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
571
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
572
                                                                        \
573
            /* output 2 pixels */                                       \
574
            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
575
            RGB_OUT(d1, r, g, b);                                       \
576
            d1 += BPP;                                                  \
577
                                                                        \
578
            y1_ptr++;                                                   \
579
            cb_ptr++;                                                   \
580
            cr_ptr++;                                                   \
581
        }                                                               \
582
        d += dst->linesize[0];                                          \
583
        y1_ptr += src->linesize[0] - width;                             \
584
        cb_ptr += src->linesize[1] - width2;                            \
585
        cr_ptr += src->linesize[2] - width2;                            \
586
    }                                                                   \
587
}                                                                       \
588
                                                                        \
589
static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src,     \
590
                                    int width, int height)              \
591
{                                                                       \
592
    int wrap, wrap3, x, y;                                              \
593
    int r, g, b, r1, g1, b1;                                            \
594
    uint8_t *lum, *cb, *cr;                                               \
595
    const uint8_t *p;                                                     \
596
                                                                        \
597
    lum = dst->data[0];                                                 \
598
    cb = dst->data[1];                                                  \
599
    cr = dst->data[2];                                                  \
600
                                                                        \
601
    wrap = dst->linesize[0];                                            \
602
    wrap3 = src->linesize[0];                                           \
603
    p = src->data[0];                                                   \
604
    for(y=0;y<height;y+=2) {                                            \
605
        for(x=0;x<width;x+=2) {                                         \
606
            RGB_IN(r, g, b, p);                                         \
607
            r1 = r;                                                     \
608
            g1 = g;                                                     \
609
            b1 = b;                                                     \
610
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +             \
611
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;        \
612
            RGB_IN(r, g, b, p + BPP);                                   \
613
            r1 += r;                                                    \
614
            g1 += g;                                                    \
615
            b1 += b;                                                    \
616
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +             \
617
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;        \
618
            p += wrap3;                                                 \
619
            lum += wrap;                                                \
620
                                                                        \
621
            RGB_IN(r, g, b, p);                                         \
622
            r1 += r;                                                    \
623
            g1 += g;                                                    \
624
            b1 += b;                                                    \
625
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +             \
626
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;        \
627
                                                                        \
628
            RGB_IN(r, g, b, p + BPP);                                   \
629
            r1 += r;                                                    \
630
            g1 += g;                                                    \
631
            b1 += b;                                                    \
632
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +             \
633
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;        \
634
                                                                        \
635
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +         \
636
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >>          \
637
                     (SCALEBITS + 2)) + 128;                            \
638
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -           \
639
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >>           \
640
                     (SCALEBITS + 2)) + 128;                            \
641
                                                                        \
642
            cb++;                                                       \
643
            cr++;                                                       \
644
            p += -wrap3 + 2 * BPP;                                      \
645
            lum += -wrap + 2;                                           \
646
        }                                                               \
647
        p += wrap3 + (wrap3 - width * BPP);                             \
648
        lum += wrap + (wrap - width);                                   \
649
        cb += dst->linesize[1] - width / 2;                             \
650
        cr += dst->linesize[2] - width / 2;                             \
651
    }                                                                   \
652
}                                                                       \
653
                                                                        \
654
static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src,        \
655
                                 int width, int height)                 \
656
{                                                                       \
657
    const unsigned char *p;                                             \
658
    unsigned char *q;                                                   \
659
    int r, g, b, dst_wrap, src_wrap;                                    \
660
    int x, y;                                                           \
661
                                                                        \
662
    p = src->data[0];                                                   \
663
    src_wrap = src->linesize[0] - BPP * width;                          \
664
                                                                        \
665
    q = dst->data[0];                                                   \
666
    dst_wrap = dst->linesize[0] - width;                                \
667
                                                                        \
668
    for(y=0;y<height;y++) {                                             \
669
        for(x=0;x<width;x++) {                                          \
670
            RGB_IN(r, g, b, p);                                         \
671
            q[0] = (FIX(0.29900) * r + FIX(0.58700) * g +               \
672
                    FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;          \
673
            q++;                                                        \
674
            p += BPP;                                                   \
675
        }                                                               \
676
        p += src_wrap;                                                  \
677
        q += dst_wrap;                                                  \
678
    }                                                                   \
679
}                                                                       \
680
                                                                        \
681
static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src,        \
682
                                 int width, int height)                 \
683
{                                                                       \
684
    const unsigned char *p;                                             \
685
    unsigned char *q;                                                   \
686
    int r, dst_wrap, src_wrap;                                          \
687
    int x, y;                                                           \
688
                                                                        \
689
    p = src->data[0];                                                   \
690
    src_wrap = src->linesize[0] - width;                                \
691
                                                                        \
692
    q = dst->data[0];                                                   \
693
    dst_wrap = dst->linesize[0] - BPP * width;                          \
694
                                                                        \
695
    for(y=0;y<height;y++) {                                             \
696
        for(x=0;x<width;x++) {                                          \
697
            r = p[0];                                                   \
698
            RGB_OUT(q, r, r, r);                                        \
699
            q += BPP;                                                   \
700
            p ++;                                                       \
701
        }                                                               \
702
        p += src_wrap;                                                  \
703
        q += dst_wrap;                                                  \
704
    }                                                                   \
705
}                                                                       \
706
                                                                        \
707
static void pal8_to_ ## rgb_name(AVPicture *dst, AVPicture *src,        \
708
                                 int width, int height)                 \
709
{                                                                       \
710
    const unsigned char *p;                                             \
711
    unsigned char *q;                                                   \
712
    int r, g, b, dst_wrap, src_wrap;                                    \
713
    int x, y;                                                           \
714
    uint32_t v;\
715
    const uint32_t *palette;\
716
\
717
    p = src->data[0];                                                   \
718
    src_wrap = src->linesize[0] - width;                                \
719
    palette = (uint32_t *)src->data[1];\
720
                                                                        \
721
    q = dst->data[0];                                                   \
722
    dst_wrap = dst->linesize[0] - BPP * width;                          \
723
                                                                        \
724
    for(y=0;y<height;y++) {                                             \
725
        for(x=0;x<width;x++) {                                          \
726
            v = palette[p[0]];\
727
            r = (v >> 16) & 0xff;\
728
            g = (v >> 8) & 0xff;\
729
            b = (v) & 0xff;\
730
            RGB_OUT(q, r, g, b);                                        \
731
            q += BPP;                                                   \
732
            p ++;                                                       \
733
        }                                                               \
734
        p += src_wrap;                                                  \
735
        q += dst_wrap;                                                  \
736
    }                                                                   \
737
}
738

    
739
/* copy bit n to bits 0 ... n - 1 */
740
static inline unsigned int bitcopy_n(unsigned int a, int n)
741
{
742
    int mask;
743
    mask = (1 << n) - 1;
744
    return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
745
}
746

    
747
/* rgb555 handling */
748

    
749
#define RGB_IN(r, g, b, s)\
750
{\
751
    unsigned int v = ((const uint16_t *)(s))[0];\
752
    r = bitcopy_n(v >> (10 - 3), 3);\
753
    g = bitcopy_n(v >> (5 - 3), 3);\
754
    b = bitcopy_n(v << 3, 3);\
755
}
756

    
757
#define RGB_OUT(d, r, g, b)\
758
{\
759
    ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
760
}
761

    
762
#define BPP 2
763

    
764
RGB_FUNCTIONS(rgb555)
765

    
766
#undef RGB_IN
767
#undef RGB_OUT
768
#undef BPP
769

    
770
/* rgb565 handling */
771

    
772
#define RGB_IN(r, g, b, s)\
773
{\
774
    unsigned int v = ((const uint16_t *)(s))[0];\
775
    r = bitcopy_n(v >> (11 - 3), 3);\
776
    g = bitcopy_n(v >> (5 - 2), 2);\
777
    b = bitcopy_n(v << 3, 3);\
778
}
779

    
780
#define RGB_OUT(d, r, g, b)\
781
{\
782
    ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
783
}
784

    
785
#define BPP 2
786

    
787
RGB_FUNCTIONS(rgb565)
788

    
789
#undef RGB_IN
790
#undef RGB_OUT
791
#undef BPP
792

    
793
/* bgr24 handling */
794

    
795
#define RGB_IN(r, g, b, s)\
796
{\
797
    b = (s)[0];\
798
    g = (s)[1];\
799
    r = (s)[2];\
800
}
801

    
802
#define RGB_OUT(d, r, g, b)\
803
{\
804
    (d)[0] = b;\
805
    (d)[1] = g;\
806
    (d)[2] = r;\
807
}
808

    
809
#define BPP 3
810

    
811
RGB_FUNCTIONS(bgr24)
812

    
813
#undef RGB_IN
814
#undef RGB_OUT
815
#undef BPP
816

    
817
/* rgb24 handling */
818

    
819
#define RGB_IN(r, g, b, s)\
820
{\
821
    r = (s)[0];\
822
    g = (s)[1];\
823
    b = (s)[2];\
824
}
825

    
826
#define RGB_OUT(d, r, g, b)\
827
{\
828
    (d)[0] = r;\
829
    (d)[1] = g;\
830
    (d)[2] = b;\
831
}
832

    
833
#define BPP 3
834

    
835
RGB_FUNCTIONS(rgb24)
836

    
837
#undef RGB_IN
838
#undef RGB_OUT
839
#undef BPP
840

    
841
/* rgba32 handling */
842

    
843
#define RGB_IN(r, g, b, s)\
844
{\
845
    unsigned int v = ((const uint32_t *)(s))[0];\
846
    r = (v >> 16) & 0xff;\
847
    g = (v >> 8) & 0xff;\
848
    b = v & 0xff;\
849
}
850

    
851
#define RGB_OUT(d, r, g, b)\
852
{\
853
    ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
854
}
855

    
856
#define BPP 4
857

    
858
RGB_FUNCTIONS(rgba32)
859

    
860
#undef RGB_IN
861
#undef RGB_OUT
862
#undef BPP
863

    
864

    
865
static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
866
                            int width, int height)
867
{
868
    const unsigned char *p;
869
    unsigned char *q;
870
    int r, g, b, dst_wrap, src_wrap;
871
    int x, y;
872

    
873
    p = src->data[0];
874
    src_wrap = src->linesize[0] - 3 * width;
875

    
876
    q = dst->data[0];
877
    dst_wrap = dst->linesize[0] - 2 * width;
878

    
879
    for(y=0;y<height;y++) {
880
        for(x=0;x<width;x++) {
881
            r = p[0];
882
            g = p[1];
883
            b = p[2];
884

    
885
            ((unsigned short *)q)[0] = 
886
                ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
887
            q += 2;
888
            p += 3;
889
        }
890
        p += src_wrap;
891
        q += dst_wrap;
892
    }
893
}
894

    
895
/* NOTE: we also add a dummy alpha bit */
896
static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
897
                            int width, int height)
898
{
899
    const unsigned char *p;
900
    unsigned char *q;
901
    int r, g, b, dst_wrap, src_wrap;
902
    int x, y;
903

    
904
    p = src->data[0];
905
    src_wrap = src->linesize[0] - 3 * width;
906

    
907
    q = dst->data[0];
908
    dst_wrap = dst->linesize[0] - 2 * width;
909

    
910
    for(y=0;y<height;y++) {
911
        for(x=0;x<width;x++) {
912
            r = p[0];
913
            g = p[1];
914
            b = p[2];
915

    
916
            ((unsigned short *)q)[0] = 
917
                ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
918
            q += 2;
919
            p += 3;
920
        }
921
        p += src_wrap;
922
        q += dst_wrap;
923
    }
924
}
925

    
926
static void mono_to_gray(AVPicture *dst, AVPicture *src,
927
                         int width, int height, int xor_mask)
928
{
929
    const unsigned char *p;
930
    unsigned char *q;
931
    int v, dst_wrap, src_wrap;
932
    int y, w;
933

    
934
    p = src->data[0];
935
    src_wrap = src->linesize[0] - ((width + 7) >> 3);
936

    
937
    q = dst->data[0];
938
    dst_wrap = dst->linesize[0] - width;
939
    for(y=0;y<height;y++) {
940
        w = width; 
941
        while (w >= 8) {
942
            v = *p++ ^ xor_mask;
943
            q[0] = -(v >> 7);
944
            q[1] = -((v >> 6) & 1);
945
            q[2] = -((v >> 5) & 1);
946
            q[3] = -((v >> 4) & 1);
947
            q[4] = -((v >> 3) & 1);
948
            q[5] = -((v >> 2) & 1);
949
            q[6] = -((v >> 1) & 1);
950
            q[7] = -((v >> 0) & 1);
951
            w -= 8;
952
            q += 8;
953
        }
954
        if (w > 0) {
955
            v = *p++ ^ xor_mask;
956
            do {
957
                q[0] = -((v >> 7) & 1);
958
                q++;
959
                v <<= 1;
960
            } while (--w);
961
        }
962
        p += src_wrap;
963
        q += dst_wrap;
964
    }
965
}
966

    
967
static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
968
                               int width, int height)
969
{
970
    mono_to_gray(dst, src, width, height, 0xff);
971
}
972

    
973
static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
974
                               int width, int height)
975
{
976
    mono_to_gray(dst, src, width, height, 0x00);
977
}
978

    
979
static void gray_to_mono(AVPicture *dst, AVPicture *src,
980
                         int width, int height, int xor_mask)
981
{
982
    int n;
983
    const uint8_t *s;
984
    uint8_t *d;
985
    int j, b, v, n1, src_wrap, dst_wrap, y;
986

    
987
    s = src->data[0];
988
    src_wrap = src->linesize[0] - width;
989

    
990
    d = dst->data[0];
991
    dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
992

    
993
    for(y=0;y<height;y++) {
994
        n = width;
995
        while (n >= 8) {
996
            v = 0;
997
            for(j=0;j<8;j++) {
998
                b = s[0];
999
                s++;
1000
                v = (v << 1) | (b >> 7);
1001
            }
1002
            d[0] = v ^ xor_mask;
1003
            d++;
1004
            n -= 8;
1005
        }
1006
        if (n > 0) {
1007
            n1 = n;
1008
            v = 0;
1009
            while (n > 0) {
1010
                b = s[0];
1011
                s++;
1012
                v = (v << 1) | (b >> 7);
1013
                n--;
1014
            }
1015
            d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
1016
            d++;
1017
        }
1018
        s += src_wrap;
1019
        d += dst_wrap;
1020
    }
1021
}
1022

    
1023
static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
1024
                              int width, int height)
1025
{
1026
    gray_to_mono(dst, src, width, height, 0xff);
1027
}
1028

    
1029
static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
1030
                              int width, int height)
1031
{
1032
    gray_to_mono(dst, src, width, height, 0x00);
1033
}
1034

    
1035
/* this is maybe slow, but allows for extensions */
1036
static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
1037
{
1038
    return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
1039
}
1040

    
1041
/* XXX: put jpeg quantize code instead */
1042
static void rgb24_to_pal8(AVPicture *dst, AVPicture *src,
1043
                          int width, int height)
1044
{
1045
    const unsigned char *p;
1046
    unsigned char *q;
1047
    int r, g, b, dst_wrap, src_wrap;
1048
    int x, y, i;
1049
    static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
1050
    uint32_t *pal;
1051

    
1052
    p = src->data[0];
1053
    src_wrap = src->linesize[0] - 3 * width;
1054

    
1055
    q = dst->data[0];
1056
    dst_wrap = dst->linesize[0] - width;
1057

    
1058
    for(y=0;y<height;y++) {
1059
        for(x=0;x<width;x++) {
1060
            r = p[0];
1061
            g = p[1];
1062
            b = p[2];
1063

    
1064
            q[0] = gif_clut_index(r, g, b);
1065
            q++;
1066
            p += 3;
1067
        }
1068
        p += src_wrap;
1069
        q += dst_wrap;
1070
    }
1071

    
1072
    /* build palette */
1073
    pal = (uint32_t *)dst->data[1];
1074
    i = 0;
1075
    for(r = 0; r < 6; r++) {
1076
        for(g = 0; g < 6; g++) {
1077
            for(b = 0; b < 6; b++) {
1078
                pal[i++] = (0xff << 24) | (pal_value[r] << 16) | 
1079
                    (pal_value[g] << 8) | pal_value[b];
1080
            }
1081
        }
1082
    }
1083
    while (i < 256)
1084
        pal[i++] = 0;
1085
}
1086
        
1087
static void rgba32_to_rgb24(AVPicture *dst, AVPicture *src,
1088
                            int width, int height)
1089
{
1090
    const uint8_t *s;
1091
    uint8_t *d;
1092
    int src_wrap, dst_wrap, j, y;
1093
    unsigned int v;
1094

    
1095
    s = src->data[0];
1096
    src_wrap = src->linesize[0] - width * 4;
1097

    
1098
    d = dst->data[0];
1099
    dst_wrap = dst->linesize[0] - width * 3;
1100

    
1101
    for(y=0;y<height;y++) {
1102
        for(j = 0;j < width; j++) {
1103
            v = *(uint32_t *)s;
1104
            s += 4;
1105
            d[0] = v >> 16;
1106
            d[1] = v >> 8;
1107
            d[2] = v;
1108
            d += 3;
1109
        }
1110
        s += src_wrap;
1111
        d += dst_wrap;
1112
    }
1113
}
1114

    
1115
typedef struct ConvertEntry {
1116
    void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
1117
} ConvertEntry;
1118

    
1119
/* add each new convertion function in this table */
1120
/* constraints;
1121
   - all non YUV modes must convert at least to and from PIX_FMT_RGB24
1122
*/
1123
static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1124
    [PIX_FMT_YUV420P] = {
1125
        [PIX_FMT_RGB555] = { 
1126
            .convert = yuv420p_to_rgb555
1127
        },
1128
        [PIX_FMT_RGB565] = { 
1129
            .convert = yuv420p_to_rgb565
1130
        },
1131
        [PIX_FMT_BGR24] = { 
1132
            .convert = yuv420p_to_bgr24
1133
        },
1134
        [PIX_FMT_RGB24] = { 
1135
            .convert = yuv420p_to_rgb24
1136
        },
1137
        [PIX_FMT_RGBA32] = { 
1138
            .convert = yuv420p_to_rgba32
1139
        },
1140
    },
1141
    [PIX_FMT_YUV422P] = {
1142
        [PIX_FMT_RGB555] = { 
1143
            .convert = yuv422p_to_rgb555
1144
        },
1145
        [PIX_FMT_RGB565] = { 
1146
            .convert = yuv422p_to_rgb565
1147
        },
1148
        [PIX_FMT_BGR24] = { 
1149
            .convert = yuv422p_to_bgr24
1150
        },
1151
        [PIX_FMT_RGB24] = { 
1152
            .convert = yuv422p_to_rgb24
1153
        },
1154
        [PIX_FMT_RGBA32] = { 
1155
            .convert = yuv422p_to_rgba32
1156
        },
1157
    },
1158
    [PIX_FMT_YUV422] = { 
1159
        [PIX_FMT_YUV420P] = { 
1160
            .convert = yuv422_to_yuv420p,
1161
        },
1162
    },
1163

    
1164
    [PIX_FMT_RGB24] = {
1165
        [PIX_FMT_YUV420P] = { 
1166
            .convert = rgb24_to_yuv420p
1167
        },
1168
        [PIX_FMT_RGB565] = { 
1169
            .convert = rgb24_to_rgb565
1170
        },
1171
        [PIX_FMT_RGB555] = { 
1172
            .convert = rgb24_to_rgb555
1173
        },
1174
        [PIX_FMT_GRAY8] = { 
1175
            .convert = rgb24_to_gray
1176
        },
1177
        [PIX_FMT_PAL8] = { 
1178
            .convert = rgb24_to_pal8
1179
        },
1180
    },
1181
    [PIX_FMT_RGBA32] = {
1182
        [PIX_FMT_YUV420P] = { 
1183
            .convert = rgba32_to_yuv420p
1184
        },
1185
        [PIX_FMT_GRAY8] = { 
1186
            .convert = rgba32_to_gray
1187
        },
1188
        [PIX_FMT_RGB24] = { 
1189
            .convert = rgba32_to_rgb24
1190
        },
1191
    },
1192
    [PIX_FMT_BGR24] = {
1193
        [PIX_FMT_YUV420P] = { 
1194
            .convert = bgr24_to_yuv420p
1195
        },
1196
        [PIX_FMT_GRAY8] = { 
1197
            .convert = bgr24_to_gray
1198
        },
1199
    },
1200
    [PIX_FMT_RGB555] = {
1201
        [PIX_FMT_YUV420P] = { 
1202
            .convert = rgb555_to_yuv420p
1203
        },
1204
        [PIX_FMT_GRAY8] = { 
1205
            .convert = rgb555_to_gray
1206
        },
1207
    },
1208
    [PIX_FMT_RGB565] = {
1209
        [PIX_FMT_YUV420P] = { 
1210
            .convert = rgb565_to_yuv420p
1211
        },
1212
        [PIX_FMT_GRAY8] = { 
1213
            .convert = rgb565_to_gray
1214
        },
1215
    },
1216
    [PIX_FMT_GRAY8] = {
1217
        [PIX_FMT_RGB555] = { 
1218
            .convert = gray_to_rgb555
1219
        },
1220
        [PIX_FMT_RGB565] = { 
1221
            .convert = gray_to_rgb565
1222
        },
1223
        [PIX_FMT_RGB24] = { 
1224
            .convert = gray_to_rgb24
1225
        },
1226
        [PIX_FMT_BGR24] = { 
1227
            .convert = gray_to_bgr24
1228
        },
1229
        [PIX_FMT_RGBA32] = { 
1230
            .convert = gray_to_rgba32
1231
        },
1232
        [PIX_FMT_MONOWHITE] = { 
1233
            .convert = gray_to_monowhite
1234
        },
1235
        [PIX_FMT_MONOBLACK] = { 
1236
            .convert = gray_to_monoblack
1237
        },
1238
    },
1239
    [PIX_FMT_MONOWHITE] = {
1240
        [PIX_FMT_GRAY8] = { 
1241
            .convert = monowhite_to_gray
1242
        },
1243
    },
1244
    [PIX_FMT_MONOBLACK] = {
1245
        [PIX_FMT_GRAY8] = { 
1246
            .convert = monoblack_to_gray
1247
        },
1248
    },
1249
    [PIX_FMT_PAL8] = {
1250
        [PIX_FMT_RGB555] = { 
1251
            .convert = pal8_to_rgb555
1252
        },
1253
        [PIX_FMT_RGB565] = { 
1254
            .convert = pal8_to_rgb565
1255
        },
1256
        [PIX_FMT_BGR24] = { 
1257
            .convert = pal8_to_bgr24
1258
        },
1259
        [PIX_FMT_RGB24] = { 
1260
            .convert = pal8_to_rgb24
1261
        },
1262
        [PIX_FMT_RGBA32] = { 
1263
            .convert = pal8_to_rgba32
1264
        },
1265
    },
1266
};
1267

    
1268
static int avpicture_alloc(AVPicture *picture,
1269
                           int pix_fmt, int width, int height)
1270
{
1271
    unsigned int size;
1272
    void *ptr;
1273

    
1274
    size = avpicture_get_size(pix_fmt, width, height);
1275
    if (size < 0)
1276
        goto fail;
1277
    ptr = av_malloc(size);
1278
    if (!ptr)
1279
        goto fail;
1280
    avpicture_fill(picture, ptr, pix_fmt, width, height);
1281
    return 0;
1282
 fail:
1283
    memset(picture, 0, sizeof(AVPicture));
1284
    return -1;
1285
}
1286

    
1287
static void avpicture_free(AVPicture *picture)
1288
{
1289
    av_free(picture->data[0]);
1290
}
1291

    
1292
/* XXX: always use linesize. Return -1 if not supported */
1293
int img_convert(AVPicture *dst, int dst_pix_fmt,
1294
                AVPicture *src, int src_pix_fmt, 
1295
                int src_width, int src_height)
1296
{
1297
    int i, ret, dst_width, dst_height, int_pix_fmt;
1298
    PixFmtInfo *src_pix, *dst_pix;
1299
    ConvertEntry *ce;
1300
    AVPicture tmp1, *tmp = &tmp1;
1301

    
1302
    if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
1303
        dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
1304
        return -1;
1305
    if (src_width <= 0 || src_height <= 0)
1306
        return 0;
1307

    
1308
    dst_width = src_width;
1309
    dst_height = src_height;
1310

    
1311
    dst_pix = &pix_fmt_info[dst_pix_fmt];
1312
    src_pix = &pix_fmt_info[src_pix_fmt];
1313
    if (src_pix_fmt == dst_pix_fmt) {
1314
        /* XXX: incorrect */
1315
        /* same format: just copy */
1316
        for(i = 0; i < dst_pix->nb_components; i++) {
1317
            int w, h;
1318
            w = dst_width;
1319
            h = dst_height;
1320
            if (dst_pix->is_yuv && (i == 1 || i == 2)) {
1321
                w >>= dst_pix->x_chroma_shift;
1322
                h >>= dst_pix->y_chroma_shift;
1323
            }
1324
            img_copy(dst->data[i], dst->linesize[i],
1325
                     src->data[i], src->linesize[i],
1326
                     w, h);
1327
        }
1328
        return 0;
1329
    }
1330

    
1331
    ce = &convert_table[src_pix_fmt][dst_pix_fmt];
1332
    if (ce->convert) {
1333
        /* specific convertion routine */
1334
        ce->convert(dst, src, dst_width, dst_height);
1335
        return 0;
1336
    }
1337

    
1338
    /* gray to YUV */
1339
    if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
1340
        int w, h, y;
1341
        uint8_t *d;
1342

    
1343
        img_copy(dst->data[0], dst->linesize[0],
1344
                 src->data[0], src->linesize[0],
1345
                 dst_width, dst_height);
1346
        /* fill U and V with 128 */
1347
        w = dst_width;
1348
        h = dst_height;
1349
        w >>= dst_pix->x_chroma_shift;
1350
        h >>= dst_pix->y_chroma_shift;
1351
        for(i = 1; i <= 2; i++) {
1352
            d = dst->data[i];
1353
            for(y = 0; y< h; y++) {
1354
                memset(d, 128, w);
1355
                d += dst->linesize[i];
1356
            }
1357
        }
1358
        return 0;
1359
    }
1360

    
1361
    /* YUV to gray */
1362
    if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
1363
        img_copy(dst->data[0], dst->linesize[0],
1364
                 src->data[0], src->linesize[0],
1365
                 dst_width, dst_height);
1366
        return 0;
1367
    }
1368

    
1369
    /* YUV to YUV */
1370
    if (dst_pix->is_yuv && src_pix->is_yuv) {
1371
        int x_shift, y_shift, w, h;
1372
        void (*resize_func)(uint8_t *dst, int dst_wrap, 
1373
                            uint8_t *src, int src_wrap,
1374
                            int width, int height);
1375

    
1376
        /* compute chroma size of the smallest dimensions */
1377
        w = dst_width;
1378
        h = dst_height;
1379
        if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
1380
            w >>= dst_pix->x_chroma_shift;
1381
        else
1382
            w >>= src_pix->x_chroma_shift;
1383
        if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
1384
            h >>= dst_pix->y_chroma_shift;
1385
        else
1386
            h >>= src_pix->y_chroma_shift;
1387

    
1388
        x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
1389
        y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
1390
        if (x_shift == 0 && y_shift == 0) {
1391
            resize_func = img_copy; /* should never happen */
1392
        } else if (x_shift == 0 && y_shift == 1) {
1393
            resize_func = shrink2;
1394
        } else if (x_shift == 1 && y_shift == 1) {
1395
            resize_func = shrink22;
1396
        } else if (x_shift == -1 && y_shift == -1) {
1397
            resize_func = grow22;
1398
        } else if (x_shift == -1 && y_shift == 1) {
1399
            resize_func = conv411;
1400
        } else {
1401
            /* currently not handled */
1402
            return -1;
1403
        }
1404

    
1405
        img_copy(dst->data[0], dst->linesize[0],
1406
                 src->data[0], src->linesize[0],
1407
                 dst_width, dst_height);
1408

    
1409
        for(i = 1;i <= 2; i++)
1410
            resize_func(dst->data[i], dst->linesize[i],
1411
                        src->data[i], src->linesize[i],
1412
                        dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
1413
       return 0;
1414
    }
1415

    
1416
    /* try to use an intermediate format */
1417
    if (src_pix_fmt == PIX_FMT_MONOWHITE ||
1418
        src_pix_fmt == PIX_FMT_MONOBLACK ||
1419
        dst_pix_fmt == PIX_FMT_MONOWHITE ||
1420
        dst_pix_fmt == PIX_FMT_MONOBLACK) {
1421
        int_pix_fmt = PIX_FMT_GRAY8;
1422
    } else {
1423
        int_pix_fmt = PIX_FMT_RGB24;
1424
    }
1425
    if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
1426
        return -1;
1427
    ret = -1;
1428
    if (img_convert(tmp, int_pix_fmt,
1429
                    src, src_pix_fmt, src_width, src_height) < 0)
1430
        goto fail1;
1431
    if (img_convert(dst, dst_pix_fmt,
1432
                    tmp, int_pix_fmt, dst_width, dst_height) < 0)
1433
        goto fail1;
1434
    ret = 0;
1435
 fail1:
1436
    avpicture_free(tmp);
1437
    return ret;
1438
}
1439

    
1440

    
1441
#ifdef HAVE_MMX
1442
#define DEINT_INPLACE_LINE_LUM \
1443
                    movd_m2r(lum_m4[0],mm0);\
1444
                    movd_m2r(lum_m3[0],mm1);\
1445
                    movd_m2r(lum_m2[0],mm2);\
1446
                    movd_m2r(lum_m1[0],mm3);\
1447
                    movd_m2r(lum[0],mm4);\
1448
                    punpcklbw_r2r(mm7,mm0);\
1449
                    movd_r2m(mm2,lum_m4[0]);\
1450
                    punpcklbw_r2r(mm7,mm1);\
1451
                    punpcklbw_r2r(mm7,mm2);\
1452
                    punpcklbw_r2r(mm7,mm3);\
1453
                    punpcklbw_r2r(mm7,mm4);\
1454
                    paddw_r2r(mm3,mm1);\
1455
                    psllw_i2r(1,mm2);\
1456
                    paddw_r2r(mm4,mm0);\
1457
                    psllw_i2r(2,mm1);\
1458
                    paddw_r2r(mm6,mm2);\
1459
                    paddw_r2r(mm2,mm1);\
1460
                    psubusw_r2r(mm0,mm1);\
1461
                    psrlw_i2r(3,mm1);\
1462
                    packuswb_r2r(mm7,mm1);\
1463
                    movd_r2m(mm1,lum_m2[0]);
1464

    
1465
#define DEINT_LINE_LUM \
1466
                    movd_m2r(lum_m4[0],mm0);\
1467
                    movd_m2r(lum_m3[0],mm1);\
1468
                    movd_m2r(lum_m2[0],mm2);\
1469
                    movd_m2r(lum_m1[0],mm3);\
1470
                    movd_m2r(lum[0],mm4);\
1471
                    punpcklbw_r2r(mm7,mm0);\
1472
                    punpcklbw_r2r(mm7,mm1);\
1473
                    punpcklbw_r2r(mm7,mm2);\
1474
                    punpcklbw_r2r(mm7,mm3);\
1475
                    punpcklbw_r2r(mm7,mm4);\
1476
                    paddw_r2r(mm3,mm1);\
1477
                    psllw_i2r(1,mm2);\
1478
                    paddw_r2r(mm4,mm0);\
1479
                    psllw_i2r(2,mm1);\
1480
                    paddw_r2r(mm6,mm2);\
1481
                    paddw_r2r(mm2,mm1);\
1482
                    psubusw_r2r(mm0,mm1);\
1483
                    psrlw_i2r(3,mm1);\
1484
                    packuswb_r2r(mm7,mm1);\
1485
                    movd_r2m(mm1,dst[0]);
1486
#endif
1487

    
1488
/* filter parameters: [-1 4 2 4 -1] // 8 */
1489
static void deinterlace_line(uint8_t *dst, uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
1490
                                int size)
1491
{
1492
#ifndef HAVE_MMX
1493
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
1494
    int sum;
1495

    
1496
    for(;size > 0;size--) {
1497
        sum = -lum_m4[0];
1498
        sum += lum_m3[0] << 2;
1499
        sum += lum_m2[0] << 1;
1500
        sum += lum_m1[0] << 2;
1501
        sum += -lum[0];
1502
        dst[0] = cm[(sum + 4) >> 3];
1503
        lum_m4++;
1504
        lum_m3++;
1505
        lum_m2++;
1506
        lum_m1++;
1507
        lum++;
1508
        dst++;
1509
    }
1510
#else
1511

    
1512
    {
1513
        mmx_t rounder;
1514
        rounder.uw[0]=4;
1515
        rounder.uw[1]=4;
1516
        rounder.uw[2]=4;
1517
        rounder.uw[3]=4;
1518
        pxor_r2r(mm7,mm7);
1519
        movq_m2r(rounder,mm6);
1520
    }
1521
    for (;size > 3; size-=4) {
1522
        DEINT_LINE_LUM
1523
        lum_m4+=4;
1524
        lum_m3+=4;
1525
        lum_m2+=4;
1526
        lum_m1+=4;
1527
        lum+=4;
1528
        dst+=4;
1529
    }
1530
#endif
1531
}
1532
static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
1533
                             int size)
1534
{
1535
#ifndef HAVE_MMX
1536
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
1537
    int sum;
1538

    
1539
    for(;size > 0;size--) {
1540
        sum = -lum_m4[0];
1541
        sum += lum_m3[0] << 2;
1542
        sum += lum_m2[0] << 1;
1543
        lum_m4[0]=lum_m2[0];
1544
        sum += lum_m1[0] << 2;
1545
        sum += -lum[0];
1546
        lum_m2[0] = cm[(sum + 4) >> 3];
1547
        lum_m4++;
1548
        lum_m3++;
1549
        lum_m2++;
1550
        lum_m1++;
1551
        lum++;
1552
    }
1553
#else
1554

    
1555
    {
1556
        mmx_t rounder;
1557
        rounder.uw[0]=4;
1558
        rounder.uw[1]=4;
1559
        rounder.uw[2]=4;
1560
        rounder.uw[3]=4;
1561
        pxor_r2r(mm7,mm7);
1562
        movq_m2r(rounder,mm6);
1563
    }
1564
    for (;size > 3; size-=4) {
1565
        DEINT_INPLACE_LINE_LUM
1566
        lum_m4+=4;
1567
        lum_m3+=4;
1568
        lum_m2+=4;
1569
        lum_m1+=4;
1570
        lum+=4;
1571
    }
1572
#endif
1573
}
1574

    
1575
/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
1576
   top field is copied as is, but the bottom field is deinterlaced
1577
   against the top field. */
1578
static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
1579
                                    uint8_t *src1, int src_wrap,
1580
                                    int width, int height)
1581
{
1582
    uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
1583
    int y;
1584

    
1585
    src_m2 = src1;
1586
    src_m1 = src1;
1587
    src_0=&src_m1[src_wrap];
1588
    src_p1=&src_0[src_wrap];
1589
    src_p2=&src_p1[src_wrap];
1590
    for(y=0;y<(height-2);y+=2) {
1591
        memcpy(dst,src_m1,width);
1592
        dst += dst_wrap;
1593
        deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
1594
        src_m2 = src_0;
1595
        src_m1 = src_p1;
1596
        src_0 = src_p2;
1597
        src_p1 += 2*src_wrap;
1598
        src_p2 += 2*src_wrap;
1599
        dst += dst_wrap;
1600
    }
1601
    memcpy(dst,src_m1,width);
1602
    dst += dst_wrap;
1603
    /* do last line */
1604
    deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
1605
}
1606

    
1607
static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
1608
                                     int width, int height)
1609
{
1610
    uint8_t *src_m1, *src_0, *src_p1, *src_p2;
1611
    int y;
1612
    uint8_t *buf;
1613
    buf = (uint8_t*)av_malloc(width);
1614

    
1615
    src_m1 = src1;
1616
    memcpy(buf,src_m1,width);
1617
    src_0=&src_m1[src_wrap];
1618
    src_p1=&src_0[src_wrap];
1619
    src_p2=&src_p1[src_wrap];
1620
    for(y=0;y<(height-2);y+=2) {
1621
        deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1622
        src_m1 = src_p1;
1623
        src_0 = src_p2;
1624
        src_p1 += 2*src_wrap;
1625
        src_p2 += 2*src_wrap;
1626
    }
1627
    /* do last line */
1628
    deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
1629
    av_free(buf);
1630
}
1631

    
1632

    
1633
/* deinterlace - if not supported return -1 */
1634
int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
1635
                          int pix_fmt, int width, int height)
1636
{
1637
    int i;
1638

    
1639
    if (pix_fmt != PIX_FMT_YUV420P &&
1640
        pix_fmt != PIX_FMT_YUV422P &&
1641
        pix_fmt != PIX_FMT_YUV444P)
1642
        return -1;
1643
    if ((width & 3) != 0 || (height & 3) != 0)
1644
        return -1;
1645

    
1646
    for(i=0;i<3;i++) {
1647
        if (i == 1) {
1648
            switch(pix_fmt) {
1649
            case PIX_FMT_YUV420P:
1650
                width >>= 1;
1651
                height >>= 1;
1652
                break;
1653
            case PIX_FMT_YUV422P:
1654
                width >>= 1;
1655
                break;
1656
            default:
1657
                break;
1658
            }
1659
        }
1660
        if (src == dst) {
1661
            deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
1662
                                 width, height);
1663
        } else {
1664
            deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1665
                                        src->data[i], src->linesize[i],
1666
                                        width, height);
1667
        }
1668
    }
1669
#ifdef HAVE_MMX
1670
    emms();
1671
#endif
1672
    return 0;
1673
}
1674

    
1675
#undef FIX