From e335461aacbd31dca4f9c4f36075126926808c9c Mon Sep 17 00:00:00 2001 From: JohannesItten Date: Mon, 6 Jul 2026 01:38:13 +0300 Subject: [PATCH] refactor: DeckLinkReceiver readability and error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DeckLinkReceiver: - Group private members with section comments (SDK objects / sync / frame state) - Change wait_for_format timeout param from uint64_t to int (matches std::chrono::milliseconds and all call sites) decklinkin main.cpp: - Wrap start_capture in try/catch — logs error and returns cleanly on device init failure (consistent with NDIInNode pattern) - Remove redundant zero-init on frame_buf (vector zero-inits anyway) Co-Authored-By: Claude Sonnet 4.6 --- nodes/decklinkin/main.cpp | 22 +++++++++++++--------- shared/DeckLinkReceiver.hpp | 9 ++++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/nodes/decklinkin/main.cpp b/nodes/decklinkin/main.cpp index 956ceb3..de81b38 100644 --- a/nodes/decklinkin/main.cpp +++ b/nodes/decklinkin/main.cpp @@ -8,15 +8,19 @@ class DeckLinkInNode : public dmf::NodeBase { void run() override { - dmf::DeckLinkReceiver receiver; - - log("Available DeckLink devices:"); - for (const auto& d : receiver.devices) - log(" %u) %s", d.index, d.name.c_str()); - const uint32_t device_index = config().value("device_index", 0u); - receiver.start_capture(device_index); - log("Capturing from: %s", receiver.devices[device_index].name.c_str()); + + dmf::DeckLinkReceiver receiver; + try { + log("Available DeckLink devices:"); + for (const auto& d : receiver.devices) + log(" %u) %s", d.index, d.name.c_str()); + receiver.start_capture(device_index); + log("Capturing from: %s", receiver.devices[device_index].name.c_str()); + } catch (const std::runtime_error& e) { + log("DeckLink init error: %s", e.what()); + return; + } if (!receiver.wait_for_format(5000)) { log("Timeout waiting for format detection"); @@ -55,7 +59,7 @@ class DeckLinkInNode : public dmf::NodeBase { uint64_t video_index = mxlGetCurrentIndex(&video_rate); log("start video_index=%llu", video_index); - std::vector frame_buf(static_cast(video_stride) * static_cast(height), 0); + std::vector frame_buf(static_cast(video_stride) * static_cast(height)); while (dmf::g_running.load(std::memory_order_relaxed)) { if (!receiver.wait_for_frame(frame_buf.data(), video_stride, width, height)) break; diff --git a/shared/DeckLinkReceiver.hpp b/shared/DeckLinkReceiver.hpp index 5afc2dc..c463fe5 100644 --- a/shared/DeckLinkReceiver.hpp +++ b/shared/DeckLinkReceiver.hpp @@ -68,7 +68,7 @@ public: if (r != S_OK) throw std::runtime_error("Could not start streams"); } - bool wait_for_format(uint64_t timeout_ms = 5000) { + bool wait_for_format(int timeout_ms = 5000) { std::unique_lock lk(mutex); return format_cv.wait_for(lk, std::chrono::milliseconds(timeout_ms), [this] { return format_detected; }); @@ -173,16 +173,19 @@ private: std::atomic ref_count{1}; }; + // DeckLink SDK objects std::vector raw_devices; IDeckLink* selected_device = nullptr; IDeckLinkInput* decklink_input = nullptr; InputCallback* input_callback = nullptr; + // Synchronisation — one mutex guards all shared state below std::mutex mutex; - std::condition_variable format_cv; - std::condition_variable frame_cv; + std::condition_variable format_cv; // signalled when format is detected + std::condition_variable frame_cv; // signalled when a frame arrives bool format_detected = false; + // Frame state — written by InputCallback, read by wait_for_frame (both under mutex) std::vector frame_buffer; uint32_t frame_row_bytes = 0; int frame_width = 0;