Video backend
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m43s
CI / Windows Release Package (push) Successful in 2m54s

This commit is contained in:
Aiden
2026-05-09 14:15:49 +10:00
parent 98f5cbe309
commit 4ffbb97abf
21 changed files with 512 additions and 275 deletions

View File

@@ -0,0 +1,67 @@
#include "RuntimeHost.h"
#include <iostream>
namespace
{
int gFailures = 0;
void Expect(bool condition, const char* message)
{
if (condition)
return;
std::cerr << "FAIL: " << message << "\n";
++gFailures;
}
}
int main()
{
RuntimeHost runtimeHost;
std::string error;
Expect(runtimeHost.Initialize(error), "runtime host initializes");
Expect(error.empty(), "runtime host initialization does not report an error");
VideoIOState state;
state.backendId = VideoIOBackendId::DeckLink;
state.deviceName = "Test Device";
state.hasInputDevice = true;
state.hasInputSource = true;
state.inputDisplayModeName = "fake input";
state.outputDisplayModeName = "fake output";
state.capabilities.supportsInternalKeying = true;
state.capabilities.supportsExternalKeying = true;
state.capabilities.keyerInterfaceAvailable = true;
state.externalKeyingRequested = true;
state.externalKeyingActive = true;
state.statusMessage = "ready";
state.formatStatusMessage = "using fake formats";
runtimeHost.SetVideoIOStatus(state);
JsonValue root;
Expect(ParseJson(runtimeHost.BuildStateJson(), root, error), "runtime state json parses");
Expect(root.find("videoIO") != nullptr, "runtime state exposes videoIO");
Expect(root.find("decklink") == nullptr, "runtime state no longer exposes a decklink top-level block");
const JsonValue* app = root.find("app");
Expect(app != nullptr, "runtime state exposes app settings");
Expect(app != nullptr && app->find("videoBackend") != nullptr, "app settings expose videoBackend");
Expect(app != nullptr && app->find("videoBackend")->asString() == "decklink", "videoBackend serializes as decklink");
const JsonValue* videoIO = root.find("videoIO");
Expect(videoIO != nullptr && videoIO->find("backend") != nullptr, "videoIO exposes backend");
Expect(videoIO != nullptr && videoIO->find("backend")->asString() == "decklink", "videoIO backend serializes as decklink");
Expect(videoIO != nullptr && videoIO->find("deviceName") != nullptr, "videoIO exposes device name");
Expect(videoIO != nullptr && videoIO->find("deviceName")->asString() == "Test Device", "videoIO device name matches");
Expect(videoIO != nullptr && videoIO->find("capabilities") != nullptr, "videoIO exposes capabilities");
if (gFailures != 0)
{
std::cerr << gFailures << " RuntimeHost video I/O state test failure(s).\n";
return 1;
}
std::cout << "RuntimeHost video I/O state tests passed.\n";
return 0;
}

View File

@@ -0,0 +1,41 @@
#include "VideoIOBackendFactory.h"
#include "VideoIOTypes.h"
#include <iostream>
namespace
{
int gFailures = 0;
void Expect(bool condition, const char* message)
{
if (condition)
return;
std::cerr << "FAIL: " << message << "\n";
++gFailures;
}
}
int main()
{
std::string error;
std::unique_ptr<VideoIODevice> device = CreateVideoIODevice(VideoIOBackendId::DeckLink, error);
Expect(device != nullptr, "decklink backend factory returns a device");
Expect(!device || device->BackendId() == VideoIOBackendId::DeckLink, "decklink backend reports decklink id");
Expect(error.empty(), "supported backend does not produce an error");
error.clear();
device = CreateVideoIODevice(static_cast<VideoIOBackendId>(999), error);
Expect(device == nullptr, "unknown backend id is rejected");
Expect(!error.empty(), "unknown backend reports an error");
if (gFailures != 0)
{
std::cerr << gFailures << " VideoIO backend factory test failure(s).\n";
return 1;
}
std::cout << "VideoIO backend factory tests passed.\n";
return 0;
}

View File

@@ -19,20 +19,26 @@ void Expect(bool condition, const char* message)
class FakeVideoIODevice : public VideoIODevice
{
public:
VideoIOBackendId BackendId() const override { return VideoIOBackendId::DeckLink; }
void ReleaseResources() override {}
bool DiscoverDevicesAndModes(const VideoFormatSelection&, std::string&) override
bool DiscoverDevicesAndModes(const VideoIOConfiguration&, std::string&) override
{
mState.backendId = BackendId();
mState.inputFrameSize = { 1920, 1080 };
mState.outputFrameSize = { 1920, 1080 };
mState.inputDisplayModeName = "fake 1080p";
mState.outputModelName = "Fake Video IO";
mState.outputDisplayModeName = "fake 1080p";
mState.deviceName = "Fake Video IO";
mState.capabilities.supportsInternalKeying = true;
mState.capabilities.supportsExternalKeying = true;
mState.hasInputDevice = true;
return true;
}
bool SelectPreferredFormats(const VideoFormatSelection&, bool, std::string&) override
bool SelectPreferredFormats(const VideoIOConfiguration& config, std::string&) override
{
mState.externalKeyingRequested = config.externalKeyingEnabled;
mState.inputPixelFormat = VideoIOPixelFormat::Uyvy8;
mState.outputPixelFormat = VideoIOPixelFormat::Bgra8;
mState.inputFrameRowBytes = VideoIORowBytes(mState.inputPixelFormat, mState.inputFrameSize.width);
@@ -42,13 +48,13 @@ public:
return true;
}
bool ConfigureInput(InputFrameCallback callback, const VideoFormat&, std::string&) override
bool ConfigureInput(InputFrameCallback callback, std::string&) override
{
mInputCallback = callback;
return true;
}
bool ConfigureOutput(OutputFrameCallback callback, const VideoFormat&, bool, std::string&) override
bool ConfigureOutput(OutputFrameCallback callback, std::string&) override
{
mOutputCallback = callback;
return true;
@@ -114,19 +120,19 @@ private:
int main()
{
FakeVideoIODevice device;
VideoFormatSelection selection;
VideoIOConfiguration config;
std::string error;
bool inputSeen = false;
bool outputSeen = false;
Expect(device.DiscoverDevicesAndModes(selection, error), "fake discovery succeeds");
Expect(device.SelectPreferredFormats(selection, false, error), "fake format selection succeeds");
Expect(device.DiscoverDevicesAndModes(config, error), "fake discovery succeeds");
Expect(device.SelectPreferredFormats(config, error), "fake format selection succeeds");
Expect(device.ConfigureInput([&](const VideoIOFrame& frame) {
inputSeen = frame.bytes != nullptr && frame.width == 1920 && frame.pixelFormat == VideoIOPixelFormat::Uyvy8;
}, selection.input, error), "fake input config succeeds");
}, error), "fake input config succeeds");
Expect(device.ConfigureOutput([&](const VideoIOCompletion& completion) {
outputSeen = completion.result == VideoIOCompletionResult::Completed;
}, selection.output, false, error), "fake output config succeeds");
}, error), "fake output config succeeds");
Expect(device.Start(), "fake device starts");
VideoIOOutputFrame outputFrame;