Architecture

Summary

obs-st2110 is a monorepo containing two components: libst2110rx (a portable C99 static library for receiving SMPTE ST 2110-20 uncompressed video over RTP multicast) and an OBS Studio source plugin that wraps it. The library has zero external dependencies and targets Windows (MSVC) and Linux (GCC/Clang).

The receiver pipeline is: UDP socket (Winsock/POSIX) receives RTP packets, RFC 4175 depayloader extracts scan line segments into a double-buffered frame assembler, a color converter transforms wire format (YCbCr 4:2:2 10-bit big-endian packed) to an output format (UYVY 8-bit for Phase 1, P010/V210 10-bit for Phase 3), and a callback delivers the completed frame to the caller.

One receiver thread per instance. The callback fires from that thread. Callers must not block in the callback. OBS obs_source_output_video() copies the frame internally, making the OBS plugin callback trivial.

Components

ComponentTypePurpose
libst2110rx/include/st2110rx.hPublic APIConfig, frame callback, stats, lifecycle
libst2110rx/src/rx_platform.hInternalPlatform abstraction (Winsock/POSIX, threads, atomics)
libst2110rx/src/rx_socket.cInternalUDP multicast socket with IGMP join, 128MB SO_RCVBUF
libst2110rx/src/rx_rfc4175.cInternalRFC 4175 depayloader and double-buffered frame assembler
libst2110rx/src/rx_convert.cInternalScalar color conversion (BE10 to UYVY)
libst2110rx/src/rx_stats.cInternalLock-free stats with RFC 3550 jitter tracking
libst2110rx/src/rx_core.cInternalLifecycle, receiver thread, wiring
libst2110rx/tools/st2110rx-cli.cToolCLI receiver for testing without OBS
libst2110rx/tools/st2110tx-test.cToolSynthetic RFC 4175 stream generator
obs-plugin/src/obs-st2110.cPluginOBS async video source (Phase 2)

Key Design Decisions

  • Static library, not shared. The OBS plugin links libst2110rx statically, producing a single .dll with no runtime dependencies.
  • Double-buffered frame assembly. Assembler writes to fill_buf while deliver_buf is being consumed by the callback. Swap on frame completion. No mutex needed since the receiver thread owns both operations sequentially.
  • Incomplete frames delivered with flag. Packet loss sets frame.incomplete = true. The caller decides whether to display or drop. Silently dropping frames would hide network problems.
  • Socket receive behind function pointer. Phase 1 uses recvfrom(). Phase 4 upgrades to IOCP without changing the assembler or converter code.
  • Color conversion in separate translation unit. AVX2 fast path (Phase 4) compiles with /arch:AVX2 flag. Runtime CPUID dispatch via function pointer.

Phased Delivery

PhaseDeliverableStatus
0obs-gstreamer hardware validationPending (needs Blackmagic device)
1libst2110rx MVP (recvfrom, RFC 4175, UYVY)Complete (2026-04-13)
2OBS source plugin MVPPlanned
310-bit output (P010, V210)Planned
4IOCP receive, AVX2 conversionPlanned
5SDP import, stats UI, polishPlanned

Sources