Files
TheXamlGuy/Media/Capture/MediaFrameReader.cs
2022-11-01 15:26:08 +00:00

89 lines
2.2 KiB
C#

using TheXamlGuy.UI;
using AForge.Video.DirectShow;
using System.Drawing;
using AForge.Video;
using System.Drawing.Imaging;
namespace TheXamlGuy.Media.Capture;
public class MediaFrameReader : IMediaFrameReader
{
private readonly VideoCaptureDevice captureDevice;
private bool isAquiringFrames;
internal MediaFrameReader(IMediaFrameSource frameSource)
{
captureDevice = new(frameSource.Info.Id);
captureDevice.VideoResolution = captureDevice
.VideoCapabilities
.FirstOrDefault(x => frameSource.CurrentFormat.FrameRate == x.AverageFrameRate && x.FrameSize.Equals(frameSource.CurrentFormat.Size));
captureDevice.NewFrame += OnNewFrame;
}
public event TypedEventHandler<IMediaFrameReader, MediaFrameArrivedEventArgs>? FrameArrived;
public void Dispose()
{
captureDevice.Stop();
}
public async Task StartAsync()
{
if (!captureDevice.IsRunning)
{
isAquiringFrames = true;
captureDevice.Start();
}
await Task.CompletedTask;
}
public async Task StopAsync()
{
if (captureDevice.IsRunning)
{
isAquiringFrames = false;
captureDevice.Stop();
}
await Task.CompletedTask;
}
public async Task<MediaFrame?> TryAcquireLatestFrameAsync()
{
TaskCompletionSource<Bitmap> completionSource = new();
void HandleNewFrame(object sender, NewFrameEventArgs args)
{
if (args.Frame.PixelFormat is not PixelFormat.DontCare)
{
captureDevice.NewFrame -= HandleNewFrame;
completionSource.SetResult(new Bitmap(args.Frame));
}
}
captureDevice.NewFrame += HandleNewFrame;
if (!isAquiringFrames)
{
captureDevice.Start();
}
Bitmap frame = await completionSource.Task;
if (!isAquiringFrames)
{
captureDevice.SignalToStop();
captureDevice.WaitForStop();
}
return new MediaFrame(frame, frame.Width, frame.Height);
}
private void OnNewFrame(object sender, NewFrameEventArgs args)
{
FrameArrived?.Invoke(this, new MediaFrameArrivedEventArgs());
}
}