Fixed camera initial position and gravitate center. Fixed bug with reusable buffers.

This commit is contained in:
Alexander Shabarshov 2026-09-19 10:15:04 +01:00
parent 7b40095ccd
commit a971ceff2c
4 changed files with 28 additions and 47 deletions

View File

@ -1,62 +1,42 @@
namespace Splitter_UI.Services; using System.Buffers;
namespace Splitter_UI.Services;
public sealed class BufferPool : IBufferPool public sealed class BufferPool : IBufferPool
{ {
public sealed class Entry : IDisposable
public sealed class Entry
{ {
private bool _disposed;
public readonly int Width; public readonly int Width;
public readonly int Height; public readonly int Height;
public readonly byte[] Bgr;
public readonly byte[] Bgra;
public Entry(int w, int h) public byte[] Bgr;
public byte[] Bgra;
internal Entry(int w, int h)
{ {
Width = w; Width = w;
Height = h; Height = h;
Bgr = new byte[w * h * 3];
Bgra = new byte[w * h * 4]; Bgr = ArrayPool<byte>.Shared.Rent(w * h * 3);
Bgra = ArrayPool<byte>.Shared.Rent(w * h * 4);
} }
override public string ToString() => $"Entry({Width}x{Height})"; public void Dispose()
}
private readonly Dictionary<(int w, int h), LinkedListNode<Entry>> _map;
private readonly LinkedList<Entry> _lru;
private readonly int _capacity;
private readonly Lock _lock = new();
public BufferPool()
{ {
_capacity = 8; if (_disposed) return;
_map = new Dictionary<(int w, int h), LinkedListNode<Entry>>(_capacity); _disposed = true;
_lru = new LinkedList<Entry>();
ArrayPool<byte>.Shared.Return(Bgr);
ArrayPool<byte>.Shared.Return(Bgra);
}
public override string ToString() => $"Entry({Width}x{Height})";
} }
public Entry Get(int w, int h) public Entry Get(int w, int h)
{ {
var key = (w, h); return new Entry(w, h);
if (_map.TryGetValue(key, out var node))
{
_lru.Remove(node);
_lru.AddLast(node);
return node.Value;
}
var created = new Entry(w, h);
var newNode = new LinkedListNode<Entry>(created);
_lru.AddLast(newNode);
_map[key] = newNode;
if (_lru.Count > _capacity)
{
var first = _lru.First!;
_lru.RemoveFirst();
_map.Remove((first.Value.Width, first.Value.Height));
}
return created;
} }
} }

View File

@ -22,7 +22,7 @@ public sealed class MatToBitmapConverter(IBufferPool _pool) : IMatToBitmapConver
lock (_sync) lock (_sync)
{ {
var entry = _pool.Get(w, h); using var entry = _pool.Get(w, h);
var src = mat; var src = mat;
if (!src.IsContinuous()) if (!src.IsContinuous())
@ -65,7 +65,7 @@ public sealed class MatToBitmapConverter(IBufferPool _pool) : IMatToBitmapConver
public Bitmap Convert(byte[] bgr, int width, int height, Bitmap? existing = null) public Bitmap Convert(byte[] bgr, int width, int height, Bitmap? existing = null)
{ {
var entry = _pool.Get(width, height); using var entry = _pool.Get(width, height);
ConvertBgrToBgra(bgr, entry.Bgra, width, height); ConvertBgrToBgra(bgr, entry.Bgra, width, height);
if (existing is WriteableBitmap wb && if (existing is WriteableBitmap wb &&

View File

@ -59,7 +59,7 @@ public sealed class ThumbnailService : IThumbnailService
height ??= ThumbHeight; height ??= ThumbHeight;
skip ??= TimeSpan.Zero; skip ??= TimeSpan.Zero;
var entry = _pool.Get(width.Value, height.Value); using var entry = _pool.Get(width.Value, height.Value);
var ok = await DecodeFrameAsync( var ok = await DecodeFrameAsync(
entry.Bgr, entry.Bgr,

View File

@ -47,6 +47,7 @@ public sealed class CameraController
_cropHeight = cropHeight; _cropHeight = cropHeight;
_kalman = kalman; _kalman = kalman;
_cmd = cmd; _cmd = cmd;
DefaultCenter = new Point2f(videoWidth * _cmd.GravitateTo.X, videoHeight * _cmd.GravitateTo.Y);
_cameraCenter = DefaultCenter; _cameraCenter = DefaultCenter;
_state = TrackState.Tracking; _state = TrackState.Tracking;
@ -58,7 +59,7 @@ public sealed class CameraController
_kalman.Reset(_cameraCenter); _kalman.Reset(_cameraCenter);
} }
private Point2f DefaultCenter => _cmd.GravitateTo; private Point2f DefaultCenter { get; set; }
public int LostFrames => _lostFrames; public int LostFrames => _lostFrames;
public Point2f CameraCenter => _cameraCenter; public Point2f CameraCenter => _cameraCenter;
@ -148,7 +149,7 @@ public sealed class CameraController
smoothedCenter = _kalman.Update(objectCenter); smoothedCenter = _kalman.Update(objectCenter);
var driftEasing = 0.01f; var driftEasing = 0.01f;
var fallbackCenter = new Point2f(_videoWidth / 2f, _videoHeight / 2f); var fallbackCenter = DefaultCenter;
_cameraCenter = new Point2f( _cameraCenter = new Point2f(
_cameraCenter.X + (fallbackCenter.X - _cameraCenter.X) * driftEasing, _cameraCenter.X + (fallbackCenter.X - _cameraCenter.X) * driftEasing,