Statistics
| Branch: | Revision:

ffmpeg / libavcodec / imgconvert.c @ 983e3246

History | View | Annotate | Download (56.7 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
 * @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_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
    for(;height > 0; height--) {
368
        s1 = src;
369
        s2 = src + src_wrap;
370
        d = dst;
371
        for(w = width;w > 0; w--) {
372
            c = (s1[0] + s2[0]) >> 1;
373
            d[0] = c;
374
            d[1] = c;
375
            s1++;
376
            s2++;
377
            d += 2;
378
        }
379
        src += src_wrap * 2;
380
        dst += dst_wrap;
381
    }
382
}
383

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

    
395
#define SCALE_BITS 10
396

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

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

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

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

    
745
/* rgb555 handling */
746

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

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

    
760
#define BPP 2
761

    
762
RGB_FUNCTIONS(rgb555)
763

    
764
#undef RGB_IN
765
#undef RGB_OUT
766
#undef BPP
767

    
768
/* rgb565 handling */
769

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

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

    
783
#define BPP 2
784

    
785
RGB_FUNCTIONS(rgb565)
786

    
787
#undef RGB_IN
788
#undef RGB_OUT
789
#undef BPP
790

    
791
/* bgr24 handling */
792

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

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

    
807
#define BPP 3
808

    
809
RGB_FUNCTIONS(bgr24)
810

    
811
#undef RGB_IN
812
#undef RGB_OUT
813
#undef BPP
814

    
815
/* rgb24 handling */
816

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

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

    
831
#define BPP 3
832

    
833
RGB_FUNCTIONS(rgb24)
834

    
835
#undef RGB_IN
836
#undef RGB_OUT
837
#undef BPP
838

    
839
/* rgba32 handling */
840

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

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

    
854
#define BPP 4
855

    
856
RGB_FUNCTIONS(rgba32)
857

    
858
#undef RGB_IN
859
#undef RGB_OUT
860
#undef BPP
861

    
862

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
985
    s = src->data[0];
986
    src_wrap = src->linesize[0] - width;
987

    
988
    d = dst->data[0];
989
    dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
990
    printf("%d %d\n", width, height);
991

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

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

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

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

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

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

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

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

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

    
1071
    /* build palette */
1072
    pal = (uint32_t *)dst->data[1];
1073
    i = 0;
1074
    for(r = 0; r < 6; r++) {
1075
        for(g = 0; g < 6; g++) {
1076
            for(b = 0; b < 6; b++) {
1077
                pal[i++] = (0xff << 24) | (pal_value[r] << 16) | 
1078
                    (pal_value[g] << 8) | pal_value[b];
1079
            }
1080
        }
1081
    }
1082
    while (i < 256)
1083
        pal[i++] = 0;
1084
}
1085
        
1086
typedef struct ConvertEntry {
1087
    void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
1088
} ConvertEntry;
1089

    
1090
/* add each new convertion function in this table */
1091
/* constraints;
1092
   - all non YUV modes must convert at least to and from PIX_FMT_RGB24
1093
*/
1094
static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1095
    [PIX_FMT_YUV420P] = {
1096
        [PIX_FMT_RGB555] = { 
1097
            .convert = yuv420p_to_rgb555
1098
        },
1099
        [PIX_FMT_RGB565] = { 
1100
            .convert = yuv420p_to_rgb565
1101
        },
1102
        [PIX_FMT_BGR24] = { 
1103
            .convert = yuv420p_to_bgr24
1104
        },
1105
        [PIX_FMT_RGB24] = { 
1106
            .convert = yuv420p_to_rgb24
1107
        },
1108
        [PIX_FMT_RGBA32] = { 
1109
            .convert = yuv420p_to_rgba32
1110
        },
1111
    },
