]> git.sesse.net Git - ffmpeg/blob - libavcodec/imgconvert.c
854ea50ddb9481e3f22703106a04106a7dc23db6
[ffmpeg] / libavcodec / imgconvert.c
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 static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
188                               UINT8 *src, int width, int height)
189 {
190     int wrap, wrap3, x, y;
191     int r, g, b, r1, g1, b1;
192     UINT8 *p;
193
194     wrap = width;
195     wrap3 = width * 3;
196     p = src;
197     for(y=0;y<height;y+=2) {
198         for(x=0;x<width;x+=2) {
199             b = p[0];
200             g = p[1];
201             r = p[2];
202             r1 = r;
203             g1 = g;
204             b1 = b;
205             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
206                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
207             b = p[3];
208             g = p[4];
209             r = p[5];
210             r1 += r;
211             g1 += g;
212             b1 += b;
213             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
214                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
215             p += wrap3;
216             lum += wrap;
217
218             b = p[0];
219             g = p[1];
220             r = p[2];
221             r1 += r;
222             g1 += g;
223             b1 += b;
224             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
225                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
226             b = p[3];
227             g = p[4];
228             r = p[5];
229             r1 += r;
230             g1 += g;
231             b1 += b;
232             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
233                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
234             
235             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
236                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
237             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
238                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
239
240             cb++;
241             cr++;
242             p += -wrap3 + 2 * 3;
243             lum += -wrap + 2;
244         }
245         p += wrap3;
246         lum += wrap;
247     }
248 }
249
250 static void bgra32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
251                               UINT8 *src, int width, int height)
252 {
253     int wrap, wrap4, x, y;
254     int r, g, b, r1, g1, b1;
255     UINT8 *p;
256
257     wrap = width;
258     wrap4 = width * 4;
259     p = src;
260     for(y=0;y<height;y+=2) {
261         for(x=0;x<width;x+=2) {
262             b = p[0];
263             g = p[1];
264             r = p[2];
265             r1 = r;
266             g1 = g;
267             b1 = b;
268             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
269                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
270             b = p[4];
271             g = p[5];
272             r = p[6];
273             r1 += r;
274             g1 += g;
275             b1 += b;
276             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
277                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
278             p += wrap4;
279             lum += wrap;
280
281             b = p[0];
282             g = p[1];
283             r = p[2];
284             r1 += r;
285             g1 += g;
286             b1 += b;
287             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
288                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
289             b = p[4];
290             g = p[5];
291             r = p[6];
292             r1 += r;
293             g1 += g;
294             b1 += b;
295             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
296                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
297             
298             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
299                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
300             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
301                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
302
303             cb++;
304             cr++;
305             p += -wrap4 + 2 * 4;
306             lum += -wrap + 2;
307         }
308         p += wrap4;
309         lum += wrap;
310     }
311 }
312
313 /* XXX: use generic filter ? */
314 /* 1x2 -> 1x1 */
315 static void shrink2(UINT8 *dst, int dst_wrap, 
316                     UINT8 *src, int src_wrap,
317                     int width, int height)
318 {
319     int w;
320     UINT8 *s1, *s2, *d;
321
322     for(;height > 0; height--) {
323         s1 = src;
324         s2 = s1 + src_wrap;
325         d = dst;
326         for(w = width;w >= 4; w-=4) {
327             d[0] = (s1[0] + s2[0]) >> 1;
328             d[1] = (s1[1] + s2[1]) >> 1;
329             d[2] = (s1[2] + s2[2]) >> 1;
330             d[3] = (s1[3] + s2[3]) >> 1;
331             s1 += 4;
332             s2 += 4;
333             d += 4;
334         }
335         for(;w > 0; w--) {
336             d[0] = (s1[0] + s2[0]) >> 1;
337             s1++;
338             s2++;
339             d++;
340         }
341         src += 2 * src_wrap;
342         dst += dst_wrap;
343     }
344 }
345
346 /* 2x2 -> 1x1 */
347 static void shrink22(UINT8 *dst, int dst_wrap, 
348                      UINT8 *src, int src_wrap,
349                      int width, int height)
350 {
351     int w;
352     UINT8 *s1, *s2, *d;
353
354     for(;height > 0; height--) {
355         s1 = src;
356         s2 = s1 + src_wrap;
357         d = dst;
358         for(w = width;w >= 4; w-=4) {
359             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
360             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
361             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
362             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
363             s1 += 8;
364             s2 += 8;
365             d += 4;
366         }
367         for(;w > 0; w--) {
368             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
369             s1 += 2;
370             s2 += 2;
371             d++;
372         }
373         src += 2 * src_wrap;
374         dst += dst_wrap;
375     }
376 }
377
378 /* 1x1 -> 2x2 */
379 static void grow22(UINT8 *dst, int dst_wrap,
380                      UINT8 *src, int src_wrap,
381                      int width, int height)
382 {
383     int w;
384     UINT8 *s1, *d;
385
386     for(;height > 0; height--) {
387         s1 = src;
388         d = dst;
389         for(w = width;w >= 4; w-=4) {
390             d[1] = d[0] = s1[0];
391             d[3] = d[2] = s1[1];
392             s1 += 2;
393             d += 4;
394         }
395         for(;w > 0; w--) {
396             d[0] = s1[0];
397             s1 ++;
398             d++;
399         }
400         if (height%2)
401             src += src_wrap;
402         dst += dst_wrap;
403     }
404 }
405
406 /* 1x2 -> 2x1. width and height are given for the source picture */
407 static void conv411(UINT8 *dst, int dst_wrap, 
408                     UINT8 *src, int src_wrap,
409                     int width, int height)
410 {
411     int w, c;
412     UINT8 *s1, *s2, *d;
413
414     for(;height > 0; height -= 2) {
415         s1 = src;
416         s2 = src + src_wrap;
417         d = dst;
418         for(w = width;w > 0; w--) {
419             c = (s1[0] + s2[0]) >> 1;
420             d[0] = c;
421             d[1] = c;
422             s1++;
423             s2++;
424             d += 2;
425         }
426         src += src_wrap * 2;
427         dst += dst_wrap;
428     }
429 }
430
431 static void img_copy(UINT8 *dst, int dst_wrap, 
432                      UINT8 *src, int src_wrap,
433                      int width, int height)
434 {
435     for(;height > 0; height--) {
436         memcpy(dst, src, width);
437         dst += dst_wrap;
438         src += src_wrap;
439     }
440 }
441
442 #define SCALE_BITS 10
443
444 #define C_Y  (76309 >> (16 - SCALE_BITS))
445 #define C_RV (117504 >> (16 - SCALE_BITS))
446 #define C_BU (138453 >> (16 - SCALE_BITS))
447 #define C_GU (13954 >> (16 - SCALE_BITS))
448 #define C_GV (34903 >> (16 - SCALE_BITS))
449
450 #define RGBOUT(r, g, b, y1)\
451 {\
452     y = (y1 - 16) * C_Y;\
453     r = cm[(y + r_add) >> SCALE_BITS];\
454     g = cm[(y + g_add) >> SCALE_BITS];\
455     b = cm[(y + b_add) >> SCALE_BITS];\
456 }
457
458 /* XXX: no chroma interpolating is done */
459 static void yuv420p_to_bgra32(AVPicture *dst, AVPicture *src, 
460                              int width, int height)
461 {
462     UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
463     int w, y, cb, cr, r_add, g_add, b_add, width2;
464     UINT8 *cm = cropTbl + MAX_NEG_CROP;
465
466     d = dst->data[0];
467     y1_ptr = src->data[0];
468     cb_ptr = src->data[1];
469     cr_ptr = src->data[2];
470     width2 = width >> 1;
471     for(;height > 0; height -= 2) {
472         d1 = d;
473         d2 = d + dst->linesize[0];
474         y2_ptr = y1_ptr + src->linesize[0];
475         for(w = width2; w > 0; w --) {
476             cb = cb_ptr[0] - 128;
477             cr = cr_ptr[0] - 128;
478             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
479             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
480             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
481             
482             /* output 4 pixels */
483             RGBOUT(d1[2], d1[1], d1[0], y1_ptr[0]);
484             RGBOUT(d1[6], d1[5], d1[4], y1_ptr[1]);
485             RGBOUT(d2[2], d2[1], d2[0], y2_ptr[0]);
486             RGBOUT(d2[6], d2[5], d2[4], y2_ptr[1]);
487
488             d1[3] = d1[7] = d2[3] = d2[7] = 255;
489
490             d1 += 8;
491             d2 += 8;
492             y1_ptr += 2;
493             y2_ptr += 2;
494             cb_ptr++;
495             cr_ptr++;
496         }
497         d += 2 * dst->linesize[0];
498         y1_ptr += 2 * src->linesize[0] - width;
499         cb_ptr += src->linesize[1] - width2;
500         cr_ptr += src->linesize[2] - width2;
501     }
502 }
503
504 /* XXX: no chroma interpolating is done */
505 static void yuv420p_to_rgba32(AVPicture *dst, AVPicture *src, 
506                              int width, int height)
507 {
508     UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
509     int w, y, cb, cr, r_add, g_add, b_add, width2;
510     UINT8 *cm = cropTbl + MAX_NEG_CROP;
511
512     d = dst->data[0];
513     y1_ptr = src->data[0];
514     cb_ptr = src->data[1];
515     cr_ptr = src->data[2];
516     width2 = width >> 1;
517     for(;height > 0; height -= 2) {
518         d1 = d;
519         d2 = d + dst->linesize[0];
520         y2_ptr = y1_ptr + src->linesize[0];
521         for(w = width2; w > 0; w --) {
522             cb = cb_ptr[0] - 128;
523             cr = cr_ptr[0] - 128;
524             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
525             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
526             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
527             
528             /* output 4 pixels */
529             RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
530             RGBOUT(d1[4], d1[5], d1[6], y1_ptr[1]);
531             RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
532             RGBOUT(d2[4], d2[5], d2[6], y2_ptr[1]);
533
534             d1[3] = d1[7] = d2[3] = d2[7] = 255;
535
536             d1 += 8;
537             d2 += 8;
538             y1_ptr += 2;
539             y2_ptr += 2;
540             cb_ptr++;
541             cr_ptr++;
542         }
543         d += 2 * dst->linesize[0];
544         y1_ptr += 2 * src->linesize[0] - width;
545         cb_ptr += src->linesize[1] - width2;
546         cr_ptr += src->linesize[2] - width2;
547     }
548 }
549
550 /* XXX: no chroma interpolating is done */
551 static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src, 
552                              int width, int height)
553 {
554     UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
555     int w, y, cb, cr, r_add, g_add, b_add, width2;
556     UINT8 *cm = cropTbl + MAX_NEG_CROP;
557
558     d = dst->data[0];
559     y1_ptr = src->data[0];
560     cb_ptr = src->data[1];
561     cr_ptr = src->data[2];
562     width2 = width >> 1;
563     for(;height > 0; height -= 2) {
564         d1 = d;
565         d2 = d + dst->linesize[0];
566         y2_ptr = y1_ptr + src->linesize[0];
567         for(w = width2; w > 0; w --) {
568             cb = cb_ptr[0] - 128;
569             cr = cr_ptr[0] - 128;
570             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
571             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
572             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
573             
574             /* output 4 pixels */
575             RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
576             RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
577             RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
578             RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
579
580             d1 += 6;
581             d2 += 6;
582             y1_ptr += 2;
583             y2_ptr += 2;
584             cb_ptr++;
585             cr_ptr++;
586         }
587         d += 2 * dst->linesize[0];
588         y1_ptr += 2 * src->linesize[0] - width;
589         cb_ptr += src->linesize[1] - width2;
590         cr_ptr += src->linesize[2] - width2;
591     }
592 }
593
594 /* XXX: no chroma interpolating is done */
595 static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src, 
596                              int width, int height)
597 {
598     UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
599     int w, y, cb, cr, r_add, g_add, b_add, width2;
600     UINT8 *cm = cropTbl + MAX_NEG_CROP;
601
602     d = dst->data[0];
603     y1_ptr = src->data[0];
604     cb_ptr = src->data[1];
605     cr_ptr = src->data[2];
606     width2 = width >> 1;
607     for(;height > 0; height --) {
608         d1 = d;
609         for(w = width2; w > 0; w --) {
610             cb = cb_ptr[0] - 128;
611             cr = cr_ptr[0] - 128;
612             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
613             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
614             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
615             
616             /* output 2 pixels */
617             RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
618             RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
619
620             d1 += 6;
621             y1_ptr += 2;
622             cb_ptr++;
623             cr_ptr++;
624         }
625         d += dst->linesize[0];
626         y1_ptr += src->linesize[0] - width;
627         cb_ptr += src->linesize[1] - width2;
628         cr_ptr += src->linesize[2] - width2;
629     }
630 }
631
632 /* XXX: always use linesize. Return -1 if not supported */
633 int img_convert(AVPicture *dst, int dst_pix_fmt,
634                 AVPicture *src, int pix_fmt, 
635                 int width, int height)
636 {
637     int i;
638
639     assert(pix_fmt != PIX_FMT_ANY && dst_pix_fmt != PIX_FMT_ANY);
640
641     if (dst_pix_fmt == pix_fmt) {
642         switch(pix_fmt) {
643         case PIX_FMT_YUV420P:
644             for(i=0;i<3;i++) {
645                 if (i == 1) {
646                     width >>= 1;
647                     height >>= 1;
648                 }
649                 img_copy(dst->data[i], dst->linesize[i],
650                          src->data[i], src->linesize[i],
651                          width, height);
652             }
653             break;
654         default:
655             return -1;
656         }
657     } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
658         
659         switch(pix_fmt) {
660         case PIX_FMT_YUV411P:
661             img_copy(dst->data[0], dst->linesize[0],
662                      src->data[0], src->linesize[0],
663                      width, height);
664             conv411(dst->data[1], dst->linesize[1],
665                     src->data[1], src->linesize[1],
666                     width / 4, height);
667             conv411(dst->data[2], dst->linesize[2],
668                     src->data[2], src->linesize[2],
669                     width / 4, height);
670             break;
671         case PIX_FMT_YUV410P:
672             img_copy(dst->data[0], dst->linesize[0],
673                      src->data[0], src->linesize[0],
674                      width, height);
675             grow22(dst->data[1], dst->linesize[1],
676                      src->data[1], src->linesize[1],
677                      width/2, height/2);
678             grow22(dst->data[2], dst->linesize[2],
679                      src->data[2], src->linesize[2],
680                      width/2, height/2);
681             break;
682         case PIX_FMT_YUV420P:
683             for(i=0;i<3;i++) {
684                 img_copy(dst->data[i], dst->linesize[i],
685                          src->data[i], src->linesize[i],
686                          width, height);
687             }
688             break;
689         case PIX_FMT_YUV422P:
690             img_copy(dst->data[0], dst->linesize[0],
691                      src->data[0], src->linesize[0],
692                      width, height);
693             width >>= 1;
694             height >>= 1;
695             for(i=1;i<3;i++) {
696                 shrink2(dst->data[i], dst->linesize[i],
697                         src->data[i], src->linesize[i],
698                         width, height);
699             }
700             break;
701         case PIX_FMT_YUV444P:
702             img_copy(dst->data[0], dst->linesize[0],
703                      src->data[0], src->linesize[0],
704                      width, height);
705             width >>= 1;
706             height >>= 1;
707             for(i=1;i<3;i++) {
708                 shrink22(dst->data[i], dst->linesize[i],
709                          src->data[i], src->linesize[i],
710                          width, height);
711             }
712             break;
713         case PIX_FMT_YUV422:
714             yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
715                               src->data[0], width, height);
716             break;
717         case PIX_FMT_RGB24:
718             rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
719                              src->data[0], width, height);
720             break;
721         case PIX_FMT_RGBA32:
722             rgba32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
723                              src->data[0], width, height);
724             break;
725         case PIX_FMT_BGR24:
726             bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
727                              src->data[0], width, height);
728             break;
729         case PIX_FMT_BGRA32:
730             bgra32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
731                              src->data[0], width, height);
732             break;
733         default:
734             return -1;
735         }
736     } else if (dst_pix_fmt == PIX_FMT_RGB24) {
737         switch(pix_fmt) {
738         case PIX_FMT_YUV420P:
739             yuv420p_to_rgb24(dst, src, width, height);
740             break;
741         case PIX_FMT_YUV422P:
742             yuv422p_to_rgb24(dst, src, width, height);
743             break;
744         default:
745             return -1;
746         }
747     } else if (dst_pix_fmt == PIX_FMT_RGBA32) {
748         switch(pix_fmt) {
749         case PIX_FMT_YUV420P:
750             yuv420p_to_rgba32(dst, src, width, height);
751             break;
752         default:
753             return -1;
754         }
755     } else if (dst_pix_fmt == PIX_FMT_BGRA32) {
756         switch(pix_fmt) {
757         case PIX_FMT_YUV420P:
758             yuv420p_to_bgra32(dst, src, width, height);
759             break;
760         default:
761             return -1;
762         }
763     } else {
764         return -1;
765     }
766     return 0;
767 }
768
769
770 #ifdef HAVE_MMX
771 #define DEINT_INPLACE_LINE_LUM \
772                     movd_m2r(lum_m4[0],mm0);\
773                     movd_m2r(lum_m3[0],mm1);\
774                     movd_m2r(lum_m2[0],mm2);\
775                     movd_m2r(lum_m1[0],mm3);\
776                     movd_m2r(lum[0],mm4);\
777                     punpcklbw_r2r(mm7,mm0);\
778                     movd_r2m(mm2,lum_m4[0]);\
779                     punpcklbw_r2r(mm7,mm1);\
780                     punpcklbw_r2r(mm7,mm2);\
781                     punpcklbw_r2r(mm7,mm3);\
782                     punpcklbw_r2r(mm7,mm4);\
783                     paddw_r2r(mm3,mm1);\
784                     psllw_i2r(1,mm2);\
785                     paddw_r2r(mm4,mm0);\
786                     psllw_i2r(2,mm1);\
787                     paddw_r2r(mm6,mm2);\
788                     paddw_r2r(mm2,mm1);\
789                     psubusw_r2r(mm0,mm1);\
790                     psrlw_i2r(3,mm1);\
791                     packuswb_r2r(mm7,mm1);\
792                     movd_r2m(mm1,lum_m2[0]);
793
794 #define DEINT_LINE_LUM \
795                     movd_m2r(lum_m4[0],mm0);\
796                     movd_m2r(lum_m3[0],mm1);\
797                     movd_m2r(lum_m2[0],mm2);\
798                     movd_m2r(lum_m1[0],mm3);\
799                     movd_m2r(lum[0],mm4);\
800                     punpcklbw_r2r(mm7,mm0);\
801                     punpcklbw_r2r(mm7,mm1);\
802                     punpcklbw_r2r(mm7,mm2);\
803                     punpcklbw_r2r(mm7,mm3);\
804                     punpcklbw_r2r(mm7,mm4);\
805                     paddw_r2r(mm3,mm1);\
806                     psllw_i2r(1,mm2);\
807                     paddw_r2r(mm4,mm0);\
808                     psllw_i2r(2,mm1);\
809                     paddw_r2r(mm6,mm2);\
810                     paddw_r2r(mm2,mm1);\
811                     psubusw_r2r(mm0,mm1);\
812                     psrlw_i2r(3,mm1);\
813                     packuswb_r2r(mm7,mm1);\
814                     movd_r2m(mm1,dst[0]);
815 #endif
816
817 /* filter parameters: [-1 4 2 4 -1] // 8 */
818 static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
819                                 int size)
820 {
821 #ifndef HAVE_MMX
822     UINT8 *cm = cropTbl + MAX_NEG_CROP;
823     int sum;
824
825     for(;size > 0;size--) {
826         sum = -lum_m4[0];
827         sum += lum_m3[0] << 2;
828         sum += lum_m2[0] << 1;
829         sum += lum_m1[0] << 2;
830         sum += -lum[0];
831         dst[0] = cm[(sum + 4) >> 3];
832         lum_m4++;
833         lum_m3++;
834         lum_m2++;
835         lum_m1++;
836         lum++;
837         dst++;
838     }
839 #else
840
841     for (;size > 3; size-=4) {
842         DEINT_LINE_LUM
843         lum_m4+=4;
844         lum_m3+=4;
845         lum_m2+=4;
846         lum_m1+=4;
847         lum+=4;
848         dst+=4;
849     }
850 #endif
851 }
852 static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
853                              int size)
854 {
855 #ifndef HAVE_MMX
856     UINT8 *cm = cropTbl + MAX_NEG_CROP;
857     int sum;
858
859     for(;size > 0;size--) {
860         sum = -lum_m4[0];
861         sum += lum_m3[0] << 2;
862         sum += lum_m2[0] << 1;
863         lum_m4[0]=lum_m2[0];
864         sum += lum_m1[0] << 2;
865         sum += -lum[0];
866         lum_m2[0] = cm[(sum + 4) >> 3];
867         lum_m4++;
868         lum_m3++;
869         lum_m2++;
870         lum_m1++;
871         lum++;
872     }
873 #else
874
875     for (;size > 3; size-=4) {
876         DEINT_INPLACE_LINE_LUM
877         lum_m4+=4;
878         lum_m3+=4;
879         lum_m2+=4;
880         lum_m1+=4;
881         lum+=4;
882     }
883 #endif
884 }
885
886 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
887    top field is copied as is, but the bottom field is deinterlaced
888    against the top field. */
889 static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
890                                     UINT8 *src1, int src_wrap,
891                                     int width, int height)
892 {
893     UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
894     int y;
895
896     src_m2 = src1;
897     src_m1 = src1;
898     src_0=&src_m1[src_wrap];
899     src_p1=&src_0[src_wrap];
900     src_p2=&src_p1[src_wrap];
901     for(y=0;y<(height-2);y+=2) {
902         memcpy(dst,src_m1,width);
903         dst += dst_wrap;
904         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
905         src_m2 = src_0;
906         src_m1 = src_p1;
907         src_0 = src_p2;
908         src_p1 += 2*src_wrap;
909         src_p2 += 2*src_wrap;
910         dst += dst_wrap;
911     }
912     memcpy(dst,src_m1,width);
913     dst += dst_wrap;
914     /* do last line */
915     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
916 }
917
918 static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
919                                      int width, int height)
920 {
921     UINT8 *src_m1, *src_0, *src_p1, *src_p2;
922     int y;
923     UINT8 *buf;
924     buf = (UINT8*)av_malloc(width);
925
926     src_m1 = src1;
927     memcpy(buf,src_m1,width);
928     src_0=&src_m1[src_wrap];
929     src_p1=&src_0[src_wrap];
930     src_p2=&src_p1[src_wrap];
931     for(y=0;y<(height-2);y+=2) {
932         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
933         src_m1 = src_p1;
934         src_0 = src_p2;
935         src_p1 += 2*src_wrap;
936         src_p2 += 2*src_wrap;
937     }
938     /* do last line */
939     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
940     av_free(buf);
941 }
942
943
944 /* deinterlace - if not supported return -1 */
945 int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
946                           int pix_fmt, int width, int height)
947 {
948     int i;
949
950     if (pix_fmt != PIX_FMT_YUV420P &&
951         pix_fmt != PIX_FMT_YUV422P &&
952         pix_fmt != PIX_FMT_YUV444P)
953         return -1;
954     if ((width & 3) != 0 || (height & 3) != 0)
955         return -1;
956
957 #ifdef HAVE_MMX
958     {
959         mmx_t rounder;
960         rounder.uw[0]=4;
961         rounder.uw[1]=4;
962         rounder.uw[2]=4;
963         rounder.uw[3]=4;
964         pxor_r2r(mm7,mm7);
965         movq_m2r(rounder,mm6);
966     }
967 #endif
968
969     
970     for(i=0;i<3;i++) {
971         if (i == 1) {
972             switch(pix_fmt) {
973             case PIX_FMT_YUV420P:
974                 width >>= 1;
975                 height >>= 1;
976                 break;
977             case PIX_FMT_YUV422P:
978                 width >>= 1;
979                 break;
980             default:
981                 break;
982             }
983         }
984         if (src == dst) {
985             deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
986                                  width, height);
987         } else {
988             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
989                                         src->data[i], src->linesize[i],
990                                         width, height);
991         }
992     }
993 #ifdef HAVE_MMX
994     emms();
995 #endif
996     return 0;
997 }
998
999 #undef FIX