UI updates and preroll buffer to 8 frames
Some checks failed
CI / Native Windows Build And Tests (push) Has been cancelled
CI / React UI Build (push) Has been cancelled
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
2026-05-05 20:56:53 +10:00
parent 44316b29c2
commit be315111ea
9 changed files with 763 additions and 378 deletions

View File

@@ -63,6 +63,7 @@ constexpr GLuint kDecodedVideoTextureUnit = 1;
constexpr GLuint kSourceHistoryTextureUnitBase = 2;
constexpr GLuint kPackedVideoTextureUnit = 2;
constexpr GLuint kGlobalParamsBindingPoint = 0;
constexpr unsigned kPrerollFrameCount = 8;
const char* kVertexShaderSource =
"#version 430 core\n"
"out vec2 vTexCoord;\n"
@@ -1233,7 +1234,7 @@ bool OpenGLComposite::Start()
mTotalPlayoutFrames = 0;
// Preroll frames
for (unsigned i = 0; i < 5; i++)
for (unsigned i = 0; i < kPrerollFrameCount; i++)
{
// Take each video frame from the front of the queue and move it to the back
IDeckLinkMutableVideoFrame* outputVideoFrame = mDLOutputVideoFrameQueue.front();

View File

@@ -53,6 +53,25 @@ bool MatchesControlKey(const std::string& candidate, const std::string& key)
return candidate == key || SimplifyControlKey(candidate) == SimplifyControlKey(key);
}
bool TryParseLayerIdNumber(const std::string& layerId, uint64_t& number)
{
const std::string prefix = "layer-";
if (layerId.rfind(prefix, 0) != 0 || layerId.size() == prefix.size())
return false;
uint64_t parsed = 0;
for (std::size_t index = prefix.size(); index < layerId.size(); ++index)
{
const unsigned char ch = static_cast<unsigned char>(layerId[index]);
if (!std::isdigit(ch))
return false;
parsed = parsed * 10 + static_cast<uint64_t>(ch - '0');
}
number = parsed;
return true;
}
std::vector<double> JsonArrayToNumbers(const JsonValue& value)
{
std::vector<double> numbers;
@@ -583,6 +602,7 @@ bool RuntimeHost::Initialize(std::string& error)
return false;
if (!ScanShaderPackages(error))
return false;
NormalizePersistentLayerIdsLocked();
for (LayerPersistentState& layer : mPersistentState.layers)
{
@@ -1469,15 +1489,31 @@ bool RuntimeHost::WriteTextFile(const std::filesystem::path& path, const std::st
std::error_code fsError;
std::filesystem::create_directories(path.parent_path(), fsError);
std::ofstream output(path, std::ios::binary);
const std::filesystem::path temporaryPath = path.string() + ".tmp";
std::ofstream output(temporaryPath, std::ios::binary | std::ios::trunc);
if (!output)
{
error = "Could not write file: " + path.string();
error = "Could not write file: " + temporaryPath.string();
return false;
}
output << contents;
return output.good();
output.close();
if (!output.good())
{
error = "Could not finish writing file: " + temporaryPath.string();
return false;
}
if (!MoveFileExA(temporaryPath.string().c_str(), path.string().c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
{
const DWORD lastError = GetLastError();
std::filesystem::remove(temporaryPath, fsError);
error = "Could not replace file: " + path.string() + " (Win32 error " + std::to_string(lastError) + ")";
return false;
}
return true;
}
bool RuntimeHost::ResolvePaths(std::string& error)
@@ -1728,6 +1764,38 @@ bool RuntimeHost::DeserializeLayerStackLocked(const JsonValue& layersValue, std:
return true;
}
void RuntimeHost::NormalizePersistentLayerIdsLocked()
{
std::set<std::string> usedIds;
uint64_t maxLayerNumber = mNextLayerId;
for (LayerPersistentState& layer : mPersistentState.layers)
{
uint64_t layerNumber = 0;
const bool hasReusableId = !layer.id.empty() &&
usedIds.find(layer.id) == usedIds.end() &&
TryParseLayerIdNumber(layer.id, layerNumber);
if (hasReusableId)
{
usedIds.insert(layer.id);
maxLayerNumber = std::max(maxLayerNumber, layerNumber);
continue;
}
do
{
++maxLayerNumber;
layer.id = "layer-" + std::to_string(maxLayerNumber);
}
while (usedIds.find(layer.id) != usedIds.end());
usedIds.insert(layer.id);
}
mNextLayerId = maxLayerNumber;
}
std::vector<std::string> RuntimeHost::GetStackPresetNamesLocked() const
{
std::vector<std::string> presetNames;

View File

@@ -112,6 +112,7 @@ private:
JsonValue BuildStateValue() const;
JsonValue SerializeLayerStackLocked() const;
bool DeserializeLayerStackLocked(const JsonValue& layersValue, std::vector<LayerPersistentState>& layers, std::string& error);
void NormalizePersistentLayerIdsLocked();
std::vector<std::string> GetStackPresetNamesLocked() const;
std::string MakeSafePresetFileStem(const std::string& presetName) const;
JsonValue SerializeParameterValue(const ShaderParameterDefinition& definition, const ShaderParameterValue& value) const;