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
643643
644644 if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0)
645645 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+ }
646651 ff_thread_finish_setup(avctx);
647652
648653 p->pict_type = AV_PICTURE_TYPE_I;
@@ -917,20 +922,20 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 268 unmodified lines
917922 return AVERROR_PATCHWELCOME;
918923 }
919924
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−
924925 // 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 {
929937 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);
934939 }
935940
936941 // Perform blending
@@ -1206,13 +1211,9 @@ static int decode_frame_apng(AVCodecContext *avctx, · 269 unmodified lines
12061211 PNGDecContext *const s = avctx->priv_data;
12071212 int ret;
12081213 AVFrame *p;
1209− ThreadFrame tmp;
12101214
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);
12161217 p = s->picture.f;
12171218
12181219 if (!(s->state & PNG_IHDR)) {
@@ -1292,8 +1293,14 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 73 unmodified lines
12921293 pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE);
12931294
12941295 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;
12971304 }
12981305
12991306 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