The real multiplanar wedge: probe MPLANE in surface.c, add NV12 mplane

This is what was actually broken — and it's much smaller than the STUDY
guessed.

The library is in fact multiplanar-aware throughout the v4l2.c helpers
(v4l2_setup_format, v4l2_get_format, v4l2_query_buffer, v4l2_queue_buffer,
v4l2_dequeue_buffer all branch on v4l2_type_is_mplane). The whole
"context.c / picture.c are single-plane" hypothesis from STUDY.md was wrong —
they derive output_type and capture_type from
video_format->v4l2_mplane and pass them through.

The bug is upstream of all that: driver_data->video_format is set in
RequestCreateSurfaces only, and the probe there only tries
V4L2_BUF_TYPE_VIDEO_CAPTURE (single-plane). On hantro the single-plane
ENUM_FMT returns nothing, video_format stays NULL, and every subsequent
operation hits the `if (video_format == NULL) return OPERATION_FAILED`
guard at the top of context.c / buffer.c / image.c. That's exactly what
Brave's vaCreateContext failure was — not a downstream multiplanar fault,
just the format-detection short-circuit firing.

Three small changes:

- src/video.c: add an NV12 multi-plane entry next to the existing
  single-plane NV12 / Sunxi entries. Same pixelformat fourcc (S264 vs NV12
  has nothing to do with mplane), distinguished by the v4l2_mplane bit.
- src/video.h + src/video.c: video_format_find() takes a `bool mplane`
  parameter and matches both fields. Without this the single-plane and
  multi-plane NV12 entries collide on pixelformat.
- src/surface.c: the probe block now tries V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
  as a fallback after the single-plane probes return nothing. On a
  single-plane decoder the mplane probe is a no-op; on hantro it picks
  the new mplane NV12 entry, video_format gets set, and the rest of the
  library — already mplane-aware — does the right thing for OUTPUT
  S_FMT, REQBUFS, EXPBUF, QBUF, DQBUF.

Also: src/context.c: the H264 case still referenced V4L2_PIX_FMT_H264_SLICE_RAW
that we renamed in commit c1f5108. Caught now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 21:47:30 +00:00
parent 294bdc24f6
commit 53999cd154
4 changed files with 33 additions and 10 deletions
+1 -1
View File
@@ -104,7 +104,7 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
case VAProfileH264ConstrainedBaseline:
case VAProfileH264MultiviewHigh:
case VAProfileH264StereoHigh:
pixelformat = V4L2_PIX_FMT_H264_SLICE_RAW;
pixelformat = V4L2_PIX_FMT_H264_SLICE;
break;
case VAProfileHEVCMain:
+18 -6
View File
@@ -73,17 +73,29 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
if (!driver_data->video_format) {
/* Single-plane CAPTURE first (the original sunxi-cedrus path) */
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_PIX_FMT_SUNXI_TILED_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_SUNXI_TILED_NV12);
video_format = video_format_find(V4L2_PIX_FMT_SUNXI_TILED_NV12, false);
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_PIX_FMT_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_NV12);
if (video_format == NULL) {
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_PIX_FMT_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_NV12, false);
}
/* Multi-plane CAPTURE fallback (Rockchip hantro / RK3588 VDPU381) */
if (video_format == NULL) {
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
V4L2_PIX_FMT_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_NV12, true);
}
if (video_format == NULL)
return VA_STATUS_ERROR_OPERATION_FAILED;
+13 -2
View File
@@ -45,6 +45,16 @@ static struct video_format formats[] = {
.planes_count = 2,
.bpp = 16,
},
{
.description = "NV12 YUV (multi-plane)",
.v4l2_format = V4L2_PIX_FMT_NV12,
.v4l2_buffers_count = 1,
.v4l2_mplane = true,
.drm_format = DRM_FORMAT_NV12,
.drm_modifier = DRM_FORMAT_MOD_NONE,
.planes_count = 2,
.bpp = 16,
},
{
.description = "Sunxi tiled NV12 YUV",
.v4l2_format = V4L2_PIX_FMT_SUNXI_TILED_NV12,
@@ -59,12 +69,13 @@ static struct video_format formats[] = {
static unsigned int formats_count = sizeof(formats) / sizeof(formats[0]);
struct video_format *video_format_find(unsigned int pixelformat)
struct video_format *video_format_find(unsigned int pixelformat, bool mplane)
{
unsigned int i;
for (i = 0; i < formats_count; i++)
if (formats[i].v4l2_format == pixelformat)
if (formats[i].v4l2_format == pixelformat &&
formats[i].v4l2_mplane == mplane)
return &formats[i];
return NULL;
+1 -1
View File
@@ -38,7 +38,7 @@ struct video_format {
unsigned int bpp;
};
struct video_format *video_format_find(unsigned int pixelformat);
struct video_format *video_format_find(unsigned int pixelformat, bool mplane);
bool video_format_is_linear(struct video_format *format);
#endif