annotate ffmpeg/libavcodec/pngdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * PNG image format
yading@10 3 * Copyright (c) 2003 Fabrice Bellard
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 //#define DEBUG
yading@10 23
yading@10 24 #include "libavutil/bprint.h"
yading@10 25 #include "libavutil/imgutils.h"
yading@10 26 #include "avcodec.h"
yading@10 27 #include "bytestream.h"
yading@10 28 #include "internal.h"
yading@10 29 #include "png.h"
yading@10 30 #include "pngdsp.h"
yading@10 31
yading@10 32 /* TODO:
yading@10 33 * - add 16 bit depth support
yading@10 34 */
yading@10 35
yading@10 36 #include <zlib.h>
yading@10 37
yading@10 38 //#define DEBUG
yading@10 39
yading@10 40 typedef struct PNGDecContext {
yading@10 41 PNGDSPContext dsp;
yading@10 42 AVCodecContext *avctx;
yading@10 43
yading@10 44 GetByteContext gb;
yading@10 45 AVFrame *prev;
yading@10 46
yading@10 47 int state;
yading@10 48 int width, height;
yading@10 49 int bit_depth;
yading@10 50 int color_type;
yading@10 51 int compression_type;
yading@10 52 int interlace_type;
yading@10 53 int filter_type;
yading@10 54 int channels;
yading@10 55 int bits_per_pixel;
yading@10 56 int bpp;
yading@10 57
yading@10 58 uint8_t *image_buf;
yading@10 59 int image_linesize;
yading@10 60 uint32_t palette[256];
yading@10 61 uint8_t *crow_buf;
yading@10 62 uint8_t *last_row;
yading@10 63 uint8_t *tmp_row;
yading@10 64 int pass;
yading@10 65 int crow_size; /* compressed row size (include filter type) */
yading@10 66 int row_size; /* decompressed row size */
yading@10 67 int pass_row_size; /* decompress row size of the current pass */
yading@10 68 int y;
yading@10 69 z_stream zstream;
yading@10 70 } PNGDecContext;
yading@10 71
yading@10 72 /* Mask to determine which pixels are valid in a pass */
yading@10 73 static const uint8_t png_pass_mask[NB_PASSES] = {
yading@10 74 0x01, 0x01, 0x11, 0x11, 0x55, 0x55, 0xff,
yading@10 75 };
yading@10 76
yading@10 77 /* Mask to determine which y pixels can be written in a pass */
yading@10 78 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
yading@10 79 0xff, 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
yading@10 80 };
yading@10 81
yading@10 82 /* Mask to determine which pixels to overwrite while displaying */
yading@10 83 static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
yading@10 84 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
yading@10 85 };
yading@10 86
yading@10 87 /* NOTE: we try to construct a good looking image at each pass. width
yading@10 88 is the original image width. We also do pixel format conversion at
yading@10 89 this stage */
yading@10 90 static void png_put_interlaced_row(uint8_t *dst, int width,
yading@10 91 int bits_per_pixel, int pass,
yading@10 92 int color_type, const uint8_t *src)
yading@10 93 {
yading@10 94 int x, mask, dsp_mask, j, src_x, b, bpp;
yading@10 95 uint8_t *d;
yading@10 96 const uint8_t *s;
yading@10 97
yading@10 98 mask = png_pass_mask[pass];
yading@10 99 dsp_mask = png_pass_dsp_mask[pass];
yading@10 100
yading@10 101 switch (bits_per_pixel) {
yading@10 102 case 1:
yading@10 103 src_x = 0;
yading@10 104 for (x = 0; x < width; x++) {
yading@10 105 j = (x & 7);
yading@10 106 if ((dsp_mask << j) & 0x80) {
yading@10 107 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
yading@10 108 dst[x >> 3] &= 0xFF7F>>j;
yading@10 109 dst[x >> 3] |= b << (7 - j);
yading@10 110 }
yading@10 111 if ((mask << j) & 0x80)
yading@10 112 src_x++;
yading@10 113 }
yading@10 114 break;
yading@10 115 case 2:
yading@10 116 src_x = 0;
yading@10 117 for (x = 0; x < width; x++) {
yading@10 118 int j2 = 2 * (x & 3);
yading@10 119 j = (x & 7);
yading@10 120 if ((dsp_mask << j) & 0x80) {
yading@10 121 b = (src[src_x >> 2] >> (6 - 2*(src_x & 3))) & 3;
yading@10 122 dst[x >> 2] &= 0xFF3F>>j2;
yading@10 123 dst[x >> 2] |= b << (6 - j2);
yading@10 124 }
yading@10 125 if ((mask << j) & 0x80)
yading@10 126 src_x++;
yading@10 127 }
yading@10 128 break;
yading@10 129 case 4:
yading@10 130 src_x = 0;
yading@10 131 for (x = 0; x < width; x++) {
yading@10 132 int j2 = 4*(x&1);
yading@10 133 j = (x & 7);
yading@10 134 if ((dsp_mask << j) & 0x80) {
yading@10 135 b = (src[src_x >> 1] >> (4 - 4*(src_x & 1))) & 15;
yading@10 136 dst[x >> 1] &= 0xFF0F>>j2;
yading@10 137 dst[x >> 1] |= b << (4 - j2);
yading@10 138 }
yading@10 139 if ((mask << j) & 0x80)
yading@10 140 src_x++;
yading@10 141 }
yading@10 142 break;
yading@10 143 default:
yading@10 144 bpp = bits_per_pixel >> 3;
yading@10 145 d = dst;
yading@10 146 s = src;
yading@10 147 for (x = 0; x < width; x++) {
yading@10 148 j = x & 7;
yading@10 149 if ((dsp_mask << j) & 0x80) {
yading@10 150 memcpy(d, s, bpp);
yading@10 151 }
yading@10 152 d += bpp;
yading@10 153 if ((mask << j) & 0x80)
yading@10 154 s += bpp;
yading@10 155 }
yading@10 156 break;
yading@10 157 }
yading@10 158 }
yading@10 159
yading@10 160 void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp)
yading@10 161 {
yading@10 162 int i;
yading@10 163 for (i = 0; i < w; i++) {
yading@10 164 int a, b, c, p, pa, pb, pc;
yading@10 165
yading@10 166 a = dst[i - bpp];
yading@10 167 b = top[i];
yading@10 168 c = top[i - bpp];
yading@10 169
yading@10 170 p = b - c;
yading@10 171 pc = a - c;
yading@10 172
yading@10 173 pa = abs(p);
yading@10 174 pb = abs(pc);
yading@10 175 pc = abs(p + pc);
yading@10 176
yading@10 177 if (pa <= pb && pa <= pc)
yading@10 178 p = a;
yading@10 179 else if (pb <= pc)
yading@10 180 p = b;
yading@10 181 else
yading@10 182 p = c;
yading@10 183 dst[i] = p + src[i];
yading@10 184 }
yading@10 185 }
yading@10 186
yading@10 187 #define UNROLL1(bpp, op) {\
yading@10 188 r = dst[0];\
yading@10 189 if(bpp >= 2) g = dst[1];\
yading@10 190 if(bpp >= 3) b = dst[2];\
yading@10 191 if(bpp >= 4) a = dst[3];\
yading@10 192 for(; i <= size - bpp; i+=bpp) {\
yading@10 193 dst[i+0] = r = op(r, src[i+0], last[i+0]);\
yading@10 194 if(bpp == 1) continue;\
yading@10 195 dst[i+1] = g = op(g, src[i+1], last[i+1]);\
yading@10 196 if(bpp == 2) continue;\
yading@10 197 dst[i+2] = b = op(b, src[i+2], last[i+2]);\
yading@10 198 if(bpp == 3) continue;\
yading@10 199 dst[i+3] = a = op(a, src[i+3], last[i+3]);\
yading@10 200 }\
yading@10 201 }
yading@10 202
yading@10 203 #define UNROLL_FILTER(op)\
yading@10 204 if(bpp == 1) UNROLL1(1, op)\
yading@10 205 else if(bpp == 2) UNROLL1(2, op)\
yading@10 206 else if(bpp == 3) UNROLL1(3, op)\
yading@10 207 else if(bpp == 4) UNROLL1(4, op)\
yading@10 208 for (; i < size; i++) {\
yading@10 209 dst[i] = op(dst[i-bpp], src[i], last[i]);\
yading@10 210 }\
yading@10 211
yading@10 212 /* NOTE: 'dst' can be equal to 'last' */
yading@10 213 static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type,
yading@10 214 uint8_t *src, uint8_t *last, int size, int bpp)
yading@10 215 {
yading@10 216 int i, p, r, g, b, a;
yading@10 217
yading@10 218 switch (filter_type) {
yading@10 219 case PNG_FILTER_VALUE_NONE:
yading@10 220 memcpy(dst, src, size);
yading@10 221 break;
yading@10 222 case PNG_FILTER_VALUE_SUB:
yading@10 223 for (i = 0; i < bpp; i++) {
yading@10 224 dst[i] = src[i];
yading@10 225 }
yading@10 226 if (bpp == 4) {
yading@10 227 p = *(int*)dst;
yading@10 228 for (; i < size; i += bpp) {
yading@10 229 int s = *(int*)(src + i);
yading@10 230 p = ((s & 0x7f7f7f7f) + (p & 0x7f7f7f7f)) ^ ((s ^ p) & 0x80808080);
yading@10 231 *(int*)(dst + i) = p;
yading@10 232 }
yading@10 233 } else {
yading@10 234 #define OP_SUB(x,s,l) x+s
yading@10 235 UNROLL_FILTER(OP_SUB);
yading@10 236 }
yading@10 237 break;
yading@10 238 case PNG_FILTER_VALUE_UP:
yading@10 239 dsp->add_bytes_l2(dst, src, last, size);
yading@10 240 break;
yading@10 241 case PNG_FILTER_VALUE_AVG:
yading@10 242 for (i = 0; i < bpp; i++) {
yading@10 243 p = (last[i] >> 1);
yading@10 244 dst[i] = p + src[i];
yading@10 245 }
yading@10 246 #define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff
yading@10 247 UNROLL_FILTER(OP_AVG);
yading@10 248 break;
yading@10 249 case PNG_FILTER_VALUE_PAETH:
yading@10 250 for (i = 0; i < bpp; i++) {
yading@10 251 p = last[i];
yading@10 252 dst[i] = p + src[i];
yading@10 253 }
yading@10 254 if (bpp > 2 && size > 4) {
yading@10 255 // would write off the end of the array if we let it process the last pixel with bpp=3
yading@10 256 int w = bpp == 4 ? size : size - 3;
yading@10 257 dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp);
yading@10 258 i = w;
yading@10 259 }
yading@10 260 ff_add_png_paeth_prediction(dst + i, src + i, last + i, size - i, bpp);
yading@10 261 break;
yading@10 262 }
yading@10 263 }
yading@10 264
yading@10 265 /* This used to be called "deloco" in FFmpeg
yading@10 266 * and is actually an inverse reversible colorspace transformation */
yading@10 267 #define YUV2RGB(NAME, TYPE) \
yading@10 268 static void deloco_ ## NAME(TYPE *dst, int size, int alpha) \
yading@10 269 { \
yading@10 270 int i; \
yading@10 271 for (i = 0; i < size; i += 3 + alpha) { \
yading@10 272 int g = dst [i+1]; \
yading@10 273 dst[i+0] += g; \
yading@10 274 dst[i+2] += g; \
yading@10 275 } \
yading@10 276 }
yading@10 277
yading@10 278 YUV2RGB(rgb8, uint8_t)
yading@10 279 YUV2RGB(rgb16, uint16_t)
yading@10 280
yading@10 281 /* process exactly one decompressed row */
yading@10 282 static void png_handle_row(PNGDecContext *s)
yading@10 283 {
yading@10 284 uint8_t *ptr, *last_row;
yading@10 285 int got_line;
yading@10 286
yading@10 287 if (!s->interlace_type) {
yading@10 288 ptr = s->image_buf + s->image_linesize * s->y;
yading@10 289 if (s->y == 0)
yading@10 290 last_row = s->last_row;
yading@10 291 else
yading@10 292 last_row = ptr - s->image_linesize;
yading@10 293
yading@10 294 png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,
yading@10 295 last_row, s->row_size, s->bpp);
yading@10 296 /* loco lags by 1 row so that it doesn't interfere with top prediction */
yading@10 297 if (s->filter_type == PNG_FILTER_TYPE_LOCO && s->y > 0) {
yading@10 298 if (s->bit_depth == 16) {
yading@10 299 deloco_rgb16((uint16_t *)(ptr - s->image_linesize), s->row_size / 2,
yading@10 300 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
yading@10 301 } else {
yading@10 302 deloco_rgb8(ptr - s->image_linesize, s->row_size,
yading@10 303 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
yading@10 304 }
yading@10 305 }
yading@10 306 s->y++;
yading@10 307 if (s->y == s->height) {
yading@10 308 s->state |= PNG_ALLIMAGE;
yading@10 309 if (s->filter_type == PNG_FILTER_TYPE_LOCO) {
yading@10 310 if (s->bit_depth == 16) {
yading@10 311 deloco_rgb16((uint16_t *)ptr, s->row_size / 2,
yading@10 312 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
yading@10 313 } else {
yading@10 314 deloco_rgb8(ptr, s->row_size,
yading@10 315 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
yading@10 316 }
yading@10 317 }
yading@10 318 }
yading@10 319 } else {
yading@10 320 got_line = 0;
yading@10 321 for (;;) {
yading@10 322 ptr = s->image_buf + s->image_linesize * s->y;
yading@10 323 if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
yading@10 324 /* if we already read one row, it is time to stop to
yading@10 325 wait for the next one */
yading@10 326 if (got_line)
yading@10 327 break;
yading@10 328 png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
yading@10 329 s->last_row, s->pass_row_size, s->bpp);
yading@10 330 FFSWAP(uint8_t*, s->last_row, s->tmp_row);
yading@10 331 got_line = 1;
yading@10 332 }
yading@10 333 if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
yading@10 334 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
yading@10 335 s->color_type, s->last_row);
yading@10 336 }
yading@10 337 s->y++;
yading@10 338 if (s->y == s->height) {
yading@10 339 memset(s->last_row, 0, s->row_size);
yading@10 340 for (;;) {
yading@10 341 if (s->pass == NB_PASSES - 1) {
yading@10 342 s->state |= PNG_ALLIMAGE;
yading@10 343 goto the_end;
yading@10 344 } else {
yading@10 345 s->pass++;
yading@10 346 s->y = 0;
yading@10 347 s->pass_row_size = ff_png_pass_row_size(s->pass,
yading@10 348 s->bits_per_pixel,
yading@10 349 s->width);
yading@10 350 s->crow_size = s->pass_row_size + 1;
yading@10 351 if (s->pass_row_size != 0)
yading@10 352 break;
yading@10 353 /* skip pass if empty row */
yading@10 354 }
yading@10 355 }
yading@10 356 }
yading@10 357 }
yading@10 358 the_end: ;
yading@10 359 }
yading@10 360 }
yading@10 361
yading@10 362 static int png_decode_idat(PNGDecContext *s, int length)
yading@10 363 {
yading@10 364 int ret;
yading@10 365 s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
yading@10 366 s->zstream.next_in = (unsigned char *)s->gb.buffer;
yading@10 367 bytestream2_skip(&s->gb, length);
yading@10 368
yading@10 369 /* decode one line if possible */
yading@10 370 while (s->zstream.avail_in > 0) {
yading@10 371 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
yading@10 372 if (ret != Z_OK && ret != Z_STREAM_END) {
yading@10 373 av_log(s->avctx, AV_LOG_ERROR, "inflate returned %d\n", ret);
yading@10 374 return -1;
yading@10 375 }
yading@10 376 if (s->zstream.avail_out == 0) {
yading@10 377 if (!(s->state & PNG_ALLIMAGE)) {
yading@10 378 png_handle_row(s);
yading@10 379 }
yading@10 380 s->zstream.avail_out = s->crow_size;
yading@10 381 s->zstream.next_out = s->crow_buf;
yading@10 382 }
yading@10 383 }
yading@10 384 return 0;
yading@10 385 }
yading@10 386
yading@10 387 static int decode_zbuf(AVBPrint *bp, const uint8_t *data,
yading@10 388 const uint8_t *data_end)
yading@10 389 {
yading@10 390 z_stream zstream;
yading@10 391 unsigned char *buf;
yading@10 392 unsigned buf_size;
yading@10 393 int ret;
yading@10 394
yading@10 395 zstream.zalloc = ff_png_zalloc;
yading@10 396 zstream.zfree = ff_png_zfree;
yading@10 397 zstream.opaque = NULL;
yading@10 398 if (inflateInit(&zstream) != Z_OK)
yading@10 399 return AVERROR_EXTERNAL;
yading@10 400 zstream.next_in = (unsigned char *)data;
yading@10 401 zstream.avail_in = data_end - data;
yading@10 402 av_bprint_init(bp, 0, -1);
yading@10 403
yading@10 404 while (zstream.avail_in > 0) {
yading@10 405 av_bprint_get_buffer(bp, 1, &buf, &buf_size);
yading@10 406 if (!buf_size) {
yading@10 407 ret = AVERROR(ENOMEM);
yading@10 408 goto fail;
yading@10 409 }
yading@10 410 zstream.next_out = buf;
yading@10 411 zstream.avail_out = buf_size;
yading@10 412 ret = inflate(&zstream, Z_PARTIAL_FLUSH);
yading@10 413 if (ret != Z_OK && ret != Z_STREAM_END) {
yading@10 414 ret = AVERROR_EXTERNAL;
yading@10 415 goto fail;
yading@10 416 }
yading@10 417 bp->len += zstream.next_out - buf;
yading@10 418 if (ret == Z_STREAM_END)
yading@10 419 break;
yading@10 420 }
yading@10 421 inflateEnd(&zstream);
yading@10 422 bp->str[bp->len] = 0;
yading@10 423 return 0;
yading@10 424
yading@10 425 fail:
yading@10 426 inflateEnd(&zstream);
yading@10 427 av_bprint_finalize(bp, NULL);
yading@10 428 return ret;
yading@10 429 }
yading@10 430
yading@10 431 static uint8_t *iso88591_to_utf8(const uint8_t *in, size_t size_in)
yading@10 432 {
yading@10 433 size_t extra = 0, i;
yading@10 434 uint8_t *out, *q;
yading@10 435
yading@10 436 for (i = 0; i < size_in; i++)
yading@10 437 extra += in[i] >= 0x80;
yading@10 438 if (size_in == SIZE_MAX || extra > SIZE_MAX - size_in - 1)
yading@10 439 return NULL;
yading@10 440 q = out = av_malloc(size_in + extra + 1);
yading@10 441 if (!out)
yading@10 442 return NULL;
yading@10 443 for (i = 0; i < size_in; i++) {
yading@10 444 if (in[i] >= 0x80) {
yading@10 445 *(q++) = 0xC0 | (in[i] >> 6);
yading@10 446 *(q++) = 0x80 | (in[i] & 0x3F);
yading@10 447 } else {
yading@10 448 *(q++) = in[i];
yading@10 449 }
yading@10 450 }
yading@10 451 *(q++) = 0;
yading@10 452 return out;
yading@10 453 }
yading@10 454
yading@10 455 static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed,
yading@10 456 AVDictionary **dict)
yading@10 457 {
yading@10 458 int ret, method;
yading@10 459 const uint8_t *data = s->gb.buffer;
yading@10 460 const uint8_t *data_end = data + length;
yading@10 461 const uint8_t *keyword = data;
yading@10 462 const uint8_t *keyword_end = memchr(keyword, 0, data_end - keyword);
yading@10 463 uint8_t *kw_utf8 = NULL, *text, *txt_utf8 = NULL;
yading@10 464 unsigned text_len;
yading@10 465 AVBPrint bp;
yading@10 466
yading@10 467 if (!keyword_end)
yading@10 468 return AVERROR_INVALIDDATA;
yading@10 469 data = keyword_end + 1;
yading@10 470
yading@10 471 if (compressed) {
yading@10 472 if (data == data_end)
yading@10 473 return AVERROR_INVALIDDATA;
yading@10 474 method = *(data++);
yading@10 475 if (method)
yading@10 476 return AVERROR_INVALIDDATA;
yading@10 477 if ((ret = decode_zbuf(&bp, data, data_end)) < 0)
yading@10 478 return ret;
yading@10 479 text_len = bp.len;
yading@10 480 av_bprint_finalize(&bp, (char **)&text);
yading@10 481 if (!text)
yading@10 482 return AVERROR(ENOMEM);
yading@10 483 } else {
yading@10 484 text = (uint8_t *)data;
yading@10 485 text_len = data_end - text;
yading@10 486 }
yading@10 487
yading@10 488 kw_utf8 = iso88591_to_utf8(keyword, keyword_end - keyword);
yading@10 489 txt_utf8 = iso88591_to_utf8(text, text_len);
yading@10 490 if (text != data)
yading@10 491 av_free(text);
yading@10 492 if (!(kw_utf8 && txt_utf8)) {
yading@10 493 av_free(kw_utf8);
yading@10 494 av_free(txt_utf8);
yading@10 495 return AVERROR(ENOMEM);
yading@10 496 }
yading@10 497
yading@10 498 av_dict_set(dict, kw_utf8, txt_utf8,
yading@10 499 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
yading@10 500 return 0;
yading@10 501 }
yading@10 502
yading@10 503 static int decode_frame(AVCodecContext *avctx,
yading@10 504 void *data, int *got_frame,
yading@10 505 AVPacket *avpkt)
yading@10 506 {
yading@10 507 PNGDecContext * const s = avctx->priv_data;
yading@10 508 const uint8_t *buf = avpkt->data;
yading@10 509 int buf_size = avpkt->size;
yading@10 510 AVFrame *p = data;
yading@10 511 AVDictionary *metadata = NULL;
yading@10 512 uint8_t *crow_buf_base = NULL;
yading@10 513 uint32_t tag, length;
yading@10 514 int64_t sig;
yading@10 515 int ret;
yading@10 516
yading@10 517 bytestream2_init(&s->gb, buf, buf_size);
yading@10 518
yading@10 519 /* check signature */
yading@10 520 sig = bytestream2_get_be64(&s->gb);
yading@10 521 if (sig != PNGSIG &&
yading@10 522 sig != MNGSIG) {
yading@10 523 av_log(avctx, AV_LOG_ERROR, "Missing png signature\n");
yading@10 524 return -1;
yading@10 525 }
yading@10 526
yading@10 527 s->y = s->state = 0;
yading@10 528
yading@10 529 /* init the zlib */
yading@10 530 s->zstream.zalloc = ff_png_zalloc;
yading@10 531 s->zstream.zfree = ff_png_zfree;
yading@10 532 s->zstream.opaque = NULL;
yading@10 533 ret = inflateInit(&s->zstream);
yading@10 534 if (ret != Z_OK) {
yading@10 535 av_log(avctx, AV_LOG_ERROR, "inflateInit returned %d\n", ret);
yading@10 536 return -1;
yading@10 537 }
yading@10 538 for (;;) {
yading@10 539 if (bytestream2_get_bytes_left(&s->gb) <= 0) {
yading@10 540 av_log(avctx, AV_LOG_ERROR, "No bytes left\n");
yading@10 541 goto fail;
yading@10 542 }
yading@10 543
yading@10 544 length = bytestream2_get_be32(&s->gb);
yading@10 545 if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) {
yading@10 546 av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
yading@10 547 goto fail;
yading@10 548 }
yading@10 549 tag = bytestream2_get_le32(&s->gb);
yading@10 550 if (avctx->debug & FF_DEBUG_STARTCODE)
yading@10 551 av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
yading@10 552 (tag & 0xff),
yading@10 553 ((tag >> 8) & 0xff),
yading@10 554 ((tag >> 16) & 0xff),
yading@10 555 ((tag >> 24) & 0xff), length);
yading@10 556 switch (tag) {
yading@10 557 case MKTAG('I', 'H', 'D', 'R'):
yading@10 558 if (length != 13)
yading@10 559 goto fail;
yading@10 560 s->width = bytestream2_get_be32(&s->gb);
yading@10 561 s->height = bytestream2_get_be32(&s->gb);
yading@10 562 if (av_image_check_size(s->width, s->height, 0, avctx)) {
yading@10 563 s->width = s->height = 0;
yading@10 564 av_log(avctx, AV_LOG_ERROR, "Invalid image size\n");
yading@10 565 goto fail;
yading@10 566 }
yading@10 567 s->bit_depth = bytestream2_get_byte(&s->gb);
yading@10 568 s->color_type = bytestream2_get_byte(&s->gb);
yading@10 569 s->compression_type = bytestream2_get_byte(&s->gb);
yading@10 570 s->filter_type = bytestream2_get_byte(&s->gb);
yading@10 571 s->interlace_type = bytestream2_get_byte(&s->gb);
yading@10 572 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 573 s->state |= PNG_IHDR;
yading@10 574 if (avctx->debug & FF_DEBUG_PICT_INFO)
yading@10 575 av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
yading@10 576 "compression_type=%d filter_type=%d interlace_type=%d\n",
yading@10 577 s->width, s->height, s->bit_depth, s->color_type,
yading@10 578 s->compression_type, s->filter_type, s->interlace_type);
yading@10 579 break;
yading@10 580 case MKTAG('p', 'H', 'Y', 's'):
yading@10 581 if (s->state & PNG_IDAT) {
yading@10 582 av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
yading@10 583 goto fail;
yading@10 584 }
yading@10 585 avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb);
yading@10 586 avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb);
yading@10 587 if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0)
yading@10 588 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
yading@10 589 bytestream2_skip(&s->gb, 1); /* unit specifier */
yading@10 590 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 591 break;
yading@10 592 case MKTAG('I', 'D', 'A', 'T'):
yading@10 593 if (!(s->state & PNG_IHDR)) {
yading@10 594 av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
yading@10 595 goto fail;
yading@10 596 }
yading@10 597 if (!(s->state & PNG_IDAT)) {
yading@10 598 /* init image info */
yading@10 599 avctx->width = s->width;
yading@10 600 avctx->height = s->height;
yading@10 601
yading@10 602 s->channels = ff_png_get_nb_channels(s->color_type);
yading@10 603 s->bits_per_pixel = s->bit_depth * s->channels;
yading@10 604 s->bpp = (s->bits_per_pixel + 7) >> 3;
yading@10 605 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
yading@10 606
yading@10 607 if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
yading@10 608 s->color_type == PNG_COLOR_TYPE_RGB) {
yading@10 609 avctx->pix_fmt = AV_PIX_FMT_RGB24;
yading@10 610 } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
yading@10 611 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
yading@10 612 avctx->pix_fmt = AV_PIX_FMT_RGBA;
yading@10 613 } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
yading@10 614 s->color_type == PNG_COLOR_TYPE_GRAY) {
yading@10 615 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
yading@10 616 } else if (s->bit_depth == 16 &&
yading@10 617 s->color_type == PNG_COLOR_TYPE_GRAY) {
yading@10 618 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
yading@10 619 } else if (s->bit_depth == 16 &&
yading@10 620 s->color_type == PNG_COLOR_TYPE_RGB) {
yading@10 621 avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
yading@10 622 } else if (s->bit_depth == 16 &&
yading@10 623 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
yading@10 624 avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
yading@10 625 } else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
yading@10 626 s->color_type == PNG_COLOR_TYPE_PALETTE) {
yading@10 627 avctx->pix_fmt = AV_PIX_FMT_PAL8;
yading@10 628 } else if (s->bit_depth == 1) {
yading@10 629 avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
yading@10 630 } else if (s->bit_depth == 8 &&
yading@10 631 s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
yading@10 632 avctx->pix_fmt = AV_PIX_FMT_Y400A;
yading@10 633 } else {
yading@10 634 av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
yading@10 635 "and color type %d\n",
yading@10 636 s->bit_depth, s->color_type);
yading@10 637 goto fail;
yading@10 638 }
yading@10 639
yading@10 640 if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0)
yading@10 641 goto fail;
yading@10 642 p->pict_type = AV_PICTURE_TYPE_I;
yading@10 643 p->key_frame = 1;
yading@10 644 p->interlaced_frame = !!s->interlace_type;
yading@10 645
yading@10 646 /* compute the compressed row size */
yading@10 647 if (!s->interlace_type) {
yading@10 648 s->crow_size = s->row_size + 1;
yading@10 649 } else {
yading@10 650 s->pass = 0;
yading@10 651 s->pass_row_size = ff_png_pass_row_size(s->pass,
yading@10 652 s->bits_per_pixel,
yading@10 653 s->width);
yading@10 654 s->crow_size = s->pass_row_size + 1;
yading@10 655 }
yading@10 656 av_dlog(avctx, "row_size=%d crow_size =%d\n",
yading@10 657 s->row_size, s->crow_size);
yading@10 658 s->image_buf = p->data[0];
yading@10 659 s->image_linesize = p->linesize[0];
yading@10 660 /* copy the palette if needed */
yading@10 661 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
yading@10 662 memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
yading@10 663 /* empty row is used if differencing to the first row */
yading@10 664 s->last_row = av_mallocz(s->row_size);
yading@10 665 if (!s->last_row)
yading@10 666 goto fail;
yading@10 667 if (s->interlace_type ||
yading@10 668 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
yading@10 669 s->tmp_row = av_malloc(s->row_size);
yading@10 670 if (!s->tmp_row)
yading@10 671 goto fail;
yading@10 672 }
yading@10 673 /* compressed row */
yading@10 674 crow_buf_base = av_malloc(s->row_size + 16);
yading@10 675 if (!crow_buf_base)
yading@10 676 goto fail;
yading@10 677
yading@10 678 /* we want crow_buf+1 to be 16-byte aligned */
yading@10 679 s->crow_buf = crow_buf_base + 15;
yading@10 680 s->zstream.avail_out = s->crow_size;
yading@10 681 s->zstream.next_out = s->crow_buf;
yading@10 682 }
yading@10 683 s->state |= PNG_IDAT;
yading@10 684 if (png_decode_idat(s, length) < 0)
yading@10 685 goto fail;
yading@10 686 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 687 break;
yading@10 688 case MKTAG('P', 'L', 'T', 'E'):
yading@10 689 {
yading@10 690 int n, i, r, g, b;
yading@10 691
yading@10 692 if ((length % 3) != 0 || length > 256 * 3)
yading@10 693 goto skip_tag;
yading@10 694 /* read the palette */
yading@10 695 n = length / 3;
yading@10 696 for (i = 0; i < n; i++) {
yading@10 697 r = bytestream2_get_byte(&s->gb);
yading@10 698 g = bytestream2_get_byte(&s->gb);
yading@10 699 b = bytestream2_get_byte(&s->gb);
yading@10 700 s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
yading@10 701 }
yading@10 702 for (; i < 256; i++) {
yading@10 703 s->palette[i] = (0xFFU << 24);
yading@10 704 }
yading@10 705 s->state |= PNG_PLTE;
yading@10 706 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 707 }
yading@10 708 break;
yading@10 709 case MKTAG('t', 'R', 'N', 'S'):
yading@10 710 {
yading@10 711 int v, i;
yading@10 712
yading@10 713 /* read the transparency. XXX: Only palette mode supported */
yading@10 714 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
yading@10 715 length > 256 ||
yading@10 716 !(s->state & PNG_PLTE))
yading@10 717 goto skip_tag;
yading@10 718 for (i = 0; i < length; i++) {
yading@10 719 v = bytestream2_get_byte(&s->gb);
yading@10 720 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
yading@10 721 }
yading@10 722 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 723 }
yading@10 724 break;
yading@10 725 case MKTAG('t', 'E', 'X', 't'):
yading@10 726 if (decode_text_chunk(s, length, 0, &metadata) < 0)
yading@10 727 av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
yading@10 728 bytestream2_skip(&s->gb, length + 4);
yading@10 729 break;
yading@10 730 case MKTAG('z', 'T', 'X', 't'):
yading@10 731 if (decode_text_chunk(s, length, 1, &metadata) < 0)
yading@10 732 av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
yading@10 733 bytestream2_skip(&s->gb, length + 4);
yading@10 734 break;
yading@10 735 case MKTAG('I', 'E', 'N', 'D'):
yading@10 736 if (!(s->state & PNG_ALLIMAGE))
yading@10 737 av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
yading@10 738 if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
yading@10 739 goto fail;
yading@10 740 }
yading@10 741 bytestream2_skip(&s->gb, 4); /* crc */
yading@10 742 goto exit_loop;
yading@10 743 default:
yading@10 744 /* skip tag */
yading@10 745 skip_tag:
yading@10 746 bytestream2_skip(&s->gb, length + 4);
yading@10 747 break;
yading@10 748 }
yading@10 749 }
yading@10 750 exit_loop:
yading@10 751
yading@10 752 if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE){
yading@10 753 int i, j, k;
yading@10 754 uint8_t *pd = p->data[0];
yading@10 755 for (j = 0; j < s->height; j++) {
yading@10 756 i = s->width / 8;
yading@10 757 for (k = 7; k >= 1; k--)
yading@10 758 if ((s->width&7) >= k)
yading@10 759 pd[8*i + k - 1] = (pd[i]>>8-k) & 1;
yading@10 760 for (i--; i >= 0; i--) {
yading@10 761 pd[8*i + 7]= pd[i] & 1;
yading@10 762 pd[8*i + 6]= (pd[i]>>1) & 1;
yading@10 763 pd[8*i + 5]= (pd[i]>>2) & 1;
yading@10 764 pd[8*i + 4]= (pd[i]>>3) & 1;
yading@10 765 pd[8*i + 3]= (pd[i]>>4) & 1;
yading@10 766 pd[8*i + 2]= (pd[i]>>5) & 1;
yading@10 767 pd[8*i + 1]= (pd[i]>>6) & 1;
yading@10 768 pd[8*i + 0]= pd[i]>>7;
yading@10 769 }
yading@10 770 pd += s->image_linesize;
yading@10 771 }
yading@10 772 }
yading@10 773 if (s->bits_per_pixel == 2){
yading@10 774 int i, j;
yading@10 775 uint8_t *pd = p->data[0];
yading@10 776 for (j = 0; j < s->height; j++) {
yading@10 777 i = s->width / 4;
yading@10 778 if (s->color_type == PNG_COLOR_TYPE_PALETTE){
yading@10 779 if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3;
yading@10 780 if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3;
yading@10 781 if ((s->width&3) >= 1) pd[4*i + 0]= pd[i] >> 6;
yading@10 782 for (i--; i >= 0; i--) {
yading@10 783 pd[4*i + 3]= pd[i] & 3;
yading@10 784 pd[4*i + 2]= (pd[i]>>2) & 3;
yading@10 785 pd[4*i + 1]= (pd[i]>>4) & 3;
yading@10 786 pd[4*i + 0]= pd[i]>>6;
yading@10 787 }
yading@10 788 } else {
yading@10 789 if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
yading@10 790 if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
yading@10 791 if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6 )*0x55;
yading@10 792 for (i--; i >= 0; i--) {
yading@10 793 pd[4*i + 3]= ( pd[i] & 3)*0x55;
yading@10 794 pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
yading@10 795 pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
yading@10 796 pd[4*i + 0]= ( pd[i]>>6 )*0x55;
yading@10 797 }
yading@10 798 }
yading@10 799 pd += s->image_linesize;
yading@10 800 }
yading@10 801 }
yading@10 802 if (s->bits_per_pixel == 4){
yading@10 803 int i, j;
yading@10 804 uint8_t *pd = p->data[0];
yading@10 805 for (j = 0; j < s->height; j++) {
yading@10 806 i = s->width/2;
yading@10 807 if (s->color_type == PNG_COLOR_TYPE_PALETTE){
yading@10 808 if (s->width&1) pd[2*i+0]= pd[i]>>4;
yading@10 809 for (i--; i >= 0; i--) {
yading@10 810 pd[2*i + 1] = pd[i] & 15;
yading@10 811 pd[2*i + 0] = pd[i] >> 4;
yading@10 812 }
yading@10 813 } else {
yading@10 814 if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11;
yading@10 815 for (i--; i >= 0; i--) {
yading@10 816 pd[2*i + 1] = (pd[i] & 15) * 0x11;
yading@10 817 pd[2*i + 0] = (pd[i] >> 4) * 0x11;
yading@10 818 }
yading@10 819 }
yading@10 820 pd += s->image_linesize;
yading@10 821 }
yading@10 822 }
yading@10 823
yading@10 824 /* handle p-frames only if a predecessor frame is available */
yading@10 825 if (s->prev->data[0]) {
yading@10 826 if ( !(avpkt->flags & AV_PKT_FLAG_KEY)
yading@10 827 && s->prev->width == p->width
yading@10 828 && s->prev->height== p->height
yading@10 829 && s->prev->format== p->format
yading@10 830 ) {
yading@10 831 int i, j;
yading@10 832 uint8_t *pd = p->data[0];
yading@10 833 uint8_t *pd_last = s->prev->data[0];
yading@10 834
yading@10 835 for (j = 0; j < s->height; j++) {
yading@10 836 for (i = 0; i < s->width * s->bpp; i++) {
yading@10 837 pd[i] += pd_last[i];
yading@10 838 }
yading@10 839 pd += s->image_linesize;
yading@10 840 pd_last += s->image_linesize;
yading@10 841 }
yading@10 842 }
yading@10 843 }
yading@10 844
yading@10 845 av_frame_set_metadata(p, metadata);
yading@10 846 metadata = NULL;
yading@10 847
yading@10 848 av_frame_unref(s->prev);
yading@10 849 if ((ret = av_frame_ref(s->prev, p)) < 0)
yading@10 850 goto fail;
yading@10 851
yading@10 852 *got_frame = 1;
yading@10 853
yading@10 854 ret = bytestream2_tell(&s->gb);
yading@10 855 the_end:
yading@10 856 inflateEnd(&s->zstream);
yading@10 857 av_free(crow_buf_base);
yading@10 858 s->crow_buf = NULL;
yading@10 859 av_freep(&s->last_row);
yading@10 860 av_freep(&s->tmp_row);
yading@10 861 return ret;
yading@10 862 fail:
yading@10 863 av_dict_free(&metadata);
yading@10 864 ret = -1;
yading@10 865 goto the_end;
yading@10 866 }
yading@10 867
yading@10 868 static av_cold int png_dec_init(AVCodecContext *avctx)
yading@10 869 {
yading@10 870 PNGDecContext *s = avctx->priv_data;
yading@10 871
yading@10 872 s->prev = av_frame_alloc();
yading@10 873 if (!s->prev)
yading@10 874 return AVERROR(ENOMEM);
yading@10 875
yading@10 876 ff_pngdsp_init(&s->dsp);
yading@10 877
yading@10 878 s->avctx = avctx;
yading@10 879
yading@10 880 return 0;
yading@10 881 }
yading@10 882
yading@10 883 static av_cold int png_dec_end(AVCodecContext *avctx)
yading@10 884 {
yading@10 885 PNGDecContext *s = avctx->priv_data;
yading@10 886
yading@10 887 av_frame_free(&s->prev);
yading@10 888
yading@10 889 return 0;
yading@10 890 }
yading@10 891
yading@10 892 AVCodec ff_png_decoder = {
yading@10 893 .name = "png",
yading@10 894 .type = AVMEDIA_TYPE_VIDEO,
yading@10 895 .id = AV_CODEC_ID_PNG,
yading@10 896 .priv_data_size = sizeof(PNGDecContext),
yading@10 897 .init = png_dec_init,
yading@10 898 .close = png_dec_end,
yading@10 899 .decode = decode_frame,
yading@10 900 .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
yading@10 901 .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"),
yading@10 902 };