Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On Tue, Mar 30, 2021 at 02:30:08PM -0300, James Almer wrote: > On 3/30/2021 5:56 AM, Michael Niedermayer wrote: > > On Tue, Feb 16, 2021 at 09:24:15PM +0100, Anton Khirnov wrote: > > > Current code is very confused and confusing. It uses two different > > > reference frames - "previous" and "last" - when only one is really > > > necessary. It also confuses the two, leading to incorrect output with > > > APNG_DISPOSE_OP_PREVIOUS mode. > > > > > > Fixes #9017. > > > --- > > > libavcodec/pngdec.c | 93 - > > > 1 file changed, 42 insertions(+), 51 deletions(-) > > > > > > [...] > > > > > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > > > *avctx, PNGDecContext *s, > > > if (!buffer) > > > return AVERROR(ENOMEM); > > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > -// Do the disposal operation specified by the last frame on the frame > > > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > > > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > s->height); > > > - > > > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > > > -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > > > ++y) > > > -memset(buffer + s->image_linesize * y + s->bpp * > > > s->last_x_offset, 0, s->bpp * s->last_w); > > > +// need to reset a rectangle to background: > > > +// create a new writable copy > > > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > > > +int ret = av_frame_make_writable(s->last_picture.f); > > > +if (ret < 0) > > > +return ret; > > > -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize > > > * s->height); > > > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > > -} else { > > > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > > > -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize > > > * s->height); > > > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > > > y++) { > > > +memset(s->last_picture.f->data[0] + s->image_linesize * y + > > > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > > > +} > > > } > > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > s->height); > > > + > > > > This results in out of array reads > > > > av_frame_make_writable() decreases linesize [0] but the memcpy() now > > av_memdup() > > assumes all frames have the same linesize > > FATE didn't detect this? What sample triggers these out of array reads? if iam reading my notes correctly 31405/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APNG_fuzzer-6572805215879168 did if someone wants to work on this and wants it i can send it privatly i dont know why fate didnt catch this ... > > Also, instead of av_frame_make_writable(), this should probably call > ff_thread_get_buffer() to get a new buffer, then copy the old data if > needed. The difference in linesize is because avcodec_default_get_buffer2() > allocates buffers in a different way than av_frame_get_buffer() as invoked > by av_frame_make_writable(). yes thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB If the United States is serious about tackling the national security threats related to an insecure 5G network, it needs to rethink the extent to which it values corporate profits and government espionage over security.-Bruce Schneier signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On 3/30/2021 5:56 AM, Michael Niedermayer wrote: On Tue, Feb 16, 2021 at 09:24:15PM +0100, Anton Khirnov wrote: Current code is very confused and confusing. It uses two different reference frames - "previous" and "last" - when only one is really necessary. It also confuses the two, leading to incorrect output with APNG_DISPOSE_OP_PREVIOUS mode. Fixes #9017. --- libavcodec/pngdec.c | 93 - 1 file changed, 42 insertions(+), 51 deletions(-) [...] @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, if (!buffer) return AVERROR(ENOMEM); +ff_thread_await_progress(>last_picture, INT_MAX, 0); -// Do the disposal operation specified by the last frame on the frame -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { -ff_thread_await_progress(>last_picture, INT_MAX, 0); -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); - -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) -memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); +// need to reset a rectangle to background: +// create a new writable copy +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { +int ret = av_frame_make_writable(s->last_picture.f); +if (ret < 0) +return ret; -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * s->height); -ff_thread_report_progress(>previous_picture, INT_MAX, 0); -} else { -ff_thread_await_progress(>previous_picture, INT_MAX, 0); -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height); +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) { +memset(s->last_picture.f->data[0] + s->image_linesize * y + + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); +} } +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); + This results in out of array reads av_frame_make_writable() decreases linesize [0] but the memcpy() now av_memdup() assumes all frames have the same linesize FATE didn't detect this? What sample triggers these out of array reads? Also, instead of av_frame_make_writable(), this should probably call ff_thread_get_buffer() to get a new buffer, then copy the old data if needed. The difference in linesize is because avcodec_default_get_buffer2() allocates buffers in a different way than av_frame_get_buffer() as invoked by av_frame_make_writable(). Thanks [...] ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On Tue, Mar 30, 2021 at 10:56:13AM +0200, Michael Niedermayer wrote: > On Tue, Feb 16, 2021 at 09:24:15PM +0100, Anton Khirnov wrote: > > Current code is very confused and confusing. It uses two different > > reference frames - "previous" and "last" - when only one is really > > necessary. It also confuses the two, leading to incorrect output with > > APNG_DISPOSE_OP_PREVIOUS mode. > > > > Fixes #9017. > > --- > > libavcodec/pngdec.c | 93 - > > 1 file changed, 42 insertions(+), 51 deletions(-) > > > [...] > > > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > > *avctx, PNGDecContext *s, > > if (!buffer) > > return AVERROR(ENOMEM); > > > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > > -// Do the disposal operation specified by the last frame on the frame > > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > s->height); > > - > > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > > -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > > ++y) > > -memset(buffer + s->image_linesize * y + s->bpp * > > s->last_x_offset, 0, s->bpp * s->last_w); > > +// need to reset a rectangle to background: > > +// create a new writable copy > > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > > +int ret = av_frame_make_writable(s->last_picture.f); > > +if (ret < 0) > > +return ret; > > > > -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * > > s->height); > > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > -} else { > > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > > -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * > > s->height); > > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) { > > +memset(s->last_picture.f->data[0] + s->image_linesize * y + > > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > > +} > > } > > > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > s->height); > > + > > This results in out of array reads > > av_frame_make_writable() decreases linesize [0] but the memcpy() now > av_memdup() > assumes all frames have the same linesize CCing anton, to make sure this is not missed in its old thread A fix to this also should be backported to release/4.4 Thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB The bravest are surely those who have the clearest vision of what is before them, glory and danger alike, and yet notwithstanding go out to meet it. -- Thucydides signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On Tue, Feb 16, 2021 at 09:24:15PM +0100, Anton Khirnov wrote: > Current code is very confused and confusing. It uses two different > reference frames - "previous" and "last" - when only one is really > necessary. It also confuses the two, leading to incorrect output with > APNG_DISPOSE_OP_PREVIOUS mode. > > Fixes #9017. > --- > libavcodec/pngdec.c | 93 - > 1 file changed, 42 insertions(+), 51 deletions(-) [...] > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext *avctx, > PNGDecContext *s, > if (!buffer) > return AVERROR(ENOMEM); > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > -// Do the disposal operation specified by the last frame on the frame > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > s->height); > - > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) > -memset(buffer + s->image_linesize * y + s->bpp * > s->last_x_offset, 0, s->bpp * s->last_w); > +// need to reset a rectangle to background: > +// create a new writable copy > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > +int ret = av_frame_make_writable(s->last_picture.f); > +if (ret < 0) > +return ret; > > -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * > s->height); > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > -} else { > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * > s->height); > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) { > +memset(s->last_picture.f->data[0] + s->image_linesize * y + > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > +} > } > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > s->height); > + This results in out of array reads av_frame_make_writable() decreases linesize [0] but the memcpy() now av_memdup() assumes all frames have the same linesize Thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB I know you won't believe me, but the highest form of Human Excellence is to question oneself and others. -- Socrates signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
Quoting Paul B Mahol (2021-02-17 14:34:18) > On Wed, Feb 17, 2021 at 12:33 PM Anton Khirnov wrote: > > > Quoting Paul B Mahol (2021-02-17 11:52:31) > > > On Tue, Feb 16, 2021 at 9:26 PM Anton Khirnov wrote: > > > > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > > > > *avctx, PNGDecContext *s, > > > > if (!buffer) > > > > return AVERROR(ENOMEM); > > > > > > > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > > > > > > -// Do the disposal operation specified by the last frame on the > > frame > > > > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > > > > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > > s->height); > > > > - > > > > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > > > > -for (y = s->last_y_offset; y < s->last_y_offset + > > s->last_h; > > > > ++y) > > > > -memset(buffer + s->image_linesize * y + s->bpp * > > > > s->last_x_offset, 0, s->bpp * s->last_w); > > > > +// need to reset a rectangle to background: > > > > +// create a new writable copy > > > > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > > > > +int ret = av_frame_make_writable(s->last_picture.f); > > > > +if (ret < 0) > > > > +return ret; > > > > > > > > -memcpy(s->previous_picture.f->data[0], buffer, > > s->image_linesize > > > > * s->height); > > > > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > > > -} else { > > > > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > > > > -memcpy(buffer, s->previous_picture.f->data[0], > > s->image_linesize > > > > * s->height); > > > > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > > y++) > > > > { > > > > +memset(s->last_picture.f->data[0] + s->image_linesize * y > > + > > > > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > > > > +} > > > > } > > > > > > > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > > s->height); > > > > + > > > > // Perform blending > > > > if (s->blend_op == APNG_BLEND_OP_SOURCE) { > > > > for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { > > > > @@ -1448,22 +1444,17 @@ exit_loop: > > > > if (CONFIG_PNG_DECODER && avctx->codec_id != > > AV_CODEC_ID_APNG) > > > > handle_p_frame_png(s, p); > > > > else if (CONFIG_APNG_DECODER && > > > > - s->previous_picture.f->width == p->width && > > > > - s->previous_picture.f->height== p->height && > > > > - s->previous_picture.f->format== p->format && > > > > > > > > > > No explanation provided why those line are removed. > > > > > > > They are removed because previous_picture is removed. As is actually > > explained in the commit message. > > > > > But you just replaced previous with last? The same check is already done for last_picture a few lines above. -- Anton Khirnov ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On Wed, Feb 17, 2021 at 12:33 PM Anton Khirnov wrote: > Quoting Paul B Mahol (2021-02-17 11:52:31) > > On Tue, Feb 16, 2021 at 9:26 PM Anton Khirnov wrote: > > > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > > > *avctx, PNGDecContext *s, > > > if (!buffer) > > > return AVERROR(ENOMEM); > > > > > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > > > > -// Do the disposal operation specified by the last frame on the > frame > > > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > > > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > s->height); > > > - > > > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > > > -for (y = s->last_y_offset; y < s->last_y_offset + > s->last_h; > > > ++y) > > > -memset(buffer + s->image_linesize * y + s->bpp * > > > s->last_x_offset, 0, s->bpp * s->last_w); > > > +// need to reset a rectangle to background: > > > +// create a new writable copy > > > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > > > +int ret = av_frame_make_writable(s->last_picture.f); > > > +if (ret < 0) > > > +return ret; > > > > > > -memcpy(s->previous_picture.f->data[0], buffer, > s->image_linesize > > > * s->height); > > > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > > -} else { > > > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > > > -memcpy(buffer, s->previous_picture.f->data[0], > s->image_linesize > > > * s->height); > > > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > y++) > > > { > > > +memset(s->last_picture.f->data[0] + s->image_linesize * y > + > > > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > > > +} > > > } > > > > > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > > s->height); > > > + > > > // Perform blending > > > if (s->blend_op == APNG_BLEND_OP_SOURCE) { > > > for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { > > > @@ -1448,22 +1444,17 @@ exit_loop: > > > if (CONFIG_PNG_DECODER && avctx->codec_id != > AV_CODEC_ID_APNG) > > > handle_p_frame_png(s, p); > > > else if (CONFIG_APNG_DECODER && > > > - s->previous_picture.f->width == p->width && > > > - s->previous_picture.f->height== p->height && > > > - s->previous_picture.f->format== p->format && > > > > > > > No explanation provided why those line are removed. > > > > They are removed because previous_picture is removed. As is actually > explained in the commit message. > > But you just replaced previous with last? > -- > Anton Khirnov > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
Quoting Paul B Mahol (2021-02-17 11:52:31) > On Tue, Feb 16, 2021 at 9:26 PM Anton Khirnov wrote: > > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > > *avctx, PNGDecContext *s, > > if (!buffer) > > return AVERROR(ENOMEM); > > > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > > > -// Do the disposal operation specified by the last frame on the frame > > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > s->height); > > - > > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > > -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > > ++y) > > -memset(buffer + s->image_linesize * y + s->bpp * > > s->last_x_offset, 0, s->bpp * s->last_w); > > +// need to reset a rectangle to background: > > +// create a new writable copy > > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > > +int ret = av_frame_make_writable(s->last_picture.f); > > +if (ret < 0) > > +return ret; > > > > -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize > > * s->height); > > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > -} else { > > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > > -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize > > * s->height); > > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) > > { > > +memset(s->last_picture.f->data[0] + s->image_linesize * y + > > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > > +} > > } > > > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > > s->height); > > + > > // Perform blending > > if (s->blend_op == APNG_BLEND_OP_SOURCE) { > > for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { > > @@ -1448,22 +1444,17 @@ exit_loop: > > if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG) > > handle_p_frame_png(s, p); > > else if (CONFIG_APNG_DECODER && > > - s->previous_picture.f->width == p->width && > > - s->previous_picture.f->height== p->height && > > - s->previous_picture.f->format== p->format && > > > > No explanation provided why those line are removed. > They are removed because previous_picture is removed. As is actually explained in the commit message. -- Anton Khirnov ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 5/6] pngdec: fix and simplify apng reference handling
On Tue, Feb 16, 2021 at 9:26 PM Anton Khirnov wrote: > Current code is very confused and confusing. It uses two different > reference frames - "previous" and "last" - when only one is really > necessary. It also confuses the two, leading to incorrect output with > APNG_DISPOSE_OP_PREVIOUS mode. > > Fixes #9017. > --- > libavcodec/pngdec.c | 93 - > 1 file changed, 42 insertions(+), 51 deletions(-) > > diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c > index d02c45f1a7..cece08ebca 100644 > --- a/libavcodec/pngdec.c > +++ b/libavcodec/pngdec.c > @@ -54,7 +54,6 @@ typedef struct PNGDecContext { > AVCodecContext *avctx; > > GetByteContext gb; > -ThreadFrame previous_picture; > ThreadFrame last_picture; > ThreadFrame picture; > > @@ -711,13 +710,10 @@ static int decode_idat_chunk(AVCodecContext *avctx, > PNGDecContext *s, > s->bpp += byte_depth; > } > > +ff_thread_release_buffer(avctx, >picture); > if ((ret = ff_thread_get_buffer(avctx, >picture, > AV_GET_BUFFER_FLAG_REF)) < 0) > return ret; > -if (avctx->codec_id == AV_CODEC_ID_APNG && s->last_dispose_op != > APNG_DISPOSE_OP_PREVIOUS) { > -ff_thread_release_buffer(avctx, >previous_picture); > -if ((ret = ff_thread_get_buffer(avctx, >previous_picture, > AV_GET_BUFFER_FLAG_REF)) < 0) > -return ret; > -} > + > p->pict_type= AV_PICTURE_TYPE_I; > p->key_frame= 1; > p->interlaced_frame = !!s->interlace_type; > @@ -1020,7 +1016,7 @@ static int decode_fctl_chunk(AVCodecContext *avctx, > PNGDecContext *s, > return AVERROR_INVALIDDATA; > } > > -if ((sequence_number == 0 || !s->previous_picture.f->data[0]) && > +if ((sequence_number == 0 || !s->last_picture.f->data[0]) && > dispose_op == APNG_DISPOSE_OP_PREVIOUS) { > // No previous frame to revert to for the first frame > // Spec says to just treat it as a APNG_DISPOSE_OP_BACKGROUND > @@ -1088,23 +1084,23 @@ static int handle_p_frame_apng(AVCodecContext > *avctx, PNGDecContext *s, > if (!buffer) > return AVERROR(ENOMEM); > > +ff_thread_await_progress(>last_picture, INT_MAX, 0); > > -// Do the disposal operation specified by the last frame on the frame > -if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { > -ff_thread_await_progress(>last_picture, INT_MAX, 0); > -memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > s->height); > - > -if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) > -for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; > ++y) > -memset(buffer + s->image_linesize * y + s->bpp * > s->last_x_offset, 0, s->bpp * s->last_w); > +// need to reset a rectangle to background: > +// create a new writable copy > +if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { > +int ret = av_frame_make_writable(s->last_picture.f); > +if (ret < 0) > +return ret; > > -memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize > * s->height); > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > -} else { > -ff_thread_await_progress(>previous_picture, INT_MAX, 0); > -memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize > * s->height); > +for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) > { > +memset(s->last_picture.f->data[0] + s->image_linesize * y + > + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); > +} > } > > +memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * > s->height); > + > // Perform blending > if (s->blend_op == APNG_BLEND_OP_SOURCE) { > for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { > @@ -1448,22 +1444,17 @@ exit_loop: > if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG) > handle_p_frame_png(s, p); > else if (CONFIG_APNG_DECODER && > - s->previous_picture.f->width == p->width && > - s->previous_picture.f->height== p->height && > - s->previous_picture.f->format== p->format && > No explanation provided why those line are removed. > avctx->codec_id == AV_CODEC_ID_APNG && > (ret = handle_p_frame_apng(avctx, s, p)) < 0) > goto fail; > } > } > ff_thread_report_progress(>picture, INT_MAX, 0); > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > > return 0; > > fail: > ff_thread_report_progress(>picture, INT_MAX, 0); > -ff_thread_report_progress(>previous_picture, INT_MAX, 0); > return ret; > } > > @@ -1475,14 +1466,10 @@ static int decode_frame_png(AVCodecContext *avctx, > PNGDecContext *const