[FFmpeg-cvslog] avcodec/pngdec: Don't open and close z_streams unnecessarily

Andreas Rheinhardt git at videolan.org
Sat Mar 19 02:30:47 EET 2022


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Tue Mar 15 15:05:53 2022 +0100| [74c930e1b8f7dfc308784e1c3410ef825bec56cf] | committer: Andreas Rheinhardt

avcodec/pngdec: Don't open and close z_streams unnecessarily

Instead reuse and reset a single z_stream.
Also use FFZStream in decode_zbuf(), because it has nicer error
messages.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=74c930e1b8f7dfc308784e1c3410ef825bec56cf
---

 configure           |   4 +-
 libavcodec/pngdec.c | 108 ++++++++++++++++++++++------------------------------
 2 files changed, 48 insertions(+), 64 deletions(-)

diff --git a/configure b/configure
index 5523b93dd3..f26e99ba71 100755
--- a/configure
+++ b/configure
@@ -2758,7 +2758,7 @@ amrwb_decoder_select="lsp"
 amv_decoder_select="sp5x_decoder exif"
 amv_encoder_select="jpegtables mpegvideoenc"
 ape_decoder_select="bswapdsp llauddsp"
-apng_decoder_deps="zlib"
+apng_decoder_select="inflate_wrapper"
 apng_encoder_deps="zlib"
 apng_encoder_select="llvidencdsp"
 aptx_decoder_select="audio_frame_queue"
@@ -2903,7 +2903,7 @@ on2avc_decoder_select="mdct"
 opus_decoder_deps="swresample"
 opus_decoder_select="mdct15"
 opus_encoder_select="audio_frame_queue mdct15"
-png_decoder_deps="zlib"
+png_decoder_select="inflate_wrapper"
 png_encoder_deps="zlib"
 png_encoder_select="llvidencdsp"
 prores_decoder_select="blockdsp idctdsp"
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index bd6feeadef..5843518ae0 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -39,6 +39,7 @@
 #include "pngdsp.h"
 #include "thread.h"
 #include "threadframe.h"
+#include "zlib_wrapper.h"
 
 #include <zlib.h>
 
@@ -107,7 +108,7 @@ typedef struct PNGDecContext {
     int row_size; /* decompressed row size */
     int pass_row_size; /* decompress row size of the current pass */
     int y;
-    z_stream zstream;
+    FFZStream zstream;
 } PNGDecContext;
 
 /* Mask to determine which pixels are valid in a pass */
@@ -429,27 +430,28 @@ the_end:;
 static int png_decode_idat(PNGDecContext *s, GetByteContext *gb,
                            uint8_t *dst, ptrdiff_t dst_stride)
 {
+    z_stream *const zstream = &s->zstream.zstream;
     int ret;
-    s->zstream.avail_in = bytestream2_get_bytes_left(gb);
-    s->zstream.next_in  = gb->buffer;
+    zstream->avail_in = bytestream2_get_bytes_left(gb);
+    zstream->next_in  = gb->buffer;
 
     /* decode one line if possible */
-    while (s->zstream.avail_in > 0) {
-        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
+    while (zstream->avail_in > 0) {
+        ret = inflate(zstream, Z_PARTIAL_FLUSH);
         if (ret != Z_OK && ret != Z_STREAM_END) {
             av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret);
             return AVERROR_EXTERNAL;
         }
-        if (s->zstream.avail_out == 0) {
+        if (zstream->avail_out == 0) {
             if (!(s->pic_state & PNG_ALLIMAGE)) {
                 png_handle_row(s, dst, dst_stride);
             }
-            s->zstream.avail_out = s->crow_size;
-            s->zstream.next_out  = s->crow_buf;
+            zstream->avail_out = s->crow_size;
+            zstream->next_out  = s->crow_buf;
         }
-        if (ret == Z_STREAM_END && s->zstream.avail_in > 0) {
+        if (ret == Z_STREAM_END && zstream->avail_in > 0) {
             av_log(s->avctx, AV_LOG_WARNING,
-                   "%d undecompressed bytes left in buffer\n", s->zstream.avail_in);
+                   "%d undecompressed bytes left in buffer\n", zstream->avail_in);
             return 0;
         }
     }
@@ -457,45 +459,43 @@ static int png_decode_idat(PNGDecContext *s, GetByteContext *gb,
 }
 
 static int decode_zbuf(AVBPrint *bp, const uint8_t *data,
-                       const uint8_t *data_end)
+                       const uint8_t *data_end, void *logctx)
 {
-    z_stream zstream;
+    FFZStream z;
+    z_stream *const zstream = &z.zstream;
     unsigned char *buf;
     unsigned buf_size;
-    int ret;
+    int ret = ff_inflate_init(&z, logctx);
+    if (ret < 0)
+        return ret;
 
-    zstream.zalloc = ff_png_zalloc;
-    zstream.zfree  = ff_png_zfree;
-    zstream.opaque = NULL;
-    if (inflateInit(&zstream) != Z_OK)
-        return AVERROR_EXTERNAL;
-    zstream.next_in  = data;
-    zstream.avail_in = data_end - data;
+    zstream->next_in  = data;
+    zstream->avail_in = data_end - data;
     av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
 
-    while (zstream.avail_in > 0) {
+    while (zstream->avail_in > 0) {
         av_bprint_get_buffer(bp, 2, &buf, &buf_size);
         if (buf_size < 2) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
-        zstream.next_out  = buf;
-        zstream.avail_out = buf_size - 1;
-        ret = inflate(&zstream, Z_PARTIAL_FLUSH);
+        zstream->next_out  = buf;
+        zstream->avail_out = buf_size - 1;
+        ret = inflate(zstream, Z_PARTIAL_FLUSH);
         if (ret != Z_OK && ret != Z_STREAM_END) {
             ret = AVERROR_EXTERNAL;
             goto fail;
         }
-        bp->len += zstream.next_out - buf;
+        bp->len += zstream->next_out - buf;
         if (ret == Z_STREAM_END)
             break;
     }
-    inflateEnd(&zstream);
+    ff_inflate_end(&z);
     bp->str[bp->len] = 0;
     return 0;
 
 fail:
-    inflateEnd(&zstream);
+    ff_inflate_end(&z);
     av_bprint_finalize(bp, NULL);
     return ret;
 }
@@ -545,7 +545,7 @@ static int decode_text_chunk(PNGDecContext *s, GetByteContext *gb, int compresse
         method = *(data++);
         if (method)
             return AVERROR_INVALIDDATA;
-        if ((ret = decode_zbuf(&bp, data, data_end)) < 0)
+        if ((ret = decode_zbuf(&bp, data, data_end, s->avctx)) < 0)
             return ret;
         text_len = bp.len;
         ret = av_bprint_finalize(&bp, (char **)&text);
@@ -767,8 +767,8 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
 
         /* we want crow_buf+1 to be 16-byte aligned */
         s->crow_buf          = s->buffer + 15;
-        s->zstream.avail_out = s->crow_size;
-        s->zstream.next_out  = s->crow_buf;
+        s->zstream.zstream.avail_out = s->crow_size;
+        s->zstream.zstream.next_out  = s->crow_buf;
     }
 
     s->pic_state |= PNG_IDAT;
@@ -877,7 +877,7 @@ static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb, AVFrame *f)
         goto fail;
     }
 
