143 lines
4.7 KiB
C++
143 lines
4.7 KiB
C++
#include "OutputProductionController.h"
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
namespace
|
|
{
|
|
int gFailures = 0;
|
|
|
|
void Expect(bool condition, const char* message)
|
|
{
|
|
if (condition)
|
|
return;
|
|
|
|
std::cerr << "FAIL: " << message << "\n";
|
|
++gFailures;
|
|
}
|
|
|
|
void TestLowQueueRequestsProductionToTarget()
|
|
{
|
|
VideoPlayoutPolicy policy;
|
|
policy.targetReadyFrames = 3;
|
|
policy.maxReadyFrames = 5;
|
|
OutputProductionController controller(policy);
|
|
|
|
OutputProductionPressure pressure;
|
|
pressure.readyQueueDepth = 1;
|
|
pressure.readyQueueCapacity = 5;
|
|
|
|
const OutputProductionDecision decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Produce, "low ready queue requests production");
|
|
Expect(decision.requestedFrames == 2, "low ready queue requests enough frames to reach target");
|
|
Expect(decision.targetReadyFrames == 3, "decision reports effective target");
|
|
Expect(decision.maxReadyFrames == 5, "decision reports effective max");
|
|
Expect(decision.reason == "ready-queue-below-target", "low queue decision names reason");
|
|
}
|
|
|
|
void TestFullQueueThrottles()
|
|
{
|
|
VideoPlayoutPolicy policy;
|
|
policy.targetReadyFrames = 2;
|
|
policy.maxReadyFrames = 4;
|
|
OutputProductionController controller(policy);
|
|
|
|
OutputProductionPressure pressure;
|
|
pressure.readyQueueDepth = 4;
|
|
pressure.readyQueueCapacity = 4;
|
|
|
|
const OutputProductionDecision decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Throttle, "full ready queue throttles production");
|
|
Expect(decision.requestedFrames == 0, "full ready queue requests no frames");
|
|
Expect(decision.reason == "ready-queue-full", "full queue decision names reason");
|
|
}
|
|
|
|
void TestAtTargetWaitsWithoutPressure()
|
|
{
|
|
VideoPlayoutPolicy policy;
|
|
policy.targetReadyFrames = 2;
|
|
policy.maxReadyFrames = 4;
|
|
OutputProductionController controller(policy);
|
|
|
|
OutputProductionPressure pressure;
|
|
pressure.readyQueueDepth = 2;
|
|
pressure.readyQueueCapacity = 4;
|
|
|
|
const OutputProductionDecision decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Wait, "ready queue at target waits without pressure");
|
|
Expect(decision.requestedFrames == 0, "wait decision requests no frames");
|
|
Expect(decision.reason == "ready-queue-at-target", "wait decision names reason");
|
|
}
|
|
|
|
void TestLateDropPressureRequestsHeadroom()
|
|
{
|
|
VideoPlayoutPolicy policy;
|
|
policy.targetReadyFrames = 2;
|
|
policy.maxReadyFrames = 4;
|
|
OutputProductionController controller(policy);
|
|
|
|
OutputProductionPressure pressure;
|
|
pressure.readyQueueDepth = 2;
|
|
pressure.readyQueueCapacity = 4;
|
|
pressure.lateStreak = 1;
|
|
|
|
OutputProductionDecision decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Produce, "late pressure requests extra headroom");
|
|
Expect(decision.requestedFrames == 1, "late pressure requests one frame");
|
|
Expect(decision.reason == "playout-pressure", "late pressure decision names reason");
|
|
|
|
pressure.lateStreak = 0;
|
|
pressure.dropStreak = 2;
|
|
decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Produce, "drop pressure requests extra headroom");
|
|
|
|
pressure.dropStreak = 0;
|
|
pressure.readyQueueUnderrunCount = 1;
|
|
decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Produce, "underrun pressure requests extra headroom");
|
|
}
|
|
|
|
void TestPolicyNormalizesAndClampsToCapacity()
|
|
{
|
|
VideoPlayoutPolicy policy;
|
|
policy.targetReadyFrames = 0;
|
|
policy.maxReadyFrames = 8;
|
|
OutputProductionController controller(policy);
|
|
|
|
OutputProductionPressure pressure;
|
|
pressure.readyQueueDepth = 1;
|
|
pressure.readyQueueCapacity = 3;
|
|
|
|
const OutputProductionDecision decision = controller.Decide(pressure);
|
|
Expect(decision.action == OutputProductionAction::Wait, "normalized target at current depth waits");
|
|
Expect(decision.targetReadyFrames == 1, "target normalizes to at least one frame");
|
|
Expect(decision.maxReadyFrames == 3, "max ready frames clamps to queue capacity");
|
|
}
|
|
|
|
void TestActionNames()
|
|
{
|
|
Expect(OutputProductionActionName(OutputProductionAction::Produce) == std::string("Produce"), "produce action has name");
|
|
Expect(OutputProductionActionName(OutputProductionAction::Wait) == std::string("Wait"), "wait action has name");
|
|
Expect(OutputProductionActionName(OutputProductionAction::Throttle) == std::string("Throttle"), "throttle action has name");
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
TestLowQueueRequestsProductionToTarget();
|
|
TestFullQueueThrottles();
|
|
TestAtTargetWaitsWithoutPressure();
|
|
TestLateDropPressureRequestsHeadroom();
|
|
TestPolicyNormalizesAndClampsToCapacity();
|
|
TestActionNames();
|
|
|
|
if (gFailures != 0)
|
|
{
|
|
std::cerr << gFailures << " OutputProductionController test failure(s).\n";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "OutputProductionController tests passed.\n";
|
|
return 0;
|
|
}
|