Signed-off-by: Donny Yang <w...@kota.moe> --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 +- libavcodec/pngenc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/configure b/configure index e1849a2..eb37aa5 100755 --- a/configure +++ b/configure @@ -2098,6 +2098,7 @@ amv_decoder_select="sp5x_decoder exif" amv_encoder_select="aandcttables mpegvideoenc" ape_decoder_select="bswapdsp llauddsp" apng_decoder_select="zlib" +apng_encoder_select="huffyuvencdsp zlib" asv1_decoder_select="blockdsp bswapdsp idctdsp" asv1_encoder_select="bswapdsp fdctdsp pixblockdsp" asv2_decoder_select="blockdsp bswapdsp idctdsp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 91a40ad..c1b7390 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -144,6 +144,7 @@ OBJS-$(CONFIG_ANM_DECODER) += anm.o OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o OBJS-$(CONFIG_APE_DECODER) += apedec.o OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o +OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o ass_split.o OBJS-$(CONFIG_SSA_ENCODER) += assenc.o ass.o OBJS-$(CONFIG_ASS_DECODER) += assdec.o ass.o ass_split.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 89acac1..ef3558a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -108,7 +108,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (AMV, amv); REGISTER_DECODER(ANM, anm); REGISTER_DECODER(ANSI, ansi); - REGISTER_DECODER(APNG, apng); + REGISTER_ENCDEC (APNG, apng); REGISTER_ENCDEC (ASV1, asv1); REGISTER_ENCDEC (ASV2, asv2); REGISTER_DECODER(AURA, aura); diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 0264575..116ebc5 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -53,6 +53,8 @@ typedef struct PNGEncContext { int bit_depth; int color_type; int bits_per_pixel; + + uint32_t palette_checksum; // Used to ensure a single unique palette in APNG mode } PNGEncContext; static void png_get_interlaced_row(uint8_t *dst, int row_size, @@ -463,6 +465,18 @@ static int encode(AVCodecContext *avctx, AVPacket *pkt, int enc_row_size; size_t max_packet_size; + if (avctx->codec_id == AV_CODEC_ID_APNG && s->color_type == PNG_COLOR_TYPE_PALETTE) { + uint32_t checksum = crc32(crc32(0, Z_NULL, 0), pict->data[1], 256 * sizeof(uint32_t)); + + if (avctx->frame_number == 0) { + s->palette_checksum = checksum; + } else if (checksum != s->palette_checksum) { + av_log(avctx, AV_LOG_ERROR, + "Input contains more than one unique palette. APNG does not support multiple palettes.\n"); + return -1; + } + } + enc_row_size = deflateBound(&s->zstream, (avctx->width * s->bits_per_pixel + 7) >> 3); max_packet_size = 8 + // PNGSIG @@ -485,15 +499,19 @@ static int encode(AVCodecContext *avctx, AVPacket *pkt, s->bytestream = pkt->data; s->bytestream_end = pkt->data + pkt->size; - ret = encode_headers(avctx, pict); - if (ret) - return ret; + if (avctx->codec_id == AV_CODEC_ID_PNG || avctx->frame_number == 0) { + 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); + if (avctx->codec_id == AV_CODEC_ID_PNG) { + 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; @@ -629,6 +647,13 @@ static const AVClass pngenc_class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVClass apngenc_class = { + .class_name = "APNG encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_png_encoder = { .name = "png", .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), @@ -649,3 +674,23 @@ AVCodec ff_png_encoder = { }, .priv_class = &pngenc_class, }; + +AVCodec ff_apng_encoder = { + .name = "apng", + .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_APNG, + .priv_data_size = sizeof(PNGEncContext), + .init = png_enc_init, + .close = png_enc_close, + .encode2 = encode, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, + AV_PIX_FMT_PAL8, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, + AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE, + AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE + }, + .priv_class = &apngenc_class, +}; -- 2.3.4 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel