Mercurial > libavcodec.hg
annotate pngdec.c @ 12494:94eaea836bf4 libavcodec
Check avctx width/height more thoroughly (e.g. all values 0 except width would
have been accepted before).
Also do not fail if they are invalid but instead override them to 0.
This allows decoding e.g. MPEG video when only the container values are corrupted.
For encoding a value of 0,0 of course makes no sense, but was allowed
through before and will be caught by an extra check in the encode function.
author | reimar |
---|---|
date | Wed, 15 Sep 2010 04:46:55 +0000 |
parents | ffb3668ff7af |
children |
rev | line source |
---|---|
2342 | 1 /* |
2 * PNG image format | |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
7236
diff
changeset
|
3 * Copyright (c) 2003 Fabrice Bellard |
2342 | 4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
2342 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
2342 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2342 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2342 | 20 */ |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
12129
diff
changeset
|
21 #include "libavcore/imgutils.h" |
2342 | 22 #include "avcodec.h" |
5067 | 23 #include "bytestream.h" |
5337 | 24 #include "png.h" |
6384 | 25 #include "dsputil.h" |
2342 | 26 |
27 /* TODO: | |
28 * - add 2, 4 and 16 bit depth support | |
29 */ | |
30 | |
31 #include <zlib.h> | |
32 | |
33 //#define DEBUG | |
34 | |
5339 | 35 typedef struct PNGDecContext { |
6384 | 36 DSPContext dsp; |
37 | |
6245 | 38 const uint8_t *bytestream; |
39 const uint8_t *bytestream_start; | |
40 const uint8_t *bytestream_end; | |
9387 | 41 AVFrame picture1, picture2; |
42 AVFrame *current_picture, *last_picture; | |
5339 | 43 |
44 int state; | |
45 int width, height; | |
46 int bit_depth; | |
47 int color_type; | |
48 int compression_type; | |
49 int interlace_type; | |
50 int filter_type; | |
51 int channels; | |
52 int bits_per_pixel; | |
53 int bpp; | |
54 | |
55 uint8_t *image_buf; | |
56 int image_linesize; | |
57 uint32_t palette[256]; | |
58 uint8_t *crow_buf; | |
59 uint8_t *last_row; | |
60 uint8_t *tmp_row; | |
61 int pass; | |
62 int crow_size; /* compressed row size (include filter type) */ | |
63 int row_size; /* decompressed row size */ | |
64 int pass_row_size; /* decompress row size of the current pass */ | |
65 int y; | |
66 z_stream zstream; | |
67 } PNGDecContext; | |
68 | |
2342 | 69 /* Mask to determine which y pixels can be written in a pass */ |
70 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = { | |
71 0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55, | |
72 }; | |
73 | |
74 /* Mask to determine which pixels to overwrite while displaying */ | |
2967 | 75 static const uint8_t png_pass_dsp_mask[NB_PASSES] = { |
2342 | 76 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff |
77 }; | |
78 | |
79 /* NOTE: we try to construct a good looking image at each pass. width | |
5355 | 80 is the original image width. We also do pixel format conversion at |
2342 | 81 this stage */ |
2967 | 82 static void png_put_interlaced_row(uint8_t *dst, int width, |
83 int bits_per_pixel, int pass, | |
2342 | 84 int color_type, const uint8_t *src) |
85 { | |
86 int x, mask, dsp_mask, j, src_x, b, bpp; | |
87 uint8_t *d; | |
88 const uint8_t *s; | |
2967 | 89 |
5337 | 90 mask = ff_png_pass_mask[pass]; |
2342 | 91 dsp_mask = png_pass_dsp_mask[pass]; |
92 switch(bits_per_pixel) { | |
93 case 1: | |
5097 | 94 /* we must initialize the line to zero before writing to it */ |
2342 | 95 if (pass == 0) |
96 memset(dst, 0, (width + 7) >> 3); | |
97 src_x = 0; | |
98 for(x = 0; x < width; x++) { | |
99 j = (x & 7); | |
100 if ((dsp_mask << j) & 0x80) { | |
101 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1; | |
102 dst[x >> 3] |= b << (7 - j); | |
103 } | |
104 if ((mask << j) & 0x80) | |
105 src_x++; | |
106 } | |
107 break; | |
108 default: | |
109 bpp = bits_per_pixel >> 3; | |
110 d = dst; | |
111 s = src; | |
112 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
113 for(x = 0; x < width; x++) { | |
114 j = x & 7; | |
115 if ((dsp_mask << j) & 0x80) { | |
116 *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2]; | |
117 } | |
118 d += bpp; | |
119 if ((mask << j) & 0x80) | |
120 s += bpp; | |
121 } | |
122 } else { | |
123 for(x = 0; x < width; x++) { | |
124 j = x & 7; | |
125 if ((dsp_mask << j) & 0x80) { | |
126 memcpy(d, s, bpp); | |
127 } | |
128 d += bpp; | |
129 if ((mask << j) & 0x80) | |
130 s += bpp; | |
131 } | |
132 } | |
133 break; | |
134 } | |
135 } | |
136 | |
6384 | 137 void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) |
138 { | |
139 int i; | |
140 for(i = 0; i < w; i++) { | |
141 int a, b, c, p, pa, pb, pc; | |
142 | |
143 a = dst[i - bpp]; | |
144 b = top[i]; | |
145 c = top[i - bpp]; | |
146 | |
147 p = b - c; | |
148 pc = a - c; | |
149 | |
150 pa = abs(p); | |
151 pb = abs(pc); | |
152 pc = abs(p + pc); | |
153 | |
154 if (pa <= pb && pa <= pc) | |
155 p = a; | |
156 else if (pb <= pc) | |
157 p = b; | |
158 else | |
159 p = c; | |
160 dst[i] = p + src[i]; | |
161 } | |
162 } | |
163 | |
164 #define UNROLL1(bpp, op) {\ | |
165 r = dst[0];\ | |
166 if(bpp >= 2) g = dst[1];\ | |
167 if(bpp >= 3) b = dst[2];\ | |
168 if(bpp >= 4) a = dst[3];\ | |
169 for(; i < size; i+=bpp) {\ | |
170 dst[i+0] = r = op(r, src[i+0], last[i+0]);\ | |
171 if(bpp == 1) continue;\ | |
172 dst[i+1] = g = op(g, src[i+1], last[i+1]);\ | |
173 if(bpp == 2) continue;\ | |
174 dst[i+2] = b = op(b, src[i+2], last[i+2]);\ | |
175 if(bpp == 3) continue;\ | |
176 dst[i+3] = a = op(a, src[i+3], last[i+3]);\ | |
177 }\ | |
178 } | |
179 | |
180 #define UNROLL_FILTER(op)\ | |
181 if(bpp == 1) UNROLL1(1, op)\ | |
182 else if(bpp == 2) UNROLL1(2, op)\ | |
183 else if(bpp == 3) UNROLL1(3, op)\ | |
184 else if(bpp == 4) UNROLL1(4, op)\ | |
9895 | 185 else {\ |
186 for (; i < size; i += bpp) {\ | |
187 int j;\ | |
188 for (j = 0; j < bpp; j++)\ | |
189 dst[i+j] = op(dst[i+j-bpp], src[i+j], last[i+j]);\ | |
190 }\ | |
191 } | |
6384 | 192 |
2342 | 193 /* NOTE: 'dst' can be equal to 'last' */ |
6384 | 194 static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type, |
2342 | 195 uint8_t *src, uint8_t *last, int size, int bpp) |
196 { | |
6384 | 197 int i, p, r, g, b, a; |
2342 | 198 |
199 switch(filter_type) { | |
200 case PNG_FILTER_VALUE_NONE: | |
201 memcpy(dst, src, size); | |
202 break; | |
203 case PNG_FILTER_VALUE_SUB: | |
204 for(i = 0; i < bpp; i++) { | |
205 dst[i] = src[i]; | |
206 } | |
6384 | 207 if(bpp == 4) { |
208 p = *(int*)dst; | |
209 for(; i < size; i+=bpp) { | |
210 int s = *(int*)(src+i); | |
211 p = ((s&0x7f7f7f7f) + (p&0x7f7f7f7f)) ^ ((s^p)&0x80808080); | |
212 *(int*)(dst+i) = p; | |
213 } | |
214 } else { | |
215 #define OP_SUB(x,s,l) x+s | |
216 UNROLL_FILTER(OP_SUB); | |
2342 | 217 } |
218 break; | |
219 case PNG_FILTER_VALUE_UP: | |
6384 | 220 dsp->add_bytes_l2(dst, src, last, size); |
2342 | 221 break; |
222 case PNG_FILTER_VALUE_AVG: | |
223 for(i = 0; i < bpp; i++) { | |
224 p = (last[i] >> 1); | |
225 dst[i] = p + src[i]; | |
226 } | |
6384 | 227 #define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff |
228 UNROLL_FILTER(OP_AVG); | |
2342 | 229 break; |
230 case PNG_FILTER_VALUE_PAETH: | |
231 for(i = 0; i < bpp; i++) { | |
232 p = last[i]; | |
233 dst[i] = p + src[i]; | |
234 } | |
6384 | 235 if(bpp > 1 && size > 4) { |
236 // would write off the end of the array if we let it process the last pixel with bpp=3 | |
237 int w = bpp==4 ? size : size-3; | |
238 dsp->add_png_paeth_prediction(dst+i, src+i, last+i, w-i, bpp); | |
239 i = w; | |
2342 | 240 } |
6384 | 241 ff_add_png_paeth_prediction(dst+i, src+i, last+i, size-i, bpp); |
2342 | 242 break; |
243 } | |
244 } | |
245 | |
6406 | 246 static av_always_inline void convert_to_rgb32_loco(uint8_t *dst, const uint8_t *src, int width, int loco) |
2342 | 247 { |
248 int j; | |
249 unsigned int r, g, b, a; | |
250 | |
251 for(j = 0;j < width; j++) { | |
252 r = src[0]; | |
253 g = src[1]; | |
254 b = src[2]; | |
255 a = src[3]; | |
6406 | 256 if(loco) { |
257 r = (r+g)&0xff; | |
258 b = (b+g)&0xff; | |
259 } | |
2342 | 260 *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b; |
261 dst += 4; | |
262 src += 4; | |
263 } | |
264 } | |
265 | |
6406 | 266 static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width, int loco) |
267 { | |
268 if(loco) | |
269 convert_to_rgb32_loco(dst, src, width, 1); | |
270 else | |
271 convert_to_rgb32_loco(dst, src, width, 0); | |
272 } | |
273 | |
274 static void deloco_rgb24(uint8_t *dst, int size) | |
275 { | |
276 int i; | |
277 for(i=0; i<size; i+=3) { | |
278 int g = dst[i+1]; | |
279 dst[i+0] += g; | |
280 dst[i+2] += g; | |
281 } | |
282 } | |
283 | |
2342 | 284 /* process exactly one decompressed row */ |
5339 | 285 static void png_handle_row(PNGDecContext *s) |
2342 | 286 { |
287 uint8_t *ptr, *last_row; | |
288 int got_line; | |
2967 | 289 |
2342 | 290 if (!s->interlace_type) { |
291 ptr = s->image_buf + s->image_linesize * s->y; | |
292 /* need to swap bytes correctly for RGB_ALPHA */ | |
293 if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
6384 | 294 png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, |
2342 | 295 s->last_row, s->row_size, s->bpp); |
6406 | 296 convert_to_rgb32(ptr, s->tmp_row, s->width, s->filter_type == PNG_FILTER_TYPE_LOCO); |
6394 | 297 FFSWAP(uint8_t*, s->last_row, s->tmp_row); |
2342 | 298 } else { |
299 /* in normal case, we avoid one copy */ | |
300 if (s->y == 0) | |
301 last_row = s->last_row; | |
302 else | |
303 last_row = ptr - s->image_linesize; | |
2967 | 304 |
6384 | 305 png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, |
2342 | 306 last_row, s->row_size, s->bpp); |
307 } | |
6406 | 308 /* loco lags by 1 row so that it doesn't interfere with top prediction */ |
309 if (s->filter_type == PNG_FILTER_TYPE_LOCO && | |
310 s->color_type == PNG_COLOR_TYPE_RGB && s->y > 0) | |
311 deloco_rgb24(ptr - s->image_linesize, s->row_size); | |
2342 | 312 s->y++; |
313 if (s->y == s->height) { | |
314 s->state |= PNG_ALLIMAGE; | |
6406 | 315 if (s->filter_type == PNG_FILTER_TYPE_LOCO && |
316 s->color_type == PNG_COLOR_TYPE_RGB) | |
317 deloco_rgb24(ptr, s->row_size); | |
2342 | 318 } |
319 } else { | |
320 got_line = 0; | |
321 for(;;) { | |
322 ptr = s->image_buf + s->image_linesize * s->y; | |
5337 | 323 if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) { |
2342 | 324 /* if we already read one row, it is time to stop to |
325 wait for the next one */ | |
326 if (got_line) | |
327 break; | |
6384 | 328 png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, |
2342 | 329 s->last_row, s->pass_row_size, s->bpp); |
6394 | 330 FFSWAP(uint8_t*, s->last_row, s->tmp_row); |
2342 | 331 got_line = 1; |
332 } | |
333 if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) { | |
4515 | 334 /* NOTE: RGB32 is handled directly in png_put_interlaced_row */ |
2967 | 335 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass, |
2342 | 336 s->color_type, s->last_row); |
337 } | |
338 s->y++; | |
339 if (s->y == s->height) { | |
340 for(;;) { | |
341 if (s->pass == NB_PASSES - 1) { | |
342 s->state |= PNG_ALLIMAGE; | |
343 goto the_end; | |
344 } else { | |
345 s->pass++; | |
346 s->y = 0; | |
5337 | 347 s->pass_row_size = ff_png_pass_row_size(s->pass, |
2967 | 348 s->bits_per_pixel, |
2342 | 349 s->width); |
350 s->crow_size = s->pass_row_size + 1; | |
351 if (s->pass_row_size != 0) | |
352 break; | |
353 /* skip pass if empty row */ | |
354 } | |
355 } | |
356 } | |
357 } | |
358 the_end: ; | |
359 } | |
360 } | |
361 | |
5339 | 362 static int png_decode_idat(PNGDecContext *s, int length) |
2342 | 363 { |
364 int ret; | |
365 s->zstream.avail_in = length; | |
366 s->zstream.next_in = s->bytestream; | |
367 s->bytestream += length; | |
2967 | 368 |
2342 | 369 if(s->bytestream > s->bytestream_end) |
370 return -1; | |
371 | |
372 /* decode one line if possible */ | |
373 while (s->zstream.avail_in > 0) { | |
374 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); | |
375 if (ret != Z_OK && ret != Z_STREAM_END) { | |
376 return -1; | |
377 } | |
378 if (s->zstream.avail_out == 0) { | |
379 if (!(s->state & PNG_ALLIMAGE)) { | |
380 png_handle_row(s); | |
381 } | |
382 s->zstream.avail_out = s->crow_size; | |
383 s->zstream.next_out = s->crow_buf; | |
384 } | |
385 } | |
386 return 0; | |
387 } | |
388 | |
2967 | 389 static int decode_frame(AVCodecContext *avctx, |
2342 | 390 void *data, int *data_size, |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
391 AVPacket *avpkt) |
2342 | 392 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
393 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
394 int buf_size = avpkt->size; |
5339 | 395 PNGDecContext * const s = avctx->priv_data; |
2342 | 396 AVFrame *picture = data; |
9387 | 397 AVFrame *p; |
9703 | 398 uint8_t *crow_buf_base = NULL; |
2342 | 399 uint32_t tag, length; |
400 int ret, crc; | |
401 | |
9387 | 402 FFSWAP(AVFrame *, s->current_picture, s->last_picture); |
403 avctx->coded_frame= s->current_picture; | |
404 p = s->current_picture; | |
405 | |
2342 | 406 s->bytestream_start= |
407 s->bytestream= buf; | |
408 s->bytestream_end= buf + buf_size; | |
409 | |
410 /* check signature */ | |
6406 | 411 if (memcmp(s->bytestream, ff_pngsig, 8) != 0 && |
412 memcmp(s->bytestream, ff_mngsig, 8) != 0) | |
2342 | 413 return -1; |
414 s->bytestream+= 8; | |
415 s->y= | |
416 s->state=0; | |
5339 | 417 // memset(s, 0, sizeof(PNGDecContext)); |
2342 | 418 /* init the zlib */ |
5337 | 419 s->zstream.zalloc = ff_png_zalloc; |
420 s->zstream.zfree = ff_png_zfree; | |
2342 | 421 s->zstream.opaque = NULL; |
422 ret = inflateInit(&s->zstream); | |
423 if (ret != Z_OK) | |
424 return -1; | |
425 for(;;) { | |
2347
c6280d48be02
When bswap_32 is a macro, png images fail to decode properly, patch by (Milan Cutka <cutka>at<szm>dot<sk>)
michael
parents:
2342
diff
changeset
|
426 int tag32; |
2342 | 427 if (s->bytestream >= s->bytestream_end) |
428 goto fail; | |
5067 | 429 length = bytestream_get_be32(&s->bytestream); |
2342 | 430 if (length > 0x7fffffff) |
431 goto fail; | |
5067 | 432 tag32 = bytestream_get_be32(&s->bytestream); |
12129 | 433 tag = av_bswap32(tag32); |
9999
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
434 dprintf(avctx, "png: tag=%c%c%c%c length=%u\n", |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
435 (tag & 0xff), |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
436 ((tag >> 8) & 0xff), |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
437 ((tag >> 16) & 0xff), |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
438 ((tag >> 24) & 0xff), length); |
2342 | 439 switch(tag) { |
440 case MKTAG('I', 'H', 'D', 'R'): | |
441 if (length != 13) | |
442 goto fail; | |
5067 | 443 s->width = bytestream_get_be32(&s->bytestream); |
444 s->height = bytestream_get_be32(&s->bytestream); | |
12462
ffb3668ff7af
Use new imgutils.h API names, fix deprecation warnings.
stefano
parents:
12372
diff
changeset
|
445 if(av_image_check_size(s->width, s->height, 0, avctx)){ |
2422 | 446 s->width= s->height= 0; |
447 goto fail; | |
448 } | |
2342 | 449 s->bit_depth = *s->bytestream++; |
450 s->color_type = *s->bytestream++; | |
451 s->compression_type = *s->bytestream++; | |
452 s->filter_type = *s->bytestream++; | |
453 s->interlace_type = *s->bytestream++; | |
5067 | 454 crc = bytestream_get_be32(&s->bytestream); |
2342 | 455 s->state |= PNG_IHDR; |
9999
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
456 dprintf(avctx, "width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n", |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
457 s->width, s->height, s->bit_depth, s->color_type, |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
458 s->compression_type, s->filter_type, s->interlace_type); |
2342 | 459 break; |
460 case MKTAG('I', 'D', 'A', 'T'): | |
461 if (!(s->state & PNG_IHDR)) | |
462 goto fail; | |
463 if (!(s->state & PNG_IDAT)) { | |
464 /* init image info */ | |
465 avctx->width = s->width; | |
466 avctx->height = s->height; | |
467 | |
5337 | 468 s->channels = ff_png_get_nb_channels(s->color_type); |
2342 | 469 s->bits_per_pixel = s->bit_depth * s->channels; |
470 s->bpp = (s->bits_per_pixel + 7) >> 3; | |
471 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3; | |
472 | |
2967 | 473 if (s->bit_depth == 8 && |
2342 | 474 s->color_type == PNG_COLOR_TYPE_RGB) { |
475 avctx->pix_fmt = PIX_FMT_RGB24; | |
2967 | 476 } else if (s->bit_depth == 8 && |
2342 | 477 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { |
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4379
diff
changeset
|
478 avctx->pix_fmt = PIX_FMT_RGB32; |
2967 | 479 } else if (s->bit_depth == 8 && |
2342 | 480 s->color_type == PNG_COLOR_TYPE_GRAY) { |
481 avctx->pix_fmt = PIX_FMT_GRAY8; | |
4067 | 482 } else if (s->bit_depth == 16 && |
483 s->color_type == PNG_COLOR_TYPE_GRAY) { | |
484 avctx->pix_fmt = PIX_FMT_GRAY16BE; | |
9895 | 485 } else if (s->bit_depth == 16 && |
486 s->color_type == PNG_COLOR_TYPE_RGB) { | |
487 avctx->pix_fmt = PIX_FMT_RGB48BE; | |
2967 | 488 } else if (s->bit_depth == 1 && |
2342 | 489 s->color_type == PNG_COLOR_TYPE_GRAY) { |
490 avctx->pix_fmt = PIX_FMT_MONOBLACK; | |
491 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) { | |
492 avctx->pix_fmt = PIX_FMT_PAL8; | |
11631 | 493 } else if (s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { |
494 avctx->pix_fmt = PIX_FMT_Y400A; | |
2342 | 495 } else { |
496 goto fail; | |
497 } | |
498 if(p->data[0]) | |
499 avctx->release_buffer(avctx, p); | |
2967 | 500 |
2342 | 501 p->reference= 0; |
502 if(avctx->get_buffer(avctx, p) < 0){ | |
503 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
504 goto fail; | |
505 } | |
506 p->pict_type= FF_I_TYPE; | |
507 p->key_frame= 1; | |
508 p->interlaced_frame = !!s->interlace_type; | |
509 | |
510 /* compute the compressed row size */ | |
511 if (!s->interlace_type) { | |
512 s->crow_size = s->row_size + 1; | |
513 } else { | |
514 s->pass = 0; | |
5337 | 515 s->pass_row_size = ff_png_pass_row_size(s->pass, |
2967 | 516 s->bits_per_pixel, |
2342 | 517 s->width); |
518 s->crow_size = s->pass_row_size + 1; | |
519 } | |
9999
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
520 dprintf(avctx, "row_size=%d crow_size =%d\n", |
c78fd9154378
Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents:
9895
diff
changeset
|
521 s->row_size, s->crow_size); |
2342 | 522 s->image_buf = p->data[0]; |
523 s->image_linesize = p->linesize[0]; | |
524 /* copy the palette if needed */ | |
525 if (s->color_type == PNG_COLOR_TYPE_PALETTE) | |
526 memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t)); | |
527 /* empty row is used if differencing to the first row */ | |
528 s->last_row = av_mallocz(s->row_size); | |
529 if (!s->last_row) | |
530 goto fail; | |
531 if (s->interlace_type || | |
532 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
533 s->tmp_row = av_malloc(s->row_size); | |
534 if (!s->tmp_row) | |
535 goto fail; | |
536 } | |
537 /* compressed row */ | |
9703 | 538 crow_buf_base = av_malloc(s->row_size + 16); |
539 if (!crow_buf_base) | |
2342 | 540 goto fail; |
9703 | 541 |
542 /* we want crow_buf+1 to be 16-byte aligned */ | |
543 s->crow_buf = crow_buf_base + 15; | |
2342 | 544 s->zstream.avail_out = s->crow_size; |
545 s->zstream.next_out = s->crow_buf; | |
546 } | |
547 s->state |= PNG_IDAT; | |
548 if (png_decode_idat(s, length) < 0) | |
549 goto fail; | |
550 /* skip crc */ | |
5067 | 551 crc = bytestream_get_be32(&s->bytestream); |
2342 | 552 break; |
553 case MKTAG('P', 'L', 'T', 'E'): | |
554 { | |
555 int n, i, r, g, b; | |
2967 | 556 |
2342 | 557 if ((length % 3) != 0 || length > 256 * 3) |
558 goto skip_tag; | |
559 /* read the palette */ | |
560 n = length / 3; | |
561 for(i=0;i<n;i++) { | |
562 r = *s->bytestream++; | |
563 g = *s->bytestream++; | |
564 b = *s->bytestream++; | |
565 s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b; | |
566 } | |
567 for(;i<256;i++) { | |
568 s->palette[i] = (0xff << 24); | |
569 } | |
570 s->state |= PNG_PLTE; | |
5067 | 571 crc = bytestream_get_be32(&s->bytestream); |
2342 | 572 } |
573 break; | |
574 case MKTAG('t', 'R', 'N', 'S'): | |
575 { | |
576 int v, i; | |
577 | |
578 /* read the transparency. XXX: Only palette mode supported */ | |
579 if (s->color_type != PNG_COLOR_TYPE_PALETTE || | |
580 length > 256 || | |
581 !(s->state & PNG_PLTE)) | |
582 goto skip_tag; | |
583 for(i=0;i<length;i++) { | |
584 v = *s->bytestream++; | |
585 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); | |
586 } | |
5067 | 587 crc = bytestream_get_be32(&s->bytestream); |
2342 | 588 } |
589 break; | |
590 case MKTAG('I', 'E', 'N', 'D'): | |
591 if (!(s->state & PNG_ALLIMAGE)) | |
592 goto fail; | |
5067 | 593 crc = bytestream_get_be32(&s->bytestream); |
2342 | 594 goto exit_loop; |
595 default: | |
596 /* skip tag */ | |
597 skip_tag: | |
598 s->bytestream += length + 4; | |
599 break; | |
600 } | |
601 } | |
602 exit_loop: | |
9387 | 603 /* handle p-frames only if a predecessor frame is available */ |
604 if(s->last_picture->data[0] != NULL) { | |
11563
5111783be6ad
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
11560
diff
changeset
|
605 if(!(avpkt->flags & AV_PKT_FLAG_KEY)) { |
9387 | 606 int i, j; |
607 uint8_t *pd = s->current_picture->data[0]; | |
608 uint8_t *pd_last = s->last_picture->data[0]; | |
609 | |
610 for(j=0; j < s->height; j++) { | |
611 for(i=0; i < s->width * s->bpp; i++) { | |
612 pd[i] += pd_last[i]; | |
613 } | |
614 pd += s->image_linesize; | |
615 pd_last += s->image_linesize; | |
616 } | |
617 } | |
618 } | |
619 | |
620 *picture= *s->current_picture; | |
7236 | 621 *data_size = sizeof(AVFrame); |
2342 | 622 |
623 ret = s->bytestream - s->bytestream_start; | |
624 the_end: | |
625 inflateEnd(&s->zstream); | |
9703 | 626 av_free(crow_buf_base); |
627 s->crow_buf = NULL; | |
2342 | 628 av_freep(&s->last_row); |
629 av_freep(&s->tmp_row); | |
630 return ret; | |
631 fail: | |
632 ret = -1; | |
633 goto the_end; | |
634 } | |
635 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6406
diff
changeset
|
636 static av_cold int png_dec_init(AVCodecContext *avctx){ |
5339 | 637 PNGDecContext *s = avctx->priv_data; |
638 | |
9387 | 639 s->current_picture = &s->picture1; |
640 s->last_picture = &s->picture2; | |
641 avcodec_get_frame_defaults(&s->picture1); | |
642 avcodec_get_frame_defaults(&s->picture2); | |
6384 | 643 dsputil_init(&s->dsp, avctx); |
5339 | 644 |
645 return 0; | |
646 } | |
647 | |
10611 | 648 static av_cold int png_dec_end(AVCodecContext *avctx) |
649 { | |
650 PNGDecContext *s = avctx->priv_data; | |
651 | |
652 if (s->picture1.data[0]) | |
653 avctx->release_buffer(avctx, &s->picture1); | |
654 if (s->picture2.data[0]) | |
655 avctx->release_buffer(avctx, &s->picture2); | |
656 | |
657 return 0; | |
658 } | |
659 | |
2342 | 660 AVCodec png_decoder = { |
661 "png", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10611
diff
changeset
|
662 AVMEDIA_TYPE_VIDEO, |
2342 | 663 CODEC_ID_PNG, |
5339 | 664 sizeof(PNGDecContext), |
665 png_dec_init, | |
2342 | 666 NULL, |
10611 | 667 png_dec_end, |
2342 | 668 decode_frame, |
9803 | 669 CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/, |
6722 | 670 NULL, |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11631
diff
changeset
|
671 .max_lowres = 5, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6722
diff
changeset
|
672 .long_name = NULL_IF_CONFIG_SMALL("PNG image"), |
2342 | 673 }; |