mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
apng: Fix decoding images with the PREVIOUS dispose op
This commit is contained in:
parent
1d7fa1ac89
commit
a906e86a8d
@ -643,6 +643,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
|
||||
if ((ret = ff_thread_get_buffer(avctx, &s->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, &s->previous_picture);
|
||||
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;
|
||||
@ -917,20 +922,20 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
// Copy the previous frame to the buffer
|
||||
ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
|
||||
memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height);
|
||||
|
||||
// Do the disposal operation specified by the last frame on the frame
|
||||
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);
|
||||
} else if (s->last_dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
|
||||
if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) {
|
||||
ff_thread_await_progress(&s->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);
|
||||
|
||||
memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * s->height);
|
||||
ff_thread_report_progress(&s->previous_picture, INT_MAX, 0);
|
||||
} else {
|
||||
ff_thread_await_progress(&s->previous_picture, INT_MAX, 0);
|
||||
for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) {
|
||||
size_t row_start = s->image_linesize * y + s->bpp * s->last_x_offset;
|
||||
memcpy(buffer + row_start, s->previous_picture.f->data[0] + row_start, s->bpp * s->last_w);
|
||||
}
|
||||
memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height);
|
||||
}
|
||||
|
||||
// Perform blending
|
||||
@ -1206,13 +1211,9 @@ static int decode_frame_apng(AVCodecContext *avctx,
|
||||
PNGDecContext *const s = avctx->priv_data;
|
||||
int ret;
|
||||
AVFrame *p;
|
||||
ThreadFrame tmp;
|
||||
|
||||
ff_thread_release_buffer(avctx, &s->previous_picture);
|
||||
tmp = s->previous_picture;
|
||||
s->previous_picture = s->last_picture;
|
||||
s->last_picture = s->picture;
|
||||
s->picture = tmp;
|
||||
ff_thread_release_buffer(avctx, &s->last_picture);
|
||||
FFSWAP(ThreadFrame, s->picture, s->last_picture);
|
||||
p = s->picture.f;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
@ -1292,8 +1293,14 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
|
||||
pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE);
|
||||
|
||||
ff_thread_release_buffer(dst, &pdst->last_picture);
|
||||
if (psrc->last_picture.f->data[0])
|
||||
return ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture);
|
||||
if (psrc->last_picture.f->data[0] &&
|
||||
(ret = ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture)) < 0)
|
||||
return ret;
|
||||
|
||||
ff_thread_release_buffer(dst, &pdst->previous_picture);
|
||||
if (psrc->previous_picture.f->data[0] &&
|
||||
(ret = ff_thread_ref_frame(&pdst->previous_picture, &psrc->previous_picture)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user