[FFmpeg-devel] [PATCH 10/14] avcodec/ffv1dec: Treat all slices as damaged if frame is fully discarded

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Sat Apr 24 14:14:42 EEST 2021


In this case each slice's context is damaged, so decoding future
frames will fail until the next keyframe; furthermore, in case of frame
threading, the current thread's decoding state is not updated based
upon the earlier frame's decoding state, so that the damaged frames
produced by frame threaded decoding do not coincide with the result
of received by non-multithreaded decoding/slice-threaded decoding.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
 libavcodec/ffv1dec.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index bddfd8e2fb..c9583db60a 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -870,9 +870,27 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
         }
         p->key_frame = 0;
     }
+    buf_p = buf + buf_size;
+    for (i = f->slice_count - 1; i >= 0; i--) {
+        int trailer = 3 + 5*!!f->ec;
+        int v;
+
+        if (i || f->version > 2) {
+            if (trailer > buf_p - buf ||
+                buf_p - c->bytestream_start < (v = AV_RB24(buf_p-trailer) + trailer)) {
+                f->key_frame_ok = 0;
+                av_log(avctx, AV_LOG_ERROR, "Slice pointer chain broken\n");
+                return AVERROR_INVALIDDATA;
+            }
+            buf_p -= v;
+        }
+    }
 
-    if ((ret = ff_thread_get_buffer(avctx, &f->picture, AV_GET_BUFFER_FLAG_REF)) < 0)
+    ret = ff_thread_get_buffer(avctx, &f->picture, AV_GET_BUFFER_FLAG_REF);
+    if (ret < 0) {
+        f->key_frame_ok = 0;
         return ret;
+    }
 
     if (avctx->debug & FF_DEBUG_PICT_INFO)
         av_log(avctx, AV_LOG_DEBUG, "ver:%d keyframe:%d coder:%d ec:%d slices:%d bps:%d\n",
@@ -887,14 +905,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
         int v;
 
         if (i || f->version > 2) {
-            if (trailer > buf_p - buf) v = INT_MAX;
-            else                       v = AV_RB24(buf_p-trailer) + trailer;
+            v = AV_RB24(buf_p-trailer) + trailer;
         } else                         v = buf_p - c->bytestream_start;
-        if (buf_p - c->bytestream_start < v) {
-            av_log(avctx, AV_LOG_ERROR, "Slice pointer chain broken\n");
-            ff_thread_report_progress(&f->picture, INT_MAX, 0);
-            return AVERROR_INVALIDDATA;
-        }
         buf_p -= v;
 
         if (f->ec) {
-- 
2.27.0



More information about the ffmpeg-devel mailing list