iter38: multi-device probe — single libva session serves all 5 codecs

Probe BOTH rkvdec and hantro-vpu at VA_DRIVER_INIT and keep their
{video,media}_fd pairs in driver_data. RequestQueryConfigProfiles
enumerates the union of supported profiles from all open fds.
RequestCreateConfig retargets driver_data->{video,media}_fd to the
device that serves the requested profile; if a switch is needed
(active fd is wrong), tears down output_pool, capture_pool, video_format
cache, and fmt_valid so the next RequestCreateContext rebuilds them
on the new device.

Profile→device map (RK3399-shaped):
  H264 / HEVC / VP9  → rkvdec
  MPEG-2 / VP8       → hantro-vpu

Honours LIBVA_V4L2_REQUEST_VIDEO_PATH / MEDIA_PATH explicit overrides
(skips alt-probe when those are set).

Closes the 'libva multi-device probe' open item from iter36/iter37
campaign-close.
This commit is contained in:
2026-05-14 18:52:12 +00:00
parent 25d3e5f06f
commit c56a77bd4c
3 changed files with 302 additions and 71 deletions
+39 -32
View File
@@ -88,6 +88,16 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
/*
* iter38: retarget the active V4L2 device to whichever physical
* decoder (rkvdec or hantro-vpu on RK3399) serves this codec profile.
* Safe no-op when the right device is already active. When a switch
* is needed, output/capture pools and the video_format cache are
* torn down so the next RequestCreateContext rebuilds them on the
* new device.
*/
(void)request_switch_device_for_profile(driver_data, profile);
if (attributes_count > V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES)
attributes_count = V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES;
@@ -139,6 +149,30 @@ VAStatus RequestDestroyConfig(VADriverContextP context, VAConfigID config_id)
return VA_STATUS_SUCCESS;
}
/*
* iter38: check whether `fmt` is supported on any of the open V4L2 device
* fds (active + the two alt fds tracked since iter38 multi-device probe).
* Tries both VIDEO_OUTPUT and VIDEO_OUTPUT_MPLANE.
*/
static bool any_fd_supports_output_format(struct request_data *driver_data,
unsigned int fmt)
{
int fds[3] = {
driver_data->video_fd,
driver_data->video_fd_rkvdec,
driver_data->video_fd_hantro,
};
int i;
for (i = 0; i < 3; i++) {
if (fds[i] < 0) continue;
if (v4l2_find_format(fds[i], V4L2_BUF_TYPE_VIDEO_OUTPUT, fmt))
return true;
if (v4l2_find_format(fds[i], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, fmt))
return true;
}
return false;
}
VAStatus RequestQueryConfigProfiles(VADriverContextP context,
VAProfile *profiles, int *profiles_count)
{
@@ -146,23 +180,13 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
unsigned int index = 0;
bool found;
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_MPEG2_SLICE) ||
v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_MPEG2_SLICE);
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_MPEG2_SLICE);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 2)) {
profiles[index++] = VAProfileMPEG2Simple;
profiles[index++] = VAProfileMPEG2Main;
}
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_H264_SLICE) ||
v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_H264_SLICE);
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_H264_SLICE);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 5)) {
profiles[index++] = VAProfileH264Main;
profiles[index++] = VAProfileH264High;
@@ -171,32 +195,15 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
profiles[index++] = VAProfileH264StereoHigh;
}
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_HEVC_SLICE) ||
v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_HEVC_SLICE);
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_HEVC_SLICE);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1))
profiles[index++] = VAProfileHEVCMain;
/* fresnel-fourier iter3: VP8 enumeration on hantro-vpu-dec */
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_VP8_FRAME) ||
v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP8_FRAME);
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_VP8_FRAME);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1))
profiles[index++] = VAProfileVP8Version0_3;
/* fresnel-fourier iter4: VP9 enumeration on rkvdec */
found = v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_VP9_FRAME) ||
v4l2_find_format(driver_data->video_fd,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP9_FRAME);
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_VP9_FRAME);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1))
profiles[index++] = VAProfileVP9Profile0;