Browse Source

implement rectangles packet for script element (#2704)

* implement rectangles packet for script element

* fixes
pull/2705/head
Jason Dove 4 weeks ago committed by GitHub
parent
commit
c14f373f23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
  2. 68
      ErsatzTV.Infrastructure/Streaming/Graphics/Script/ScriptElement.cs

1
ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="EFCore.BulkExtensions" Version="9.0.2" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.2.2" />
<PackageReference Include="Humanizer.Core" Version="3.0.1" />
<PackageReference Include="Jint" Version="4.4.2" />
<PackageReference Include="JsonSchema.Net" Version="7.4.0" />
<PackageReference Include="Lucene.Net" Version="4.8.0-beta00017" />

68
ErsatzTV.Infrastructure/Streaming/Graphics/Script/ScriptElement.cs

@ -6,6 +6,7 @@ using CliWrap; @@ -6,6 +6,7 @@ using CliWrap;
using ErsatzTV.Core;
using ErsatzTV.Core.Graphics;
using ErsatzTV.Core.Interfaces.Streaming;
using Humanizer;
using Microsoft.Extensions.Logging;
using SkiaSharp;
@ -24,9 +25,15 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger) @@ -24,9 +25,15 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger)
private TimeSpan _startTime;
private TimeSpan _endTime;
private int _repeatCount;
private long _totalBytes;
public void Dispose()
{
logger.LogDebug(
"Script element produced {ByteSize} ({Bytes} bytes)",
ByteSize.FromBytes(_totalBytes),
_totalBytes);
GC.SuppressFinalize(this);
_pipeReader?.Complete();
@ -94,7 +101,7 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger) @@ -94,7 +101,7 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger)
.WithStandardOutputPipe(PipeTarget.ToStream(pipe.Writer.AsStream()));
logger.LogDebug(
"script element command {Command} arguments {Arguments}",
"Script element command {Command} arguments {Arguments}",
command.TargetFilePath,
command.Arguments);
@ -163,6 +170,8 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger) @@ -163,6 +170,8 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger)
// mark this frame as consumed
consumed = sequence.End;
_totalBytes += _frameSize;
// we are done, return the frame
return new PreparedElementImage(_canvasBitmap, SKPointI.Empty, 1.0f, ZIndex, false);
}
@ -226,6 +235,7 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger) @@ -226,6 +235,7 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger)
// consume header
_pipeReader.AdvanceTo(buffer.GetPosition(11));
_totalBytes += 11;
var success = true;
@ -248,14 +258,64 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger) @@ -248,14 +258,64 @@ public class ScriptElement(ScriptGraphicsElement scriptElement, ILogger logger)
_repeatCount = (int)BinaryPrimitives.ReadUInt32BigEndian(repeatBytes);
break;
case (byte)ScriptPayloadType.Rectangles:
// TODO: support rectangles
logger.LogWarning("Unsupported graphics packet type: {Type}", type);
success = false;
_canvasBitmap.Erase(SKColors.Transparent);
Span<byte> shortBytes = stackalloc byte[2];
buffer.Slice(0, shortBytes.Length).CopyTo(shortBytes);
int rectangleCount = BinaryPrimitives.ReadUInt16BigEndian(shortBytes);
int offset = shortBytes.Length;
using (SKPixmap pixmap = _canvasBitmap.PeekPixels())
{
int canvasWidth = pixmap.Width;
int canvasHeight = pixmap.Height;
const int BYTES_PER_PIXEL = 4;
int destRowBytes = pixmap.RowBytes;
Span<byte> canvasSpan = pixmap.GetPixelSpan();
for (int i = 0; i < rectangleCount; i++)
{
buffer.Slice(offset, 2).CopyTo(shortBytes);
offset += 2;
int x = BinaryPrimitives.ReadUInt16BigEndian(shortBytes);
buffer.Slice(offset, 2).CopyTo(shortBytes);
offset += 2;
int y = BinaryPrimitives.ReadUInt16BigEndian(shortBytes);
buffer.Slice(offset, 2).CopyTo(shortBytes);
offset += 2;
int w = BinaryPrimitives.ReadUInt16BigEndian(shortBytes);
buffer.Slice(offset, 2).CopyTo(shortBytes);
offset += 2;
int h = BinaryPrimitives.ReadUInt16BigEndian(shortBytes);
int effectiveW = Math.Max(0, Math.Min(w, canvasWidth - x));
int effectiveH = Math.Max(0, Math.Min(h, canvasHeight - y));
if (effectiveW > 0 && effectiveH > 0)
{
int sourceRowBytes = w * BYTES_PER_PIXEL;
for (int row = 0; row < effectiveH; row++)
{
int sourceIndex = offset + (row * sourceRowBytes);
int destIndex = ((y + row) * destRowBytes) + (x * BYTES_PER_PIXEL);
buffer.Slice(sourceIndex, effectiveW * BYTES_PER_PIXEL)
.CopyTo(canvasSpan.Slice(destIndex, effectiveW * BYTES_PER_PIXEL));
}
}
offset += w * h * 4;
}
}
break;
}
// consume payload
_pipeReader.AdvanceTo(buffer.GetPosition(payloadLen));
_totalBytes += payloadLen;
}
else
{

Loading…
Cancel
Save