summaryrefslogtreecommitdiff
path: root/libavcodec/pngdec.c
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2022-03-15 15:05:53 +0100
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2022-03-19 00:18:36 +0100
commit74c930e1b8f7dfc308784e1c3410ef825bec56cf (patch)
tree2669dfaab14a159189cc43eb6bd51e7b968eeb39 /libavcodec/pngdec.c
parent7ca99e1f15de13b044fe676fa0fed20bda7c5bd3 (diff)
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@outlook.com>
Diffstat (limited to 'libavcodec/pngdec.c')
-rw-r--r--libavcodec/pngdec.c108
1 files changed, 46 insertions, 62 deletions
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;
}