00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "avcodec.h"
00020
00021
00022
00023
00024
00025
00026 #ifdef CONFIG_ZLIB
00027 #include <zlib.h>
00028
00029
00030
00031 #define PNG_COLOR_MASK_PALETTE 1
00032 #define PNG_COLOR_MASK_COLOR 2
00033 #define PNG_COLOR_MASK_ALPHA 4
00034
00035 #define PNG_COLOR_TYPE_GRAY 0
00036 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
00037 #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
00038 #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
00039 #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
00040
00041 #define PNG_FILTER_VALUE_NONE 0
00042 #define PNG_FILTER_VALUE_SUB 1
00043 #define PNG_FILTER_VALUE_UP 2
00044 #define PNG_FILTER_VALUE_AVG 3
00045 #define PNG_FILTER_VALUE_PAETH 4
00046
00047 #define PNG_IHDR 0x0001
00048 #define PNG_IDAT 0x0002
00049 #define PNG_ALLIMAGE 0x0004
00050 #define PNG_PLTE 0x0008
00051
00052 #define NB_PASSES 7
00053
00054 #define IOBUF_SIZE 4096
00055
00056 typedef struct PNGContext {
00057 uint8_t *bytestream;
00058 uint8_t *bytestream_start;
00059 uint8_t *bytestream_end;
00060 AVFrame picture;
00061
00062 int state;
00063 int width, height;
00064 int bit_depth;
00065 int color_type;
00066 int compression_type;
00067 int interlace_type;
00068 int filter_type;
00069 int channels;
00070 int bits_per_pixel;
00071 int bpp;
00072
00073 uint8_t *image_buf;
00074 int image_linesize;
00075 uint32_t palette[256];
00076 uint8_t *crow_buf;
00077 uint8_t *last_row;
00078 uint8_t *tmp_row;
00079 int pass;
00080 int crow_size;
00081 int row_size;
00082 int pass_row_size;
00083 int y;
00084 z_stream zstream;
00085 uint8_t buf[IOBUF_SIZE];
00086 } PNGContext;
00087
00088 static unsigned int get32(uint8_t **b){
00089 (*b) += 4;
00090 return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
00091 }
00092
00093 static void put32(uint8_t **b, unsigned int v){
00094 *(*b)++= v>>24;
00095 *(*b)++= v>>16;
00096 *(*b)++= v>>8;
00097 *(*b)++= v;
00098 }
00099
00100 static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
00101
00102
00103 static const uint8_t png_pass_ymask[NB_PASSES] = {
00104 0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
00105 };
00106
00107
00108 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
00109 0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
00110 };
00111
00112
00113 static const uint8_t png_pass_xmin[NB_PASSES] = {
00114 0, 4, 0, 2, 0, 1, 0
00115 };
00116
00117
00118 static const uint8_t png_pass_xshift[NB_PASSES] = {
00119 3, 3, 2, 2, 1, 1, 0
00120 };
00121
00122
00123 static const uint8_t png_pass_mask[NB_PASSES] = {
00124 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
00125 };
00126
00127
00128 static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
00129 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
00130 };
00131 #if 0
00132 static int png_probe(AVProbeData *pd)
00133 {
00134 if (pd->buf_size >= 8 &&
00135 memcmp(pd->buf, pngsig, 8) == 0)
00136 return AVPROBE_SCORE_MAX;
00137 else
00138 return 0;
00139 }
00140 #endif
00141 static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
00142 {
00143 if(items >= UINT_MAX / size)
00144 return NULL;
00145 return av_malloc(items * size);
00146 }
00147
00148 static void png_zfree(void *opaque, void *ptr)
00149 {
00150 av_free(ptr);
00151 }
00152
00153 static int png_get_nb_channels(int color_type)
00154 {
00155 int channels;
00156 channels = 1;
00157 if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) ==
00158 PNG_COLOR_MASK_COLOR)
00159 channels = 3;
00160 if (color_type & PNG_COLOR_MASK_ALPHA)
00161 channels++;
00162 return channels;
00163 }
00164
00165
00166 static int png_pass_row_size(int pass, int bits_per_pixel, int width)
00167 {
00168 int shift, xmin, pass_width;
00169
00170 xmin = png_pass_xmin[pass];
00171 if (width <= xmin)
00172 return 0;
00173 shift = png_pass_xshift[pass];
00174 pass_width = (width - xmin + (1 << shift) - 1) >> shift;
00175 return (pass_width * bits_per_pixel + 7) >> 3;
00176 }
00177
00178
00179
00180
00181 static void png_put_interlaced_row(uint8_t *dst, int width,
00182 int bits_per_pixel, int pass,
00183 int color_type, const uint8_t *src)
00184 {
00185 int x, mask, dsp_mask, j, src_x, b, bpp;
00186 uint8_t *d;
00187 const uint8_t *s;
00188
00189 mask = png_pass_mask[pass];
00190 dsp_mask = png_pass_dsp_mask[pass];
00191 switch(bits_per_pixel) {
00192 case 1:
00193
00194 if (pass == 0)
00195 memset(dst, 0, (width + 7) >> 3);
00196 src_x = 0;
00197 for(x = 0; x < width; x++) {
00198 j = (x & 7);
00199 if ((dsp_mask << j) & 0x80) {
00200 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
00201 dst[x >> 3] |= b << (7 - j);
00202 }
00203 if ((mask << j) & 0x80)
00204 src_x++;
00205 }
00206 break;
00207 default:
00208 bpp = bits_per_pixel >> 3;
00209 d = dst;
00210 s = src;
00211 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00212 for(x = 0; x < width; x++) {
00213 j = x & 7;
00214 if ((dsp_mask << j) & 0x80) {
00215 *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
00216 }
00217 d += bpp;
00218 if ((mask << j) & 0x80)
00219 s += bpp;
00220 }
00221 } else {
00222 for(x = 0; x < width; x++) {
00223 j = x & 7;
00224 if ((dsp_mask << j) & 0x80) {
00225 memcpy(d, s, bpp);
00226 }
00227 d += bpp;
00228 if ((mask << j) & 0x80)
00229 s += bpp;
00230 }
00231 }
00232 break;
00233 }
00234 }
00235
00236 static void png_get_interlaced_row(uint8_t *dst, int row_size,
00237 int bits_per_pixel, int pass,
00238 const uint8_t *src, int width)
00239 {
00240 int x, mask, dst_x, j, b, bpp;
00241 uint8_t *d;
00242 const uint8_t *s;
00243
00244 mask = png_pass_mask[pass];
00245 switch(bits_per_pixel) {
00246 case 1:
00247 memset(dst, 0, row_size);
00248 dst_x = 0;
00249 for(x = 0; x < width; x++) {
00250 j = (x & 7);
00251 if ((mask << j) & 0x80) {
00252 b = (src[x >> 3] >> (7 - j)) & 1;
00253 dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
00254 dst_x++;
00255 }
00256 }
00257 break;
00258 default:
00259 bpp = bits_per_pixel >> 3;
00260 d = dst;
00261 s = src;
00262 for(x = 0; x < width; x++) {
00263 j = x & 7;
00264 if ((mask << j) & 0x80) {
00265 memcpy(d, s, bpp);
00266 d += bpp;
00267 }
00268 s += bpp;
00269 }
00270 break;
00271 }
00272 }
00273
00274
00275
00276 static void png_filter_row(uint8_t *dst, int filter_type,
00277 uint8_t *src, uint8_t *last, int size, int bpp)
00278 {
00279 int i, p;
00280
00281 switch(filter_type) {
00282 case PNG_FILTER_VALUE_NONE:
00283 memcpy(dst, src, size);
00284 break;
00285 case PNG_FILTER_VALUE_SUB:
00286 for(i = 0; i < bpp; i++) {
00287 dst[i] = src[i];
00288 }
00289 for(i = bpp; i < size; i++) {
00290 p = dst[i - bpp];
00291 dst[i] = p + src[i];
00292 }
00293 break;
00294 case PNG_FILTER_VALUE_UP:
00295 for(i = 0; i < size; i++) {
00296 p = last[i];
00297 dst[i] = p + src[i];
00298 }
00299 break;
00300 case PNG_FILTER_VALUE_AVG:
00301 for(i = 0; i < bpp; i++) {
00302 p = (last[i] >> 1);
00303 dst[i] = p + src[i];
00304 }
00305 for(i = bpp; i < size; i++) {
00306 p = ((dst[i - bpp] + last[i]) >> 1);
00307 dst[i] = p + src[i];
00308 }
00309 break;
00310 case PNG_FILTER_VALUE_PAETH:
00311 for(i = 0; i < bpp; i++) {
00312 p = last[i];
00313 dst[i] = p + src[i];
00314 }
00315 for(i = bpp; i < size; i++) {
00316 int a, b, c, pa, pb, pc;
00317
00318 a = dst[i - bpp];
00319 b = last[i];
00320 c = last[i - bpp];
00321
00322 p = b - c;
00323 pc = a - c;
00324
00325 pa = abs(p);
00326 pb = abs(pc);
00327 pc = abs(p + pc);
00328
00329 if (pa <= pb && pa <= pc)
00330 p = a;
00331 else if (pb <= pc)
00332 p = b;
00333 else
00334 p = c;
00335 dst[i] = p + src[i];
00336 }
00337 break;
00338 }
00339 }
00340
00341 static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
00342 {
00343 uint8_t *d;
00344 int j;
00345 unsigned int v;
00346
00347 d = dst;
00348 for(j = 0; j < width; j++) {
00349 v = ((uint32_t *)src)[j];
00350 d[0] = v >> 16;
00351 d[1] = v >> 8;
00352 d[2] = v;
00353 d[3] = v >> 24;
00354 d += 4;
00355 }
00356 }
00357
00358 static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
00359 {
00360 int j;
00361 unsigned int r, g, b, a;
00362
00363 for(j = 0;j < width; j++) {
00364 r = src[0];
00365 g = src[1];
00366 b = src[2];
00367 a = src[3];
00368 *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
00369 dst += 4;
00370 src += 4;
00371 }
00372 }
00373
00374
00375 static void png_handle_row(PNGContext *s)
00376 {
00377 uint8_t *ptr, *last_row;
00378 int got_line;
00379
00380 if (!s->interlace_type) {
00381 ptr = s->image_buf + s->image_linesize * s->y;
00382
00383 if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00384 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
00385 s->last_row, s->row_size, s->bpp);
00386 memcpy(s->last_row, s->tmp_row, s->row_size);
00387 convert_to_rgba32(ptr, s->tmp_row, s->width);
00388 } else {
00389
00390 if (s->y == 0)
00391 last_row = s->last_row;
00392 else
00393 last_row = ptr - s->image_linesize;
00394
00395 png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
00396 last_row, s->row_size, s->bpp);
00397 }
00398 s->y++;
00399 if (s->y == s->height) {
00400 s->state |= PNG_ALLIMAGE;
00401 }
00402 } else {
00403 got_line = 0;
00404 for(;;) {
00405 ptr = s->image_buf + s->image_linesize * s->y;
00406 if ((png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
00407
00408
00409 if (got_line)
00410 break;
00411 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
00412 s->last_row, s->pass_row_size, s->bpp);
00413 memcpy(s->last_row, s->tmp_row, s->pass_row_size);
00414 got_line = 1;
00415 }
00416 if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
00417
00418 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
00419 s->color_type, s->last_row);
00420 }
00421 s->y++;
00422 if (s->y == s->height) {
00423 for(;;) {
00424 if (s->pass == NB_PASSES - 1) {
00425 s->state |= PNG_ALLIMAGE;
00426 goto the_end;
00427 } else {
00428 s->pass++;
00429 s->y = 0;
00430 s->pass_row_size = png_pass_row_size(s->pass,
00431 s->bits_per_pixel,
00432 s->width);
00433 s->crow_size = s->pass_row_size + 1;
00434 if (s->pass_row_size != 0)
00435 break;
00436
00437 }
00438 }
00439 }
00440 }
00441 the_end: ;
00442 }
00443 }
00444
00445 static int png_decode_idat(PNGContext *s, int length)
00446 {
00447 int ret;
00448 s->zstream.avail_in = length;
00449 s->zstream.next_in = s->bytestream;
00450 s->bytestream += length;
00451
00452 if(s->bytestream > s->bytestream_end)
00453 return -1;
00454
00455
00456 while (s->zstream.avail_in > 0) {
00457 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
00458 if (ret != Z_OK && ret != Z_STREAM_END) {
00459 return -1;
00460 }
00461 if (s->zstream.avail_out == 0) {
00462 if (!(s->state & PNG_ALLIMAGE)) {
00463 png_handle_row(s);
00464 }
00465 s->zstream.avail_out = s->crow_size;
00466 s->zstream.next_out = s->crow_buf;
00467 }
00468 }
00469 return 0;
00470 }
00471
00472 static int decode_frame(AVCodecContext *avctx,
00473 void *data, int *data_size,
00474 uint8_t *buf, int buf_size)
00475 {
00476 PNGContext * const s = avctx->priv_data;
00477 AVFrame *picture = data;
00478 AVFrame * const p= (AVFrame*)&s->picture;
00479 uint32_t tag, length;
00480 int ret, crc;
00481
00482 s->bytestream_start=
00483 s->bytestream= buf;
00484 s->bytestream_end= buf + buf_size;
00485
00486
00487 if (memcmp(s->bytestream, pngsig, 8) != 0)
00488 return -1;
00489 s->bytestream+= 8;
00490 s->y=
00491 s->state=0;
00492
00493
00494 s->zstream.zalloc = png_zalloc;
00495 s->zstream.zfree = png_zfree;
00496 s->zstream.opaque = NULL;
00497 ret = inflateInit(&s->zstream);
00498 if (ret != Z_OK)
00499 return -1;
00500 for(;;) {
00501 int tag32;
00502 if (s->bytestream >= s->bytestream_end)
00503 goto fail;
00504 length = get32(&s->bytestream);
00505 if (length > 0x7fffffff)
00506 goto fail;
00507 tag32 = get32(&s->bytestream);
00508 tag = bswap_32(tag32);
00509 #ifdef DEBUG
00510 printf("png: tag=%c%c%c%c length=%u\n",
00511 (tag & 0xff),
00512 ((tag >> 8) & 0xff),
00513 ((tag >> 16) & 0xff),
00514 ((tag >> 24) & 0xff), length);
00515 #endif
00516 switch(tag) {
00517 case MKTAG('I', 'H', 'D', 'R'):
00518 if (length != 13)
00519 goto fail;
00520 s->width = get32(&s->bytestream);
00521 s->height = get32(&s->bytestream);
00522 if(avcodec_check_dimensions(avctx, s->width, s->height)){
00523 s->width= s->height= 0;
00524 goto fail;
00525 }
00526 s->bit_depth = *s->bytestream++;
00527 s->color_type = *s->bytestream++;
00528 s->compression_type = *s->bytestream++;
00529 s->filter_type = *s->bytestream++;
00530 s->interlace_type = *s->bytestream++;
00531 crc = get32(&s->bytestream);
00532 s->state |= PNG_IHDR;
00533 #ifdef DEBUG
00534 printf("width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n",
00535 s->width, s->height, s->bit_depth, s->color_type,
00536 s->compression_type, s->filter_type, s->interlace_type);
00537 #endif
00538 break;
00539 case MKTAG('I', 'D', 'A', 'T'):
00540 if (!(s->state & PNG_IHDR))
00541 goto fail;
00542 if (!(s->state & PNG_IDAT)) {
00543
00544 avctx->width = s->width;
00545 avctx->height = s->height;
00546
00547 s->channels = png_get_nb_channels(s->color_type);
00548 s->bits_per_pixel = s->bit_depth * s->channels;
00549 s->bpp = (s->bits_per_pixel + 7) >> 3;
00550 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
00551
00552 if (s->bit_depth == 8 &&
00553 s->color_type == PNG_COLOR_TYPE_RGB) {
00554 avctx->pix_fmt = PIX_FMT_RGB24;
00555 } else if (s->bit_depth == 8 &&
00556 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00557 avctx->pix_fmt = PIX_FMT_RGBA32;
00558 } else if (s->bit_depth == 8 &&
00559 s->color_type == PNG_COLOR_TYPE_GRAY) {
00560 avctx->pix_fmt = PIX_FMT_GRAY8;
00561 } else if (s->bit_depth == 1 &&
00562 s->color_type == PNG_COLOR_TYPE_GRAY) {
00563 avctx->pix_fmt = PIX_FMT_MONOBLACK;
00564 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
00565 avctx->pix_fmt = PIX_FMT_PAL8;
00566 } else {
00567 goto fail;
00568 }
00569 if(p->data[0])
00570 avctx->release_buffer(avctx, p);
00571
00572 p->reference= 0;
00573 if(avctx->get_buffer(avctx, p) < 0){
00574 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00575 goto fail;
00576 }
00577 p->pict_type= FF_I_TYPE;
00578 p->key_frame= 1;
00579 p->interlaced_frame = !!s->interlace_type;
00580
00581
00582 if (!s->interlace_type) {
00583 s->crow_size = s->row_size + 1;
00584 } else {
00585 s->pass = 0;
00586 s->pass_row_size = png_pass_row_size(s->pass,
00587 s->bits_per_pixel,
00588 s->width);
00589 s->crow_size = s->pass_row_size + 1;
00590 }
00591 #ifdef DEBUG
00592 printf("row_size=%d crow_size =%d\n",
00593 s->row_size, s->crow_size);
00594 #endif
00595 s->image_buf = p->data[0];
00596 s->image_linesize = p->linesize[0];
00597
00598 if (s->color_type == PNG_COLOR_TYPE_PALETTE)
00599 memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
00600
00601 s->last_row = av_mallocz(s->row_size);
00602 if (!s->last_row)
00603 goto fail;
00604 if (s->interlace_type ||
00605 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00606 s->tmp_row = av_malloc(s->row_size);
00607 if (!s->tmp_row)
00608 goto fail;
00609 }
00610
00611 s->crow_buf = av_malloc(s->row_size + 1);
00612 if (!s->crow_buf)
00613 goto fail;
00614 s->zstream.avail_out = s->crow_size;
00615 s->zstream.next_out = s->crow_buf;
00616 }
00617 s->state |= PNG_IDAT;
00618 if (png_decode_idat(s, length) < 0)
00619 goto fail;
00620
00621 crc = get32(&s->bytestream);
00622 break;
00623 case MKTAG('P', 'L', 'T', 'E'):
00624 {
00625 int n, i, r, g, b;
00626
00627 if ((length % 3) != 0 || length > 256 * 3)
00628 goto skip_tag;
00629
00630 n = length / 3;
00631 for(i=0;i<n;i++) {
00632 r = *s->bytestream++;
00633 g = *s->bytestream++;
00634 b = *s->bytestream++;
00635 s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
00636 }
00637 for(;i<256;i++) {
00638 s->palette[i] = (0xff << 24);
00639 }
00640 s->state |= PNG_PLTE;
00641 crc = get32(&s->bytestream);
00642 }
00643 break;
00644 case MKTAG('t', 'R', 'N', 'S'):
00645 {
00646 int v, i;
00647
00648
00649 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
00650 length > 256 ||
00651 !(s->state & PNG_PLTE))
00652 goto skip_tag;
00653 for(i=0;i<length;i++) {
00654 v = *s->bytestream++;
00655 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
00656 }
00657 crc = get32(&s->bytestream);
00658 }
00659 break;
00660 case MKTAG('I', 'E', 'N', 'D'):
00661 if (!(s->state & PNG_ALLIMAGE))
00662 goto fail;
00663 crc = get32(&s->bytestream);
00664 goto exit_loop;
00665 default:
00666
00667 skip_tag:
00668 s->bytestream += length + 4;
00669 break;
00670 }
00671 }
00672 exit_loop:
00673 *picture= *(AVFrame*)&s->picture;
00674 *data_size = sizeof(AVPicture);
00675
00676 ret = s->bytestream - s->bytestream_start;
00677 the_end:
00678 inflateEnd(&s->zstream);
00679 av_freep(&s->crow_buf);
00680 av_freep(&s->last_row);
00681 av_freep(&s->tmp_row);
00682 return ret;
00683 fail:
00684 ret = -1;
00685 goto the_end;
00686 }
00687
00688 static void png_write_chunk(uint8_t **f, uint32_t tag,
00689 const uint8_t *buf, int length)
00690 {
00691 uint32_t crc;
00692 uint8_t tagbuf[4];
00693
00694 put32(f, length);
00695 crc = crc32(0, Z_NULL, 0);
00696 tagbuf[0] = tag;
00697 tagbuf[1] = tag >> 8;
00698 tagbuf[2] = tag >> 16;
00699 tagbuf[3] = tag >> 24;
00700 crc = crc32(crc, tagbuf, 4);
00701 put32(f, bswap_32(tag));
00702 if (length > 0) {
00703 crc = crc32(crc, buf, length);
00704 memcpy(*f, buf, length);
00705 *f += length;
00706 }
00707 put32(f, crc);
00708 }
00709
00710
00711 static void to_be32(uint8_t *p, uint32_t v)
00712 {
00713 p[0] = v >> 24;
00714 p[1] = v >> 16;
00715 p[2] = v >> 8;
00716 p[3] = v;
00717 }
00718
00719
00720 static int png_write_row(PNGContext *s, const uint8_t *data, int size)
00721 {
00722 int ret;
00723
00724 s->zstream.avail_in = size;
00725 s->zstream.next_in = (uint8_t *)data;
00726 while (s->zstream.avail_in > 0) {
00727 ret = deflate(&s->zstream, Z_NO_FLUSH);
00728 if (ret != Z_OK)
00729 return -1;
00730 if (s->zstream.avail_out == 0) {
00731 if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
00732 png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE);
00733 s->zstream.avail_out = IOBUF_SIZE;
00734 s->zstream.next_out = s->buf;
00735 }
00736 }
00737 return 0;
00738 }
00739
00740 static int common_init(AVCodecContext *avctx){
00741 PNGContext *s = avctx->priv_data;
00742
00743 avcodec_get_frame_defaults((AVFrame*)&s->picture);
00744 avctx->coded_frame= (AVFrame*)&s->picture;
00745
00746
00747 return 0;
00748 }
00749
00750 static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
00751 PNGContext *s = avctx->priv_data;
00752 AVFrame *pict = data;
00753 AVFrame * const p= (AVFrame*)&s->picture;
00754 int bit_depth, color_type, y, len, row_size, ret, is_progressive;
00755 int bits_per_pixel, pass_row_size;
00756 uint8_t *ptr;
00757 uint8_t *crow_buf = NULL;
00758 uint8_t *tmp_buf = NULL;
00759
00760 *p = *pict;
00761 p->pict_type= FF_I_TYPE;
00762 p->key_frame= 1;
00763
00764 s->bytestream_start=
00765 s->bytestream= buf;
00766 s->bytestream_end= buf+buf_size;
00767
00768 is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
00769 switch(avctx->pix_fmt) {
00770 case PIX_FMT_RGBA32:
00771 bit_depth = 8;
00772 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
00773 break;
00774 case PIX_FMT_RGB24:
00775 bit_depth = 8;
00776 color_type = PNG_COLOR_TYPE_RGB;
00777 break;
00778 case PIX_FMT_GRAY8:
00779 bit_depth = 8;
00780 color_type = PNG_COLOR_TYPE_GRAY;
00781 break;
00782 case PIX_FMT_MONOBLACK:
00783 bit_depth = 1;
00784 color_type = PNG_COLOR_TYPE_GRAY;
00785 break;
00786 case PIX_FMT_PAL8:
00787 bit_depth = 8;
00788 color_type = PNG_COLOR_TYPE_PALETTE;
00789 break;
00790 default:
00791 return -1;
00792 }
00793 bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
00794 row_size = (avctx->width * bits_per_pixel + 7) >> 3;
00795
00796 s->zstream.zalloc = png_zalloc;
00797 s->zstream.zfree = png_zfree;
00798 s->zstream.opaque = NULL;
00799 ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
00800 Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
00801 if (ret != Z_OK)
00802 return -1;
00803 crow_buf = av_malloc(row_size + 1);
00804 if (!crow_buf)
00805 goto fail;
00806 if (is_progressive) {
00807 tmp_buf = av_malloc(row_size + 1);
00808 if (!tmp_buf)
00809 goto fail;
00810 }
00811
00812
00813 memcpy(s->bytestream, pngsig, 8);
00814 s->bytestream += 8;
00815
00816 to_be32(s->buf, avctx->width);
00817 to_be32(s->buf + 4, avctx->height);
00818 s->buf[8] = bit_depth;
00819 s->buf[9] = color_type;
00820 s->buf[10] = 0;
00821 s->buf[11] = 0;
00822 s->buf[12] = is_progressive;
00823
00824 png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
00825
00826
00827 if (color_type == PNG_COLOR_TYPE_PALETTE) {
00828 int has_alpha, alpha, i;
00829 unsigned int v;
00830 uint32_t *palette;
00831 uint8_t *alpha_ptr;
00832
00833 palette = (uint32_t *)p->data[1];
00834 ptr = s->buf;
00835 alpha_ptr = s->buf + 256 * 3;
00836 has_alpha = 0;
00837 for(i = 0; i < 256; i++) {
00838 v = palette[i];
00839 alpha = v >> 24;
00840 if (alpha != 0xff)
00841 has_alpha = 1;
00842 *alpha_ptr++ = alpha;
00843 ptr[0] = v >> 16;
00844 ptr[1] = v >> 8;
00845 ptr[2] = v;
00846 ptr += 3;
00847 }
00848 png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
00849 if (has_alpha) {
00850 png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
00851 }
00852 }
00853
00854
00855 s->zstream.avail_out = IOBUF_SIZE;
00856 s->zstream.next_out = s->buf;
00857 if (is_progressive) {
00858 uint8_t *ptr1;
00859 int pass;
00860
00861 for(pass = 0; pass < NB_PASSES; pass++) {
00862
00863
00864 pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
00865 if (pass_row_size > 0) {
00866 for(y = 0; y < avctx->height; y++) {
00867 if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
00868 ptr = p->data[0] + y * p->linesize[0];
00869 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
00870 convert_from_rgba32(tmp_buf, ptr, avctx->width);
00871 ptr1 = tmp_buf;
00872 } else {
00873 ptr1 = ptr;
00874 }
00875 png_get_interlaced_row(crow_buf + 1, pass_row_size,
00876 bits_per_pixel, pass,
00877 ptr1, avctx->width);
00878 crow_buf[0] = PNG_FILTER_VALUE_NONE;
00879 png_write_row(s, crow_buf, pass_row_size + 1);
00880 }
00881 }
00882 }
00883 }
00884 } else {
00885 for(y = 0; y < avctx->height; y++) {
00886 ptr = p->data[0] + y * p->linesize[0];
00887 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00888 convert_from_rgba32(crow_buf + 1, ptr, avctx->width);
00889 else
00890 memcpy(crow_buf + 1, ptr, row_size);
00891 crow_buf[0] = PNG_FILTER_VALUE_NONE;
00892 png_write_row(s, crow_buf, row_size + 1);
00893 }
00894 }
00895
00896 for(;;) {
00897 ret = deflate(&s->zstream, Z_FINISH);
00898 if (ret == Z_OK || ret == Z_STREAM_END) {
00899 len = IOBUF_SIZE - s->zstream.avail_out;
00900 if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
00901 png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len);
00902 }
00903 s->zstream.avail_out = IOBUF_SIZE;
00904 s->zstream.next_out = s->buf;
00905 if (ret == Z_STREAM_END)
00906 break;
00907 } else {
00908 goto fail;
00909 }
00910 }
00911 png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
00912
00913 ret = s->bytestream - s->bytestream_start;
00914 the_end:
00915 av_free(crow_buf);
00916 av_free(tmp_buf);
00917 deflateEnd(&s->zstream);
00918 return ret;
00919 fail:
00920 ret = -1;
00921 goto the_end;
00922 }
00923
00924 AVCodec png_decoder = {
00925 "png",
00926 CODEC_TYPE_VIDEO,
00927 CODEC_ID_PNG,
00928 sizeof(PNGContext),
00929 common_init,
00930 NULL,
00931 NULL,
00932 decode_frame,
00933 0 ,
00934 NULL
00935 };
00936
00937 #ifdef CONFIG_PNG_ENCODER
00938 AVCodec png_encoder = {
00939 "png",
00940 CODEC_TYPE_VIDEO,
00941 CODEC_ID_PNG,
00942 sizeof(PNGContext),
00943 common_init,
00944 encode_frame,
00945 NULL,
00946 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
00947 };
00948 #endif // CONFIG_PNG_ENCODER
00949 #endif