Video format refactor
This commit is contained in:
@@ -14,6 +14,17 @@ std::string NormalizeModeToken(const std::string& value)
|
||||
}
|
||||
|
||||
bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::string& frameRate, BMDDisplayMode& displayMode, std::string& displayModeName)
|
||||
{
|
||||
VideoFormat videoMode;
|
||||
if (!ResolveConfiguredVideoFormat(videoFormat, frameRate, videoMode))
|
||||
return false;
|
||||
|
||||
displayMode = videoMode.displayMode;
|
||||
displayModeName = videoMode.displayName;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResolveConfiguredVideoFormat(const std::string& videoFormat, const std::string& frameRate, VideoFormat& videoMode)
|
||||
{
|
||||
const std::string formatToken = NormalizeModeToken(videoFormat);
|
||||
const std::string frameToken = NormalizeModeToken(frameRate);
|
||||
@@ -78,8 +89,8 @@ bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::str
|
||||
{
|
||||
if (combinedToken == option.token || (frameToken.empty() && formatToken == option.token))
|
||||
{
|
||||
displayMode = option.mode;
|
||||
displayModeName = option.displayName;
|
||||
videoMode.displayMode = option.mode;
|
||||
videoMode.displayName = option.displayName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -87,6 +98,31 @@ bool ResolveConfiguredDisplayMode(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,
|
||||
std::string& error)
|
||||
{
|
||||
if (!ResolveConfiguredVideoFormat(inputVideoFormat, inputFrameRate, videoModes.input))
|
||||
{
|
||||
error = "Unsupported DeckLink inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
|
||||
inputVideoFormat + " / " + inputFrameRate;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ResolveConfiguredVideoFormat(outputVideoFormat, outputFrameRate, videoModes.output))
|
||||
{
|
||||
error = "Unsupported DeckLink outputVideoFormat/outputFrameRate in config/runtime-host.json: " +
|
||||
outputVideoFormat + " / " + outputFrameRate;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindDeckLinkDisplayMode(IDeckLinkDisplayModeIterator* iterator, BMDDisplayMode targetMode, IDeckLinkDisplayMode** foundMode)
|
||||
{
|
||||
if (!iterator || !foundMode)
|
||||
|
||||
@@ -4,6 +4,44 @@
|
||||
|
||||
#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
|
||||
{
|
||||
BMDDisplayMode displayMode = bmdModeHD1080p5994;
|
||||
std::string displayName = "1080p59.94";
|
||||
};
|
||||
|
||||
struct VideoFormatSelection
|
||||
{
|
||||
VideoFormat input;
|
||||
VideoFormat 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,
|
||||
std::string& error);
|
||||
bool FindDeckLinkDisplayMode(IDeckLinkDisplayModeIterator* iterator, BMDDisplayMode targetMode, IDeckLinkDisplayMode** foundMode);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "DeckLinkSession.h"
|
||||
|
||||
#include "DeckLinkDisplayMode.h"
|
||||
#include "GlRenderConstants.h"
|
||||
|
||||
#include <atlbase.h>
|
||||
@@ -57,14 +56,14 @@ void DeckLinkSession::ReleaseResources()
|
||||
playoutAllocator.Release();
|
||||
}
|
||||
|
||||
bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, BMDDisplayMode outputDisplayMode, const std::string& requestedInputDisplayModeName, const std::string& requestedOutputDisplayModeName, std::string& error)
|
||||
bool DeckLinkSession::DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error)
|
||||
{
|
||||
CComPtr<IDeckLinkIterator> deckLinkIterator;
|
||||
CComPtr<IDeckLinkDisplayMode> inputMode;
|
||||
CComPtr<IDeckLinkDisplayMode> outputMode;
|
||||
|
||||
inputDisplayModeName = requestedInputDisplayModeName;
|
||||
outputDisplayModeName = requestedOutputDisplayModeName;
|
||||
inputDisplayModeName = videoModes.input.displayName;
|
||||
outputDisplayModeName = videoModes.output.displayName;
|
||||
|
||||
HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, nullptr, CLSCTX_ALL, IID_IDeckLinkIterator, reinterpret_cast<void**>(&deckLinkIterator));
|
||||
if (FAILED(result))
|
||||
@@ -143,9 +142,9 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
||||
return false;
|
||||
}
|
||||
|
||||
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, inputDisplayMode, &inputMode))
|
||||
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, videoModes.input.displayMode, &inputMode))
|
||||
{
|
||||
error = "Cannot get specified input BMDDisplayMode for configured mode: " + requestedInputDisplayModeName;
|
||||
error = "Cannot get specified input BMDDisplayMode for configured mode: " + videoModes.input.displayName;
|
||||
ReleaseResources();
|
||||
return false;
|
||||
}
|
||||
@@ -159,17 +158,17 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, outputDisplayMode, &outputMode))
|
||||
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, videoModes.output.displayMode, &outputMode))
|
||||
{
|
||||
error = "Cannot get specified output BMDDisplayMode for configured mode: " + requestedOutputDisplayModeName;
|
||||
error = "Cannot get specified output BMDDisplayMode for configured mode: " + videoModes.output.displayName;
|
||||
ReleaseResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
outputFrameWidth = outputMode->GetWidth();
|
||||
outputFrameHeight = outputMode->GetHeight();
|
||||
inputFrameWidth = inputMode ? inputMode->GetWidth() : outputFrameWidth;
|
||||
inputFrameHeight = inputMode ? inputMode->GetHeight() : outputFrameHeight;
|
||||
outputFrameSize = { static_cast<unsigned>(outputMode->GetWidth()), static_cast<unsigned>(outputMode->GetHeight()) };
|
||||
inputFrameSize = inputMode
|
||||
? FrameSize{ static_cast<unsigned>(inputMode->GetWidth()), static_cast<unsigned>(inputMode->GetHeight()) }
|
||||
: outputFrameSize;
|
||||
if (!input)
|
||||
inputDisplayModeName = "No input - black frame";
|
||||
outputMode->GetFrameRate(&frameDuration, &frameTimescale);
|
||||
@@ -177,7 +176,7 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode inputDisplayMode, std::string& error)
|
||||
bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, const VideoFormat& inputVideoMode, std::string& error)
|
||||
{
|
||||
if (!input)
|
||||
{
|
||||
@@ -188,7 +187,7 @@ bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglr
|
||||
|
||||
CComPtr<IDeckLinkVideoBufferAllocatorProvider> captureAllocator(new (std::nothrow) InputAllocatorPool(hdc, hglrc));
|
||||
|
||||
if (input->EnableVideoInputWithAllocatorProvider(inputDisplayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
|
||||
if (input->EnableVideoInputWithAllocatorProvider(inputVideoMode.displayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
|
||||
{
|
||||
OutputDebugStringA("DeckLink input could not be enabled; continuing in output-only black-frame mode.\n");
|
||||
input.Release();
|
||||
@@ -212,23 +211,23 @@ bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglr
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode outputDisplayMode, bool externalKeyingEnabled, std::string& error)
|
||||
bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error)
|
||||
{
|
||||
int outputFrameRowBytes = 0;
|
||||
if (output->RowBytesForPixelFormat(bmdFormat8BitBGRA, outputFrameWidth, &outputFrameRowBytes) != S_OK)
|
||||
if (output->RowBytesForPixelFormat(bmdFormat8BitBGRA, outputFrameSize.width, &outputFrameRowBytes) != S_OK)
|
||||
{
|
||||
error = "DeckLink output setup failed while calculating BGRA row bytes.";
|
||||
return false;
|
||||
}
|
||||
|
||||
playoutAllocator.Attach(new (std::nothrow) PinnedMemoryAllocator(hdc, hglrc, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * outputFrameHeight));
|
||||
playoutAllocator.Attach(new (std::nothrow) PinnedMemoryAllocator(hdc, hglrc, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * outputFrameSize.height));
|
||||
if (playoutAllocator == nullptr)
|
||||
{
|
||||
error = "DeckLink output setup failed while creating the playout allocator.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output->EnableVideoOutput(outputDisplayMode, bmdVideoOutputFlagDefault) != S_OK)
|
||||
if (output->EnableVideoOutput(outputVideoMode.displayMode, bmdVideoOutputFlagDefault) != S_OK)
|
||||
{
|
||||
error = "DeckLink output setup failed while enabling video output.";
|
||||
return false;
|
||||
@@ -273,7 +272,7 @@ bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hgl
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output->CreateVideoFrameWithBuffer(outputFrameWidth, outputFrameHeight, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
|
||||
if (output->CreateVideoFrameWithBuffer(outputFrameSize.width, outputFrameSize.height, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
|
||||
{
|
||||
error = "DeckLink output setup failed while creating an output video frame.";
|
||||
return false;
|
||||
@@ -374,7 +373,7 @@ bool DeckLinkSession::Start()
|
||||
|
||||
void* pFrame;
|
||||
outputVideoFrameBuffer->GetBytes((void**)&pFrame);
|
||||
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * outputFrameHeight);
|
||||
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * outputFrameSize.height);
|
||||
|
||||
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "DeckLinkAPI_h.h"
|
||||
#include "DeckLinkDisplayMode.h"
|
||||
#include "DeckLinkFrameTransfer.h"
|
||||
|
||||
#include <atlbase.h>
|
||||
@@ -16,20 +17,22 @@ public:
|
||||
~DeckLinkSession();
|
||||
|
||||
void ReleaseResources();
|
||||
bool DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, BMDDisplayMode outputDisplayMode, const std::string& requestedInputDisplayModeName, const std::string& requestedOutputDisplayModeName, std::string& error);
|
||||
bool ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode inputDisplayMode, std::string& error);
|
||||
bool ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode outputDisplayMode, bool externalKeyingEnabled, std::string& error);
|
||||
bool DiscoverDevicesAndModes(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();
|
||||
|
||||
bool HasInputDevice() const { return input != nullptr; }
|
||||
bool HasInputSource() const { return !hasNoInputSource; }
|
||||
void SetInputSourceMissing(bool missing) { hasNoInputSource = missing; }
|
||||
bool InputOutputDimensionsDiffer() const { return inputFrameWidth != outputFrameWidth || inputFrameHeight != outputFrameHeight; }
|
||||
unsigned InputFrameWidth() const { return inputFrameWidth; }
|
||||
unsigned InputFrameHeight() const { return inputFrameHeight; }
|
||||
unsigned OutputFrameWidth() const { return outputFrameWidth; }
|
||||
unsigned OutputFrameHeight() const { return outputFrameHeight; }
|
||||
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; }
|
||||
const std::string& InputDisplayModeName() const { return inputDisplayModeName; }
|
||||
const std::string& OutputModelName() const { return outputModelName; }
|
||||
bool SupportsInternalKeying() const { return supportsInternalKeying; }
|
||||
@@ -56,10 +59,8 @@ private:
|
||||
BMDTimeValue frameDuration = 0;
|
||||
BMDTimeScale frameTimescale = 0;
|
||||
unsigned totalPlayoutFrames = 0;
|
||||
unsigned inputFrameWidth = 0;
|
||||
unsigned inputFrameHeight = 0;
|
||||
unsigned outputFrameWidth = 0;
|
||||
unsigned outputFrameHeight = 0;
|
||||
FrameSize inputFrameSize;
|
||||
FrameSize outputFrameSize;
|
||||
std::string inputDisplayModeName = "1080p59.94";
|
||||
std::string outputDisplayModeName = "1080p59.94";
|
||||
bool hasNoInputSource = true;
|
||||
|
||||
@@ -97,10 +97,7 @@ OpenGLComposite::~OpenGLComposite()
|
||||
|
||||
bool OpenGLComposite::InitDeckLink()
|
||||
{
|
||||
BMDDisplayMode inputDisplayMode = bmdModeHD1080p5994;
|
||||
BMDDisplayMode outputDisplayMode = bmdModeHD1080p5994;
|
||||
std::string inputDisplayModeName = "1080p59.94";
|
||||
std::string outputDisplayModeName = "1080p59.94";
|
||||
VideoFormatSelection videoModes;
|
||||
std::string initFailureReason;
|
||||
|
||||
if (mRuntimeHost && mRuntimeHost->GetRepoRoot().empty())
|
||||
@@ -115,23 +112,20 @@ bool OpenGLComposite::InitDeckLink()
|
||||
|
||||
if (mRuntimeHost)
|
||||
{
|
||||
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetInputVideoFormat(), mRuntimeHost->GetInputFrameRate(), inputDisplayMode, inputDisplayModeName))
|
||||
if (!ResolveConfiguredVideoFormats(
|
||||
mRuntimeHost->GetInputVideoFormat(),
|
||||
mRuntimeHost->GetInputFrameRate(),
|
||||
mRuntimeHost->GetOutputVideoFormat(),
|
||||
mRuntimeHost->GetOutputFrameRate(),
|
||||
videoModes,
|
||||
initFailureReason))
|
||||
{
|
||||
const std::string error = "Unsupported DeckLink inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
|
||||
mRuntimeHost->GetInputVideoFormat() + " / " + mRuntimeHost->GetInputFrameRate();
|
||||
MessageBoxA(NULL, error.c_str(), "DeckLink input mode configuration error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetOutputVideoFormat(), mRuntimeHost->GetOutputFrameRate(), outputDisplayMode, outputDisplayModeName))
|
||||
{
|
||||
const std::string error = "Unsupported DeckLink outputVideoFormat/outputFrameRate in config/runtime-host.json: " +
|
||||
mRuntimeHost->GetOutputVideoFormat() + " / " + mRuntimeHost->GetOutputFrameRate();
|
||||
MessageBoxA(NULL, error.c_str(), "DeckLink output mode configuration error", MB_OK);
|
||||
MessageBoxA(NULL, initFailureReason.c_str(), "DeckLink mode configuration error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDeckLink->DiscoverDevicesAndModes(inputDisplayMode, outputDisplayMode, inputDisplayModeName, outputDisplayModeName, initFailureReason))
|
||||
if (!mDeckLink->DiscoverDevicesAndModes(videoModes, initFailureReason))
|
||||
{
|
||||
const char* title = initFailureReason == "Please install the Blackmagic DeckLink drivers to use the features of this application."
|
||||
? "This application requires the DeckLink drivers installed."
|
||||
@@ -177,7 +171,7 @@ bool OpenGLComposite::InitDeckLink()
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDeckLink->ConfigureInput(this, hGLDC, hGLRC, inputDisplayMode, initFailureReason))
|
||||
if (!mDeckLink->ConfigureInput(this, hGLDC, hGLRC, videoModes.input, initFailureReason))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
@@ -186,7 +180,7 @@ bool OpenGLComposite::InitDeckLink()
|
||||
mRuntimeHost->SetSignalStatus(false, mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight(), mDeckLink->InputDisplayModeName());
|
||||
}
|
||||
|
||||
if (!mDeckLink->ConfigureOutput(this, hGLDC, hGLRC, outputDisplayMode, mRuntimeHost && mRuntimeHost->ExternalKeyingEnabled(), initFailureReason))
|
||||
if (!mDeckLink->ConfigureOutput(this, hGLDC, hGLRC, videoModes.output, mRuntimeHost && mRuntimeHost->ExternalKeyingEnabled(), initFailureReason))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user