Statistics
| Branch: | Revision:

ffmpeg / libavcodec / imgconvert.c @ 2bbf7177

History | View | Annotate | Download (33.5 KB)

1
/*
2
 * Misc image convertion routines
3
 * Copyright (c) 2001, 2002 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
#include "avcodec.h"
20
#include "dsputil.h"
21

    
22
#ifdef USE_FASTMEMCPY
23
#include "fastmemcpy.h"
24
#endif
25

    
26
#ifdef HAVE_MMX
27
#include "i386/mmx.h"
28
#endif
29
/* XXX: totally non optimized */
30

    
31
static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
32
                              UINT8 *src, int width, int height)
33
{
34
    int x, y;
35
    UINT8 *p = src;
36

    
37
    for(y=0;y<height;y+=2) {
38
        for(x=0;x<width;x+=2) {
39
            lum[0] = p[0];
40
            cb[0] = p[1];
41
            lum[1] = p[2];
42
            cr[0] = p[3];
43
            p += 4;
44
            lum += 2;
45
            cb++;
46
            cr++;
47
        }
48
        for(x=0;x<width;x+=2) {
49
            lum[0] = p[0];
50
            lum[1] = p[2];
51
            p += 4;
52
            lum += 2;
53
        }
54
    }
55
}
56

    
57
#define SCALEBITS 8
58
#define ONE_HALF  (1 << (SCALEBITS - 1))
59
#define FIX(x)                ((int) ((x) * (1L<<SCALEBITS) + 0.5))
60

    
61
static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
62
                              UINT8 *src, int width, int height)
63
{
64
    int wrap, wrap3, x, y;
65
    int r, g, b, r1, g1, b1;
66
    UINT8 *p;
67

    
68
    wrap = width;
69
    wrap3 = width * 3;
70
    p = src;
71
    for(y=0;y<height;y+=2) {
72
        for(x=0;x<width;x+=2) {
73
            r = p[0];
74
            g = p[1];
75
            b = p[2];
76
            r1 = r;
77
            g1 = g;
78
            b1 = b;
79
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
80
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
81
            r = p[3];
82
            g = p[4];
83
            b = p[5];
84
            r1 += r;
85
            g1 += g;
86
            b1 += b;
87
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
88
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
89
            p += wrap3;
90
            lum += wrap;
91

    
92
            r = p[0];
93
            g = p[1];
94
            b = p[2];
95
            r1 += r;
96
            g1 += g;
97
            b1 += b;
98
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
99
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
100
            r = p[3];
101
            g = p[4];
102
            b = p[5];
103
            r1 += r;
104
            g1 += g;
105
            b1 += b;
106
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
107
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
108
            
109
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
110
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
111
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
112
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
113

    
114
            cb++;
115
            cr++;
116
            p += -wrap3 + 2 * 3;
117
            lum += -wrap + 2;
118
        }
119
        p += wrap3;
120
        lum += wrap;
121
    }
122
}
123

    
124
static void rgba32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
125
                              UINT8 *src, int width, int height)
126
{
127
    int wrap, wrap4, x, y;
128
    int r, g, b, r1, g1, b1;
129
    UINT8 *p;
130

    
131
    wrap = width;
132
    wrap4 = width * 4;
133
    p = src;
134
    for(y=0;y<height;y+=2) {
135
        for(x=0;x<width;x+=2) {
136
            r = p[0];
137
            g = p[1];
138
            b = p[2];
139
            r1 = r;
140
            g1 = g;
141
            b1 = b;
142
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
143
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
144
            r = p[4];
145
            g = p[5];
146
            b = p[6];
147
            r1 += r;
148
            g1 += g;
149
            b1 += b;
150
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
151
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
152
            p += wrap4;
153
            lum += wrap;
154

    
155
            r = p[0];
156
            g = p[1];
157
            b = p[2];
158
            r1 += r;
159
            g1 += g;
160
            b1 += b;
161
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
162
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
163
            r = p[4];
164
            g = p[5];
165
            b = p[6];
166
            r1 += r;
167
            g1 += g;
168
            b1 += b;
169
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
170
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
171
            
172
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
173
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
174
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
175
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
176

    
177
            cb++;
178
            cr++;
179
            p += -wrap4 + 2 * 4;
180
            lum += -wrap + 2;
181
        }
182
        p += wrap4;
183
        lum += wrap;
184
    }
185
}
186

    
187
#define rgb565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0020,63,0x0001,31)
188
#define rgb555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0400,31, 0x0020,31,0x0001,31)
189
#define rgb5551_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0040,31,0x0002,31)
190
#define bgr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,63,0x0800,31)
191
#define bgr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,31,0x0400,31)
192
#define gbr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0800,31,0x0040,63)
193
#define gbr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0400,31,0x0020,31)
194

    
195
static void rgbmisc_to_yuv420p
196
  (UINT8 *lum, UINT8 *cb, UINT8 *cr,
197
   UINT8 *src, int width, int height,
198
   
199
   UINT16 R_LOWMASK, UINT16 R_MAX,
200
   UINT16 G_LOWMASK, UINT16 G_MAX,
201
   UINT16 B_LOWMASK, UINT16 B_MAX
202
  )
