From: Markus Fritsche Date: 2026-05-01 Subject: [PATCH] DEBUG: dump VAPictureH264 raw bytes + decoded fields 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 --- --- a/src/h264.c 2026-05-01 22:56:42.656744048 +0000 +++ b/src/h264.c 2026-05-02 00:00:00.000000000 +0000 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -259,6 +259,42 @@ * 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;