scaffold: CMake + API skeleton + smoke test
First code on daedalus-decoder per the Phase 1 decisions merged 2026-05-24.
Repo skeleton only — no Vulkan pipeline yet, no shaders, no libavcodec
intercept. Establishes the build shape so subsequent work has a place
to land.
Layout:
LICENSE BSD-2-Clause (matches daedalus-fourier)
.gitignore build/, CMake artefacts, *.spv
CMakeLists.txt top-level — finds daedalus-fourier
≥0.1.0 via pkg-config (per §9.6
decision: find_package, pinned to
tagged release; .pc consumed via
pkg_check_modules until we ship a
CMake config), Vulkan via
find_package, builds static lib
+ smoke test, GNUInstallDirs install
include/daedalus_decoder.h public API surface:
- daedalus_decoder_{create,destroy,
version,has_qpu}
- daedalus_decoder_set_output_format
(NV12 default, RGBA opt-in per §5)
- daedalus_decoder_append_mb +
struct daedalus_decoder_mb_input
(matches §3 per-MB descriptor)
- daedalus_decoder_flush_frame
(per-frame submit + wait)
- daedalus_decoder_export_dmabuf
(Vulkan-native VkImage export per
§9.4 decision)
Dimensions are CODED frame size
(mod-16), not displayed — caller
translates from SPS + crop offsets.
src/internal.h internal mb_desc struct (matches
shader std430 layout, to be nailed
down once shaders exist) + per-ctx
state
src/daedalus_decoder.c stub bodies:
- create/destroy with proper resource
lifecycle
- append_mb validates + writes CPU
staging buffers (no GPU yet)
- flush_frame returns -2 (not
implemented) — Phase 1 work
- export_dmabuf returns -1
- has_qpu / version diagnostics
tests/test_smoke.c link + lifecycle test: bad dims
reject, OOB MB reject, null inputs
reject, raster-order enforcement,
mid-frame format-change reject,
incomplete-frame flush reject.
On hosts without V3D7 Vulkan,
SKIPs gracefully (returns 0).
Verified on hertz (Pi 5 / V3D 7.1 / Mesa V3DV via daedalus-fourier
0.1.0):
$ cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
$ cmake --build build
$ ctest --test-dir build --output-on-failure
Test #1: smoke ... Passed
$ ./build/test_smoke
daedalus-decoder version: 0.0.1
ctx created: 1920x1088, has_qpu=1
smoke OK
Note the coded-vs-displayed dims trap: 1080p H.264 has coded height
1088 with 8 rows cropped via SPS frame_cropping_*. Header docstring
on daedalus_decoder_create() spells this out so future callers don't
hit the multiple-of-16 reject (smoke test caught it during scaffold
write).
Next: Phase 1 implementation begins — IDCT 4×4 / 8×8 frame-scaled
dispatch (reusing daedalus-fourier shaders per Appendix A), intra
prediction wavefront, reconstruct stage, NV12 output via dmabuf
export. Smoke test grows from "ctx lifecycle works" to
"I-frame-only Baseline decode bit-exact vs FFmpeg reference".
This commit is contained in:
+128
@@ -0,0 +1,128 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# daedalus-decoder — frame-level GPU H.264 decoder for V3D7 (Pi 5).
|
||||
# Phase 1 scaffold; see DESIGN.md for architecture.
|
||||
#
|
||||
# Build dependencies:
|
||||
# - daedalus-fourier ≥ 0.1.0 (kernel pack, V3D primitives + recipe layer)
|
||||
# resolved via pkg-config; install via the daedalus-fourier upstream
|
||||
# `cmake --install` rule (PR #5 made the .pc relocatable, so any
|
||||
# install prefix works as long as $PKG_CONFIG_PATH is set).
|
||||
# - Vulkan headers + libvulkan (pulled in transitively via
|
||||
# daedalus-fourier, listed here explicitly for the link order).
|
||||
#
|
||||
# Build:
|
||||
# cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
|
||||
# cmake --build build
|
||||
# ctest --test-dir build
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(daedalus-decoder
|
||||
VERSION 0.0.1
|
||||
DESCRIPTION "Frame-level GPU H.264 decoder for Raspberry Pi 5 / V3D7"
|
||||
LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
# Pi 5 is the only supported target. Other aarch64 SoCs (Pi 4 V3D4,
|
||||
# RK3588 Mali, …) might work but would need explicit substrate +
|
||||
# shader-pack validation per the daedalus-fourier architecture
|
||||
# backlog. Don't pretend to support what we haven't validated.
|
||||
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
message(WARNING
|
||||
"daedalus-decoder is designed for aarch64 (Pi 5 BCM2712 / V3D7). "
|
||||
"Build will proceed but is unlikely to function.")
|
||||
endif()
|
||||
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter)
|
||||
|
||||
# ---- Dependencies --------------------------------------------------
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# daedalus-fourier — find_package via pkg-config per the Phase 1
|
||||
# decision §9.6. Minimum version 0.1.0 (the cycle 6-9 shaders + pool
|
||||
# + recipe-flip baseline). PKG_CONFIG_PATH should point at the
|
||||
# directory holding daedalus-fourier.pc (e.g. /usr/local/lib/pkgconfig
|
||||
# or a custom install prefix).
|
||||
pkg_check_modules(DAEDALUS_FOURIER REQUIRED daedalus-fourier>=0.1.0)
|
||||
|
||||
# Vulkan — daedalus-fourier already depends on this; we add it
|
||||
# explicitly so the link order stays correct (daedalus-fourier static
|
||||
# archive contains undefined vk* symbols that the loader resolves).
|
||||
find_package(Vulkan REQUIRED)
|
||||
|
||||
# ---- Version string baked into the library ------------------------
|
||||
|
||||
# git rev tagged onto the version string for traceability; degrades
|
||||
# gracefully to bare semver if git isn't available.
|
||||
execute_process(
|
||||
COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} rev-parse --short=7 HEAD
|
||||
OUTPUT_VARIABLE DAEDALUS_DECODER_GITREV
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
if(DAEDALUS_DECODER_GITREV)
|
||||
set(DAEDALUS_DECODER_VERSION "${PROJECT_VERSION}+g${DAEDALUS_DECODER_GITREV}")
|
||||
else()
|
||||
set(DAEDALUS_DECODER_VERSION "${PROJECT_VERSION}")
|
||||
endif()
|
||||
message(STATUS "daedalus-decoder version: ${DAEDALUS_DECODER_VERSION}")
|
||||
|
||||
# ---- Library ------------------------------------------------------
|
||||
|
||||
add_library(daedalus_decoder STATIC
|
||||
src/daedalus_decoder.c
|
||||
)
|
||||
target_include_directories(daedalus_decoder
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE
|
||||
src
|
||||
${DAEDALUS_FOURIER_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_directories(daedalus_decoder
|
||||
PUBLIC
|
||||
${DAEDALUS_FOURIER_LIBRARY_DIRS}
|
||||
)
|
||||
target_link_libraries(daedalus_decoder
|
||||
PUBLIC
|
||||
# Order matters: daedalus-fourier static archive references
|
||||
# vulkan symbols; the loader needs daedalus-fourier first then
|
||||
# vulkan to resolve them.
|
||||
${DAEDALUS_FOURIER_LIBRARIES}
|
||||
Vulkan::Vulkan
|
||||
)
|
||||
target_compile_definitions(daedalus_decoder
|
||||
PRIVATE
|
||||
DAEDALUS_DECODER_VERSION="${DAEDALUS_DECODER_VERSION}"
|
||||
)
|
||||
target_compile_options(daedalus_decoder PRIVATE -O2)
|
||||
|
||||
# ---- Smoke test ---------------------------------------------------
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(test_smoke tests/test_smoke.c)
|
||||
target_link_libraries(test_smoke PRIVATE daedalus_decoder)
|
||||
target_compile_options(test_smoke PRIVATE -O2)
|
||||
|
||||
add_test(NAME smoke COMMAND test_smoke)
|
||||
|
||||
# ---- Install ------------------------------------------------------
|
||||
#
|
||||
# Library + public header. Stage 2/3 will add a pkg-config file and
|
||||
# CMake config exports once the API stabilises; pre-0.1 the scaffold
|
||||
# install just gives the static archive a home.
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS daedalus_decoder
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(FILES include/daedalus_decoder.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
Reference in New Issue
Block a user