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