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) |         if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) | ||||||
|             return ret; |             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); |         ff_thread_finish_setup(avctx); | ||||||
| 
 | 
 | ||||||
|         p->pict_type        = AV_PICTURE_TYPE_I; |         p->pict_type        = AV_PICTURE_TYPE_I; | ||||||
| @ -917,20 +922,20 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, | |||||||
|         return AVERROR_PATCHWELCOME; |         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
 |     // Do the disposal operation specified by the last frame on the frame
 | ||||||
|     if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { |     if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { | ||||||
|         for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) |         ff_thread_await_progress(&s->last_picture, INT_MAX, 0); | ||||||
|             memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); |         memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); | ||||||
|     } else if (s->last_dispose_op == APNG_DISPOSE_OP_PREVIOUS) { | 
 | ||||||
|  |         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); |         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) { |         memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height); | ||||||
|             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); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Perform blending
 |     // Perform blending
 | ||||||
| @ -1206,13 +1211,9 @@ static int decode_frame_apng(AVCodecContext *avctx, | |||||||
|     PNGDecContext *const s = avctx->priv_data; |     PNGDecContext *const s = avctx->priv_data; | ||||||
|     int ret; |     int ret; | ||||||
|     AVFrame *p; |     AVFrame *p; | ||||||
|     ThreadFrame tmp; |  | ||||||
| 
 | 
 | ||||||
|     ff_thread_release_buffer(avctx, &s->previous_picture); |     ff_thread_release_buffer(avctx, &s->last_picture); | ||||||
|     tmp = s->previous_picture; |     FFSWAP(ThreadFrame, s->picture, s->last_picture); | ||||||
|     s->previous_picture = s->last_picture; |  | ||||||
|     s->last_picture = s->picture; |  | ||||||
|     s->picture = tmp; |  | ||||||
|     p = s->picture.f; |     p = s->picture.f; | ||||||
| 
 | 
 | ||||||
|     if (!(s->state & PNG_IHDR)) { |     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); |         pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE); | ||||||
| 
 | 
 | ||||||
|         ff_thread_release_buffer(dst, &pdst->last_picture); |         ff_thread_release_buffer(dst, &pdst->last_picture); | ||||||
|         if (psrc->last_picture.f->data[0]) |         if (psrc->last_picture.f->data[0] && | ||||||
|             return ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture); |             (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; |     return 0; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user