History

apng: Fix decoding images with the PREVIOUS dispose op

Donny Yang committed 11 years ago

Commit a906e861 parent 1d7fa1a1 file · +27 −20Browse files

Unified · Split

libavcodec/pngdec.c+27−20
@@ -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 frame925 // 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 blending941 // 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;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t