203
{
204
    int wrap, wrap2, x, y;
205
    int r, g, b, r1, g1, b1;
206
    UINT8 *p;
207
    UINT16 pixel;
208

    
209
    wrap = width;
210
    wrap2 = width * 2;
211
    p = src;
212
    for(y=0;y<height;y+=2) {
213
        for(x=0;x<width;x+=2) {
214
            pixel = p[0] | (p[1]<<8);
215
            r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
216
            g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
217
            b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
218
            r1 = r;
219
            g1 = g;
220
            b1 = b;
221
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
222
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
223

    
224
            pixel = p[2] | (p[3]<<8);
225
            r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
226
            g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
227
            b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
228
            r1 += r;
229
            g1 += g;
230
            b1 += b;
231
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
232
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
233
            p += wrap2;
234
            lum += wrap;
235

    
236
            pixel = p[0] | (p[1]<<8);
237
            r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
238
            g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
239
            b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
240
            r1 += r;
241
            g1 += g;
242
            b1 += b;
243
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
244
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
245
            pixel = p[2] | (p[3]<<8);
246
            r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
247
            g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
248
            b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
249
            r1 += r;
250
            g1 += g;
251
            b1 += b;
252
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
253
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
254
            
255
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
256
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
257
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
258
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
259

    
260
            cb++;
261
            cr++;
262
            p += -wrap2 + 2 * 2;
263
            lum += -wrap + 2;
264
        }
265
        p += wrap2;
266
        lum += wrap;
267
    }
268
}
269

    
270

    
271
static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
272
                              UINT8 *src, int width, int height)
273
{
274
    int wrap, wrap3, x, y;
275
    int r, g, b, r1, g1, b1;
276
    UINT8 *p;
277

    
278
    wrap = width;
279
    wrap3 = width * 3;
280
    p = src;
281
    for(y=0;y<height;y+=2) {
282
        for(x=0;x<width;x+=2) {
283
            b = p[0];
284
            g = p[1];
285
            r = p[2];
286
            r1 = r;
287
            g1 = g;
288
            b1 = b;
289
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
290
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
291
            b = p[3];
292
            g = p[4];
293
            r = p[5];
294
            r1 += r;
295
            g1 += g;
296
            b1 += b;
297
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
298
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
299
            p += wrap3;
300
            lum += wrap;
301

    
302
            b = p[0];
303
            g = p[1];
304
            r = p[2];
305
            r1 += r;
306
            g1 += g;
307
            b1 += b;
308
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
309
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
310
            b = p[3];
311
            g = p[4];
312
            r = p[5];
313
            r1 += r;
314
            g1 += g;
315
            b1 += b;
316
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
317
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
318
            
319
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
320
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
321
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
322
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
323

    
324
            cb++;
325
            cr++;
326
            p += -wrap3 + 2 * 3;
327
            lum += -wrap + 2;
328
        }
329
        p += wrap3;
330
        lum += wrap;
331
    }
332
}
333

    
334
static void bgra32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
335
                              UINT8 *src, int width, int height)
