00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avcodec.h"
00022 #include "bytestream.h"
00023 #include "png.h"
00024
00025
00026
00027
00028
00029 #include <zlib.h>
00030
00031
00032
00033 typedef struct PNGDecContext {
00034 const uint8_t *bytestream;
00035 const uint8_t *bytestream_start;
00036 const uint8_t *bytestream_end;
00037 AVFrame picture;
00038
00039 int state;
00040 int width, height;
00041 int bit_depth;
00042 int color_type;
00043 int compression_type;
00044 int interlace_type;
00045 int filter_type;
00046 int channels;
00047 int bits_per_pixel;
00048 int bpp;
00049
00050 uint8_t *image_buf;
00051 int image_linesize;
00052 uint32_t palette[256];
00053 uint8_t *crow_buf;
00054 uint8_t *last_row;
00055 uint8_t *tmp_row;
00056 int pass;
00057 int crow_size;
00058 int row_size;
00059 int pass_row_size;
00060 int y;
00061 z_stream zstream;
00062 } PNGDecContext;
00063
00064
00065 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
00066 0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
00067 };
00068
00069
00070 static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
00071 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
00072 };
00073
00074
00075
00076
00077 static void png_put_interlaced_row(uint8_t *dst, int width,
00078 int bits_per_pixel, int pass,
00079 int color_type, const uint8_t *src)
00080 {
00081 int x, mask, dsp_mask, j, src_x, b, bpp;
00082 uint8_t *d;
00083 const uint8_t *s;
00084
00085 mask = ff_png_pass_mask[pass];
00086 dsp_mask = png_pass_dsp_mask[pass];
00087 switch(bits_per_pixel) {
00088 case 1:
00089
00090 if (pass == 0)
00091 memset(dst, 0, (width + 7) >> 3);
00092 src_x = 0;
00093 for(x = 0; x < width; x++) {
00094 j = (x & 7);
00095 if ((dsp_mask << j) & 0x80) {
00096 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
00097 dst[x >> 3] |= b << (7 - j);
00098 }
00099 if ((mask << j) & 0x80)
00100 src_x++;
00101 }
00102 break;
00103 default:
00104 bpp = bits_per_pixel >> 3;
00105 d = dst;
00106 s = src;
00107 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00108 for(x = 0; x < width; x++) {
00109 j = x & 7;
00110 if ((dsp_mask << j) & 0x80) {
00111 *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
00112 }
00113 d += bpp;
00114 if ((mask << j) & 0x80)
00115 s += bpp;
00116 }
00117 } else {
00118 for(x = 0; x < width; x++) {
00119 j = x & 7;
00120 if ((dsp_mask << j) & 0x80) {
00121 memcpy(d, s, bpp);
00122 }
00123 d += bpp;
00124 if ((mask << j) & 0x80)
00125 s += bpp;
00126 }
00127 }
00128 break;
00129 }
00130 }
00131
00132
00133
00134 static void png_filter_row(uint8_t *dst, int filter_type,
00135 uint8_t *src, uint8_t *last, int size, int bpp)
00136 {
00137 int i, p;
00138
00139 switch(filter_type) {
00140 case PNG_FILTER_VALUE_NONE:
00141 memcpy(dst, src, size);
00142 break;
00143 case PNG_FILTER_VALUE_SUB:
00144 for(i = 0; i < bpp; i++) {
00145 dst[i] = src[i];
00146 }
00147 for(i = bpp; i < size; i++) {
00148 p = dst[i - bpp];
00149 dst[i] = p + src[i];
00150 }
00151 break;
00152 case PNG_FILTER_VALUE_UP:
00153 for(i = 0; i < size; i++) {
00154 p = last[i];
00155 dst[i] = p + src[i];
00156 }
00157 break;
00158 case PNG_FILTER_VALUE_AVG:
00159 for(i = 0; i < bpp; i++) {
00160 p = (last[i] >> 1);
00161 dst[i] = p + src[i];
00162 }
00163 for(i = bpp; i < size; i++) {
00164 p = ((dst[i - bpp] + last[i]) >> 1);
00165 dst[i] = p + src[i];
00166 }
00167 break;
00168 case PNG_FILTER_VALUE_PAETH:
00169 for(i = 0; i < bpp; i++) {
00170 p = last[i];
00171 dst[i] = p + src[i];
00172 }
00173 for(i = bpp; i < size; i++) {
00174 int a, b, c, pa, pb, pc;
00175
00176 a = dst[i - bpp];
00177 b = last[i];
00178 c = last[i - bpp];
00179
00180 p = b - c;
00181 pc = a - c;
00182
00183 pa = abs(p);
00184 pb = abs(pc);
00185 pc = abs(p + pc);
00186
00187 if (pa <= pb && pa <= pc)
00188 p = a;
00189 else if (pb <= pc)
00190 p = b;
00191 else
00192 p = c;
00193 dst[i] = p + src[i];
00194 }
00195 break;
00196 }
00197 }
00198
00199 static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width)
00200 {
00201 int j;
00202 unsigned int r, g, b, a;
00203
00204 for(j = 0;j < width; j++) {
00205 r = src[0];
00206 g = src[1];
00207 b = src[2];
00208 a = src[3];
00209 *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
00210 dst += 4;
00211 src += 4;
00212 }
00213 }
00214
00215
00216 static void png_handle_row(PNGDecContext *s)
00217 {
00218 uint8_t *ptr, *last_row;
00219 int got_line;
00220
00221 if (!s->interlace_type) {
00222 ptr = s->image_buf + s->image_linesize * s->y;
00223
00224 if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00225 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
00226 s->last_row, s->row_size, s->bpp);
00227 memcpy(s->last_row, s->tmp_row, s->row_size);
00228 convert_to_rgb32(ptr, s->tmp_row, s->width);
00229 } else {
00230
00231 if (s->y == 0)
00232 last_row = s->last_row;
00233 else
00234 last_row = ptr - s->image_linesize;
00235
00236 png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
00237 last_row, s->row_size, s->bpp);
00238 }
00239 s->y++;
00240 if (s->y == s->height) {
00241 s->state |= PNG_ALLIMAGE;
00242 }
00243 } else {
00244 got_line = 0;
00245 for(;;) {
00246 ptr = s->image_buf + s->image_linesize * s->y;
00247 if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
00248
00249
00250 if (got_line)
00251 break;
00252 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
00253 s->last_row, s->pass_row_size, s->bpp);
00254 memcpy(s->last_row, s->tmp_row, s->pass_row_size);
00255 got_line = 1;
00256 }
00257 if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
00258
00259 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
00260 s->color_type, s->last_row);
00261 }
00262 s->y++;
00263 if (s->y == s->height) {
00264 for(;;) {
00265 if (s->pass == NB_PASSES - 1) {
00266 s->state |= PNG_ALLIMAGE;
00267 goto the_end;
00268 } else {
00269 s->pass++;
00270 s->y = 0;
00271 s->pass_row_size = ff_png_pass_row_size(s->pass,
00272 s->bits_per_pixel,
00273 s->width);
00274 s->crow_size = s->pass_row_size + 1;
00275 if (s->pass_row_size != 0)
00276 break;
00277
00278 }
00279 }
00280 }
00281 }
00282 the_end: ;
00283 }
00284 }
00285
00286 static int png_decode_idat(PNGDecContext *s, int length)
00287 {
00288 int ret;
00289 s->zstream.avail_in = length;
00290 s->zstream.next_in = s->bytestream;
00291 s->bytestream += length;
00292
00293 if(s->bytestream > s->bytestream_end)
00294 return -1;
00295
00296
00297 while (s->zstream.avail_in > 0) {
00298 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
00299 if (ret != Z_OK && ret != Z_STREAM_END) {
00300 return -1;
00301 }
00302 if (s->zstream.avail_out == 0) {
00303 if (!(s->state & PNG_ALLIMAGE)) {
00304 png_handle_row(s);
00305 }
00306 s->zstream.avail_out = s->crow_size;
00307 s->zstream.next_out = s->crow_buf;
00308 }
00309 }
00310 return 0;
00311 }
00312
00313 static int decode_frame(AVCodecContext *avctx,
00314 void *data, int *data_size,
00315 const uint8_t *buf, int buf_size)
00316 {
00317 PNGDecContext * const s = avctx->priv_data;
00318 AVFrame *picture = data;
00319 AVFrame * const p= (AVFrame*)&s->picture;
00320 uint32_t tag, length;
00321 int ret, crc;
00322
00323 s->bytestream_start=
00324 s->bytestream= buf;
00325 s->bytestream_end= buf + buf_size;
00326
00327
00328 if (memcmp(s->bytestream, ff_pngsig, 8) != 0)
00329 return -1;
00330 s->bytestream+= 8;
00331 s->y=
00332 s->state=0;
00333
00334
00335 s->zstream.zalloc = ff_png_zalloc;
00336 s->zstream.zfree = ff_png_zfree;
00337 s->zstream.opaque = NULL;
00338 ret = inflateInit(&s->zstream);
00339 if (ret != Z_OK)
00340 return -1;
00341 for(;;) {
00342 int tag32;
00343 if (s->bytestream >= s->bytestream_end)
00344 goto fail;
00345 length = bytestream_get_be32(&s->bytestream);
00346 if (length > 0x7fffffff)
00347 goto fail;
00348 tag32 = bytestream_get_be32(&s->bytestream);
00349 tag = bswap_32(tag32);
00350 #ifdef DEBUG
00351 av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
00352 (tag & 0xff),
00353 ((tag >> 8) & 0xff),
00354 ((tag >> 16) & 0xff),
00355 ((tag >> 24) & 0xff), length);
00356 #endif
00357 switch(tag) {
00358 case MKTAG('I', 'H', 'D', 'R'):
00359 if (length != 13)
00360 goto fail;
00361 s->width = bytestream_get_be32(&s->bytestream);
00362 s->height = bytestream_get_be32(&s->bytestream);
00363 if(avcodec_check_dimensions(avctx, s->width, s->height)){
00364 s->width= s->height= 0;
00365 goto fail;
00366 }
00367 s->bit_depth = *s->bytestream++;
00368 s->color_type = *s->bytestream++;
00369 s->compression_type = *s->bytestream++;
00370 s->filter_type = *s->bytestream++;
00371 s->interlace_type = *s->bytestream++;
00372 crc = bytestream_get_be32(&s->bytestream);
00373 s->state |= PNG_IHDR;
00374 #ifdef DEBUG
00375 av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n",
00376 s->width, s->height, s->bit_depth, s->color_type,
00377 s->compression_type, s->filter_type, s->interlace_type);
00378 #endif
00379 break;
00380 case MKTAG('I', 'D', 'A', 'T'):
00381 if (!(s->state & PNG_IHDR))
00382 goto fail;
00383 if (!(s->state & PNG_IDAT)) {
00384
00385 avctx->width = s->width;
00386 avctx->height = s->height;
00387
00388 s->channels = ff_png_get_nb_channels(s->color_type);
00389 s->bits_per_pixel = s->bit_depth * s->channels;
00390 s->bpp = (s->bits_per_pixel + 7) >> 3;
00391 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
00392
00393 if (s->bit_depth == 8 &&
00394 s->color_type == PNG_COLOR_TYPE_RGB) {
00395 avctx->pix_fmt = PIX_FMT_RGB24;
00396 } else if (s->bit_depth == 8 &&
00397 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00398 avctx->pix_fmt = PIX_FMT_RGB32;
00399 } else if (s->bit_depth == 8 &&
00400 s->color_type == PNG_COLOR_TYPE_GRAY) {
00401 avctx->pix_fmt = PIX_FMT_GRAY8;
00402 } else if (s->bit_depth == 16 &&
00403 s->color_type == PNG_COLOR_TYPE_GRAY) {
00404 avctx->pix_fmt = PIX_FMT_GRAY16BE;
00405 } else if (s->bit_depth == 1 &&
00406 s->color_type == PNG_COLOR_TYPE_GRAY) {
00407 avctx->pix_fmt = PIX_FMT_MONOBLACK;
00408 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
00409 avctx->pix_fmt = PIX_FMT_PAL8;
00410 } else {
00411 goto fail;
00412 }
00413 if(p->data[0])
00414 avctx->release_buffer(avctx, p);
00415
00416 p->reference= 0;
00417 if(avctx->get_buffer(avctx, p) < 0){
00418 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00419 goto fail;
00420 }
00421 p->pict_type= FF_I_TYPE;
00422 p->key_frame= 1;
00423 p->interlaced_frame = !!s->interlace_type;
00424
00425
00426 if (!s->interlace_type) {
00427 s->crow_size = s->row_size + 1;
00428 } else {
00429 s->pass = 0;
00430 s->pass_row_size = ff_png_pass_row_size(s->pass,
00431 s->bits_per_pixel,
00432 s->width);
00433 s->crow_size = s->pass_row_size + 1;
00434 }
00435 #ifdef DEBUG
00436 av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
00437 s->row_size, s->crow_size);
00438 #endif
00439 s->image_buf = p->data[0];
00440 s->image_linesize = p->linesize[0];
00441
00442 if (s->color_type == PNG_COLOR_TYPE_PALETTE)
00443 memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
00444
00445 s->last_row = av_mallocz(s->row_size);
00446 if (!s->last_row)
00447 goto fail;
00448 if (s->interlace_type ||
00449 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00450 s->tmp_row = av_malloc(s->row_size);
00451 if (!s->tmp_row)
00452 goto fail;
00453 }
00454
00455 s->crow_buf = av_malloc(s->row_size + 1);
00456 if (!s->crow_buf)
00457 goto fail;
00458 s->zstream.avail_out = s->crow_size;
00459 s->zstream.next_out = s->crow_buf;
00460 }
00461 s->state |= PNG_IDAT;
00462 if (png_decode_idat(s, length) < 0)
00463 goto fail;
00464
00465 crc = bytestream_get_be32(&s->bytestream);
00466 break;
00467 case MKTAG('P', 'L', 'T', 'E'):
00468 {
00469 int n, i, r, g, b;
00470
00471 if ((length % 3) != 0 || length > 256 * 3)
00472 goto skip_tag;
00473
00474 n = length / 3;
00475 for(i=0;i<n;i++) {
00476 r = *s->bytestream++;
00477 g = *s->bytestream++;
00478 b = *s->bytestream++;
00479 s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
00480 }
00481 for(;i<256;i++) {
00482 s->palette[i] = (0xff << 24);
00483 }
00484 s->state |= PNG_PLTE;
00485 crc = bytestream_get_be32(&s->bytestream);
00486 }
00487 break;
00488 case MKTAG('t', 'R', 'N', 'S'):
00489 {
00490 int v, i;
00491
00492
00493 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
00494 length > 256 ||
00495 !(s->state & PNG_PLTE))
00496 goto skip_tag;
00497 for(i=0;i<length;i++) {
00498 v = *s->bytestream++;
00499 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
00500 }
00501 crc = bytestream_get_be32(&s->bytestream);
00502 }
00503 break;
00504 case MKTAG('I', 'E', 'N', 'D'):
00505 if (!(s->state & PNG_ALLIMAGE))
00506 goto fail;
00507 crc = bytestream_get_be32(&s->bytestream);
00508 goto exit_loop;
00509 default:
00510
00511 skip_tag:
00512 s->bytestream += length + 4;
00513 break;
00514 }
00515 }
00516 exit_loop:
00517 *picture= *(AVFrame*)&s->picture;
00518 *data_size = sizeof(AVPicture);
00519
00520 ret = s->bytestream - s->bytestream_start;
00521 the_end:
00522 inflateEnd(&s->zstream);
00523 av_freep(&s->crow_buf);
00524 av_freep(&s->last_row);
00525 av_freep(&s->tmp_row);
00526 return ret;
00527 fail:
00528 ret = -1;
00529 goto the_end;
00530 }
00531
00532 static int png_dec_init(AVCodecContext *avctx){
00533 PNGDecContext *s = avctx->priv_data;
00534
00535 avcodec_get_frame_defaults((AVFrame*)&s->picture);
00536 avctx->coded_frame= (AVFrame*)&s->picture;
00537
00538 return 0;
00539 }
00540
00541 AVCodec png_decoder = {
00542 "png",
00543 CODEC_TYPE_VIDEO,
00544 CODEC_ID_PNG,
00545 sizeof(PNGDecContext),
00546 png_dec_init,
00547 NULL,
00548 NULL,
00549 decode_frame,
00550 0 ,
00551 NULL
00552 };