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() {
|
void DeckLinkOutNode::close_device() {
|
||||||
if (output_) {
|
if (output_) {
|
||||||
|
if (playing_) {
|
||||||
output_->StopScheduledPlayback(0, nullptr, time_scale_);
|
output_->StopScheduledPlayback(0, nullptr, time_scale_);
|
||||||
|
}
|
||||||
output_->DisableVideoOutput();
|
output_->DisableVideoOutput();
|
||||||
output_->Release();
|
output_->Release();
|
||||||
output_ = nullptr;
|
output_ = nullptr;
|
||||||
@@ -213,6 +215,13 @@ void DeckLinkOutNode::close_device() {
|
|||||||
}
|
}
|
||||||
playing_ = false;
|
playing_ = false;
|
||||||
callback_.reset();
|
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");
|
spdlog::info("DeckLink-out: device closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,14 +238,15 @@ void DeckLinkOutNode::schedule_frame(void* mxl_payload, long width, long height,
|
|||||||
}
|
}
|
||||||
|
|
||||||
IDeckLinkMutableVideoFrame* frame = nullptr;
|
IDeckLinkMutableVideoFrame* frame = nullptr;
|
||||||
HRESULT hr = output_->CreateVideoFrame(width, height, out_row_bytes, output_format_,
|
{
|
||||||
bmdFrameFlagDefault, &frame);
|
std::unique_lock<std::mutex> lock(frame_pool_mutex_);
|
||||||
if (hr != S_OK || !frame) {
|
if (frame_pool_cv_.wait_for(lock, std::chrono::milliseconds(100), [this] { return !frame_pool_.empty(); })) {
|
||||||
if (create_fail_count_ < 5) {
|
frame = frame_pool_.back();
|
||||||
spdlog::error("DeckLink-out: CreateVideoFrame {}x{} row_bytes={} fmt=0x{:x} hr=0x{:08x}",
|
frame_pool_.pop_back();
|
||||||
width, height, out_row_bytes, static_cast<uint32_t>(output_format_), static_cast<uint32_t>(hr));
|
|
||||||
create_fail_count_++;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!frame) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +344,12 @@ nlohmann::json DeckLinkOutNode::status() const {
|
|||||||
|
|
||||||
HRESULT DeckLinkOutNode::OutputCallback::ScheduledFrameCompleted(
|
HRESULT DeckLinkOutNode::OutputCallback::ScheduledFrameCompleted(
|
||||||
IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result) {
|
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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
#include <DeckLinkAPI.h>
|
#include <DeckLinkAPI.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace dmf_node {
|
namespace dmf_node {
|
||||||
|
|
||||||
@@ -81,6 +83,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<OutputCallback> callback_;
|
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;
|
IDeckLinkMutableVideoFrame* scheduled_frame_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user