1112
    [PIX_FMT_YUV422P] = {
1113
        [PIX_FMT_RGB555] = { 
1114
            .convert = yuv422p_to_rgb555
1115
        },
1116
        [PIX_FMT_RGB565] = { 
1117
            .convert = yuv422p_to_rgb565
1118
        },
1119
        [PIX_FMT_BGR24] = { 
1120
            .convert = yuv422p_to_bgr24
1121
        },
1122
        [PIX_FMT_RGB24] = { 
1123
            .convert = yuv422p_to_rgb24
1124
        },
1125
        [PIX_FMT_RGBA32] = { 
1126
            .convert = yuv422p_to_rgba32
1127
        },
1128
    },
1129
    [PIX_FMT_YUV422] = { 
1130
        [PIX_FMT_YUV420P] = { 
1131
            .convert = yuv422_to_yuv420p,
1132
        },
1133
    },
1134

    
1135
    [PIX_FMT_RGB24] = {
1136
        [PIX_FMT_YUV420P] = { 
1137
            .convert = rgb24_to_yuv420p
1138
        },
1139
        [PIX_FMT_RGB565] = { 
1140
            .convert = rgb24_to_rgb565
1141
        },
1142
        [PIX_FMT_RGB555] = { 
1143
            .convert = rgb24_to_rgb555
1144
        },
1145
        [PIX_FMT_GRAY8] = { 
1146
            .convert = rgb24_to_gray
1147
        },
1148
        [PIX_FMT_PAL8] = { 
1149
            .convert = rgb24_to_pal8
1150
        },
1151
    },
1152
    [PIX_FMT_RGBA32] = {
1153
        [PIX_FMT_YUV420P] = { 
1154
            .convert = rgba32_to_yuv420p
1155
        },
1156
        [PIX_FMT_GRAY8] = { 
1157
            .convert = rgba32_to_gray
1158
        },
1159
    },
1160
    [PIX_FMT_BGR24] = {
1161
        [PIX_FMT_YUV420P] = { 
1162
            .convert = bgr24_to_yuv420p
1163
        },
1164
        [PIX_FMT_GRAY8] = { 
1165
            .convert = bgr24_to_gray
1166
        },
1167
    },
1168
    [PIX_FMT_RGB555] = {
1169
        [PIX_FMT_YUV420P] = { 
1170
            .convert = rgb555_to_yuv420p
1171
        },
1172
        [PIX_FMT_GRAY8] = { 
1173
            .convert = rgb555_to_gray
1174
        },
1175
    },
1176
    [PIX_FMT_RGB565] = {
1177
        [PIX_FMT_YUV420P] = { 
1178
            .convert = rgb565_to_yuv420p
1179
        },
1180
        [PIX_FMT_GRAY8] = { 
1181
            .convert = rgb565_to_gray
1182
        },
1183
    },
1184
    [PIX_FMT_GRAY8] = {
1185
        [PIX_FMT_RGB555] = { 
1186
            .convert = gray_to_rgb555
1187
        },
1188
        [PIX_FMT_RGB565] = { 
1189
            .convert = gray_to_rgb565
1190
        },
1191
        [PIX_FMT_RGB24] = { 
1192
            .convert = gray_to_rgb24
1193
        },
1194
        [PIX_FMT_BGR24] = { 
1195
            .convert = gray_to_bgr24
1196
        },
1197
        [PIX_FMT_RGBA32] = { 
1198
            .convert = gray_to_rgba32
1199
        },
1200
        [PIX_FMT_MONOWHITE] = { 
1201
            .convert = gray_to_monowhite
1202
        },
1203
        [PIX_FMT_MONOBLACK] = { 
1204
            .convert = gray_to_monoblack
1205
        },
1206
    },
1207
    [PIX_FMT_MONOWHITE] = {
1208
        [PIX_FMT_GRAY8] = { 
1209
            .convert = monowhite_to_gray
1210
        },
1211
    },
1212
    [PIX_FMT_MONOBLACK] = {
1213
        [PIX_FMT_GRAY8] = { 
1214
            .convert = monoblack_to_gray
1215
        },
1216
    },
