claude-noether 1e9619afe8 daemon: AV1 Sequence Header OBU synthesiser + unit test
V4L2 stateless AV1 passes the sequence header information as a
structured control (V4L2_CID_STATELESS_AV1_SEQUENCE) and ships
only tile-group bytes in the OUTPUT buffer.  libavcodec's AV1
decoder is full-bitstream, so the daemon needs to reconstruct
the OBU bytes the consumer parsed out before feeding the
assembled stream to libavcodec.

This commit lands the Sequence Header OBU half of that
reconstruction — av1_synth_sequence_header_obu().  Frame
Header / Frame OBU synthesisers + the integration that wires
the assembled OBUs into the decode hot path are separate
follow-on modules.

Module shape mirrors the H.264 NAL synthesiser (PR #1):

  - Public API: single function returning byte count or 0
    on overflow/invalid input.
  - Wire encoder uses the existing bitstream_writer (bsw_put_u
    is AV1's f(n); bsw_put_ue is bit-identical to AV1's uvlc;
    bsw_align_rbsp matches AV1's trailing_bits()).
  - AV1-specific helpers (leb128 size, min_bits_for, subsampling
    resolution per §5.5.2) are file-local statics.
  - No emulation prevention — AV1 uses leb128-sized OBUs for
    bitstream boundaries, not byte-pattern escapes.

Synthesis decisions for fields V4L2 doesn't carry are documented
verbatim in the file header (reduced_still_picture_header = 0;
single operating point at seq_level_idx = 13 / level 5.1;
color_description_present_flag = 0; chroma_sample_position = 0;
seq_choose_screen_detection_tools = 1; seq_choose_integer_mv = 1).

Rejection cases:
  - seq_profile > 2
  - bit_depth not in {8, 10, 12}
  - seq_profile = 1 + monochrome (4:4:4 forced colour)
  - seq_profile = 1 + bit_depth = 12 (only profile 2 allows it)
  - max_frame_{width,height}_minus_1 requiring > 16 length bits
  - out_cap too small to hold header + leb128 + payload

Each returns 0 to surface the mismatch loudly rather than emit
nonsense the libavcodec parser would reject downstream.

Unit test (test_av1_obu_synth.c, opt-in via DAEDALUS_BUILD_TESTS=ON)
exercises four cases bit-by-bit against a hand-computed reference:

  1. profile 0, 1080p, 8-bit, 4:2:0, order_hint on (7 bits),
     CDEF+restoration on — the common Pi 5 path.
  2. profile 0, 720p, 10-bit, monochrome — exercises high_bitdepth
     and the monochrome short-form color_config.
  3. profile 1 + bit_depth 12 → expects 0 (rejected).
  4. tiny out_cap → expects 0 (overflow).

All four green on hertz (aarch64 Arch, gcc Wall+Wextra+Wpedantic
clean).

This commit does not change daemon behaviour — av1_obu_synth.c is
built into the daemon binary so the symbols are reachable, but
no call site is wired yet.  Integration goes in the follow-on
DAEMON-AV1 patches that also synthesise the Frame Header OBU
and bracket the assembled OBUs with a Temporal Delimiter.

Refs reauktion/daedalus-v4l2#11 daemon-half; closes daedalus
backlog task #144.
2026-05-23 15:41:07 +02:00

daedalus-v4l2

V4L2 stateless decoder for the Raspberry Pi 5 / CM5, backed by the daedalus-fourier kernel library (VP9 + AV1 CDEF + H.264 video decode kernels on VideoCore VII compute + ARM NEON).

Status: scaffold (2026-05-18). Architecture locked per daedalus-fourier session memory; implementation not yet begun.

What this is

Sibling repo to daedalus-fourier (the kernel library; cycles 1-9 closed).

A two-piece userspace + kernel-module stack that exposes a V4L2 stateless decoder interface (/dev/videoNN) so that libva-v4l2-request-fourierfirefox-fourier / chromium-fourier can drive it the same way they drive existing hardware-decode pipelines on Pi 5 / RK3588.

+-----------------------------------------------------------+
| firefox-fourier / chromium-fourier  (existing)            |
+-----------------------------------------------------------+
| VA-API                                                    |
+-----------------------------------------------------------+
| libva-v4l2-request-fourier  (existing, sibling project)   |
+-----------------------------------------------------------+
| V4L2 stateless ioctl uAPI                                 |
+-----------------------------------------------------------+
| daedalus-v4l2 kernel module  (`kernel/`)                  |
|   - registers /dev/videoNN                                |
|   - parses V4L2 stateless ioctls (VP9/AV1/H.264 controls) |
|   - forwards bitstream + controls to userspace daemon     |
|     via chardev or netlink                                |
+-----------------------------------------------------------+
| daedalus-v4l2 userspace daemon  (`daemon/`)               |
|   - takes bitstream blobs + per-slice controls            |
|   - drives FFmpeg parsers via dlopen (Option γ)           |
|   - dispatches per-block ops via daedalus-fourier         |
|     public API (daedalus_dispatch_*)                      |
|   - posts decoded frames back to kernel module            |
+-----------------------------------------------------------+
| daedalus-fourier kernel library  (sibling project)        |
|   - exports include/daedalus.h public API                 |
|   - per-kernel CPU NEON + opportunistic V3D QPU dispatch  |
|   - 9 closed cycles across VP9, AV1 CDEF, H.264           |
+-----------------------------------------------------------+
| V3D 7.1 (Mesa userspace v3dv) + ARM NEON (BCM2712)        |
+-----------------------------------------------------------+

Why this architecture (Option B + γ + sibling)

Locked by user 2026-05-18 from 3 options in daedalus-fourier/docs/phase8_scoping.md:

  • Option B over A (userspace v4l2loopback): real /dev/videoNN, proper DRM PRIME / dmabuf for browser zero-copy.
  • Option γ: dlopen FFmpeg as parser at runtime. No vendoring, fastest to v1.
  • Sibling repo: per project_consumer_target convention, V4L2-side work lives outside daedalus-fourier so the kernel-library has a clean API boundary.

Status

Initial scaffold only. See docs/architecture.md for the deeper design and docs/roadmap.md for the sub-phase breakdown.

Repo layout

  • kernel/ — Linux kernel module (V4L2 device registration + ioctl handling + userspace chardev bridge). Out-of-tree.
  • daemon/ — userspace decoder daemon (links libdaedalus_core.a from sibling daedalus-fourier; uses dlopen for FFmpeg parser).
  • include/ — shared headers between kernel and daemon.
  • docs/ — architecture + roadmap.

License

Kernel module: GPLv2 (required for kernel-tree compatibility). Userspace daemon: BSD-2-Clause (matches daedalus-fourier).

S
Description
No description provided
Readme 686 KiB
Languages
C 97.8%
CMake 1.5%
Makefile 0.7%