diff mbox series

[FFmpeg-devel,03/14] avcodec/mpegvideo_dec: Sync linesize and uvlinesize between threads

Message ID GV1SPRMB00216593923503E70A6FAD588F1B2@GV1SPRMB0021.EURP250.PROD.OUTLOOK.COM
State New
Headers show
Series [FFmpeg-devel,01/14] avcodec/get_buffer: Remove redundant check | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished

Commit Message

Andreas Rheinhardt April 29, 2024, 12:35 a.m. UTC
linesize and uvlinesize are supposed to be the common linesize of all
the Y/UV-planes of all the currently cached pictures.
ff_mpeg_update_thread_context() syncs the pictures, yet it did not sync
linesize and uvlinesize. This mostly works, because ff_alloc_picture()
only accepts new pictures if they coincide with the linesize of the
already provided pictures (if any).  Yet there is a catch: Linesize
changes are accepted when the dimensions change (in which case the
cached frames are discarded).

So imagine a scenario where all frame threads use the same dimension A
until a frame with a different dimension B is encountered in the
bitstream, only to be instantly reverted to A in the next picture. If
the user changes the linesize of the frames upon the change to dimension
B and keeps the linesize thereafter (possible if B > A),
ff_alloc_picture() will report an error when frame-threading is in use:
The thread decoding B will perform a frame size change and so will the
next thread in ff_mpeg_update_thread_context() as well as when decoding
its picture. But the next thread will (presuming it is not the same
thread that decoded B, i.e. presuming >= 3 threads) not perform a frame
size change, because the new frame size coincides with its old frame
size, yet the linesize it expects from ff_alloc_picture() is outdated,
so that it errors out.

It is also possible for the user to use the original linesizes for
the frame after the frame that reverted back to A; this will be
accepted, yet the assumption that of all pictures are the same
will be broken, leading to segfaults.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 3 +++
 1 file changed, 3 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 31403d9acc..597ffde7f8 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -127,6 +127,9 @@  do {\
     UPDATE_PICTURE(last_picture);
     UPDATE_PICTURE(next_picture);
 
+    s->linesize   = s1->linesize;
+    s->uvlinesize = s1->uvlinesize;
+
 #define REBASE_PICTURE(pic, new_ctx, old_ctx)                                 \
     ((pic && pic >= old_ctx->picture &&                                       \
       pic < old_ctx->picture + MAX_PICTURE_COUNT) ?                           \