forked from marfrit/libva-v4l2-request-fourier
iter39 α-31: H264 Hi10P + HEVC Main10 sub-profile support (10-bit, rkvdec NV15)
Adds VAProfileH264High10 and VAProfileHEVCMain10 to the libva-v4l2-request
backend. RK3399 rkvdec emits decoded frames as V4L2_PIX_FMT_NV15 (4 × 10-bit
values packed in 5 bytes per element); VAAPI consumers receive standard
VA_FOURCC_P010 via a new userspace unpack in copy_surface_to_image.
VP9 Profile 2 explicitly NOT added — RK3399 rkvdec kernel ctrl table
caps at V4L2_MPEG_VIDEO_VP9_PROFILE_0 (rkvdec.c::rkvdec_vp9_ctrl_descs).
Touchpoints (per Phase 5 sonnet-architect review amendments):
- include/drm_fourcc.h: define DRM_FORMAT_NV15 (vendored libdrm lacks it)
- src/nv15.{c,h}: NV15 → P010 plane unpack (LSB-first, per
Documentation/userspace-api/media/v4l/pixfmt-nv15.rst)
- src/video.c: NV15 entry in formats[] (else NULL-deref on video_format_find)
- src/codec.c: pixelformat_for_profile cases for Hi10P + Main10
- src/config.c: enumeration, validation, entrypoints, RT_FORMAT_YUV420_10
advertisement for 10-bit profiles
- src/context.c: per-profile CAPTURE pix_fmt (NV12/NV15), 10-bit synthetic
SPS (bit_depth_luma_minus8=2), video_format invalidation on bit-depth
transition (sibling to iter38 device-switch invalidation), is_10bit flag
- src/surface.c: RT_FORMAT_YUV420_10 admission, NV15 fourcc on PRIME export
- src/image.c: P010 reporting in DeriveImage + QueryImageFormats,
P010-aware sizing in CreateImage, NV15 → P010 unpack call in
copy_surface_to_image (gated on is_10bit + image.format.fourcc == P010)
- src/picture.c: 4 switch blocks route Hi10P/Main10 to existing H264/HEVC
per-codec paths
- src/request.h: MAX_PROFILES bump 11 → 13, driver_data->is_10bit flag
Scope: COPY path (vaGetImage / vaDeriveImage) only. Standard ffmpeg-vaapi
hwdownload, mpv vaapi-copy, and any consumer using vaGetImage works
end-to-end. PRIME-path consumers that only know NV12/P010 must use the
COPY path; PRIME consumers aware of NV15 (panfrost-Mesa et al.) get the
correct fourcc on RequestExportSurfaceHandle. PRIME-side P010 emission is
follow-up scope (would need DRM_FORMAT_P010 + per-plane unpack into a
GPU-accessible buffer).
Compile-tested on boltzmann (aarch64 native, gcc 15.2.1, libva 1.23.0,
libdrm 2.4.133): clean build, .so produced, 0 new warnings.
Phase 0/2 evidence: linux-mmind-v7.0 drivers/media/platform/rockchip/rkvdec.
rkvdec_h264_decoded_fmts[] and rkvdec_hevc_decoded_fmts[] both list NV15;
ctrl tables cap at HEVC MAIN_10 and H264 HIGH_422_INTRA (Hi10P < cap, not
in menu_skip_mask). image_fmt resolution (rkvdec-h264-common.c:196,
rkvdec-hevc-common.c:467) dispatches on bit_depth_luma_minus8 only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+39
-17
@@ -59,30 +59,27 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
||||
case VAProfileH264ConstrainedBaseline:
|
||||
case VAProfileH264MultiviewHigh:
|
||||
case VAProfileH264StereoHigh:
|
||||
case VAProfileH264High10:
|
||||
// FIXME
|
||||
// iter39: Hi10P routed through same H264 path; bit-depth gating
|
||||
// happens in context.c synthetic SPS and CAPTURE pix_fmt
|
||||
// selection.
|
||||
break;
|
||||
case VAProfileMPEG2Simple:
|
||||
case VAProfileMPEG2Main:
|
||||
// fresnel-fourier iter1: MPEG-2 enabled. Same shape as H.264
|
||||
// above — no profile-specific config validation in the libva
|
||||
// backend; validation happens at vaCreateContext / control
|
||||
// submission time.
|
||||
break;
|
||||
case VAProfileHEVCMain:
|
||||
// fresnel-fourier iter2: HEVC enabled. Same shape as H.264/
|
||||
// MPEG-2 above — no profile-specific config validation in the
|
||||
// libva backend; validation happens at vaCreateContext / control
|
||||
// submission time.
|
||||
case VAProfileHEVCMain10:
|
||||
// iter39: Main10 routed through same HEVC path; bit-depth
|
||||
// gating happens in context.c.
|
||||
break;
|
||||
case VAProfileVP8Version0_3:
|
||||
// fresnel-fourier iter3: VP8 enabled. Same shape as iter1+iter2
|
||||
// above — no profile-specific config validation in the libva
|
||||
// backend; validation happens at vaCreateContext / control
|
||||
// submission time.
|
||||
break;
|
||||
case VAProfileVP9Profile0:
|
||||
// fresnel-fourier iter4: VP9 Profile 0 enabled on rkvdec.
|
||||
// Same shape — no profile-specific validation here.
|
||||
// VP9 Profile 2 is NOT supported by RK3399 rkvdec (kernel ctrl
|
||||
// cap is V4L2_MPEG_VIDEO_VP9_PROFILE_0). Do not add a case for
|
||||
// VAProfileVP9Profile2 — kernel will reject.
|
||||
break;
|
||||
default:
|
||||
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||
@@ -119,7 +116,15 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
||||
*/
|
||||
config_object->pixelformat = pixelformat_for_profile(profile);
|
||||
config_object->attributes[0].type = VAConfigAttribRTFormat;
|
||||
config_object->attributes[0].value = VA_RT_FORMAT_YUV420;
|
||||
/*
|
||||
* iter39: 10-bit profiles advertise YUV420_10. ffmpeg-vaapi reads
|
||||
* this attribute on vaGetConfigAttributes and refuses surface
|
||||
* allocation if it mismatches the input bitstream's bit depth.
|
||||
*/
|
||||
if (profile == VAProfileH264High10 || profile == VAProfileHEVCMain10)
|
||||
config_object->attributes[0].value = VA_RT_FORMAT_YUV420_10;
|
||||
else
|
||||
config_object->attributes[0].value = VA_RT_FORMAT_YUV420;
|
||||
config_object->attributes_count = 1;
|
||||
|
||||
for (i = 1; i < attributes_count; i++) {
|
||||
@@ -187,17 +192,22 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
|
||||
}
|
||||
|
||||
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_H264_SLICE);
|
||||
if (found && index < (V4L2_REQUEST_MAX_PROFILES - 5)) {
|
||||
if (found && index < (V4L2_REQUEST_MAX_PROFILES - 6)) {
|
||||
profiles[index++] = VAProfileH264Main;
|
||||
profiles[index++] = VAProfileH264High;
|
||||
profiles[index++] = VAProfileH264ConstrainedBaseline;
|
||||
profiles[index++] = VAProfileH264MultiviewHigh;
|
||||
profiles[index++] = VAProfileH264StereoHigh;
|
||||
/* iter39: Hi10P on rkvdec (NV15 CAPTURE, bit_depth=10). */
|
||||
profiles[index++] = VAProfileH264High10;
|
||||
}
|
||||
|
||||
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_HEVC_SLICE);
|
||||
if (found && index < (V4L2_REQUEST_MAX_PROFILES - 1))
|
||||
if (found && index < (V4L2_REQUEST_MAX_PROFILES - 2)) {
|
||||
profiles[index++] = VAProfileHEVCMain;
|
||||
/* iter39: Main10 on rkvdec (NV15 CAPTURE). */
|
||||
profiles[index++] = VAProfileHEVCMain10;
|
||||
}
|
||||
|
||||
found = any_fd_supports_output_format(driver_data, V4L2_PIX_FMT_VP8_FRAME);
|
||||
if (found && index < (V4L2_REQUEST_MAX_PROFILES - 1))
|
||||
@@ -225,7 +235,9 @@ VAStatus RequestQueryConfigEntrypoints(VADriverContextP context,
|
||||
case VAProfileH264ConstrainedBaseline:
|
||||
case VAProfileH264MultiviewHigh:
|
||||
case VAProfileH264StereoHigh:
|
||||
case VAProfileH264High10:
|
||||
case VAProfileHEVCMain:
|
||||
case VAProfileHEVCMain10:
|
||||
case VAProfileVP8Version0_3:
|
||||
case VAProfileVP9Profile0:
|
||||
entrypoints[0] = VAEntrypointVLD;
|
||||
@@ -281,7 +293,17 @@ VAStatus RequestGetConfigAttributes(VADriverContextP context, VAProfile profile,
|
||||
for (i = 0; i < attributes_count; i++) {
|
||||
switch (attributes[i].type) {
|
||||
case VAConfigAttribRTFormat:
|
||||
attributes[i].value = VA_RT_FORMAT_YUV420;
|
||||
/*
|
||||
* iter39: 10-bit profiles publish YUV420_10. Profile-
|
||||
* less query (this is invoked from vaGetConfigAttributes
|
||||
* before vaCreateConfig) routes off the `profile` arg
|
||||
* directly — same gating as RequestCreateConfig.
|
||||
*/
|
||||
if (profile == VAProfileH264High10 ||
|
||||
profile == VAProfileHEVCMain10)
|
||||
attributes[i].value = VA_RT_FORMAT_YUV420_10;
|
||||
else
|
||||
attributes[i].value = VA_RT_FORMAT_YUV420;
|
||||
break;
|
||||
default:
|
||||
attributes[i].value = VA_ATTRIB_NOT_SUPPORTED;
|
||||
|
||||
Reference in New Issue
Block a user