Repository navigation
ndistreamer 2.0: reengineered real-time pipeline - #9
Merged
Merged
Conversation
Replace the three duplicated software/VAAPI/CUDA applications with one threaded pipeline (demux -> decode -> process -> present) connected by bounded queues and driven by a shared presentation clock. - Frames are sent at their presentation timestamps; audio is the master clock while it plays, and NDI timecodes derive from media timestamps. - Hardware decoding through any FFmpeg device type, with per-stream software fallback; GPU frames download straight into NDI's layout. - Pixel formats NDI accepts pass through (new default `-p auto`), cutting sender CPU by 45-67% versus converting everything to UYVY. - Graceful overload: drop late frames when newer ones are ready, skip processing of late frames, then decode keyframes only. Audio is never starved, and live sources tolerate drift and mid-GOP joins. - Seamless looping, FFmpeg filters, any FFmpeg input or capture device, multichannel float audio, clean signal handling, stats and logging. - The NDI runtime is loaded with dlopen, so building needs no NDI SDK. Fixes 1.x crashes on files without audio, the 0/0 NDI frame rate, lost final frames at end of input, and the build against FFmpeg 8+. Tests stream generated clips through the whole pipeline into a fake libndi.so, checking pacing, A/V alignment, loop continuity and frame lifetime. With the NDI SDK configured, they also verify the ABI against the official headers and stream end to end to a real receiver. CI builds with GCC, Clang and ASan/UBSan on Ubuntu 24.04 (FFmpeg 6.1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Older FFmpeg (6.1, found by CI) does not trim AAC end padding when decoding, so at a loop point the last block of a pass ran 256 samples past where the next pass begins. Receivers would play the extra samples and drift a little further behind on every loop. The audio processor now holds back one block (about 21 ms). When the next block starts slightly before it ends, the held block's tail is trimmed. Larger backward jumps are discontinuities and are left to the presentation clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A ground-up rewrite. The goal is the same (stream media as an NDI source from Linux), but the architecture, timing model and feature set are new. See
CHANGELOG.mdfor the full list.Summary
-t auto|vaapi|cuda|…accepts any FFmpeg device type. A stream the device can't decode falls back to software, and GPU frames are downloaded straight into NDI's buffer layout.-p autopasses through layouts NDI accepts. At 1080p60 H.264 with the real NDI 6.3 runtime, sender CPU is 33% of a core with software decode and 19% with VAAPI, versus 65% when forcing UYVY. All 720/720 frames were delivered with 0 dropped.--loop,--vffilters, any FFmpeg input or capture device, multichannel float audio, clean SIGINT/SIGTERM handling,--stats./opt/ndiSDK path is still searched.-i,-sand-t software|vaapi|cudastill work.Fixes compared to 1.x
avcodec_closewas removed upstream).Testing
libndi.so. They check frame counts, real-time pacing, A/V alignment, loop continuity, pixel layouts, async frame lifetime, and overload handling.ndi_abichecks the project's NDI declarations against the official headers with static_asserts.ndi_end_to_endstreams to a real NDI receiver through a private discovery server.🤖 Generated with Claude Code