ffmpeg / libavcodec / imgconvert.c @ 5509bffa
History | View | Annotate | Download (66.1 KB)
1 |
/*
|
---|---|
2 |
* Misc image convertion routines
|
3 |
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
|
4 |
*
|
5 |
* This library is free software; you can redistribute it and/or
|
6 |
* modify it under the terms of the GNU Lesser General Public
|
7 |
* License as published by the Free Software Foundation; either
|
8 |
* version 2 of the License, or (at your option) any later version.
|
9 |
*
|
10 |
* This library is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13 |
* Lesser General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU Lesser General Public
|
16 |
* License along with this library; if not, write to the Free Software
|
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 |
*/
|
19 |
|
20 |
/**
|
21 |
* @file imgconvert.c
|
22 |
* Misc image convertion routines.
|
23 |
*/
|
24 |
|
25 |
/* TODO:
|
26 |
* - write 'ffimg' program to test all the image related stuff
|
27 |
* - move all api to slice based system
|
28 |
* - integrate deinterlacing, postprocessing and scaling in the conversion process
|
29 |
*/
|
30 |
|
31 |
#include "avcodec.h" |
32 |
#include "dsputil.h" |
33 |
|
34 |
#ifdef USE_FASTMEMCPY
|
35 |
#include "fastmemcpy.h" |
36 |
#endif
|
37 |
|
38 |
#ifdef HAVE_MMX
|
39 |
#include "i386/mmx.h" |
40 |
#endif
|
41 |
|
42 |
#define xglue(x, y) x ## y |
43 |
#define glue(x, y) xglue(x, y)
|
44 |
|
45 |
#define FF_COLOR_RGB 0 /* RGB color space */ |
46 |
#define FF_COLOR_GRAY 1 /* gray color space */ |
47 |
#define FF_COLOR_YUV 2 /* YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ |
48 |
#define FF_COLOR_YUV_JPEG 3 /* YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ |
49 |
|
50 |
#define FF_PIXEL_PLANAR 0 /* each channel has one component in AVPicture */ |
51 |
#define FF_PIXEL_PACKED 1 /* only one components containing all the channels */ |
52 |
#define FF_PIXEL_PALETTE 2 /* one components containing indexes for a palette */ |
53 |
|
54 |
typedef struct PixFmtInfo { |
55 |
const char *name; |
56 |
uint8_t nb_channels; /* number of channels (including alpha) */
|
57 |
uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */
|
58 |
uint8_t pixel_type; /* pixel storage type (see FF_PIXEL_xxx constants) */
|
59 |
uint8_t is_alpha : 1; /* true if alpha can be specified */ |
60 |
uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
|
61 |
uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
|
62 |
uint8_t depth; /* bit depth of the color components */
|
63 |
} PixFmtInfo; |
64 |
|
65 |
/* this table gives more information about formats */
|
66 |
static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
|
67 |
/* YUV formats */
|
68 |
[PIX_FMT_YUV420P] = { |
69 |
.name = "yuv420p",
|
70 |
.nb_channels = 3,
|
71 |
.color_type = FF_COLOR_YUV, |
72 |
.pixel_type = FF_PIXEL_PLANAR, |
73 |
.depth = 8,
|
74 |
.x_chroma_shift = 1, .y_chroma_shift = 1, |
75 |
}, |
76 |
[PIX_FMT_YUV422P] = { |
77 |
.name = "yuv422p",
|
78 |
.nb_channels = 3,
|
79 |
.color_type = FF_COLOR_YUV, |
80 |
.pixel_type = FF_PIXEL_PLANAR, |
81 |
.depth = 8,
|
82 |
.x_chroma_shift = 1, .y_chroma_shift = 0, |
83 |
}, |
84 |
[PIX_FMT_YUV444P] = { |
85 |
.name = "yuv444p",
|
86 |
.nb_channels = 3,
|
87 |
.color_type = FF_COLOR_YUV, |
88 |
.pixel_type = FF_PIXEL_PLANAR, |
89 |
.depth = 8,
|
90 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
91 |
}, |
92 |
[PIX_FMT_YUV422] = { |
93 |
.name = "yuv422",
|
94 |
.nb_channels = 1,
|
95 |
.color_type = FF_COLOR_YUV, |
96 |
.pixel_type = FF_PIXEL_PACKED, |
97 |
.depth = 8,
|
98 |
.x_chroma_shift = 1, .y_chroma_shift = 0, |
99 |
}, |
100 |
[PIX_FMT_UYVY422] = { |
101 |
.name = "uyvy422",
|
102 |
.nb_channels = 1,
|
103 |
.color_type = FF_COLOR_YUV, |
104 |
.pixel_type = FF_PIXEL_PACKED, |
105 |
.depth = 8,
|
106 |
.x_chroma_shift = 1, .y_chroma_shift = 0, |
107 |
}, |
108 |
[PIX_FMT_YUV410P] = { |
109 |
.name = "yuv410p",
|
110 |
.nb_channels = 3,
|
111 |
.color_type = FF_COLOR_YUV, |
112 |
.pixel_type = FF_PIXEL_PLANAR, |
113 |
.depth = 8,
|
114 |
.x_chroma_shift = 2, .y_chroma_shift = 2, |
115 |
}, |
116 |
[PIX_FMT_YUV411P] = { |
117 |
.name = "yuv411p",
|
118 |
.nb_channels = 3,
|
119 |
.color_type = FF_COLOR_YUV, |
120 |
.pixel_type = FF_PIXEL_PLANAR, |
121 |
.depth = 8,
|
122 |
.x_chroma_shift = 2, .y_chroma_shift = 0, |
123 |
}, |
124 |
|
125 |
/* JPEG YUV */
|
126 |
[PIX_FMT_YUVJ420P] = { |
127 |
.name = "yuvj420p",
|
128 |
.nb_channels = 3,
|
129 |
.color_type = FF_COLOR_YUV_JPEG, |
130 |
.pixel_type = FF_PIXEL_PLANAR, |
131 |
.depth = 8,
|
132 |
.x_chroma_shift = 1, .y_chroma_shift = 1, |
133 |
}, |
134 |
[PIX_FMT_YUVJ422P] = { |
135 |
.name = "yuvj422p",
|
136 |
.nb_channels = 3,
|
137 |
.color_type = FF_COLOR_YUV_JPEG, |
138 |
.pixel_type = FF_PIXEL_PLANAR, |
139 |
.depth = 8,
|
140 |
.x_chroma_shift = 1, .y_chroma_shift = 0, |
141 |
}, |
142 |
[PIX_FMT_YUVJ444P] = { |
143 |
.name = "yuvj444p",
|
144 |
.nb_channels = 3,
|
145 |
.color_type = FF_COLOR_YUV_JPEG, |
146 |
.pixel_type = FF_PIXEL_PLANAR, |
147 |
.depth = 8,
|
148 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
149 |
}, |
150 |
|
151 |
/* RGB formats */
|
152 |
[PIX_FMT_RGB24] = { |
153 |
.name = "rgb24",
|
154 |
.nb_channels = 3,
|
155 |
.color_type = FF_COLOR_RGB, |
156 |
.pixel_type = FF_PIXEL_PACKED, |
157 |
.depth = 8,
|
158 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
159 |
}, |
160 |
[PIX_FMT_BGR24] = { |
161 |
.name = "bgr24",
|
162 |
.nb_channels = 3,
|
163 |
.color_type = FF_COLOR_RGB, |
164 |
.pixel_type = FF_PIXEL_PACKED, |
165 |
.depth = 8,
|
166 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
167 |
}, |
168 |
[PIX_FMT_RGBA32] = { |
169 |
.name = "rgba32",
|
170 |
.nb_channels = 4, .is_alpha = 1, |
171 |
.color_type = FF_COLOR_RGB, |
172 |
.pixel_type = FF_PIXEL_PACKED, |
173 |
.depth = 8,
|
174 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
175 |
}, |
176 |
[PIX_FMT_RGB565] = { |
177 |
.name = "rgb565",
|
178 |
.nb_channels = 3,
|
179 |
.color_type = FF_COLOR_RGB, |
180 |
.pixel_type = FF_PIXEL_PACKED, |
181 |
.depth = 5,
|
182 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
183 |
}, |
184 |
[PIX_FMT_RGB555] = { |
185 |
.name = "rgb555",
|
186 |
.nb_channels = 4, .is_alpha = 1, |
187 |
.color_type = FF_COLOR_RGB, |
188 |
.pixel_type = FF_PIXEL_PACKED, |
189 |
.depth = 5,
|
190 |
.x_chroma_shift = 0, .y_chroma_shift = 0, |
191 |
}, |
192 |
|
193 |
/* gray / mono formats */
|
194 |
[PIX_FMT_GRAY8] = { |
195 |
.name = "gray",
|
196 |
.nb_channels = 1,
|
197 |
.color_type = FF_COLOR_GRAY, |
198 |
.pixel_type = FF_PIXEL_PLANAR, |
199 |
.depth = 8,
|
200 |
}, |
201 |
[PIX_FMT_MONOWHITE] = { |
202 |
.name = "monow",
|
203 |
.nb_channels = 1,
|
204 |
.color_type = FF_COLOR_GRAY, |
205 |
.pixel_type = FF_PIXEL_PLANAR, |
206 |
.depth = 1,
|
207 |
}, |
208 |
[PIX_FMT_MONOBLACK] = { |
209 |
.name = "monob",
|
210 |
.nb_channels = 1,
|
211 |
.color_type = FF_COLOR_GRAY, |
212 |
.pixel_type = FF_PIXEL_PLANAR, |
213 |
.depth = 1,
|
214 |
}, |
215 |
|
216 |
/* paletted formats */
|
217 |
[PIX_FMT_PAL8] = { |
218 |
.name = "pal8",
|
219 |
.nb_channels = 4, .is_alpha = 1, |
220 |
.color_type = FF_COLOR_RGB, |
221 |
.pixel_type = FF_PIXEL_PALETTE, |
222 |
.depth = 8,
|
223 |
}, |
224 |
[PIX_FMT_XVMC_MPEG2_MC] = { |
225 |
.name = "xvmcmc",
|
226 |
}, |
227 |
[PIX_FMT_XVMC_MPEG2_IDCT] = { |
228 |
.name = "xvmcidct",
|
229 |
}, |
230 |
[PIX_FMT_UYVY411] = { |
231 |
.name = "uyvy411",
|
232 |
.nb_channels = 1,
|
233 |
.color_type = FF_COLOR_YUV, |
234 |
.pixel_type = FF_PIXEL_PACKED, |
235 |
.depth = 8,
|
236 |
.x_chroma_shift = 2, .y_chroma_shift = 0, |
237 |
}, |
238 |
}; |
239 |
|
240 |
void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift) |
241 |
{ |
242 |
*h_shift = pix_fmt_info[pix_fmt].x_chroma_shift; |
243 |
*v_shift = pix_fmt_info[pix_fmt].y_chroma_shift; |
244 |
} |
245 |
|
246 |
const char *avcodec_get_pix_fmt_name(int pix_fmt) |
247 |
{ |
248 |
if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) |
249 |
return "???"; |
250 |
else
|
251 |
return pix_fmt_info[pix_fmt].name;
|
252 |
} |
253 |
|
254 |
enum PixelFormat avcodec_get_pix_fmt(const char* name) |
255 |
{ |
256 |
int i;
|
257 |
|
258 |
for (i=0; i < PIX_FMT_NB; i++) |
259 |
if (!strcmp(pix_fmt_info[i].name, name))
|
260 |
break;
|
261 |
return i;
|
262 |
} |
263 |
|
264 |
/* Picture field are filled with 'ptr' addresses. Also return size */
|
265 |
int avpicture_fill(AVPicture *picture, uint8_t *ptr,
|
266 |
int pix_fmt, int width, int height) |
267 |
{ |
268 |
int size, w2, h2, size2;
|
269 |
PixFmtInfo *pinfo; |
270 |
|
271 |
if(avcodec_check_dimensions(NULL, width, height)) |
272 |
goto fail;
|
273 |
|
274 |
pinfo = &pix_fmt_info[pix_fmt]; |
275 |
size = width * height; |
276 |
switch(pix_fmt) {
|
277 |
case PIX_FMT_YUV420P:
|
278 |
case PIX_FMT_YUV422P:
|
279 |
case PIX_FMT_YUV444P:
|
280 |
case PIX_FMT_YUV410P:
|
281 |
case PIX_FMT_YUV411P:
|
282 |
case PIX_FMT_YUVJ420P:
|
283 |
case PIX_FMT_YUVJ422P:
|
284 |
case PIX_FMT_YUVJ444P:
|
285 |
w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; |
286 |
h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; |
287 |
size2 = w2 * h2; |
288 |
picture->data[0] = ptr;
|
289 |
picture->data[1] = picture->data[0] + size; |
290 |
picture->data[2] = picture->data[1] + size2; |
291 |
picture->linesize[0] = width;
|
292 |
picture->linesize[1] = w2;
|
293 |
picture->linesize[2] = w2;
|
294 |
return size + 2 * size2; |
295 |
case PIX_FMT_RGB24:
|
296 |
case PIX_FMT_BGR24:
|
297 |
picture->data[0] = ptr;
|
298 |
picture->data[1] = NULL; |
299 |
picture->data[2] = NULL; |
300 |
picture->linesize[0] = width * 3; |
301 |
return size * 3; |
302 |
case PIX_FMT_RGBA32:
|
303 |
picture->data[0] = ptr;
|
304 |
picture->data[1] = NULL; |
305 |
picture->data[2] = NULL; |
306 |
picture->linesize[0] = width * 4; |
307 |
return size * 4; |
308 |
case PIX_FMT_RGB555:
|
309 |
case PIX_FMT_RGB565:
|
310 |
case PIX_FMT_YUV422:
|
311 |
picture->data[0] = ptr;
|
312 |
picture->data[1] = NULL; |
313 |
picture->data[2] = NULL; |
314 |
picture->linesize[0] = width * 2; |
315 |
return size * 2; |
316 |
case PIX_FMT_UYVY422:
|
317 |
picture->data[0] = ptr;
|
318 |
picture->data[1] = NULL; |
319 |
picture->data[2] = NULL; |
320 |
picture->linesize[0] = width * 2; |
321 |
return size * 2; |
322 |
case PIX_FMT_UYVY411:
|
323 |
picture->data[0] = ptr;
|
324 |
picture->data[1] = NULL; |
325 |
picture->data[2] = NULL; |
326 |
picture->linesize[0] = width + width/2; |
327 |
return size + size/2; |
328 |
case PIX_FMT_GRAY8:
|
329 |
picture->data[0] = ptr;
|
330 |
picture->data[1] = NULL; |
331 |
picture->data[2] = NULL; |
332 |
picture->linesize[0] = width;
|
333 |
return size;
|
334 |
case PIX_FMT_MONOWHITE:
|
335 |
case PIX_FMT_MONOBLACK:
|
336 |
picture->data[0] = ptr;
|
337 |
picture->data[1] = NULL; |
338 |
picture->data[2] = NULL; |
339 |
picture->linesize[0] = (width + 7) >> 3; |
340 |
return picture->linesize[0] * height; |
341 |
case PIX_FMT_PAL8:
|
342 |
size2 = (size + 3) & ~3; |
343 |
picture->data[0] = ptr;
|
344 |
picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */ |
345 |
picture->data[2] = NULL; |
346 |
picture->linesize[0] = width;
|
347 |
picture->linesize[1] = 4; |
348 |
return size2 + 256 * 4; |
349 |
default:
|
350 |
fail:
|
351 |
picture->data[0] = NULL; |
352 |
picture->data[1] = NULL; |
353 |
picture->data[2] = NULL; |
354 |
picture->data[3] = NULL; |
355 |
return -1; |
356 |
} |
357 |
} |
358 |
|
359 |
int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height, |
360 |
unsigned char *dest, int dest_size) |
361 |
{ |
362 |
PixFmtInfo* pf = &pix_fmt_info[pix_fmt]; |
363 |
int i, j, w, h, data_planes;
|
364 |
const unsigned char* s; |
365 |
int size = avpicture_get_size(pix_fmt, width, height);
|
366 |
|
367 |
if (size > dest_size || size < 0) |
368 |
return -1; |
369 |
|
370 |
if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
|
371 |
if (pix_fmt == PIX_FMT_YUV422 ||
|
372 |
pix_fmt == PIX_FMT_UYVY422 || |
373 |
pix_fmt == PIX_FMT_RGB565 || |
374 |
pix_fmt == PIX_FMT_RGB555) |
375 |
w = width * 2;
|
376 |
else if (pix_fmt == PIX_FMT_UYVY411) |
377 |
w = width + width/2;
|
378 |
else if (pix_fmt == PIX_FMT_PAL8) |
379 |
w = width; |
380 |
else
|
381 |
w = width * (pf->depth * pf->nb_channels / 8);
|
382 |
|
383 |
data_planes = 1;
|
384 |
h = height; |
385 |
} else {
|
386 |
data_planes = pf->nb_channels; |
387 |
w = (width*pf->depth + 7)/8; |
388 |
h = height; |
389 |
} |
390 |
|
391 |
for (i=0; i<data_planes; i++) { |
392 |
if (i == 1) { |
393 |
w = width >> pf->x_chroma_shift; |
394 |
h = height >> pf->y_chroma_shift; |
395 |
} |
396 |
s = src->data[i]; |
397 |
for(j=0; j<h; j++) { |
398 |
memcpy(dest, s, w); |
399 |
dest += w; |
400 |
s += src->linesize[i]; |
401 |
} |
402 |
} |
403 |
|
404 |
if (pf->pixel_type == FF_PIXEL_PALETTE)
|
405 |
memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4); |
406 |
|
407 |
return size;
|
408 |
} |
409 |
|
410 |
int avpicture_get_size(int pix_fmt, int width, int height) |
411 |
{ |
412 |
AVPicture dummy_pict; |
413 |
return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); |
414 |
} |
415 |
|
416 |
/**
|
417 |
* compute the loss when converting from a pixel format to another
|
418 |
*/
|
419 |
int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt, |
420 |
int has_alpha)
|
421 |
{ |
422 |
const PixFmtInfo *pf, *ps;
|
423 |
int loss;
|
424 |
|
425 |
ps = &pix_fmt_info[src_pix_fmt]; |
426 |
pf = &pix_fmt_info[dst_pix_fmt]; |
427 |
|
428 |
/* compute loss */
|
429 |
loss = 0;
|
430 |
pf = &pix_fmt_info[dst_pix_fmt]; |
431 |
if (pf->depth < ps->depth ||
|
432 |
(dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565)) |
433 |
loss |= FF_LOSS_DEPTH; |
434 |
if (pf->x_chroma_shift > ps->x_chroma_shift ||
|
435 |
pf->y_chroma_shift > ps->y_chroma_shift) |
436 |
loss |= FF_LOSS_RESOLUTION; |
437 |
switch(pf->color_type) {
|
438 |
case FF_COLOR_RGB:
|
439 |
if (ps->color_type != FF_COLOR_RGB &&
|
440 |
ps->color_type != FF_COLOR_GRAY) |
441 |
loss |= FF_LOSS_COLORSPACE; |
442 |
break;
|
443 |
case FF_COLOR_GRAY:
|
444 |
if (ps->color_type != FF_COLOR_GRAY)
|
445 |
loss |= FF_LOSS_COLORSPACE; |
446 |
break;
|
447 |
case FF_COLOR_YUV:
|
448 |
if (ps->color_type != FF_COLOR_YUV)
|
449 |
loss |= FF_LOSS_COLORSPACE; |
450 |
break;
|
451 |
case FF_COLOR_YUV_JPEG:
|
452 |
if (ps->color_type != FF_COLOR_YUV_JPEG &&
|
453 |
ps->color_type != FF_COLOR_YUV && |
454 |
ps->color_type != FF_COLOR_GRAY) |
455 |
loss |= FF_LOSS_COLORSPACE; |
456 |
break;
|
457 |
default:
|
458 |
/* fail safe test */
|
459 |
if (ps->color_type != pf->color_type)
|
460 |
loss |= FF_LOSS_COLORSPACE; |
461 |
break;
|
462 |
} |
463 |
if (pf->color_type == FF_COLOR_GRAY &&
|
464 |
ps->color_type != FF_COLOR_GRAY) |
465 |
loss |= FF_LOSS_CHROMA; |
466 |
if (!pf->is_alpha && (ps->is_alpha && has_alpha))
|
467 |
loss |= FF_LOSS_ALPHA; |
468 |
if (pf->pixel_type == FF_PIXEL_PALETTE &&
|
469 |
(ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY)) |
470 |
loss |= FF_LOSS_COLORQUANT; |
471 |
return loss;
|
472 |
} |
473 |
|
474 |
static int avg_bits_per_pixel(int pix_fmt) |
475 |
{ |
476 |
int bits;
|
477 |
const PixFmtInfo *pf;
|
478 |
|
479 |
pf = &pix_fmt_info[pix_fmt]; |
480 |
switch(pf->pixel_type) {
|
481 |
case FF_PIXEL_PACKED:
|
482 |
switch(pix_fmt) {
|
483 |
case PIX_FMT_YUV422:
|
484 |
case PIX_FMT_UYVY422:
|
485 |
case PIX_FMT_RGB565:
|
486 |
case PIX_FMT_RGB555:
|
487 |
bits = 16;
|
488 |
break;
|
489 |
case PIX_FMT_UYVY411:
|
490 |
bits = 12;
|
491 |
break;
|
492 |
default:
|
493 |
bits = pf->depth * pf->nb_channels; |
494 |
break;
|
495 |
} |
496 |
break;
|
497 |
case FF_PIXEL_PLANAR:
|
498 |
if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) { |
499 |
bits = pf->depth * pf->nb_channels; |
500 |
} else {
|
501 |
bits = pf->depth + ((2 * pf->depth) >>
|
502 |
(pf->x_chroma_shift + pf->y_chroma_shift)); |
503 |
} |
504 |
break;
|
505 |
case FF_PIXEL_PALETTE:
|
506 |
bits = 8;
|
507 |
break;
|
508 |
default:
|
509 |
bits = -1;
|
510 |
break;
|
511 |
} |
512 |
return bits;
|
513 |
} |
514 |
|
515 |
static int avcodec_find_best_pix_fmt1(int pix_fmt_mask, |
516 |
int src_pix_fmt,
|
517 |
int has_alpha,
|
518 |
int loss_mask)
|
519 |
{ |
520 |
int dist, i, loss, min_dist, dst_pix_fmt;
|
521 |
|
522 |
/* find exact color match with smallest size */
|
523 |
dst_pix_fmt = -1;
|
524 |
min_dist = 0x7fffffff;
|
525 |
for(i = 0;i < PIX_FMT_NB; i++) { |
526 |
if (pix_fmt_mask & (1 << i)) { |
527 |
loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask; |
528 |
if (loss == 0) { |
529 |
dist = avg_bits_per_pixel(i); |
530 |
if (dist < min_dist) {
|
531 |
min_dist = dist; |
532 |
dst_pix_fmt = i; |
533 |
} |
534 |
} |
535 |
} |
536 |
} |
537 |
return dst_pix_fmt;
|
538 |
} |
539 |
|
540 |
/**
|
541 |
* find best pixel format to convert to. Return -1 if none found
|
542 |
*/
|
543 |
int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt, |
544 |
int has_alpha, int *loss_ptr) |
545 |
{ |
546 |
int dst_pix_fmt, loss_mask, i;
|
547 |
static const int loss_mask_order[] = { |
548 |
~0, /* no loss first */ |
549 |
~FF_LOSS_ALPHA, |
550 |
~FF_LOSS_RESOLUTION, |
551 |
~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), |
552 |
~FF_LOSS_COLORQUANT, |
553 |
~FF_LOSS_DEPTH, |
554 |
0,
|
555 |
}; |
556 |
|
557 |
/* try with successive loss */
|
558 |
i = 0;
|
559 |
for(;;) {
|
560 |
loss_mask = loss_mask_order[i++]; |
561 |
dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt, |
562 |
has_alpha, loss_mask); |
563 |
if (dst_pix_fmt >= 0) |
564 |
goto found;
|
565 |
if (loss_mask == 0) |
566 |
break;
|
567 |
} |
568 |
return -1; |
569 |
found:
|
570 |
if (loss_ptr)
|
571 |
*loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); |
572 |
return dst_pix_fmt;
|
573 |
} |
574 |
|
575 |
static void img_copy_plane(uint8_t *dst, int dst_wrap, |
576 |
const uint8_t *src, int src_wrap, |
577 |
int width, int height) |
578 |
{ |
579 |
if((!dst) || (!src))
|
580 |
return;
|
581 |
for(;height > 0; height--) { |
582 |
memcpy(dst, src, width); |
583 |
dst += dst_wrap; |
584 |
src += src_wrap; |
585 |
} |
586 |
} |
587 |
|
588 |
/**
|
589 |
* Copy image 'src' to 'dst'.
|
590 |
*/
|
591 |
void img_copy(AVPicture *dst, const AVPicture *src, |
592 |
int pix_fmt, int width, int height) |
593 |
{ |
594 |
int bwidth, bits, i;
|
595 |
PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; |
596 |
|
597 |
pf = &pix_fmt_info[pix_fmt]; |
598 |
switch(pf->pixel_type) {
|
599 |
case FF_PIXEL_PACKED:
|
600 |
switch(pix_fmt) {
|
601 |
case PIX_FMT_YUV422:
|
602 |
case PIX_FMT_UYVY422:
|
603 |
case PIX_FMT_RGB565:
|
604 |
case PIX_FMT_RGB555:
|
605 |
bits = 16;
|
606 |
break;
|
607 |
case PIX_FMT_UYVY411:
|
608 |
bits = 12;
|
609 |
break;
|
610 |
default:
|
611 |
bits = pf->depth * pf->nb_channels; |
612 |
break;
|
613 |
} |
614 |
bwidth = (width * bits + 7) >> 3; |
615 |
img_copy_plane(dst->data[0], dst->linesize[0], |
616 |
src->data[0], src->linesize[0], |
617 |
bwidth, height); |
618 |
break;
|
619 |
case FF_PIXEL_PLANAR:
|
620 |
for(i = 0; i < pf->nb_channels; i++) { |
621 |
int w, h;
|
622 |
w = width; |
623 |
h = height; |
624 |
if (i == 1 || i == 2) { |
625 |
w >>= pf->x_chroma_shift; |
626 |
h >>= pf->y_chroma_shift; |
627 |
} |
628 |
bwidth = (w * pf->depth + 7) >> 3; |
629 |
img_copy_plane(dst->data[i], dst->linesize[i], |
630 |
src->data[i], src->linesize[i], |
631 |
bwidth, h); |
632 |
} |
633 |
break;
|
634 |
case FF_PIXEL_PALETTE:
|
635 |
img_copy_plane(dst->data[0], dst->linesize[0], |
636 |
src->data[0], src->linesize[0], |
637 |
width, height); |
638 |
/* copy the palette */
|
639 |
img_copy_plane(dst->data[1], dst->linesize[1], |
640 |
src->data[1], src->linesize[1], |
641 |
4, 256); |
642 |
break;
|
643 |
} |
644 |
} |
645 |
|
646 |
/* XXX: totally non optimized */
|
647 |
|
648 |
static void yuv422_to_yuv420p(AVPicture *dst, const AVPicture *src, |
649 |
int width, int height) |
650 |
{ |
651 |
const uint8_t *p, *p1;
|
652 |
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; |
653 |
int w;
|
654 |
|
655 |
p1 = src->data[0];
|
656 |
lum1 = dst->data[0];
|
657 |
cb1 = dst->data[1];
|
658 |
cr1 = dst->data[2];
|
659 |
|
660 |
for(;height >= 1; height -= 2) { |
661 |
p = p1; |
662 |
lum = lum1; |
663 |
cb = cb1; |
664 |
cr = cr1; |
665 |
for(w = width; w >= 2; w -= 2) { |
666 |
lum[0] = p[0]; |
667 |
cb[0] = p[1]; |
668 |
lum[1] = p[2]; |
669 |
cr[0] = p[3]; |
670 |
p += 4;
|
671 |
lum += 2;
|
672 |
cb++; |
673 |
cr++; |
674 |
} |
675 |
if (w) {
|
676 |
lum[0] = p[0]; |
677 |
cb[0] = p[1]; |
678 |
cr[0] = p[3]; |
679 |
cb++; |
680 |
cr++; |
681 |
} |
682 |
p1 += src->linesize[0];
|
683 |
lum1 += dst->linesize[0];
|
684 |
if (height>1) { |
685 |
p = p1; |
686 |
lum = lum1; |
687 |
for(w = width; w >= 2; w -= 2) { |
688 |
lum[0] = p[0]; |
689 |
lum[1] = p[2]; |
690 |
p += 4;
|
691 |
lum += 2;
|
692 |
} |
693 |
if (w) {
|
694 |
lum[0] = p[0]; |
695 |
} |
696 |
p1 += src->linesize[0];
|
697 |
lum1 += dst->linesize[0];
|
698 |
} |
699 |
cb1 += dst->linesize[1];
|
700 |
cr1 += dst->linesize[2];
|
701 |
} |
702 |
} |
703 |
|
704 |
static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src, |
705 |
int width, int height) |
706 |
{ |
707 |
const uint8_t *p, *p1;
|
708 |
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; |
709 |
int w;
|
710 |
|
711 |
p1 = src->data[0];
|
712 |
|
713 |
lum1 = dst->data[0];
|
714 |
cb1 = dst->data[1];
|
715 |
cr1 = dst->data[2];
|
716 |
|
717 |
for(;height >= 1; height -= 2) { |
718 |
p = p1; |
719 |
lum = lum1; |
720 |
cb = cb1; |
721 |
cr = cr1; |
722 |
for(w = width; w >= 2; w -= 2) { |
723 |
lum[0] = p[1]; |
724 |
cb[0] = p[0]; |
725 |
lum[1] = p[3]; |
726 |
cr[0] = p[2]; |
727 |
p += 4;
|
728 |
lum += 2;
|
729 |
cb++; |
730 |
cr++; |
731 |
} |
732 |
if (w) {
|
733 |
lum[0] = p[1]; |
734 |
cb[0] = p[0]; |
735 |
cr[0] = p[2]; |
736 |
cb++; |
737 |
cr++; |
738 |
} |
739 |
p1 += src->linesize[0];
|
740 |
lum1 += dst->linesize[0];
|
741 |
if (height>1) { |
742 |
p = p1; |
743 |
lum = lum1; |
744 |
for(w = width; w >= 2; w -= 2) { |
745 |
lum[0] = p[1]; |
746 |
lum[1] = p[3]; |
747 |
p += 4;
|
748 |
lum += 2;
|
749 |
} |
750 |
if (w) {
|
751 |
lum[0] = p[1]; |
752 |
} |
753 |
p1 += src->linesize[0];
|
754 |
lum1 += dst->linesize[0];
|
755 |
} |
756 |
cb1 += dst->linesize[1];
|
757 |
cr1 += dst->linesize[2];
|
758 |
} |
759 |
} |
760 |
|
761 |
|
762 |
static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src, |
763 |
int width, int height) |
764 |
{ |
765 |
const uint8_t *p, *p1;
|
766 |
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; |
767 |
int w;
|
768 |
|
769 |
p1 = src->data[0];
|
770 |
lum1 = dst->data[0];
|
771 |
cb1 = dst->data[1];
|
772 |
cr1 = dst->data[2];
|
773 |
for(;height > 0; height--) { |
774 |
p = p1; |
775 |
lum = lum1; |
776 |
cb = cb1; |
777 |
cr = cr1; |
778 |
for(w = width; w >= 2; w -= 2) { |
779 |
lum[0] = p[1]; |
780 |
cb[0] = p[0]; |
781 |
lum[1] = p[3]; |
782 |
cr[0] = p[2]; |
783 |
p += 4;
|
784 |
lum += 2;
|
785 |
cb++; |
786 |
cr++; |
787 |
} |
788 |
p1 += src->linesize[0];
|
789 |
lum1 += dst->linesize[0];
|
790 |
cb1 += dst->linesize[1];
|
791 |
cr1 += dst->linesize[2];
|
792 |
} |
793 |
} |
794 |
|
795 |
|
796 |
static void yuv422_to_yuv422p(AVPicture *dst, const AVPicture *src, |
797 |
int width, int height) |
798 |
{ |
799 |
const uint8_t *p, *p1;
|
800 |
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; |
801 |
int w;
|
802 |
|
803 |
p1 = src->data[0];
|
804 |
lum1 = dst->data[0];
|
805 |
cb1 = dst->data[1];
|
806 |
cr1 = dst->data[2];
|
807 |
for(;height > 0; height--) { |
808 |
p = p1; |
809 |
lum = lum1; |
810 |
cb = cb1; |
811 |
cr = cr1; |
812 |
for(w = width; w >= 2; w -= 2) { |
813 |
lum[0] = p[0]; |
814 |
cb[0] = p[1]; |
815 |
lum[1] = p[2]; |
816 |
cr[0] = p[3]; |
817 |
p += 4;
|
818 |
lum += 2;
|
819 |
cb++; |
820 |
cr++; |
821 |
} |
822 |
p1 += src->linesize[0];
|
823 |
lum1 += dst->linesize[0];
|
824 |
cb1 += dst->linesize[1];
|
825 |
cr1 += dst->linesize[2];
|
826 |
} |
827 |
} |
828 |
|
829 |
static void yuv422p_to_yuv422(AVPicture *dst, const AVPicture *src, |
830 |
int width, int height) |
831 |
{ |
832 |
uint8_t *p, *p1; |
833 |
const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
|
834 |
int w;
|
835 |
|
836 |
p1 = dst->data[0];
|
837 |
lum1 = src->data[0];
|
838 |
cb1 = src->data[1];
|
839 |
cr1 = src->data[2];
|
840 |
for(;height > 0; height--) { |
841 |
p = p1; |
842 |
lum = lum1; |
843 |
cb = cb1; |
844 |
cr = cr1; |
845 |
for(w = width; w >= 2; w -= 2) { |
846 |
p[0] = lum[0]; |
847 |
p[1] = cb[0]; |
848 |
p[2] = lum[1]; |
849 |
p[3] = cr[0]; |
850 |
p += 4;
|
851 |
lum += 2;
|
852 |
cb++; |
853 |
cr++; |
854 |
} |
855 |
p1 += dst->linesize[0];
|
856 |
lum1 += src->linesize[0];
|
857 |
cb1 += src->linesize[1];
|
858 |
cr1 += src->linesize[2];
|
859 |
} |
860 |
} |
861 |
|
862 |
static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src, |
863 |
int width, int height) |
864 |
{ |
865 |
uint8_t *p, *p1; |
866 |
const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
|
867 |
int w;
|
868 |
|
869 |
p1 = dst->data[0];
|
870 |
lum1 = src->data[0];
|
871 |
cb1 = src->data[1];
|
872 |
cr1 = src->data[2];
|
873 |
for(;height > 0; height--) { |
874 |
p = p1; |
875 |
lum = lum1; |
876 |
cb = cb1; |
877 |
cr = cr1; |
878 |
for(w = width; w >= 2; w -= 2) { |
879 |
p[1] = lum[0]; |
880 |
p[0] = cb[0]; |
881 |
p[3] = lum[1]; |
882 |
p[2] = cr[0]; |
883 |
p += 4;
|
884 |
lum += 2;
|
885 |
cb++; |
886 |
cr++; |
887 |
} |
888 |
p1 += dst->linesize[0];
|
889 |
lum1 += src->linesize[0];
|
890 |
cb1 += src->linesize[1];
|
891 |
cr1 += src->linesize[2];
|
892 |
} |
893 |
} |
894 |
|
895 |
static void uyvy411_to_yuv411p(AVPicture *dst, const AVPicture *src, |
896 |
int width, int height) |
897 |
{ |
898 |
const uint8_t *p, *p1;
|
899 |
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; |
900 |
int w;
|
901 |
|
902 |
p1 = src->data[0];
|
903 |
lum1 = dst->data[0];
|
904 |
cb1 = dst->data[1];
|
905 |
cr1 = dst->data[2];
|
906 |
for(;height > 0; height--) { |
907 |
p = p1; |
908 |
lum = lum1; |
909 |
cb = cb1; |
910 |
cr = cr1; |
911 |
for(w = width; w >= 4; w -= 4) { |
912 |
cb[0] = p[0]; |
913 |
lum[0] = p[1]; |
914 |
lum[1] = p[2]; |
915 |
cr[0] = p[3]; |
916 |
lum[2] = p[4]; |
917 |
lum[3] = p[5]; |
918 |
p += 6;
|
919 |
lum += 4;
|
920 |
cb++; |
921 |
cr++; |
922 |
} |
923 |
p1 += src->linesize[0];
|
924 |
lum1 += dst->linesize[0];
|
925 |
cb1 += dst->linesize[1];
|
926 |
cr1 += dst->linesize[2];
|
927 |
} |
928 |
} |
929 |
|
930 |
|
931 |
static void yuv420p_to_yuv422(AVPicture *dst, const AVPicture *src, |
932 |
int width, int height) |
933 |
{ |
934 |
int w, h;
|
935 |
uint8_t *line1, *line2, *linesrc = dst->data[0];
|
936 |
uint8_t *lum1, *lum2, *lumsrc = src->data[0];
|
937 |
uint8_t *cb1, *cb2 = src->data[1];
|
938 |
uint8_t *cr1, *cr2 = src->data[2];
|
939 |
|
940 |
for(h = height / 2; h--;) { |
941 |
line1 = linesrc; |
942 |
line2 = linesrc + dst->linesize[0];
|
943 |
|
944 |
lum1 = lumsrc; |
945 |
lum2 = lumsrc + src->linesize[0];
|
946 |
|
947 |
cb1 = cb2; |
948 |
cr1 = cr2; |
949 |
|
950 |
for(w = width / 2; w--;) { |
951 |
*line1++ = *lum1++; *line2++ = *lum2++; |
952 |
*line1++ = *line2++ = *cb1++; |
953 |
*line1++ = *lum1++; *line2++ = *lum2++; |
954 |
*line1++ = *line2++ = *cr1++; |
955 |
} |
956 |
|
957 |
linesrc += dst->linesize[0] * 2; |
958 |
lumsrc += src->linesize[0] * 2; |
959 |
cb2 += src->linesize[1];
|
960 |
cr2 += src->linesize[2];
|
961 |
} |
962 |
} |
963 |
|
964 |
static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src, |
965 |
int width, int height) |
966 |
{ |
967 |
int w, h;
|
968 |
uint8_t *line1, *line2, *linesrc = dst->data[0];
|
969 |
uint8_t *lum1, *lum2, *lumsrc = src->data[0];
|
970 |
uint8_t *cb1, *cb2 = src->data[1];
|
971 |
uint8_t *cr1, *cr2 = src->data[2];
|
972 |
|
973 |
for(h = height / 2; h--;) { |
974 |
line1 = linesrc; |
975 |
line2 = linesrc + dst->linesize[0];
|
976 |
|
977 |
lum1 = lumsrc; |
978 |
lum2 = lumsrc + src->linesize[0];
|
979 |
|
980 |
cb1 = cb2; |
981 |
cr1 = cr2; |
982 |
|
983 |
for(w = width / 2; w--;) { |
984 |
*line1++ = *line2++ = *cb1++; |
985 |
*line1++ = *lum1++; *line2++ = *lum2++; |
986 |
*line1++ = *line2++ = *cr1++; |
987 |
*line1++ = *lum1++; *line2++ = *lum2++; |
988 |
} |
989 |
|
990 |
linesrc += dst->linesize[0] * 2; |
991 |
lumsrc += src->linesize[0] * 2; |
992 |
cb2 += src->linesize[1];
|
993 |
cr2 += src->linesize[2];
|
994 |
} |
995 |
} |
996 |
|
997 |
#define SCALEBITS 10 |
998 |
#define ONE_HALF (1 << (SCALEBITS - 1)) |
999 |
#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) |
1000 |
|
1001 |
#define YUV_TO_RGB1_CCIR(cb1, cr1)\
|
1002 |
{\ |
1003 |
cb = (cb1) - 128;\
|
1004 |
cr = (cr1) - 128;\
|
1005 |
r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\ |
1006 |
g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \ |
1007 |
ONE_HALF;\ |
1008 |
b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\ |
1009 |
} |
1010 |
|
1011 |
#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
|
1012 |
{\ |
1013 |
y = ((y1) - 16) * FIX(255.0/219.0);\ |
1014 |
r = cm[(y + r_add) >> SCALEBITS];\ |
1015 |
g = cm[(y + g_add) >> SCALEBITS];\ |
1016 |
b = cm[(y + b_add) >> SCALEBITS];\ |
1017 |
} |
1018 |
|
1019 |
#define YUV_TO_RGB1(cb1, cr1)\
|
1020 |
{\ |
1021 |
cb = (cb1) - 128;\
|
1022 |
cr = (cr1) - 128;\
|
1023 |
r_add = FIX(1.40200) * cr + ONE_HALF;\ |
1024 |
g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ |
1025 |
b_add = FIX(1.77200) * cb + ONE_HALF;\ |
1026 |
} |
1027 |
|
1028 |
#define YUV_TO_RGB2(r, g, b, y1)\
|
1029 |
{\ |
1030 |
y = (y1) << SCALEBITS;\ |
1031 |
r = cm[(y + r_add) >> SCALEBITS];\ |
1032 |
g = cm[(y + g_add) >> SCALEBITS];\ |
1033 |
b = cm[(y + b_add) >> SCALEBITS];\ |
1034 |
} |
1035 |
|
1036 |
#define Y_CCIR_TO_JPEG(y)\
|
1037 |
cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] |
1038 |
|
1039 |
#define Y_JPEG_TO_CCIR(y)\
|
1040 |
(((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) |
1041 |
|
1042 |
#define C_CCIR_TO_JPEG(y)\
|
1043 |
cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] |
1044 |
|
1045 |
/* NOTE: the clamp is really necessary! */
|
1046 |
static inline int C_JPEG_TO_CCIR(int y) { |
1047 |
y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); |
1048 |
if (y < 16) |
1049 |
y = 16;
|
1050 |
return y;
|
1051 |
} |
1052 |
|
1053 |
|
1054 |
#define RGB_TO_Y(r, g, b) \
|
1055 |
((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ |
1056 |
FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) |
1057 |
|
1058 |
#define RGB_TO_U(r1, g1, b1, shift)\
|
1059 |
(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ |
1060 |
FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
1061 |
|
1062 |
#define RGB_TO_V(r1, g1, b1, shift)\
|
1063 |
(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ |
1064 |
FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
1065 |
|
1066 |
#define RGB_TO_Y_CCIR(r, g, b) \
|
1067 |
((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ |
1068 |
FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) |
1069 |
|
1070 |
#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
|
1071 |
(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ |
1072 |
FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
1073 |
|
1074 |
#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
|
1075 |
(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ |
1076 |
FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) |
1077 |
|
1078 |
static uint8_t y_ccir_to_jpeg[256]; |
1079 |
static uint8_t y_jpeg_to_ccir[256]; |
1080 |
static uint8_t c_ccir_to_jpeg[256]; |
1081 |
static uint8_t c_jpeg_to_ccir[256]; |
1082 |
|
1083 |
/* init various conversion tables */
|
1084 |
static void img_convert_init(void) |
1085 |
{ |
1086 |
int i;
|
1087 |
uint8_t *cm = cropTbl + MAX_NEG_CROP; |
1088 |
|
1089 |
for(i = 0;i < 256; i++) { |
1090 |
y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i); |
1091 |
y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i); |
1092 |
c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i); |
1093 |
c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i); |
1094 |
} |
1095 |
} |
1096 |
|
1097 |
/* apply to each pixel the given table */
|
1098 |
static void img_apply_table(uint8_t *dst, int dst_wrap, |
1099 |
const uint8_t *src, int src_wrap, |
1100 |
int width, int height, const uint8_t *table1) |
1101 |
{ |
1102 |
int n;
|
1103 |
const uint8_t *s;
|
1104 |
uint8_t *d; |
1105 |
const uint8_t *table;
|
1106 |
|
1107 |
table = table1; |
1108 |
for(;height > 0; height--) { |
1109 |
s = src; |
1110 |
d = dst; |
1111 |
n = width; |
1112 |
while (n >= 4) { |
1113 |
d[0] = table[s[0]]; |
1114 |
d[1] = table[s[1]]; |
1115 |
d[2] = table[s[2]]; |
1116 |
d[3] = table[s[3]]; |
1117 |
d += 4;
|
1118 |
s += 4;
|
1119 |
n -= 4;
|
1120 |
} |
1121 |
while (n > 0) { |
1122 |
d[0] = table[s[0]]; |
1123 |
d++; |
1124 |
s++; |
1125 |
n--; |
1126 |
} |
1127 |
dst += dst_wrap; |
1128 |
src += src_wrap; |
1129 |
} |
1130 |
} |
1131 |
|
1132 |
/* XXX: use generic filter ? */
|
1133 |
/* XXX: in most cases, the sampling position is incorrect */
|
1134 |
|
1135 |
/* 4x1 -> 1x1 */
|
1136 |
static void shrink41(uint8_t *dst, int dst_wrap, |
1137 |
const uint8_t *src, int src_wrap, |
1138 |
int width, int height) |
1139 |
{ |
1140 |
int w;
|
1141 |
const uint8_t *s;
|
1142 |
uint8_t *d; |
1143 |
|
1144 |
for(;height > 0; height--) { |
1145 |
s = src; |
1146 |
d = dst; |
1147 |
for(w = width;w > 0; w--) { |
1148 |
d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2; |
1149 |
s += 4;
|
1150 |
d++; |
1151 |
} |
1152 |
src += src_wrap; |
1153 |
dst += dst_wrap; |
1154 |
} |
1155 |
} |
1156 |
|
1157 |
/* 2x1 -> 1x1 */
|
1158 |
static void shrink21(uint8_t *dst, int dst_wrap, |
1159 |
const uint8_t *src, int src_wrap, |
1160 |
int width, int height) |
1161 |
{ |
1162 |
int w;
|
1163 |
const uint8_t *s;
|
1164 |
uint8_t *d; |
1165 |
|
1166 |
for(;height > 0; height--) { |
1167 |
s = src; |
1168 |
d = dst; |
1169 |
for(w = width;w > 0; w--) { |
1170 |
d[0] = (s[0] + s[1]) >> 1; |
1171 |
s += 2;
|
1172 |
d++; |
1173 |
} |
1174 |
src += src_wrap; |
1175 |
dst += dst_wrap; |
1176 |
} |
1177 |
} |
1178 |
|
1179 |
/* 1x2 -> 1x1 */
|
1180 |
static void shrink12(uint8_t *dst, int dst_wrap, |
1181 |
const uint8_t *src, int src_wrap, |
1182 |
int width, int height) |
1183 |
{ |
1184 |
int w;
|
1185 |
uint8_t *d; |
1186 |
const uint8_t *s1, *s2;
|
1187 |
|
1188 |
for(;height > 0; height--) { |
1189 |
s1 = src; |
1190 |
s2 = s1 + src_wrap; |
1191 |
d = dst; |
1192 |
for(w = width;w >= 4; w-=4) { |
1193 |
d[0] = (s1[0] + s2[0]) >> 1; |
1194 |
d[1] = (s1[1] + s2[1]) >> 1; |
1195 |
d[2] = (s1[2] + s2[2]) >> 1; |
1196 |
d[3] = (s1[3] + s2[3]) >> 1; |
1197 |
s1 += 4;
|
1198 |
s2 += 4;
|
1199 |
d += 4;
|
1200 |
} |
1201 |
for(;w > 0; w--) { |
1202 |
d[0] = (s1[0] + s2[0]) >> 1; |
1203 |
s1++; |
1204 |
s2++; |
1205 |
d++; |
1206 |
} |
1207 |
src += 2 * src_wrap;
|
1208 |
dst += dst_wrap; |
1209 |
} |
1210 |
} |
1211 |
|
1212 |
/* 2x2 -> 1x1 */
|
1213 |
static void shrink22(uint8_t *dst, int dst_wrap, |
1214 |
const uint8_t *src, int src_wrap, |
1215 |
int width, int height) |
1216 |
{ |
1217 |
int w;
|
1218 |
const uint8_t *s1, *s2;
|
1219 |
uint8_t *d; |
1220 |
|
1221 |
for(;height > 0; height--) { |
1222 |
s1 = src; |
1223 |
s2 = s1 + src_wrap; |
1224 |
d = dst; |
1225 |
for(w = width;w >= 4; w-=4) { |
1226 |
d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; |
1227 |
d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; |
1228 |
d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; |
1229 |
d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; |
1230 |
s1 += 8;
|
1231 |
s2 += 8;
|
1232 |
d += 4;
|
1233 |
} |
1234 |
for(;w > 0; w--) { |
1235 |
d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; |
1236 |
s1 += 2;
|
1237 |
s2 += 2;
|
1238 |
d++; |
1239 |
} |
1240 |
src += 2 * src_wrap;
|
1241 |
dst += dst_wrap; |
1242 |
} |
1243 |
} |
1244 |
|
1245 |
/* 4x4 -> 1x1 */
|
1246 |
static void shrink44(uint8_t *dst, int dst_wrap, |
1247 |
const uint8_t *src, int src_wrap, |
1248 |
int width, int height) |
1249 |
{ |
1250 |
int w;
|
1251 |
const uint8_t *s1, *s2, *s3, *s4;
|
1252 |
uint8_t *d; |
1253 |
|
1254 |
for(;height > 0; height--) { |
1255 |
s1 = src; |
1256 |
s2 = s1 + src_wrap; |
1257 |
s3 = s2 + src_wrap; |
1258 |
s4 = s3 + src_wrap; |
1259 |
d = dst; |
1260 |
for(w = width;w > 0; w--) { |
1261 |
d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + |
1262 |
s2[0] + s2[1] + s2[2] + s2[3] + |
1263 |
s3[0] + s3[1] + s3[2] + s3[3] + |
1264 |
s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; |
1265 |
s1 += 4;
|
1266 |
s2 += 4;
|
1267 |
s3 += 4;
|
1268 |
s4 += 4;
|
1269 |
d++; |
1270 |
} |
1271 |
src += 4 * src_wrap;
|
1272 |
dst += dst_wrap; |
1273 |
} |
1274 |
} |
1275 |
|
1276 |
static void grow21_line(uint8_t *dst, const uint8_t *src, |
1277 |
int width)
|
1278 |
{ |
1279 |
int w;
|
1280 |
const uint8_t *s1;
|
1281 |
uint8_t *d; |
1282 |
|
1283 |
s1 = src; |
1284 |
d = dst; |
1285 |
for(w = width;w >= 4; w-=4) { |
1286 |
d[1] = d[0] = s1[0]; |
1287 |
d[3] = d[2] = s1[1]; |
1288 |
s1 += 2;
|
1289 |
d += 4;
|
1290 |
} |
1291 |
for(;w >= 2; w -= 2) { |
1292 |
d[1] = d[0] = s1[0]; |
1293 |
s1 ++; |
1294 |
d += 2;
|
1295 |
} |
1296 |
/* only needed if width is not a multiple of two */
|
1297 |
/* XXX: veryfy that */
|
1298 |
if (w) {
|
1299 |
d[0] = s1[0]; |
1300 |
} |
1301 |
} |
1302 |
|
1303 |
static void grow41_line(uint8_t *dst, const uint8_t *src, |
1304 |
int width)
|
1305 |
{ |
1306 |
int w, v;
|
1307 |
const uint8_t *s1;
|
1308 |
uint8_t *d; |
1309 |
|
1310 |
s1 = src; |
1311 |
d = dst; |
1312 |
for(w = width;w >= 4; w-=4) { |
1313 |
v = s1[0];
|
1314 |
d[0] = v;
|
1315 |
d[1] = v;
|
1316 |
d[2] = v;
|
1317 |
d[3] = v;
|
1318 |
s1 ++; |
1319 |
d += 4;
|
1320 |
} |
1321 |
} |
1322 |
|
1323 |
/* 1x1 -> 2x1 */
|
1324 |
static void grow21(uint8_t *dst, int dst_wrap, |
1325 |
const uint8_t *src, int src_wrap, |
1326 |
int width, int height) |
1327 |
{ |
1328 |
for(;height > 0; height--) { |
1329 |
grow21_line(dst, src, width); |
1330 |
src += src_wrap; |
1331 |
dst += dst_wrap; |
1332 |
} |
1333 |
} |
1334 |
|
1335 |
/* 1x1 -> 2x2 */
|
1336 |
static void grow22(uint8_t *dst, int dst_wrap, |
1337 |
const uint8_t *src, int src_wrap, |
1338 |
int width, int height) |
1339 |
{ |
1340 |
for(;height > 0; height--) { |
1341 |
grow21_line(dst, src, width); |
1342 |
if (height%2) |
1343 |
src += src_wrap; |
1344 |
dst += dst_wrap; |
1345 |
} |
1346 |
} |
1347 |
|
1348 |
/* 1x1 -> 4x1 */
|
1349 |
static void grow41(uint8_t *dst, int dst_wrap, |
1350 |
const uint8_t *src, int src_wrap, |
1351 |
int width, int height) |
1352 |
{ |
1353 |
for(;height > 0; height--) { |
1354 |
grow41_line(dst, src, width); |
1355 |
src += src_wrap; |
1356 |
dst += dst_wrap; |
1357 |
} |
1358 |
} |
1359 |
|
1360 |
/* 1x1 -> 4x4 */
|
1361 |
static void grow44(uint8_t *dst, int dst_wrap, |
1362 |
const uint8_t *src, int src_wrap, |
1363 |
int width, int height) |
1364 |
{ |
1365 |
for(;height > 0; height--) { |
1366 |
grow41_line(dst, src, width); |
1367 |
if ((height & 3) == 1) |
1368 |
src += src_wrap; |
1369 |
dst += dst_wrap; |
1370 |
} |
1371 |
} |
1372 |
|
1373 |
/* 1x2 -> 2x1 */
|
1374 |
static void conv411(uint8_t *dst, int dst_wrap, |
1375 |
const uint8_t *src, int src_wrap, |
1376 |
int width, int height) |
1377 |
{ |
1378 |
int w, c;
|
1379 |
const uint8_t *s1, *s2;
|
1380 |
uint8_t *d; |
1381 |
|
1382 |
width>>=1;
|
1383 |
|
1384 |
for(;height > 0; height--) { |
1385 |
s1 = src; |
1386 |
s2 = src + src_wrap; |
1387 |
d = dst; |
1388 |
for(w = width;w > 0; w--) { |
1389 |
c = (s1[0] + s2[0]) >> 1; |
1390 |
d[0] = c;
|
1391 |
d[1] = c;
|
1392 |
s1++; |
1393 |
s2++; |
1394 |
d += 2;
|
1395 |
} |
1396 |
src += src_wrap * 2;
|
1397 |
dst += dst_wrap; |
1398 |
} |
1399 |
} |
1400 |
|
1401 |
/* XXX: add jpeg quantize code */
|
1402 |
|
1403 |
#define TRANSP_INDEX (6*6*6) |
1404 |
|
1405 |
/* this is maybe slow, but allows for extensions */
|
1406 |
static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b) |
1407 |
{ |
1408 |
return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6)); |
1409 |
} |
1410 |
|
1411 |
static void build_rgb_palette(uint8_t *palette, int has_alpha) |
1412 |
{ |
1413 |
uint32_t *pal; |
1414 |
static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; |
1415 |
int i, r, g, b;
|
1416 |
|
1417 |
pal = (uint32_t *)palette; |
1418 |
i = 0;
|
1419 |
for(r = 0; r < 6; r++) { |
1420 |
for(g = 0; g < 6; g++) { |
1421 |
for(b = 0; b < 6; b++) { |
1422 |
pal[i++] = (0xff << 24) | (pal_value[r] << 16) | |
1423 |
(pal_value[g] << 8) | pal_value[b];
|
1424 |
} |
1425 |
} |
1426 |
} |
1427 |
if (has_alpha)
|
1428 |
pal[i++] = 0;
|
1429 |
while (i < 256) |
1430 |
pal[i++] = 0xff000000;
|
1431 |
} |
1432 |
|
1433 |
/* copy bit n to bits 0 ... n - 1 */
|
1434 |
static inline unsigned int bitcopy_n(unsigned int a, int n) |
1435 |
{ |
1436 |
int mask;
|
1437 |
mask = (1 << n) - 1; |
1438 |
return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask); |
1439 |
} |
1440 |
|
1441 |
/* rgb555 handling */
|
1442 |
|
1443 |
#define RGB_NAME rgb555
|
1444 |
|
1445 |
#define RGB_IN(r, g, b, s)\
|
1446 |
{\ |
1447 |
unsigned int v = ((const uint16_t *)(s))[0];\ |
1448 |
r = bitcopy_n(v >> (10 - 3), 3);\ |
1449 |
g = bitcopy_n(v >> (5 - 3), 3);\ |
1450 |
b = bitcopy_n(v << 3, 3);\ |
1451 |
} |
1452 |
|
1453 |
#define RGBA_IN(r, g, b, a, s)\
|
1454 |
{\ |
1455 |
unsigned int v = ((const uint16_t *)(s))[0];\ |
1456 |
r = bitcopy_n(v >> (10 - 3), 3);\ |
1457 |
g = bitcopy_n(v >> (5 - 3), 3);\ |
1458 |
b = bitcopy_n(v << 3, 3);\ |
1459 |
a = (-(v >> 15)) & 0xff;\ |
1460 |
} |
1461 |
|
1462 |
#define RGBA_OUT(d, r, g, b, a)\
|
1463 |
{\ |
1464 |
((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \ |
1465 |
((a << 8) & 0x8000);\ |
1466 |
} |
1467 |
|
1468 |
#define BPP 2 |
1469 |
|
1470 |
#include "imgconvert_template.h" |
1471 |
|
1472 |
/* rgb565 handling */
|
1473 |
|
1474 |
#define RGB_NAME rgb565
|
1475 |
|
1476 |
#define RGB_IN(r, g, b, s)\
|
1477 |
{\ |
1478 |
unsigned int v = ((const uint16_t *)(s))[0];\ |
1479 |
r = bitcopy_n(v >> (11 - 3), 3);\ |
1480 |
g = bitcopy_n(v >> (5 - 2), 2);\ |
1481 |
b = bitcopy_n(v << 3, 3);\ |
1482 |
} |
1483 |
|
1484 |
#define RGB_OUT(d, r, g, b)\
|
1485 |
{\ |
1486 |
((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ |
1487 |
} |
1488 |
|
1489 |
#define BPP 2 |
1490 |
|
1491 |
#include "imgconvert_template.h" |
1492 |
|
1493 |
/* bgr24 handling */
|
1494 |
|
1495 |
#define RGB_NAME bgr24
|
1496 |
|
1497 |
#define RGB_IN(r, g, b, s)\
|
1498 |
{\ |
1499 |
b = (s)[0];\
|
1500 |
g = (s)[1];\
|
1501 |
r = (s)[2];\
|
1502 |
} |
1503 |
|
1504 |
#define RGB_OUT(d, r, g, b)\
|
1505 |
{\ |
1506 |
(d)[0] = b;\
|
1507 |
(d)[1] = g;\
|
1508 |
(d)[2] = r;\
|
1509 |
} |
1510 |
|
1511 |
#define BPP 3 |
1512 |
|
1513 |
#include "imgconvert_template.h" |
1514 |
|
1515 |
#undef RGB_IN
|
1516 |
#undef RGB_OUT
|
1517 |
#undef BPP
|
1518 |
|
1519 |
/* rgb24 handling */
|
1520 |
|
1521 |
#define RGB_NAME rgb24
|
1522 |
#define FMT_RGB24
|
1523 |
|
1524 |
#define RGB_IN(r, g, b, s)\
|
1525 |
{\ |
1526 |
r = (s)[0];\
|
1527 |
g = (s)[1];\
|
1528 |
b = (s)[2];\
|
1529 |
} |
1530 |
|
1531 |
#define RGB_OUT(d, r, g, b)\
|
1532 |
{\ |
1533 |
(d)[0] = r;\
|
1534 |
(d)[1] = g;\
|
1535 |
(d)[2] = b;\
|
1536 |
} |
1537 |
|
1538 |
#define BPP 3 |
1539 |
|
1540 |
#include "imgconvert_template.h" |
1541 |
|
1542 |
/* rgba32 handling */
|
1543 |
|
1544 |
#define RGB_NAME rgba32
|
1545 |
#define FMT_RGBA32
|
1546 |
|
1547 |
#define RGB_IN(r, g, b, s)\
|
1548 |
{\ |
1549 |
unsigned int v = ((const uint32_t *)(s))[0];\ |
1550 |
r = (v >> 16) & 0xff;\ |
1551 |
g = (v >> 8) & 0xff;\ |
1552 |
b = v & 0xff;\
|
1553 |
} |
1554 |
|
1555 |
#define RGBA_IN(r, g, b, a, s)\
|
1556 |
{\ |
1557 |
unsigned int v = ((const uint32_t *)(s))[0];\ |
1558 |
a = (v >> 24) & 0xff;\ |
1559 |
r = (v >> 16) & 0xff;\ |
1560 |
g = (v >> 8) & 0xff;\ |
1561 |
b = v & 0xff;\
|
1562 |
} |
1563 |
|
1564 |
#define RGBA_OUT(d, r, g, b, a)\
|
1565 |
{\ |
1566 |
((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ |
1567 |
} |
1568 |
|
1569 |
#define BPP 4 |
1570 |
|
1571 |
#include "imgconvert_template.h" |
1572 |
|
1573 |
static void mono_to_gray(AVPicture *dst, const AVPicture *src, |
1574 |
int width, int height, int xor_mask) |
1575 |
{ |
1576 |
const unsigned char *p; |
1577 |
unsigned char *q; |
1578 |
int v, dst_wrap, src_wrap;
|
1579 |
int y, w;
|
1580 |
|
1581 |
p = src->data[0];
|
1582 |
src_wrap = src->linesize[0] - ((width + 7) >> 3); |
1583 |
|
1584 |
q = dst->data[0];
|
1585 |
dst_wrap = dst->linesize[0] - width;
|
1586 |
for(y=0;y<height;y++) { |
1587 |
w = width; |
1588 |
while (w >= 8) { |
1589 |
v = *p++ ^ xor_mask; |
1590 |
q[0] = -(v >> 7); |
1591 |
q[1] = -((v >> 6) & 1); |
1592 |
q[2] = -((v >> 5) & 1); |
1593 |
q[3] = -((v >> 4) & 1); |
1594 |
q[4] = -((v >> 3) & 1); |
1595 |
q[5] = -((v >> 2) & 1); |
1596 |
q[6] = -((v >> 1) & 1); |
1597 |
q[7] = -((v >> 0) & 1); |
1598 |
w -= 8;
|
1599 |
q += 8;
|
1600 |
} |
1601 |
if (w > 0) { |
1602 |
v = *p++ ^ xor_mask; |
1603 |
do {
|
1604 |
q[0] = -((v >> 7) & 1); |
1605 |
q++; |
1606 |
v <<= 1;
|
1607 |
} while (--w);
|
1608 |
} |
1609 |
p += src_wrap; |
1610 |
q += dst_wrap; |
1611 |
} |
1612 |
} |
1613 |
|
1614 |
static void monowhite_to_gray(AVPicture *dst, const AVPicture *src, |
1615 |
int width, int height) |
1616 |
{ |
1617 |
mono_to_gray(dst, src, width, height, 0xff);
|
1618 |
} |
1619 |
|
1620 |
static void monoblack_to_gray(AVPicture *dst, const AVPicture *src, |
1621 |
int width, int height) |
1622 |
{ |
1623 |
mono_to_gray(dst, src, width, height, 0x00);
|
1624 |
} |
1625 |
|
1626 |
static void gray_to_mono(AVPicture *dst, const AVPicture *src, |
1627 |
int width, int height, int xor_mask) |
1628 |
{ |
1629 |
int n;
|
1630 |
const uint8_t *s;
|
1631 |
uint8_t *d; |
1632 |
int j, b, v, n1, src_wrap, dst_wrap, y;
|
1633 |
|
1634 |
s = src->data[0];
|
1635 |
src_wrap = src->linesize[0] - width;
|
1636 |
|
1637 |
d = dst->data[0];
|
1638 |
dst_wrap = dst->linesize[0] - ((width + 7) >> 3); |
1639 |
|
1640 |
for(y=0;y<height;y++) { |
1641 |
n = width; |
1642 |
while (n >= 8) { |
1643 |
v = 0;
|
1644 |
for(j=0;j<8;j++) { |
1645 |
b = s[0];
|
1646 |
s++; |
1647 |
v = (v << 1) | (b >> 7); |
1648 |
} |
1649 |
d[0] = v ^ xor_mask;
|
1650 |
d++; |
1651 |
n -= 8;
|
1652 |
} |
1653 |
if (n > 0) { |
1654 |
n1 = n; |
1655 |
v = 0;
|
1656 |
while (n > 0) { |
1657 |
b = s[0];
|
1658 |
s++; |
1659 |
v = (v << 1) | (b >> 7); |
1660 |
n--; |
1661 |
} |
1662 |
d[0] = (v << (8 - (n1 & 7))) ^ xor_mask; |
1663 |
d++; |
1664 |
} |
1665 |
s += src_wrap; |
1666 |
d += dst_wrap; |
1667 |
} |
1668 |
} |
1669 |
|
1670 |
static void gray_to_monowhite(AVPicture *dst, const AVPicture *src, |
1671 |
int width, int height) |
1672 |
{ |
1673 |
gray_to_mono(dst, src, width, height, 0xff);
|
1674 |
} |
1675 |
|
1676 |
static void gray_to_monoblack(AVPicture *dst, const AVPicture *src, |
1677 |
int width, int height) |
1678 |
{ |
1679 |
gray_to_mono(dst, src, width, height, 0x00);
|
1680 |
} |
1681 |
|
1682 |
typedef struct ConvertEntry { |
1683 |
void (*convert)(AVPicture *dst,
|
1684 |
const AVPicture *src, int width, int height); |
1685 |
} ConvertEntry; |
1686 |
|
1687 |
/* Add each new convertion function in this table. In order to be able
|
1688 |
to convert from any format to any format, the following constraints
|
1689 |
must be satisfied:
|
1690 |
|
1691 |
- all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
|
1692 |
|
1693 |
- all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
|
1694 |
|
1695 |
- all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32
|
1696 |
|
1697 |
- PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
|
1698 |
PIX_FMT_RGB24.
|
1699 |
|
1700 |
- PIX_FMT_422 must convert to and from PIX_FMT_422P.
|
1701 |
|
1702 |
The other conversion functions are just optimisations for common cases.
|
1703 |
*/
|
1704 |
static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
|
1705 |
[PIX_FMT_YUV420P] = { |
1706 |
[PIX_FMT_YUV422] = { |
1707 |
.convert = yuv420p_to_yuv422, |
1708 |
}, |
1709 |
[PIX_FMT_RGB555] = { |
1710 |
.convert = yuv420p_to_rgb555 |
1711 |
}, |
1712 |
[PIX_FMT_RGB565] = { |
1713 |
.convert = yuv420p_to_rgb565 |
1714 |
}, |
1715 |
[PIX_FMT_BGR24] = { |
1716 |
.convert = yuv420p_to_bgr24 |
1717 |
}, |
1718 |
[PIX_FMT_RGB24] = { |
1719 |
.convert = yuv420p_to_rgb24 |
1720 |
}, |
1721 |
[PIX_FMT_RGBA32] = { |
1722 |
.convert = yuv420p_to_rgba32 |
1723 |
}, |
1724 |
[PIX_FMT_UYVY422] = { |
1725 |
.convert = yuv420p_to_uyvy422, |
1726 |
}, |
1727 |
}, |
1728 |
[PIX_FMT_YUV422P] = { |
1729 |
[PIX_FMT_YUV422] = { |
1730 |
.convert = yuv422p_to_yuv422, |
1731 |
}, |
1732 |
[PIX_FMT_UYVY422] = { |
1733 |
.convert = yuv422p_to_uyvy422, |
1734 |
}, |
1735 |
}, |
1736 |
[PIX_FMT_YUV444P] = { |
1737 |
[PIX_FMT_RGB24] = { |
1738 |
.convert = yuv444p_to_rgb24 |
1739 |
}, |
1740 |
}, |
1741 |
[PIX_FMT_YUVJ420P] = { |
1742 |
[PIX_FMT_RGB555] = { |
1743 |
.convert = yuvj420p_to_rgb555 |
1744 |
}, |
1745 |
[PIX_FMT_RGB565] = { |
1746 |
.convert = yuvj420p_to_rgb565 |
1747 |
}, |
1748 |
[PIX_FMT_BGR24] = { |
1749 |
.convert = yuvj420p_to_bgr24 |
1750 |
}, |
1751 |
[PIX_FMT_RGB24] = { |
1752 |
.convert = yuvj420p_to_rgb24 |
1753 |
}, |
1754 |
[PIX_FMT_RGBA32] = { |
1755 |
.convert = yuvj420p_to_rgba32 |
1756 |
}, |
1757 |
}, |
1758 |
[PIX_FMT_YUVJ444P] = { |
1759 |
[PIX_FMT_RGB24] = { |
1760 |
.convert = yuvj444p_to_rgb24 |
1761 |
}, |
1762 |
}, |
1763 |
[PIX_FMT_YUV422] = { |
1764 |
[PIX_FMT_YUV420P] = { |
1765 |
.convert = yuv422_to_yuv420p, |
1766 |
}, |
1767 |
[PIX_FMT_YUV422P] = { |
1768 |
.convert = yuv422_to_yuv422p, |
1769 |
}, |
1770 |
}, |
1771 |
[PIX_FMT_UYVY422] = { |
1772 |
[PIX_FMT_YUV420P] = { |
1773 |
.convert = uyvy422_to_yuv420p, |
1774 |
}, |
1775 |
[PIX_FMT_YUV422P] = { |
1776 |
.convert = uyvy422_to_yuv422p, |
1777 |
}, |
1778 |
}, |
1779 |
[PIX_FMT_RGB24] = { |
1780 |
[PIX_FMT_YUV420P] = { |
1781 |
.convert = rgb24_to_yuv420p |
1782 |
}, |
1783 |
[PIX_FMT_RGB565] = { |
1784 |
.convert = rgb24_to_rgb565 |
1785 |
}, |
1786 |
[PIX_FMT_RGB555] = { |
1787 |
.convert = rgb24_to_rgb555 |
1788 |
}, |
1789 |
[PIX_FMT_RGBA32] = { |
1790 |
.convert = rgb24_to_rgba32 |
1791 |
}, |
1792 |
[PIX_FMT_BGR24] = { |
1793 |
.convert = rgb24_to_bgr24 |
1794 |
}, |
1795 |
[PIX_FMT_GRAY8] = { |
1796 |
.convert = rgb24_to_gray |
1797 |
}, |
1798 |
[PIX_FMT_PAL8] = { |
1799 |
.convert = rgb24_to_pal8 |
1800 |
}, |
1801 |
[PIX_FMT_YUV444P] = { |
1802 |
.convert = rgb24_to_yuv444p |
1803 |
}, |
1804 |
[PIX_FMT_YUVJ420P] = { |
1805 |
.convert = rgb24_to_yuvj420p |
1806 |
}, |
1807 |
[PIX_FMT_YUVJ444P] = { |
1808 |
.convert = rgb24_to_yuvj444p |
1809 |
}, |
1810 |
}, |
1811 |
[PIX_FMT_RGBA32] = { |
1812 |
[PIX_FMT_RGB24] = { |
1813 |
.convert = rgba32_to_rgb24 |
1814 |
}, |
1815 |
[PIX_FMT_RGB555] = { |
1816 |
.convert = rgba32_to_rgb555 |
1817 |
}, |
1818 |
[PIX_FMT_PAL8] = { |
1819 |
.convert = rgba32_to_pal8 |
1820 |
}, |
1821 |
[PIX_FMT_YUV420P] = { |
1822 |
.convert = rgba32_to_yuv420p |
1823 |
}, |
1824 |
[PIX_FMT_GRAY8] = { |
1825 |
.convert = rgba32_to_gray |
1826 |
}, |
1827 |
}, |
1828 |
[PIX_FMT_BGR24] = { |
1829 |
[PIX_FMT_RGB24] = { |
1830 |
.convert = bgr24_to_rgb24 |
1831 |
}, |
1832 |
[PIX_FMT_YUV420P] = { |
1833 |
.convert = bgr24_to_yuv420p |
1834 |
}, |
1835 |
[PIX_FMT_GRAY8] = { |
1836 |
.convert = bgr24_to_gray |
1837 |
}, |
1838 |
}, |
1839 |
[PIX_FMT_RGB555] = { |
1840 |
[PIX_FMT_RGB24] = { |
1841 |
.convert = rgb555_to_rgb24 |
1842 |
}, |
1843 |
[PIX_FMT_RGBA32] = { |
1844 |
.convert = rgb555_to_rgba32 |
1845 |
}, |
1846 |
[PIX_FMT_YUV420P] = { |
1847 |
.convert = rgb555_to_yuv420p |
1848 |
}, |
1849 |
[PIX_FMT_GRAY8] = { |
1850 |
.convert = rgb555_to_gray |
1851 |
}, |
1852 |
}, |
1853 |
[PIX_FMT_RGB565] = { |
1854 |
[PIX_FMT_RGB24] = { |
1855 |
.convert = rgb565_to_rgb24 |
1856 |
}, |
1857 |
[PIX_FMT_YUV420P] = { |
1858 |
.convert = rgb565_to_yuv420p |
1859 |
}, |
1860 |
[PIX_FMT_GRAY8] = { |
1861 |
.convert = rgb565_to_gray |
1862 |
}, |
1863 |
}, |
1864 |
[PIX_FMT_GRAY8] = { |
1865 |
[PIX_FMT_RGB555] = { |
1866 |
.convert = gray_to_rgb555 |
1867 |
}, |
1868 |
[PIX_FMT_RGB565] = { |
1869 |
.convert = gray_to_rgb565 |
1870 |
}, |
1871 |
[PIX_FMT_RGB24] = { |
1872 |
.convert = gray_to_rgb24 |
1873 |
}, |
1874 |
[PIX_FMT_BGR24] = { |
1875 |
.convert = gray_to_bgr24 |
1876 |
}, |
1877 |
[PIX_FMT_RGBA32] = { |
1878 |
.convert = gray_to_rgba32 |
1879 |
}, |
1880 |
[PIX_FMT_MONOWHITE] = { |
1881 |
.convert = gray_to_monowhite |
1882 |
}, |
1883 |
[PIX_FMT_MONOBLACK] = { |
1884 |
.convert = gray_to_monoblack |
1885 |
}, |
1886 |
}, |
1887 |
[PIX_FMT_MONOWHITE] = { |
1888 |
[PIX_FMT_GRAY8] = { |
1889 |
.convert = monowhite_to_gray |
1890 |
}, |
1891 |
}, |
1892 |
[PIX_FMT_MONOBLACK] = { |
1893 |
[PIX_FMT_GRAY8] = { |
1894 |
.convert = monoblack_to_gray |
1895 |
}, |
1896 |
}, |
1897 |
[PIX_FMT_PAL8] = { |
1898 |
[PIX_FMT_RGB555] = { |
1899 |
.convert = pal8_to_rgb555 |
1900 |
}, |
1901 |
[PIX_FMT_RGB565] = { |
1902 |
.convert = pal8_to_rgb565 |
1903 |
}, |
1904 |
[PIX_FMT_BGR24] = { |
1905 |
.convert = pal8_to_bgr24 |
1906 |
}, |
1907 |
[PIX_FMT_RGB24] = { |
1908 |
.convert = pal8_to_rgb24 |
1909 |
}, |
1910 |
[PIX_FMT_RGBA32] = { |
1911 |
.convert = pal8_to_rgba32 |
1912 |
}, |
1913 |
}, |
1914 |
[PIX_FMT_UYVY411] = { |
1915 |
[PIX_FMT_YUV411P] = { |
1916 |
.convert = uyvy411_to_yuv411p, |
1917 |
}, |
1918 |
}, |
1919 |
|
1920 |
}; |
1921 |
|
1922 |
int avpicture_alloc(AVPicture *picture,
|
1923 |
int pix_fmt, int width, int height) |
1924 |
{ |
1925 |
unsigned int size; |
1926 |
void *ptr;
|
1927 |
|
1928 |
size = avpicture_get_size(pix_fmt, width, height); |
1929 |
if(size<0) |
1930 |
goto fail;
|
1931 |
ptr = av_malloc(size); |
1932 |
if (!ptr)
|
1933 |
goto fail;
|
1934 |
avpicture_fill(picture, ptr, pix_fmt, width, height); |
1935 |
return 0; |
1936 |
fail:
|
1937 |
memset(picture, 0, sizeof(AVPicture)); |
1938 |
return -1; |
1939 |
} |
1940 |
|
1941 |
void avpicture_free(AVPicture *picture)
|
1942 |
{ |
1943 |
av_free(picture->data[0]);
|
1944 |
} |
1945 |
|
1946 |
/* return true if yuv planar */
|
1947 |
static inline int is_yuv_planar(PixFmtInfo *ps) |
1948 |
{ |
1949 |
return (ps->color_type == FF_COLOR_YUV ||
|
1950 |
ps->color_type == FF_COLOR_YUV_JPEG) && |
1951 |
ps->pixel_type == FF_PIXEL_PLANAR; |
1952 |
} |
1953 |
|
1954 |
/* XXX: always use linesize. Return -1 if not supported */
|
1955 |
int img_convert(AVPicture *dst, int dst_pix_fmt, |
1956 |
const AVPicture *src, int src_pix_fmt, |
1957 |
int src_width, int src_height) |
1958 |
{ |
1959 |
static int inited; |
1960 |
int i, ret, dst_width, dst_height, int_pix_fmt;
|
1961 |
PixFmtInfo *src_pix, *dst_pix; |
1962 |
ConvertEntry *ce; |
1963 |
AVPicture tmp1, *tmp = &tmp1; |
1964 |
|
1965 |
if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB || |
1966 |
dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
|
1967 |
return -1; |
1968 |
if (src_width <= 0 || src_height <= 0) |
1969 |
return 0; |
1970 |
|
1971 |
if (!inited) {
|
1972 |
inited = 1;
|
1973 |
img_convert_init(); |
1974 |
} |
1975 |
|
1976 |
dst_width = src_width; |
1977 |
dst_height = src_height; |
1978 |
|
1979 |
dst_pix = &pix_fmt_info[dst_pix_fmt]; |
1980 |
src_pix = &pix_fmt_info[src_pix_fmt]; |
1981 |
if (src_pix_fmt == dst_pix_fmt) {
|
1982 |
/* no conversion needed: just copy */
|
1983 |
img_copy(dst, src, dst_pix_fmt, dst_width, dst_height); |
1984 |
return 0; |
1985 |
} |
1986 |
|
1987 |
ce = &convert_table[src_pix_fmt][dst_pix_fmt]; |
1988 |
if (ce->convert) {
|
1989 |
/* specific conversion routine */
|
1990 |
ce->convert(dst, src, dst_width, dst_height); |
1991 |
return 0; |
1992 |
} |
1993 |
|
1994 |
/* gray to YUV */
|
1995 |
if (is_yuv_planar(dst_pix) &&
|
1996 |
src_pix_fmt == PIX_FMT_GRAY8) { |
1997 |
int w, h, y;
|
1998 |
uint8_t *d; |
1999 |
|
2000 |
if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
|
2001 |
img_copy_plane(dst->data[0], dst->linesize[0], |
2002 |
src->data[0], src->linesize[0], |
2003 |
dst_width, dst_height); |
2004 |
} else {
|
2005 |
img_apply_table(dst->data[0], dst->linesize[0], |
2006 |
src->data[0], src->linesize[0], |
2007 |
dst_width, dst_height, |
2008 |
y_jpeg_to_ccir); |
2009 |
} |
2010 |
/* fill U and V with 128 */
|
2011 |
w = dst_width; |
2012 |
h = dst_height; |
2013 |
w >>= dst_pix->x_chroma_shift; |
2014 |
h >>= dst_pix->y_chroma_shift; |
2015 |
for(i = 1; i <= 2; i++) { |
2016 |
d = dst->data[i]; |
2017 |
for(y = 0; y< h; y++) { |
2018 |
memset(d, 128, w);
|
2019 |
d += dst->linesize[i]; |
2020 |
} |
2021 |
} |
2022 |
return 0; |
2023 |
} |
2024 |
|
2025 |
/* YUV to gray */
|
2026 |
if (is_yuv_planar(src_pix) &&
|
2027 |
dst_pix_fmt == PIX_FMT_GRAY8) { |
2028 |
if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
|
2029 |
img_copy_plane(dst->data[0], dst->linesize[0], |
2030 |
src->data[0], src->linesize[0], |
2031 |
dst_width, dst_height); |
2032 |
} else {
|
2033 |
img_apply_table(dst->data[0], dst->linesize[0], |
2034 |
src->data[0], src->linesize[0], |
2035 |
dst_width, dst_height, |
2036 |
y_ccir_to_jpeg); |
2037 |
} |
2038 |
return 0; |
2039 |
} |
2040 |
|
2041 |
/* YUV to YUV planar */
|
2042 |
if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
|
2043 |
int x_shift, y_shift, w, h, xy_shift;
|
2044 |
void (*resize_func)(uint8_t *dst, int dst_wrap, |
2045 |
const uint8_t *src, int src_wrap, |
2046 |
int width, int height); |
2047 |
|
2048 |
/* compute chroma size of the smallest dimensions */
|
2049 |
w = dst_width; |
2050 |
h = dst_height; |
2051 |
if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
|
2052 |
w >>= dst_pix->x_chroma_shift; |
2053 |
else
|
2054 |
w >>= src_pix->x_chroma_shift; |
2055 |
if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
|
2056 |
h >>= dst_pix->y_chroma_shift; |
2057 |
else
|
2058 |
h >>= src_pix->y_chroma_shift; |
2059 |
|
2060 |
x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); |
2061 |
y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); |
2062 |
xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf); |
2063 |
/* there must be filters for conversion at least from and to
|
2064 |
YUV444 format */
|
2065 |
switch(xy_shift) {
|
2066 |
case 0x00: |
2067 |
resize_func = img_copy_plane; |
2068 |
break;
|
2069 |
case 0x10: |
2070 |
resize_func = shrink21; |
2071 |
break;
|
2072 |
case 0x20: |
2073 |
resize_func = shrink41; |
2074 |
break;
|
2075 |
case 0x01: |
2076 |
resize_func = shrink12; |
2077 |
break;
|
2078 |
case 0x11: |
2079 |
resize_func = shrink22; |
2080 |
break;
|
2081 |
case 0x22: |
2082 |
resize_func = shrink44; |
2083 |
break;
|
2084 |
case 0xf0: |
2085 |
resize_func = grow21; |
2086 |
break;
|
2087 |
case 0xe0: |
2088 |
resize_func = grow41; |
2089 |
break;
|
2090 |
case 0xff: |
2091 |
resize_func = grow22; |
2092 |
break;
|
2093 |
case 0xee: |
2094 |
resize_func = grow44; |
2095 |
break;
|
2096 |
case 0xf1: |
2097 |
resize_func = conv411; |
2098 |
break;
|
2099 |
default:
|
2100 |
/* currently not handled */
|
2101 |
goto no_chroma_filter;
|
2102 |
} |
2103 |
|
2104 |
img_copy_plane(dst->data[0], dst->linesize[0], |
2105 |
src->data[0], src->linesize[0], |
2106 |
dst_width, dst_height); |
2107 |
|
2108 |
for(i = 1;i <= 2; i++) |
2109 |
resize_func(dst->data[i], dst->linesize[i], |
2110 |
src->data[i], src->linesize[i], |
2111 |
dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift); |
2112 |
/* if yuv color space conversion is needed, we do it here on
|
2113 |
the destination image */
|
2114 |
if (dst_pix->color_type != src_pix->color_type) {
|
2115 |
const uint8_t *y_table, *c_table;
|
2116 |
if (dst_pix->color_type == FF_COLOR_YUV) {
|
2117 |
y_table = y_jpeg_to_ccir; |
2118 |
c_table = c_jpeg_to_ccir; |
2119 |
} else {
|
2120 |
y_table = y_ccir_to_jpeg; |
2121 |
c_table = c_ccir_to_jpeg; |
2122 |
} |
2123 |
img_apply_table(dst->data[0], dst->linesize[0], |
2124 |
dst->data[0], dst->linesize[0], |
2125 |
dst_width, dst_height, |
2126 |
y_table); |
2127 |
|
2128 |
for(i = 1;i <= 2; i++) |
2129 |
img_apply_table(dst->data[i], dst->linesize[i], |
2130 |
dst->data[i], dst->linesize[i], |
2131 |
dst_width>>dst_pix->x_chroma_shift, |
2132 |
dst_height>>dst_pix->y_chroma_shift, |
2133 |
c_table); |
2134 |
} |
2135 |
return 0; |
2136 |
} |
2137 |
no_chroma_filter:
|
2138 |
|
2139 |
/* try to use an intermediate format */
|
2140 |
if (src_pix_fmt == PIX_FMT_YUV422 ||
|
2141 |
dst_pix_fmt == PIX_FMT_YUV422) { |
2142 |
/* specific case: convert to YUV422P first */
|
2143 |
int_pix_fmt = PIX_FMT_YUV422P; |
2144 |
} else if (src_pix_fmt == PIX_FMT_UYVY422 || |
2145 |
dst_pix_fmt == PIX_FMT_UYVY422) { |
2146 |
/* specific case: convert to YUV422P first */
|
2147 |
int_pix_fmt = PIX_FMT_YUV422P; |
2148 |
} else if (src_pix_fmt == PIX_FMT_UYVY411 || |
2149 |
dst_pix_fmt == PIX_FMT_UYVY411) { |
2150 |
/* specific case: convert to YUV411P first */
|
2151 |
int_pix_fmt = PIX_FMT_YUV411P; |
2152 |
} else if ((src_pix->color_type == FF_COLOR_GRAY && |
2153 |
src_pix_fmt != PIX_FMT_GRAY8) || |
2154 |
(dst_pix->color_type == FF_COLOR_GRAY && |
2155 |
dst_pix_fmt != PIX_FMT_GRAY8)) { |
2156 |
/* gray8 is the normalized format */
|
2157 |
int_pix_fmt = PIX_FMT_GRAY8; |
2158 |
} else if ((is_yuv_planar(src_pix) && |
2159 |
src_pix_fmt != PIX_FMT_YUV444P && |
2160 |
src_pix_fmt != PIX_FMT_YUVJ444P)) { |
2161 |
/* yuv444 is the normalized format */
|
2162 |
if (src_pix->color_type == FF_COLOR_YUV_JPEG)
|
2163 |
int_pix_fmt = PIX_FMT_YUVJ444P; |
2164 |
else
|
2165 |
int_pix_fmt = PIX_FMT_YUV444P; |
2166 |
} else if ((is_yuv_planar(dst_pix) && |
2167 |
dst_pix_fmt != PIX_FMT_YUV444P && |
2168 |
dst_pix_fmt != PIX_FMT_YUVJ444P)) { |
2169 |
/* yuv444 is the normalized format */
|
2170 |
if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
|
2171 |
int_pix_fmt = PIX_FMT_YUVJ444P; |
2172 |
else
|
2173 |
int_pix_fmt = PIX_FMT_YUV444P; |
2174 |
} else {
|
2175 |
/* the two formats are rgb or gray8 or yuv[j]444p */
|
2176 |
if (src_pix->is_alpha && dst_pix->is_alpha)
|
2177 |
int_pix_fmt = PIX_FMT_RGBA32; |
2178 |
else
|
2179 |
int_pix_fmt = PIX_FMT_RGB24; |
2180 |
} |
2181 |
if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0) |
2182 |
return -1; |
2183 |
ret = -1;
|
2184 |
if (img_convert(tmp, int_pix_fmt,
|
2185 |
src, src_pix_fmt, src_width, src_height) < 0)
|
2186 |
goto fail1;
|
2187 |
if (img_convert(dst, dst_pix_fmt,
|
2188 |
tmp, int_pix_fmt, dst_width, dst_height) < 0)
|
2189 |
goto fail1;
|
2190 |
ret = 0;
|
2191 |
fail1:
|
2192 |
avpicture_free(tmp); |
2193 |
return ret;
|
2194 |
} |
2195 |
|
2196 |
/* NOTE: we scan all the pixels to have an exact information */
|
2197 |
static int get_alpha_info_pal8(const AVPicture *src, int width, int height) |
2198 |
{ |
2199 |
const unsigned char *p; |
2200 |
int src_wrap, ret, x, y;
|
2201 |
unsigned int a; |
2202 |
uint32_t *palette = (uint32_t *)src->data[1];
|
2203 |
|
2204 |
p = src->data[0];
|
2205 |
src_wrap = src->linesize[0] - width;
|
2206 |
ret = 0;
|
2207 |
for(y=0;y<height;y++) { |
2208 |
for(x=0;x<width;x++) { |
2209 |
a = palette[p[0]] >> 24; |
2210 |
if (a == 0x00) { |
2211 |
ret |= FF_ALPHA_TRANSP; |
2212 |
} else if (a != 0xff) { |
2213 |
ret |= FF_ALPHA_SEMI_TRANSP; |
2214 |
} |
2215 |
p++; |
2216 |
} |
2217 |
p += src_wrap; |
2218 |
} |
2219 |
return ret;
|
2220 |
} |
2221 |
|
2222 |
/**
|
2223 |
* Tell if an image really has transparent alpha values.
|
2224 |
* @return ored mask of FF_ALPHA_xxx constants
|
2225 |
*/
|
2226 |
int img_get_alpha_info(const AVPicture *src, |
2227 |
int pix_fmt, int width, int height) |
2228 |
{ |
2229 |
PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; |
2230 |
int ret;
|
2231 |
|
2232 |
pf = &pix_fmt_info[pix_fmt]; |
2233 |
/* no alpha can be represented in format */
|
2234 |
if (!pf->is_alpha)
|
2235 |
return 0; |
2236 |
switch(pix_fmt) {
|
2237 |
case PIX_FMT_RGBA32:
|
2238 |
ret = get_alpha_info_rgba32(src, width, height); |
2239 |
break;
|
2240 |
case PIX_FMT_RGB555:
|
2241 |
ret = get_alpha_info_rgb555(src, width, height); |
2242 |
break;
|
2243 |
case PIX_FMT_PAL8:
|
2244 |
ret = get_alpha_info_pal8(src, width, height); |
2245 |
break;
|
2246 |
default:
|
2247 |
/* we do not know, so everything is indicated */
|
2248 |
ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP; |
2249 |
break;
|
2250 |
} |
2251 |
return ret;
|
2252 |
} |
2253 |
|
2254 |
#ifdef HAVE_MMX
|
2255 |
#define DEINT_INPLACE_LINE_LUM \
|
2256 |
movd_m2r(lum_m4[0],mm0);\
|
2257 |
movd_m2r(lum_m3[0],mm1);\
|
2258 |
movd_m2r(lum_m2[0],mm2);\
|
2259 |
movd_m2r(lum_m1[0],mm3);\
|
2260 |
movd_m2r(lum[0],mm4);\
|
2261 |
punpcklbw_r2r(mm7,mm0);\ |
2262 |
movd_r2m(mm2,lum_m4[0]);\
|
2263 |
punpcklbw_r2r(mm7,mm1);\ |
2264 |
punpcklbw_r2r(mm7,mm2);\ |
2265 |
punpcklbw_r2r(mm7,mm3);\ |
2266 |
punpcklbw_r2r(mm7,mm4);\ |
2267 |
paddw_r2r(mm3,mm1);\ |
2268 |
psllw_i2r(1,mm2);\
|
2269 |
paddw_r2r(mm4,mm0);\ |
2270 |
psllw_i2r(2,mm1);\
|
2271 |
paddw_r2r(mm6,mm2);\ |
2272 |
paddw_r2r(mm2,mm1);\ |
2273 |
psubusw_r2r(mm0,mm1);\ |
2274 |
psrlw_i2r(3,mm1);\
|
2275 |
packuswb_r2r(mm7,mm1);\ |
2276 |
movd_r2m(mm1,lum_m2[0]);
|
2277 |
|
2278 |
#define DEINT_LINE_LUM \
|
2279 |
movd_m2r(lum_m4[0],mm0);\
|
2280 |
movd_m2r(lum_m3[0],mm1);\
|
2281 |
movd_m2r(lum_m2[0],mm2);\
|
2282 |
movd_m2r(lum_m1[0],mm3);\
|
2283 |
movd_m2r(lum[0],mm4);\
|
2284 |
punpcklbw_r2r(mm7,mm0);\ |
2285 |
punpcklbw_r2r(mm7,mm1);\ |
2286 |
punpcklbw_r2r(mm7,mm2);\ |
2287 |
punpcklbw_r2r(mm7,mm3);\ |
2288 |
punpcklbw_r2r(mm7,mm4);\ |
2289 |
paddw_r2r(mm3,mm1);\ |
2290 |
psllw_i2r(1,mm2);\
|
2291 |
paddw_r2r(mm4,mm0);\ |
2292 |
psllw_i2r(2,mm1);\
|
2293 |
paddw_r2r(mm6,mm2);\ |
2294 |
paddw_r2r(mm2,mm1);\ |
2295 |
psubusw_r2r(mm0,mm1);\ |
2296 |
psrlw_i2r(3,mm1);\
|
2297 |
packuswb_r2r(mm7,mm1);\ |
2298 |
movd_r2m(mm1,dst[0]);
|
2299 |
#endif
|
2300 |
|
2301 |
/* filter parameters: [-1 4 2 4 -1] // 8 */
|
2302 |
static void deinterlace_line(uint8_t *dst, |
2303 |
const uint8_t *lum_m4, const uint8_t *lum_m3, |
2304 |
const uint8_t *lum_m2, const uint8_t *lum_m1, |
2305 |
const uint8_t *lum,
|
2306 |
int size)
|
2307 |
{ |
2308 |
#ifndef HAVE_MMX
|
2309 |
uint8_t *cm = cropTbl + MAX_NEG_CROP; |
2310 |
int sum;
|
2311 |
|
2312 |
for(;size > 0;size--) { |
2313 |
sum = -lum_m4[0];
|
2314 |
sum += lum_m3[0] << 2; |
2315 |
sum += lum_m2[0] << 1; |
2316 |
sum += lum_m1[0] << 2; |
2317 |
sum += -lum[0];
|
2318 |
dst[0] = cm[(sum + 4) >> 3]; |
2319 |
lum_m4++; |
2320 |
lum_m3++; |
2321 |
lum_m2++; |
2322 |
lum_m1++; |
2323 |
lum++; |
2324 |
dst++; |
2325 |
} |
2326 |
#else
|
2327 |
|
2328 |
{ |
2329 |
mmx_t rounder; |
2330 |
rounder.uw[0]=4; |
2331 |
rounder.uw[1]=4; |
2332 |
rounder.uw[2]=4; |
2333 |
rounder.uw[3]=4; |
2334 |
pxor_r2r(mm7,mm7); |
2335 |
movq_m2r(rounder,mm6); |
2336 |
} |
2337 |
for (;size > 3; size-=4) { |
2338 |
DEINT_LINE_LUM |
2339 |
lum_m4+=4;
|
2340 |
lum_m3+=4;
|
2341 |
lum_m2+=4;
|
2342 |
lum_m1+=4;
|
2343 |
lum+=4;
|
2344 |
dst+=4;
|
2345 |
} |
2346 |
#endif
|
2347 |
} |
2348 |
static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum, |
2349 |
int size)
|
2350 |
{ |
2351 |
#ifndef HAVE_MMX
|
2352 |
uint8_t *cm = cropTbl + MAX_NEG_CROP; |
2353 |
int sum;
|
2354 |
|
2355 |
for(;size > 0;size--) { |
2356 |
sum = -lum_m4[0];
|
2357 |
sum += lum_m3[0] << 2; |
2358 |
sum += lum_m2[0] << 1; |
2359 |
lum_m4[0]=lum_m2[0]; |
2360 |
sum += lum_m1[0] << 2; |
2361 |
sum += -lum[0];
|
2362 |
lum_m2[0] = cm[(sum + 4) >> 3]; |
2363 |
lum_m4++; |
2364 |
lum_m3++; |
2365 |
lum_m2++; |
2366 |
lum_m1++; |
2367 |
lum++; |
2368 |
} |
2369 |
#else
|
2370 |
|
2371 |
{ |
2372 |
mmx_t rounder; |
2373 |
rounder.uw[0]=4; |
2374 |
rounder.uw[1]=4; |
2375 |
rounder.uw[2]=4; |
2376 |
rounder.uw[3]=4; |
2377 |
pxor_r2r(mm7,mm7); |
2378 |
movq_m2r(rounder,mm6); |
2379 |
} |
2380 |
for (;size > 3; size-=4) { |
2381 |
DEINT_INPLACE_LINE_LUM |
2382 |
lum_m4+=4;
|
2383 |
lum_m3+=4;
|
2384 |
lum_m2+=4;
|
2385 |
lum_m1+=4;
|
2386 |
lum+=4;
|
2387 |
} |
2388 |
#endif
|
2389 |
} |
2390 |
|
2391 |
/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
|
2392 |
top field is copied as is, but the bottom field is deinterlaced
|
2393 |
against the top field. */
|
2394 |
static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, |
2395 |
const uint8_t *src1, int src_wrap, |
2396 |
int width, int height) |
2397 |
{ |
2398 |
const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
|
2399 |
int y;
|
2400 |
|
2401 |
src_m2 = src1; |
2402 |
src_m1 = src1; |
2403 |
src_0=&src_m1[src_wrap]; |
2404 |
src_p1=&src_0[src_wrap]; |
2405 |
src_p2=&src_p1[src_wrap]; |
2406 |
for(y=0;y<(height-2);y+=2) { |
2407 |
memcpy(dst,src_m1,width); |
2408 |
dst += dst_wrap; |
2409 |
deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width); |
2410 |
src_m2 = src_0; |
2411 |
src_m1 = src_p1; |
2412 |
src_0 = src_p2; |
2413 |
src_p1 += 2*src_wrap;
|
2414 |
src_p2 += 2*src_wrap;
|
2415 |
dst += dst_wrap; |
2416 |
} |
2417 |
memcpy(dst,src_m1,width); |
2418 |
dst += dst_wrap; |
2419 |
/* do last line */
|
2420 |
deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width); |
2421 |
} |
2422 |
|
2423 |
static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, |
2424 |
int width, int height) |
2425 |
{ |
2426 |
uint8_t *src_m1, *src_0, *src_p1, *src_p2; |
2427 |
int y;
|
2428 |
uint8_t *buf; |
2429 |
buf = (uint8_t*)av_malloc(width); |
2430 |
|
2431 |
src_m1 = src1; |
2432 |
memcpy(buf,src_m1,width); |
2433 |
src_0=&src_m1[src_wrap]; |
2434 |
src_p1=&src_0[src_wrap]; |
2435 |
src_p2=&src_p1[src_wrap]; |
2436 |
for(y=0;y<(height-2);y+=2) { |
2437 |
deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width); |
2438 |
src_m1 = src_p1; |
2439 |
src_0 = src_p2; |
2440 |
src_p1 += 2*src_wrap;
|
2441 |
src_p2 += 2*src_wrap;
|
2442 |
} |
2443 |
/* do last line */
|
2444 |
deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width); |
2445 |
av_free(buf); |
2446 |
} |
2447 |
|
2448 |
|
2449 |
/* deinterlace - if not supported return -1 */
|
2450 |
int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, |
2451 |
int pix_fmt, int width, int height) |
2452 |
{ |
2453 |
int i;
|
2454 |
|
2455 |
if (pix_fmt != PIX_FMT_YUV420P &&
|
2456 |
pix_fmt != PIX_FMT_YUV422P && |
2457 |
pix_fmt != PIX_FMT_YUV444P && |
2458 |
pix_fmt != PIX_FMT_YUV411P) |
2459 |
return -1; |
2460 |
if ((width & 3) != 0 || (height & 3) != 0) |
2461 |
return -1; |
2462 |
|
2463 |
for(i=0;i<3;i++) { |
2464 |
if (i == 1) { |
2465 |
switch(pix_fmt) {
|
2466 |
case PIX_FMT_YUV420P:
|
2467 |
width >>= 1;
|
2468 |
height >>= 1;
|
2469 |
break;
|
2470 |
case PIX_FMT_YUV422P:
|
2471 |
width >>= 1;
|
2472 |
break;
|
2473 |
case PIX_FMT_YUV411P:
|
2474 |
width >>= 2;
|
2475 |
break;
|
2476 |
default:
|
2477 |
break;
|
2478 |
} |
2479 |
} |
2480 |
if (src == dst) {
|
2481 |
deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], |
2482 |
width, height); |
2483 |
} else {
|
2484 |
deinterlace_bottom_field(dst->data[i],dst->linesize[i], |
2485 |
src->data[i], src->linesize[i], |
2486 |
width, height); |
2487 |
} |
2488 |
} |
2489 |
#ifdef HAVE_MMX
|
2490 |
emms(); |
2491 |
#endif
|
2492 |
return 0; |
2493 |
} |
2494 |
|
2495 |
#undef FIX
|