Video format
This commit is contained in:
@@ -74,7 +74,7 @@ END
|
|||||||
|
|
||||||
STRINGTABLE
|
STRINGTABLE
|
||||||
BEGIN
|
BEGIN
|
||||||
IDS_APP_TITLE "LoopThroughWithOpenGLCompositing"
|
IDS_APP_TITLE "Video Shader Toys"
|
||||||
IDC_OPENGLOUTPUT "OPENGLOUTPUT"
|
IDC_OPENGLOUTPUT "OPENGLOUTPUT"
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cctype>
|
||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -61,7 +62,6 @@ constexpr GLuint kDecodedVideoTextureUnit = 1;
|
|||||||
constexpr GLuint kSourceHistoryTextureUnitBase = 2;
|
constexpr GLuint kSourceHistoryTextureUnitBase = 2;
|
||||||
constexpr GLuint kPackedVideoTextureUnit = 2;
|
constexpr GLuint kPackedVideoTextureUnit = 2;
|
||||||
constexpr GLuint kGlobalParamsBindingPoint = 0;
|
constexpr GLuint kGlobalParamsBindingPoint = 0;
|
||||||
const char* kDisplayModeName = "1080p59.94";
|
|
||||||
const char* kVertexShaderSource =
|
const char* kVertexShaderSource =
|
||||||
"#version 430 core\n"
|
"#version 430 core\n"
|
||||||
"out vec2 vTexCoord;\n"
|
"out vec2 vTexCoord;\n"
|
||||||
@@ -106,6 +106,91 @@ void CopyErrorMessage(const std::string& message, int errorMessageSize, char* er
|
|||||||
strncpy_s(errorMessage, errorMessageSize, message.c_str(), _TRUNCATE);
|
strncpy_s(errorMessage, errorMessageSize, message.c_str(), _TRUNCATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string NormalizeModeToken(const std::string& value)
|
||||||
|
{
|
||||||
|
std::string normalized;
|
||||||
|
for (unsigned char ch : value)
|
||||||
|
{
|
||||||
|
if (std::isalnum(ch))
|
||||||
|
normalized.push_back(static_cast<char>(std::tolower(ch)));
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::string& frameRate, BMDDisplayMode& displayMode, std::string& displayModeName)
|
||||||
|
{
|
||||||
|
const std::string formatToken = NormalizeModeToken(videoFormat);
|
||||||
|
const std::string frameToken = NormalizeModeToken(frameRate);
|
||||||
|
const std::string combinedToken = formatToken + frameToken;
|
||||||
|
|
||||||
|
struct ModeOption
|
||||||
|
{
|
||||||
|
const char* token;
|
||||||
|
BMDDisplayMode mode;
|
||||||
|
const char* displayName;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ModeOption options[] =
|
||||||
|
{
|
||||||
|
{ "720p50", bmdModeHD720p50, "720p50" },
|
||||||
|
{ "hd720p50", bmdModeHD720p50, "720p50" },
|
||||||
|
{ "720p5994", bmdModeHD720p5994, "720p59.94" },
|
||||||
|
{ "hd720p5994", bmdModeHD720p5994, "720p59.94" },
|
||||||
|
{ "720p60", bmdModeHD720p60, "720p60" },
|
||||||
|
{ "hd720p60", bmdModeHD720p60, "720p60" },
|
||||||
|
{ "1080i50", bmdModeHD1080i50, "1080i50" },
|
||||||
|
{ "hd1080i50", bmdModeHD1080i50, "1080i50" },
|
||||||
|
{ "1080i5994", bmdModeHD1080i5994, "1080i59.94" },
|
||||||
|
{ "hd1080i5994", bmdModeHD1080i5994, "1080i59.94" },
|
||||||
|
{ "1080i60", bmdModeHD1080i6000, "1080i60" },
|
||||||
|
{ "hd1080i60", bmdModeHD1080i6000, "1080i60" },
|
||||||
|
{ "1080p2398", bmdModeHD1080p2398, "1080p23.98" },
|
||||||
|
{ "hd1080p2398", bmdModeHD1080p2398, "1080p23.98" },
|
||||||
|
{ "1080p24", bmdModeHD1080p24, "1080p24" },
|
||||||
|
{ "hd1080p24", bmdModeHD1080p24, "1080p24" },
|
||||||
|
{ "1080p25", bmdModeHD1080p25, "1080p25" },
|
||||||
|
{ "hd1080p25", bmdModeHD1080p25, "1080p25" },
|
||||||
|
{ "1080p2997", bmdModeHD1080p2997, "1080p29.97" },
|
||||||
|
{ "hd1080p2997", bmdModeHD1080p2997, "1080p29.97" },
|
||||||
|
{ "1080p30", bmdModeHD1080p30, "1080p30" },
|
||||||
|
{ "hd1080p30", bmdModeHD1080p30, "1080p30" },
|
||||||
|
{ "1080p50", bmdModeHD1080p50, "1080p50" },
|
||||||
|
{ "hd1080p50", bmdModeHD1080p50, "1080p50" },
|
||||||
|
{ "1080p5994", bmdModeHD1080p5994, "1080p59.94" },
|
||||||
|
{ "hd1080p5994", bmdModeHD1080p5994, "1080p59.94" },
|
||||||
|
{ "1080p60", bmdModeHD1080p6000, "1080p60" },
|
||||||
|
{ "hd1080p60", bmdModeHD1080p6000, "1080p60" },
|
||||||
|
{ "2160p2398", bmdMode4K2160p2398, "2160p23.98" },
|
||||||
|
{ "4k2160p2398", bmdMode4K2160p2398, "2160p23.98" },
|
||||||
|
{ "2160p24", bmdMode4K2160p24, "2160p24" },
|
||||||
|
{ "4k2160p24", bmdMode4K2160p24, "2160p24" },
|
||||||
|
{ "2160p25", bmdMode4K2160p25, "2160p25" },
|
||||||
|
{ "4k2160p25", bmdMode4K2160p25, "2160p25" },
|
||||||
|
{ "2160p2997", bmdMode4K2160p2997, "2160p29.97" },
|
||||||
|
{ "4k2160p2997", bmdMode4K2160p2997, "2160p29.97" },
|
||||||
|
{ "2160p30", bmdMode4K2160p30, "2160p30" },
|
||||||
|
{ "4k2160p30", bmdMode4K2160p30, "2160p30" },
|
||||||
|
{ "2160p50", bmdMode4K2160p50, "2160p50" },
|
||||||
|
{ "4k2160p50", bmdMode4K2160p50, "2160p50" },
|
||||||
|
{ "2160p5994", bmdMode4K2160p5994, "2160p59.94" },
|
||||||
|
{ "4k2160p5994", bmdMode4K2160p5994, "2160p59.94" },
|
||||||
|
{ "2160p60", bmdMode4K2160p60, "2160p60" },
|
||||||
|
{ "4k2160p60", bmdMode4K2160p60, "2160p60" }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const ModeOption& option : options)
|
||||||
|
{
|
||||||
|
if (combinedToken == option.token || (frameToken.empty() && formatToken == option.token))
|
||||||
|
{
|
||||||
|
displayMode = option.mode;
|
||||||
|
displayModeName = option.displayName;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class ScopedGlShader
|
class ScopedGlShader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -210,6 +295,7 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
|||||||
mDLInput(NULL), mDLOutput(NULL), mDLKeyer(NULL),
|
mDLInput(NULL), mDLOutput(NULL), mDLKeyer(NULL),
|
||||||
mPlayoutAllocator(NULL),
|
mPlayoutAllocator(NULL),
|
||||||
mFrameWidth(0), mFrameHeight(0),
|
mFrameWidth(0), mFrameHeight(0),
|
||||||
|
mDisplayModeName("1080p59.94"),
|
||||||
mHasNoInputSource(true),
|
mHasNoInputSource(true),
|
||||||
mDeckLinkSupportsInternalKeying(false),
|
mDeckLinkSupportsInternalKeying(false),
|
||||||
mDeckLinkSupportsExternalKeying(false),
|
mDeckLinkSupportsExternalKeying(false),
|
||||||
@@ -340,9 +426,32 @@ bool OpenGLComposite::InitDeckLink()
|
|||||||
IDeckLinkDisplayModeIterator* pDLDisplayModeIterator = NULL;
|
IDeckLinkDisplayModeIterator* pDLDisplayModeIterator = NULL;
|
||||||
IDeckLinkDisplayMode* pDLDisplayMode = NULL;
|
IDeckLinkDisplayMode* pDLDisplayMode = NULL;
|
||||||
BMDDisplayMode displayMode = bmdModeHD1080p5994; // mode to use for capture and playout
|
BMDDisplayMode displayMode = bmdModeHD1080p5994; // mode to use for capture and playout
|
||||||
|
std::string displayModeName = "1080p59.94";
|
||||||
int outputFrameRowBytes;
|
int outputFrameRowBytes;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
|
|
||||||
|
if (mRuntimeHost && mRuntimeHost->GetRepoRoot().empty())
|
||||||
|
{
|
||||||
|
std::string runtimeError;
|
||||||
|
if (!mRuntimeHost->Initialize(runtimeError))
|
||||||
|
{
|
||||||
|
MessageBoxA(NULL, runtimeError.c_str(), "Runtime host failed to initialize", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRuntimeHost)
|
||||||
|
{
|
||||||
|
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetVideoFormat(), mRuntimeHost->GetFrameRate(), displayMode, displayModeName))
|
||||||
|
{
|
||||||
|
const std::string error = "Unsupported DeckLink video format/frameRate in config/runtime-host.json: " +
|
||||||
|
mRuntimeHost->GetVideoFormat() + " / " + mRuntimeHost->GetFrameRate();
|
||||||
|
MessageBoxA(NULL, error.c_str(), "DeckLink mode configuration error", MB_OK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDisplayModeName = displayModeName;
|
||||||
|
|
||||||
result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&pDLIterator);
|
result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&pDLIterator);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
@@ -444,7 +553,8 @@ bool OpenGLComposite::InitDeckLink()
|
|||||||
|
|
||||||
if (pDLDisplayMode == NULL)
|
if (pDLDisplayMode == NULL)
|
||||||
{
|
{
|
||||||
MessageBox(NULL, _T("Cannot get specified BMDDisplayMode."), _T("DeckLink error."), MB_OK);
|
const std::string error = "Cannot get specified BMDDisplayMode for configured mode: " + displayModeName;
|
||||||
|
MessageBoxA(NULL, error.c_str(), "DeckLink error.", MB_OK);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +807,7 @@ bool OpenGLComposite::InitOpenGLState()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string runtimeError;
|
std::string runtimeError;
|
||||||
if (!mRuntimeHost->Initialize(runtimeError))
|
if (mRuntimeHost->GetRepoRoot().empty() && !mRuntimeHost->Initialize(runtimeError))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, runtimeError.c_str(), "Runtime host failed to initialize", MB_OK);
|
MessageBoxA(NULL, runtimeError.c_str(), "Runtime host failed to initialize", MB_OK);
|
||||||
return false;
|
return false;
|
||||||
@@ -867,7 +977,7 @@ void OpenGLComposite::VideoFrameArrived(IDeckLinkVideoInputFrame* inputFrame, bo
|
|||||||
{
|
{
|
||||||
mHasNoInputSource = hasNoInputSource;
|
mHasNoInputSource = hasNoInputSource;
|
||||||
if (mRuntimeHost)
|
if (mRuntimeHost)
|
||||||
mRuntimeHost->SetSignalStatus(!hasNoInputSource, mFrameWidth, mFrameHeight, kDisplayModeName);
|
mRuntimeHost->SetSignalStatus(!hasNoInputSource, mFrameWidth, mFrameHeight, mDisplayModeName);
|
||||||
|
|
||||||
if (mHasNoInputSource)
|
if (mHasNoInputSource)
|
||||||
return; // don't transfer texture when there's no input
|
return; // don't transfer texture when there's no input
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ private:
|
|||||||
unsigned mTotalPlayoutFrames;
|
unsigned mTotalPlayoutFrames;
|
||||||
unsigned mFrameWidth;
|
unsigned mFrameWidth;
|
||||||
unsigned mFrameHeight;
|
unsigned mFrameHeight;
|
||||||
|
std::string mDisplayModeName;
|
||||||
bool mHasNoInputSource;
|
bool mHasNoInputSource;
|
||||||
std::string mDeckLinkOutputModelName;
|
std::string mDeckLinkOutputModelName;
|
||||||
bool mDeckLinkSupportsInternalKeying;
|
bool mDeckLinkSupportsInternalKeying;
|
||||||
|
|||||||
@@ -1118,6 +1118,22 @@ bool RuntimeHost::LoadConfig(std::string& error)
|
|||||||
}
|
}
|
||||||
if (const JsonValue* enableExternalKeyingValue = configJson.find("enableExternalKeying"))
|
if (const JsonValue* enableExternalKeyingValue = configJson.find("enableExternalKeying"))
|
||||||
mConfig.enableExternalKeying = enableExternalKeyingValue->asBoolean(mConfig.enableExternalKeying);
|
mConfig.enableExternalKeying = enableExternalKeyingValue->asBoolean(mConfig.enableExternalKeying);
|
||||||
|
if (const JsonValue* videoFormatValue = configJson.find("videoFormat"))
|
||||||
|
{
|
||||||
|
if (videoFormatValue->isString() && !videoFormatValue->asString().empty())
|
||||||
|
mConfig.videoFormat = videoFormatValue->asString();
|
||||||
|
}
|
||||||
|
if (const JsonValue* frameRateValue = configJson.find("frameRate"))
|
||||||
|
{
|
||||||
|
if (frameRateValue->isString() && !frameRateValue->asString().empty())
|
||||||
|
mConfig.frameRate = frameRateValue->asString();
|
||||||
|
else if (frameRateValue->isNumber())
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << frameRateValue->asNumber();
|
||||||
|
mConfig.frameRate = stream.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mAutoReloadEnabled = mConfig.autoReload;
|
mAutoReloadEnabled = mConfig.autoReload;
|
||||||
return true;
|
return true;
|
||||||
@@ -1398,6 +1414,8 @@ JsonValue RuntimeHost::BuildStateValue() const
|
|||||||
app.set("autoReload", JsonValue(mAutoReloadEnabled));
|
app.set("autoReload", JsonValue(mAutoReloadEnabled));
|
||||||
app.set("maxTemporalHistoryFrames", JsonValue(static_cast<double>(mConfig.maxTemporalHistoryFrames)));
|
app.set("maxTemporalHistoryFrames", JsonValue(static_cast<double>(mConfig.maxTemporalHistoryFrames)));
|
||||||
app.set("enableExternalKeying", JsonValue(mConfig.enableExternalKeying));
|
app.set("enableExternalKeying", JsonValue(mConfig.enableExternalKeying));
|
||||||
|
app.set("videoFormat", JsonValue(mConfig.videoFormat));
|
||||||
|
app.set("frameRate", JsonValue(mConfig.frameRate));
|
||||||
root.set("app", app);
|
root.set("app", app);
|
||||||
|
|
||||||
JsonValue runtime = JsonValue::MakeObject();
|
JsonValue runtime = JsonValue::MakeObject();
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ public:
|
|||||||
unsigned short GetServerPort() const { return mServerPort; }
|
unsigned short GetServerPort() const { return mServerPort; }
|
||||||
unsigned GetMaxTemporalHistoryFrames() const { return mConfig.maxTemporalHistoryFrames; }
|
unsigned GetMaxTemporalHistoryFrames() const { return mConfig.maxTemporalHistoryFrames; }
|
||||||
bool ExternalKeyingEnabled() const { return mConfig.enableExternalKeying; }
|
bool ExternalKeyingEnabled() const { return mConfig.enableExternalKeying; }
|
||||||
|
const std::string& GetVideoFormat() const { return mConfig.videoFormat; }
|
||||||
|
const std::string& GetFrameRate() const { return mConfig.frameRate; }
|
||||||
void SetServerPort(unsigned short port);
|
void SetServerPort(unsigned short port);
|
||||||
bool AutoReloadEnabled() const { return mAutoReloadEnabled; }
|
bool AutoReloadEnabled() const { return mAutoReloadEnabled; }
|
||||||
|
|
||||||
@@ -60,6 +62,8 @@ private:
|
|||||||
bool autoReload = true;
|
bool autoReload = true;
|
||||||
unsigned maxTemporalHistoryFrames = 4;
|
unsigned maxTemporalHistoryFrames = 4;
|
||||||
bool enableExternalKeying = false;
|
bool enableExternalKeying = false;
|
||||||
|
std::string videoFormat = "1080p";
|
||||||
|
std::string frameRate = "59.94";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeckLinkOutputStatus
|
struct DeckLinkOutputStatus
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"shaderLibrary": "shaders",
|
"shaderLibrary": "shaders",
|
||||||
"serverPort": 8080,
|
"serverPort": 8080,
|
||||||
|
"videoFormat": "1080p",
|
||||||
|
"frameRate": "59.94",
|
||||||
"autoReload": true,
|
"autoReload": true,
|
||||||
"maxTemporalHistoryFrames": 12,
|
"maxTemporalHistoryFrames": 12,
|
||||||
"enableExternalKeying": true
|
"enableExternalKeying": true
|
||||||
|
|||||||
Reference in New Issue
Block a user