From 37f02f01d930efbf0425f9eabf992df2ce38fb59 Mon Sep 17 00:00:00 2001 From: Johanness Date: Tue, 26 May 2026 01:42:44 +0300 Subject: [PATCH] docs: add build and test instructions --- README.md | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1ec355 --- /dev/null +++ b/README.md @@ -0,0 +1,187 @@ +# DMF Studio + +Node-based visual production platform for the Dynamic Media Facility architecture. + +## Prerequisites + +- CMake 3.24+ +- C++20 compiler (GCC 12+, Clang 15+) +- vcpkg (at `~/vcpkg` or set `CMAKE_TOOLCHAIN_FILE`) +- GStreamer (for MXL test tools only) + +## Build + +```bash +# Configure (from project root) +cmake -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_DOCS=OFF \ + -DBUILD_TESTS=OFF \ + -DBUILD_TOOLS=OFF \ + -DBUILD_UTILS=OFF + +# Build all +cmake --build build -j$(nproc) +``` + +Binaries end up in: +- `build/engine/dmf-studio-engine` +- `build/nodes/passthrough/dmf-node-passthrough` + +## Rebuild after changes + +```bash +# Full rebuild +cmake --build build -j$(nproc) + +# Rebuild only one target (faster) +cmake --build build -j$(nproc) --target dmf-node-passthrough +cmake --build build -j$(nproc) --target dmf-studio-engine +``` + +## Clean rebuild + +```bash +rm -rf build +# Then re-run the configure + build steps above +``` + +## Run unit tests + +```bash +build/tests/dmf-test-graph +``` + +## Test with MXL + +### 1. Create MXL domain + +```bash +mkdir -p /tmp/dmf-mxl +``` + +### 2. Start MXL test source (writes V210 video flow) + +Create a flow config file: + +```bash +cat > /tmp/v210_50p.json << 'EOF' +{ + "id": "a0000001-0000-0000-0000-000000000001", + "description": "DMF Studio test video flow", + "format": "urn:x-nmos:format:video", + "label": "DMF Studio Test Video", + "tags": { + "urn:x-nmos:tag:grouphint/v1.0": ["dmf-studio:Video"] + }, + "media_type": "video/v210", + "grain_rate": {"numerator": 50, "denominator": 1}, + "frame_width": 1920, + "frame_height": 1080, + "interlace_mode": "progressive", + "colorspace": "BT709", + "components": [ + {"name": "Y", "width": 1920, "height": 1080, "bit_depth": 10}, + {"name": "Cb", "width": 960, "height": 1080, "bit_depth": 10}, + {"name": "Cr", "width": 960, "height": 1080, "bit_depth": 10} + ] +} +EOF +``` + +Start test source (needs GStreamer + MXL tools built separately): + +```bash +mxl-gst-testsrc -d /tmp/dmf-mxl -v /tmp/v210_50p.json --pattern smpte & +``` + +Check active flows: + +```bash +mxl-info --domain /tmp/dmf-mxl +``` + +### 3. Start passthrough node + +```bash +build/nodes/passthrough/dmf-node-passthrough \ + --node-id pass1 \ + --control-port 9100 \ + --mxl-domain /tmp/dmf-mxl +``` + +Options: +- `--node-id, -n` — Unique node instance ID (required) +- `--control-port, -p` — WebSocket control port (required) +- `--mxl-domain, -d` — MXL domain path (default: `/dev/shm/mxl`) +- `--config, -c` — Node config as JSON string + +### 4. Start engine + +```bash +export DMF_STUDIO_BIN_DIR=build/nodes/passthrough +build/engine/dmf-studio-engine --port 8080 +``` + +### 5. Control via REST API + +```bash +# Add nodes +curl -X POST http://localhost:8080/api/graph/nodes \ + -H "Content-Type: application/json" \ + -d '{"type":"passthrough","id":"pass1"}' + +curl -X POST http://localhost:8080/api/graph/nodes \ + -H "Content-Type: application/json" \ + -d '{"type":"passthrough","id":"pass2"}' + +# Connect nodes (creates MXL flow between them) +curl -X POST http://localhost:8080/api/graph/edges \ + -H "Content-Type: application/json" \ + -d '{"from_node":"pass1","from_port":"video_out","to_node":"pass2","to_port":"video_in"}' + +# View graph +curl http://localhost:8080/api/graph + +# Start all nodes +curl -X POST http://localhost:8080/api/graph/start + +# Stop all nodes +curl -X POST http://localhost:8080/api/graph/stop + +# Remove node +curl -X DELETE http://localhost:8080/api/graph/nodes/pass1 + +# Remove edge +curl -X DELETE http://localhost:8080/api/graph/edges/pass1:video_out->pass2:video_in +``` + +### 6. Control node directly via WebSocket + +Connect to `ws://localhost:9100` with subprotocol `dmf-control`: + +```bash +wscat -c ws://localhost:9100 -s dmf-control +``` + +Commands: +```json +{"cmd": "add_reader", "flow_id": "", "port_id": "video_in"} +{"cmd": "add_writer", "flow_id": "", "port_id": "video_out", "flow_def": {}} +{"cmd": "remove_reader", "port_id": "video_in"} +{"cmd": "remove_writer", "port_id": "video_out"} +{"cmd": "configure", "params": {}} +{"cmd": "shutdown"} +``` + +## Project structure + +``` +libs/dmf-node/ — Node skeleton library (interface, WS control, MXL lifecycle) +libs/dmf-engine/ — Engine library (graph model, flow manager, process manager, REST API) +nodes/passthrough/ — Passthrough node (1 MXL in → 1 MXL out, memcpy) +engine/ — Engine binary +tests/ — Unit tests +```