dbf01eddb8
Toolchain plumbing for the upcoming daedalus-decoder shadow-mode
path. Production behaviour is unchanged.
What lands here:
1. CMake links libdaedalus_decoder via pkg-config. Static archive,
so no .so dependency change in the daemon's link map.
2. ffmpeg_loader resolves ff_h264_set_mb_inspect_cb NULL-tolerantly.
Stock libavcodec lacks the symbol (logged as INFO at startup);
the marfrit-packages ffmpeg-v4l2-request-fourier fork's 0016
patch exports it. The shadow path activates only when both
env DAEDALUS_SHADOW_MODE=1 AND the symbol resolves.
3. New shadow_decoder.[ch] module:
- shadow_decoder_create() gates on env + symbol presence,
returns NULL in production state (the common case).
- shadow_decoder_install_cb() registers a per-MB callback on
the H.264 AVCodecContext; lazily-created daedalus_decoder
context will pick up dimensions from the first AVFrame.
- shadow_decoder_on_frame() logs per-frame MB-observed count.
Every entry point is NULL-safe so decoder.c stays clean of
conditionals.
4. decoder.{c,h} grow a `struct shadow_decoder *shadow` field on
daedalus_decoder. Install hook fires once per H.264 codec open;
frame hook fires after each successful avcodec_receive_frame.
PR-Q3a.1 scope ENDS here. The callback just counts MBs; no
daedalus_decoder_append_mb or flush_frame yet. Real-coeffs / edges
extraction needs the patched FFmpeg source-tree headers
(DAEDALUS_FFMPEG_SRC) to introspect H264Context internals — that
lands in PR-Q3a.2.
dejavu-check: this path is daedalus-decoder's frame-major UMA
dispatch architecture (one cmdbuf per frame, one submit) running
alongside libavcodec's reference decode for validation. It is NOT
per-kernel libavcodec function-pointer substitution. No new
libavcodec patches; the existing 0016 callback is the only intercept
point.
Verified on hertz:
- Build: clean, libdaedalus_decoder.a linked.
- Disabled state (env unset OR symbol absent): no shadow log
lines, daemon init continues normally, INFO logs
"libavcodec lacks ff_h264_set_mb_inspect_cb (stock build,
no daedalus-fourier 0016 patch) — shadow-mode unavailable".
- Enabled state would require ffmpeg-v4l2-request-fourier .deb
rebuilt with patches 0016/0017 deployed to hertz (current .deb
release 10 predates them). That's a deployment task, separate
from this PR.
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.