Decklink abstraction
This commit is contained in:
151
tests/VideoIODeviceFakeTests.cpp
Normal file
151
tests/VideoIODeviceFakeTests.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "VideoIOTypes.h"
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
int gFailures = 0;
|
||||
|
||||
void Expect(bool condition, const char* message)
|
||||
{
|
||||
if (condition)
|
||||
return;
|
||||
|
||||
std::cerr << "FAIL: " << message << "\n";
|
||||
++gFailures;
|
||||
}
|
||||
|
||||
class FakeVideoIODevice : public VideoIODevice
|
||||
{
|
||||
public:
|
||||
void ReleaseResources() override {}
|
||||
|
||||
bool DiscoverDevicesAndModes(const VideoFormatSelection&, std::string&) override
|
||||
{
|
||||
mState.inputFrameSize = { 1920, 1080 };
|
||||
mState.outputFrameSize = { 1920, 1080 };
|
||||
mState.inputDisplayModeName = "fake 1080p";
|
||||
mState.outputModelName = "Fake Video IO";
|
||||
mState.hasInputDevice = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SelectPreferredFormats(const VideoFormatSelection&, std::string&) override
|
||||
{
|
||||
mState.inputPixelFormat = VideoIOPixelFormat::Uyvy8;
|
||||
mState.outputPixelFormat = VideoIOPixelFormat::Bgra8;
|
||||
mState.inputFrameRowBytes = VideoIORowBytes(mState.inputPixelFormat, mState.inputFrameSize.width);
|
||||
mState.outputFrameRowBytes = VideoIORowBytes(mState.outputPixelFormat, mState.outputFrameSize.width);
|
||||
mState.captureTextureWidth = PackedTextureWidthFromRowBytes(mState.inputFrameRowBytes);
|
||||
mState.outputPackTextureWidth = mState.outputFrameSize.width;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigureInput(InputFrameCallback callback, const VideoFormat&, std::string&) override
|
||||
{
|
||||
mInputCallback = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigureOutput(OutputFrameCallback callback, const VideoFormat&, bool, std::string&) override
|
||||
{
|
||||
mOutputCallback = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Start() override
|
||||
{
|
||||
mState.hasInputSource = true;
|
||||
VideoIOFrame input;
|
||||
input.bytes = mInputBytes.data();
|
||||
input.rowBytes = static_cast<long>(mState.inputFrameRowBytes);
|
||||
input.width = mState.inputFrameSize.width;
|
||||
input.height = mState.inputFrameSize.height;
|
||||
input.pixelFormat = mState.inputPixelFormat;
|
||||
if (mInputCallback)
|
||||
mInputCallback(input);
|
||||
if (mOutputCallback)
|
||||
mOutputCallback(VideoIOCompletion{ VideoIOCompletionResult::Completed });
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Stop() override { return true; }
|
||||
const VideoIOState& State() const override { return mState; }
|
||||
VideoIOState& MutableState() override { return mState; }
|
||||
|
||||
bool BeginOutputFrame(VideoIOOutputFrame& frame) override
|
||||
{
|
||||
frame.bytes = mOutputBytes.data();
|
||||
frame.rowBytes = static_cast<long>(mState.outputFrameRowBytes);
|
||||
frame.width = mState.outputFrameSize.width;
|
||||
frame.height = mState.outputFrameSize.height;
|
||||
frame.pixelFormat = mState.outputPixelFormat;
|
||||
return true;
|
||||
}
|
||||
|
||||
void EndOutputFrame(VideoIOOutputFrame&) override {}
|
||||
|
||||
bool ScheduleOutputFrame(const VideoIOOutputFrame&) override
|
||||
{
|
||||
++mScheduledFrames;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AccountForCompletionResult(VideoIOCompletionResult result) override
|
||||
{
|
||||
mLastCompletion = result;
|
||||
}
|
||||
|
||||
unsigned ScheduledFrames() const { return mScheduledFrames; }
|
||||
VideoIOCompletionResult LastCompletion() const { return mLastCompletion; }
|
||||
|
||||
private:
|
||||
VideoIOState mState;
|
||||
InputFrameCallback mInputCallback;
|
||||
OutputFrameCallback mOutputCallback;
|
||||
std::array<unsigned char, 3840> mInputBytes = {};
|
||||
std::array<unsigned char, 7680> mOutputBytes = {};
|
||||
unsigned mScheduledFrames = 0;
|
||||
VideoIOCompletionResult mLastCompletion = VideoIOCompletionResult::Unknown;
|
||||
};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FakeVideoIODevice device;
|
||||
VideoFormatSelection selection;
|
||||
std::string error;
|
||||
bool inputSeen = false;
|
||||
bool outputSeen = false;
|
||||
|
||||
Expect(device.DiscoverDevicesAndModes(selection, error), "fake discovery succeeds");
|
||||
Expect(device.SelectPreferredFormats(selection, 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");
|
||||
Expect(device.ConfigureOutput([&](const VideoIOCompletion& completion) {
|
||||
outputSeen = completion.result == VideoIOCompletionResult::Completed;
|
||||
}, selection.output, false, error), "fake output config succeeds");
|
||||
Expect(device.Start(), "fake device starts");
|
||||
|
||||
VideoIOOutputFrame outputFrame;
|
||||
Expect(device.BeginOutputFrame(outputFrame), "fake output frame can be acquired");
|
||||
device.EndOutputFrame(outputFrame);
|
||||
device.AccountForCompletionResult(VideoIOCompletionResult::Completed);
|
||||
Expect(device.ScheduleOutputFrame(outputFrame), "fake output frame can be scheduled");
|
||||
|
||||
Expect(inputSeen, "fake input callback emits generic frame");
|
||||
Expect(outputSeen, "fake output callback emits generic completion");
|
||||
Expect(device.ScheduledFrames() == 1, "fake backend schedules one frame");
|
||||
Expect(device.LastCompletion() == VideoIOCompletionResult::Completed, "fake backend records generic completion");
|
||||
|
||||
if (gFailures != 0)
|
||||
{
|
||||
std::cerr << gFailures << " VideoIODevice fake test failure(s).\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "VideoIODevice fake tests passed.\n";
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user