PR #24138 opened by ffmpeg-devel
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24138
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24138.patch

**Backport:** https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23963

Fixes: 
https://fate.ffmpeg.org/report.cgi?slot=x86_64-archlinux-gcc-threads-8&time=20260730105059


From 24abbbe95a9fa68b0e55b1af0e18b57ffa90c4dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Thu, 30 Jul 2026 17:25:52 +0200
Subject: [PATCH 1/2] avcodec/h264_direct: move check before loading things

(cherry picked from commit 029c80900e2b92a8495e36aa19d7fac9c55b8482)
---
 libavcodec/h264_direct.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c
index 8f07981130..4efb69793c 100644
--- a/libavcodec/h264_direct.c
+++ b/libavcodec/h264_direct.c
@@ -181,13 +181,13 @@ void ff_h264_direct_ref_list_init(const H264Context 
*const h, H264SliceContext *
 static void await_reference_mb_row(const H264Context *const h, H264Ref *ref,
                                    int mb_y)
 {
+    if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_FRAME))
+        return;
+
     int ref_field         = ref->reference - 1;
     int ref_field_picture = ref->parent->field_picture;
     int ref_height        = 16 * h->mb_height >> ref_field_picture;
 
-    if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_FRAME))
-        return;
-
     /* FIXME: It can be safe to access mb stuff
      * even if pixels aren't deblocked yet. */
 
-- 
2.52.0


From 33cba6bd62b34ede112c9355fcd9b0a61260be8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Thu, 30 Jul 2026 17:27:09 +0200
Subject: [PATCH 2/2] avcodec/h264_direct: await both fields of a colocated
 field pair
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When a frame coded picture uses a complementary field pair as its
colocated picture, ff_h264_direct_ref_list_init() selects the field whose
POC is closest to the current one and stores it in col_parity. The direct
mode setup then remaps mb_xy to that parity and reads the colocated
mb_type, motion_val and ref_index from it.

await_reference_mb_row() waits on the field given by "ref_field_picture &&
ref_field", which is 1 for any such reference, since the pair is
referenced as a frame and ref->reference is 3. Only the bottom field is
therefore awaited, while the data is just as likely to be read from the
top one. With frame threading the two fields are decoded by different
threads, so the colocated data can be read while the field it belongs to
is still being decoded, yielding stale motion vectors and a corrupt
frame. await_references() already handles the same case correctly for
motion compensation.

Fixes sporadic failures of fate-h264-conformance-cabac_mot_picaff0_full,
where display frame 14.

Signed-off-by: Kacper Michajłow <[email protected]>
(cherry picked from commit 274cb6731bd204e9537a7e588d4a3436fdf51b93)
---
 libavcodec/h264_direct.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c
index 4efb69793c..f868adbee2 100644
--- a/libavcodec/h264_direct.c
+++ b/libavcodec/h264_direct.c
@@ -187,14 +187,19 @@ static void await_reference_mb_row(const H264Context 
*const h, H264Ref *ref,
     int ref_field         = ref->reference - 1;
     int ref_field_picture = ref->parent->field_picture;
     int ref_height        = 16 * h->mb_height >> ref_field_picture;
+    int row               = FFMIN(16 * mb_y >> ref_field_picture, ref_height - 
1);
 
     /* FIXME: It can be safe to access mb stuff
      * even if pixels aren't deblocked yet. */
 
-    ff_thread_await_progress(&ref->parent->tf,
-                             FFMIN(16 * mb_y >> ref_field_picture,
-                                   ref_height - 1),
+    ff_thread_await_progress(&ref->parent->tf, row,
                              ref_field_picture && ref_field);
+
+    /* A frame references a field pair as a whole, so the wait above covers
+     * its bottom field only, while the colocated data is read from the field
+     * selected by col_parity. The two are decoded by different threads. */
+    if (ref_field_picture && !FIELD_PICTURE(h))
+        ff_thread_await_progress(&ref->parent->tf, row, 0);
 }
 
 static void pred_spatial_direct_motion(const H264Context *const h, 
H264SliceContext *sl,
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to