336
{
337
    int wrap, wrap4, x, y;
338
    int r, g, b, r1, g1, b1;
339
    UINT8 *p;
340

    
341
    wrap = width;
342
    wrap4 = width * 4;
343
    p = src;
344
    for(y=0;y<height;y+=2) {
345
        for(x=0;x<width;x+=2) {
346
            b = p[0];
347
            g = p[1];
348
            r = p[2];
349
            r1 = r;
350
            g1 = g;
351
            b1 = b;
352
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
353
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
354
            b = p[4];
355
            g = p[5];
356
            r = p[6];
357
            r1 += r;
358
            g1 += g;
359
            b1 += b;
360
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
361
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
362
            p += wrap4;
363
            lum += wrap;
364

    
365
            b = p[0];
366
            g = p[1];
367
            r = p[2];
368
            r1 += r;
369
            g1 += g;
370
            b1 += b;
371
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
372
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
373
            b = p[4];
374
            g = p[5];
375
            r = p[6];
376
            r1 += r;
377
            g1 += g;
378
            b1 += b;
379
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
380
                      FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
381
            
382
            cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
383
                      FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
384
            cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
385
                     FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
386

    
387
            cb++;
388
            cr++;
389
            p += -wrap4 + 2 * 4;
390
            lum += -wrap + 2;
391
        }
392
        p += wrap4;
393
        lum += wrap;
394
    }
395
}
396

    
397
/* XXX: use generic filter ? */
398
/* 1x2 -> 1x1 */
399
static void shrink2(UINT8 *dst, int dst_wrap, 
400
                    UINT8 *src, int src_wrap,
401
                    int width, int height)
402
{
403
    int w;
404
    UINT8 *s1, *s2, *d;
405

    
406
    for(;height > 0; height--) {
407
        s1 = src;
408
        s2 = s1 + src_wrap;
409
        d = dst;
410
        for(w = width;w >= 4; w-=4) {
411
            d[0] = (s1[0] + s2[0]) >> 1;
412
            d[1] = (s1[1] + s2[1]) >> 1;
413
            d[2] = (s1[2] + s2[2]) >> 1;
414
            d[3] = (s1[3] + s2[3]) >> 1;
415
            s1 += 4;
416
            s2 += 4;
417
            d += 4;
418
        }
419
        for(;w > 0; w--) {
420
            d[0] = (s1[0] + s2[0]) >> 1;
421
            s1++;
422
            s2++;
423
            d++;
424
        }
425
        src += 2 * src_wrap;
426
        dst += dst_wrap;
427
    }
428
}
429

    
430
/* 2x2 -> 1x1 */
431
static void shrink22(UINT8 *dst, int dst_wrap, 
432
                     UINT8 *src, int src_wrap,
433
                     int width, int height)
434
{
435
    int w;
436
    UINT8 *s1, *s2, *d;
437

    
438
    for(;height > 0; height--) {
439
        s1 = src;
440
        s2 = s1 + src_wrap;
441
        d = dst;
442
        for(w = width;w >= 4; w-=4) {
443
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
444
            d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
445
            d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
446
            d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
447
            s1 += 8;
448
            s2 += 8;
449
            d += 4;
450
        }
451
        for(;w > 0; w--) {
452
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
453
            s1 += 2;
454
            s2 += 2;
455
            d++;
456
        }
457
        src += 2 * src_wrap;
458
        dst += dst_wrap;
459
    }
460
}
461

    
462
/* 1x1 -> 2x2 */
463
static void grow22(UINT8 *dst, int dst_wrap,
464
                     UINT8 *src, int src_wrap,
465
                     int width, int height)
466
{
467
    int w;
468
    UINT8 *s1, *d;
469

    
470
    for(;height > 0; height--) {
471
        s1 = src;
472
        d = dst;
473
        for(w = width;w >= 4; w-=4) {
474
            d[1] = d[0] = s1[0];
475
            d[3] = d[2] = s1[1];
476
            s1 += 2;
477
            d += 4;
478
        }
479
        for(;w > 0; w--) {
480
            d[0] = s1[0];
481
            s1 ++;
482
            d++;
483
        }
484
        if (height%2)
485
            src += src_wrap;
486
        dst += dst_wrap;
487
    }
488
}
489

    
490
/* 1x2 -> 2x1. width and height are given for the source picture */
491
static void conv411(UINT8 *dst, int dst_wrap, 
492
                    UINT8 *src, int src_wrap,
493
                    int width, int height)
