#include "DeckLinkOutput.h" #include "VideoIOFormat.h" namespace RenderCadenceCompositor { DeckLinkOutput::~DeckLinkOutput() { ReleaseResources(); } bool DeckLinkOutput::Initialize(const DeckLinkOutputConfig& config, CompletionCallback completionCallback, std::string& error) { mConfig = config; mCompletionCallback = completionCallback; VideoFormatSelection formats; formats.output = config.outputVideoMode; if (!mSession.DiscoverDevicesAndModes(formats, error)) return false; if (!mSession.SelectPreferredFormats(formats, config.outputAlphaRequired, error)) return false; if (!mSession.ConfigureOutput( [this](const VideoIOCompletion& completion) { HandleCompletion(completion); }, formats.output, config.externalKeyingEnabled, error)) { return false; } if (!mSession.PrepareOutputSchedule()) { error = "DeckLink output schedule preparation failed."; return false; } return true; } bool DeckLinkOutput::StartScheduledPlayback(std::string& error) { if (mSession.StartScheduledPlayback()) return true; error = "DeckLink scheduled playback failed to start."; return false; } bool DeckLinkOutput::ScheduleFrame(const VideoIOOutputFrame& frame) { return mSession.ScheduleOutputFrame(frame); } void DeckLinkOutput::Stop() { mSession.Stop(); } void DeckLinkOutput::ReleaseResources() { mSession.ReleaseResources(); } const VideoIOState& DeckLinkOutput::State() const { return mSession.State(); } DeckLinkOutputMetrics DeckLinkOutput::Metrics() const { DeckLinkOutputMetrics metrics; metrics.completions = mCompletions.load(); metrics.displayedLate = mDisplayedLate.load(); metrics.dropped = mDropped.load(); metrics.flushed = mFlushed.load(); const VideoIOState& state = mSession.State(); metrics.scheduleFailures = state.deckLinkScheduleFailureCount; metrics.actualBufferedFramesAvailable = state.actualDeckLinkBufferedFramesAvailable; metrics.actualBufferedFrames = state.actualDeckLinkBufferedFrames; metrics.scheduleCallMilliseconds = state.deckLinkScheduleCallMilliseconds; metrics.scheduleLeadAvailable = state.deckLinkScheduleLeadAvailable; metrics.playbackStreamTime = state.deckLinkPlaybackStreamTime; metrics.playbackFrameIndex = state.deckLinkPlaybackFrameIndex; metrics.nextScheduleFrameIndex = state.deckLinkNextScheduleFrameIndex; metrics.scheduleLeadFrames = state.deckLinkScheduleLeadFrames; metrics.scheduleRealignmentCount = state.deckLinkScheduleRealignmentCount; return metrics; } void DeckLinkOutput::HandleCompletion(const VideoIOCompletion& completion) { ++mCompletions; switch (completion.result) { case VideoIOCompletionResult::DisplayedLate: ++mDisplayedLate; break; case VideoIOCompletionResult::Dropped: ++mDropped; break; case VideoIOCompletionResult::Flushed: ++mFlushed; break; case VideoIOCompletionResult::Completed: case VideoIOCompletionResult::Unknown: default: break; } if (mCompletionCallback) mCompletionCallback(completion); } }