ampere-av1 Phase 2 step 1: third-device fd scaffolding for vpu981
RK3588 has THREE hantro-vpu instances (legacy MPEG2/VP8 at /dev/video2,
encoder at /dev/video3, vpu981 AV1 at /dev/video4). The existing
2-device probe is "RK3399-shaped knowledge" — silently picks the first
hantro-vpu and never finds vpu981.
This commit adds:
- video_fd_vpu981 + media_fd_vpu981 slots to request_data
- video_node_supports_output_fmt(): capability probe via VIDIOC_ENUM_FMT
on OUTPUT/OUTPUT_MPLANE queues
- find_decoder_device_by_driver_with_fmt(): walks /dev/media* matching
driver name AND capability filter (V4L2_PIX_FMT_AV1_FRAME for vpu981)
- 'a' kind in request_device_kind_for_profile (VAProfileAV1Profile0)
- 'a' branch in request_switch_device_for_profile
- vpu981 probe at backend init, alongside existing rkvdec + hantro
- vpu981 fd cleanup in RequestTerminate
- VAProfileAV1Profile0 → V4L2_PIX_FMT_AV1_FRAME in codec.c
Verified on ampere:
$ LIBVA_DRIVER_NAME=v4l2_request ffmpeg ... 2>&1 | grep iter38
v4l2-request: auto-selected codec device: /dev/video1 + /dev/media0
v4l2-request: iter38: also opened hantro-vpu decoder at /dev/video2 + /dev/media1
v4l2-request: ampere-av1: vpu981 AV1 decoder at /dev/video4 + /dev/media3
Three devices opened. HEVC still works (iter2 EXT_SPS_RPS probe still
triggers on rkvdec, sibling-campaign bit-perfect behaviour preserved).
Next steps: config.c advertise VAProfileAV1Profile0, surface.h add
av1 substruct, picture.c dispatch, av1.{c,h} for the codec dispatch
(~700 LoC mirroring Kwiboo v4l2_request_av1.c).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,8 @@ unsigned int pixelformat_for_profile(VAProfile profile)
|
|||||||
return V4L2_PIX_FMT_VP8_FRAME;
|
return V4L2_PIX_FMT_VP8_FRAME;
|
||||||
case VAProfileVP9Profile0:
|
case VAProfileVP9Profile0:
|
||||||
return V4L2_PIX_FMT_VP9_FRAME;
|
return V4L2_PIX_FMT_VP9_FRAME;
|
||||||
|
case VAProfileAV1Profile0:
|
||||||
|
return V4L2_PIX_FMT_AV1_FRAME;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+138
-1
@@ -325,6 +325,37 @@ static bool probe_hevc_ext_sps_rps_controls(int video_fd)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inspect a /dev/videoN's OUTPUT formats for `want_pixfmt`. Returns true
|
||||||
|
* iff at least one OUTPUT/OUTPUT_MPLANE format matches.
|
||||||
|
*
|
||||||
|
* Used to discriminate between multiple devices sharing a driver name —
|
||||||
|
* RK3588 has 3 hantro-vpu instances and only one of them is vpu981 (the
|
||||||
|
* dedicated AV1 decoder advertising V4L2_PIX_FMT_AV1_FRAME).
|
||||||
|
*/
|
||||||
|
static bool video_node_supports_output_fmt(int video_fd, uint32_t want_pixfmt)
|
||||||
|
{
|
||||||
|
struct v4l2_fmtdesc desc;
|
||||||
|
const enum v4l2_buf_type types[] = {
|
||||||
|
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||||
|
V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||||
|
};
|
||||||
|
unsigned int t, i;
|
||||||
|
|
||||||
|
for (t = 0; t < sizeof(types) / sizeof(types[0]); t++) {
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
memset(&desc, 0, sizeof desc);
|
||||||
|
desc.index = i;
|
||||||
|
desc.type = types[t];
|
||||||
|
if (ioctl(video_fd, VIDIOC_ENUM_FMT, &desc) < 0)
|
||||||
|
break;
|
||||||
|
if (desc.pixelformat == want_pixfmt)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int find_decoder_device_by_driver(const char *want_driver,
|
static int find_decoder_device_by_driver(const char *want_driver,
|
||||||
char *video_out, size_t video_out_sz,
|
char *video_out, size_t video_out_sz,
|
||||||
char *media_out, size_t media_out_sz)
|
char *media_out, size_t media_out_sz)
|
||||||
@@ -372,6 +403,65 @@ static int find_decoder_device_by_driver(const char *want_driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ampere-av1-enablement Phase 2 — like find_decoder_device_by_driver but
|
||||||
|
* additionally verifies the resolved /dev/videoN advertises `want_pixfmt`
|
||||||
|
* as an OUTPUT format. Required for RK3588 where 3 hantro-vpu instances
|
||||||
|
* share the driver name but only one is vpu981 (AV1 decoder).
|
||||||
|
*
|
||||||
|
* Walks all /dev/media* with matching driver name; takes the first hit
|
||||||
|
* whose OUTPUT formats include `want_pixfmt`. Non-matching candidates
|
||||||
|
* (encoder-only nodes, legacy hantro for MPEG2/VP8) are skipped.
|
||||||
|
*/
|
||||||
|
static int find_decoder_device_by_driver_with_fmt(const char *want_driver,
|
||||||
|
uint32_t want_pixfmt,
|
||||||
|
char *video_out,
|
||||||
|
size_t video_out_sz,
|
||||||
|
char *media_out,
|
||||||
|
size_t media_out_sz)
|
||||||
|
{
|
||||||
|
struct media_device_info info;
|
||||||
|
char path[32];
|
||||||
|
char vpath[32];
|
||||||
|
int fd, vfd, i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
snprintf(path, sizeof path, "/dev/media%d", i);
|
||||||
|
fd = open(path, O_RDWR | O_NONBLOCK);
|
||||||
|
if (fd < 0)
|
||||||
|
continue;
|
||||||
|
memset(&info, 0, sizeof info);
|
||||||
|
if (ioctl(fd, MEDIA_IOC_DEVICE_INFO, &info) != 0) {
|
||||||
|
close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(info.driver, want_driver) != 0) {
|
||||||
|
close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (find_decoder_video_node_via_topology(fd, vpath,
|
||||||
|
sizeof vpath) != 0) {
|
||||||
|
close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* Capability check: does this /dev/videoN advertise the
|
||||||
|
* codec-specific OUTPUT format? */
|
||||||
|
vfd = open(vpath, O_RDWR | O_NONBLOCK);
|
||||||
|
if (vfd < 0)
|
||||||
|
continue;
|
||||||
|
if (video_node_supports_output_fmt(vfd, want_pixfmt)) {
|
||||||
|
close(vfd);
|
||||||
|
snprintf(video_out, video_out_sz, "%s", vpath);
|
||||||
|
snprintf(media_out, media_out_sz, "%s", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
close(vfd);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int find_codec_device(char *video_out, size_t video_out_sz,
|
static int find_codec_device(char *video_out, size_t video_out_sz,
|
||||||
char *media_out, size_t media_out_sz)
|
char *media_out, size_t media_out_sz)
|
||||||
{
|
{
|
||||||
@@ -408,6 +498,8 @@ char request_device_kind_for_profile(VAProfile profile)
|
|||||||
case VAProfileMPEG2Main:
|
case VAProfileMPEG2Main:
|
||||||
case VAProfileVP8Version0_3:
|
case VAProfileVP8Version0_3:
|
||||||
return 'h';
|
return 'h';
|
||||||
|
case VAProfileAV1Profile0:
|
||||||
|
return 'a'; /* ampere-av1-enablement: vpu981 dedicated AV1 */
|
||||||
default:
|
default:
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
@@ -437,6 +529,9 @@ int request_switch_device_for_profile(struct request_data *driver_data,
|
|||||||
} else if (kind == 'h') {
|
} else if (kind == 'h') {
|
||||||
target_video = driver_data->video_fd_hantro;
|
target_video = driver_data->video_fd_hantro;
|
||||||
target_media = driver_data->media_fd_hantro;
|
target_media = driver_data->media_fd_hantro;
|
||||||
|
} else if (kind == 'a') {
|
||||||
|
target_video = driver_data->video_fd_vpu981;
|
||||||
|
target_media = driver_data->media_fd_vpu981;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -624,6 +719,8 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context)
|
|||||||
driver_data->media_fd_rkvdec = -1;
|
driver_data->media_fd_rkvdec = -1;
|
||||||
driver_data->video_fd_hantro = -1;
|
driver_data->video_fd_hantro = -1;
|
||||||
driver_data->media_fd_hantro = -1;
|
driver_data->media_fd_hantro = -1;
|
||||||
|
driver_data->video_fd_vpu981 = -1;
|
||||||
|
driver_data->media_fd_vpu981 = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* iter38: probe BOTH rkvdec and hantro-vpu so a single libva session
|
* iter38: probe BOTH rkvdec and hantro-vpu so a single libva session
|
||||||
@@ -681,6 +778,40 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void)primary_driver;
|
(void)primary_driver;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ampere-av1-enablement Phase 2 — additionally probe for
|
||||||
|
* vpu981 (RK3588's dedicated AV1 decoder). Driver name
|
||||||
|
* "hantro-vpu" alone is ambiguous on RK3588 (3 instances:
|
||||||
|
* legacy MPEG2/VP8, encoder, vpu981 AV1). Discriminate by
|
||||||
|
* V4L2_PIX_FMT_AV1_FRAME capability. If the primary or alt
|
||||||
|
* hantro happens to BE vpu981 (unlikely but possible on
|
||||||
|
* non-RK3588 boards), this probe finds it again and we just
|
||||||
|
* dedupe via the fd value.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
static char av1_video[32], av1_media[32];
|
||||||
|
if (find_decoder_device_by_driver_with_fmt(
|
||||||
|
"hantro-vpu", V4L2_PIX_FMT_AV1_FRAME,
|
||||||
|
av1_video, sizeof av1_video,
|
||||||
|
av1_media, sizeof av1_media) == 0) {
|
||||||
|
int av1_v = open(av1_video, O_RDWR | O_NONBLOCK);
|
||||||
|
int av1_m = (av1_v >= 0)
|
||||||
|
? open(av1_media, O_RDWR | O_NONBLOCK)
|
||||||
|
: -1;
|
||||||
|
if (av1_v >= 0 && av1_m >= 0) {
|
||||||
|
driver_data->video_fd_vpu981 = av1_v;
|
||||||
|
driver_data->media_fd_vpu981 = av1_m;
|
||||||
|
request_log(
|
||||||
|
"ampere-av1: vpu981 AV1 decoder "
|
||||||
|
"at %s + %s\n",
|
||||||
|
av1_video, av1_media);
|
||||||
|
} else {
|
||||||
|
if (av1_v >= 0) close(av1_v);
|
||||||
|
if (av1_m >= 0) close(av1_m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -745,9 +876,15 @@ VAStatus RequestTerminate(VADriverContextP context)
|
|||||||
close(driver_data->video_fd_hantro);
|
close(driver_data->video_fd_hantro);
|
||||||
if (driver_data->media_fd_hantro >= 0)
|
if (driver_data->media_fd_hantro >= 0)
|
||||||
close(driver_data->media_fd_hantro);
|
close(driver_data->media_fd_hantro);
|
||||||
|
if (driver_data->video_fd_vpu981 >= 0)
|
||||||
|
close(driver_data->video_fd_vpu981);
|
||||||
|
if (driver_data->media_fd_vpu981 >= 0)
|
||||||
|
close(driver_data->media_fd_vpu981);
|
||||||
/* Fall back to direct close if neither alt fd captured the active
|
/* Fall back to direct close if neither alt fd captured the active
|
||||||
* pair (env-override path). */
|
* pair (env-override path). */
|
||||||
if (driver_data->video_fd_rkvdec < 0 && driver_data->video_fd_hantro < 0) {
|
if (driver_data->video_fd_rkvdec < 0 &&
|
||||||
|
driver_data->video_fd_hantro < 0 &&
|
||||||
|
driver_data->video_fd_vpu981 < 0) {
|
||||||
if (driver_data->video_fd >= 0)
|
if (driver_data->video_fd >= 0)
|
||||||
close(driver_data->video_fd);
|
close(driver_data->video_fd);
|
||||||
if (driver_data->media_fd >= 0)
|
if (driver_data->media_fd >= 0)
|
||||||
|
|||||||
@@ -79,6 +79,20 @@ struct request_data {
|
|||||||
int video_fd_hantro;
|
int video_fd_hantro;
|
||||||
int media_fd_hantro;
|
int media_fd_hantro;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ampere-av1-enablement Phase 2 — vpu981 is a THIRD physical
|
||||||
|
* hantro-vpu instance on RK3588 (separate from the legacy MPEG2/VP8
|
||||||
|
* hantro at /dev/video2). It's the dedicated AV1 decoder at
|
||||||
|
* /dev/video4 with card name "rockchip,rk3588-av1-vpu-dec".
|
||||||
|
*
|
||||||
|
* Driver-name alone ("hantro-vpu") is ambiguous on RK3588 — three
|
||||||
|
* instances share the name. The probe discriminates by capability:
|
||||||
|
* which OUTPUT format does the device advertise? Only vpu981
|
||||||
|
* exposes V4L2_PIX_FMT_AV1_FRAME.
|
||||||
|
*/
|
||||||
|
int video_fd_vpu981;
|
||||||
|
int media_fd_vpu981;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* iter2 (ampere-kernel-decoders campaign) — per-fd probe result
|
* iter2 (ampere-kernel-decoders campaign) — per-fd probe result
|
||||||
* for the V4L2_CID_STATELESS_HEVC_EXT_SPS_{ST,LT}_RPS controls
|
* for the V4L2_CID_STATELESS_HEVC_EXT_SPS_{ST,LT}_RPS controls
|
||||||
|
|||||||
Reference in New Issue
Block a user