Signed-off-by: Donny Yang <w...@kota.moe> --- libavcodec/pngenc.c | 146 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 60 deletions(-)
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 410a829..0264575 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -291,58 +291,9 @@ static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) return 1; } -static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *pict, int *got_packet) +static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) { - PNGEncContext *s = avctx->priv_data; - const AVFrame *const p = pict; - int y, len, row_size, ret; - int pass_row_size, enc_row_size; - int64_t max_packet_size; - uint8_t *ptr, *top, *crow_buf, *crow; - uint8_t *crow_base = NULL; - uint8_t *progressive_buf = NULL; - uint8_t *top_buf = NULL; - - row_size = (avctx->width * s->bits_per_pixel + 7) >> 3; - - enc_row_size = deflateBound(&s->zstream, row_size); - max_packet_size = - 8 + // PNGSIG - 13 + 12 + // IHDR - 9 + 12 + // pHYs - 1 + 12 + // sRGB - 32 + 12 + // cHRM - 4 + 12 + // gAMA - 256 * 3 + 12 + // PLTE - 256 + 12 + // tRNS - avctx->height * ( - enc_row_size + - 12 * (((int64_t)enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // 12 * ceil(enc_row_size / IOBUF_SIZE) - ); - ret = ff_alloc_packet2(avctx, pkt, max_packet_size < FF_MIN_BUFFER_SIZE ? FF_MIN_BUFFER_SIZE : max_packet_size); - if (ret) - return ret; - - s->bytestream_start = - s->bytestream = pkt->data; - s->bytestream_end = pkt->data + pkt->size; - - crow_base = av_malloc((row_size + 32) << (s->filter_type == PNG_FILTER_VALUE_MIXED)); - if (!crow_base) { - ret = AVERROR(ENOMEM); - goto the_end; - } - // pixel data should be aligned, but there's a control byte before it - crow_buf = crow_base + 15; - if (s->is_progressive) { - progressive_buf = av_malloc(row_size + 1); - top_buf = av_malloc(row_size + 1); - if (!progressive_buf || !top_buf) { - ret = AVERROR(ENOMEM); - goto the_end; - } - } + PNGEncContext *s = avctx->priv_data; /* write png header */ AV_WB64(s->bytestream, PNGSIG); @@ -386,9 +337,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int has_alpha, alpha, i; unsigned int v; uint32_t *palette; - uint8_t *alpha_ptr; + uint8_t *ptr, *alpha_ptr; - palette = (uint32_t *)p->data[1]; + palette = (uint32_t *)pict->data[1]; ptr = s->buf; alpha_ptr = s->buf + 256 * 3; has_alpha = 0; @@ -408,7 +359,39 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } } - /* now put each row */ + return 0; +} + +static int encode_frame(AVCodecContext *avctx, const AVFrame *pict) +{ + PNGEncContext *s = avctx->priv_data; + const AVFrame *const p = pict; + int y, len, ret; + int row_size, pass_row_size; + uint8_t *ptr, *top, *crow_buf, *crow; + uint8_t *crow_base = NULL; + uint8_t *progressive_buf = NULL; + uint8_t *top_buf = NULL; + + row_size = (avctx->width * s->bits_per_pixel + 7) >> 3; + + crow_base = av_malloc((row_size + 32) << (s->filter_type == PNG_FILTER_VALUE_MIXED)); + if (!crow_base) { + ret = AVERROR(ENOMEM); + goto the_end; + } + // pixel data should be aligned, but there's a control byte before it + crow_buf = crow_base + 15; + if (s->is_progressive) { + progressive_buf = av_malloc(row_size + 1); + top_buf = av_malloc(row_size + 1); + if (!progressive_buf || !top_buf) { + ret = AVERROR(ENOMEM); + goto the_end; + } + } + + /* put each row */ s->zstream.avail_out = IOBUF_SIZE; s->zstream.next_out = s->buf; if (s->is_progressive) { @@ -461,12 +444,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, goto the_end; } } - png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0); - pkt->size = s->bytestream - s->bytestream_start; - pkt->flags |= AV_PKT_FLAG_KEY; - *got_packet = 1; - ret = 0; + ret = 0; the_end: av_freep(&crow_base); @@ -476,6 +455,53 @@ the_end: return ret; } +static int encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + PNGEncContext *s = avctx->priv_data; + int ret; + int enc_row_size; + size_t max_packet_size; + + enc_row_size = deflateBound(&s->zstream, (avctx->width * s->bits_per_pixel + 7) >> 3); + max_packet_size = + 8 + // PNGSIG + 13 + 12 + // IHDR + 9 + 12 + // pHYs + 1 + 12 + // sRGB + 32 + 12 + // cHRM + 4 + 12 + // gAMA + 256 * 3 + 12 + // PLTE + 256 + 12 + // tRNS + avctx->height * ( + enc_row_size + + 12 * ((enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // 12 * ceil(enc_row_size / IOBUF_SIZE) + ); + + ret = ff_alloc_packet2(avctx, pkt, max_packet_size < FF_MIN_BUFFER_SIZE ? FF_MIN_BUFFER_SIZE : max_packet_size); + if (ret) + return ret; + s->bytestream_start = + s->bytestream = pkt->data; + s->bytestream_end = pkt->data + pkt->size; + + ret = encode_headers(avctx, pict); + if (ret) + return ret; + + ret = encode_frame(avctx, pict); + if (ret) + return ret; + + png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0); + + pkt->size = s->bytestream - s->bytestream_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + static av_cold int png_enc_init(AVCodecContext *avctx) { PNGEncContext *s = avctx->priv_data; @@ -611,7 +637,7 @@ AVCodec ff_png_encoder = { .priv_data_size = sizeof(PNGEncContext), .init = png_enc_init, .close = png_enc_close, - .encode2 = encode_frame, + .encode2 = encode, .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, -- 2.3.4 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel