Commit graph

2 commits

Author SHA1 Message Date
Wild Dragon Dev
01211fef7a fix(framecache): address critical bugs from code review
C-Bug 1 (Torn read): fc_client.c zero-copy pointer replaced with consumer-owned
copy buffer + post-copy cursor revalidation to prevent reading torn frames when
the writer laps a slow consumer. New FC_LAPPED return code.
C-Bug 3 (Semaphore busy-spin): fc_client.c drains the semaphore (sem_trywait)
so the count never accumulates, relying entirely on write_cursor diff for
availability. Prevents 100% CPU loops + EOVERFLOW.
C-Bug 4 (GET /slots stack overflow): framecache.c uses heap allocation with
explicit bounds checking for JSON serialization instead of a 64KB stack buffer.
C-Bug 6 (DeckLink race): decklink-bridge uses pthread_mutex_t around fc_writer
calls and reopen_slot to prevent UAF/double-free from concurrent SDK callbacks.
C-Bug 2-net (Resolution resync): net_ingest explicitly scales to target W:H
so ffmpeg always outputs exactly frame_size bytes, ignoring source resolution
changes.
C-Bug 8 (strdup leak): net_ingest uses static caller-owned buffers for ffmpeg
args instead of strdup across listener reconnects.
C-Bug 9 (PROT_READ segfault): removed atomic write to hdr->dropped_frames from
the consumer read loop (which maps shm read-only).
2026-06-03 16:25:34 +00:00
Wild Dragon Dev
b2c63de2fa feat(framecache): phase 3 — decklink-bridge writes to shm
- services/capture/decklink-bridge/main.cpp: new C++ DeckLink bridge
  - IDeckLinkInputCallback (VideoInputFrameArrived) writes UYVY422
    frames to framecache slot via fc_writer_write()
  - VideoInputFormatChanged reopens slot with new resolution/fps
  - bmdVideoInputEnableFormatDetection: auto-detects signal format
  - bmdFormat8BitYUV (UYVY422) — same pixel format as deltacast-bridge
  - Audio written from callback to named FIFO (same pattern as deltacast)
  - Silence thread keeps audio FIFO open between sessions
  - slot_id: decklink-<NODE_ID>-<device_idx>
  - Format JSON emitted on first frame (includes slot_id)
  - LEGACY_FIFO compile flag mirrors deltacast-bridge
  - --devices csv, --fc-url, --audio-pipe-dir, --signal-timeout args

- services/capture/decklink-bridge/CMakeLists.txt:
  - Reuses fc_writer.c from deltacast-bridge (shared writer module)
  - Links rt + dl + pthread; DeckLink SDK via dlopen at runtime
  - LEGACY_FIFO option

- services/capture/Dockerfile:
  - New decklink-bridge-builder stage (g++ + DeckLink SDK headers)
  - Copies decklink-bridge binary to /usr/local/bin/decklink-bridge

- services/node-agent/index.js:
  - FC_URL + FC_NODE_ID constants (from env vars, passed to all bridges)
  - startDecklinkBridge(deviceIndices) / stopDecklinkBridge() functions
    mirror deltacast bridge lifecycle management
  - deltacast startDeltacastBridge: adds --fc-url arg + NODE_ID env
  - sidecar start: injects FC_URL into all sidecar envs; sets IpcMode=host
    for deltacast + blackmagic sidecars; starts decklink-bridge for sdi/
    blackmagic source types; injects FC_SLOT_ID from fmt JSON
  - sidecar stop: stopDecklinkBridge() when last blackmagic sidecar stops
2026-06-03 15:25:25 +00:00