forked from amkovkov/GranuSightSoftware2
comprehensive update
1) remove unused components: camera view (due it causes segmentation faults), compute resources and all related, illuminator controller (due in useless without camera view), image storage service, temperature and humidity service 2) database schema - reduce tables references, features storing in records themselves in compressed form, add records creation and editing date and time, add separator comment column 3) analysis - rework of pipeline and ui, now database storing only raw data and all display values calculated from it 4) lights service - add reconnection if disconnected 5) add width and height command line arguments 6) fix some typos and other issues
This commit is contained in:
@@ -41,7 +41,6 @@ public class CameraService : IDisposable
|
||||
CameraManagerStarted = 1 << 1,
|
||||
CameraAcquired = 1 << 2,
|
||||
CameraStarted = 1 << 3,
|
||||
ViewFinderFrameBufferAllocated = 1 << 4,
|
||||
ImageCaptureFrameBufferAllocated = 1 << 5,
|
||||
ImageCaptureFrameBuffersMapped = 1 << 6
|
||||
}
|
||||
@@ -51,10 +50,6 @@ public class CameraService : IDisposable
|
||||
public static CameraServiceConfiguration Default => new CameraServiceConfiguration
|
||||
{
|
||||
CameraId = "",
|
||||
ViewFinderFrameBufferCount = 5,
|
||||
ViewFinderWidth = 4056,
|
||||
ViewFinderHeight = 3080,
|
||||
ViewFinderFps = 30,
|
||||
ImageCaptureFrameBufferCount = 2,
|
||||
ImageCaptureWidth = 4056,
|
||||
ImageCaptureHeight = 3080,
|
||||
@@ -66,10 +61,6 @@ public class CameraService : IDisposable
|
||||
};
|
||||
|
||||
public string CameraId { get; init; } = "";
|
||||
public int ViewFinderFrameBufferCount { get; init; }
|
||||
public int ViewFinderWidth { get; init; }
|
||||
public int ViewFinderHeight { get; init; }
|
||||
public int ViewFinderFps { get; init; }
|
||||
public int ImageCaptureFrameBufferCount { get; init; }
|
||||
public int ImageCaptureWidth { get; init; }
|
||||
public int ImageCaptureHeight { get; init; }
|
||||
@@ -87,16 +78,11 @@ public class CameraService : IDisposable
|
||||
private CameraManager? _cameraManager;
|
||||
private Camera? _camera;
|
||||
private CameraConfiguration? _cameraConfiguration;
|
||||
private StreamConfiguration? _viewFinderStreamConfiguration;
|
||||
private StreamConfiguration? _imageCaptureStreamConfiguration;
|
||||
private FrameBufferAllocator? _viewFinderFrameBufferAllocator;
|
||||
private FrameBufferAllocator? _imageCaptureFrameBufferAllocator;
|
||||
private Stream? _viewFinderStream;
|
||||
private Stream? _imageCaptureStream;
|
||||
private List<MappedBuffer>? _imageCaptureMappedBuffers;
|
||||
private System.Timers.Timer? _viewFinderTimer = null;
|
||||
private System.Timers.ElapsedEventHandler? _viewFinderTimerElapsed = null;
|
||||
private EventHandler<Camera.RequestCompletedEventArgs>? _viewFinderRequestCompletedHandler = null;
|
||||
private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource();
|
||||
private readonly Dictionary<string, object> _cameraHardSettings = new Dictionary<string, object>();
|
||||
|
||||
@@ -176,10 +162,8 @@ public class CameraService : IDisposable
|
||||
CameraSelect(effectiveCancellationToken);
|
||||
CameraAcquire(effectiveCancellationToken);
|
||||
CameraConfigure(effectiveCancellationToken);
|
||||
ViewFinderFrameBuffersAllocate(effectiveCancellationToken);
|
||||
ImageCaptureFrameBuffersAllocate(effectiveCancellationToken);
|
||||
CameraStart(effectiveCancellationToken);
|
||||
ViewFinderFrameBuffersInitialize(effectiveCancellationToken);
|
||||
ImageCaptureFrameBuffersInitialize(effectiveCancellationToken);
|
||||
ImageCaptureFrameBuffersMap(effectiveCancellationToken);
|
||||
}
|
||||
@@ -251,16 +235,8 @@ public class CameraService : IDisposable
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
_cameraConfiguration = _camera.GenerateConfiguration(
|
||||
StreamRoleEnum.Viewfinder,
|
||||
StreamRoleEnum.Raw);
|
||||
_cameraConfiguration = _camera.GenerateConfiguration(StreamRoleEnum.Raw);
|
||||
|
||||
_viewFinderStreamConfiguration = _cameraConfiguration.First();
|
||||
_viewFinderStreamConfiguration.BufferCount = checked((uint)_configuration.ViewFinderFrameBufferCount);
|
||||
_viewFinderStreamConfiguration.Size = new Size(
|
||||
checked((uint)_configuration.ViewFinderWidth),
|
||||
checked((uint)_configuration.ViewFinderHeight)
|
||||
);
|
||||
|
||||
_imageCaptureStreamConfiguration = _cameraConfiguration.Skip(1).First();
|
||||
_imageCaptureStreamConfiguration.BufferCount = checked((uint)_configuration.ImageCaptureFrameBufferCount);
|
||||
@@ -275,13 +251,6 @@ public class CameraService : IDisposable
|
||||
throw new Exception("Error while camera configuration validation");
|
||||
}
|
||||
|
||||
_logger.LogDebug(@$"ViewFinder stream configuration:
|
||||
Size: {_viewFinderStreamConfiguration.Size.ToString(true)}
|
||||
FrameSize: {_viewFinderStreamConfiguration.FrameSize}
|
||||
Stride: {_viewFinderStreamConfiguration.Stride}
|
||||
ColorSpace: {_viewFinderStreamConfiguration.ColorSpace?.ToString(true)}
|
||||
PixelFormat: {_viewFinderStreamConfiguration.PixelFormat?.ToString(true)}");
|
||||
|
||||
_logger.LogDebug(@$"ImageCapture stream configuration:
|
||||
Size: {_imageCaptureStreamConfiguration.Size.ToString(true)}
|
||||
FrameSize: {_imageCaptureStreamConfiguration.FrameSize}
|
||||
@@ -298,7 +267,6 @@ public class CameraService : IDisposable
|
||||
throw new Exception($"Error while camera configuration {result}");
|
||||
}
|
||||
|
||||
_viewFinderStream = _viewFinderStreamConfiguration.Stream();
|
||||
_imageCaptureStream = _imageCaptureStreamConfiguration.Stream();
|
||||
}
|
||||
private void CameraStart(CancellationToken cancellationToken)
|
||||
@@ -320,28 +288,6 @@ public class CameraService : IDisposable
|
||||
|
||||
_state |= State.CameraStarted;
|
||||
}
|
||||
private void ViewFinderFrameBuffersAllocate(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_camera is null)
|
||||
throw new InvalidOperationException("Camera not initialized");
|
||||
if (_viewFinderStream is null)
|
||||
throw new InvalidOperationException("ViewFinderStream not initialized");
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
_viewFinderFrameBufferAllocator = new FrameBufferAllocator(_camera);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
int result = _viewFinderFrameBufferAllocator.Allocate(_viewFinderStream);
|
||||
if (result < 0)
|
||||
{
|
||||
_logger.LogCritical("Error while view finder frame buffers allocation {Result}", result);
|
||||
throw new Exception($"Error while view finder frame buffers allocation {result}");
|
||||
}
|
||||
|
||||
_state |= State.ViewFinderFrameBufferAllocated;
|
||||
}
|
||||
private void ImageCaptureFrameBuffersAllocate(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_camera is null)
|
||||
@@ -364,55 +310,6 @@ public class CameraService : IDisposable
|
||||
|
||||
_state |= State.ImageCaptureFrameBufferAllocated;
|
||||
}
|
||||
private void ViewFinderFrameBuffersInitialize(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_camera is null)
|
||||
throw new InvalidOperationException("Camera not initialized");
|
||||
if (_viewFinderStream is null)
|
||||
throw new InvalidOperationException("ViewFinderStream not initialized");
|
||||
if (_viewFinderFrameBufferAllocator is null)
|
||||
throw new InvalidOperationException("ViewFinderFrameBufferAllocator not initialized");
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var buffers = _viewFinderFrameBufferAllocator.Buffers(_viewFinderStream);
|
||||
|
||||
_logger.LogDebug("View finder frame buffers initialization");
|
||||
foreach (var buffer in buffers)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var request = _camera.CreateRequest(0);
|
||||
var result = request.AddBuffer(_viewFinderStream, buffer);
|
||||
if (result < 0)
|
||||
throw new Exception("Error while request create");
|
||||
|
||||
var cts = new TaskCompletionSource();
|
||||
void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs e)
|
||||
{
|
||||
if (e.Request.Handle == request.Handle)
|
||||
cts.SetResult();
|
||||
}
|
||||
|
||||
_camera.RequestCompleted += RequestCompleted;
|
||||
result = _camera.QueueRequest(request);
|
||||
if (result < 0)
|
||||
{
|
||||
_camera.RequestCompleted -= RequestCompleted;
|
||||
throw new Exception("Error while request queue");
|
||||
}
|
||||
cts.Task.WaitAsync(cancellationToken).GetAwaiter().GetResult();
|
||||
_camera.RequestCompleted -= RequestCompleted;
|
||||
|
||||
_logger.LogDebug("Request completed: \n\tResult: {} \n\tStatus: {} \n\tCookie: {} \n\tSequence: {} \n\tHasPendingBuffers: {}", result, request.Status, request.Cookie, request.Sequence, request.HasPendingBuffers);
|
||||
_logger.LogDebug("Request buffer: \n\tStatus: {} \n\tCookie: {} \n\tSequence: {} \n\tTimestamp: {}", buffer.Metadata.Status, buffer.Cookie, buffer.Metadata.Sequence, buffer.Metadata.Timestamp);
|
||||
_logger.LogDebug("Request buffer planes: ");
|
||||
foreach (var (i, plane) in buffer.Metadata.Planes.Enumerate())
|
||||
_logger.LogDebug("Plane[{}]: bytes used: 0x{:X}", i, plane.BytesUsed);
|
||||
foreach (var (i, plane) in buffer.Planes.Enumerate())
|
||||
_logger.LogDebug("Plane[{}]: \n\tFd: 0x{:X} \n\tOffset: 0x{:X} \n\tLength: 0x{:X} \n\tKInvalidOffset: 0x{:X}", i, plane.Fd.Get(), plane.Offset, plane.Length, plane.KInvalidOffset);
|
||||
}
|
||||
}
|
||||
private void ImageCaptureFrameBuffersInitialize(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_camera is null)
|
||||
@@ -826,135 +723,6 @@ public class CameraService : IDisposable
|
||||
return image;
|
||||
}
|
||||
|
||||
public void StartViewFinder()
|
||||
{
|
||||
if (_camera is null)
|
||||
throw new InvalidOperationException("Camera not initialized");
|
||||
if (_viewFinderStream is null)
|
||||
throw new InvalidOperationException("ViewFinderStream not initialized");
|
||||
if (_viewFinderStreamConfiguration is null)
|
||||
throw new InvalidOperationException("ViewFinderStreamConfiguration not initialized");
|
||||
if (_viewFinderFrameBufferAllocator is null)
|
||||
throw new InvalidOperationException("ViewFinderFrameBufferAllocator not initialized");
|
||||
if (_viewFinderTimer is not null ||
|
||||
_viewFinderTimerElapsed is not null ||
|
||||
_viewFinderRequestCompletedHandler is not null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
ViewFinderStarted = true;
|
||||
|
||||
_viewFinderTimer = new System.Timers.Timer()
|
||||
{
|
||||
Interval = 1000 / _configuration.ViewFinderFps,
|
||||
AutoReset = true,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var buffers = _viewFinderFrameBufferAllocator.Buffers(_viewFinderStream);
|
||||
lock (ViewFinderBufferQueue)
|
||||
foreach (var buffer in buffers)
|
||||
ViewFinderBufferQueue.Add(buffer);
|
||||
|
||||
void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs ea)
|
||||
{
|
||||
if (ea.Request.Cookie != 2)
|
||||
return;
|
||||
var buffer = ea.Request.FindBuffer(_viewFinderStream);
|
||||
// _logger.LogInformation("Completed request for frame buffer {}", buffer);
|
||||
lock (ViewFinderBufferQueue)
|
||||
ViewFinderBufferQueue.Add(buffer);
|
||||
}
|
||||
_viewFinderRequestCompletedHandler = RequestCompleted;
|
||||
_camera.RequestCompleted += _viewFinderRequestCompletedHandler;
|
||||
|
||||
void TimerElapsed(object? sender, System.Timers.ElapsedEventArgs ea)
|
||||
{
|
||||
if (IsImageCapturing)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
FrameBuffer buffer;
|
||||
lock (ViewFinderBufferQueue)
|
||||
{
|
||||
if (ViewFinderBufferQueue.Count() > 0 && (
|
||||
ViewFinderBufferQueue.First().Request.Cookie != 2 ||
|
||||
ViewFinderBufferQueue.First().Request.Status == Request.StatusEnum.RequestComplete ||
|
||||
ViewFinderBufferQueue.First().Request.Status == Request.StatusEnum.RequestCancelled))
|
||||
{
|
||||
buffer = ViewFinderBufferQueue.First();
|
||||
ViewFinderBufferQueue.Remove(buffer);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
var request = _camera.CreateRequest(2);
|
||||
request.AddBuffer(_viewFinderStream, buffer);
|
||||
_camera.QueueRequest(request);
|
||||
// _logger.LogInformation("Queued request for frame buffer {}", buffer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while ViewFinder tick");
|
||||
}
|
||||
}
|
||||
_viewFinderTimerElapsed = TimerElapsed;
|
||||
_viewFinderTimer.Elapsed += _viewFinderTimerElapsed;
|
||||
_viewFinderTimer.Start();
|
||||
|
||||
_logger.LogInformation("ViewFinder started");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while ViewFinder start");
|
||||
_viewFinderTimer.Stop();
|
||||
_viewFinderTimer.Dispose();
|
||||
_viewFinderTimer = null;
|
||||
_viewFinderTimerElapsed = null;
|
||||
_camera.RequestCompleted -= _viewFinderRequestCompletedHandler;
|
||||
_viewFinderRequestCompletedHandler = null;
|
||||
lock (ViewFinderBufferQueue)
|
||||
ViewFinderBufferQueue.Clear();
|
||||
}
|
||||
}
|
||||
public void StopViewFinder()
|
||||
{
|
||||
ViewFinderStarted = false;
|
||||
_viewFinderTimer?.Stop();
|
||||
_viewFinderTimer?.Dispose();
|
||||
_viewFinderTimer = null;
|
||||
_viewFinderTimerElapsed = null;
|
||||
_camera?.RequestCompleted -= _viewFinderRequestCompletedHandler;
|
||||
_viewFinderRequestCompletedHandler = null;
|
||||
lock (ViewFinderBufferQueue)
|
||||
ViewFinderBufferQueue.Clear();
|
||||
}
|
||||
public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame()
|
||||
{
|
||||
if (IsImageCapturing)
|
||||
return null;
|
||||
|
||||
FrameBuffer? buffer = null;
|
||||
lock (ViewFinderBufferQueue)
|
||||
if (ViewFinderBufferQueue.Count() > 0)
|
||||
{
|
||||
buffer = ViewFinderBufferQueue.LastOrDefault();
|
||||
if (buffer is not null)
|
||||
ViewFinderBufferQueue.Remove(buffer);
|
||||
}
|
||||
if (buffer is not null && _viewFinderStreamConfiguration is not null)
|
||||
return (buffer, _viewFinderStreamConfiguration);
|
||||
return null;
|
||||
}
|
||||
public void ReturnViewFinderFrame(FrameBuffer frameBuffer)
|
||||
{
|
||||
lock (ViewFinderBufferQueue)
|
||||
ViewFinderBufferQueue.Insert(0, frameBuffer);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
@@ -986,8 +754,6 @@ public class CameraService : IDisposable
|
||||
}
|
||||
_imageCaptureMappedBuffers.Clear();
|
||||
}
|
||||
if (_state.HasFlag(State.ViewFinderFrameBufferAllocated) && _viewFinderStream is not null)
|
||||
_viewFinderFrameBufferAllocator?.Free(_viewFinderStream);
|
||||
if (_state.HasFlag(State.ImageCaptureFrameBufferAllocated) && _imageCaptureStream is not null)
|
||||
_imageCaptureFrameBufferAllocator?.Free(_imageCaptureStream);
|
||||
if (_state.HasFlag(State.CameraStarted))
|
||||
@@ -997,23 +763,17 @@ public class CameraService : IDisposable
|
||||
if (_state.HasFlag(State.CameraManagerStarted))
|
||||
_cameraManager?.Stop();
|
||||
|
||||
// _viewFinderStream?.Dispose();
|
||||
// _imageCaptureStream?.Dispose();
|
||||
// _viewFinderFrameBufferAllocator?.Dispose();
|
||||
// _imageCaptureFrameBufferAllocator?.Dispose();
|
||||
_cameraManager?.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(e, "Error while CameraService cleanup");
|
||||
_logger.LogError(ex, "Error while CameraService cleanup");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_cameraManager = null;
|
||||
_camera = null;
|
||||
_viewFinderFrameBufferAllocator = null;
|
||||
_imageCaptureFrameBufferAllocator = null;
|
||||
_viewFinderStream = null;
|
||||
_imageCaptureStream = null;
|
||||
_imageCaptureMappedBuffers = null;
|
||||
_state = State.NotInitialized;
|
||||
|
||||
Reference in New Issue
Block a user