decklink-out: reuse frames via ScheduledFrameCompleted callback pool

This commit is contained in:
Johanness
2026-05-30 23:23:15 +03:00
parent 26febc41d6
commit bd1f060c73
2 changed files with 29 additions and 8 deletions
+24 -8
View File
@@ -202,7 +202,9 @@ bool DeckLinkOutNode::open_device() {
void DeckLinkOutNode::close_device() {
if (output_) {
output_->StopScheduledPlayback(0, nullptr, time_scale_);
if (playing_) {
output_->StopScheduledPlayback(0, nullptr, time_scale_);
}
output_->DisableVideoOutput();
output_->Release();
output_ = nullptr;
@@ -213,6 +215,13 @@ void DeckLinkOutNode::close_device() {
}
playing_ = false;
callback_.reset();
{
std::lock_guard<std::mutex> lock(frame_pool_mutex_);
for (auto* f : frame_pool_) {
f->Release();
}
frame_pool_.clear();
}
spdlog::info("DeckLink-out: device closed");
}
@@ -229,14 +238,15 @@ void DeckLinkOutNode::schedule_frame(void* mxl_payload, long width, long height,
}
IDeckLinkMutableVideoFrame* frame = nullptr;
HRESULT hr = output_->CreateVideoFrame(width, height, out_row_bytes, output_format_,
bmdFrameFlagDefault, &frame);
if (hr != S_OK || !frame) {
if (create_fail_count_ < 5) {
spdlog::error("DeckLink-out: CreateVideoFrame {}x{} row_bytes={} fmt=0x{:x} hr=0x{:08x}",
width, height, out_row_bytes, static_cast<uint32_t>(output_format_), static_cast<uint32_t>(hr));
create_fail_count_++;
{
std::unique_lock<std::mutex> lock(frame_pool_mutex_);
if (frame_pool_cv_.wait_for(lock, std::chrono::milliseconds(100), [this] { return !frame_pool_.empty(); })) {
frame = frame_pool_.back();
frame_pool_.pop_back();
}
}
if (!frame) {
return;
}
@@ -334,6 +344,12 @@ nlohmann::json DeckLinkOutNode::status() const {
HRESULT DeckLinkOutNode::OutputCallback::ScheduledFrameCompleted(
IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result) {
if (completedFrame) {
completedFrame->AddRef();
std::lock_guard<std::mutex> lock(owner_.frame_pool_mutex_);
owner_.frame_pool_.push_back(static_cast<IDeckLinkMutableVideoFrame*>(completedFrame));
owner_.frame_pool_cv_.notify_one();
}
return S_OK;
}
@@ -7,9 +7,11 @@
#include <DeckLinkAPI.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <thread>
#include <vector>
namespace dmf_node {
@@ -81,6 +83,9 @@ private:
};
std::unique_ptr<OutputCallback> callback_;
std::vector<IDeckLinkMutableVideoFrame*> frame_pool_;
std::mutex frame_pool_mutex_;
std::condition_variable frame_pool_cv_;
IDeckLinkMutableVideoFrame* scheduled_frame_ = nullptr;
};