feat(pipeline): add SolidFrameRenderer slate and IFrameScaler/PassthroughFrameScaler
Some checks failed
CI / build-and-test (push) Failing after 25s
Some checks failed
CI / build-and-test (push) Failing after 25s
This commit is contained in:
parent
1b280e3e77
commit
970f04861d
4 changed files with 72 additions and 0 deletions
8
src/TeamsISO.Engine/Pipeline/IFrameScaler.cs
Normal file
8
src/TeamsISO.Engine/Pipeline/IFrameScaler.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
using TeamsISO.Engine.Domain;
|
||||
|
||||
namespace TeamsISO.Engine.Pipeline;
|
||||
|
||||
public interface IFrameScaler
|
||||
{
|
||||
ProcessedFrame Scale(RawFrame source, int targetWidth, int targetHeight, AspectMode aspect, long timestampTicks);
|
||||
}
|
||||
20
src/TeamsISO.Engine/Pipeline/PassthroughFrameScaler.cs
Normal file
20
src/TeamsISO.Engine/Pipeline/PassthroughFrameScaler.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using TeamsISO.Engine.Domain;
|
||||
|
||||
namespace TeamsISO.Engine.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// Phase A scaler. Copies the source frame's pixel buffer through unchanged and tags the
|
||||
/// output with the requested target dimensions. Real scaling is added in Phase B against libyuv.
|
||||
/// </summary>
|
||||
public sealed class PassthroughFrameScaler : IFrameScaler
|
||||
{
|
||||
public ProcessedFrame Scale(RawFrame source, int targetWidth, int targetHeight, AspectMode aspect, long timestampTicks)
|
||||
{
|
||||
return new ProcessedFrame(
|
||||
Width: targetWidth,
|
||||
Height: targetHeight,
|
||||
TimestampTicks: timestampTicks,
|
||||
Pixels: source.Pixels,
|
||||
Format: source.Format == PixelFormat.Bgra ? PixelFormat.Bgra : PixelFormat.Bgra);
|
||||
}
|
||||
}
|
||||
20
src/TeamsISO.Engine/Pipeline/SolidFrameRenderer.cs
Normal file
20
src/TeamsISO.Engine/Pipeline/SolidFrameRenderer.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
namespace TeamsISO.Engine.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a solid-color BGRA frame for use as a "no signal" slate.
|
||||
/// </summary>
|
||||
public sealed class SolidFrameRenderer
|
||||
{
|
||||
public ProcessedFrame Render(int width, int height, byte b, byte g, byte r, byte a, long timestampTicks)
|
||||
{
|
||||
var pixels = new byte[width * height * 4];
|
||||
for (var i = 0; i < pixels.Length; i += 4)
|
||||
{
|
||||
pixels[i + 0] = b;
|
||||
pixels[i + 1] = g;
|
||||
pixels[i + 2] = r;
|
||||
pixels[i + 3] = a;
|
||||
}
|
||||
return new ProcessedFrame(width, height, timestampTicks, pixels, PixelFormat.Bgra);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using TeamsISO.Engine.Pipeline;
|
||||
|
||||
namespace TeamsISO.Engine.Tests.Pipeline;
|
||||
|
||||
public class SolidFrameRendererTests
|
||||
{
|
||||
[Fact]
|
||||
public void Render_ProducesBgraFrameOfTargetSize_FilledWithColor()
|
||||
{
|
||||
var renderer = new SolidFrameRenderer();
|
||||
var frame = renderer.Render(width: 1920, height: 1080, b: 0x80, g: 0x80, r: 0x80, a: 0xFF, timestampTicks: 12345);
|
||||
|
||||
frame.Width.Should().Be(1920);
|
||||
frame.Height.Should().Be(1080);
|
||||
frame.Format.Should().Be(PixelFormat.Bgra);
|
||||
frame.Pixels.Length.Should().Be(1920 * 1080 * 4);
|
||||
frame.TimestampTicks.Should().Be(12345);
|
||||
|
||||
var span = frame.Pixels.Span;
|
||||
span[0].Should().Be(0x80); span[1].Should().Be(0x80); span[2].Should().Be(0x80); span[3].Should().Be(0xFF);
|
||||
var last = span.Length - 4;
|
||||
span[last].Should().Be(0x80); span[last + 3].Should().Be(0xFF);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue