fixed static init
[libav.git] / libavcodec / imgconvert.c
CommitLineData
de6d9b64
FB
1/*
2 * Misc image convertion routines
524c6b63 3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
de6d9b64 4 *
ff4ec49e
FB
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.
de6d9b64 9 *
ff4ec49e 10 * This library is distributed in the hope that it will be useful,
de6d9b64 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ff4ec49e
FB
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
de6d9b64 14 *
ff4ec49e
FB
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
de6d9b64 18 */
983e3246
MN
19
20/**
1ab3d669 21 * @file imgconvert.c
983e3246
MN
22 * Misc image convertion routines.
23 */
24
25
de6d9b64 26#include "avcodec.h"
85c242d8 27#include "dsputil.h"
de6d9b64 28
54329dd5
NK
29#ifdef USE_FASTMEMCPY
30#include "fastmemcpy.h"
31#endif
5981f4e6
F
32
33#ifdef HAVE_MMX
34#include "i386/mmx.h"
35#endif
524c6b63
FB
36
37typedef struct PixFmtInfo {
38 const char *name;
0c1a9eda
ZK
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 */
524c6b63
FB
47} PixFmtInfo;
48
49/* this table gives more information about formats */
50static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
51 /* YUV formats */
52 [PIX_FMT_YUV420P] = {
ef9f7306
MR
53 .name = "yuv420p",
54 .nb_components = 3, .is_yuv = 1,
55 .x_chroma_shift = 1, .y_chroma_shift = 1,
524c6b63
FB
56 },
57 [PIX_FMT_YUV422P] = {
ef9f7306
MR
58 .name = "yuv422p",
59 .nb_components = 3, .is_yuv = 1,
60 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
61 },
62 [PIX_FMT_YUV444P] = {
ef9f7306
MR
63 .name = "yuv444p",
64 .nb_components = 3, .is_yuv = 1,
65 .x_chroma_shift = 0, .y_chroma_shift = 0,
524c6b63
FB
66 },
67 [PIX_FMT_YUV422] = {
ef9f7306
MR
68 .name = "yuv422",
69 .nb_components = 1, .is_yuv = 1, .is_packed = 1,
70 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
71 },
72 [PIX_FMT_YUV410P] = {
ef9f7306
MR
73 .name = "yuv410p",
74 .nb_components = 3, .is_yuv = 1,
75 .x_chroma_shift = 2, .y_chroma_shift = 2,
524c6b63
FB
76 },
77 [PIX_FMT_YUV411P] = {
ef9f7306
MR
78 .name = "yuv411p",
79 .nb_components = 3, .is_yuv = 1,
80 .x_chroma_shift = 2, .y_chroma_shift = 0,
524c6b63
FB
81 },
82
83 /* RGB formats */
84 [PIX_FMT_RGB24] = {
ef9f7306
MR
85 .name = "rgb24",
86 .nb_components = 1, .is_packed = 1,
524c6b63
FB
87 },
88 [PIX_FMT_BGR24] = {
ef9f7306
MR
89 .name = "bgr24",
90 .nb_components = 1, .is_packed = 1,
524c6b63
FB
91 },
92 [PIX_FMT_RGBA32] = {
ef9f7306
MR
93 .name = "rgba32",
94 .nb_components = 1, .is_packed = 1, .is_alpha = 1,
524c6b63
FB
95 },
96 [PIX_FMT_RGB565] = {
ef9f7306
MR
97 .name = "rgb565",
98 .nb_components = 1, .is_packed = 1,
524c6b63
FB
99 },
100 [PIX_FMT_RGB555] = {
ef9f7306
MR
101 .name = "rgb555",
102 .nb_components = 1, .is_packed = 1, .is_alpha = 1,
524c6b63
FB
103 },
104
105 /* gray / mono formats */
106 [PIX_FMT_GRAY8] = {
ef9f7306
MR
107 .name = "gray",
108 .nb_components = 1, .is_gray = 1,
524c6b63
FB
109 },
110 [PIX_FMT_MONOWHITE] = {
ef9f7306
MR
111 .name = "monow",
112 .nb_components = 1, .is_packed = 1, .is_gray = 1,
524c6b63
FB
113 },
114 [PIX_FMT_MONOBLACK] = {
ef9f7306
MR
115 .name = "monob",
116 .nb_components = 1, .is_packed = 1, .is_gray = 1,
524c6b63 117 },
7e6d70d0
FB
118
119 /* paletted formats */
120 [PIX_FMT_PAL8] = {
121 .name = "pal8",
6d93f194 122 .nb_components = 1, .is_packed = 1, .is_alpha = 1, .is_paletted = 1,
7e6d70d0 123 },
524c6b63
FB
124};
125
126void 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
137const 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
2a877875 145/* Picture field are filled with 'ptr' addresses. Also return size */
0c1a9eda 146int avpicture_fill(AVPicture *picture, uint8_t *ptr,
2a877875
FB
147 int pix_fmt, int width, int height)
148{
4c7e8619
FB
149 int size, w2, h2, size2;
150 PixFmtInfo *pinfo;
151
152 pinfo = &pix_fmt_info[pix_fmt];
2a877875
FB
153 size = width * height;
154 switch(pix_fmt) {
155 case PIX_FMT_YUV420P:
4c7e8619
FB
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;
2a877875
FB
163 picture->data[0] = ptr;
164 picture->data[1] = picture->data[0] + size;
4c7e8619 165 picture->data[2] = picture->data[1] + size2;
2a877875 166 picture->linesize[0] = width;
4c7e8619
FB
167 picture->linesize[1] = w2;
168 picture->linesize[2] = w2;
169 return size + 2 * size2;
2a877875
FB
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;
2a877875
FB
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;
2a877875
FB
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;
7e6d70d0
FB
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;
2a877875
FB
212 default:
213 picture->data[0] = NULL;
214 picture->data[1] = NULL;
215 picture->data[2] = NULL;
7e6d70d0 216 picture->data[3] = NULL;
2a877875
FB
217 return -1;
218 }
219}
220
221int 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
de6d9b64
FB
228/* XXX: totally non optimized */
229
524c6b63
FB
230static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
231 int width, int height)
de6d9b64 232{
0c1a9eda 233 uint8_t *lum, *cb, *cr;
de6d9b64 234 int x, y;
0c1a9eda 235 const uint8_t *p;
524c6b63
FB
236
237 lum = dst->data[0];
238 cb = dst->data[1];
239 cr = dst->data[2];
240 p = src->data[0];
241
de6d9b64
FB
242 for(y=0;y<height;y+=2) {
243 for(x=0;x<width;x+=2) {
e78df699
MN
244 lum[0] = p[0];
245 cb[0] = p[1];
246 lum[1] = p[2];
247 cr[0] = p[3];
de6d9b64
FB
248 p += 4;
249 lum += 2;
250 cb++;
251 cr++;
252 }
253 for(x=0;x<width;x+=2) {
e78df699
MN
254 lum[0] = p[0];
255 lum[1] = p[2];
de6d9b64
FB
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
85c242d8
FB
266/* XXX: use generic filter ? */
267/* 1x2 -> 1x1 */
0c1a9eda
ZK
268static void shrink2(uint8_t *dst, int dst_wrap,
269 uint8_t *src, int src_wrap,
85c242d8
FB
270 int width, int height)
271{
272 int w;
0c1a9eda 273 uint8_t *s1, *s2, *d;
85c242d8
FB
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 */
0c1a9eda
ZK
300static void shrink22(uint8_t *dst, int dst_wrap,
301 uint8_t *src, int src_wrap,
85c242d8
FB
302 int width, int height)
303{
304 int w;
0c1a9eda 305 uint8_t *s1, *s2, *d;
85c242d8
FB
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
6742d95d 331/* 1x1 -> 2x2 */
0c1a9eda
ZK
332static void grow22(uint8_t *dst, int dst_wrap,
333 uint8_t *src, int src_wrap,
6742d95d
FR
334 int width, int height)
335{
336 int w;
0c1a9eda 337 uint8_t *s1, *d;
6742d95d
FR
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
524c6b63 359/* 1x2 -> 2x1 */
0c1a9eda
ZK
360static void conv411(uint8_t *dst, int dst_wrap,
361 uint8_t *src, int src_wrap,
789587d5
FB
362 int width, int height)
363{
364 int w, c;
0c1a9eda 365 uint8_t *s1, *s2, *d;
789587d5 366
50643575
MN
367 width>>=1;
368
524c6b63 369 for(;height > 0; height--) {
789587d5
FB
370 s1 = src;
371 s2 = src + src_wrap;
372 d = dst;
373 for(w = width;w > 0; w--) {
374 c = (s1[0] + s2[0]) >> 1;
375 d[0] = c;
376 d[1] = c;
377 s1++;
378 s2++;
379 d += 2;
380 }
381 src += src_wrap * 2;
382 dst += dst_wrap;
383 }
384}
385
0c1a9eda
ZK
386static void img_copy(uint8_t *dst, int dst_wrap,
387 uint8_t *src, int src_wrap,
85c242d8
FB
388 int width, int height)
389{
390 for(;height > 0; height--) {
391 memcpy(dst, src, width);
392 dst += dst_wrap;
393 src += src_wrap;
394 }
395}
396
397#define SCALE_BITS 10
398
399#define C_Y (76309 >> (16 - SCALE_BITS))
400#define C_RV (117504 >> (16 - SCALE_BITS))
401#define C_BU (138453 >> (16 - SCALE_BITS))
402#define C_GU (13954 >> (16 - SCALE_BITS))
403#define C_GV (34903 >> (16 - SCALE_BITS))
404
524c6b63 405#define YUV_TO_RGB2(r, g, b, y1)\
85c242d8
FB
406{\
407 y = (y1 - 16) * C_Y;\
408 r = cm[(y + r_add) >> SCALE_BITS];\
409 g = cm[(y + g_add) >> SCALE_BITS];\
410 b = cm[(y + b_add) >> SCALE_BITS];\
411}
412
413/* XXX: no chroma interpolating is done */
524c6b63
FB
414#define RGB_FUNCTIONS(rgb_name) \
415 \
416static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
417 int width, int height) \
418{ \
0c1a9eda 419 uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \
524c6b63 420 int w, y, cb, cr, r_add, g_add, b_add, width2; \
0c1a9eda 421 uint8_t *cm = cropTbl + MAX_NEG_CROP; \
524c6b63
FB
422 unsigned int r, g, b; \
423 \
424 d = dst->data[0]; \
425 y1_ptr = src->data[0]; \
426 cb_ptr = src->data[1]; \
427 cr_ptr = src->data[2]; \
4c7e8619
FB
428 width2 = (width + 1) >> 1; \
429 for(;height >= 2; height -= 2) { \
524c6b63
FB
430 d1 = d; \
431 d2 = d + dst->linesize[0]; \
432 y2_ptr = y1_ptr + src->linesize[0]; \
4c7e8619 433 for(w = width; w >= 2; w -= 2) { \
524c6b63
FB
434 cb = cb_ptr[0] - 128; \
435 cr = cr_ptr[0] - 128; \
436 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
437 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
438 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
439 \
440 /* output 4 pixels */ \
441 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
442 RGB_OUT(d1, r, g, b); \
443 \
444 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
445 RGB_OUT(d1 + BPP, r, g, b); \
446 \
447 YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
448 RGB_OUT(d2, r, g, b); \
449 \
450 YUV_TO_RGB2(r, g, b, y2_ptr[1]); \
451 RGB_OUT(d2 + BPP, r, g, b); \
452 \
453 d1 += 2 * BPP; \
454 d2 += 2 * BPP; \
455 \
456 y1_ptr += 2; \
457 y2_ptr += 2; \
458 cb_ptr++; \
459 cr_ptr++; \
460 } \
4c7e8619
FB
461 /* handle odd width */ \
462 if (w) { \
463 cb = cb_ptr[0] - 128; \
464 cr = cr_ptr[0] - 128; \
465 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
466 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
467 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
468 \
469 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
470 RGB_OUT(d1, r, g, b); \
471 \
472 YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
473 RGB_OUT(d2, r, g, b); \
474 d1 += BPP; \
475 d2 += BPP; \
476 y1_ptr++; \
477 y2_ptr++; \
478 cb_ptr++; \
479 cr_ptr++; \
480 } \
524c6b63
FB
481 d += 2 * dst->linesize[0]; \
482 y1_ptr += 2 * src->linesize[0] - width; \
483 cb_ptr += src->linesize[1] - width2; \
484 cr_ptr += src->linesize[2] - width2; \
485 } \
4c7e8619
FB
486 /* handle odd height */ \
487 if (height) { \
488 d1 = d; \
489 for(w = width; w >= 2; w -= 2) { \
490 cb = cb_ptr[0] - 128; \
491 cr = cr_ptr[0] - 128; \
492 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
493 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
494 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
495 \
496 /* output 2 pixels */ \
497 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
498 RGB_OUT(d1, r, g, b); \
499 \
500 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
501 RGB_OUT(d1 + BPP, r, g, b); \
502 \
503 d1 += 2 * BPP; \
504 \
505 y1_ptr += 2; \
506 cb_ptr++; \
507 cr_ptr++; \
508 } \
509 /* handle width */ \
510 if (w) { \
511 cb = cb_ptr[0] - 128; \
512 cr = cr_ptr[0] - 128; \
513 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
514 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
515 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
516 \
517 /* output 2 pixels */ \
518 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
519 RGB_OUT(d1, r, g, b); \
520 d1 += BPP; \
521 \
522 y1_ptr++; \
523 cb_ptr++; \
524 cr_ptr++; \
525 } \
526 } \
524c6b63
FB
527} \
528 \
529/* XXX: no chroma interpolating is done */ \
530static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
531 int width, int height) \
532{ \
0c1a9eda 533 uint8_t *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \
524c6b63 534 int w, y, cb, cr, r_add, g_add, b_add, width2; \
0c1a9eda 535 uint8_t *cm = cropTbl + MAX_NEG_CROP; \
524c6b63
FB
536 unsigned int r, g, b; \
537 \
538 d = dst->data[0]; \
539 y1_ptr = src->data[0]; \
540 cb_ptr = src->data[1]; \
541 cr_ptr = src->data[2]; \
4c7e8619 542 width2 = (width + 1) >> 1; \
524c6b63
FB
543 for(;height > 0; height --) { \
544 d1 = d; \
4c7e8619 545 for(w = width; w >= 2; w -= 2) { \
524c6b63
FB
546 cb = cb_ptr[0] - 128; \
547 cr = cr_ptr[0] - 128; \
548 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
549 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
550 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
551 \
552 /* output 2 pixels */ \
553 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
4c7e8619 554 RGB_OUT(d1, r, g, b); \
524c6b63
FB
555 \
556 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
4c7e8619 557 RGB_OUT(d1 + BPP, r, g, b); \
524c6b63 558 \
4c7e8619 559 d1 += 2 * BPP; \
524c6b63
FB
560 \
561 y1_ptr += 2; \
562 cb_ptr++; \
563 cr_ptr++; \
564 } \
4c7e8619
FB
565 /* handle width */ \
566 if (w) { \
567 cb = cb_ptr[0] - 128; \
568 cr = cr_ptr[0] - 128; \
569 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
570 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
571 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
572 \
573 /* output 2 pixels */ \
574 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
575 RGB_OUT(d1, r, g, b); \
576 d1 += BPP; \
577 \
578 y1_ptr++; \
579 cb_ptr++; \
580 cr_ptr++; \
581 } \
524c6b63
FB
582 d += dst->linesize[0]; \
583 y1_ptr += src->linesize[0] - width; \
584 cb_ptr += src->linesize[1] - width2; \
585 cr_ptr += src->linesize[2] - width2; \
586 } \
587} \
588 \
589static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \
590 int width, int height) \
591{ \
592 int wrap, wrap3, x, y; \
593 int r, g, b, r1, g1, b1; \
0c1a9eda
ZK
594 uint8_t *lum, *cb, *cr; \
595 const uint8_t *p; \
524c6b63
FB
596 \
597 lum = dst->data[0]; \
598 cb = dst->data[1]; \
599 cr = dst->data[2]; \
600 \
16e83cbb
PG
601 wrap = dst->linesize[0]; \
602 wrap3 = src->linesize[0]; \
524c6b63
FB
603 p = src->data[0]; \
604 for(y=0;y<height;y+=2) { \
605 for(x=0;x<width;x+=2) { \
606 RGB_IN(r, g, b, p); \
607 r1 = r; \
608 g1 = g; \
609 b1 = b; \
610 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
611 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
612 RGB_IN(r, g, b, p + BPP); \
613 r1 += r; \
614 g1 += g; \
615 b1 += b; \
616 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
617 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
618 p += wrap3; \
619 lum += wrap; \
620 \
621 RGB_IN(r, g, b, p); \
622 r1 += r; \
623 g1 += g; \
624 b1 += b; \
625 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
626 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
627 \
628 RGB_IN(r, g, b, p + BPP); \
629 r1 += r; \
630 g1 += g; \
631 b1 += b; \
632 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
633 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
634 \
635 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
636 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \
637 (SCALEBITS + 2)) + 128; \
638 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
639 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \
640 (SCALEBITS + 2)) + 128; \
641 \
642 cb++; \
643 cr++; \
69572401 644 p += -wrap3 + 2 * BPP; \
524c6b63
FB
645 lum += -wrap + 2; \
646 } \
16e83cbb
PG
647 p += wrap3 + (wrap3 - width * BPP); \
648 lum += wrap + (wrap - width); \
649 cb += dst->linesize[1] - width / 2; \
650 cr += dst->linesize[2] - width / 2; \
524c6b63 651 } \
69572401
FB
652} \
653 \
654static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src, \
655 int width, int height) \
656{ \
657 const unsigned char *p; \
658 unsigned char *q; \
659 int r, g, b, dst_wrap, src_wrap; \
660 int x, y; \
661 \
662 p = src->data[0]; \
663 src_wrap = src->linesize[0] - BPP * width; \
664 \
665 q = dst->data[0]; \
666 dst_wrap = dst->linesize[0] - width; \
667 \
668 for(y=0;y<height;y++) { \
669 for(x=0;x<width;x++) { \
670 RGB_IN(r, g, b, p); \
671 q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
672 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
673 q++; \
674 p += BPP; \
675 } \
676 p += src_wrap; \
677 q += dst_wrap; \
678 } \
679} \
680 \
681static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
682 int width, int height) \
683{ \
684 const unsigned char *p; \
685 unsigned char *q; \
686 int r, dst_wrap, src_wrap; \
687 int x, y; \
688 \
689 p = src->data[0]; \
690 src_wrap = src->linesize[0] - width; \
691 \
692 q = dst->data[0]; \
693 dst_wrap = dst->linesize[0] - BPP * width; \
694 \
695 for(y=0;y<height;y++) { \
696 for(x=0;x<width;x++) { \
697 r = p[0]; \
698 RGB_OUT(q, r, r, r); \
699 q += BPP; \
700 p ++; \
701 } \
702 p += src_wrap; \
703 q += dst_wrap; \
704 } \
7e6d70d0
FB
705} \
706 \
707static void pal8_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
708 int width, int height) \
709{ \
710 const unsigned char *p; \
711 unsigned char *q; \
712 int r, g, b, dst_wrap, src_wrap; \
713 int x, y; \
714 uint32_t v;\
715 const uint32_t *palette;\
716\
717 p = src->data[0]; \
718 src_wrap = src->linesize[0] - width; \
719 palette = (uint32_t *)src->data[1];\
720 \
721 q = dst->data[0]; \
722 dst_wrap = dst->linesize[0] - BPP * width; \
723 \
724 for(y=0;y<height;y++) { \
725 for(x=0;x<width;x++) { \
726 v = palette[p[0]];\
727 r = (v >> 16) & 0xff;\
728 g = (v >> 8) & 0xff;\
729 b = (v) & 0xff;\
730 RGB_OUT(q, r, g, b); \
731 q += BPP; \
732 p ++; \
733 } \
734 p += src_wrap; \
735 q += dst_wrap; \
736 } \
524c6b63
FB
737}
738
739/* copy bit n to bits 0 ... n - 1 */
740static inline unsigned int bitcopy_n(unsigned int a, int n)
b71472eb 741{
524c6b63
FB
742 int mask;
743 mask = (1 << n) - 1;
744 return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
745}
746
747/* rgb555 handling */
748
749#define RGB_IN(r, g, b, s)\
750{\
0c1a9eda 751 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
752 r = bitcopy_n(v >> (10 - 3), 3);\
753 g = bitcopy_n(v >> (5 - 3), 3);\
754 b = bitcopy_n(v << 3, 3);\
755}
756
757#define RGB_OUT(d, r, g, b)\
758{\
0c1a9eda 759 ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
524c6b63
FB
760}
761
762#define BPP 2
763
764RGB_FUNCTIONS(rgb555)
765
766#undef RGB_IN
767#undef RGB_OUT
768#undef BPP
769
770/* rgb565 handling */
771
772#define RGB_IN(r, g, b, s)\
773{\
0c1a9eda 774 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
775 r = bitcopy_n(v >> (11 - 3), 3);\
776 g = bitcopy_n(v >> (5 - 2), 2);\
777 b = bitcopy_n(v << 3, 3);\
778}
779
780#define RGB_OUT(d, r, g, b)\
781{\
0c1a9eda 782 ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
524c6b63
FB
783}
784
785#define BPP 2
786
787RGB_FUNCTIONS(rgb565)
788
789#undef RGB_IN
790#undef RGB_OUT
791#undef BPP
792
793/* bgr24 handling */
794
795#define RGB_IN(r, g, b, s)\
796{\
797 b = (s)[0];\
798 g = (s)[1];\
799 r = (s)[2];\
800}
801
802#define RGB_OUT(d, r, g, b)\
803{\
804 (d)[0] = b;\
805 (d)[1] = g;\
806 (d)[2] = r;\
807}
808
809#define BPP 3
810
811RGB_FUNCTIONS(bgr24)
812
813#undef RGB_IN
814#undef RGB_OUT
815#undef BPP
816
817/* rgb24 handling */
818
819#define RGB_IN(r, g, b, s)\
820{\
821 r = (s)[0];\
822 g = (s)[1];\
823 b = (s)[2];\
824}
825
826#define RGB_OUT(d, r, g, b)\
827{\
828 (d)[0] = r;\
829 (d)[1] = g;\
830 (d)[2] = b;\
831}
832
833#define BPP 3
834
835RGB_FUNCTIONS(rgb24)
836
837#undef RGB_IN
838#undef RGB_OUT
839#undef BPP
840
841/* rgba32 handling */
842
843#define RGB_IN(r, g, b, s)\
844{\
0c1a9eda 845 unsigned int v = ((const uint32_t *)(s))[0];\
524c6b63
FB
846 r = (v >> 16) & 0xff;\
847 g = (v >> 8) & 0xff;\
848 b = v & 0xff;\
849}
850
851#define RGB_OUT(d, r, g, b)\
852{\
0c1a9eda 853 ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
524c6b63
FB
854}
855
856#define BPP 4
857
858RGB_FUNCTIONS(rgba32)
859
860#undef RGB_IN
861#undef RGB_OUT
862#undef BPP
863
864
865static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
866 int width, int height)
867{
868 const unsigned char *p;
869 unsigned char *q;
870 int r, g, b, dst_wrap, src_wrap;
871 int x, y;
872
873 p = src->data[0];
874 src_wrap = src->linesize[0] - 3 * width;
875
876 q = dst->data[0];
877 dst_wrap = dst->linesize[0] - 2 * width;
878
879 for(y=0;y<height;y++) {
880 for(x=0;x<width;x++) {
881 r = p[0];
882 g = p[1];
883 b = p[2];
884
885 ((unsigned short *)q)[0] =
886 ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
887 q += 2;
888 p += 3;
b71472eb 889 }
524c6b63
FB
890 p += src_wrap;
891 q += dst_wrap;
b71472eb
PG
892 }
893}
894
524c6b63
FB
895/* NOTE: we also add a dummy alpha bit */
896static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
897 int width, int height)
b71472eb 898{
524c6b63
FB
899 const unsigned char *p;
900 unsigned char *q;
901 int r, g, b, dst_wrap, src_wrap;
902 int x, y;
903
904 p = src->data[0];
905 src_wrap = src->linesize[0] - 3 * width;
906
907 q = dst->data[0];
908 dst_wrap = dst->linesize[0] - 2 * width;
909
910 for(y=0;y<height;y++) {
911 for(x=0;x<width;x++) {
912 r = p[0];
913 g = p[1];
914 b = p[2];
915
916 ((unsigned short *)q)[0] =
917 ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
918 q += 2;
919 p += 3;
b71472eb 920 }
524c6b63
FB
921 p += src_wrap;
922 q += dst_wrap;
b71472eb
PG
923 }
924}
925
2a877875
FB
926static void mono_to_gray(AVPicture *dst, AVPicture *src,
927 int width, int height, int xor_mask)
524c6b63
FB
928{
929 const unsigned char *p;
930 unsigned char *q;
931 int v, dst_wrap, src_wrap;
932 int y, w;
933
934 p = src->data[0];
935 src_wrap = src->linesize[0] - ((width + 7) >> 3);
936
937 q = dst->data[0];
2a877875 938 dst_wrap = dst->linesize[0] - width;
524c6b63
FB
939 for(y=0;y<height;y++) {
940 w = width;
941 while (w >= 8) {
2a877875
FB
942 v = *p++ ^ xor_mask;
943 q[0] = -(v >> 7);
944 q[1] = -((v >> 6) & 1);
945 q[2] = -((v >> 5) & 1);
946 q[3] = -((v >> 4) & 1);
947 q[4] = -((v >> 3) & 1);
948 q[5] = -((v >> 2) & 1);
949 q[6] = -((v >> 1) & 1);
950 q[7] = -((v >> 0) & 1);
524c6b63 951 w -= 8;
2a877875 952 q += 8;
524c6b63
FB
953 }
954 if (w > 0) {
2a877875 955 v = *p++ ^ xor_mask;
524c6b63 956 do {
2a877875
FB
957 q[0] = -((v >> 7) & 1);
958 q++;
524c6b63
FB
959 v <<= 1;
960 } while (--w);
85c242d8 961 }
524c6b63
FB
962 p += src_wrap;
963 q += dst_wrap;
85c242d8
FB
964 }
965}
966
2a877875 967static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
524c6b63
FB
968 int width, int height)
969{
2a877875
FB
970 mono_to_gray(dst, src, width, height, 0xff);
971}
524c6b63 972
2a877875
FB
973static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
974 int width, int height)
975{
976 mono_to_gray(dst, src, width, height, 0x00);
977}
524c6b63 978
2a877875
FB
979static void gray_to_mono(AVPicture *dst, AVPicture *src,
980 int width, int height, int xor_mask)
981{
982 int n;
0c1a9eda
ZK
983 const uint8_t *s;
984 uint8_t *d;
2a877875
FB
985 int j, b, v, n1, src_wrap, dst_wrap, y;
986
987 s = src->data[0];
988 src_wrap = src->linesize[0] - width;
989
990 d = dst->data[0];
991 dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
524c6b63
FB
992
993 for(y=0;y<height;y++) {
2a877875
FB
994 n = width;
995 while (n >= 8) {
996 v = 0;
997 for(j=0;j<8;j++) {
998 b = s[0];
999 s++;
1000 v = (v << 1) | (b >> 7);
1001 }
1002 d[0] = v ^ xor_mask;
1003 d++;
1004 n -= 8;
524c6b63 1005 }
2a877875
FB
1006 if (n > 0) {
1007 n1 = n;
1008 v = 0;
1009 while (n > 0) {
1010 b = s[0];
1011 s++;
1012 v = (v << 1) | (b >> 7);
1013 n--;
1014 }
1015 d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
1016 d++;
524c6b63 1017 }
2a877875
FB
1018 s += src_wrap;
1019 d += dst_wrap;
524c6b63
FB
1020 }
1021}
1022
2a877875
FB
1023static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
1024 int width, int height)
1025{
1026 gray_to_mono(dst, src, width, height, 0xff);
1027}
1028
1029static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
1030 int width, int height)
1031{
1032 gray_to_mono(dst, src, width, height, 0x00);
1033}
1034
7e6d70d0 1035/* this is maybe slow, but allows for extensions */
0c1a9eda 1036static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
7e6d70d0
FB
1037{
1038 return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
1039}
1040
1041/* XXX: put jpeg quantize code instead */
1042static void rgb24_to_pal8(AVPicture *dst, AVPicture *src,
1043 int width, int height)
1044{
1045 const unsigned char *p;
1046 unsigned char *q;
1047 int r, g, b, dst_wrap, src_wrap;
1048 int x, y, i;
1049 static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
1050 uint32_t *pal;
1051
1052 p = src->data[0];
1053 src_wrap = src->linesize[0] - 3 * width;
1054
1055 q = dst->data[0];
1056 dst_wrap = dst->linesize[0] - width;
1057
1058 for(y=0;y<height;y++) {
1059 for(x=0;x<width;x++) {
1060 r = p[0];
1061 g = p[1];
1062 b = p[2];
1063
1064 q[0] = gif_clut_index(r, g, b);
1065 q++;
1066 p += 3;
1067 }
1068 p += src_wrap;
1069 q += dst_wrap;
1070 }
1071
1072 /* build palette */
1073 pal = (uint32_t *)dst->data[1];
1074 i = 0;
1075 for(r = 0; r < 6; r++) {
1076 for(g = 0; g < 6; g++) {
1077 for(b = 0; b < 6; b++) {
1078 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
1079 (pal_value[g] << 8) | pal_value[b];
1080 }
1081 }
1082 }
1083 while (i < 256)
1084 pal[i++] = 0;
1085}
1086
6d93f194
FB
1087static void rgba32_to_rgb24(AVPicture *dst, AVPicture *src,
1088 int width, int height)
1089{
1090 const uint8_t *s;
1091 uint8_t *d;
1092 int src_wrap, dst_wrap, j, y;
1093 unsigned int v;
1094
1095 s = src->data[0];
1096 src_wrap = src->linesize[0] - width * 4;
1097
1098 d = dst->data[0];
1099 dst_wrap = dst->linesize[0] - width * 3;
1100
1101 for(y=0;y<height;y++) {
1102 for(j = 0;j < width; j++) {
1103 v = *(uint32_t *)s;
1104 s += 4;
1105 d[0] = v >> 16;
1106 d[1] = v >> 8;
1107 d[2] = v;
1108 d += 3;
1109 }
1110 s += src_wrap;
1111 d += dst_wrap;
1112 }
1113}
1114
524c6b63
FB
1115typedef struct ConvertEntry {
1116 void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
1117} ConvertEntry;
1118
1119/* add each new convertion function in this table */
1120/* constraints;
1121 - all non YUV modes must convert at least to and from PIX_FMT_RGB24
1122*/
1123static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1124 [PIX_FMT_YUV420P] = {
1125 [PIX_FMT_RGB555] = {
ef9f7306 1126 .convert = yuv420p_to_rgb555
524c6b63
FB
1127 },
1128 [PIX_FMT_RGB565] = {
ef9f7306 1129 .convert = yuv420p_to_rgb565
524c6b63
FB
1130 },
1131 [PIX_FMT_BGR24] = {
ef9f7306 1132 .convert = yuv420p_to_bgr24
524c6b63
FB
1133 },
1134 [PIX_FMT_RGB24] = {
ef9f7306 1135 .convert = yuv420p_to_rgb24
524c6b63
FB
1136 },
1137 [PIX_FMT_RGBA32] = {
ef9f7306 1138 .convert = yuv420p_to_rgba32
524c6b63
FB
1139 },
1140 },
1141 [PIX_FMT_YUV422P] = {
1142 [PIX_FMT_RGB555] = {
ef9f7306 1143 .convert = yuv422p_to_rgb555
524c6b63
FB
1144 },
1145 [PIX_FMT_RGB565] = {
ef9f7306 1146 .convert = yuv422p_to_rgb565
524c6b63
FB
1147 },
1148 [PIX_FMT_BGR24] = {
ef9f7306 1149 .convert = yuv422p_to_bgr24
524c6b63
FB
1150 },
1151 [PIX_FMT_RGB24] = {
ef9f7306 1152 .convert = yuv422p_to_rgb24
524c6b63
FB
1153 },
1154 [PIX_FMT_RGBA32] = {
ef9f7306 1155 .convert = yuv422p_to_rgba32
524c6b63
FB
1156 },
1157 },
1158 [PIX_FMT_YUV422] = {
1159 [PIX_FMT_YUV420P] = {
ef9f7306 1160 .convert = yuv422_to_yuv420p,
524c6b63
FB
1161 },
1162 },
1163
1164 [PIX_FMT_RGB24] = {
1165 [PIX_FMT_YUV420P] = {
ef9f7306 1166 .convert = rgb24_to_yuv420p
524c6b63
FB
1167 },
1168 [PIX_FMT_RGB565] = {
ef9f7306 1169 .convert = rgb24_to_rgb565
524c6b63
FB
1170 },
1171 [PIX_FMT_RGB555] = {
ef9f7306 1172 .convert = rgb24_to_rgb555
524c6b63
FB
1173 },
1174 [PIX_FMT_GRAY8] = {
ef9f7306 1175 .convert = rgb24_to_gray
524c6b63 1176 },
7e6d70d0
FB
1177 [PIX_FMT_PAL8] = {
1178 .convert = rgb24_to_pal8
1179 },
524c6b63
FB
1180 },
1181 [PIX_FMT_RGBA32] = {
1182 [PIX_FMT_YUV420P] = {
ef9f7306 1183 .convert = rgba32_to_yuv420p
524c6b63 1184 },
69572401
FB
1185 [PIX_FMT_GRAY8] = {
1186 .convert = rgba32_to_gray
1187 },
6d93f194
FB
1188 [PIX_FMT_RGB24] = {
1189 .convert = rgba32_to_rgb24
1190 },
524c6b63
FB
1191 },
1192 [PIX_FMT_BGR24] = {
1193 [PIX_FMT_YUV420P] = {
ef9f7306 1194 .convert = bgr24_to_yuv420p
524c6b63 1195 },
69572401
FB
1196 [PIX_FMT_GRAY8] = {
1197 .convert = bgr24_to_gray
1198 },
524c6b63
FB
1199 },
1200 [PIX_FMT_RGB555] = {
1201 [PIX_FMT_YUV420P] = {
ef9f7306 1202 .convert = rgb555_to_yuv420p
524c6b63 1203 },
69572401
FB
1204 [PIX_FMT_GRAY8] = {
1205 .convert = rgb555_to_gray
1206 },
524c6b63
FB
1207 },
1208 [PIX_FMT_RGB565] = {
1209 [PIX_FMT_YUV420P] = {
ef9f7306 1210 .convert = rgb565_to_yuv420p
524c6b63 1211 },
69572401
FB
1212 [PIX_FMT_GRAY8] = {
1213 .convert = rgb565_to_gray
1214 },
524c6b63
FB
1215 },
1216 [PIX_FMT_GRAY8] = {
69572401
FB
1217 [PIX_FMT_RGB555] = {
1218 .convert = gray_to_rgb555
1219 },
1220 [PIX_FMT_RGB565] = {
1221 .convert = gray_to_rgb565
1222 },
524c6b63 1223 [PIX_FMT_RGB24] = {
ef9f7306 1224 .convert = gray_to_rgb24
524c6b63 1225 },
69572401
FB
1226 [PIX_FMT_BGR24] = {
1227 .convert = gray_to_bgr24
1228 },
1229 [PIX_FMT_RGBA32] = {
1230 .convert = gray_to_rgba32
1231 },
2a877875 1232 [PIX_FMT_MONOWHITE] = {
ef9f7306 1233 .convert = gray_to_monowhite
2a877875
FB
1234 },
1235 [PIX_FMT_MONOBLACK] = {
ef9f7306 1236 .convert = gray_to_monoblack
2a877875 1237 },
524c6b63
FB
1238 },
1239 [PIX_FMT_MONOWHITE] = {
2a877875 1240 [PIX_FMT_GRAY8] = {
ef9f7306 1241 .convert = monowhite_to_gray
524c6b63
FB
1242 },
1243 },
1244 [PIX_FMT_MONOBLACK] = {
2a877875 1245 [PIX_FMT_GRAY8] = {
ef9f7306 1246 .convert = monoblack_to_gray
524c6b63
FB
1247 },
1248 },
7e6d70d0
FB
1249 [PIX_FMT_PAL8] = {
1250 [PIX_FMT_RGB555] = {
1251 .convert = pal8_to_rgb555
1252 },
1253 [PIX_FMT_RGB565] = {
1254 .convert = pal8_to_rgb565
1255 },
1256 [PIX_FMT_BGR24] = {
1257 .convert = pal8_to_bgr24
1258 },
1259 [PIX_FMT_RGB24] = {
1260 .convert = pal8_to_rgb24
1261 },
1262 [PIX_FMT_RGBA32] = {
1263 .convert = pal8_to_rgba32
1264 },
1265 },
524c6b63
FB
1266};
1267
1268static int avpicture_alloc(AVPicture *picture,
1269 int pix_fmt, int width, int height)
1270{
5c91a675 1271 unsigned int size;
524c6b63
FB
1272 void *ptr;
1273
1274 size = avpicture_get_size(pix_fmt, width, height);
1275 if (size < 0)
1276 goto fail;
1277 ptr = av_malloc(size);
1278 if (!ptr)
1279 goto fail;
1280 avpicture_fill(picture, ptr, pix_fmt, width, height);
1281 return 0;
1282 fail:
1283 memset(picture, 0, sizeof(AVPicture));
1284 return -1;
1285}
1286
1287static void avpicture_free(AVPicture *picture)
1288{
8e1e6f31 1289 av_free(picture->data[0]);
524c6b63
FB
1290}
1291
85c242d8
FB
1292/* XXX: always use linesize. Return -1 if not supported */
1293int img_convert(AVPicture *dst, int dst_pix_fmt,
524c6b63
FB
1294 AVPicture *src, int src_pix_fmt,
1295 int src_width, int src_height)
85c242d8 1296{
2a877875 1297 int i, ret, dst_width, dst_height, int_pix_fmt;
524c6b63
FB
1298 PixFmtInfo *src_pix, *dst_pix;
1299 ConvertEntry *ce;
1300 AVPicture tmp1, *tmp = &tmp1;
1301
1302 if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
1303 dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
1304 return -1;
1305 if (src_width <= 0 || src_height <= 0)
1306 return 0;
69572401 1307
524c6b63
FB
1308 dst_width = src_width;
1309 dst_height = src_height;
69572401 1310
524c6b63
FB
1311 dst_pix = &pix_fmt_info[dst_pix_fmt];
1312 src_pix = &pix_fmt_info[src_pix_fmt];
1313 if (src_pix_fmt == dst_pix_fmt) {
2a877875 1314 /* XXX: incorrect */
524c6b63
FB
1315 /* same format: just copy */
1316 for(i = 0; i < dst_pix->nb_components; i++) {
1317 int w, h;
1318 w = dst_width;
1319 h = dst_height;
1320 if (dst_pix->is_yuv && (i == 1 || i == 2)) {
1321 w >>= dst_pix->x_chroma_shift;
1322 h >>= dst_pix->y_chroma_shift;
85c242d8 1323 }
524c6b63
FB
1324 img_copy(dst->data[i], dst->linesize[i],
1325 src->data[i], src->linesize[i],
1326 w, h);
85c242d8 1327 }
524c6b63
FB
1328 return 0;
1329 }
1330
1331 ce = &convert_table[src_pix_fmt][dst_pix_fmt];
1332 if (ce->convert) {
1333 /* specific convertion routine */
1334 ce->convert(dst, src, dst_width, dst_height);
1335 return 0;
1336 }
1337
524c6b63
FB
1338 /* gray to YUV */
1339 if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
1340 int w, h, y;
1341 uint8_t *d;
1342
1343 img_copy(dst->data[0], dst->linesize[0],
1344 src->data[0], src->linesize[0],
1345 dst_width, dst_height);
1346 /* fill U and V with 128 */
1347 w = dst_width;
1348 h = dst_height;
1349 w >>= dst_pix->x_chroma_shift;
1350 h >>= dst_pix->y_chroma_shift;
1351 for(i = 1; i <= 2; i++) {
1352 d = dst->data[i];
2a877875
FB
1353 for(y = 0; y< h; y++) {
1354 memset(d, 128, w);
524c6b63
FB
1355 d += dst->linesize[i];
1356 }
b71472eb 1357 }
524c6b63
FB
1358 return 0;
1359 }
1360
1361 /* YUV to gray */
1362 if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
1363 img_copy(dst->data[0], dst->linesize[0],
1364 src->data[0], src->linesize[0],
1365 dst_width, dst_height);
1366 return 0;
1367 }
1368
1369 /* YUV to YUV */
1370 if (dst_pix->is_yuv && src_pix->is_yuv) {
1371 int x_shift, y_shift, w, h;
0c1a9eda
ZK
1372 void (*resize_func)(uint8_t *dst, int dst_wrap,
1373 uint8_t *src, int src_wrap,
524c6b63
FB
1374 int width, int height);
1375
1376 /* compute chroma size of the smallest dimensions */
1377 w = dst_width;
1378 h = dst_height;
1379 if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
1380 w >>= dst_pix->x_chroma_shift;
1381 else
1382 w >>= src_pix->x_chroma_shift;
1383 if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
1384 h >>= dst_pix->y_chroma_shift;
1385 else
1386 h >>= src_pix->y_chroma_shift;
1387
1388 x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
1389 y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
1390 if (x_shift == 0 && y_shift == 0) {
1391 resize_func = img_copy; /* should never happen */
1392 } else if (x_shift == 0 && y_shift == 1) {
1393 resize_func = shrink2;
1394 } else if (x_shift == 1 && y_shift == 1) {
1395 resize_func = shrink22;
1396 } else if (x_shift == -1 && y_shift == -1) {
1397 resize_func = grow22;
1398 } else if (x_shift == -1 && y_shift == 1) {
1399 resize_func = conv411;
1400 } else {
1401 /* currently not handled */
85c242d8
FB
1402 return -1;
1403 }
524c6b63
FB
1404
1405 img_copy(dst->data[0], dst->linesize[0],
1406 src->data[0], src->linesize[0],
1407 dst_width, dst_height);
566986ee 1408
524c6b63 1409 for(i = 1;i <= 2; i++)
566986ee
MK
1410 resize_func(dst->data[i], dst->linesize[i],
1411 src->data[i], src->linesize[i],
185fdc54 1412 dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
566986ee 1413 return 0;
85c242d8 1414 }
524c6b63 1415
2a877875
FB
1416 /* try to use an intermediate format */
1417 if (src_pix_fmt == PIX_FMT_MONOWHITE ||
1418 src_pix_fmt == PIX_FMT_MONOBLACK ||
1419 dst_pix_fmt == PIX_FMT_MONOWHITE ||
1420 dst_pix_fmt == PIX_FMT_MONOBLACK) {
1421 int_pix_fmt = PIX_FMT_GRAY8;
1422 } else {
1423 int_pix_fmt = PIX_FMT_RGB24;
1424 }
1425 if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
1426 return -1;
1427 ret = -1;
1428 if (img_convert(tmp, int_pix_fmt,
1429 src, src_pix_fmt, src_width, src_height) < 0)
1430 goto fail1;
1431 if (img_convert(dst, dst_pix_fmt,
1432 tmp, int_pix_fmt, dst_width, dst_height) < 0)
1433 goto fail1;
1434 ret = 0;
1435 fail1:
1436 avpicture_free(tmp);
1437 return ret;
85c242d8
FB
1438}
1439
5981f4e6
F
1440
1441#ifdef HAVE_MMX
1442#define DEINT_INPLACE_LINE_LUM \
1443 movd_m2r(lum_m4[0],mm0);\
1444 movd_m2r(lum_m3[0],mm1);\
1445 movd_m2r(lum_m2[0],mm2);\
1446 movd_m2r(lum_m1[0],mm3);\
1447 movd_m2r(lum[0],mm4);\
1448 punpcklbw_r2r(mm7,mm0);\
1449 movd_r2m(mm2,lum_m4[0]);\
1450 punpcklbw_r2r(mm7,mm1);\
1451 punpcklbw_r2r(mm7,mm2);\
1452 punpcklbw_r2r(mm7,mm3);\
1453 punpcklbw_r2r(mm7,mm4);\
1454 paddw_r2r(mm3,mm1);\
1455 psllw_i2r(1,mm2);\
1456 paddw_r2r(mm4,mm0);\
1457 psllw_i2r(2,mm1);\
1458 paddw_r2r(mm6,mm2);\
1459 paddw_r2r(mm2,mm1);\
1460 psubusw_r2r(mm0,mm1);\
1461 psrlw_i2r(3,mm1);\
1462 packuswb_r2r(mm7,mm1);\
1463 movd_r2m(mm1,lum_m2[0]);
1464
1465#define DEINT_LINE_LUM \
1466 movd_m2r(lum_m4[0],mm0);\
1467 movd_m2r(lum_m3[0],mm1);\
1468 movd_m2r(lum_m2[0],mm2);\
1469 movd_m2r(lum_m1[0],mm3);\
1470 movd_m2r(lum[0],mm4);\
1471 punpcklbw_r2r(mm7,mm0);\
1472 punpcklbw_r2r(mm7,mm1);\
1473 punpcklbw_r2r(mm7,mm2);\
1474 punpcklbw_r2r(mm7,mm3);\
1475 punpcklbw_r2r(mm7,mm4);\
1476 paddw_r2r(mm3,mm1);\
1477 psllw_i2r(1,mm2);\
1478 paddw_r2r(mm4,mm0);\
1479 psllw_i2r(2,mm1);\
1480 paddw_r2r(mm6,mm2);\
1481 paddw_r2r(mm2,mm1);\
1482 psubusw_r2r(mm0,mm1);\
1483 psrlw_i2r(3,mm1);\
1484 packuswb_r2r(mm7,mm1);\
1485 movd_r2m(mm1,dst[0]);
1486#endif
1487
85c242d8 1488/* filter parameters: [-1 4 2 4 -1] // 8 */
0c1a9eda 1489static 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,
5981f4e6 1490 int size)
85c242d8 1491{
5981f4e6 1492#ifndef HAVE_MMX
0c1a9eda 1493 uint8_t *cm = cropTbl + MAX_NEG_CROP;
85c242d8 1494 int sum;
85c242d8
FB
1495
1496 for(;size > 0;size--) {
5981f4e6
F
1497 sum = -lum_m4[0];
1498 sum += lum_m3[0] << 2;
1499 sum += lum_m2[0] << 1;
1500 sum += lum_m1[0] << 2;
1501 sum += -lum[0];
85c242d8 1502 dst[0] = cm[(sum + 4) >> 3];
5981f4e6
F
1503 lum_m4++;
1504 lum_m3++;
1505 lum_m2++;
1506 lum_m1++;
1507 lum++;
85c242d8 1508 dst++;
85c242d8 1509 }
5981f4e6
F
1510#else
1511
782c5984
MN
1512 {
1513 mmx_t rounder;
1514 rounder.uw[0]=4;
1515 rounder.uw[1]=4;
1516 rounder.uw[2]=4;
1517 rounder.uw[3]=4;
1518 pxor_r2r(mm7,mm7);
1519 movq_m2r(rounder,mm6);
1520 }
5981f4e6
F
1521 for (;size > 3; size-=4) {
1522 DEINT_LINE_LUM
1523 lum_m4+=4;
1524 lum_m3+=4;
1525 lum_m2+=4;
1526 lum_m1+=4;
1527 lum+=4;
1528 dst+=4;
1529 }
1530#endif
1531}
0c1a9eda 1532static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
5981f4e6
F
1533 int size)
1534{
1535#ifndef HAVE_MMX
0c1a9eda 1536 uint8_t *cm = cropTbl + MAX_NEG_CROP;
5981f4e6
F
1537 int sum;
1538
1539 for(;size > 0;size--) {
1540 sum = -lum_m4[0];
1541 sum += lum_m3[0] << 2;
1542 sum += lum_m2[0] << 1;
1543 lum_m4[0]=lum_m2[0];
1544 sum += lum_m1[0] << 2;
1545 sum += -lum[0];
1546 lum_m2[0] = cm[(sum + 4) >> 3];
1547 lum_m4++;
1548 lum_m3++;
1549 lum_m2++;
1550 lum_m1++;
1551 lum++;
1552 }
1553#else
1554
782c5984
MN
1555 {
1556 mmx_t rounder;
1557 rounder.uw[0]=4;
1558 rounder.uw[1]=4;
1559 rounder.uw[2]=4;
1560 rounder.uw[3]=4;
1561 pxor_r2r(mm7,mm7);
1562 movq_m2r(rounder,mm6);
1563 }
5981f4e6
F
1564 for (;size > 3; size-=4) {
1565 DEINT_INPLACE_LINE_LUM
1566 lum_m4+=4;
1567 lum_m3+=4;
1568 lum_m2+=4;
1569 lum_m1+=4;
1570 lum+=4;
1571 }
1572#endif
85c242d8
FB
1573}
1574
1575/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
1576 top field is copied as is, but the bottom field is deinterlaced
1577 against the top field. */
0c1a9eda
ZK
1578static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
1579 uint8_t *src1, int src_wrap,
5981f4e6 1580 int width, int height)
85c242d8 1581{
0c1a9eda 1582 uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6
F
1583 int y;
1584
1585 src_m2 = src1;
1586 src_m1 = src1;
1587 src_0=&src_m1[src_wrap];
1588 src_p1=&src_0[src_wrap];
1589 src_p2=&src_p1[src_wrap];
1590 for(y=0;y<(height-2);y+=2) {
1591 memcpy(dst,src_m1,width);
85c242d8 1592 dst += dst_wrap;
5981f4e6
F
1593 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
1594 src_m2 = src_0;
1595 src_m1 = src_p1;
1596 src_0 = src_p2;
1597 src_p1 += 2*src_wrap;
1598 src_p2 += 2*src_wrap;
85c242d8 1599 dst += dst_wrap;
85c242d8 1600 }
5981f4e6
F
1601 memcpy(dst,src_m1,width);
1602 dst += dst_wrap;
1603 /* do last line */
1604 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
1605}
1606
0c1a9eda 1607static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
5981f4e6
F
1608 int width, int height)
1609{
0c1a9eda 1610 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6 1611 int y;
0c1a9eda
ZK
1612 uint8_t *buf;
1613 buf = (uint8_t*)av_malloc(width);
5981f4e6
F
1614
1615 src_m1 = src1;
1616 memcpy(buf,src_m1,width);
1617 src_0=&src_m1[src_wrap];
1618 src_p1=&src_0[src_wrap];
1619 src_p2=&src_p1[src_wrap];
1620 for(y=0;y<(height-2);y+=2) {
1621 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1622 src_m1 = src_p1;
1623 src_0 = src_p2;
1624 src_p1 += 2*src_wrap;
1625 src_p2 += 2*src_wrap;
1626 }
1627 /* do last line */
1628 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
6000abfa 1629 av_free(buf);
85c242d8
FB
1630}
1631
1632
5981f4e6 1633/* deinterlace - if not supported return -1 */
85c242d8 1634int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
de6d9b64
FB
1635 int pix_fmt, int width, int height)
1636{
85c242d8
FB
1637 int i;
1638
1639 if (pix_fmt != PIX_FMT_YUV420P &&
1640 pix_fmt != PIX_FMT_YUV422P &&
1641 pix_fmt != PIX_FMT_YUV444P)
1642 return -1;
5981f4e6 1643 if ((width & 3) != 0 || (height & 3) != 0)
85c242d8 1644 return -1;
5981f4e6 1645
85c242d8
FB
1646 for(i=0;i<3;i++) {
1647 if (i == 1) {
1648 switch(pix_fmt) {
1649 case PIX_FMT_YUV420P:
1650 width >>= 1;
1651 height >>= 1;
1652 break;
1653 case PIX_FMT_YUV422P:
1654 width >>= 1;
1655 break;
1656 default:
1657 break;
1658 }
1659 }
5981f4e6
F
1660 if (src == dst) {
1661 deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
85c242d8 1662 width, height);
5981f4e6
F
1663 } else {
1664 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1665 src->data[i], src->linesize[i],
1666 width, height);
1667 }
de6d9b64 1668 }
5981f4e6
F
1669#ifdef HAVE_MMX
1670 emms();
1671#endif
85c242d8 1672 return 0;
de6d9b64 1673}
cd4af68a
ZK
1674
1675#undef FIX