Files
daedalus-v4l2/daemon/CMakeLists.txt
T
marfrit dbf01eddb8 daemon: shadow_decoder wiring (PR-Q3a.1)
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>
2026-05-26 14:15:13 +02:00

117 lines
3.6 KiB
CMake
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPDX-License-Identifier: BSD-2-Clause
#
# daedalus-v4l2 userspace daemon — CMake build.
#
# Notes:
# - FFmpeg is dlopen'd at runtime (Option γ), so we link only
# -ldl + -lpthread. Headers from libavformat-dev /
# libavcodec-dev / libavutil-dev are used at compile time
# for struct definitions.
# - Strict warnings enforced.
cmake_minimum_required(VERSION 3.20)
project(daedalus_v4l2_daemon C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
add_compile_options(-Wall -Wextra -Wpedantic
-Wno-unused-parameter)
# FFmpeg headers (we dlopen the libs but include the headers for
# struct definitions). pkg-config is the canonical way.
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat libavcodec libavutil)
# daedalus-fourier — VC VII (V3D) + ARM NEON back-end kernel library.
# Linked statically. Today only the no-QPU smoke-test path is wired
# (a ctx_create_no_qpu at daemon startup, log-and-destroy at exit);
# follow-up patches (per daedalus-v4l2#11) substitute the
# `daedalus_recipe_dispatch_h264_*` family for libavcodec's per-MB
# pixel primitives, one cycle at a time.
#
# We bypass IMPORTED_TARGET and consume pkg-config's static variables
# (--static --libs path) directly so we control the link order:
# libdaedalus_core.a must precede -lvulkan because the static archive
# references vulkan symbols and the linker resolves left-to-right.
pkg_check_modules(DAEDALUS_FOURIER REQUIRED daedalus-fourier)
# daedalus-decoder — frame-major UMA H.264 decoder. Linked into the
# shadow-mode path (env DAEDALUS_SHADOW_MODE=1) and inert otherwise.
# Linked unconditionally to keep CMake configurations symmetrical
# between production and shadow-mode runs.
pkg_check_modules(DAEDALUS_DECODER REQUIRED daedalus-decoder)
find_package(Vulkan REQUIRED)
add_executable(daedalus_v4l2_daemon
src/main.c
src/ffmpeg_loader.c
src/log.c
src/parser.c
src/decoder.c
src/shadow_decoder.c
src/chardev_client.c
src/dmabuf_capture.c
src/bitstream_writer.c
src/h264_nal_synth.c
src/av1_obu_synth.c
)
target_include_directories(daedalus_v4l2_daemon
PRIVATE
src
${CMAKE_CURRENT_SOURCE_DIR}/../include
${FFMPEG_INCLUDE_DIRS}
${DAEDALUS_FOURIER_INCLUDE_DIRS}
${DAEDALUS_DECODER_INCLUDE_DIRS}
)
# dl for dlopen, pthread for future threading work.
target_link_directories(daedalus_v4l2_daemon
PRIVATE
${DAEDALUS_FOURIER_LIBRARY_DIRS}
${DAEDALUS_DECODER_LIBRARY_DIRS}
)
target_link_libraries(daedalus_v4l2_daemon
PRIVATE
dl
pthread
# Order matters for left-to-right linker resolution of
# static archives. daedalus-decoder references symbols
# from daedalus-fourier; daedalus-fourier references
# vulkan symbols. So: decoder, fourier, vulkan.
${DAEDALUS_DECODER_LIBRARIES}
${DAEDALUS_FOURIER_LIBRARIES}
Vulkan::Vulkan
)
install(TARGETS daedalus_v4l2_daemon
RUNTIME DESTINATION /usr/local/bin)
# --- Unit tests (opt-in) -------------------------------------------------
#
# DAEDALUS_BUILD_TESTS=ON enables standalone test executables that run on
# the build host (no V4L2 / FFmpeg / Vulkan dependency). Used by CI to
# gate bitstream synthesis modules against regressions.
option(DAEDALUS_BUILD_TESTS "Build daemon unit tests" OFF)
if (DAEDALUS_BUILD_TESTS)
add_executable(test_av1_obu_synth
src/test_av1_obu_synth.c
src/av1_obu_synth.c
src/bitstream_writer.c
)
target_include_directories(test_av1_obu_synth PRIVATE src)
# Test binary does not link FFmpeg / Vulkan / dl — it exercises
# pure-C encoders against in-memory inputs.
enable_testing()
add_test(NAME av1_obu_synth COMMAND test_av1_obu_synth)
endif()