[FFmpeg-devel] Fwd: GSoC: APNG
Michael Niedermayer
michaelni at gmx.at
Sat Mar 28 14:08:25 CET 2015
On Sat, Mar 28, 2015 at 09:12:10AM +0000, Donny Yang wrote:
> Sorry for the delay. I was a bit busy this week.
>
> On 25 March 2015 at 09:59, Michael Niedermayer <michaelni at gmx.at> wrote:
>
> > is there any advantage for multiple small IDATs ?
> > if not i suggest to make the IDAT change to png as well in a seperate
> > patch so that a single frame APNG and PNG produce identical data
> > and especially so that the introduction of APNG does not change PNG
> > files
>
>
> Having multiple small IDAT sections is simply to make the encoder easier to
> write.
> For now, I've left it how it is, but now the APNG encoder and muxer
> produces identical output to PNG before.
>
> I've also changed my edits to libavcodec a fair bit as well after thinking
> more carefully about the next steps in implementing a full APNG encoder.
> The APNG encoder currently just outputs normal PNG headers and IDAT chunks,
> while the muxer adds the necessary headers for APNG and converts the IDAT
> chunks to fdAT where needed.
>
> On 28 March 2015 at 18:24, Paul B Mahol <onemda at gmail.com> wrote:
>
> > Dana 28. 3. 2015. 04:56 osoba "Donny Yang" <work at kota.moe> napisala je:
> > > On 28 March 2015 at 04:36, Paul B Mahol <onemda at gmail.com> wrote:
> > >>
> > >> The style of code inside patch do not match other files in codebase,
> > >> look at style of other files inside codebase.
> > >
> > > I assume you're referring to the opening brace style on functions?
> > >
> > Yes.
> >
> Okay, I've fixed them.
>
> Also, I just realised I'm not supposed to be sending more than one patch
> per email.
> I've put them again for this email, but what should I do instead next time?
git send-email should send one patch per mail
>
> configure | 1
> libavcodec/Makefile | 1
> libavcodec/allcodecs.c | 2
> libavcodec/pngenc.c | 326 +++++++++++++++++++++++++++++--------------------
> libavcodec/version.h | 2
> 5 files changed, 203 insertions(+), 129 deletions(-)
> 2724818cf358ca284e59add36b1a28e410bc28da 0001-apng-Make-PNG-encoder-only-write-headers-once-in-APN.patch
> From cdc40aa212d3c8a34b2895213f6bc63efe881df5 Mon Sep 17 00:00:00 2001
> From: Donny Yang <work at kota.moe>
> Date: Sat, 28 Mar 2015 19:09:11 +1100
> Subject: [PATCH 1/2] apng: Make PNG encoder only write headers once in APNG
> mode
>
> Signed-off-by: Donny Yang <work at kota.moe>
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 2 +-
> libavcodec/pngenc.c | 326 ++++++++++++++++++++++++++++++-------------------
> libavcodec/version.h | 2 +-
> 5 files changed, 203 insertions(+), 129 deletions(-)
>
> diff --git a/configure b/configure
> index 017a9d2..8a30549 100755
> --- a/configure
> +++ b/configure
> @@ -2096,6 +2096,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 b2d9c71..9a145d3 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 10aad4c..2e5d558 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -107,7 +107,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 9bdefc4..6959435 100644
> --- a/libavcodec/pngenc.c
> +++ b/libavcodec/pngenc.c
> @@ -48,6 +48,11 @@ typedef struct PNGEncContext {
> uint8_t buf[IOBUF_SIZE];
> int dpi; ///< Physical pixel density, in dots per inch, if set
> int dpm; ///< Physical pixel density, in dots per meter, if set
> +
> + int is_progressive;
> + int bit_depth;
> + int color_type;
> + int bits_per_pixel;
> } PNGEncContext;
>
> static void png_get_interlaced_row(uint8_t *dst, int row_size,
> @@ -286,107 +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 bit_depth, color_type, y, len, row_size, ret, is_progressive;
> - int bits_per_pixel, pass_row_size, enc_row_size;
> - int64_t max_packet_size;
> - int compression_level;
> - uint8_t *ptr, *top, *crow_buf, *crow;
> - uint8_t *crow_base = NULL;
> - uint8_t *progressive_buf = NULL;
> - uint8_t *top_buf = NULL;
> -
> - is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
> - switch (avctx->pix_fmt) {
> - case AV_PIX_FMT_RGBA64BE:
> - bit_depth = 16;
> - color_type = PNG_COLOR_TYPE_RGB_ALPHA;
> - break;
> - case AV_PIX_FMT_RGB48BE:
> - bit_depth = 16;
> - color_type = PNG_COLOR_TYPE_RGB;
> - break;
> - case AV_PIX_FMT_RGBA:
> - bit_depth = 8;
> - color_type = PNG_COLOR_TYPE_RGB_ALPHA;
> - break;
> - case AV_PIX_FMT_RGB24:
> - bit_depth = 8;
> - color_type = PNG_COLOR_TYPE_RGB;
> - break;
> - case AV_PIX_FMT_GRAY16BE:
> - bit_depth = 16;
> - color_type = PNG_COLOR_TYPE_GRAY;
> - break;
> - case AV_PIX_FMT_GRAY8:
> - bit_depth = 8;
> - color_type = PNG_COLOR_TYPE_GRAY;
> - break;
> - case AV_PIX_FMT_GRAY8A:
> - bit_depth = 8;
> - color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
> - break;
> - case AV_PIX_FMT_YA16BE:
> - bit_depth = 16;
> - color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
> - break;
> - case AV_PIX_FMT_MONOBLACK:
> - bit_depth = 1;
> - color_type = PNG_COLOR_TYPE_GRAY;
> - break;
> - case AV_PIX_FMT_PAL8:
> - bit_depth = 8;
> - color_type = PNG_COLOR_TYPE_PALETTE;
> - break;
> - default:
> - return -1;
> - }
> - bits_per_pixel = ff_png_get_nb_channels(color_type) * bit_depth;
> - row_size = (avctx->width * bits_per_pixel + 7) >> 3;
> -
> - s->zstream.zalloc = ff_png_zalloc;
> - s->zstream.zfree = ff_png_zfree;
> - s->zstream.opaque = NULL;
> - compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT
> - ? Z_DEFAULT_COMPRESSION
> - : av_clip(avctx->compression_level, 0, 9);
> - ret = deflateInit2(&s->zstream, compression_level,
> - Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
> - if (ret != Z_OK)
> - return -1;
> -
> - enc_row_size = deflateBound(&s->zstream, row_size);
> - max_packet_size = avctx->height * (int64_t)(enc_row_size +
> - ((enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) * 12)
> - + FF_MIN_BUFFER_SIZE;
> - if (max_packet_size > INT_MAX)
> - return AVERROR(ENOMEM);
> - if ((ret = ff_alloc_packet2(avctx, pkt, max_packet_size)) < 0)
> - 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)
> - goto fail;
> - // pixel data should be aligned, but there's a control byte before it
> - crow_buf = crow_base + 15;
> - if (is_progressive) {
> - progressive_buf = av_malloc(row_size + 1);
> - if (!progressive_buf)
> - goto fail;
> - }
> - if (is_progressive) {
> - top_buf = av_malloc(row_size + 1);
> - if (!top_buf)
> - goto fail;
> - }
> + PNGEncContext *s = avctx->priv_data;
moving code around should be in a seperate patch from changing code
in ways other than needed for the move
>
> /* write png header */
> AV_WB64(s->bytestream, PNGSIG);
> @@ -394,14 +301,14 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
>
> AV_WB32(s->buf, avctx->width);
> AV_WB32(s->buf + 4, avctx->height);
> - s->buf[8] = bit_depth;
> - s->buf[9] = color_type;
> + s->buf[8] = s->bit_depth;
> + s->buf[9] = s->color_type;
> s->buf[10] = 0; /* compression type */
> s->buf[11] = 0; /* filter type */
> - s->buf[12] = is_progressive; /* interlace type */
> -
> + s->buf[12] = s->is_progressive; /* interlace type */
> png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
moving variables to the context should also be in a seperate patch
[...]
> the_end:
> - av_free(crow_base);
> - av_free(progressive_buf);
> - av_free(top_buf);
> - deflateEnd(&s->zstream);
> + av_freep(&crow_base);
> + av_freep(&progressive_buf);
> + av_freep(&top_buf);
> + deflateReset(&s->zstream);
> return ret;
changing av_free to av_freep() should be a seperate patch as well
> -fail:
> - ret = -1;
> - goto the_end;
> +}
> +
> +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;
> +
> + if (avctx->codec_id == AV_CODEC_ID_PNG || pict->pts == 0) {
pts == 0 is not a reliable way to detect the first picture
this patchset also breaks PAL8
./ffmpeg -i lena.pnm -pix_fmt pal8 test.png
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The worst form of inequality is to try to make unequal things equal.
-- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150328/55205340/attachment.asc>
More information about the ffmpeg-devel
mailing list