## Iteration 38 — Phase 8 (close): Multi-device probe — 5/5 codecs in a single libva session Closes 2026-05-14, eighth campaign-day milestone. The last remaining "architectural" open item from iter37. ### Goal Before iter38, libva backend's `find_codec_device` (single-device auto-probe) tied a session to ONE physical decoder. Users had to set `LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video3 LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media1` to use rkvdec (H264/HEVC/VP9) or `…video2 …media0` to use hantro (VP8/MPEG-2). A single ffmpeg invocation could never serve all 5 codecs. iter38 makes the auto-probe path open BOTH devices and retarget on-the-fly per-config so a single libva session supports the full 5-codec set. ### Design `struct request_data` gains four fields (in addition to the existing active `video_fd` / `media_fd`): ```c int video_fd_rkvdec; int media_fd_rkvdec; int video_fd_hantro; int media_fd_hantro; ``` VA_DRIVER_INIT flow: 1. Auto-detect the primary decoder (current behaviour: prefer rkvdec, fall back to hantro). Open its `video_fd` + `media_fd`. 2. Identify the primary by `MEDIA_IOC_DEVICE_INFO::driver` name → tag the appropriate primary `*_fd_rkvdec` or `*_fd_hantro` pair. 3. Probe the OTHER known decoder via `find_decoder_device_by_driver()`. Open its fds into the unused pair. -1 if not present. 4. Skip the alt-probe when `LIBVA_V4L2_REQUEST_VIDEO_PATH` or `LIBVA_V4L2_REQUEST_MEDIA_PATH` is set (explicit single-device intent). `RequestQueryConfigProfiles` now iterates the active fd and the two alt fds via a helper `any_fd_supports_output_format()`, returning the UNION of supported profiles. `RequestCreateConfig` calls a new helper `request_switch_device_for_profile(driver_data, profile)`: - Maps profile → device kind ('r' for rkvdec / 'h' for hantro). - If the active fd is wrong, tear down `output_pool`, `capture_pool`, and `video_format` cache, then retarget `driver_data->{video,media}_fd` to the target pair. - If the required device kind wasn't probed, no-op (caller's `LIBVA_V4L2_REQUEST_VIDEO_PATH` override took precedence). RequestTerminate closes BOTH fd pairs. ### Bonus fix: iter38b bounds correction While testing iter38, VP9 disappeared from the auto-detect profile list — surfaced a LATENT off-by-one in `RequestQueryConfigProfiles`. The `profiles[]` buffer is sized by `V4L2_REQUEST_MAX_PROFILES` (11), but the bounds checks used `V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES` (10). Pre-iter38 single-device probe never returned more than 9 profiles, so the off-by-one never bit. iter38's 10-profile union pushed VP9 (the 10th profile) past the check. Fixed all bounds to use `MAX_PROFILES`. ### Result ``` $ vainfo (NO env override) v4l2-request: auto-selected codec device: /dev/video3 + /dev/media1 v4l2-request: iter38: also opened hantro-vpu decoder at /dev/video2 + /dev/media0 vainfo: Driver version: v4l2-request vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointVLD VAProfileH264Main : VAEntrypointVLD VAProfileH264High : VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointVLD VAProfileH264MultiviewHigh : VAEntrypointVLD VAProfileH264StereoHigh : VAEntrypointVLD VAProfileHEVCMain : VAEntrypointVLD VAProfileVP8Version0_3 : VAEntrypointVLD VAProfileVP9Profile0 : VAEntrypointVLD ``` 5-codec regression (NO env override, each ffmpeg invocation fresh process): | Codec | libva sha-16 | kdirect sha-16 | Match | |---|---|---|---| | H.264 | dd4f5f2d552c07bc | same | ✓ | | HEVC | 108f925bb6cbb6c9 | same | ✓ | | VP9 | cf35908ae0f9ab60 | same | ✓ | | VP8 | d3231e5b6c0ee10b | same | ✓ | | MPEG-2| 95c5905890c937d4 | same | ✓ | **5/5 PASS** in a single libva session without `LIBVA_V4L2_REQUEST_VIDEO_PATH` per codec. ### Substrate state at iter38 close - Backend fork tip `7ac934e` (iter38 + iter38b) - Kernel `linux-fresnel-fourier 7.0-14` (clean, unchanged from iter34) - Removed env knobs: VP8/MPEG-2 no longer need explicit device routing - Retained env knobs: `LIBVA_V4L2_REQUEST_VIDEO_PATH` / `MEDIA_PATH` still work for forced single-device testing ### Open items remaining (post iter38) The campaign is now at its definitive close. No urgent open items. Optional follow-ups: - Multi-context simultaneously: current design allows only one decode context at a time across devices (a device switch tears down pools). Could be expanded to per-context pools to support simultaneous mixed-codec decode. Not requested. - Sub-profile support (H264 Hi10, HEVC Main10, VP9 Profile 2): rkvdec supports these on RK3399 but the libva backend has no entries for them in pixelformat_for_profile / etc. Out of scope for this campaign. ### Memory entry `feedback_multi_device_probe_design.md` — design notes for the rkvdec+hantro dual-fd model, RequestQueryConfigProfiles union, and the MAX_PROFILES bounds-check gotcha.