teamsiso/docs/superpowers/plans/2026-05-07-teamsiso-phase-b-2-ndi-interop.md
Zac Gaetano 60b12eb637
Some checks failed
CI / build-and-test (push) Failing after 27s
docs: add Phase B-2 NDI interop plan
2026-05-07 15:34:11 +00:00

3.4 KiB

TeamsISO Phase B-2 — Real NDI Interop Plan

Goal: Production INdiInterop implementation in TeamsISO.Engine.NdiInterop against NDI SDK 6, a managed BGRA scaler with aspect modes, an NDI version constant, and a TeamsISO.Console headless smoke runner that wires up the engine end-to-end. After this phase the engine can drive real Teams NDI streams once run on a Windows box with the NDI runtime installed.

Architecture: P/Invoke against Processing.NDI.Lib.x64.dll. Frame marshalling translates NDI's video_frame_v2_t to/from our managed RawFrame/ProcessedFrame. Receive in BGRA color space (NDIlib_recv_color_format_e_BGRX_BGRA) so the scaler doesn't need to handle UYVY in v1.0. Memory management: every captured frame is freed via NDIlib_recv_free_video_v2 once we've copied its pixels into a managed buffer.

Tech Stack: .NET 8, System.Runtime.InteropServices, plain C# scaler (managed BGRA nearest-neighbor; libyuv is a v1.5 perf optimization). The console runner uses the existing EngineLogging.CreateConsole.

Source spec: docs/superpowers/specs/2026-05-07-teamsiso-v1-design.md

Tasks

  1. NDI native bindings: NdiNative.cs with all [DllImport] declarations needed (initialize, destroy, find_create_v2/destroy/get_current_sources, recv_create_v3/destroy/capture_v3/free_video_v2, send_create/destroy/send_video_v2, version). Define NDIlib_video_frame_v2_t, NDIlib_source_t, NDIlib_recv_create_v3_t, NDIlib_send_create_t structs with explicit layout.
  2. Handles: NdiPInvokeFindHandle, NdiPInvokeReceiverHandle, NdiPInvokeSenderHandle deriving from the abstract Phase A handles, owning the unmanaged pointers.
  3. NdiInteropPInvoke: the production INdiInterop implementation. Initializes NDI on construction; destroys on dispose. Marshals between native and managed frame structs. Allocates managed pixel buffers and copies; frees the native frame immediately.
  4. NdiVersion: a constants class exposing the version string the engine probe compares against.
  5. ManagedNearestNeighborFrameScaler: managed BGRA scaler with Pillarbox, Letterbox, Stretch aspect modes. Fully unit-tested.
  6. TeamsISO.Console: a small console host. Constructs IsoController against NdiInteropPInvoke + ManagedNearestNeighborFrameScaler, prints participant updates, listens for q\n to quit. Useful for headless validation.
  7. Wire-up tests: integration scaffold uses RuntimeInformation.IsOSPlatform(OSPlatform.Windows) to skip cleanly on non-Windows. Add a smoke integration test that constructs the interop and probes the version.
  8. Wrap-up: tag phase-b-2-complete.

What this phase intentionally does NOT include

  • libyuv-backed scaler (deferred to v1.5 per spec — managed scaler is functionally complete).
  • Actual integration test suite running against an NDI Test Pattern source. Those tests need the NDI runtime; they're authored here but stay tagged requires=ndi and skip in the Linux CI.
  • Audio handling (passthrough video only in this phase; audio support added later if v1.0 needs it before ship).

Self-review

Spec coverage: §4 NdiReceiver/NdiSender/IsoController already done in B-1; this phase fills in the actual NDI SDK calls under INdiInterop. §6 startup preflight via NdiVersion + the existing NdiRuntimeProbe. §8 console smoke runner is a Phase B-2 deliverable for first end-to-end Windows validation before WPF.