494
{
495
    int w, c;
496
    UINT8 *s1, *s2, *d;
497

    
498
    for(;height > 0; height -= 2) {
499
        s1 = src;
500
        s2 = src + src_wrap;
501
        d = dst;
502
        for(w = width;w > 0; w--) {
503
            c = (s1[0] + s2[0]) >> 1;
504
            d[0] = c;
505
            d[1] = c;
506
            s1++;
507
            s2++;
508
            d += 2;
509
        }
510
        src += src_wrap * 2;
511
        dst += dst_wrap;
512
    }
513
}
514

    
515
static void img_copy(UINT8 *dst, int dst_wrap, 
516
                     UINT8 *src, int src_wrap,
517
                     int width, int height)
518
{
519
    for(;height > 0; height--) {
520
        memcpy(dst, src, width);
521
        dst += dst_wrap;
522
        src += src_wrap;
523
    }
524
}
525

    
526
#define SCALE_BITS 10
527

    
528
#define C_Y  (76309 >> (16 - SCALE_BITS))
529
#define C_RV (117504 >> (16 - SCALE_BITS))
530
#define C_BU (138453 >> (16 - SCALE_BITS))
531
#define C_GU (13954 >> (16 - SCALE_BITS))
532
#define C_GV (34903 >> (16 - SCALE_BITS))
533

    
534
#define RGBOUT(r, g, b, y1)\
535
{\
536
    y = (y1 - 16) * C_Y;\
537
    r = cm[(y + r_add) >> SCALE_BITS];\
538
    g = cm[(y + g_add) >> SCALE_BITS];\
539
    b = cm[(y + b_add) >> SCALE_BITS];\
540
}
541

    
542
/* XXX: no chroma interpolating is done */
543
static void yuv420p_to_bgra32(AVPicture *dst, AVPicture *src, 
544
                             int width, int height)
545
{
546
    UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
547
    int w, y, cb, cr, r_add, g_add, b_add, width2;
548
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
549

    
550
    d = dst->data[0];
551
    y1_ptr = src->data[0];
552
    cb_ptr = src->data[1];
553
    cr_ptr = src->data[2];
554
    width2 = width >> 1;
555
    for(;height > 0; height -= 2) {
556
        d1 = d;
557
        d2 = d + dst->linesize[0];
558
        y2_ptr = y1_ptr + src->linesize[0];
559
        for(w = width2; w > 0; w --) {
560
            cb = cb_ptr[0] - 128;
561
            cr = cr_ptr[0] - 128;
562
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
563
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
564
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
565
            
566
            /* output 4 pixels */
567
            RGBOUT(d1[2], d1[1], d1[0], y1_ptr[0]);
568
            RGBOUT(d1[6], d1[5], d1[4], y1_ptr[1]);
569
            RGBOUT(d2[2], d2[1], d2[0], y2_ptr[0]);
570
            RGBOUT(d2[6], d2[5], d2[4], y2_ptr[1]);
571

    
572
            d1[3] = d1[7] = d2[3] = d2[7] = 255;
573

    
574
            d1 += 8;
575
            d2 += 8;
576
            y1_ptr += 2;
577
            y2_ptr += 2;
578
            cb_ptr++;
579
            cr_ptr++;
580
        }
581
        d += 2 * dst->linesize[0];
582
        y1_ptr += 2 * src->linesize[0] - width;
583
        cb_ptr += src->linesize[1] - width2;
584
        cr_ptr += src->linesize[2] - width2;
585
    }
586
}
587

    
588
/* XXX: no chroma interpolating is done */
589
static void yuv420p_to_rgba32(AVPicture *dst, AVPicture *src, 
590
                             int width, int height)
