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