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