Initial commit: testpattern → fakesink pipeline over MXL shared memory

- NodeBase, Signal, FlowDef, V210 shared headers
- testpattern node: SMPTE 75% color bars writer at 25fps
- fakesink node: non-blocking MXL reader with per-second stats
- studio-manager: FlowGraph data model, graph-driven fork/exec launcher
- mxl pinned as submodule at 0ae1dc5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
JohannesItten
2026-06-23 13:35:01 +03:00
commit ca682eaf0a
17 changed files with 1269 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# DMF Studio — AI Context
Read ARCHITECTURE.md first for the full picture. This file adds guidance specific to working in this codebase.
## Project in one sentence
Node-based media signal processing system: each node is a separate C++ process, nodes exchange video/audio via MXL shared memory, studio-manager orchestrates them, Vue.js frontend planned.
## Current state
- Core built: testpattern node (color bars writer), fakesink node (reader/logger), studio-manager (fork/exec orchestrator)
- Not built yet: real processing nodes, Vue frontend, graph.json persistence, WebSocket API
## Key conventions
- Node configuration comes from `NODE_CONFIG` env var (JSON). Never hardcode flow UUIDs.
- MXL domain comes from `MXL_DOMAIN` env var. Default: `/dev/shm/dmf-studio` (Linux) or `/tmp/dmf-studio` (macOS).
- All shared utilities live in `shared/` as header-only files. New nodes add a subdirectory under `nodes/`.
- Timing always goes through MXL time API (`mxlGetCurrentIndex`, `mxlGetNsUntilIndex`, `mxlSleepForNs`). Do not use `std::chrono::system_clock` for frame timing — MXL uses TAI.
- V210 line stride comes from `configInfo.discrete.sliceSizes[0]` after `mxlCreateFlowWriter`. Never hardcode 5120.
## What the user cares about
- Dmitry is not a very experienced C++ developer. Prefer architectural discussion before implementation.
- Keep code minimal and clear. No premature abstractions.
- When adding a new node type, follow the patterns in `nodes/testpattern/main.cpp` and `nodes/fakesink/main.cpp`.
## MXL API quick reference
```
mxlCreateInstance(domain, nullptr)
mxlCreateFlowWriter(inst, flow_def_json, nullptr, &writer, &configInfo, &created)
mxlCreateFlowReader(inst, flow_id, nullptr, &reader)
mxlFlowWriterOpenGrain(writer, index, &grain, &buf)
mxlFlowWriterCommitGrain(writer, &grain)
mxlFlowReaderGetGrain(reader, index, timeout_ns, &grain, &buf)
mxlGetCurrentIndex(&rate)
mxlGetNsUntilIndex(next_index, &rate) → ns to sleep
mxlSleepForNs(ns)
mxlIsFlowActive(inst, flow_id, &active)
mxlFlowSynchronizationGroup — for multi-input nodes (PiP)
```
## MXL error codes to handle in readers
- `MXL_STATUS_OK` — grain ready
- `MXL_ERR_TIMEOUT` — writer stalled, log and retry same index
- `MXL_ERR_OUT_OF_RANGE_TOO_LATE` — fell behind ring buffer, call `mxlGetCurrentIndex` and jump