Unified · Split
| @@ -643,6 +643,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, · 642 unmodified lines | |||
| 643 | 643 | ||
| 644 | if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) | 644 | if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) |
| 645 | return ret; | 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 | ff_thread_finish_setup(avctx); | 651 | ff_thread_finish_setup(avctx); |
| 647 | 652 | ||
| 648 | p->pict_type = AV_PICTURE_TYPE_I; | 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 | return AVERROR_PATCHWELCOME; | 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 | // Do the disposal operation specified by the last frame on the frame | 925 | // Do the disposal operation specified by the last frame on the frame |
| 925 | if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { | 926 | if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { |
| 926 | for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) | 927 | ff_thread_await_progress(&s->last_picture, INT_MAX, 0); |
| 927 | memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); | 928 | memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); |
| 928 | } else if (s->last_dispose_op == APNG_DISPOSE_OP_PREVIOUS) { | 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 | ff_thread_await_progress(&s->previous_picture, INT_MAX, 0); | 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) { | 938 | memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height); |
| 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 | } | ||
| 934 | } | 939 | } |
| 935 | 940 | ||
| 936 | // Perform blending | 941 | // Perform blending |
| @@ -1206,13 +1211,9 @@ static int decode_frame_apng(AVCodecContext *avctx, · 269 unmodified lines | |||
| 1206 | PNGDecContext *const s = avctx->priv_data; | 1211 | PNGDecContext *const s = avctx->priv_data; |
| 1207 | int ret; | 1212 | int ret; |
| 1208 | AVFrame *p; | 1213 | AVFrame *p; |
| 1209 | ThreadFrame tmp; | ||
| 1210 | 1214 | ||
| 1211 | ff_thread_release_buffer(avctx, &s->previous_picture); | 1215 | ff_thread_release_buffer(avctx, &s->last_picture); |
| 1212 | tmp = s->previous_picture; | 1216 | FFSWAP(ThreadFrame, s->picture, s->last_picture); |
| 1213 | s->previous_picture = s->last_picture; | ||
| 1214 | s->last_picture = s->picture; | ||
| 1215 | s->picture = tmp; | ||
| 1216 | p = s->picture.f; | 1217 | p = s->picture.f; |
| 1217 | 1218 | ||
| 1218 | if (!(s->state & PNG_IHDR)) { | 1219 | if (!(s->state & PNG_IHDR)) { |
| @@ -1292,8 +1293,14 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 73 unmodified lines | |||
| 1292 | pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE); | 1293 | pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE); |
| 1293 | 1294 | ||
| 1294 | ff_thread_release_buffer(dst, &pdst->last_picture); | 1295 | ff_thread_release_buffer(dst, &pdst->last_picture); |
| 1295 | if (psrc->last_picture.f->data[0]) | 1296 | if (psrc->last_picture.f->data[0] && |
| 1296 | return ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture); | 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 | return 0; | 1306 | return 0; |