591
{
592
    UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
593
    int w, y, cb, cr, r_add, g_add, b_add, width2;
594
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
595

    
596
    d = dst->data[0];
597
    y1_ptr = src->data[0];
598
    cb_ptr = src->data[1];
599
    cr_ptr = src->data[2];
600
    width2 = width >> 1;
601
    for(;height > 0; height -= 2) {
602
        d1 = d;
603
        d2 = d + dst->linesize[0];
604
        y2_ptr = y1_ptr + src->linesize[0];
605
        for(w = width2; w > 0; w --) {
606
            cb = cb_ptr[0] - 128;
607
            cr = cr_ptr[0] - 128;
608
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
609
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
610
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
611
            
612
            /* output 4 pixels */
613
            RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
614
            RGBOUT(d1[4], d1[5], d1[6], y1_ptr[1]);
615
            RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
616
            RGBOUT(d2[4], d2[5], d2[6], y2_ptr[1]);
617

    
618
            d1[3] = d1[7] = d2[3] = d2[7] = 255;
619

    
620
            d1 += 8;
621
            d2 += 8;
622
            y1_ptr += 2;
623
            y2_ptr += 2;
624
            cb_ptr++;
625
            cr_ptr++;
626
        }
627
        d += 2 * dst->linesize[0];
628
        y1_ptr += 2 * src->linesize[0] - width;
629
        cb_ptr += src->linesize[1] - width2;
630
        cr_ptr += src->linesize[2] - width2;
631
    }
632
}
633

    
634
/* XXX: no chroma interpolating is done */
635
static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src, 
636
                             int width, int height)
637
{
638
    UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
639
    int w, y, cb, cr, r_add, g_add, b_add, width2;
640
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
641

    
642
    d = dst->data[0];
643
    y1_ptr = src->data[0];
644
    cb_ptr = src->data[1];
645
    cr_ptr = src->data[2];
646
    width2 = width >> 1;
647
    for(;height > 0; height -= 2) {
648
        d1 = d;
649
        d2 = d + dst->linesize[0];
650
        y2_ptr = y1_ptr + src->linesize[0];
651
        for(w = width2; w > 0; w --) {
652
            cb = cb_ptr[0] - 128;
653
            cr = cr_ptr[0] - 128;
654
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
655
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
656
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
657
            
658
            /* output 4 pixels */
659
            RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
660
            RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
661
            RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
662
            RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
663

    
664
            d1 += 6;
665
            d2 += 6;
666
            y1_ptr += 2;
667
            y2_ptr += 2;
668
            cb_ptr++;
669
            cr_ptr++;
670
        }
671
        d += 2 * dst->linesize[0];
672
        y1_ptr += 2 * src->linesize[0] - width;
673
        cb_ptr += src->linesize[1] - width2;
674
        cr_ptr += src->linesize[2] - width2;
675
    }
676
}
677

    
678
/* XXX: no chroma interpolating is done */
679
static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src, 
680
                             int width, int height)
681
{
682
    UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
683
    int w, y, cb, cr, r_add, g_add, b_add, width2;
684
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
685

    
686
    d = dst->data[0];
687
    y1_ptr = src->data[0];
688
    cb_ptr = src->data[1];
689
    cr_ptr = src->data[2];
690
    width2 = width >> 1;
691
    for(;height > 0; height --) {
692
        d1 = d;
693
        for(w = width2; w > 0; w --) {
694
            cb = cb_ptr[0] - 128;
695
            cr = cr_ptr[0] - 128;
696
            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
697
            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
698
            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
699
            
700
            /* output 2 pixels */
701
            RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
702
            RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
703

    
704
            d1 += 6;
705
            y1_ptr += 2;
706
            cb_ptr++;
707
            cr_ptr++;
708
        }
709
        d += dst->linesize[0];
710
        y1_ptr += src->linesize[0] - width;
711
        cb_ptr += src->linesize[1] - width2;
712
        cr_ptr += src->linesize[2] - width2;
713
    }
714
}
715

    
716
/* XXX: always use linesize. Return -1 if not supported */
717
int img_convert(AVPicture *dst, int dst_pix_fmt,
718
                AVPicture *src, int pix_fmt, 
719
                int width, int height)
