From c036a44f98189777ef0dfed368d5604e7ad4c6d2 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Mon, 4 May 2026 18:34:50 +0000 Subject: [PATCH] image: fully populate VAImageFormat per VAAPI spec for NV12 QueryImageFormats and DeriveImage previously set only .fourcc and left byte_order, bits_per_pixel, depth, and color masks zero (uninitialized in the caller's buffer). VAAPI consumers that read these fields (FFmpeg's hwcontext_vaapi.c::vaapi_init_pixfmt, intel-vaapi-driver test paths) inherit caller-stack garbage with non-deterministic behavior. Cross-reference: Mesa's gallium/frontends/va/image.c and intel-vaapi-driver's i965_drv_video.c both publish NV12 with byte_order=VA_LSB_FIRST and bits_per_pixel=12. We now match. For YUV formats, depth/red_mask/green_mask/blue_mask/alpha_mask are not meaningful (RGB-bitlayout-only fields); leave them zeroed via memset. Audit context: 2026-05-04 cross-reference of all libva entry points Firefox 150 calls vs our backend implementations. The SEPARATE_LAYERS fix (commit ac891a0) cleared the load-bearing bug; this fixes a latent uninitialized-field issue that was masked by mpv's tolerance. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/image.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/image.c b/src/image.c index cd8d9d2..eb901f0 100644 --- a/src/image.c +++ b/src/image.c @@ -198,7 +198,11 @@ VAStatus RequestDeriveImage(VADriverContextP context, VASurfaceID surface_id, return status; } + /* Fully populate VAImageFormat to match QueryImageFormats output. */ + memset(&format, 0, sizeof(format)); format.fourcc = VA_FOURCC_NV12; + format.byte_order = VA_LSB_FIRST; + format.bits_per_pixel = 12; status = RequestCreateImage(context, &format, surface_object->width, surface_object->height, image); @@ -221,7 +225,25 @@ VAStatus RequestQueryImageFormats(VADriverContextP context, VAImageFormat *formats, int *formats_count) { request_log("ENTER RequestQueryImageFormats\n"); + + /* + * Populate the VAImageFormat fully per VAAPI spec for NV12 — + * not just .fourcc. Consumers (FFmpeg's hwcontext_vaapi, mpv, + * Firefox) read .byte_order and .bits_per_pixel; leaving them + * uninitialized inherits whatever caller-stack garbage is in + * the buffer and produces non-deterministic behavior. Reference: + * Mesa's gallium/frontends/va/image.c::vlVaQueryImageFormats and + * intel-vaapi-driver's i965_drv_video.c — both publish NV12 + * with byte_order=VA_LSB_FIRST and bits_per_pixel=12. + * + * For YUV formats, depth/red_mask/green_mask/blue_mask/alpha_mask + * are not meaningful (those describe RGB bit layouts); leave them + * zeroed via memset before populating. + */ + memset(&formats[0], 0, sizeof(formats[0])); formats[0].fourcc = VA_FOURCC_NV12; + formats[0].byte_order = VA_LSB_FIRST; + formats[0].bits_per_pixel = 12; *formats_count = 1; return VA_STATUS_SUCCESS;