Video backend
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
#include "VideoIOBackendFactory.h"
|
||||
|
||||
#include "DeckLinkSession.h"
|
||||
#include "VideoIOTypes.h"
|
||||
|
||||
std::unique_ptr<VideoIODevice> CreateVideoIODevice(VideoIOBackendId backendId, std::string& error)
|
||||
{
|
||||
switch (backendId)
|
||||
{
|
||||
case VideoIOBackendId::DeckLink:
|
||||
return std::make_unique<DeckLinkSession>();
|
||||
}
|
||||
|
||||
error = "Unsupported video I/O backend.";
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "VideoIOConfig.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class VideoIODevice;
|
||||
|
||||
std::unique_ptr<VideoIODevice> CreateVideoIODevice(VideoIOBackendId backendId, std::string& error);
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "VideoIOConfig.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string NormalizeToken(std::string value)
|
||||
{
|
||||
std::transform(value.begin(), value.end(), value.begin(),
|
||||
[](unsigned char ch) { return static_cast<char>(std::tolower(ch)); });
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
const char* VideoIOBackendName(VideoIOBackendId backendId)
|
||||
{
|
||||
switch (backendId)
|
||||
{
|
||||
case VideoIOBackendId::DeckLink:
|
||||
return "decklink";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bool ParseVideoIOBackendId(const std::string& value, VideoIOBackendId& backendId)
|
||||
{
|
||||
const std::string normalized = NormalizeToken(value);
|
||||
if (normalized.empty() || normalized == "decklink")
|
||||
{
|
||||
backendId = VideoIOBackendId::DeckLink;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
enum class VideoIOBackendId
|
||||
{
|
||||
DeckLink
|
||||
};
|
||||
|
||||
const char* VideoIOBackendName(VideoIOBackendId backendId);
|
||||
bool ParseVideoIOBackendId(const std::string& value, VideoIOBackendId& backendId);
|
||||
|
||||
struct FrameSize
|
||||
{
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
|
||||
bool IsEmpty() const { return width == 0 || height == 0; }
|
||||
};
|
||||
|
||||
inline bool operator==(const FrameSize& left, const FrameSize& right)
|
||||
{
|
||||
return left.width == right.width && left.height == right.height;
|
||||
}
|
||||
|
||||
inline bool operator!=(const FrameSize& left, const FrameSize& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
struct VideoIOModeConfiguration
|
||||
{
|
||||
std::string videoFormat = "1080p";
|
||||
std::string frameRate = "59.94";
|
||||
};
|
||||
|
||||
struct VideoIOConfiguration
|
||||
{
|
||||
VideoIOBackendId backendId = VideoIOBackendId::DeckLink;
|
||||
VideoIOModeConfiguration inputMode;
|
||||
VideoIOModeConfiguration outputMode;
|
||||
bool externalKeyingEnabled = false;
|
||||
bool preferTenBit = true;
|
||||
};
|
||||
@@ -1,15 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "DeckLinkDisplayMode.h"
|
||||
#include "VideoIOConfig.h"
|
||||
#include "VideoIOFormat.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
enum class VideoIOBackend
|
||||
struct VideoIOCapabilities
|
||||
{
|
||||
DeckLink
|
||||
bool supportsInternalKeying = false;
|
||||
bool supportsExternalKeying = false;
|
||||
bool keyerInterfaceAvailable = false;
|
||||
};
|
||||
|
||||
enum class VideoIOCompletionResult
|
||||
@@ -21,15 +23,9 @@ enum class VideoIOCompletionResult
|
||||
Unknown
|
||||
};
|
||||
|
||||
struct VideoIOConfig
|
||||
{
|
||||
VideoFormatSelection videoModes;
|
||||
bool externalKeyingEnabled = false;
|
||||
bool preferTenBit = true;
|
||||
};
|
||||
|
||||
struct VideoIOState
|
||||
{
|
||||
VideoIOBackendId backendId = VideoIOBackendId::DeckLink;
|
||||
FrameSize inputFrameSize;
|
||||
FrameSize outputFrameSize;
|
||||
VideoIOPixelFormat inputPixelFormat = VideoIOPixelFormat::Uyvy8;
|
||||
@@ -40,14 +36,13 @@ struct VideoIOState
|
||||
unsigned outputPackTextureWidth = 0;
|
||||
std::string inputDisplayModeName = "1080p59.94";
|
||||
std::string outputDisplayModeName = "1080p59.94";
|
||||
std::string outputModelName;
|
||||
std::string deviceName;
|
||||
std::string statusMessage;
|
||||
std::string formatStatusMessage;
|
||||
bool hasInputDevice = false;
|
||||
bool hasInputSource = false;
|
||||
bool supportsInternalKeying = false;
|
||||
bool supportsExternalKeying = false;
|
||||
bool keyerInterfaceAvailable = false;
|
||||
VideoIOCapabilities capabilities;
|
||||
bool externalKeyingRequested = false;
|
||||
bool externalKeyingActive = false;
|
||||
double frameBudgetMilliseconds = 0.0;
|
||||
};
|
||||
@@ -93,11 +88,12 @@ public:
|
||||
using OutputFrameCallback = std::function<void(const VideoIOCompletion&)>;
|
||||
|
||||
virtual ~VideoIODevice() = default;
|
||||
virtual VideoIOBackendId BackendId() const = 0;
|
||||
virtual void ReleaseResources() = 0;
|
||||
virtual bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error) = 0;
|
||||
virtual bool SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, std::string& error) = 0;
|
||||
virtual bool ConfigureInput(InputFrameCallback callback, const VideoFormat& inputVideoMode, std::string& error) = 0;
|
||||
virtual bool ConfigureOutput(OutputFrameCallback callback, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error) = 0;
|
||||
virtual bool DiscoverDevicesAndModes(const VideoIOConfiguration& config, std::string& error) = 0;
|
||||
virtual bool SelectPreferredFormats(const VideoIOConfiguration& config, std::string& error) = 0;
|
||||
virtual bool ConfigureInput(InputFrameCallback callback, std::string& error) = 0;
|
||||
virtual bool ConfigureOutput(OutputFrameCallback callback, std::string& error) = 0;
|
||||
virtual bool Start() = 0;
|
||||
virtual bool Stop() = 0;
|
||||
virtual const VideoIOState& State() const = 0;
|
||||
@@ -126,10 +122,11 @@ public:
|
||||
unsigned OutputPackTextureWidth() const { return State().outputPackTextureWidth; }
|
||||
const std::string& FormatStatusMessage() const { return State().formatStatusMessage; }
|
||||
const std::string& InputDisplayModeName() const { return State().inputDisplayModeName; }
|
||||
const std::string& OutputModelName() const { return State().outputModelName; }
|
||||
bool SupportsInternalKeying() const { return State().supportsInternalKeying; }
|
||||
bool SupportsExternalKeying() const { return State().supportsExternalKeying; }
|
||||
bool KeyerInterfaceAvailable() const { return State().keyerInterfaceAvailable; }
|
||||
const std::string& DeviceName() const { return State().deviceName; }
|
||||
bool SupportsInternalKeying() const { return State().capabilities.supportsInternalKeying; }
|
||||
bool SupportsExternalKeying() const { return State().capabilities.supportsExternalKeying; }
|
||||
bool KeyerInterfaceAvailable() const { return State().capabilities.keyerInterfaceAvailable; }
|
||||
bool ExternalKeyingRequested() const { return State().externalKeyingRequested; }
|
||||
bool ExternalKeyingActive() const { return State().externalKeyingActive; }
|
||||
const std::string& StatusMessage() const { return State().statusMessage; }
|
||||
double FrameBudgetMilliseconds() const { return State().frameBudgetMilliseconds; }
|
||||
|
||||
@@ -13,10 +13,10 @@ std::string NormalizeModeToken(const std::string& value)
|
||||
return normalized;
|
||||
}
|
||||
|
||||
bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::string& frameRate, BMDDisplayMode& displayMode, std::string& displayModeName)
|
||||
bool ResolveConfiguredDeckLinkDisplayMode(const VideoIOModeConfiguration& mode, BMDDisplayMode& displayMode, std::string& displayModeName)
|
||||
{
|
||||
VideoFormat videoMode;
|
||||
if (!ResolveConfiguredVideoFormat(videoFormat, frameRate, videoMode))
|
||||
DeckLinkVideoMode videoMode;
|
||||
if (!ResolveConfiguredDeckLinkVideoMode(mode, videoMode))
|
||||
return false;
|
||||
|
||||
displayMode = videoMode.displayMode;
|
||||
@@ -24,10 +24,10 @@ bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::str
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResolveConfiguredVideoFormat(const std::string& videoFormat, const std::string& frameRate, VideoFormat& videoMode)
|
||||
bool ResolveConfiguredDeckLinkVideoMode(const VideoIOModeConfiguration& mode, DeckLinkVideoMode& videoMode)
|
||||
{
|
||||
const std::string formatToken = NormalizeModeToken(videoFormat);
|
||||
const std::string frameToken = NormalizeModeToken(frameRate);
|
||||
const std::string formatToken = NormalizeModeToken(mode.videoFormat);
|
||||
const std::string frameToken = NormalizeModeToken(mode.frameRate);
|
||||
const std::string combinedToken = formatToken + frameToken;
|
||||
|
||||
struct ModeOption
|
||||
@@ -98,25 +98,22 @@ bool ResolveConfiguredVideoFormat(const std::string& videoFormat, const std::str
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ResolveConfiguredVideoFormats(
|
||||
const std::string& inputVideoFormat,
|
||||
const std::string& inputFrameRate,
|
||||
const std::string& outputVideoFormat,
|
||||
const std::string& outputFrameRate,
|
||||
VideoFormatSelection& videoModes,
|
||||
bool ResolveConfiguredDeckLinkVideoModes(
|
||||
const VideoIOConfiguration& config,
|
||||
DeckLinkVideoModeSelection& videoModes,
|
||||
std::string& error)
|
||||
{
|
||||
if (!ResolveConfiguredVideoFormat(inputVideoFormat, inputFrameRate, videoModes.input))
|
||||
if (!ResolveConfiguredDeckLinkVideoMode(config.inputMode, videoModes.input))
|
||||
{
|
||||
error = "Unsupported DeckLink inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
|
||||
inputVideoFormat + " / " + inputFrameRate;
|
||||
error = "Unsupported DeckLink input mode in config/runtime-host.json: " +
|
||||
config.inputMode.videoFormat + " / " + config.inputMode.frameRate;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ResolveConfiguredVideoFormat(outputVideoFormat, outputFrameRate, videoModes.output))
|
||||
if (!ResolveConfiguredDeckLinkVideoMode(config.outputMode, videoModes.output))
|
||||
{
|
||||
error = "Unsupported DeckLink outputVideoFormat/outputFrameRate in config/runtime-host.json: " +
|
||||
outputVideoFormat + " / " + outputFrameRate;
|
||||
error = "Unsupported DeckLink output mode in config/runtime-host.json: " +
|
||||
config.outputMode.videoFormat + " / " + config.outputMode.frameRate;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "DeckLinkAPI_h.h"
|
||||
#include "VideoIOConfig.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct FrameSize
|
||||
{
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
|
||||
bool IsEmpty() const { return width == 0 || height == 0; }
|
||||
};
|
||||
|
||||
inline bool operator==(const FrameSize& left, const FrameSize& right)
|
||||
{
|
||||
return left.width == right.width && left.height == right.height;
|
||||
}
|
||||
|
||||
inline bool operator!=(const FrameSize& left, const FrameSize& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
struct VideoFormat
|
||||
struct DeckLinkVideoMode
|
||||
{
|
||||
BMDDisplayMode displayMode = bmdModeHD1080p5994;
|
||||
std::string displayName = "1080p59.94";
|
||||
};
|
||||
|
||||
struct VideoFormatSelection
|
||||
struct DeckLinkVideoModeSelection
|
||||
{
|
||||
VideoFormat input;
|
||||
VideoFormat output;
|
||||
DeckLinkVideoMode input;
|
||||
DeckLinkVideoMode output;
|
||||
};
|
||||
|
||||
std::string NormalizeModeToken(const std::string& value);
|
||||
bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::string& frameRate, BMDDisplayMode& displayMode, std::string& displayModeName);
|
||||
bool ResolveConfiguredVideoFormat(const std::string& videoFormat, const std::string& frameRate, VideoFormat& videoMode);
|
||||
bool ResolveConfiguredVideoFormats(
|
||||
const std::string& inputVideoFormat,
|
||||
const std::string& inputFrameRate,
|
||||
const std::string& outputVideoFormat,
|
||||
const std::string& outputFrameRate,
|
||||
VideoFormatSelection& videoModes,
|
||||
bool ResolveConfiguredDeckLinkDisplayMode(const VideoIOModeConfiguration& mode, BMDDisplayMode& displayMode, std::string& displayModeName);
|
||||
bool ResolveConfiguredDeckLinkVideoMode(const VideoIOModeConfiguration& mode, DeckLinkVideoMode& videoMode);
|
||||
bool ResolveConfiguredDeckLinkVideoModes(
|
||||
const VideoIOConfiguration& config,
|
||||
DeckLinkVideoModeSelection& videoModes,
|
||||
std::string& error);
|
||||
bool FindDeckLinkDisplayMode(IDeckLinkDisplayModeIterator* iterator, BMDDisplayMode targetMode, IDeckLinkDisplayMode** foundMode);
|
||||
|
||||
@@ -92,14 +92,19 @@ void DeckLinkSession::ReleaseResources()
|
||||
output.Release();
|
||||
}
|
||||
|
||||
bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error)
|
||||
bool DeckLinkSession::DiscoverDevicesAndModes(const VideoIOConfiguration& config, std::string& error)
|
||||
{
|
||||
CComPtr<IDeckLinkIterator> deckLinkIterator;
|
||||
CComPtr<IDeckLinkDisplayMode> inputMode;
|
||||
CComPtr<IDeckLinkDisplayMode> outputMode;
|
||||
|
||||
mState.inputDisplayModeName = videoModes.input.displayName;
|
||||
mState.outputDisplayModeName = videoModes.output.displayName;
|
||||
mState.backendId = BackendId();
|
||||
mState.externalKeyingRequested = config.externalKeyingEnabled;
|
||||
if (!ResolveConfiguredDeckLinkVideoModes(config, mConfiguredModes, error))
|
||||
return false;
|
||||
|
||||
mState.inputDisplayModeName = mConfiguredModes.input.displayName;
|
||||
mState.outputDisplayModeName = mConfiguredModes.output.displayName;
|
||||
|
||||
HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, nullptr, CLSCTX_ALL, IID_IDeckLinkIterator, reinterpret_cast<void**>(&deckLinkIterator));
|
||||
if (FAILED(result))
|
||||
@@ -151,9 +156,9 @@ bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoM
|
||||
output.Release();
|
||||
else
|
||||
{
|
||||
mState.outputModelName = modelName;
|
||||
mState.supportsInternalKeying = deviceSupportsInternalKeying;
|
||||
mState.supportsExternalKeying = deviceSupportsExternalKeying;
|
||||
mState.deviceName = modelName;
|
||||
mState.capabilities.supportsInternalKeying = deviceSupportsInternalKeying;
|
||||
mState.capabilities.supportsExternalKeying = deviceSupportsExternalKeying;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,9 +183,9 @@ bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoM
|
||||
return false;
|
||||
}
|
||||
|
||||
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, videoModes.input.displayMode, &inputMode))
|
||||
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, mConfiguredModes.input.displayMode, &inputMode))
|
||||
{
|
||||
error = "Cannot get specified input BMDDisplayMode for configured mode: " + videoModes.input.displayName;
|
||||
error = "Cannot get specified input BMDDisplayMode for configured mode: " + mConfiguredModes.input.displayName;
|
||||
ReleaseResources();
|
||||
return false;
|
||||
}
|
||||
@@ -194,9 +199,9 @@ bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoM
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, videoModes.output.displayMode, &outputMode))
|
||||
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, mConfiguredModes.output.displayMode, &outputMode))
|
||||
{
|
||||
error = "Cannot get specified output BMDDisplayMode for configured mode: " + videoModes.output.displayName;
|
||||
error = "Cannot get specified output BMDDisplayMode for configured mode: " + mConfiguredModes.output.displayName;
|
||||
ReleaseResources();
|
||||
return false;
|
||||
}
|
||||
@@ -223,7 +228,7 @@ bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoM
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, std::string& error)
|
||||
bool DeckLinkSession::SelectPreferredFormats(const VideoIOConfiguration& config, std::string& error)
|
||||
{
|
||||
if (!output)
|
||||
{
|
||||
@@ -233,19 +238,19 @@ bool DeckLinkSession::SelectPreferredFormats(const VideoFormatSelection& videoMo
|
||||
|
||||
mState.formatStatusMessage.clear();
|
||||
|
||||
const bool inputTenBitSupported = input != nullptr && InputSupportsFormat(input, videoModes.input.displayMode, bmdFormat10BitYUV);
|
||||
const bool inputTenBitSupported = input != nullptr && InputSupportsFormat(input, mConfiguredModes.input.displayMode, bmdFormat10BitYUV);
|
||||
mState.inputPixelFormat = input != nullptr ? ChoosePreferredVideoIOFormat(inputTenBitSupported) : VideoIOPixelFormat::Uyvy8;
|
||||
if (input != nullptr && !inputTenBitSupported)
|
||||
mState.formatStatusMessage += "DeckLink input does not report 10-bit YUV support for the configured mode; using 8-bit capture. ";
|
||||
|
||||
const bool outputTenBitSupported = OutputSupportsFormat(output, videoModes.output.displayMode, bmdFormat10BitYUV);
|
||||
const bool outputTenBitYuvaSupported = OutputSupportsFormat(output, videoModes.output.displayMode, bmdFormat10BitYUVA);
|
||||
mState.outputPixelFormat = outputAlphaRequired
|
||||
const bool outputTenBitSupported = OutputSupportsFormat(output, mConfiguredModes.output.displayMode, bmdFormat10BitYUV);
|
||||
const bool outputTenBitYuvaSupported = OutputSupportsFormat(output, mConfiguredModes.output.displayMode, bmdFormat10BitYUVA);
|
||||
mState.outputPixelFormat = config.externalKeyingEnabled
|
||||
? (outputTenBitYuvaSupported ? VideoIOPixelFormat::Yuva10 : VideoIOPixelFormat::Bgra8)
|
||||
: (outputTenBitSupported ? VideoIOPixelFormat::V210 : VideoIOPixelFormat::Bgra8);
|
||||
if (outputAlphaRequired && outputTenBitYuvaSupported)
|
||||
if (config.externalKeyingEnabled && outputTenBitYuvaSupported)
|
||||
mState.formatStatusMessage += "External keying requires alpha; using 10-bit YUVA output. ";
|
||||
else if (outputAlphaRequired)
|
||||
else if (config.externalKeyingEnabled)
|
||||
mState.formatStatusMessage += "External keying requires alpha, but DeckLink output does not report 10-bit YUVA support for the configured mode; using 8-bit BGRA output. ";
|
||||
else if (!outputTenBitSupported)
|
||||
mState.formatStatusMessage += "DeckLink output does not report 10-bit YUV support for the configured mode; using 8-bit BGRA output. ";
|
||||
@@ -286,7 +291,7 @@ bool DeckLinkSession::SelectPreferredFormats(const VideoFormatSelection& videoMo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ConfigureInput(InputFrameCallback callback, const VideoFormat& inputVideoMode, std::string& error)
|
||||
bool DeckLinkSession::ConfigureInput(InputFrameCallback callback, std::string& error)
|
||||
{
|
||||
mInputFrameCallback = std::move(callback);
|
||||
|
||||
@@ -298,7 +303,7 @@ bool DeckLinkSession::ConfigureInput(InputFrameCallback callback, const VideoFor
|
||||
}
|
||||
|
||||
const BMDPixelFormat deckLinkInputPixelFormat = DeckLinkPixelFormatForVideoIO(mState.inputPixelFormat);
|
||||
if (input->EnableVideoInput(inputVideoMode.displayMode, deckLinkInputPixelFormat, bmdVideoInputFlagDefault) != S_OK)
|
||||
if (input->EnableVideoInput(mConfiguredModes.input.displayMode, deckLinkInputPixelFormat, bmdVideoInputFlagDefault) != S_OK)
|
||||
{
|
||||
if (mState.inputPixelFormat == VideoIOPixelFormat::V210)
|
||||
{
|
||||
@@ -306,7 +311,7 @@ bool DeckLinkSession::ConfigureInput(InputFrameCallback callback, const VideoFor
|
||||
mState.inputPixelFormat = VideoIOPixelFormat::Uyvy8;
|
||||
mState.inputFrameRowBytes = mState.inputFrameSize.width * 2u;
|
||||
mState.captureTextureWidth = mState.inputFrameSize.width / 2u;
|
||||
if (input->EnableVideoInput(inputVideoMode.displayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault) == S_OK)
|
||||
if (input->EnableVideoInput(mConfiguredModes.input.displayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault) == S_OK)
|
||||
{
|
||||
std::ostringstream status;
|
||||
status << "DeckLink formats: capture " << VideoIOPixelFormatName(mState.inputPixelFormat)
|
||||
@@ -341,26 +346,26 @@ input_enabled:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ConfigureOutput(OutputFrameCallback callback, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error)
|
||||
bool DeckLinkSession::ConfigureOutput(OutputFrameCallback callback, std::string& error)
|
||||
{
|
||||
mOutputFrameCallback = std::move(callback);
|
||||
|
||||
if (output->EnableVideoOutput(outputVideoMode.displayMode, bmdVideoOutputFlagDefault) != S_OK)
|
||||
if (output->EnableVideoOutput(mConfiguredModes.output.displayMode, bmdVideoOutputFlagDefault) != S_OK)
|
||||
{
|
||||
error = "DeckLink output setup failed while enabling video output.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output->QueryInterface(IID_IDeckLinkKeyer, (void**)&keyer) == S_OK && keyer != NULL)
|
||||
mState.keyerInterfaceAvailable = true;
|
||||
mState.capabilities.keyerInterfaceAvailable = true;
|
||||
|
||||
if (externalKeyingEnabled)
|
||||
if (mState.externalKeyingRequested)
|
||||
{
|
||||
if (!mState.supportsExternalKeying)
|
||||
if (!mState.capabilities.supportsExternalKeying)
|
||||
{
|
||||
mState.statusMessage = "External keying was requested, but the selected DeckLink output does not report external keying support.";
|
||||
}
|
||||
else if (!mState.keyerInterfaceAvailable)
|
||||
else if (!mState.capabilities.keyerInterfaceAvailable)
|
||||
{
|
||||
mState.statusMessage = "External keying was requested, but the selected DeckLink output does not expose the IDeckLinkKeyer interface.";
|
||||
}
|
||||
@@ -374,7 +379,7 @@ bool DeckLinkSession::ConfigureOutput(OutputFrameCallback callback, const VideoF
|
||||
mState.statusMessage = "External keying is active on the selected DeckLink output.";
|
||||
}
|
||||
}
|
||||
else if (mState.supportsExternalKeying)
|
||||
else if (mState.capabilities.supportsExternalKeying)
|
||||
{
|
||||
mState.statusMessage = "Selected DeckLink output supports external keying. Set enableExternalKeying to true in runtime-host.json to request it.";
|
||||
}
|
||||
|
||||
@@ -20,41 +20,14 @@ public:
|
||||
DeckLinkSession() = default;
|
||||
~DeckLinkSession();
|
||||
|
||||
VideoIOBackendId BackendId() const override { return VideoIOBackendId::DeckLink; }
|
||||
void ReleaseResources() override;
|
||||
bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error) override;
|
||||
bool SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, 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 DiscoverDevicesAndModes(const VideoIOConfiguration& config, std::string& error) override;
|
||||
bool SelectPreferredFormats(const VideoIOConfiguration& config, std::string& error) override;
|
||||
bool ConfigureInput(InputFrameCallback callback, std::string& error) override;
|
||||
bool ConfigureOutput(OutputFrameCallback callback, std::string& error) override;
|
||||
bool Start() override;
|
||||
bool Stop() override;
|
||||
|
||||
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;
|
||||
@@ -76,4 +49,5 @@ private:
|
||||
VideoPlayoutScheduler mScheduler;
|
||||
InputFrameCallback mInputFrameCallback;
|
||||
OutputFrameCallback mOutputFrameCallback;
|
||||
DeckLinkVideoModeSelection mConfiguredModes;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user