1217
    [PIX_FMT_PAL8] = {
1218
        [PIX_FMT_RGB555] = { 
1219
            .convert = pal8_to_rgb555
1220
        },
1221
        [PIX_FMT_RGB565] = { 
1222
            .convert = pal8_to_rgb565
1223
        },
1224
        [PIX_FMT_BGR24] = { 
1225
            .convert = pal8_to_bgr24
1226
        },
1227
        [PIX_FMT_RGB24] = { 
1228
            .convert = pal8_to_rgb24
1229
        },
1230
        [PIX_FMT_RGBA32] = { 
1231
            .convert = pal8_to_rgba32
1232
        },
1233
    },
1234
};
1235

    
1236
static int avpicture_alloc(AVPicture *picture,
1237
                           int pix_fmt, int width, int height)
1238
{
1239
    unsigned int size;
1240
    void *ptr;
1241

    
1242
    size = avpicture_get_size(pix_fmt, width, height);
1243
    if (size < 0)
1244
        goto fail;
1245
    ptr = av_malloc(size);
1246
    if (!ptr)
1247
        goto fail;
1248
    avpicture_fill(picture, ptr, pix_fmt, width, height);
1249
    return 0;
1250
 fail:
1251
    memset(picture, 0, sizeof(AVPicture));
1252
    return -1;
1253
}
1254

    
1255
static void avpicture_free(AVPicture *picture)
1256
{
1257
    av_free(picture->data[0]);
1258
}
1259

    
1260
/* XXX: always use linesize. Return -1 if not supported */
1261
int img_convert(AVPicture *dst, int dst_pix_fmt,
1262
                AVPicture *src, int src_pix_fmt, 
1263
                int src_width, int src_height)
1264
{
1265
    int i, ret, dst_width, dst_height, int_pix_fmt;
1266
    PixFmtInfo *src_pix, *dst_pix;
1267
    ConvertEntry *ce;
1268
    AVPicture tmp1, *tmp = &tmp1;
1269

    
1270
    if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
1271
        dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
1272
        return -1;
1273
    if (src_width <= 0 || src_height <= 0)
1274
        return 0;
1275

    
1276
    dst_width = src_width;
1277
    dst_height = src_height;
1278

    
1279
    dst_pix = &pix_fmt_info[dst_pix_fmt];
1280
    src_pix = &pix_fmt_info[src_pix_fmt];
1281
    if (src_pix_fmt == dst_pix_fmt) {
1282
        /* XXX: incorrect */
1283
        /* same format: just copy */
1284
        for(i = 0; i < dst_pix->nb_components; i++) {
1285
            int w, h;
1286
            w = dst_width;
1287
            h = dst_height;
1288
            if (dst_pix->is_yuv && (i == 1 || i == 2)) {
1289
                w >>= dst_pix->x_chroma_shift;
1290
                h >>= dst_pix->y_chroma_shift;
1291
            }
1292
            img_copy(dst->data[i], dst->linesize[i],
1293
                     src->data[i], src->linesize[i],
1294
                     w, h);
1295
        }
1296
        return 0;
1297
    }
1298

    
1299
    ce = &convert_table[src_pix_fmt][dst_pix_fmt];
1300
    if (ce->convert) {
1301
        /* specific convertion routine */
1302
        ce->convert(dst, src, dst_width, dst_height);
1303
        return 0;
1304
    }
1305

    
1306
    /* gray to YUV */
1307
    if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
1308
        int w, h, y;
1309
        uint8_t *d;
1310

    
1311
        img_copy(dst->data[0], dst->linesize[0],
1312
                 src->data[0], src->linesize[0],
1313
                 dst_width, dst_height);
1314
        /* fill U and V with 128 */
1315
        w = dst_width;
1316
        h = dst_height;
1317
        w >>= dst_pix->x_chroma_shift;
1318
        h >>= dst_pix->y_chroma_shift;
1319
        for(i = 1; i <= 2; i++) {
1320
            d = dst->data[i];
1321
            for(y = 0; y< h; y++) {
1322
                memset(d, 128, w);
1323
                d += dst->linesize[i];
1324
            }
1325
        }
1326
        return 0;
1327
    }
