Skip to content

Huge Update, NT4, CsCore, and .NET Core 3.1 #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions DotNetDash.CameraViews/BitmapSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using FRC.CameraServer;
using FRC.CameraServer.Interop;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CsPixelFormat = FRC.CameraServer.PixelFormat;

namespace DotNetDash.CameraViews
{
public class BitmapSink : ImageSink
{
private CS_RawFrame frame = new CS_RawFrame();
unsafe byte* dataPtr;
int width;
int height;
int pixelFormat;


public BitmapSink(string name)
: base(CsCore.CreateRawSink(name.AsSpan()))
{

}

public long GrabFrame(ref Bitmap image)
{
return GrabFrame(ref image, .225);
}

public unsafe long GrabFrame(ref Bitmap image, double timeout)
{
frame.width = 0;
frame.height = 0;
frame.pixelFormat = (int)CsPixelFormat.BGR;

ulong rv = CsCore.GrabRawSinkFrameTimeout(Handle, ref frame, timeout);
if (rv == 0) return 0;


if (dataPtr != frame.data || width != frame.width || height != frame.height || pixelFormat != frame.pixelFormat)
{
dataPtr = frame.data;
width = frame.width;
height = frame.height;
pixelFormat = frame.pixelFormat;
}

if (image == null || image.Width != width || image.Height != height || image.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
{
image = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
}

ToBitmap(frame, image);

//BitmapConverter.ToBitmap(tmpMat, image);
return (long)rv;
}

private unsafe void ToBitmap(in CS_RawFrame src, Bitmap dst)
{
var pf = dst.PixelFormat;

if (pf != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
{
throw new Exception("Unsupported pixel format");
}

int w = src.width;
int h = src.height;

Rectangle rect = new Rectangle(0, 0, w, h);
BitmapData bd = null;

try
{
bd = dst.LockBits(rect, ImageLockMode.WriteOnly, pf);

IntPtr srcData = (IntPtr)src.data;
byte* pSrc = (byte*)srcData.ToPointer();
byte* pDst = (byte*)bd.Scan0.ToPointer();
int ch = 3;
int sstep = src.width * ch;
int dstep = ((src.width * 3) + 3) / 4 * 4;
int stride = bd.Stride;

if (sstep == dstep)
{
CopyMemory(pDst, pSrc, src.totalData);
}
else
{
for (int y = 0; y < h; y++)
{
long offsetSrc = (long)y * sstep;
long offsetDst = (long)y * dstep;

CopyMemory(pDst + offsetDst, pSrc + offsetSrc, w * ch);
}
}
}
finally
{
dst.UnlockBits(bd);
}
}

private unsafe void CopyMemory(void* outDest, void* inSrc, int inNumOfBytes)
{
Buffer.MemoryCopy(inSrc, outDest, inNumOfBytes, inNumOfBytes);
}
}
}
6 changes: 3 additions & 3 deletions DotNetDash.CameraViews/CameraInfoRootTableProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
using System.Text;
using System.Threading.Tasks;
using DotNetDash.BuiltinProcessors;
using NetworkTables.Tables;
using FRC.NetworkTables;

namespace DotNetDash.CameraViews
{
class CameraInfoRootTableProcessor : DefaultRootTableProcessor
{
public CameraInfoRootTableProcessor(string name, ITable table, IEnumerable<Lazy<ITableProcessorFactory, IDashboardTypeMetadata>> processorFactories) : base(name, table, processorFactories)
public CameraInfoRootTableProcessor(string name, NetworkTable table, IEnumerable<Lazy<ITableProcessorFactory, IDashboardTypeMetadata>> processorFactories) : base(name, table, processorFactories)
{
}

Expand All @@ -29,7 +29,7 @@ public CameraInfoRootTableProcessorFactory([ImportMany] IEnumerable<Lazy<ITableP
this.processorFactories = processorFactories;
}

public TableProcessor Create(string subTable, ITable table)
public TableProcessor Create(string subTable, NetworkTable table)
{
return new CameraInfoRootTableProcessor(subTable, table, processorFactories);
}
Expand Down
8 changes: 4 additions & 4 deletions DotNetDash.CameraViews/CameraInformationProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using System;
using FRC.NetworkTables;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using NetworkTables.Tables;

namespace DotNetDash.CameraViews
{
class CameraInformationProcessor : TableProcessor
{
public CameraInformationProcessor(string name, ITable table, IEnumerable<Lazy<ITableProcessorFactory, IDashboardTypeMetadata>> processorFactories) : base(name, table, processorFactories)
public CameraInformationProcessor(string name, NetworkTable table, IEnumerable<Lazy<ITableProcessorFactory, IDashboardTypeMetadata>> processorFactories) : base(name, table, processorFactories)
{
}

Expand All @@ -31,7 +31,7 @@ public CameraInformationProcessorFactory([ImportMany] IEnumerable<Lazy<ITablePro
this.processorFactories = processorFactories;
}

public TableProcessor Create(string subTable, ITable table)
public TableProcessor Create(string subTable, NetworkTable table)
{
return new CameraInformationProcessor(subTable, table, processorFactories);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<UserControl x:Class="DotNetDash.CameraViews.CameraView"
<UserControl x:Class="DotNetDash.CameraViews.CsCameraView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using AForge.Video;

namespace DotNetDash.CameraViews
{
/// <summary>
/// Interaction logic for BaseCameraView.xaml
/// </summary>
public partial class CameraView : UserControl, INotifyPropertyChanged
public partial class CsCameraView : UserControl, INotifyPropertyChanged
{
public CameraView()
public CsCameraView()
{
DataContext = this;
InitializeComponent();
IsVisibleChanged += OnIsVisibleChanged;
}

volatile bool doUpdate = false;

private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var isVisible = (bool)e.NewValue;
if (isVisible)
CurrentDevice?.Start();
else
CurrentDevice?.SignalToStop();
doUpdate = isVisible;
}

public IVideoSource currentDevice;
public CsVideoSource currentDevice;

public IVideoSource CurrentDevice
public CsVideoSource CurrentDevice
{
get
{
Expand All @@ -42,7 +41,6 @@ public IVideoSource CurrentDevice
{
if (currentDevice != null)
{
currentDevice.NewFrame -= NewFrame;
currentDevice.Stop();
}
currentDevice = value;
Expand All @@ -54,15 +52,14 @@ public IVideoSource CurrentDevice
}
}

private void NewFrame(object sender, NewFrameEventArgs eventArgs)
private void NewFrame(object sender, Bitmap bitmap)
{
var bitmap = eventArgs.Frame.Clone() as System.Drawing.Bitmap;
if (!doUpdate) return;
var previous = View;
Stream stream = unusedStream;
stream.Seek(0, SeekOrigin.Begin);
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
stream.Seek(0, SeekOrigin.Begin);
bitmap.Dispose();

Dispatcher.Invoke(() =>
{
Expand Down
56 changes: 56 additions & 0 deletions DotNetDash.CameraViews/CsVideoSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using FRC.CameraServer;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DotNetDash.CameraViews
{
public class CsVideoSource
{
private Thread readThread;
private volatile bool isRunning = true;
private BitmapSink cvSink;
private Bitmap bitmap;
private VideoSource source;

public event EventHandler<Bitmap> NewFrame;

public CsVideoSource(BitmapSink sink, VideoSource source)
{
cvSink = sink;
this.source = source;
}

public void Start()
{
readThread = new Thread(ThreadMain);
readThread.IsBackground = true;
readThread.Start();
}

private void ThreadMain()
{
while (isRunning)
{
var ret = cvSink.GrabFrame(ref bitmap);
if (!isRunning) return;
if (ret == 0) continue;

NewFrame?.Invoke(this, bitmap);
}
}

public void Stop()
{
isRunning = false;
if (readThread != null)
{
readThread.Join();
}
}
}
}
Loading