From d4e7c300f4ec921bd79811b05e9ac29d2b9bb07a Mon Sep 17 00:00:00 2001 From: Alek-ban Date: Fri, 23 Jan 2026 08:42:58 +0300 Subject: [PATCH] chore: move CameraView logic to itself --- GSS2.Core/Hardware/CameraService.cs | 38 +++++---------- GSS2.Test/CameraView.axaml.cs | 36 ++++++++++++-- GSS2.Test/CameraViewModel.cs | 34 ++++++------- GSS2.Test/MainWindow.axaml.cs | 18 +------ GSS2.Test/MainWindowViewModel.cs | 35 -------------- GSS2.Test/Worker.cs | 74 ++++++++++++++--------------- GSS2.Test/appsettings.json | 2 +- GSS2.Vulkan/VulkanExtensions.cs | 2 +- 8 files changed, 100 insertions(+), 139 deletions(-) diff --git a/GSS2.Core/Hardware/CameraService.cs b/GSS2.Core/Hardware/CameraService.cs index 6660f54..78f27bf 100644 --- a/GSS2.Core/Hardware/CameraService.cs +++ b/GSS2.Core/Hardware/CameraService.cs @@ -680,7 +680,7 @@ public class CameraService : IDisposable var result = request.AddBuffer(_viewFinderStream, buffer); if (result < 0) throw new Exception("Error while request create"); - _logger.LogDebug("Request(s) created"); + // _logger.LogDebug("Request(s) created"); effectiveCancellationToken.ThrowIfCancellationRequested(); @@ -694,20 +694,20 @@ public class CameraService : IDisposable if (buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameError || buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameStartup) { - _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status); + // _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status); e.Request.Reuse(Request.ReuseFlagEnum.ReuseBuffers); var result = _camera.QueueRequest(e.Request); if (result >= 0) return; } - _logger.LogDebug("Request complited: \n\tStatus: {}\n\tCookie: {}\n\tSequence: {}\n\tHasPendingBuffers: {}", e.Request.Status, e.Request.Cookie, e.Request.Sequence, e.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); + // _logger.LogDebug("Request complited: \n\tStatus: {}\n\tCookie: {}\n\tSequence: {}\n\tHasPendingBuffers: {}", e.Request.Status, e.Request.Cookie, e.Request.Sequence, e.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); effectiveCancellationToken.ThrowIfCancellationRequested(); @@ -722,26 +722,12 @@ public class CameraService : IDisposable _camera.RequestCompleted -= RequestCompleted; throw new Exception("Error while request queue"); } - _logger.LogDebug("Request queued"); + // _logger.LogDebug("Request queued"); await cts.Task.WaitAsync(effectiveCancellationToken); _camera.RequestCompleted -= RequestCompleted; - _logger.LogDebug("Request complited"); + // _logger.LogDebug("Request complited"); - return new (buffer, _viewFinderStreamConfiguration); - } - - public void Test() - { - var config = _viewFinderStreamConfiguration!; - var size = config.Size; - var fourcc = config.PixelFormat.Fourcc; - var modifier = config.PixelFormat.Modifier; - var primariesEnum = config.ColorSpace?.Primaries; - var transferFunctionEnum = config.ColorSpace?.TransferFunction; - var ycbcrEncodingEnum = config.ColorSpace?.YcbcrEncoding; - var rangeEnum = config.ColorSpace?.Range; - var stride = config.Stride; - _logger.LogInformation($"Cannot find decoder for fourcc=0x{fourcc:X}({new string(BitConverter.GetBytes(fourcc).Select(b => (char)b).ToArray())}) modifier=0x{modifier:X} primariesEnum={primariesEnum} transferFunctionEnum={transferFunctionEnum} ycbcrEncodingEnum={ycbcrEncodingEnum} rangeEnum={rangeEnum}"); + return new(buffer, _viewFinderStreamConfiguration); } protected virtual void Dispose(bool disposing) diff --git a/GSS2.Test/CameraView.axaml.cs b/GSS2.Test/CameraView.axaml.cs index 9856053..bc56e4b 100644 --- a/GSS2.Test/CameraView.axaml.cs +++ b/GSS2.Test/CameraView.axaml.cs @@ -72,7 +72,7 @@ class VkRenderer SType = StructureType.FenceCreateInfo }; context.Api.CreateFence(context.Device, &fenceInfo, null, out var fence).ThrowOnError(); - + var (importImage, importMemoryReqirements, importMemory) = ImportImage(fdDup, width, height, stride); var (exportImage, exportMemoryReqirements, exportMemory) = CreateExportImage(width, height); @@ -380,6 +380,7 @@ public partial class CameraView : Control private bool _compositionRequested; private VkRenderer? _renerer; private VkImage? _latestImage; + private System.Timers.Timer? _updateTimer; public CameraView() { } @@ -388,11 +389,40 @@ public partial class CameraView : Control { base.OnAttachedToVisualTree(e); Initialize(); + if (!_initialized) + return; + int i = 0; + _updateTimer = new System.Timers.Timer(100) + { + AutoReset = true + }; + _updateTimer.Elapsed += async (_, _) => + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + var viewModel = DataContext as CameraViewModel; + if (viewModel is null) + return; + + var result = await viewModel.CaptureImage(i++); + if (result is not null) + { + var (frameBuffer, streamConfiguration) = result.Value; + if (frameBuffer.Metadata.Status == FrameMetadata.StatusEnum.FrameSuccess) + Update(frameBuffer, streamConfiguration); + } + }); + }; + _updateTimer.Start(); } protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) { if (_initialized) + { + _updateTimer?.Stop(); + _updateTimer?.Dispose(); Surface?.Dispose(); + } _initialized = false; base.OnDetachedFromLogicalTree(e); @@ -425,10 +455,6 @@ public partial class CameraView : Control _visual.Size = new Vector(Bounds.Width, Bounds.Height); Update(); } - if (change.Property == DataContextProperty) - { - (DataContext as CameraViewModel)?.Update += (_, ea) => Update(ea.FrameBuffer, ea.StreamConfiguration); - } base.OnPropertyChanged(change); } diff --git a/GSS2.Test/CameraViewModel.cs b/GSS2.Test/CameraViewModel.cs index 493506c..256e0ab 100644 --- a/GSS2.Test/CameraViewModel.cs +++ b/GSS2.Test/CameraViewModel.cs @@ -1,32 +1,32 @@ +using GSS2.Core.Hardware; + using LibCameraSharp; namespace GSS2.Test; public class CameraViewModel : ViewModelBase { - public class UpdateEventArgs : EventArgs - { - public FrameBuffer? FrameBuffer { get; } - public StreamConfiguration? StreamConfiguration { get; } - - public UpdateEventArgs(FrameBuffer? frameBuffer = null, StreamConfiguration? streamConfiguration = null) - { - FrameBuffer = frameBuffer; - StreamConfiguration = streamConfiguration; - } - } + private readonly CameraService _cameraService; private readonly ILogger _logger; - public event EventHandler? Update; - - public CameraViewModel(ILogger logger) + public CameraViewModel(CameraService cameraService, ILogger logger) { + _cameraService = cameraService; _logger = logger; - _logger.LogInformation("Initialized"); } - public void CallUpdate(FrameBuffer? frameBuffer = null, StreamConfiguration? streamConfiguration = null) + public async Task<(FrameBuffer, StreamConfiguration)?> CaptureImage(int bufferId) { - Update?.Invoke(this, new UpdateEventArgs(frameBuffer, streamConfiguration)); + (FrameBuffer, StreamConfiguration)? result = null; + try + { + result = await _cameraService.CaptureViewFinderBuffer(bufferId, CancellationToken.None); + } + catch (Exception e) + { + _logger.LogError(e, "Error while image capture"); + } + + return result; } } \ No newline at end of file diff --git a/GSS2.Test/MainWindow.axaml.cs b/GSS2.Test/MainWindow.axaml.cs index 4bfccc0..992b15d 100644 --- a/GSS2.Test/MainWindow.axaml.cs +++ b/GSS2.Test/MainWindow.axaml.cs @@ -1,4 +1,5 @@ using Avalonia.Controls; +using Avalonia.Threading; namespace GSS2.Test; @@ -7,22 +8,5 @@ public partial class MainWindow : Window public MainWindow() { InitializeComponent(); - int i = 0; - - PointerPressed += async (_, _) => - { - var viewModel = DataContext as MainWindowViewModel; - if (viewModel is null) - return; - - var result = await viewModel.CaptureImage(i++); - if (result is not null) - { - var (frameBuffer, streamConfiguration) = result.Value; - if (frameBuffer.Metadata.Status == LibCameraSharp.FrameMetadata.StatusEnum.FrameSuccess) - // cameraView.Update(frameBuffer, streamConfiguration); - (cameraView.Content as CameraViewModel)?.CallUpdate(frameBuffer, streamConfiguration); - } - }; } } \ No newline at end of file diff --git a/GSS2.Test/MainWindowViewModel.cs b/GSS2.Test/MainWindowViewModel.cs index 9646e7a..5563cbd 100644 --- a/GSS2.Test/MainWindowViewModel.cs +++ b/GSS2.Test/MainWindowViewModel.cs @@ -27,40 +27,5 @@ public partial class MainWindowViewModel : ViewModelBase _lightsService = lightsService; _logger = logger; CameraViewModel = cameraViewModel; - _logger.LogInformation("Initialized"); - } - - public async Task<(LibCameraSharp.FrameBuffer, LibCameraSharp.StreamConfiguration)?> CaptureImage(int bufferId) - { - _logger.LogInformation("Capture image"); - _lightsService.CpuLoad(0.5, 1, System.Drawing.Color.Aqua); - - (LibCameraSharp.FrameBuffer, LibCameraSharp.StreamConfiguration)? result = null; - try - { - // _illuminatorService.SetIntensity(0.01, 0, 0); - // _illuminatorService.TurnOn(); - result = await _cameraService.CaptureViewFinderBuffer(bufferId, CancellationToken.None); - _lightsService.Flash(0.5, 2, System.Drawing.Color.Green); - } - catch (Exception e) - { - _logger.LogError(e, "Error while image capture"); - _lightsService.Flash(0.5, 2, System.Drawing.Color.Red); - } - finally - { - // _illuminatorService.TurnOff(); - } - - var snowfallTimer = new System.Timers.Timer(3000); - snowfallTimer.Elapsed += (_, _) => - { - _lightsService.Snowfall(0.3, 1, System.Drawing.Color.Aqua); - snowfallTimer.Dispose(); - }; - snowfallTimer.Start(); - - return result; } } \ No newline at end of file diff --git a/GSS2.Test/Worker.cs b/GSS2.Test/Worker.cs index cc7de70..df67f3a 100644 --- a/GSS2.Test/Worker.cs +++ b/GSS2.Test/Worker.cs @@ -1,49 +1,49 @@ -using System.Drawing; +// using System.Drawing; -using GSS2.Core.Analysis.AmineContent.Database; -using GSS2.Core.Hardware; +// using GSS2.Core.Analysis.AmineContent.Database; +// using GSS2.Core.Hardware; -namespace GSS2.Test; +// namespace GSS2.Test; -public class Worker( - ILogger logger, - IHostApplicationLifetime applicationLifetime, - AmineContentCalibrationContext amineCalibrationContext, - AmineContentResultsContext amineResultsContext, - LightsService lightsService, - IlluminatorService illuminatorService, - CameraService cameraService -) : BackgroundService -{ - private readonly ILogger _logger = logger; - private readonly IHostApplicationLifetime _applicationLifetime = applicationLifetime; - private readonly AmineContentCalibrationContext _amineCalibrationContext = amineCalibrationContext; - private readonly AmineContentResultsContext _amineResultsContext = amineResultsContext; - private readonly LightsService _lightsService = lightsService; - private readonly IlluminatorService _illuminatorService = illuminatorService; - private readonly CameraService _cameraService = cameraService; +// public class Worker( +// ILogger logger, +// IHostApplicationLifetime applicationLifetime, +// AmineContentCalibrationContext amineCalibrationContext, +// AmineContentResultsContext amineResultsContext, +// LightsService lightsService, +// IlluminatorService illuminatorService, +// CameraService cameraService +// ) : BackgroundService +// { +// private readonly ILogger _logger = logger; +// private readonly IHostApplicationLifetime _applicationLifetime = applicationLifetime; +// private readonly AmineContentCalibrationContext _amineCalibrationContext = amineCalibrationContext; +// private readonly AmineContentResultsContext _amineResultsContext = amineResultsContext; +// private readonly LightsService _lightsService = lightsService; +// private readonly IlluminatorService _illuminatorService = illuminatorService; +// private readonly CameraService _cameraService = cameraService; - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - _cameraService.Test(); +// protected override async Task ExecuteAsync(CancellationToken cancellationToken) +// { +// // _cameraService.Test(); - // _ = _lightsService.Run(cancellationToken); - // _ = _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken); +// // _ = _lightsService.Run(cancellationToken); +// // _ = _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken); - // _illuminatorService.SetIntensity(0.01, 0, 0); - // _illuminatorService.TurnOn(); +// // _illuminatorService.SetIntensity(0.01, 0, 0); +// // _illuminatorService.TurnOn(); - // await Task.Delay(1000); +// // await Task.Delay(1000); - // var img = await _cameraService.CaptureImage(cancellationToken, 50); - // // img?.SaveImage("IMAGE.png"); +// // var img = await _cameraService.CaptureImage(cancellationToken, 50); +// // // img?.SaveImage("IMAGE.png"); - // await Task.Delay(1000); +// // await Task.Delay(1000); - // _illuminatorService.TurnOff(); +// // _illuminatorService.TurnOff(); - // await _lightsService.DisconnectAsync(cancellationToken); +// // await _lightsService.DisconnectAsync(cancellationToken); - applicationLifetime.StopApplication(); - } -} +// applicationLifetime.StopApplication(); +// } +// } diff --git a/GSS2.Test/appsettings.json b/GSS2.Test/appsettings.json index 7faf7c1..72d29d0 100644 --- a/GSS2.Test/appsettings.json +++ b/GSS2.Test/appsettings.json @@ -38,7 +38,7 @@ }, "Camera": { "CameraId": "", - "ViewFinderFrameBufferCount": 2, + "ViewFinderFrameBufferCount": 30, "ViewFinderWidth": 1920, "ViewFinderHeight": 1080, "ViewFinderFps": 30, diff --git a/GSS2.Vulkan/VulkanExtensions.cs b/GSS2.Vulkan/VulkanExtensions.cs index 262441d..72f41e1 100644 --- a/GSS2.Vulkan/VulkanExtensions.cs +++ b/GSS2.Vulkan/VulkanExtensions.cs @@ -11,7 +11,7 @@ public static class VulkanExtensions { public static void ThrowOnError(this Result result, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = -1) { - Console.WriteLine($"{callerFilePath} {callerMemberName} {callerLineNumber} {result}"); + // Console.WriteLine($"{callerFilePath} {callerMemberName} {callerLineNumber} {result}"); if (result != Result.Success) throw new Exception($"Unexpected API error \"{result}\""); }