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