fix ndi->decklinkout slowdown

This commit is contained in:
JohannesItten
2026-07-07 19:50:09 +03:00
parent 370cbd89a2
commit 8dfeeacecd
2 changed files with 17 additions and 6 deletions
+8 -2
View File
@@ -114,8 +114,9 @@ class DeckLinkOutNode : public dmf::NodeBase {
uint64_t frame_count = 0; uint64_t frame_count = 0;
uint64_t invalid_count = 0; uint64_t invalid_count = 0;
uint64_t late_count = 0; uint64_t late_count = 0;
auto wall_start = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point wall_start;
auto last_log_time = wall_start; bool timing_started = false;
auto last_log_time = std::chrono::steady_clock::now();
// --- Main loop --- // --- Main loop ---
while (dmf::g_running.load(std::memory_order_relaxed)) { while (dmf::g_running.load(std::memory_order_relaxed)) {
@@ -169,6 +170,11 @@ class DeckLinkOutNode : public dmf::NodeBase {
video_reader, video_index, &video_grain, &video_buf); video_reader, video_index, &video_grain, &video_buf);
if (vst == MXL_STATUS_OK) { if (vst == MXL_STATUS_OK) {
if (!timing_started) {
wall_start = std::chrono::steady_clock::now();
last_log_time = wall_start;
timing_started = true;
}
if (video_grain.flags & MXL_GRAIN_FLAG_INVALID) invalid_count++; if (video_grain.flags & MXL_GRAIN_FLAG_INVALID) invalid_count++;
sender.submit_frame(video_buf, video_stride); sender.submit_frame(video_buf, video_stride);
frame_count++; frame_count++;
+9 -4
View File
@@ -1,3 +1,4 @@
#include <chrono>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -96,19 +97,23 @@ class NDIInNode : public dmf::NodeBase {
dmf::NDIReceiver::AudioInfo audio_info; dmf::NDIReceiver::AudioInfo audio_info;
while (dmf::g_running.load(std::memory_order_relaxed)) { while (dmf::g_running.load(std::memory_order_relaxed)) {
// Drain all queued NDI frames before writing one MXL grain. // Drain available NDI frames before writing one MXL grain.
// With audio enabled, many audio packets may be queued ahead of a video frame. // With audio enabled, many audio packets may be queued ahead of a video frame.
// Calling capture() once per grain window would starve video reception. // Budget: drain for at most half a frame period so the grain clock stays on time
// Strategy: blocking first call (5ms), then non-blocking drain of remainder. // even when catching up from a startup audio backlog.
try { try {
const auto drain_deadline =
std::chrono::steady_clock::now() + std::chrono::milliseconds(20);
bool first = true; bool first = true;
while (dmf::g_running.load(std::memory_order_relaxed)) { while (dmf::g_running.load(std::memory_order_relaxed) &&
std::chrono::steady_clock::now() < drain_deadline) {
auto kind = ndi.capture(latest_video.data(), video_stride, auto kind = ndi.capture(latest_video.data(), video_stride,
audio_buf, audio_info, has_audio, audio_buf, audio_info, has_audio,
first ? 5 : 0); first ? 5 : 0);
first = false; first = false;
if (kind == dmf::NDIReceiver::FrameKind::Video) { if (kind == dmf::NDIReceiver::FrameKind::Video) {
have_video = true; have_video = true;
break; // got video — write grain now, remaining audio deferred to next window
} else if (kind == dmf::NDIReceiver::FrameKind::Audio && has_audio) { } else if (kind == dmf::NDIReceiver::FrameKind::Audio && has_audio) {
mxlMutableWrappedMultiBufferSlice slice{}; mxlMutableWrappedMultiBufferSlice slice{};
if (mxlFlowWriterOpenSamples(audio_writer, audio_index, if (mxlFlowWriterOpenSamples(audio_writer, audio_index,