Decklink abstraction
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 1m41s
CI / Windows Release Package (push) Successful in 2m20s

This commit is contained in:
2026-05-08 16:27:40 +10:00
parent 6d5a606107
commit ebbc11bb34
23 changed files with 971 additions and 342 deletions

View File

@@ -3,7 +3,10 @@
#include "DeckLinkAPI_h.h"
#include "DeckLinkDisplayMode.h"
#include "DeckLinkFrameTransfer.h"
#include "DeckLinkVideoIOFormat.h"
#include "VideoIOFormat.h"
#include "VideoIOTypes.h"
#include "VideoPlayoutScheduler.h"
#include <atlbase.h>
#include <deque>
@@ -11,51 +14,56 @@
class OpenGLComposite;
class DeckLinkSession
class DeckLinkSession : public VideoIODevice
{
public:
DeckLinkSession() = default;
~DeckLinkSession();
void ReleaseResources();
bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error);
bool SelectPreferredFormats(const VideoFormatSelection& videoModes, std::string& error);
bool ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, const VideoFormat& inputVideoMode, std::string& error);
bool ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error);
bool Start();
bool Stop();
void ReleaseResources() override;
bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error) override;
bool SelectPreferredFormats(const VideoFormatSelection& videoModes, std::string& error) override;
bool ConfigureInput(InputFrameCallback callback, const VideoFormat& inputVideoMode, std::string& error) override;
bool ConfigureOutput(OutputFrameCallback callback, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error) override;
bool Start() override;
bool Stop() override;
bool HasInputDevice() const { return input != nullptr; }
bool HasInputSource() const { return !hasNoInputSource; }
void SetInputSourceMissing(bool missing) { hasNoInputSource = missing; }
bool InputOutputDimensionsDiffer() const { return inputFrameSize != outputFrameSize; }
const FrameSize& InputFrameSize() const { return inputFrameSize; }
const FrameSize& OutputFrameSize() const { return outputFrameSize; }
unsigned InputFrameWidth() const { return inputFrameSize.width; }
unsigned InputFrameHeight() const { return inputFrameSize.height; }
unsigned OutputFrameWidth() const { return outputFrameSize.width; }
unsigned OutputFrameHeight() const { return outputFrameSize.height; }
VideoIOPixelFormat InputPixelFormat() const { return inputPixelFormat; }
VideoIOPixelFormat OutputPixelFormat() const { return outputPixelFormat; }
bool InputIsTenBit() const { return VideoIOPixelFormatIsTenBit(inputPixelFormat); }
bool OutputIsTenBit() const { return VideoIOPixelFormatIsTenBit(outputPixelFormat); }
unsigned InputFrameRowBytes() const { return inputFrameRowBytes; }
unsigned OutputFrameRowBytes() const { return outputFrameRowBytes; }
unsigned CaptureTextureWidth() const { return captureTextureWidth; }
unsigned OutputPackTextureWidth() const { return outputPackTextureWidth; }
const std::string& FormatStatusMessage() const { return formatStatusMessage; }
const std::string& InputDisplayModeName() const { return inputDisplayModeName; }
const std::string& OutputModelName() const { return outputModelName; }
bool SupportsInternalKeying() const { return supportsInternalKeying; }
bool SupportsExternalKeying() const { return supportsExternalKeying; }
bool KeyerInterfaceAvailable() const { return keyerInterfaceAvailable; }
bool ExternalKeyingActive() const { return externalKeyingActive; }
const std::string& StatusMessage() const { return statusMessage; }
void SetStatusMessage(const std::string& message) { statusMessage = message; }
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 override { return mState; }
VideoIOState& MutableState() override { return mState; }
double FrameBudgetMilliseconds() const;
IDeckLinkMutableVideoFrame* RotateOutputFrame();
void AccountForCompletionResult(BMDOutputFrameCompletionResult completionResult);
bool ScheduleOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
void AccountForCompletionResult(VideoIOCompletionResult completionResult) override;
bool BeginOutputFrame(VideoIOOutputFrame& frame) override;
void EndOutputFrame(VideoIOOutputFrame& frame) override;
bool ScheduleOutputFrame(const VideoIOOutputFrame& frame) override;
void HandleVideoInputFrame(IDeckLinkVideoInputFrame* inputFrame, bool hasNoInputSource);
void HandlePlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completionResult);
private:
CComPtr<CaptureDelegate> captureDelegate;
@@ -64,25 +72,8 @@ private:
CComPtr<IDeckLinkOutput> output;
CComPtr<IDeckLinkKeyer> keyer;
std::deque<CComPtr<IDeckLinkMutableVideoFrame>> outputVideoFrameQueue;
BMDTimeValue frameDuration = 0;
BMDTimeScale frameTimescale = 0;
unsigned totalPlayoutFrames = 0;
FrameSize inputFrameSize;
FrameSize outputFrameSize;
VideoIOPixelFormat inputPixelFormat = VideoIOPixelFormat::Uyvy8;
VideoIOPixelFormat outputPixelFormat = VideoIOPixelFormat::Uyvy8;
unsigned inputFrameRowBytes = 0;
unsigned outputFrameRowBytes = 0;
unsigned captureTextureWidth = 0;
unsigned outputPackTextureWidth = 0;
std::string inputDisplayModeName = "1080p59.94";
std::string outputDisplayModeName = "1080p59.94";
bool hasNoInputSource = true;
std::string outputModelName;
bool supportsInternalKeying = false;
bool supportsExternalKeying = false;
bool keyerInterfaceAvailable = false;
bool externalKeyingActive = false;
std::string statusMessage;
std::string formatStatusMessage;
VideoIOState mState;
VideoPlayoutScheduler mScheduler;
InputFrameCallback mInputFrameCallback;
OutputFrameCallback mOutputFrameCallback;
};