720
{
721
    int i;
722

    
723
    if (dst_pix_fmt == pix_fmt) {
724
        switch(pix_fmt) {
725
        case PIX_FMT_YUV420P:
726
            for(i=0;i<3;i++) {
727
                if (i == 1) {
728
                    width >>= 1;
729
                    height >>= 1;
730
                }
731
                img_copy(dst->data[i], dst->linesize[i],
732
                         src->data[i], src->linesize[i],
733
                         width, height);
734
            }
735
            break;
736
        default:
737
            return -1;
738
        }
739
    } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
740
        
741
        switch(pix_fmt) {
742
        case PIX_FMT_YUV411P:
743
            img_copy(dst->data[0], dst->linesize[0],
744
                     src->data[0], src->linesize[0],
745
                     width, height);
746
            conv411(dst->data[1], dst->linesize[1],
747
                    src->data[1], src->linesize[1],
748
                    width / 4, height);
749
            conv411(dst->data[2], dst->linesize[2],
750
                    src->data[2], src->linesize[2],
751
                    width / 4, height);
752
            break;
753
        case PIX_FMT_YUV410P:
754
            img_copy(dst->data[0], dst->linesize[0],
755
                     src->data[0], src->linesize[0],
756
                     width, height);
757
            grow22(dst->data[1], dst->linesize[1],
758
                     src->data[1], src->linesize[1],
759
                     width/2, height/2);
760
            grow22(dst->data[2], dst->linesize[2],
761
                     src->data[2], src->linesize[2],
762
                     width/2, height/2);
763
            break;
764
        case PIX_FMT_YUV420P:
765
            for(i=0;i<3;i++) {
766
                img_copy(dst->data[i], dst->linesize[i],
767
                         src->data[i], src->linesize[i],
768
                         width, height);
769
            }
770
            break;
771
        case PIX_FMT_YUV422P:
772
            img_copy(dst->data[0], dst->linesize[0],
773
                     src->data[0], src->linesize[0],
774
                     width, height);
775
            width >>= 1;
776
            height >>= 1;
777
            for(i=1;i<3;i++) {
778
                shrink2(dst->data[i], dst->linesize[i],
779
                        src->data[i], src->linesize[i],
780
                        width, height);
781
            }
782
            break;
783
        case PIX_FMT_YUV444P:
784
            img_copy(dst->data[0], dst->linesize[0],
785
                     src->data[0], src->linesize[0],
786
                     width, height);
787
            width >>= 1;
788
            height >>= 1;
789
            for(i=1;i<3;i++) {
790
                shrink22(dst->data[i], dst->linesize[i],
791
                         src->data[i], src->linesize[i],
792
                         width, height);
793
            }
794
            break;
795
        case PIX_FMT_YUV422:
796
            yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
797
                              src->data[0], width, height);
798
            break;
799
        case PIX_FMT_RGB24:
800
            rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
801
                             src->data[0], width, height);
802
            break;
803
        case PIX_FMT_RGBA32:
804
            rgba32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
805
                             src->data[0], width, height);
806
            break;
807
        case PIX_FMT_BGR24:
808
            bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
809
                             src->data[0], width, height);
810
            break;
811
        case PIX_FMT_BGRA32:
812
            bgra32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
813
                             src->data[0], width, height);
814
            break;
815
        case PIX_FMT_RGB565:
816
            rgb565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
817
                             src->data[0], width, height);
818
            break;
819
        case PIX_FMT_RGB555:
820
            rgb555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
821
                             src->data[0], width, height);
822
            break;
823
/*        case PIX_FMT_RGB5551:
824
            rgb5551_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
825
                             src->data[0], width, height);
826
            break;*/
827
        case PIX_FMT_BGR565:
828
            bgr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
829
                             src->data[0], width, height);
830
            break;
831
        case PIX_FMT_BGR555:
832
            bgr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
833
                             src->data[0], width, height);
834
            break;
835
/*        case PIX_FMT_GBR565:
836
            gbr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
837
                             src->data[0], width, height);
838
            break;
839
        case PIX_FMT_GBR555:
840
            gbr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
841
                             src->data[0], width, height);
842
            break;*/
843
        default:
844
            return -1;
845
        }
846
    } else if (dst_pix_fmt == PIX_FMT_RGB24) {
847
        switch(pix_fmt) {
848
        case PIX_FMT_YUV420P:
849
            yuv420p_to_rgb24(dst, src, width, height);
850
            break;
851
        case PIX_FMT_YUV422P:
852
            yuv422p_to_rgb24(dst, src, width, height);
853
            break;
854
        default:
855
            return -1;
856
        }
857
    } else if (dst_pix_fmt == PIX_FMT_RGBA32) {
858
        switch(pix_fmt) {
859
        case PIX_FMT_YUV420P:
860
            yuv420p_to_rgba32(dst, src, width, height);
861
            break;
862
        default:
863
            return -1;
864
        }
865
    } else if (dst_pix_fmt == PIX_FMT_BGRA32) {
866
        switch(pix_fmt) {
867
        case PIX_FMT_YUV420P:
868
            yuv420p_to_bgra32(dst, src, width, height);
869
            break;
870
        default:
871
            return -1;
872
        }
873
    } else {
874
        return -1;
875
    }
