141 lines
4.7 KiB
C#
141 lines
4.7 KiB
C#
|
|
using System.Numerics;
|
||
|
|
using Aquarium.LocalCast;
|
||
|
|
|
||
|
|
namespace Aquarium.LocalCast.Tests;
|
||
|
|
|
||
|
|
public sealed class LocalCastNativeVisualFrameSourceTests
|
||
|
|
{
|
||
|
|
[Fact]
|
||
|
|
public void ReadsLatestRenderPacketFromNativeRuntimeThroughInjectedDecoder()
|
||
|
|
{
|
||
|
|
var sample = new LocalCastNativeSampleHandle
|
||
|
|
{
|
||
|
|
SensorIdHash = 11,
|
||
|
|
TimestampNs = 1_000,
|
||
|
|
ArrivalNs = 1_010,
|
||
|
|
Sequence = 7,
|
||
|
|
PayloadHandle = 99,
|
||
|
|
Flags = LocalCastNativeSampleFlags.None,
|
||
|
|
};
|
||
|
|
var runtime = new FakeNativeRuntime(sample, renderPacketCount: 2);
|
||
|
|
var source = new LocalCastNativeVisualFrameSource(
|
||
|
|
runtime,
|
||
|
|
(LocalCastNativeSampleHandle handle, out LocalCastVisualFrame frame) =>
|
||
|
|
{
|
||
|
|
frame = FrameFromPayload(handle.PayloadHandle, handle.TimestampNs);
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Assert.True(source.TryReadLatest(out var frame));
|
||
|
|
Assert.Equal(99, frame.FrameId);
|
||
|
|
Assert.Equal(1_000, frame.SourceTimeMaxNs);
|
||
|
|
Assert.Equal(1, runtime.ViewReadCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void RejectsMissingOrNonLiveRenderPacket()
|
||
|
|
{
|
||
|
|
var diagnostic = new LocalCastNativeSampleHandle
|
||
|
|
{
|
||
|
|
SensorIdHash = 11,
|
||
|
|
TimestampNs = 1_000,
|
||
|
|
ArrivalNs = 1_010,
|
||
|
|
Sequence = 7,
|
||
|
|
PayloadHandle = 99,
|
||
|
|
Flags = LocalCastNativeSampleFlags.Diagnostic,
|
||
|
|
};
|
||
|
|
var source = new LocalCastNativeVisualFrameSource(
|
||
|
|
new FakeNativeRuntime(diagnostic, renderPacketCount: 1),
|
||
|
|
(LocalCastNativeSampleHandle _, out LocalCastVisualFrame frame) =>
|
||
|
|
{
|
||
|
|
frame = FrameFromPayload(1, 1);
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Assert.False(source.TryReadLatest(out _));
|
||
|
|
|
||
|
|
var empty = new LocalCastNativeVisualFrameSource(
|
||
|
|
new FakeNativeRuntime(diagnostic, renderPacketCount: 0),
|
||
|
|
(LocalCastNativeSampleHandle _, out LocalCastVisualFrame frame) =>
|
||
|
|
{
|
||
|
|
frame = FrameFromPayload(1, 1);
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
Assert.False(empty.TryReadLatest(out _));
|
||
|
|
}
|
||
|
|
|
||
|
|
private static LocalCastVisualFrame FrameFromPayload(ulong payloadHandle, ulong timestampNs)
|
||
|
|
{
|
||
|
|
return new LocalCastVisualFrame
|
||
|
|
{
|
||
|
|
SchemaVersion = LocalCastVisualStateReader.RenderFrameSchemaId,
|
||
|
|
FrameId = (long)payloadHandle,
|
||
|
|
CreatedMonotonicNs = (long)timestampNs,
|
||
|
|
SourceTimeMinNs = (long)timestampNs,
|
||
|
|
SourceTimeMaxNs = (long)timestampNs,
|
||
|
|
PresentTimeNs = (long)timestampNs,
|
||
|
|
AudioAlignmentTimeNs = (long)timestampNs,
|
||
|
|
SpoutSenderName = "LocalCastBridge Point Cloud",
|
||
|
|
TargetWidth = 1920,
|
||
|
|
TargetHeight = 1080,
|
||
|
|
Points =
|
||
|
|
[
|
||
|
|
new LocalCastVisualPoint(
|
||
|
|
"native:point",
|
||
|
|
new Vector3(0.1f, 0.2f, 1.2f),
|
||
|
|
0.03f,
|
||
|
|
new Vector4(0.7f, 0.6f, 0.5f, 0.9f),
|
||
|
|
0.8f,
|
||
|
|
(long)timestampNs),
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private sealed class FakeNativeRuntime : ILocalCastNativeRuntime
|
||
|
|
{
|
||
|
|
private readonly LocalCastNativeSampleHandle sample;
|
||
|
|
private readonly UIntPtr renderPacketCount;
|
||
|
|
|
||
|
|
public FakeNativeRuntime(LocalCastNativeSampleHandle sample, int renderPacketCount)
|
||
|
|
{
|
||
|
|
this.sample = sample;
|
||
|
|
this.renderPacketCount = (UIntPtr)renderPacketCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int ViewReadCount { get; private set; }
|
||
|
|
|
||
|
|
public bool TryGetStatus(out LocalCastNativeRuntimeStatus status)
|
||
|
|
{
|
||
|
|
status = new LocalCastNativeRuntimeStatus
|
||
|
|
{
|
||
|
|
TotalSampleCount = renderPacketCount,
|
||
|
|
RenderPacketCount = renderPacketCount,
|
||
|
|
};
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool TryReadSample(nuint index, out LocalCastNativeSampleKind kind, out LocalCastNativeSampleHandle sample)
|
||
|
|
{
|
||
|
|
kind = LocalCastNativeSampleKind.RenderPacket;
|
||
|
|
sample = this.sample;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool TryReadViewSample(LocalCastNativeSampleKind kind, nuint index, out LocalCastNativeSampleHandle sample)
|
||
|
|
{
|
||
|
|
ViewReadCount++;
|
||
|
|
sample = this.sample;
|
||
|
|
return kind == LocalCastNativeSampleKind.RenderPacket && index + 1 == renderPacketCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool TryReadLatestForSensor(LocalCastNativeSampleKind kind, ulong sensorIdHash, out LocalCastNativeSampleHandle sample)
|
||
|
|
{
|
||
|
|
sample = this.sample;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|