forked from amkovkov/GranuSightSoftware2
feat: Camera settings + some refactor
This commit is contained in:
@@ -3,11 +3,13 @@ using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using LibCameraSharp;
|
||||
|
||||
using GSS2.Core.Extentions;
|
||||
using GSS2.Core.Abstractions;
|
||||
using GSS2.Core.Helpers;
|
||||
|
||||
using Stream = LibCameraSharp.Stream;
|
||||
|
||||
@@ -55,17 +57,19 @@ public class CameraService : IDisposable
|
||||
ViewFinderFps = 30,
|
||||
ImageCaptureFrameBufferCount = 2,
|
||||
ImageCaptureWidth = 4056,
|
||||
ImageCaptureHeight = 3080
|
||||
ImageCaptureHeight = 3080,
|
||||
CameraHardSettings = null
|
||||
};
|
||||
|
||||
public string CameraId { get; set; } = "";
|
||||
public int ViewFinderFrameBufferCount { get; set; }
|
||||
public int ViewFinderWidth { get; set; }
|
||||
public int ViewFinderHeight { get; set; }
|
||||
public int ViewFinderFps { get; set; }
|
||||
public int ImageCaptureFrameBufferCount { get; set; }
|
||||
public int ImageCaptureWidth { get; set; }
|
||||
public int ImageCaptureHeight { get; set; }
|
||||
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; }
|
||||
public IConfigurationSection? CameraHardSettings { get; init; }
|
||||
}
|
||||
|
||||
private bool _disposedValue;
|
||||
@@ -86,6 +90,7 @@ public class CameraService : IDisposable
|
||||
private System.Timers.ElapsedEventHandler? _viewFinderTimerElapsed = null;
|
||||
private EventHandler<Camera.RequestCompletedEventArgs>? _viewFinderRequestComplitedHandler = null;
|
||||
private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource();
|
||||
private readonly Dictionary<string, object> _cameraHardSettings = new Dictionary<string, object>();
|
||||
|
||||
public bool IsImageCapturing { get; private set; } = false;
|
||||
public List<FrameBuffer> ViewFinderBufferQueue { get; private set; } = new List<FrameBuffer>();
|
||||
@@ -106,6 +111,27 @@ public class CameraService : IDisposable
|
||||
_configuration = configuration;
|
||||
_logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
|
||||
|
||||
|
||||
if (_configuration.CameraHardSettings is not null)
|
||||
{
|
||||
foreach (var child in _configuration.CameraHardSettings.GetChildren())
|
||||
{
|
||||
object? value = child.Get<object>();
|
||||
if (value is string)
|
||||
{
|
||||
_cameraHardSettings.Add(child.Key, value);
|
||||
continue;
|
||||
}
|
||||
value = child.Get<object[]>();
|
||||
if (value is not null)
|
||||
{
|
||||
_cameraHardSettings.Add(child.Key, value);
|
||||
continue;
|
||||
}
|
||||
_logger.LogWarning("Cannot serialize camera hard settings value: {}: {}", child.Key, child.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (autoInitialize)
|
||||
Initialize(CancellationToken.None);
|
||||
}
|
||||
@@ -279,6 +305,8 @@ public class CameraService : IDisposable
|
||||
throw new Exception($"Error while camera start {result}");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Camera settings: \n{}", GetSettings(4));
|
||||
|
||||
_state |= State.CameraStarted;
|
||||
}
|
||||
private void ViewFinderFrameBuffersAllocate(CancellationToken cancellationToken)
|
||||
@@ -365,7 +393,7 @@ public class CameraService : IDisposable
|
||||
cts.Task.WaitAsync(cancellationToken).GetAwaiter().GetResult();
|
||||
_camera.RequestCompleted -= RequestCompleted;
|
||||
|
||||
_logger.LogDebug("Request complited: \n\tResult: {} \n\tStatus: {}\n\tCookie: {}\n\tSequence: {}\n\tHasPendingBuffers: {}", result, request.Status, request.Cookie, request.Sequence, request.HasPendingBuffers);
|
||||
_logger.LogDebug("Request complited: \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())
|
||||
@@ -476,6 +504,63 @@ public class CameraService : IDisposable
|
||||
|
||||
_state |= State.ImageCaptureFrameBuffersMapped;
|
||||
}
|
||||
private string GetSettings(int indent = 0)
|
||||
{
|
||||
if (_camera is null)
|
||||
throw new InvalidOperationException("Camera not initialized");
|
||||
|
||||
var controls = _camera.Controls.ToList();
|
||||
controls.Sort((c1, c2) => (int)(c1.Key.Id - c2.Key.Id));
|
||||
var strs = new List<List<string>>()
|
||||
{
|
||||
{["Id", "Name", "Type", "Direction", "IsArray", "Size", "Range", "Default", "Enumerators"]}
|
||||
};
|
||||
|
||||
foreach (var (id, info) in controls)
|
||||
{
|
||||
strs.Add([
|
||||
id.Id.ToString(),
|
||||
id.Name.ToString(),
|
||||
id.Type.ToString(),
|
||||
id.Direction.ToString(),
|
||||
id.IsArray.ToString(),
|
||||
id.Size.ToString(),
|
||||
$"{info.Min.ToString(true)}...{info.Max.ToString(true)}",
|
||||
info.Def.ToString(true),
|
||||
string.Join(", ", id.Enumerators.FirstOrDefault())
|
||||
]);
|
||||
foreach (var enumerator in id.Enumerators.Skip(1))
|
||||
strs.Add([
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
string.Join(", ", enumerator)
|
||||
]);
|
||||
}
|
||||
var maxLengths = new List<int>();
|
||||
foreach (var str in strs)
|
||||
foreach (var (i, s) in str.Enumerate())
|
||||
{
|
||||
if (i >= maxLengths.Count())
|
||||
maxLengths.Add(0);
|
||||
maxLengths[i] = Math.Max(maxLengths[i], s.Length);
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (var (i, str) in strs.Enumerate())
|
||||
{
|
||||
foreach (var (j, s) in str.Enumerate())
|
||||
sb.Append(new string(' ', indent) + string.Format($"{{0,-{maxLengths[j] + 1}}}", s));
|
||||
if (i != strs.Count() - 1)
|
||||
sb.AppendLine();
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public async Task<OpenCvSharp.Mat?> CaptureImage(CancellationToken cancellationToken, int framesCount = 1)
|
||||
{
|
||||
@@ -510,7 +595,7 @@ public class CameraService : IDisposable
|
||||
while (planesData.Count() < framesCount)
|
||||
{
|
||||
effectiveCancellationToken.ThrowIfCancellationRequested();
|
||||
_logger.LogDebug("Requested {} frame(s), now collected {}", framesCount, planesData.Count());
|
||||
_logger.LogDebug("Requested {} frame(s), now collected: {}", framesCount, planesData.Count());
|
||||
|
||||
var oldPlanesDataCount = planesData.Count();
|
||||
|
||||
@@ -524,6 +609,8 @@ public class CameraService : IDisposable
|
||||
foreach (var buffer in buffers)
|
||||
{
|
||||
var request = _camera.CreateRequest(1);
|
||||
ApplySettings(request, _cameraHardSettings);
|
||||
|
||||
var result = request.AddBuffer(_imageCaptureStream, buffer);
|
||||
if (result < 0)
|
||||
throw new Exception("Error while request create");
|
||||
@@ -669,6 +756,40 @@ public class CameraService : IDisposable
|
||||
IsImageCapturing = false;
|
||||
return image;
|
||||
}
|
||||
private void ApplySettings(Request request, Dictionary<string, object> settings)
|
||||
{
|
||||
if (_camera is null)
|
||||
throw new InvalidOperationException("Camera not initialized");
|
||||
|
||||
foreach (var (id, info) in _camera.Controls)
|
||||
{
|
||||
if (!settings.ContainsKey(id.Name))
|
||||
continue;
|
||||
|
||||
var value = settings[id.Name];
|
||||
ControlValue? controlValue;
|
||||
try
|
||||
{
|
||||
if (!id.IsArray)
|
||||
controlValue = ControlValueHelper.ConvertToControlValue(value, id, info);
|
||||
else
|
||||
controlValue = ControlValueHelper.ConvertToControlArray(value, id, info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while converting value (control name:{}, control type:{}, value type:{}, value:{})", id.Name, id.Type, value.GetType(), value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (controlValue is null)
|
||||
{
|
||||
_logger.LogWarning("Cannot convert to control value (control name:{}, control type:{}, value type:{}, value:{})", id.Name, id.Type, value.GetType(), value);
|
||||
continue;
|
||||
}
|
||||
|
||||
request.Controls.Set(id.Id, controlValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartViewFinder()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user