1328

    
1329
    /* YUV to gray */
1330
    if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
1331
        img_copy(dst->data[0], dst->linesize[0],
1332
                 src->data[0], src->linesize[0],
1333
                 dst_width, dst_height);
1334
        return 0;
1335
    }
1336

    
1337
    /* YUV to YUV */
1338
    if (dst_pix->is_yuv && src_pix->is_yuv) {
1339
        int x_shift, y_shift, w, h;
1340
        void (*resize_func)(uint8_t *dst, int dst_wrap, 
1341
                            uint8_t *src, int src_wrap,
1342
                            int width, int height);
1343

    
1344
        /* compute chroma size of the smallest dimensions */
1345
        w = dst_width;
1346
        h = dst_height;
1347
        if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
1348
            w >>= dst_pix->x_chroma_shift;
1349
        else
1350
            w >>= src_pix->x_chroma_shift;
1351
        if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
1352
            h >>= dst_pix->y_chroma_shift;
1353
        else
1354
            h >>= src_pix->y_chroma_shift;
1355

    
1356
        x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
1357
        y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
1358
        if (x_shift == 0 && y_shift == 0) {
1359
            resize_func = img_copy; /* should never happen */
1360
        } else if (x_shift == 0 && y_shift == 1) {
1361
            resize_func = shrink2;
1362
        } else if (x_shift == 1 && y_shift == 1) {
1363
            resize_func = shrink22;
1364
        } else if (x_shift == -1 && y_shift == -1) {
1365
            resize_func = grow22;
1366
        } else if (x_shift == -1 && y_shift == 1) {
1367
            resize_func = conv411;
1368
        } else {
1369
            /* currently not handled */
1370
            return -1;
1371
        }
1372

    
1373
        img_copy(dst->data[0], dst->linesize[0],
1374
                 src->data[0], src->linesize[0],
1375
                 dst_width, dst_height);
1376

    
1377
        for(i = 1;i <= 2; i++)
1378
            resize_func(dst->data[i], dst->linesize[i],
1379
                        src->data[i], src->linesize[i],
1380
                        dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
1381
       return 0;
1382
    }
1383

    
1384
    /* try to use an intermediate format */
1385
    if (src_pix_fmt == PIX_FMT_MONOWHITE ||
1386
        src_pix_fmt == PIX_FMT_MONOBLACK ||
1387
        dst_pix_fmt == PIX_FMT_MONOWHITE ||
1388
        dst_pix_fmt == PIX_FMT_MONOBLACK) {
1389
        int_pix_fmt = PIX_FMT_GRAY8;
1390
    } else {
1391
        int_pix_fmt = PIX_FMT_RGB24;
1392
    }
1393
    if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
1394
        return -1;
1395
    ret = -1;
1396
    if (img_convert(tmp, int_pix_fmt,
1397
                    src, src_pix_fmt, src_width, src_height) < 0)
1398
        goto fail1;
1399
    if (img_convert(dst, dst_pix_fmt,
1400
                    tmp, int_pix_fmt, dst_width, dst_height) < 0)
1401
        goto fail1;
1402
    ret = 0;
1403
 fail1:
1404
    avpicture_free(tmp);
1405
    return ret;
1406
}
1407

    
1408

    
1409
#ifdef HAVE_MMX
1410
#define DEINT_INPLACE_LINE_LUM \
1411
                    movd_m2r(lum_m4[0],mm0);\
1412
                    movd_m2r(lum_m3[0],mm1);\
1413
                    movd_m2r(lum_m2[0],mm2);\
1414
                    movd_m2r(lum_m1[0],mm3);\
1415
                    movd_m2r(lum[0],mm4);\
1416
                    punpcklbw_r2r(mm7,mm0);\
1417
                    movd_r2m(mm2,lum_m4[0]);\
1418
                    punpcklbw_r2r(mm7,mm1);\
1419
                    punpcklbw_r2r(mm7,mm2);\
1420
                    punpcklbw_r2r(mm7,mm3);\
1421
                    punpcklbw_r2r(mm7,mm4);\
