Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2021-11-15 22:20:33 +0300
committerRichard Antalik <richardantalik@gmail.com>2021-11-15 22:20:33 +0300
commitd3c45e1c391eaafd9c54dba5b574b1a7ee23c82a (patch)
tree874cea7188bd56ccddcb59151d5d46e29f469b77 /source/blender/imbuf
parentef8240e64c9f7805ef65d9f7599bfb3eca97566c (diff)
Fix T91405: Block artefacts in WEBM video
Issue was caused by incorrect FFmpeg asynchronous decoding API. In most cases, decoder returns 1 frame each time it is fed by 1 packet. Here decoder wanted to return more frames, but our code always expected only one. Before sending new packets to decoder, check if there are frames to receive. If there are, process them, otherwise continue decoding as usual. Reviewed By: zeddb, sergey Differential Revision: https://developer.blender.org/D13079
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/intern/anim_movie.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index c11c6d778a1..87f2fd124c0 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -939,14 +939,36 @@ static void ffmpeg_postprocess(struct anim *anim)
}
}
-/* decode one video frame also considering the packet read into cur_packet */
+static void ffmpeg_decode_store_frame_pts(struct anim *anim)
+{
+ anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
+
+ if (anim->pFrame->key_frame) {
+ anim->cur_key_frame_pts = anim->cur_pts;
+ }
+
+ av_log(anim->pFormatCtx,
+ AV_LOG_DEBUG,
+ " FRAME DONE: cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
+ (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
+ (int64_t)anim->cur_pts);
+}
+/* decode one video frame also considering the packet read into cur_packet */
static int ffmpeg_decode_video_frame(struct anim *anim)
{
- int rval = 0;
-
av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n");
+ /* Sometimes, decoder returns more than one frame per sent packet. Check if frames are available.
+ * This frames must be read, otherwise decoding will fail. See T91405. */
+ anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
+ if (anim->pFrameComplete) {
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE FROM CODEC BUFFER\n");
+ ffmpeg_decode_store_frame_pts(anim);
+ return 1;
+ }
+
+ int rval = 0;
if (anim->cur_packet->stream_index == anim->videoStream) {
av_packet_unref(anim->cur_packet);
anim->cur_packet->stream_index = -1;
@@ -963,22 +985,11 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
(anim->cur_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->cur_packet->pts,
(anim->cur_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
if (anim->cur_packet->stream_index == anim->videoStream) {
- anim->pFrameComplete = 0;
-
avcodec_send_packet(anim->pCodecCtx, anim->cur_packet);
anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
if (anim->pFrameComplete) {
- anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
-
- if (anim->pFrame->key_frame) {
- anim->cur_key_frame_pts = anim->cur_pts;
- }
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- " FRAME DONE: cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
- (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
- (int64_t)anim->cur_pts);
+ ffmpeg_decode_store_frame_pts(anim);
break;
}
}
@@ -988,22 +999,11 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
if (rval == AVERROR_EOF) {
/* Flush any remaining frames out of the decoder. */
- anim->pFrameComplete = 0;
-
avcodec_send_packet(anim->pCodecCtx, NULL);
anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
if (anim->pFrameComplete) {
- anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
-
- if (anim->pFrame->key_frame) {
- anim->cur_key_frame_pts = anim->cur_pts;
- }
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- " FRAME DONE (after EOF): cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
- (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
- (int64_t)anim->cur_pts);
+ ffmpeg_decode_store_frame_pts(anim);
rval = 0;
}
}