From affb4bd12a396db2beb69eeed85724a15ec6d9c3 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Fri, 1 May 2026 12:00:00 +0000 Subject: [PATCH] DEBUG: dump VAPictureH264 raw bytes + decoded fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diagnostic-only. Investigating the observed anomaly: - V4L2 strace shows decode_params.top_field_order_cnt = 65536 on the first IDR frame submitted by mpv+ffmpeg+libva-v4l2-request - GStreamer's reference path writes 0 (spec-correct: PicOrderCnt=0 for IDR with pic_order_cnt_type=0 / pic_order_cnt_lsb=0) - Reading FFmpeg source (libavcodec/vaapi_h264.c::fill_vaapi_pic): va_pic->TopFieldOrderCnt = 0; if (pic->field_poc[0] != INT_MAX) va_pic->TopFieldOrderCnt = pic->field_poc[0]; For IDR: ff_h264_init_poc sets field_poc[0] = poc_msb + poc_lsb = 0 + 0 = 0. So FFmpeg should write 0. If FFmpeg writes 0 but fourier reads 65536, the mismatch is in the libva ABI between ffmpeg's writer and our reader. Most likely suspect: VA_PADDING_LOW size in VAPictureH264 differs between the libva headers ffmpeg+libva were built against and the headers fourier was built against, shifting struct field offsets. This patch dumps: 1. sizeof(VAPictureH264) at our reader's view 2. First 32 raw bytes of VAPicture->CurrPic 3. Field-decoded values via the .picture_id, .frame_idx, .flags, .TopFieldOrderCnt, .BottomFieldOrderCnt accessors If the raw bytes show 00 00 01 00 at offset 12 (= 65536 LE), the field offset is correct and FFmpeg actually wrote 65536 — meaning either FFmpeg has a bug, or our test scenario triggers a non-spec code path. If the raw bytes show 00 00 00 00 at offset 12 but TopFieldOrderCnt accessor returns 65536, the struct ABI is mismatched and we need to reconcile libva versions. If sizeof(VAPictureH264) prints as something other than 36 (= 4*5 + 4*VA_PADDING_LOW assuming VA_PADDING_LOW=4), the struct layout on this build differs from the documented libva-2.x layout. Removed once the source of the 65536 is identified. Signed-off-by: Markus Fritsche --- src/h264.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/h264.c b/src/h264.c index ba29c5d..34f5025 100644 --- a/src/h264.c +++ b/src/h264.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -259,6 +260,42 @@ static void h264_va_picture_to_v4l2(struct request_data *driver_data, * the OUTPUT bitstream — a hypothesis verified empirically by * running this patch and inspecting the CAPTURE buffer. */ + /* + * DEBUG INSTRUMENTATION (0014): dump the raw bytes of + * VAPicture->CurrPic plus sizeof(VAPictureH264) so we can + * tell whether the observed TopFieldOrderCnt=65536 anomaly is + * (a) at the documented byte-offset 12 (ffmpeg-side bug or + * intentional non-spec encoding) or + * (b) at a different offset (libva ABI / VA_PADDING_LOW + * mismatch between ffmpeg's writer and our reader). + * + * Documented VAPictureH264 layout (libva-2.x): + * offset 0: VASurfaceID picture_id (uint32) + * offset 4: uint32 frame_idx + * offset 8: uint32 flags + * offset 12: int32 TopFieldOrderCnt + * offset 16: int32 BottomFieldOrderCnt + * offset 20+: uint32 va_reserved[VA_PADDING_LOW] + */ + { + const unsigned char *cp = (const unsigned char *)&VAPicture->CurrPic; + char hex[32 * 3 + 1] = { 0 }; + unsigned int i; + for (i = 0; i < 32; i++) + snprintf(hex + i * 3, 4, " %02x", cp[i]); + request_log("VAPictureH264 sizeof=%zu CurrPic[0..31]:%s\n", + sizeof(VAPictureH264), hex); + request_log("VAPictureH264 CurrPic field reads: " + "picture_id=0x%08x frame_idx=%u flags=0x%x " + "TopFOC=%d BottomFOC=%d frame_num=%u\n", + (unsigned)VAPicture->CurrPic.picture_id, + (unsigned)VAPicture->CurrPic.frame_idx, + (unsigned)VAPicture->CurrPic.flags, + (int)VAPicture->CurrPic.TopFieldOrderCnt, + (int)VAPicture->CurrPic.BottomFieldOrderCnt, + (unsigned)VAPicture->frame_num); + } + decode->nal_ref_idc = nal_ref_idc; decode->frame_num = VAPicture->frame_num; decode->top_field_order_cnt = VAPicture->CurrPic.TopFieldOrderCnt;