876
    return 0;
877
}
878

    
879

    
880
#ifdef HAVE_MMX
881
#define DEINT_INPLACE_LINE_LUM \
882
                    movd_m2r(lum_m4[0],mm0);\
883
                    movd_m2r(lum_m3[0],mm1);\
884
                    movd_m2r(lum_m2[0],mm2);\
885
                    movd_m2r(lum_m1[0],mm3);\
886
                    movd_m2r(lum[0],mm4);\
887
                    punpcklbw_r2r(mm7,mm0);\
888
                    movd_r2m(mm2,lum_m4[0]);\
889
                    punpcklbw_r2r(mm7,mm1);\
890
                    punpcklbw_r2r(mm7,mm2);\
891
                    punpcklbw_r2r(mm7,mm3);\
892
                    punpcklbw_r2r(mm7,mm4);\
893
                    paddw_r2r(mm3,mm1);\
894
                    psllw_i2r(1,mm2);\
895
                    paddw_r2r(mm4,mm0);\
896
                    psllw_i2r(2,mm1);\
897
                    paddw_r2r(mm6,mm2);\
898
                    paddw_r2r(mm2,mm1);\
899
                    psubusw_r2r(mm0,mm1);\
900
                    psrlw_i2r(3,mm1);\
901
                    packuswb_r2r(mm7,mm1);\
902
                    movd_r2m(mm1,lum_m2[0]);
903

    
904
#define DEINT_LINE_LUM \
905
                    movd_m2r(lum_m4[0],mm0);\
906
                    movd_m2r(lum_m3[0],mm1);\
907
                    movd_m2r(lum_m2[0],mm2);\
908
                    movd_m2r(lum_m1[0],mm3);\
909
                    movd_m2r(lum[0],mm4);\
910
                    punpcklbw_r2r(mm7,mm0);\
911
                    punpcklbw_r2r(mm7,mm1);\
912
                    punpcklbw_r2r(mm7,mm2);\
913
                    punpcklbw_r2r(mm7,mm3);\
914
                    punpcklbw_r2r(mm7,mm4);\
915
                    paddw_r2r(mm3,mm1);\
916
                    psllw_i2r(1,mm2);\
917
                    paddw_r2r(mm4,mm0);\
918
                    psllw_i2r(2,mm1);\
919
                    paddw_r2r(mm6,mm2);\
920
                    paddw_r2r(mm2,mm1);\
921
                    psubusw_r2r(mm0,mm1);\
922
                    psrlw_i2r(3,mm1);\
923
                    packuswb_r2r(mm7,mm1);\
924
                    movd_r2m(mm1,dst[0]);
925
#endif
926

    
927
/* filter parameters: [-1 4 2 4 -1] // 8 */
928
static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
929
                                int size)
930
{
931
#ifndef HAVE_MMX
932
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
933
    int sum;
934

    
935
    for(;size > 0;size--) {
936
        sum = -lum_m4[0];
937
        sum += lum_m3[0] << 2;
938
        sum += lum_m2[0] << 1;
939
        sum += lum_m1[0] << 2;
940
        sum += -lum[0];
941
        dst[0] = cm[(sum + 4) >> 3];
942
        lum_m4++;
943
        lum_m3++;
944
        lum_m2++;
945
        lum_m1++;
946
        lum++;
947
        dst++;
948
    }
949
#else
950

    
951
    for (;size > 3; size-=4) {
952
        DEINT_LINE_LUM
953
        lum_m4+=4;
954
        lum_m3+=4;
955
        lum_m2+=4;
956
        lum_m1+=4;
957
        lum+=4;
958
        dst+=4;
959
    }
960
#endif
961
}
962
static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
963
                             int size)
