forked from amkovkov/GranuSightSoftware2
fix: CameraService view finder
Image capturing while view finder work
This commit is contained in:
@@ -79,6 +79,8 @@ public class CameraService : IDisposable
|
|||||||
private List<MappedBuffer>? _imageCaptureMappedBuffers;
|
private List<MappedBuffer>? _imageCaptureMappedBuffers;
|
||||||
private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource();
|
private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
public bool IsImageCapturing { get; private set; } = false;
|
||||||
|
|
||||||
public CameraService(ILogger<CameraService> logger, CameraServiceConfiguration? configuration = null, bool autoInitialize = false)
|
public CameraService(ILogger<CameraService> logger, CameraServiceConfiguration? configuration = null, bool autoInitialize = false)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -488,6 +490,8 @@ public class CameraService : IDisposable
|
|||||||
.CreateLinkedTokenSource(_disposeCts.Token, cancellationToken)
|
.CreateLinkedTokenSource(_disposeCts.Token, cancellationToken)
|
||||||
.Token;
|
.Token;
|
||||||
|
|
||||||
|
IsImageCapturing = true;
|
||||||
|
|
||||||
_logger.LogDebug("Capturing {} frame(s)", framesCount);
|
_logger.LogDebug("Capturing {} frame(s)", framesCount);
|
||||||
|
|
||||||
OpenCvSharp.Mat? image = null;
|
OpenCvSharp.Mat? image = null;
|
||||||
@@ -501,8 +505,6 @@ public class CameraService : IDisposable
|
|||||||
{
|
{
|
||||||
effectiveCancellationToken.ThrowIfCancellationRequested();
|
effectiveCancellationToken.ThrowIfCancellationRequested();
|
||||||
_logger.LogDebug("Requested {} frame(s), now collected {}", framesCount, planesData.Count());
|
_logger.LogDebug("Requested {} frame(s), now collected {}", framesCount, planesData.Count());
|
||||||
if (File.Exists("/proc/self/status"))
|
|
||||||
_logger.LogDebug("Current RAM Usage: {}", File.ReadAllLines("/proc/self/status").FirstOrDefault(l => l.StartsWith("RssAnon:"))?.Substring("RssAnon:".Length)?.Trim() ?? "UNKNOWN");
|
|
||||||
|
|
||||||
var oldPlanesDataCount = planesData.Count();
|
var oldPlanesDataCount = planesData.Count();
|
||||||
|
|
||||||
@@ -521,7 +523,7 @@ public class CameraService : IDisposable
|
|||||||
throw new Exception("Error while request create");
|
throw new Exception("Error while request create");
|
||||||
requests.Add(request);
|
requests.Add(request);
|
||||||
}
|
}
|
||||||
_logger.LogDebug("Request(s) created");
|
_logger.LogDebug("{} request(s) created", requests.Count());
|
||||||
|
|
||||||
effectiveCancellationToken.ThrowIfCancellationRequested();
|
effectiveCancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -578,6 +580,8 @@ public class CameraService : IDisposable
|
|||||||
planesData.Add(planeData);
|
planesData.Add(planeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogDebug("Planes data added");
|
||||||
|
|
||||||
if (planesData.Count() - oldPlanesDataCount == requests.Count())
|
if (planesData.Count() - oldPlanesDataCount == requests.Count())
|
||||||
cts.SetResult();
|
cts.SetResult();
|
||||||
}
|
}
|
||||||
@@ -592,8 +596,9 @@ public class CameraService : IDisposable
|
|||||||
throw new Exception("Error while request queue");
|
throw new Exception("Error while request queue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_logger.LogDebug("Request(s) queued");
|
_logger.LogDebug("{} request(s) queued", requests.Count());
|
||||||
await cts.Task.WaitAsync(effectiveCancellationToken);
|
await cts.Task.WaitAsync(effectiveCancellationToken);
|
||||||
|
_logger.LogDebug("{} request(s) compilted", requests.Count());
|
||||||
_camera.RequestCompleted -= RequestCompleted;
|
_camera.RequestCompleted -= RequestCompleted;
|
||||||
|
|
||||||
foreach (var key in fdsData.Keys)
|
foreach (var key in fdsData.Keys)
|
||||||
@@ -604,9 +609,6 @@ public class CameraService : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("Frame(s) collected");
|
_logger.LogDebug("Frame(s) collected");
|
||||||
if (File.Exists("/proc/self/status"))
|
|
||||||
_logger.LogDebug("Current RAM Usage: {}", File.ReadAllLines("/proc/self/status").FirstOrDefault(l => l.StartsWith("RssAnon:"))?.Substring("RssAnon:".Length)?.Trim() ?? "UNKNOWN");
|
|
||||||
|
|
||||||
|
|
||||||
effectiveCancellationToken.ThrowIfCancellationRequested();
|
effectiveCancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -657,6 +659,8 @@ public class CameraService : IDisposable
|
|||||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||||
planesData.Clear();
|
planesData.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsImageCapturing = false;
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,6 +711,9 @@ public class CameraService : IDisposable
|
|||||||
|
|
||||||
void TimerElapsed(object? sender, System.Timers.ElapsedEventArgs ea)
|
void TimerElapsed(object? sender, System.Timers.ElapsedEventArgs ea)
|
||||||
{
|
{
|
||||||
|
if (IsImageCapturing)
|
||||||
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FrameBuffer buffer;
|
FrameBuffer buffer;
|
||||||
@@ -766,6 +773,9 @@ public class CameraService : IDisposable
|
|||||||
}
|
}
|
||||||
public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame()
|
public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame()
|
||||||
{
|
{
|
||||||
|
if (IsImageCapturing)
|
||||||
|
return null;
|
||||||
|
|
||||||
FrameBuffer? buffer = null;
|
FrameBuffer? buffer = null;
|
||||||
lock (ViewFinderBufferQueue)
|
lock (ViewFinderBufferQueue)
|
||||||
if (ViewFinderBufferQueue.Count() > 0)
|
if (ViewFinderBufferQueue.Count() > 0)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public partial class MainViewModel : ViewModelBase
|
|||||||
ResourcesViewModel = resourcesViewModel;
|
ResourcesViewModel = resourcesViewModel;
|
||||||
ButtonClick = new RelayCommand(() =>
|
ButtonClick = new RelayCommand(() =>
|
||||||
{
|
{
|
||||||
cameraService.CaptureImage(CancellationToken.None, 10).ContinueWith(image => Image = image.Result);
|
Task.Run(() => cameraService.CaptureImage(CancellationToken.None, 10).ContinueWith(image => Image = image.Result));
|
||||||
});
|
});
|
||||||
|
|
||||||
_logger.LogInformation("{} initialized", nameof(MainViewModel));
|
_logger.LogInformation("{} initialized", nameof(MainViewModel));
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
xmlns:core="using:GSS2.UI.Core"
|
xmlns:core="using:GSS2.UI.Core"
|
||||||
x:DataType="local_vm:MainViewModel"
|
x:DataType="local_vm:MainViewModel"
|
||||||
x:Class="GSS2.Test.Views.MainView">
|
x:Class="GSS2.Test.Views.MainView">
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
<Grid RowDefinitions="*,*">
|
||||||
<core:OpenCvImage Grid.Column="0" Image="{Binding Image}" />
|
<Grid Grid.Row="0" ColumnDefinitions="*,*,Auto">
|
||||||
<Button Grid.Column="1" Width="50" VerticalAlignment="Stretch" Command="{Binding ButtonClick}"/>
|
<ContentControl Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="{Binding CameraViewModel}" />
|
||||||
<!-- <ContentControl Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="{Binding CameraViewModel}" /> -->
|
<core:OpenCvImage Grid.Column="1" Image="{Binding Image}" />
|
||||||
<!-- <ContentControl Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="{Binding ResourcesViewModel}" /> -->
|
<Button Grid.Column="2" Width="50" VerticalAlignment="Stretch" Command="{Binding ButtonClick}"/>
|
||||||
|
</Grid>
|
||||||
|
<ContentControl Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="{Binding ResourcesViewModel}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
"Camera": {
|
"Camera": {
|
||||||
"CameraId": "",
|
"CameraId": "",
|
||||||
"ViewFinderFrameBufferCount": 5,
|
"ViewFinderFrameBufferCount": 5,
|
||||||
"ViewFinderWidth": 1920,
|
"ViewFinderWidth": 4056,
|
||||||
"ViewFinderHeight": 1080,
|
"ViewFinderHeight": 3040,
|
||||||
"ViewFinderFps": 30,
|
"ViewFinderFps": 30,
|
||||||
"ImageCaptureFrameBufferCount": 2,
|
"ImageCaptureFrameBufferCount": 2,
|
||||||
"ImageCaptureWidth": 4056,
|
"ImageCaptureWidth": 4056,
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ public partial class CameraViewModel : ViewModelBase, IDisposable
|
|||||||
_cameraService = cameraService;
|
_cameraService = cameraService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_renderTimer = new System.Timers.Timer(33);
|
_renderTimer = new System.Timers.Timer(33);
|
||||||
_renderTimer.Elapsed += (_, _) => RenderReqested?.Invoke(this, new EventArgs());
|
_renderTimer.Elapsed += (_, _) =>
|
||||||
|
{
|
||||||
|
if (!_cameraService.IsImageCapturing)
|
||||||
|
RenderReqested?.Invoke(this, new EventArgs());
|
||||||
|
};
|
||||||
_logger.LogInformation("{} initialized", nameof(CameraViewModel));
|
_logger.LogInformation("{} initialized", nameof(CameraViewModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +46,7 @@ public partial class CameraViewModel : ViewModelBase, IDisposable
|
|||||||
_renderTimer.Stop();
|
_renderTimer.Stop();
|
||||||
_cameraService.StopViewFinder();
|
_cameraService.StopViewFinder();
|
||||||
}
|
}
|
||||||
|
public bool CanGrabViewFinderFrame() => !_cameraService.IsImageCapturing;
|
||||||
public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame() => _cameraService.GrabViewFinderFrame();
|
public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame() => _cameraService.GrabViewFinderFrame();
|
||||||
public void ReturnViewFinderFrame(FrameBuffer frameBuffer) => _cameraService.ReturnViewFinderFrame(frameBuffer);
|
public void ReturnViewFinderFrame(FrameBuffer frameBuffer) => _cameraService.ReturnViewFinderFrame(frameBuffer);
|
||||||
|
|
||||||
|
|||||||
@@ -391,8 +391,10 @@ public partial class CameraView : OpenGlControlBase
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
(LibCameraSharp.FrameBuffer, LibCameraSharp.StreamConfiguration)? frame = null;
|
(LibCameraSharp.FrameBuffer, LibCameraSharp.StreamConfiguration)? frame = null;
|
||||||
while (frame is null)
|
while (frame is null && (DataContext as CameraViewModel)?.CanGrabViewFinderFrame() == true)
|
||||||
frame = (DataContext as CameraViewModel)?.GrabViewFinderFrame();
|
frame = (DataContext as CameraViewModel)?.GrabViewFinderFrame();
|
||||||
|
if (frame is null)
|
||||||
|
return;
|
||||||
var (frameBuffer, streamConfiguration) = frame.Value;
|
var (frameBuffer, streamConfiguration) = frame.Value;
|
||||||
|
|
||||||
// 0. Проверяем что полученый фрейм ожидаемый праильный формат
|
// 0. Проверяем что полученый фрейм ожидаемый праильный формат
|
||||||
@@ -429,12 +431,12 @@ public partial class CameraView : OpenGlControlBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var plane = frameBuffer.Planes.First();
|
var plane = frameBuffer.Planes.First();
|
||||||
if (plane.Length != width * height * 4)
|
// if (plane.Length != width * height * 4)
|
||||||
{
|
// {
|
||||||
_logger.LogError("Cannot render frame, plane validation error, expected plane size 0x{:X}, got 0x{:X}", width * height * 4, plane.Length);
|
// _logger.LogError("Cannot render frame, plane validation error, expected plane size 0x{:X}, got 0x{:X}", width * height * 4, plane.Length);
|
||||||
(DataContext as CameraViewModel)?.ReturnViewFinderFrame(frameBuffer);
|
// (DataContext as CameraViewModel)?.ReturnViewFinderFrame(frameBuffer);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
var fd = plane.Fd.Get();
|
var fd = plane.Fd.Get();
|
||||||
if (fd <= 0)
|
if (fd <= 0)
|
||||||
{
|
{
|
||||||
@@ -468,7 +470,7 @@ public partial class CameraView : OpenGlControlBase
|
|||||||
OpenGLContext.EGL_LINUX_DRM_FOURCC_EXT, unchecked((int)OpenGLContext.DRM_FORMAT_BGRX8888),
|
OpenGLContext.EGL_LINUX_DRM_FOURCC_EXT, unchecked((int)OpenGLContext.DRM_FORMAT_BGRX8888),
|
||||||
OpenGLContext.EGL_DMA_BUF_PLANE0_FD_EXT, fd,
|
OpenGLContext.EGL_DMA_BUF_PLANE0_FD_EXT, fd,
|
||||||
OpenGLContext.EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
OpenGLContext.EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||||
OpenGLContext.EGL_DMA_BUF_PLANE0_PITCH_EXT, (int)(width * 4),
|
OpenGLContext.EGL_DMA_BUF_PLANE0_PITCH_EXT, (int)(plane.Length / height),
|
||||||
EglConsts.EGL_NONE
|
EglConsts.EGL_NONE
|
||||||
};
|
};
|
||||||
image = _openGLContext.EglCreateImageKHR.Invoke(_openGLContext.EglDisplay, IntPtr.Zero, OpenGLContext.EGL_LINUX_DMA_BUF_EXT, IntPtr.Zero, attribs);
|
image = _openGLContext.EglCreateImageKHR.Invoke(_openGLContext.EglDisplay, IntPtr.Zero, OpenGLContext.EGL_LINUX_DMA_BUF_EXT, IntPtr.Zero, attribs);
|
||||||
|
|||||||
Reference in New Issue
Block a user