PR #24155 opened by Kacper Michajłow (kasper93) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24155 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24155.patch
From f1d318e5eb2eb487d2be4b4b721b93ae76fd5ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Thu, 30 Jul 2026 17:29:04 +0200 Subject: [PATCH 1/2] avcodec/h264_slice: clear the ER picture when starting a second field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit h264_frame_start() clears h->er.cur_pic, and decode_nal_units() only sets it again for pictures that are not field coded, right before running error concealment. A second field goes through neither, so h->er.cur_pic keeps pointing at whatever frame coded picture the context decoded earlier. With frame threading the two fields of a pair are decoded by different contexts, so whether this triggers depends on what the context that picks up the second field decoded before, which is why the number of bogus warnings varies between runs. Signed-off-by: Kacper Michajłow <[email protected]> --- libavcodec/h264_slice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 9b5ed8f77e..a13047ffe8 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1627,6 +1627,10 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, int field = h->picture_structure == PICT_BOTTOM_FIELD; release_unused_pictures(h, 0); h->cur_pic_ptr->tf.owner[field] = h->avctx; + /* h264_frame_start(), which clears this for every other picture, is + * not called for a second field. */ + if (CONFIG_ERROR_RESILIENCE) + ff_h264_set_erpic(&h->er.cur_pic, NULL); } /* Some macroblocks can be accessed before they're available in case * of lost slices, MBAFF or threading. */ -- 2.52.0 From c3a8a223b29260dc170d41c62f9b3b33f6b97b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Sat, 15 Aug 2026 00:36:22 +0200 Subject: [PATCH 2/2] avcodec/h264_direct: do not read the other field's rows of colocated mb_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To determine whether the colocated picture is field coded, the temporal and spatial direct setup peek at sl->ref_list[1][0].parent->mb_type[mb_xy] before mb_xy has been remapped to the colocated field's parity. That row belongs to the current field's parity, while await_reference_mb_row() above waited on the parity of the referenced field, so whenever the two differ the load is unsynchronised and with frame threading can observe macroblocks of a field that is still being decoded. Every macroblock of a field picture has MB_TYPE_INTERLACED set, so checking field_picture first gives the same result in all correctly synchronized cases without touching the mb_type array. This also fixes few TSAN reported warnings. Fixes: https://trac.ffmpeg.org/ticket/10891 Signed-off-by: Kacper Michajłow <[email protected]> --- libavcodec/h264_direct.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index be388ada3a..1bc4f911ba 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -292,7 +292,8 @@ static void pred_spatial_direct_motion(const H264Context *const h, H264SliceCont return; } - if (IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (sl->ref_list[1][0].parent->field_picture || + IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL mb_y = (sl->mb_y & ~1) + sl->col_parity; mb_xy = sl->mb_x + @@ -510,7 +511,8 @@ static void pred_temp_direct_motion(const H264Context *const h, H264SliceContext await_reference_mb_row(h, &sl->ref_list[1][0], sl->mb_y + !!IS_INTERLACED(*mb_type)); - if (IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (sl->ref_list[1][0].parent->field_picture || + IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL mb_y = (sl->mb_y & ~1) + sl->col_parity; mb_xy = sl->mb_x + -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