964
{
965
#ifndef HAVE_MMX
966
    UINT8 *cm = cropTbl + MAX_NEG_CROP;
967
    int sum;
968

    
969
    for(;size > 0;size--) {
970
        sum = -lum_m4[0];
971
        sum += lum_m3[0] << 2;
972
        sum += lum_m2[0] << 1;
973
        lum_m4[0]=lum_m2[0];
974
        sum += lum_m1[0] << 2;
975
        sum += -lum[0];
976
        lum_m2[0] = cm[(sum + 4) >> 3];
977
        lum_m4++;
978
        lum_m3++;
979
        lum_m2++;
980
        lum_m1++;
981
        lum++;
982
    }
983
#else
984

    
985
    for (;size > 3; size-=4) {
986
        DEINT_INPLACE_LINE_LUM
987
        lum_m4+=4;
988
        lum_m3+=4;
989
        lum_m2+=4;
990
        lum_m1+=4;
991
        lum+=4;
992
    }
993
#endif
994
}
995

    
996
/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
997
   top field is copied as is, but the bottom field is deinterlaced
998
   against the top field. */
999
static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
1000
                                    UINT8 *src1, int src_wrap,
1001
                                    int width, int height)
1002
{
1003
    UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
1004
    int y;
1005

    
1006
    src_m2 = src1;
1007
    src_m1 = src1;
1008
    src_0=&src_m1[src_wrap];
1009
    src_p1=&src_0[src_wrap];
1010
    src_p2=&src_p1[src_wrap];
1011
    for(y=0;y<(height-2);y+=2) {
1012
        memcpy(dst,src_m1,width);
1013
        dst += dst_wrap;
1014
        deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
1015
        src_m2 = src_0;
1016
        src_m1 = src_p1;
1017
        src_0 = src_p2;
1018
        src_p1 += 2*src_wrap;
1019
        src_p2 += 2*src_wrap;
1020
        dst += dst_wrap;
1021
    }
1022
    memcpy(dst,src_m1,width);
1023
    dst += dst_wrap;
1024
    /* do last line */
1025
    deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
1026
}
1027

    
1028
static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
1029
                                     int width, int height)
1030
{
1031
    UINT8 *src_m1, *src_0, *src_p1, *src_p2;
1032
    int y;
1033
    UINT8 *buf;
1034
    buf = (UINT8*)av_malloc(width);
1035

    
1036
    src_m1 = src1;
1037
    memcpy(buf,src_m1,width);
1038
    src_0=&src_m1[src_wrap];
1039
    src_p1=&src_0[src_wrap];
1040
    src_p2=&src_p1[src_wrap];
1041
    for(y=0;y<(height-2);y+=2) {
1042
        deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1043
        src_m1 = src_p1;
1044
        src_0 = src_p2;
1045
        src_p1 += 2*src_wrap;
1046
        src_p2 += 2*src_wrap;
1047
    }
1048
    /* do last line */
1049
    deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
1050
    av_free(buf);
1051
}
1052

    
1053

    
1054
/* deinterlace - if not supported return -1 */
1055
int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
1056
                          int pix_fmt, int width, int height)
1057
{
1058
    int i;
1059

    
1060
    if (pix_fmt != PIX_FMT_YUV420P &&
1061
        pix_fmt != PIX_FMT_YUV422P &&
1062
        pix_fmt != PIX_FMT_YUV444P)
1063
        return -1;
1064
    if ((width & 3) != 0 || (height & 3) != 0)
1065
        return -1;
1066

    
1067
#ifdef HAVE_MMX
1068
    {
1069
        mmx_t rounder;
1070
        rounder.uw[0]=4;
1071
        rounder.uw[1]=4;
1072
        rounder.uw[2]=4;
1073
        rounder.uw[3]=4;
1074
        pxor_r2r(mm7,mm7);
1075
        movq_m2r(rounder,mm6);
1076
    }
1077
#endif
1078

    
1079
    
1080
    for(i=0;i<3;i++) {
1081
        if (i == 1) {
1082
            switch(pix_fmt) {
1083
            case PIX_FMT_YUV420P:
1084
                width >>= 1;
1085
                height >>= 1;
1086
                break;
1087
            case PIX_FMT_YUV422P:
1088
                width >>= 1;
1089
                break;
1090
            default:
1091
                break;
1092
            }
1093
        }
1094
        if (src == dst) {
1095
            deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
1096
                                 width, height);
1097
        } else {
1098
            deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1099
                                        src->data[i], src->linesize[i],
1100
                                        width, height);
1101
        }
1102
    }
1103
#ifdef HAVE_MMX
1104
    emms();
1105
#endif
1106
    return 0;
1107
}
1108

    
1109
#undef FIX