[FFmpeg-devel] [PATCH 1/2] png: split header state and data state in two separate variables.
Ronald S. Bultje
rsbultje at gmail.com
Wed Mar 29 02:37:54 EEST 2017
Fixes a reported (but false) race condition in tsan for fate-apng.
---
libavcodec/pngdec.c | 39 +++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index a4eb6cc..bbb9610 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -45,7 +45,7 @@ typedef struct PNGDecContext {
ThreadFrame last_picture;
ThreadFrame picture;
- int state;
+ int state, pstate;
int width, height;
int cur_w, cur_h;
int last_w, last_h;
@@ -334,7 +334,7 @@ static void png_handle_row(PNGDecContext *s)
}
s->y++;
if (s->y == s->cur_h) {
- s->state |= PNG_ALLIMAGE;
+ s->pstate |= PNG_ALLIMAGE;
if (s->filter_type == PNG_FILTER_TYPE_LOCO) {
if (s->bit_depth == 16) {
deloco_rgb16((uint16_t *)ptr, s->row_size / 2,
@@ -369,7 +369,7 @@ static void png_handle_row(PNGDecContext *s)
memset(s->last_row, 0, s->row_size);
for (;;) {
if (s->pass == NB_PASSES - 1) {
- s->state |= PNG_ALLIMAGE;
+ s->pstate |= PNG_ALLIMAGE;
goto the_end;
} else {
s->pass++;
@@ -404,7 +404,7 @@ static int png_decode_idat(PNGDecContext *s, int length)
return AVERROR_EXTERNAL;
}
if (s->zstream.avail_out == 0) {
- if (!(s->state & PNG_ALLIMAGE)) {
+ if (!(s->pstate & PNG_ALLIMAGE)) {
png_handle_row(s);
}
s->zstream.avail_out = s->crow_size;
@@ -541,7 +541,7 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
if (length != 13)
return AVERROR_INVALIDDATA;
- if (s->state & PNG_IDAT) {
+ if (s->pstate & PNG_IDAT) {
av_log(avctx, AV_LOG_ERROR, "IHDR after IDAT\n");
return AVERROR_INVALIDDATA;
}
@@ -585,7 +585,7 @@ error:
static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
{
- if (s->state & PNG_IDAT) {
+ if (s->pstate & PNG_IDAT) {
av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
return AVERROR_INVALIDDATA;
}
@@ -609,7 +609,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
return AVERROR_INVALIDDATA;
}
- if (!(s->state & PNG_IDAT)) {
+ if (!(s->pstate & PNG_IDAT)) {
/* init image info */
avctx->width = s->width;
avctx->height = s->height;
@@ -690,11 +690,10 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
if ((ret = ff_thread_get_buffer(avctx, &s->previous_picture, AV_GET_BUFFER_FLAG_REF)) < 0)
return ret;
}
- ff_thread_finish_setup(avctx);
-
p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1;
p->interlaced_frame = !!s->interlace_type;
+ ff_thread_finish_setup(avctx);
/* compute the compressed row size */
if (!s->interlace_type) {
@@ -734,7 +733,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
s->zstream.next_out = s->crow_buf;
}
- s->state |= PNG_IDAT;
+ s->pstate |= PNG_IDAT;
/* set image to non-transparent bpp while decompressing */
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
@@ -786,7 +785,7 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
return AVERROR_INVALIDDATA;
}
- if (s->state & PNG_IDAT) {
+ if (s->pstate & PNG_IDAT) {
av_log(avctx, AV_LOG_ERROR, "trns after IDAT\n");
return AVERROR_INVALIDDATA;
}
@@ -1122,13 +1121,13 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
}
if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && length == 0) {
- if (!(s->state & PNG_IDAT))
+ if (!(s->pstate & PNG_IDAT))
return 0;
else
goto exit_loop;
}
av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", length);
- if ( s->state & PNG_ALLIMAGE
+ if ( s->pstate & PNG_ALLIMAGE
&& avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
goto exit_loop;
ret = AVERROR_INVALIDDATA;
@@ -1231,9 +1230,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
break;
}
case MKTAG('I', 'E', 'N', 'D'):
- if (!(s->state & PNG_ALLIMAGE))
+ if (!(s->pstate & PNG_ALLIMAGE))
av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
- if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
+ if (!(s->pstate & (PNG_ALLIMAGE|PNG_IDAT))) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
@@ -1333,7 +1332,7 @@ static int decode_frame_png(AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}
- s->y = s->state = s->has_trns = 0;
+ s->y = s->state = s->pstate = s->has_trns = 0;
/* init the zlib */
s->zstream.zalloc = ff_png_zalloc;
@@ -1400,14 +1399,14 @@ static int decode_frame_apng(AVCodecContext *avctx,
goto end;
}
s->y = 0;
- s->state &= ~(PNG_IDAT | PNG_ALLIMAGE);
+ s->pstate &= ~(PNG_IDAT | PNG_ALLIMAGE);
bytestream2_init(&s->gb, avpkt->data, avpkt->size);
if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
goto end;
- if (!(s->state & PNG_ALLIMAGE))
+ if (!(s->pstate & PNG_ALLIMAGE))
av_log(avctx, AV_LOG_WARNING, "Frame did not contain a complete image\n");
- if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
+ if (!(s->pstate & (PNG_ALLIMAGE|PNG_IDAT))) {
ret = AVERROR_INVALIDDATA;
goto end;
}
@@ -1456,7 +1455,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
memcpy(pdst->palette, psrc->palette, sizeof(pdst->palette));
- pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE);
+ pdst->state |= psrc->state;
ff_thread_release_buffer(dst, &pdst->last_picture);
if (psrc->last_picture.f->data[0] &&
--
2.8.1
More information about the ffmpeg-devel
mailing list