iter4 Phase 6: 4 commits landed (Z+A+B+C), ffmpeg-vaapi VP9 decode PASS
Fork at marfrit/libva-multiplanar tip beaa914: - Z (7f8fa93) device-path auto-detect via media controller topology; walk /dev/media*, MEDIA_IOC_DEVICE_INFO match, MEDIA_IOC_G_TOPOLOGY -> MEDIA_INTF_T_V4L_VIDEO -> resolve via /sys/dev/char. LIBVA_V4L2_REQUEST_NO_AUTODETECT=1 escape hatch. - A (16b3973) src/config.c VP9 enumeration + dispatch + entrypoints. - B (406d08e) NEW src/vp9.c (~750 LOC: VPX rac + inv_map_table + uncompressed-header partial parser + compressed-header parser + vp9_set_controls) + src/vp9.h + meson.build + context.h (persistent vp9_lf state for Phase 5 C2) + surface.h (params.vp9 union extension). - C (beaa914) src/picture.c VP9 dispatcher + 2 buffer-type cases. NO Commit D — buffer.c allow-list already permissive for VP9's 3 buffer types (Picture, Slice, SliceData; all in iter3 baseline). Phase 5 amendments all in code: C1 no-XOR direct, C2 persistent vp9_lf with VP9 spec defaults, C3 out_reference_mode parameter, C4 NO_AUTODETECT escape, S4 uv_mode memcpy omitted. Plan amendment to Commit Z section in phase4_iter4_plan.md documents the canonical media-topology approach (replacing the original /dev/video* walk). Verification empirically on fresnel: - Criterion 1: vainfo enumerates VAProfileVP9Profile0 alongside H.264 + HEVC under auto-detect rkvdec. - Criterion 2 (implicit via successful ffmpeg run). - Criterion 3: ffmpeg-vaapi VP9 5-frame decode exit 0 at 0.307x speed, no ioctl errors. - Criterion 4: deferred to Phase 7 verification. - Criterion 5: rkvdec codecs work without env override; hantro (MPEG-2/VP8) still need env override per iter4-B1 backlog. Open iter4 backlog: B1 (multi-decoder dispatch refactor), B2 (mpv-vaapi Could-not-create-device — ffmpeg-vaapi works fine through same backend, mpv does not), Q6 (per-segment ALT_Q mapping for non-BBB), COLOR_RANGE (VAAPI gap). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+32
-43
@@ -391,70 +391,59 @@ vp9_parse_uncompressed_header_lf_quant(
|
||||
|
||||
iter4 implements as 5 commits (mitigation B + iter3-style ABCD):
|
||||
|
||||
### Commit Z — `src/request.c`: device-path enumeration (mitigation B)
|
||||
### Commit Z — `src/request.c`: device-path auto-detect via media-controller topology (mitigation B, canonical form)
|
||||
|
||||
Replace hardcoded `/dev/video0` + `/dev/media0` defaults with walk-and-pick-first-known-decoder:
|
||||
**Approach correction (post-implementation user redirect)**: the original plan walked `/dev/video0..15` + matched by `VIDIOC_QUERYCAP` driver name, then paired media node via a separate scan. This is brittle: dependence on enumeration order + assumption that video↔media pairing follows /dev/* numbering. The canonical v4l2-request discovery path drives discovery from the media controller graph instead (which is what FFmpeg's v4l2-request does):
|
||||
|
||||
```c
|
||||
static int find_codec_device(char video_path[32], char media_path[32])
|
||||
{
|
||||
static const char * const known_drivers[] = {
|
||||
"rkvdec", "hantro-vpu", "cedrus", "sun4i_csi", NULL
|
||||
};
|
||||
char path[32];
|
||||
struct v4l2_capability caps;
|
||||
int fd, i;
|
||||
const char * const *kd;
|
||||
/* Algorithm:
|
||||
* 1. Walk /dev/media0..15. MEDIA_IOC_DEVICE_INFO names the driver.
|
||||
* Match against {rkvdec, hantro-vpu, cedrus, sun4i_csi}.
|
||||
* 2. MEDIA_IOC_G_TOPOLOGY enumerates the entity/interface graph.
|
||||
* The MEDIA_INTF_T_V4L_VIDEO interface carries major:minor of
|
||||
* the V4L2 video node owned by THIS media controller — paired
|
||||
* by the kernel, NOT by /dev/* enumeration order.
|
||||
* 3. Resolve major:minor to /dev/videoN via /sys/dev/char/<M>:<N>
|
||||
* (the kernel's char-device sysfs symlink whose basename is
|
||||
* the device node name).
|
||||
*/
|
||||
static int find_codec_device(char *video_out, size_t video_out_sz,
|
||||
char *media_out, size_t media_out_sz);
|
||||
static int find_video_node_via_topology(int media_fd, char *video_out, size_t out_sz);
|
||||
static int resolve_dev_node(uint32_t major, uint32_t minor, char *out, size_t out_sz);
|
||||
```
|
||||
|
||||
/* Walk /dev/video0..15 */
|
||||
for (i = 0; i < 16; i++) {
|
||||
snprintf(path, sizeof path, "/dev/video%d", i);
|
||||
fd = open(path, O_RDWR | O_NONBLOCK);
|
||||
if (fd < 0) continue;
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == 0) {
|
||||
for (kd = known_drivers; *kd; kd++) {
|
||||
if (strcmp((char *)caps.driver, *kd) == 0) {
|
||||
strncpy(video_path, path, 32);
|
||||
/* Match media device by driver name */
|
||||
find_media_for_driver((char *)caps.driver, media_path);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
In `RequestInit`:
|
||||
|
||||
/* In RequestInit (Phase 5 C4 amendment — escape hatch for legacy callers): */
|
||||
```c
|
||||
if (getenv("LIBVA_V4L2_REQUEST_NO_AUTODETECT")) {
|
||||
/* Skip walk; old hardcoded behavior. Lets test automation that
|
||||
* relied on /dev/video0 opt out of the new auto-detect logic. */
|
||||
video_path = "/dev/video0";
|
||||
video_path = "/dev/video0"; /* legacy escape hatch */
|
||||
media_path = "/dev/media0";
|
||||
} else {
|
||||
video_path = getenv("LIBVA_V4L2_REQUEST_VIDEO_PATH");
|
||||
if (video_path == NULL) {
|
||||
static char auto_video[32], auto_media[32];
|
||||
if (find_codec_device(auto_video, auto_media) == 0) {
|
||||
if (find_codec_device(auto_video, sizeof auto_video,
|
||||
auto_media, sizeof auto_media) == 0) {
|
||||
video_path = auto_video;
|
||||
if (getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH") == NULL)
|
||||
media_path = auto_media;
|
||||
auto_media_set = true;
|
||||
request_log("auto-selected codec device: %s + %s\n",
|
||||
video_path, media_path);
|
||||
auto_video, auto_media);
|
||||
} else {
|
||||
video_path = "/dev/video0"; /* fall back to legacy default */
|
||||
video_path = "/dev/video0";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`find_media_for_driver` walks `/dev/media0..15`, opens each, calls `MEDIA_IOC_DEVICE_INFO`, returns the path whose `driver` field matches. Phase 3 baseline confirmed `media0 ↔ rkvdec` and `media1 ↔ hantro-vpu` on 7.0.
|
||||
Predicted +152 LOC, 1 file modified. Build target after Commit Z: `vainfo` (no env) lists the auto-selected decoder's profiles, paired correctly via topology graph. Independent of VP9 — can be tested + merged before Commit A.
|
||||
|
||||
Predicted +35 LOC, 1 file modified. Build target after Commit Z: `vainfo` (no env override) lists the auto-selected decoder's profiles. Independent of VP9 work — can be tested + merged before Commit A.
|
||||
**End-user UX gap (documented, NOT fixed in iter4)**: backend opens ONE codec device at init. If user wants the OTHER decoder (default selects rkvdec; user wants hantro for MPEG-2/VP8), they still need env override. Aggregating BOTH decoders simultaneously requires multi-fd dispatch refactor; out of iter4 scope, cross-cutting backlog item iter4-B1.
|
||||
|
||||
**End-user UX gap (documented, NOT fixed in iter4)**: backend opens ONE codec device at init. If user wants the OTHER decoder (e.g., default selects rkvdec but user wants hantro for MPEG-2/VP8), they still need env override. Aggregating BOTH decoders simultaneously requires a deeper refactor (multi-fd dispatch); out of iter4 scope, cross-cutting backlog item iter4-B1.
|
||||
**Verified on fresnel `7.0.0-fresnel-fourier` post-Phase-6**:
|
||||
- `vainfo` (no env) → `auto-selected codec device: /dev/video1 + /dev/media0`, enumerates H.264×5 + HEVCMain (rkvdec) — pair came from topology graph, not from /dev/* numbering.
|
||||
- `vainfo NO_AUTODETECT=1` → empty list (legacy /dev/video0 = rga).
|
||||
- `vainfo` with explicit `/dev/video3` + `/dev/media1` → MPEG-2×2 + VP8.
|
||||
|
||||
### Commit A — `src/config.c`: VP9 enumeration + dispatch + entrypoints
|
||||
|
||||
|
||||
Reference in New Issue
Block a user