Unified · Split
| @@ -643,6 +643,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, · 642 unmodified lines | ||
| 643 | 643 | |
| 644 | 644 | if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) |
| 645 | 645 | return ret; |
| 646 | + if (avctx->codec_id == AV_CODEC_ID_APNG && s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { | |
| 647 | + ff_thread_release_buffer(avctx, &s->previous_picture); | |
| 648 | + if ((ret = ff_thread_get_buffer(avctx, &s->previous_picture, AV_GET_BUFFER_FLAG_REF)) < 0) | |
| 649 | + return ret; | |
| 650 | + } | |
| 646 | 651 | ff_thread_finish_setup(avctx); |
| 647 | 652 | |
| 648 | 653 | p->pict_type = AV_PICTURE_TYPE_I; |
| @@ -917,20 +922,20 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 268 unmodified lines | ||
| 917 | 922 | return AVERROR_PATCHWELCOME; |
| 918 | 923 | } |
| 919 | 924 | |
| 920 | − // Copy the previous frame to the buffer | |
| 921 | − ff_thread_await_progress(&s->last_picture, INT_MAX, 0); | |
| 922 | − memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); | |
| 923 | − | |
| 924 | 925 | // Do the disposal operation specified by the last frame on the frame |
| 925 | − if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { | |
| 926 | − for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) | |
| 927 | − memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); | |
| 928 | − } else if (s->last_dispose_op == APNG_DISPOSE_OP_PREVIOUS) { | |
| 926 | + if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { | |
| 927 | + ff_thread_await_progress(&s->last_picture, INT_MAX, 0); | |
| 928 | + memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); | |
| 929 | + | |
| 930 | + if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) | |
| 931 | + for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) | |
| 932 | + memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); | |
| 933 | + | |
| 934 | + memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * s->height); | |
| 935 | + ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); | |
| 936 | + } else { | |
| 929 | 937 | ff_thread_await_progress(&s->previous_picture, INT_MAX, 0); |
| 930 | − for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) { | |
| 931 | − size_t row_start = s->image_linesize * y + s->bpp * s->last_x_offset; | |
| 932 | − memcpy(buffer + row_start, s->previous_picture.f->data[0] + row_start, s->bpp * s->last_w); | |
| 933 | − } | |
| 938 | + memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height); | |
| 934 | 939 | } |
| 935 | 940 | |
| 936 | 941 | // Perform blending |
| @@ -1206,13 +1211,9 @@ static int decode_frame_apng(AVCodecContext *avctx, · 269 unmodified lines | ||
| 1206 | 1211 | PNGDecContext *const s = avctx->priv_data; |
| 1207 | 1212 | int ret; |
| 1208 | 1213 | AVFrame *p; |
| 1209 | − ThreadFrame tmp; | |
| 1210 | 1214 | |
| 1211 | − ff_thread_release_buffer(avctx, &s->previous_picture); | |
| 1212 | − tmp = s->previous_picture; | |
| 1213 | − s->previous_picture = s->last_picture; | |
| 1214 | − s->last_picture = s->picture; | |
| 1215 | − s->picture = tmp; | |
| 1215 | + ff_thread_release_buffer(avctx, &s->last_picture); | |
| 1216 | + FFSWAP(ThreadFrame, s->picture, s->last_picture); | |
| 1216 | 1217 | p = s->picture.f; |
| 1217 | 1218 | |
| 1218 | 1219 | if (!(s->state & PNG_IHDR)) { |
| @@ -1292,8 +1293,14 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 73 unmodified lines | ||
| 1292 | 1293 | pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE); |
| 1293 | 1294 | |
| 1294 | 1295 | ff_thread_release_buffer(dst, &pdst->last_picture); |
| 1295 | − if (psrc->last_picture.f->data[0]) | |
| 1296 | − return ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture); | |
| 1296 | + if (psrc->last_picture.f->data[0] && | |
| 1297 | + (ret = ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture)) < 0) | |
| 1298 | + return ret; | |
| 1299 | + | |
| 1300 | + ff_thread_release_buffer(dst, &pdst->previous_picture); | |
| 1301 | + if (psrc->previous_picture.f->data[0] && | |
| 1302 | + (ret = ff_thread_ref_frame(&pdst->previous_picture, &psrc->previous_picture)) < 0) | |
| 1303 | + return ret; | |
| 1297 | 1304 | } |
| 1298 | 1305 | |
| 1299 | 1306 | return 0; |