forked from marfrit/libva-v4l2-request-fourier
662f8874ba
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>
76 lines
2.5 KiB
C
76 lines
2.5 KiB
C
/*
|
|
* Copyright (C) 2026 claude-noether <claude-noether@reauktion.de>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
* of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "nv15.h"
|
|
|
|
void nv15_unpack_plane_to_p010(const uint8_t *src, uint16_t *dst,
|
|
unsigned int width, unsigned int height,
|
|
unsigned int src_stride)
|
|
{
|
|
unsigned int x, y;
|
|
unsigned int dst_pitch_px = width;
|
|
|
|
for (y = 0; y < height; y++) {
|
|
const uint8_t *s = src + y * src_stride;
|
|
uint16_t *d = dst + y * dst_pitch_px;
|
|
|
|
for (x = 0; x + 4 <= width; x += 4) {
|
|
uint16_t a = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
|
|
uint16_t b = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
|
|
uint16_t c = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
|
|
uint16_t e = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
|
|
|
|
d[0] = (uint16_t)(a << 6);
|
|
d[1] = (uint16_t)(b << 6);
|
|
d[2] = (uint16_t)(c << 6);
|
|
d[3] = (uint16_t)(e << 6);
|
|
|
|
d += 4;
|
|
s += 5;
|
|
}
|
|
|
|
if (x < width) {
|
|
unsigned int rem = width - x;
|
|
uint16_t pix[4] = { 0, 0, 0, 0 };
|
|
|
|
pix[0] = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
|
|
if (rem >= 2)
|
|
pix[1] = ((uint16_t)s[1] >> 2) |
|
|
((uint16_t)(s[2] & 0x0F) << 6);
|
|
if (rem >= 3)
|
|
pix[2] = ((uint16_t)s[2] >> 4) |
|
|
((uint16_t)(s[3] & 0x3F) << 4);
|
|
if (rem >= 4)
|
|
pix[3] = ((uint16_t)s[3] >> 6) |
|
|
((uint16_t)s[4] << 2);
|
|
|
|
{
|
|
unsigned int j;
|
|
for (j = 0; j < rem; j++)
|
|
d[j] = (uint16_t)(pix[j] << 6);
|
|
}
|
|
}
|
|
}
|
|
}
|