decklink-out: reuse frames via ScheduledFrameCompleted callback pool
This commit is contained in:
@@ -202,7 +202,9 @@ bool DeckLinkOutNode::open_device() {
|
||||
|
||||
void DeckLinkOutNode::close_device() {
|
||||
if (output_) {
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user