1422
                    paddw_r2r(mm3,mm1);\
1423
                    psllw_i2r(1,mm2);\
1424
                    paddw_r2r(mm4,mm0);\
1425
                    psllw_i2r(2,mm1);\
1426
                    paddw_r2r(mm6,mm2);\
1427
                    paddw_r2r(mm2,mm1);\
1428
                    psubusw_r2r(mm0,mm1);\
1429
                    psrlw_i2r(3,mm1);\
1430
                    packuswb_r2r(mm7,mm1);\
1431
                    movd_r2m(mm1,lum_m2[0]);
1432

    
1433
#define DEINT_LINE_LUM \
1434
                    movd_m2r(lum_m4[0],mm0);\
1435
                    movd_m2r(lum_m3[0],mm1);\
1436
                    movd_m2r(lum_m2[0],mm2);\
1437
                    movd_m2r(lum_m1[0],mm3);\
1438
                    movd_m2r(lum[0],mm4);\
1439
                    punpcklbw_r2r(mm7,mm0);\
1440
                    punpcklbw_r2r(mm7,mm1);\
1441
                    punpcklbw_r2r(mm7,mm2);\
1442
                    punpcklbw_r2r(mm7,mm3);\
1443
                    punpcklbw_r2r(mm7,mm4);\
1444
                    paddw_r2r(mm3,mm1);\
1445
                    psllw_i2r(1,mm2);\
1446
                    paddw_r2r(mm4,mm0);\
1447
                    psllw_i2r(2,mm1);\
1448
                    paddw_r2r(mm6,mm2);\
1449
                    paddw_r2r(mm2,mm1);\
1450
                    psubusw_r2r(mm0,mm1);\
1451
                    psrlw_i2r(3,mm1);\
1452
                    packuswb_r2r(mm7,mm1);\
1453
                    movd_r2m(mm1,dst[0]);
1454
#endif
1455

    
1456
/* filter parameters: [-1 4 2 4 -1] // 8 */
1457
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,
1458
                                int size)
1459
{
1460
#ifndef HAVE_MMX
1461
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
1462
    int sum;
1463

    
1464
    for(;size > 0;size--) {
1465
        sum = -lum_m4[0];
1466
        sum += lum_m3[0] << 2;
1467
        sum += lum_m2[0] << 1;
1468
        sum += lum_m1[0] << 2;
1469
        sum += -lum[0];
1470
        dst[0] = cm[(sum + 4) >> 3];
1471
        lum_m4++;
1472
        lum_m3++;
1473
        lum_m2++;
1474
        lum_m1++;
1475
        lum++;
1476
        dst++;
1477
    }
1478
#else
1479

    
1480
    {
1481
        mmx_t rounder;
1482
        rounder.uw[0]=4;
1483
        rounder.uw[1]=4;
1484
        rounder.uw[2]=4;
1485
        rounder.uw[3]=4;
1486
        pxor_r2r(mm7,mm7);
1487
        movq_m2r(rounder,mm6);
1488
    }
1489
    for (;size > 3; size-=4) {
1490
        DEINT_LINE_LUM
1491
        lum_m4+=4;
1492
        lum_m3+=4;
1493
        lum_m2+=4;
1494
        lum_m1+=4;
1495
        lum+=4;
1496
        dst+=4;
1497
    }
1498
#endif
1499
}
1500
static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
1501
                             int size)
