diff mbox series

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

Message ID HE1PR0301MB21546F75016395FC215B0B238F449@HE1PR0301MB2154.eurprd03.prod.outlook.com
State New
Headers show
Series [FFmpeg-devel,01/14] avcodec/ffv1dec: Remove redundant writes, fix races
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt April 24, 2021, 11:14 a.m. UTC
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@outlook.com>
---
 libavcodec/ffv1dec.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)
diff mbox series

Patch

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) {