115 lines
5.4 KiB
C++
115 lines
5.4 KiB
C++
#pragma once
|
|
|
|
#include "DeckLinkAPI_h.h"
|
|
#include "DeckLinkDisplayMode.h"
|
|
#include "DeckLinkFrameTransfer.h"
|
|
#include "DeckLinkVideoIOFormat.h"
|
|
#include "VideoIOFormat.h"
|
|
#include "VideoIOTypes.h"
|
|
#include "VideoPlayoutPolicy.h"
|
|
#include "VideoPlayoutScheduler.h"
|
|
|
|
#include <atlbase.h>
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
|
|
class OpenGLComposite;
|
|
|
|
struct DeckLinkSessionTelemetry
|
|
{
|
|
bool actualBufferedFramesAvailable = false;
|
|
uint64_t actualBufferedFrames = 0;
|
|
double scheduleCallMilliseconds = 0.0;
|
|
uint64_t scheduleFailureCount = 0;
|
|
bool scheduleLeadAvailable = false;
|
|
int64_t playbackStreamTime = 0;
|
|
uint64_t playbackFrameIndex = 0;
|
|
uint64_t nextScheduleFrameIndex = 0;
|
|
int64_t scheduleLeadFrames = 0;
|
|
uint64_t scheduleRealignmentCount = 0;
|
|
};
|
|
|
|
class DeckLinkSession
|
|
{
|
|
public:
|
|
DeckLinkSession() = default;
|
|
~DeckLinkSession();
|
|
|
|
using OutputFrameCallback = std::function<void(const VideoIOCompletion&)>;
|
|
|
|
void ReleaseResources();
|
|
bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error);
|
|
bool SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, std::string& error);
|
|
bool ConfigureOutput(OutputFrameCallback callback, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error);
|
|
bool PrepareOutputSchedule();
|
|
bool StartScheduledPlayback();
|
|
bool Stop();
|
|
|
|
bool HasInputDevice() const { return mState.hasInputDevice; }
|
|
bool HasInputSource() const { return mState.hasInputSource; }
|
|
void SetInputSourceMissing(bool missing) { mState.hasInputSource = !missing; }
|
|
bool InputOutputDimensionsDiffer() const { return mState.inputFrameSize != mState.outputFrameSize; }
|
|
const FrameSize& InputFrameSize() const { return mState.inputFrameSize; }
|
|
const FrameSize& OutputFrameSize() const { return mState.outputFrameSize; }
|
|
unsigned InputFrameWidth() const { return mState.inputFrameSize.width; }
|
|
unsigned InputFrameHeight() const { return mState.inputFrameSize.height; }
|
|
unsigned OutputFrameWidth() const { return mState.outputFrameSize.width; }
|
|
unsigned OutputFrameHeight() const { return mState.outputFrameSize.height; }
|
|
VideoIOPixelFormat InputPixelFormat() const { return mState.inputPixelFormat; }
|
|
VideoIOPixelFormat OutputPixelFormat() const { return mState.outputPixelFormat; }
|
|
bool InputIsTenBit() const { return VideoIOPixelFormatIsTenBit(mState.inputPixelFormat); }
|
|
bool OutputIsTenBit() const { return VideoIOPixelFormatIsTenBit(mState.outputPixelFormat); }
|
|
unsigned InputFrameRowBytes() const { return mState.inputFrameRowBytes; }
|
|
unsigned OutputFrameRowBytes() const { return mState.outputFrameRowBytes; }
|
|
unsigned CaptureTextureWidth() const { return mState.captureTextureWidth; }
|
|
unsigned OutputPackTextureWidth() const { return mState.outputPackTextureWidth; }
|
|
const std::string& FormatStatusMessage() const { return mState.formatStatusMessage; }
|
|
const std::string& InputDisplayModeName() const { return mState.inputDisplayModeName; }
|
|
const std::string& OutputModelName() const { return mState.outputModelName; }
|
|
bool SupportsInternalKeying() const { return mState.supportsInternalKeying; }
|
|
bool SupportsExternalKeying() const { return mState.supportsExternalKeying; }
|
|
bool KeyerInterfaceAvailable() const { return mState.keyerInterfaceAvailable; }
|
|
bool ExternalKeyingActive() const { return mState.externalKeyingActive; }
|
|
const std::string& StatusMessage() const { return mState.statusMessage; }
|
|
void SetStatusMessage(const std::string& message) { mState.statusMessage = message; }
|
|
const VideoIOState& State() const { return mState; }
|
|
VideoIOState& MutableState() { return mState; }
|
|
const DeckLinkSessionTelemetry& Telemetry() const { return mTelemetry; }
|
|
double FrameBudgetMilliseconds() const;
|
|
VideoPlayoutRecoveryDecision AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth);
|
|
bool BeginOutputFrame(VideoIOOutputFrame& frame);
|
|
void EndOutputFrame(VideoIOOutputFrame& frame);
|
|
bool ScheduleOutputFrame(const VideoIOOutputFrame& frame);
|
|
void HandlePlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completionResult);
|
|
|
|
private:
|
|
bool AcquireNextOutputVideoFrame(CComPtr<IDeckLinkMutableVideoFrame>& outputVideoFrame);
|
|
bool PopulateOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame, VideoIOOutputFrame& frame);
|
|
bool ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
|
void UpdateScheduleLeadTelemetry();
|
|
void MaybeRealignScheduleCursorForLowLead();
|
|
void RealignScheduleCursorToPlayback();
|
|
bool ScheduleSystemMemoryFrame(const VideoIOOutputFrame& frame);
|
|
bool ScheduleBlackFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
|
void RefreshBufferedVideoFrameCount();
|
|
static VideoIOCompletionResult TranslateCompletionResult(BMDOutputFrameCompletionResult completionResult);
|
|
|
|
CComPtr<PlayoutDelegate> playoutDelegate;
|
|
CComPtr<IDeckLinkOutput> output;
|
|
CComPtr<IDeckLinkKeyer> keyer;
|
|
std::deque<CComPtr<IDeckLinkMutableVideoFrame>> outputVideoFrameQueue;
|
|
std::mutex mScheduledSystemFrameMutex;
|
|
std::unordered_map<IDeckLinkVideoFrame*, void*> mScheduledSystemFrameBuffers;
|
|
VideoIOState mState;
|
|
DeckLinkSessionTelemetry mTelemetry;
|
|
VideoPlayoutPolicy mPlayoutPolicy;
|
|
VideoPlayoutScheduler mScheduler;
|
|
bool mScheduleRealignmentPending = false;
|
|
bool mScheduleRealignmentArmed = true;
|
|
bool mProactiveScheduleRealignmentArmed = true;
|
|
OutputFrameCallback mOutputFrameCallback;
|
|
};
|