Commit graph

10 commits

Author SHA1 Message Date
Claude
a61e385693 feat(deltacast): replace per-port bridges with shared multi-port daemon
The old architecture spawned one deltacast-capture per recorder port; each
called VHD_OpenBoardHandle, triggering a BufMngr.c:781 OOB fault in the
delta_x300 kernel driver whenever two opens raced.

Fix: a single deltacast-bridge daemon opens the board once, opens RX
streams for all requested ports concurrently, and writes each port's
video/audio to named FIFOs (/dev/shm/deltacast/video-<N>.fifo,
/dev/shm/deltacast/audio-<N>.fifo). Capture sidecars read from those
FIFOs directly — no board handle, no race, no flock.

Changes:
  services/capture/deltacast-bridge/main.c
    - Complete rewrite: --ports csv arg, board opened once, one
      video+audio thread pair per port, FIFO paths per port, format
      JSON emitted per port on signal lock, SIGTERM clean shutdown.
    - flock/serialize logic removed (no longer needed).
    - --port single-port compat alias retained.
  services/capture/deltacast-bridge/CMakeLists.txt
    - Rename target deltacast-capture -> deltacast-bridge.
    - POST_BUILD symlink deltacast-capture -> deltacast-bridge for compat.
  services/capture/src/capture-manager.js
    - deltacast _buildInputArgs: remove bridge spawn; wait up to 30s
      for FIFOs to exist (bridge may be starting); return rawvideo +
      s16le FIFO inputArgs. bridgeProcess=null.
    - audioMap: keyed on sourceType instead of bridgeProcess (both
      inputs are always present for deltacast).
    - Remove readFirstStderrLine helper (no longer needed).
    - Remove bridgeProcess.stdout.pipe / processes.bridge stop signal.
  services/node-agent/index.js
    - Add import spawn for bridge daemon management.
    - Add startDeltacastBridge / stopDeltacastBridge: host-process
      lifecycle for the shared bridge, ref-counted by sidecar count.
    - handleSidecarStart: on deltacast, increment counter + start bridge;
      decrement on container create/start failure.
    - handleSidecarStop: decrement counter; stop bridge when last sidecar.
    - _containerSourceType map tracks containerId->sourceType for stop.
    - Old acquireDcLock mutex retained but no longer called.
2026-06-02 00:21:52 +00:00
cad1e52c38 fix(deltacast-bridge): reset signal-wait deadline AFTER acquiring flock
The signal timeout deadline was set at process start before waiting for
the flock. Bridges queued behind earlier ports waited minutes for the
lock, then found their 30s signal deadline had already expired before
they even opened the board, causing false "no signal" failures on ports
that have live signal.

Fix: move clock_gettime deadline initialisation to AFTER flock acquired
and board opened, so the full sig_timeout is always available for signal
detection regardless of queue wait time.
2026-06-01 19:32:01 -04:00
7d704d3af3 fix(deltacast-bridge): serialize VHD_OpenBoardHandle via flock to prevent BufMngr wedge
Concurrent VHD_OpenBoardHandle calls from multiple capture sidecars
trigger delta_x300 BufMngr.c:781 array-index-out-of-bounds, wedging all
RX channels until the module is reloaded. The node-agent stagger only
delays container start — the bridge binary starts ~2s later and can still
race. This fix acquires an exclusive flock on /dev/shm/deltacast/bridge.lock
before VHD_OpenBoardHandle and holds it until signal lock succeeds (then
adds a 4s settle before releasing so the board's buffer queues stabilize).
Lock is released on signal failure too so the next bridge is never
permanently blocked. All 8 channels can now start safely by serializing
through the same lock file mounted into every sidecar.
2026-06-01 18:54:00 -04:00
3d3c8c48de fix(deltacast): always open audio FIFO writer (silence fallback) to stop ffmpeg input deadlock
ffmpeg opens all inputs before processing; input 1 is the audio FIFO. The
bridge previously opened the FIFO writer only after VHD_OpenStreamHandle +
VHD_StartStream succeeded, returning early on failure / no embedded audio and
never opening the FIFO -> ffmpeg blocked forever on input 1 -> 0 fps and an
empty HLS preview. Now the FIFO writer is opened unconditionally and first,
and the audio thread feeds a continuous, wall-clock-paced s16le stereo stream
(real samples when available, otherwise silence). SIGPIPE is ignored so a
dying ffmpeg returns EPIPE instead of killing the bridge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:52:24 -04:00
12d76edc42 feat(deltacast): support 8 RX channels (ports 0-7) on DELTA-12G-elp-h 2026-06-01 13:31:06 -04:00
7d408035ac fix(capture): fix VHD_CORE_SP_BUFFERQUEUE_DEPTH constant name for SDK 6.34 2026-06-01 08:59:06 -04:00
962c7c8f20 fix(capture): log SDK errors in video loop, warn on unsupported port index 2026-06-01 08:00:55 -04:00
c7e07df515 fix(capture): handle partial writes in audio_thread FIFO write loop 2026-06-01 07:51:10 -04:00
67c071a0ee feat(capture): add deltacast-capture bridge binary source 2026-06-01 07:50:07 -04:00
3529590160 build(capture): add CMakeLists for deltacast-capture bridge binary 2026-06-01 07:47:32 -04:00