1502
{
1503
#ifndef HAVE_MMX
1504
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
1505
    int sum;
1506

    
1507
    for(;size > 0;size--) {
1508
        sum = -lum_m4[0];
1509
        sum += lum_m3[0] << 2;
1510
        sum += lum_m2[0] << 1;
1511
        lum_m4[0]=lum_m2[0];
1512
        sum += lum_m1[0] << 2;
1513
        sum += -lum[0];
1514
        lum_m2[0] = cm[(sum + 4) >> 3];
1515
        lum_m4++;
1516
        lum_m3++;
1517
        lum_m2++;
1518
        lum_m1++;
1519
        lum++;
1520
    }
1521
#else
1522

    
1523
    {
1524
        mmx_t rounder;
1525
        rounder.uw[0]=4;
1526
        rounder.uw[1]=4;
1527
        rounder.uw[2]=4;
1528
        rounder.uw[3]=4;
1529
        pxor_r2r(mm7,mm7);
1530
        movq_m2r(rounder,mm6);
1531
    }
1532
    for (;size > 3; size-=4) {
1533
        DEINT_INPLACE_LINE_LUM
1534
        lum_m4+=4;
1535
        lum_m3+=4;
1536
        lum_m2+=4;
1537
        lum_m1+=4;
1538
        lum+=4;
1539
    }
1540
#endif
1541
}
1542

    
1543
/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
1544
   top field is copied as is, but the bottom field is deinterlaced
1545
   against the top field. */
1546
static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
1547
                                    uint8_t *src1, int src_wrap,
1548
                                    int width, int height)
1549
{
1550
    uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
1551
    int y;
1552

    
1553
    src_m2 = src1;
1554
    src_m1 = src1;
1555
    src_0=&src_m1[src_wrap];
1556
    src_p1=&src_0[src_wrap];
1557
    src_p2=&src_p1[src_wrap];
1558
    for(y=0;y<(height-2);y+=2) {
1559
        memcpy(dst,src_m1,width);
1560
        dst += dst_wrap;
1561
        deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
1562
        src_m2 = src_0;
1563
        src_m1 = src_p1;
1564
        src_0 = src_p2;
1565
        src_p1 += 2*src_wrap;
1566
        src_p2 += 2*src_wrap;
1567
        dst += dst_wrap;
1568
    }
1569
    memcpy(dst,src_m1,width);
1570
    dst += dst_wrap;
1571
    /* do last line */
1572
    deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
1573
}
1574

    
1575
static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
1576
                                     int width, int height)
1577
{
1578
    uint8_t *src_m1, *src_0, *src_p1, *src_p2;
1579
    int y;
1580
    uint8_t *buf;
1581
    buf = (uint8_t*)av_malloc(width);
1582

    
1583
    src_m1 = src1;
1584
    memcpy(buf,src_m1,width);
1585
    src_0=&src_m1[src_wrap];
1586
    src_p1=&src_0[src_wrap];
1587
    src_p2=&src_p1[src_wrap];
1588
    for(y=0;y<(height-2);y+=2) {
1589
        deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1590
        src_m1 = src_p1;
1591
        src_0 = src_p2;
1592
        src_p1 += 2*src_wrap;
1593
        src_p2 += 2*src_wrap;
1594
    }
1595
    /* do last line */
1596
    deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
1597
    av_free(buf);
1598
}
1599

    
1600

    
1601
/* deinterlace - if not supported return -1 */
1602
int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
1603
                          int pix_fmt, int width, int height)
1604
{
1605
    int i;
1606

    
1607
    if (pix_fmt != PIX_FMT_YUV420P &&
1608
        pix_fmt != PIX_FMT_YUV422P &&
1609
        pix_fmt != PIX_FMT_YUV444P)
1610
        return -1;
1611
    if ((width & 3) != 0 || (height & 3) != 0)
1612
        return -1;
1613

    
1614
    for(i=0;i<3;i++) {
1615
        if (i == 1) {
1616
            switch(pix_fmt) {
1617
            case PIX_FMT_YUV420P:
1618
                width >>= 1;
1619
                height >>= 1;
1620
                break;
1621
            case PIX_FMT_YUV422P:
1622
                width >>= 1;
1623
                break;
1624
            default:
1625
                break;
1626
            }
1627
        }
1628
        if (src == dst) {
1629
            deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
1630
                                 width, height);
1631
        } else {
1632
            deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1633
                                        src->data[i], src->linesize[i],
1634
                                        width, height);
1635
        }
1636
    }
1637
#ifdef HAVE_MMX
1638
    emms();
1639
#endif
1640
    return 0;
1641
}
1642

    
1643
#undef FIX