1e9619afe8
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.
106 lines
3.1 KiB
CMake
106 lines
3.1 KiB
CMake
# 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)
|
||
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/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}
|
||
)
|
||
|
||
# dl for dlopen, pthread for future threading work.
|
||
target_link_directories(daedalus_v4l2_daemon
|
||
PRIVATE
|
||
${DAEDALUS_FOURIER_LIBRARY_DIRS}
|
||
)
|
||
|
||
target_link_libraries(daedalus_v4l2_daemon
|
||
PRIVATE
|
||
dl
|
||
pthread
|
||
# Order matters: libdaedalus_core.a first (so its undefined
|
||
# vulkan symbols register), then -lvulkan to satisfy them.
|
||
${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()
|