Closes the last architectural open item from iter37 campaign-close. VA_DRIVER_INIT now opens BOTH rkvdec and hantro fds when no env override is set. RequestQueryConfigProfiles enumerates the union (via any_fd_supports_output_format helper). RequestCreateConfig calls request_switch_device_for_profile to retarget the active fd to the device that serves the profile; tears down output_pool + capture_pool + video_format cache on switch so the next RequestCreateContext rebuilds them on the new device. Bonus iter38b: fixed latent bounds-check bug in RequestQueryConfigProfiles — profile array bounds checks should use MAX_PROFILES (11), not MAX_CONFIG_ATTRIBUTES (10). Pre-iter38 single- device probes never returned more than 9 profiles so the off-by-one never bit. iter38's 10-profile union surfaced it. Result: 5/5 codecs PASS bit-exact vs kdirect with NO env override. $ vainfo (no env) v4l2-request: auto-selected: /dev/video3 + /dev/media1 v4l2-request: iter38: also opened hantro at /dev/video2 + /dev/media0 → all 10 profiles enumerated (MPEG2+H264+HEVC+VP8+VP9) Backend tip 7ac934e.
4.9 KiB
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):
int video_fd_rkvdec;
int media_fd_rkvdec;
int video_fd_hantro;
int media_fd_hantro;
VA_DRIVER_INIT flow:
- Auto-detect the primary decoder (current behaviour: prefer rkvdec, fall back to hantro). Open its
video_fd+media_fd. - Identify the primary by
MEDIA_IOC_DEVICE_INFO::drivername → tag the appropriate primary*_fd_rkvdecor*_fd_hantropair. - Probe the OTHER known decoder via
find_decoder_device_by_driver(). Open its fds into the unused pair. -1 if not present. - Skip the alt-probe when
LIBVA_V4L2_REQUEST_VIDEO_PATHorLIBVA_V4L2_REQUEST_MEDIA_PATHis 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, andvideo_formatcache, then retargetdriver_data->{video,media}_fdto the target pair. - If the required device kind wasn't probed, no-op (caller's
LIBVA_V4L2_REQUEST_VIDEO_PATHoverride 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_PATHstill 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.