161 lines
6.0 KiB
C++
161 lines
6.0 KiB
C++
#include "InputFrameMailbox.h"
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
namespace
|
|
{
|
|
int gFailures = 0;
|
|
|
|
void Expect(bool condition, const char* message)
|
|
{
|
|
if (condition)
|
|
return;
|
|
|
|
++gFailures;
|
|
std::cerr << "FAIL: " << message << "\n";
|
|
}
|
|
|
|
InputFrameMailboxConfig MakeConfig(std::size_t capacity = 2)
|
|
{
|
|
InputFrameMailboxConfig config;
|
|
config.width = 2;
|
|
config.height = 2;
|
|
config.pixelFormat = VideoIOPixelFormat::Bgra8;
|
|
config.rowBytes = VideoIORowBytes(config.pixelFormat, config.width);
|
|
config.capacity = capacity;
|
|
return config;
|
|
}
|
|
|
|
InputFrameMailboxConfig MakeBufferedConfig(std::size_t capacity = 4, std::size_t maxReadyFrames = 2)
|
|
{
|
|
InputFrameMailboxConfig config = MakeConfig(capacity);
|
|
config.maxReadyFrames = maxReadyFrames;
|
|
return config;
|
|
}
|
|
|
|
std::vector<unsigned char> MakeFrame(unsigned char value)
|
|
{
|
|
return std::vector<unsigned char>(16, value);
|
|
}
|
|
|
|
void TestAcquireLatestDropsOlderReadyFrames()
|
|
{
|
|
InputFrameMailbox mailbox(MakeConfig(3));
|
|
const std::vector<unsigned char> frame1 = MakeFrame(1);
|
|
const std::vector<unsigned char> frame2 = MakeFrame(2);
|
|
const std::vector<unsigned char> frame3 = MakeFrame(3);
|
|
|
|
Expect(mailbox.SubmitFrame(frame1.data(), 8, 1), "first input frame submits");
|
|
Expect(mailbox.SubmitFrame(frame2.data(), 8, 2), "second input frame submits");
|
|
Expect(mailbox.SubmitFrame(frame3.data(), 8, 3), "third input frame submits");
|
|
|
|
InputFrame latest;
|
|
Expect(mailbox.TryAcquireLatest(latest), "latest input frame can be acquired");
|
|
Expect(latest.frameIndex == 3, "mailbox returns newest frame");
|
|
Expect(latest.bytes != nullptr && static_cast<const unsigned char*>(latest.bytes)[0] == 3, "latest frame bytes match newest frame");
|
|
Expect(mailbox.Release(latest), "latest input frame can be released");
|
|
|
|
const InputFrameMailboxMetrics metrics = mailbox.Metrics();
|
|
Expect(metrics.droppedReadyFrames == 2, "older ready input frames are dropped after latest acquire");
|
|
Expect(metrics.freeCount == 3, "all slots are free after release");
|
|
}
|
|
|
|
void TestSubmitDropsOldestWhenFull()
|
|
{
|
|
InputFrameMailbox mailbox(MakeConfig(2));
|
|
const std::vector<unsigned char> frame1 = MakeFrame(1);
|
|
const std::vector<unsigned char> frame2 = MakeFrame(2);
|
|
const std::vector<unsigned char> frame3 = MakeFrame(3);
|
|
|
|
Expect(mailbox.SubmitFrame(frame1.data(), 8, 1), "first frame submits into full test");
|
|
Expect(mailbox.SubmitFrame(frame2.data(), 8, 2), "second frame submits into full test");
|
|
Expect(mailbox.SubmitFrame(frame3.data(), 8, 3), "third frame submits by dropping oldest ready frame");
|
|
|
|
InputFrame latest;
|
|
Expect(mailbox.TryAcquireLatest(latest), "latest frame available after drop");
|
|
Expect(latest.frameIndex == 3, "newest frame survived full mailbox");
|
|
Expect(mailbox.Release(latest), "newest frame releases");
|
|
|
|
const InputFrameMailboxMetrics metrics = mailbox.Metrics();
|
|
Expect(metrics.droppedReadyFrames >= 1, "full mailbox records ready drop");
|
|
Expect(metrics.submitMisses == 0, "full mailbox did not block producer when ready slots were disposable");
|
|
}
|
|
|
|
void TestReadingFrameIsProtected()
|
|
{
|
|
InputFrameMailbox mailbox(MakeConfig(1));
|
|
const std::vector<unsigned char> frame1 = MakeFrame(1);
|
|
const std::vector<unsigned char> frame2 = MakeFrame(2);
|
|
|
|
Expect(mailbox.SubmitFrame(frame1.data(), 8, 1), "protected frame submits");
|
|
InputFrame acquired;
|
|
Expect(mailbox.TryAcquireLatest(acquired), "protected frame acquired");
|
|
Expect(!mailbox.SubmitFrame(frame2.data(), 8, 2), "producer cannot overwrite frame currently being read");
|
|
Expect(mailbox.Release(acquired), "protected frame releases");
|
|
Expect(mailbox.SubmitFrame(frame2.data(), 8, 2), "producer can submit after release");
|
|
}
|
|
|
|
void TestAcquireOldestConsumesFifoWithoutDroppingReadyFrames()
|
|
{
|
|
InputFrameMailbox mailbox(MakeConfig(3));
|
|
const std::vector<unsigned char> frame1 = MakeFrame(1);
|
|
const std::vector<unsigned char> frame2 = MakeFrame(2);
|
|
|
|
Expect(mailbox.SubmitFrame(frame1.data(), 8, 1), "fifo first frame submits");
|
|
Expect(mailbox.SubmitFrame(frame2.data(), 8, 2), "fifo second frame submits");
|
|
|
|
InputFrame acquired;
|
|
Expect(mailbox.TryAcquireOldest(acquired), "fifo oldest frame acquired");
|
|
Expect(acquired.frameIndex == 1, "fifo acquire returns oldest frame");
|
|
Expect(mailbox.Release(acquired), "fifo acquired frame releases");
|
|
|
|
const InputFrameMailboxMetrics metrics = mailbox.Metrics();
|
|
Expect(metrics.readyCount == 1, "fifo acquire leaves newer frame ready");
|
|
Expect(metrics.droppedReadyFrames == 0, "fifo acquire does not drop newer ready frame");
|
|
}
|
|
|
|
void TestMaxReadyFramesKeepsConfiguredInputBuffer()
|
|
{
|
|
InputFrameMailbox mailbox(MakeBufferedConfig(4, 3));
|
|
const std::vector<unsigned char> frame1 = MakeFrame(1);
|
|
const std::vector<unsigned char> frame2 = MakeFrame(2);
|
|
const std::vector<unsigned char> frame3 = MakeFrame(3);
|
|
const std::vector<unsigned char> frame4 = MakeFrame(4);
|
|
|
|
Expect(mailbox.SubmitFrame(frame1.data(), 8, 1), "bounded first frame submits");
|
|
Expect(mailbox.SubmitFrame(frame2.data(), 8, 2), "bounded second frame submits");
|
|
Expect(mailbox.SubmitFrame(frame3.data(), 8, 3), "bounded third frame submits");
|
|
Expect(mailbox.SubmitFrame(frame4.data(), 8, 4), "bounded fourth frame submits");
|
|
|
|
InputFrame acquired;
|
|
Expect(mailbox.TryAcquireOldest(acquired), "bounded oldest available frame acquired");
|
|
Expect(acquired.frameIndex == 2, "bounded buffer trims oldest beyond configured ready frame limit");
|
|
Expect(mailbox.Release(acquired), "bounded acquired frame releases");
|
|
|
|
const InputFrameMailboxMetrics metrics = mailbox.Metrics();
|
|
Expect(metrics.readyCount == 2, "bounded acquire leaves remaining configured ready frames");
|
|
Expect(metrics.droppedReadyFrames == 1, "bounded buffer records trimmed frame");
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
TestAcquireLatestDropsOlderReadyFrames();
|
|
TestSubmitDropsOldestWhenFull();
|
|
TestReadingFrameIsProtected();
|
|
TestAcquireOldestConsumesFifoWithoutDroppingReadyFrames();
|
|
TestMaxReadyFramesKeepsConfiguredInputBuffer();
|
|
|
|
if (gFailures != 0)
|
|
{
|
|
std::cerr << gFailures << " RenderCadenceCompositorInputFrameMailbox test failure(s).\n";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "RenderCadenceCompositorInputFrameMailbox tests passed.\n";
|
|
return 0;
|
|
}
|