-    if ((ret = decode_zbuf(&bp, gb->buffer, gb->buffer_end)) < 0)
+    if ((ret = decode_zbuf(&bp, gb->buffer, gb->buffer_end, s->avctx)) < 0)
         return ret;
 
     av_freep(&s->iccp_data);
@@ -1542,15 +1542,10 @@ static int decode_frame_png(AVCodecContext *avctx,
     s->hdr_state = 0;
     s->pic_state = 0;
 
-    /* init the zlib */
-    s->zstream.zalloc = ff_png_zalloc;
-    s->zstream.zfree  = ff_png_zfree;
-    s->zstream.opaque = NULL;
-    ret = inflateInit(&s->zstream);
-    if (ret != Z_OK) {
-        av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
+    /* Reset z_stream */
+    ret = inflateReset(&s->zstream.zstream);
+    if (ret != Z_OK)
         return AVERROR_EXTERNAL;
-    }
 
     if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
         goto the_end;
@@ -1574,7 +1569,6 @@ static int decode_frame_png(AVCodecContext *avctx,
 
     ret = bytestream2_tell(&s->gb);
 the_end:
-    inflateEnd(&s->zstream);
     s->crow_buf = NULL;
     return ret;
 }
@@ -1596,37 +1590,30 @@ static int decode_frame_apng(AVCodecContext *avctx,
         if (!avctx->extradata_size)
             return AVERROR_INVALIDDATA;
 
-        /* only init fields, there is no zlib use in extradata */
-        s->zstream.zalloc = ff_png_zalloc;
-        s->zstream.zfree  = ff_png_zfree;
-
+        if ((ret = inflateReset(&s->zstream.zstream)) != Z_OK)
+            return AVERROR_EXTERNAL;
         bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
         if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
-            goto end;
+            return ret;
     }
 
     /* reset state for a new frame */
-    if ((ret = inflateInit(&s->zstream)) != Z_OK) {
-        av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
-        ret = AVERROR_EXTERNAL;
-        goto end;
-    }
+    if ((ret = inflateReset(&s->zstream.zstream)) != Z_OK)
+        return AVERROR_EXTERNAL;
     s->y = 0;
     s->pic_state = 0;
     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
     if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
-        goto end;
+        return ret;
 
     if (!(s->pic_state & PNG_ALLIMAGE))
         av_log(avctx, AV_LOG_WARNING, "Frame did not contain a complete image\n");
-    if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT))) {
-        ret = AVERROR_INVALIDDATA;
-        goto end;
-    }
+    if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT)))
+        return AVERROR_INVALIDDATA;
 
     ret = output_frame(s, dst_frame, s->picture.f);
     if (ret < 0)
-        goto end;
+        return ret;
 
     if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
         if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
@@ -1638,11 +1625,7 @@ static int decode_frame_apng(AVCodecContext *avctx,
     }
 
     *got_frame = 1;
-    ret = bytestream2_tell(&s->gb);
-
-end:
-    inflateEnd(&s->zstream);
-    return ret;
+    return bytestream2_tell(&s->gb);
 }
 #endif
 
@@ -1708,7 +1691,7 @@ static av_cold int png_dec_init(AVCodecContext *avctx)
 
     ff_pngdsp_init(&s->dsp);
 
-    return 0;
+    return ff_inflate_init(&s->zstream, avctx);
 }
 
 static av_cold int png_dec_end(AVCodecContext *avctx)
@@ -1729,6 +1712,7 @@ static av_cold int png_dec_end(AVCodecContext *avctx)
 
     av_freep(&s->iccp_data);
     av_dict_free(&s->frame_metadata);
+    ff_inflate_end(&s->zstream);
 
     return 0;
 }



More information about the ffmpeg-cvslog mailing list