fixes + cmake fixes for macos

This commit is contained in:
JohannesItten
2026-07-07 19:33:55 +03:00
parent 31346c48a6
commit 370cbd89a2
4 changed files with 53 additions and 33 deletions
+6 -1
View File
@@ -7,5 +7,10 @@ set(NDI_INCLUDE "${NDI_SDK_DIR}/include")
target_include_directories(dmf-node-ndiin PRIVATE
"${NDI_INCLUDE}"
)
find_library(NDI_LIB NAMES ndi PATHS "${NDI_SDK_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu" "${NDI_SDK_DIR}/lib/x64" "${NDI_SDK_DIR}/lib" NO_DEFAULT_PATH)
find_library(NDI_LIB NAMES ndi PATHS
"${NDI_SDK_DIR}/lib/macOS"
"${NDI_SDK_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu"
"${NDI_SDK_DIR}/lib/x64"
"${NDI_SDK_DIR}/lib"
NO_DEFAULT_PATH)
target_link_libraries(dmf-node-ndiin PRIVATE ${NDI_LIB})
+37 -28
View File
@@ -96,40 +96,49 @@ class NDIInNode : public dmf::NodeBase {
dmf::NDIReceiver::AudioInfo audio_info;
while (dmf::g_running.load(std::memory_order_relaxed)) {
dmf::NDIReceiver::FrameKind kind;
// Drain all queued NDI frames before writing one MXL grain.
// With audio enabled, many audio packets may be queued ahead of a video frame.
// Calling capture() once per grain window would starve video reception.
// Strategy: blocking first call (5ms), then non-blocking drain of remainder.
try {
kind = ndi.capture(latest_video.data(), video_stride, audio_buf, audio_info, has_audio);
bool first = true;
while (dmf::g_running.load(std::memory_order_relaxed)) {
auto kind = ndi.capture(latest_video.data(), video_stride,
audio_buf, audio_info, has_audio,
first ? 5 : 0);
first = false;
if (kind == dmf::NDIReceiver::FrameKind::Video) {
have_video = true;
} else if (kind == dmf::NDIReceiver::FrameKind::Audio && has_audio) {
mxlMutableWrappedMultiBufferSlice slice{};
if (mxlFlowWriterOpenSamples(audio_writer, audio_index,
static_cast<size_t>(audio_info.samples),
&slice) == MXL_STATUS_OK) {
const size_t frag0 = slice.base.fragments[0].size / sizeof(float);
const size_t frag1 = slice.base.fragments[1].size / sizeof(float);
for (int c = 0; c < audio_info.channels; ++c) {
const float* src = &audio_buf[c * audio_info.channel_stride];
auto* dst0 = reinterpret_cast<float*>(
static_cast<uint8_t*>(slice.base.fragments[0].pointer) + c * slice.stride);
std::memcpy(dst0, src, frag0 * sizeof(float));
if (frag1 > 0) {
auto* dst1 = reinterpret_cast<float*>(
static_cast<uint8_t*>(slice.base.fragments[1].pointer) + c * slice.stride);
std::memcpy(dst1, src + frag0, frag1 * sizeof(float));
}
}
mxlFlowWriterCommitSamples(audio_writer);
}
audio_index += audio_info.samples;
} else {
break; // None — queue drained
}
}
} catch (const std::runtime_error& e) {
log("NDI error: %s — stopping", e.what());
break;
}
if (kind == dmf::NDIReceiver::FrameKind::Video) {
have_video = true;
} else if (kind == dmf::NDIReceiver::FrameKind::Audio && has_audio) {
mxlMutableWrappedMultiBufferSlice slice{};
if (mxlFlowWriterOpenSamples(audio_writer, audio_index,
static_cast<size_t>(audio_info.samples), &slice) == MXL_STATUS_OK) {
// MXL audio is float32 planar: each channel occupies its own ring buffer
// region, accessed at base + c * stride. Fragments handle ring wraparound.
const size_t frag0 = slice.base.fragments[0].size / sizeof(float);
const size_t frag1 = slice.base.fragments[1].size / sizeof(float);
for (int c = 0; c < audio_info.channels; ++c) {
const float* src = &audio_buf[c * audio_info.channel_stride];
auto* dst0 = reinterpret_cast<float*>(
static_cast<uint8_t*>(slice.base.fragments[0].pointer) + c * slice.stride);
std::memcpy(dst0, src, frag0 * sizeof(float));
if (frag1 > 0) {
auto* dst1 = reinterpret_cast<float*>(
static_cast<uint8_t*>(slice.base.fragments[1].pointer) + c * slice.stride);
std::memcpy(dst1, src + frag0, frag1 * sizeof(float));
}
}
mxlFlowWriterCommitSamples(audio_writer);
}
audio_index += audio_info.samples;
}
// Write video grain whenever the MXL clock has reached video_index
const uint64_t current = mxlGetCurrentIndex(&video_rate);
if (current >= video_index) {
+6 -1
View File
@@ -7,5 +7,10 @@ set(NDI_INCLUDE "${NDI_SDK_DIR}/include")
target_include_directories(dmf-node-ndiout PRIVATE
"${NDI_INCLUDE}"
)
find_library(NDI_LIB NAMES ndi PATHS "${NDI_SDK_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu" "${NDI_SDK_DIR}/lib/x64" "${NDI_SDK_DIR}/lib" NO_DEFAULT_PATH)
find_library(NDI_LIB NAMES ndi PATHS
"${NDI_SDK_DIR}/lib/macOS"
"${NDI_SDK_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu"
"${NDI_SDK_DIR}/lib/x64"
"${NDI_SDK_DIR}/lib"
NO_DEFAULT_PATH)
target_link_libraries(dmf-node-ndiout PRIVATE ${NDI_LIB})