feat(pipeline): pass the configured frame rate to each ISO NDI sender

IsoPipeline now hands config.Settings.FrameRate (the exact rational) to the
NdiSender it builds, completing the settings -> sender plumbing. Previously
every output advertised 59.94 regardless of the operator-configured target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Zac Gaetano 2026-07-06 21:26:09 -04:00
parent 97d7028a3a
commit 6a141c1031
2 changed files with 29 additions and 1 deletions

View file

@ -378,9 +378,10 @@ public sealed class IsoPipeline : IAsyncDisposable
using var receiver = new NdiReceiver(
interop, config.SourceName, rawWriter, loggerFactory.CreateLogger<NdiReceiver>());
var (frameRateN, frameRateD) = config.Settings.FrameRate;
using var sender = new NdiSender(
interop, config.OutputName, processedChannel.Reader, loggerFactory.CreateLogger<NdiSender>(),
config.OutputGroups);
config.OutputGroups, frameRateN, frameRateD);
var processor = new FrameProcessor(
config.Settings, scaler, new SolidFrameRenderer(),

View file

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging.Abstractions;
using DragonISO.Engine.Domain;
using DragonISO.Engine.Pipeline;
using DragonISO.Engine.Tests.Fakes;
namespace DragonISO.Engine.Tests.Pipeline;
@ -76,6 +77,32 @@ public class IsoPipelineTests
await pipeline.StopAsync();
}
[Fact]
public async Task ProductionCtor_PassesConfiguredFrameRate_ToSender()
{
// The operator configures 29.97 in settings; the NDI sender for every ISO
// output must be created with that exact rational (30000/1001), not the
// hardwired 59.94 default.
var interop = new FakeNdiInterop();
var config = new IsoPipelineConfig(
Guid.NewGuid(),
"Teams - Alice",
"Alice-ISO",
FrameProcessingSettings.Default with { Framerate = TargetFramerate.Fps29_97 });
var pipeline = new IsoPipeline(
config, interop, new ManagedNearestNeighborFrameScaler(), new FakeFrameClock(),
FastBackoff(), NoDelay(), NullLoggerFactory.Instance);
await pipeline.StartAsync();
var deadline = DateTime.UtcNow.AddSeconds(2);
while (!interop.SenderFrameRates.ContainsKey("Alice-ISO") && DateTime.UtcNow < deadline)
await Task.Delay(10);
await pipeline.StopAsync();
interop.SenderFrameRates.Should().ContainKey("Alice-ISO");
interop.SenderFrameRates["Alice-ISO"].Should().Be((30000, 1001));
}
[Fact]
public async Task Supervisor_FailsRepeatedly_TransitionsToError()
{