0de0288dce
Brings daedalus_v4l2 from "standalone test client" to "VAAPI-
discoverable decoder" by adding the surface formats and
media-controller plumbing that libva-v4l2-request-fourier
(sibling repo) requires.
libva-v4l2-request-fourier patches (pushed separately):
- b5b3acf: daedalus_v4l2 added to known_decoder_drivers
- 2146341: meson option gate
This commit (daedalus-v4l2 side, 3 production changes):
1. V4L2_PIX_FMT_NV12 (single-plane) on CAPTURE
- Added to daedalus_capture_formats[] alongside NV12M + P010
- daedalus_fill_capture_fmt handles num_planes=1 case
(sizeimage = W*H*3/2, bytesperline = W)
- daemon pack_nv12_single_to_plane: Y at base+0,
interleaved CbCr at base+(stride*H); same byte content
as NV12M two-plane, different layout
- Required because libva-v4l2-request-fourier's video.c
only knows non-multi-plane NV12 (it advertises
v4l2_mplane=true but uses the single-plane fourcc).
- Verified byte-exact via test_m2m_stream against
ffmpeg -pix_fmt nv12 reference (VP9 1080p 10 frames,
31 MB).
2. V4L2 Request API media ops
- daedalus_media_ops = { vb2_request_validate,
v4l2_m2m_request_queue } assigned to mdev.ops before
media_device_init.
- Without this, MEDIA_IOC_REQUEST_ALLOC returned
-ENOTTY and no VAAPI consumer could allocate a
media_request.
3. Stateless control registration via v4l2_ctrl_new_custom
- Switched from v4l2_ctrl_new_std_compound(NULL p_def)
to v4l2_ctrl_new_custom — pattern rkvdec/cedrus/
hantro use. Adds a no-op s_ctrl callback.
Verification (hertz, Pi 5, 6.12.75+rpt-rpi-2712):
LibVA trace through `ffmpeg -hwaccel vaapi`:
vaInitialize / Profiles / Entrypoints / CreateConfig /
QuerySurfaceAttributes / CreateSurfaces / CreateContext
(cap_pool: 24 slots, 1 plane each) / CreateBuffer
(slice + picture params) / MEDIA_IOC_REQUEST_ALLOC
— all succeed.
Standalone NV12 decode path:
test_m2m_stream vp9_1080_stream.ivf out.nv12 1920 1080 vp9 nv12
→ 10/10 frames, byte-exact vs ffmpeg -pix_fmt nv12
vainfo (via libva-v4l2-request-fourier with our driver):
7 VAProfile entries with VAEntrypointVLD
(H264 Main/High/CBaseline/MultiviewHigh/StereoHigh,
VP9Profile0, AV1Profile0)
What's NOT here (Phase 8.12):
The libva trace stops at VIDIOC_S_EXT_CTRLS returning
EINVAL when populating V4L2_CID_STATELESS_VP9_FRAME on
the request. The compound-control payload validation
against the kernel's expected struct shape rejects.
This isn't a "missing line" fix — it needs proper
stateless control plumbing (the SPS/PPS/SliceParams
get_dims, validate, default-value paths that in-tree
rkvdec/cedrus/hantro implement to satisfy v4l2-core's
std_validate). Documented as Phase 8.12 scope.
The shipped integration is itself a meaningful deliverable:
all the framework scaffolding is in place; the remaining
gap is well-characterised and bounded.
See docs/phase_8_10_11_closure.md for the full trace
analysis + next-phase plan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
daemon/ — daedalus-v4l2 userspace decoder daemon
Userspace daemon that:
- Connects to the kernel module's chardev
- Receives bitstream + V4L2 control blobs
- Parses bitstream via dlopen'd FFmpeg
- Dispatches per-block work via
daedalus_dispatch_*from siblingdaedalus-fourier - Returns decoded frames to kernel
Status
Scaffold only. Phase 8.3 not yet started.
Build dependencies (planned)
- libdaedalus_core.a from sibling daedalus-fourier (static link)
- FFmpeg dev headers (for AVPacket/AVCodec interface types) + runtime FFmpeg .so (loaded via dlopen)
- libv4l2 (for V4L2 control struct definitions)
- pthread
Build (when implemented)
mkdir build && cd build
cmake .. -DDAEDALUS_FOURIER_DIR=/path/to/daedalus-fourier
make
Layout (planned)
CMakeLists.txtsrc/main.c— event loop, chardev connectionsrc/parser.c— FFmpeg dlopen wrapper + per-codec dispatchsrc/decode_vp9.c,src/decode_av1.c,src/decode_h264.c— per-codec block walkerssrc/frame_io.c— frame allocation, return to kernel
License
BSD-2-Clause (matches daedalus-fourier sibling).
Phase 8.3 starting point
A standalone program that:
- Opens a .ivf or .mp4
- Pulls codec packets via dlopen'd avformat
- Calls dlopen'd avcodec to parse (without decoding)
- Walks the block-level metadata
- Validates output structure
No kernel involvement yet — just confirm the parse path works.