2019-08-23 09:13:10 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Drawing2D;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using DateTime = System.DateTime;
|
|
|
|
|
|
|
|
|
|
namespace IPCamAppBar
|
|
|
|
|
{
|
|
|
|
|
public partial class CameraView : UserControl
|
|
|
|
|
{
|
|
|
|
|
private DateTime lastFrameTime;
|
2019-08-24 15:35:41 +00:00
|
|
|
|
|
2019-08-23 09:13:10 +00:00
|
|
|
|
|
|
|
|
|
public CameraView(string url)
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
|
|
|
|
var cameraStream = new CameraMJPEGStream();
|
|
|
|
|
cameraStream.Frame += CameraStreamOnFrame;
|
2019-08-24 15:35:41 +00:00
|
|
|
|
cameraStream.StreamException += CameraStreamOnStreamException;
|
2019-08-23 09:13:10 +00:00
|
|
|
|
cameraStream.Start(url);
|
|
|
|
|
|
|
|
|
|
Disposed += (sender, args) =>
|
|
|
|
|
{
|
2019-08-25 18:02:22 +00:00
|
|
|
|
cameraStream.Dispose();
|
2019-08-23 09:13:10 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CameraStreamOnFrame(object sender, FrameEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
// The event comes from a background thread, so if needed invoke it on the main thread
|
|
|
|
|
if (InvokeRequired)
|
|
|
|
|
{
|
|
|
|
|
Invoke(new Action(() => { CameraStreamOnFrame(sender, args); }));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConnectingLabel.Visible = false;
|
|
|
|
|
StreamView.Visible = true;
|
2019-08-24 15:35:41 +00:00
|
|
|
|
IssueLabel.Visible = false;
|
2019-08-23 09:13:10 +00:00
|
|
|
|
|
|
|
|
|
lastFrameTime = DateTime.Now;
|
2019-08-24 15:35:41 +00:00
|
|
|
|
NoDataTimer.Start();
|
2019-08-23 09:13:10 +00:00
|
|
|
|
|
|
|
|
|
var viewImage = new Bitmap(Width, Height);
|
|
|
|
|
using (var graphics = Graphics.FromImage(viewImage))
|
|
|
|
|
{
|
|
|
|
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
|
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
|
|
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
|
|
|
|
|
|
|
|
graphics.DrawImage(args.Image, 0, 0, viewImage.Width, viewImage.Height);
|
|
|
|
|
|
|
|
|
|
using (var path = new GraphicsPath())
|
|
|
|
|
{
|
|
|
|
|
path.AddString(
|
|
|
|
|
lastFrameTime.ToString("G"),
|
|
|
|
|
FontFamily.GenericSansSerif,
|
|
|
|
|
(int)FontStyle.Regular,
|
|
|
|
|
graphics.DpiY * 14 / 72,
|
|
|
|
|
Rectangle.Inflate(new Rectangle(0, 0, viewImage.Width, viewImage.Height), -4, -4),
|
|
|
|
|
new StringFormat
|
|
|
|
|
{
|
|
|
|
|
Alignment = StringAlignment.Far,
|
|
|
|
|
LineAlignment = StringAlignment.Far
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
graphics.DrawPath(new Pen(Color.Black, 3), path);
|
|
|
|
|
graphics.FillPath(Brushes.White, path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
graphics.Flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var oldImage = StreamView.Image;
|
|
|
|
|
StreamView.Image = viewImage;
|
|
|
|
|
oldImage?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-08-24 15:35:41 +00:00
|
|
|
|
private void CameraStreamOnStreamException(object sender, StreamExceptionEventArgs args)
|
|
|
|
|
{
|
2019-08-25 18:02:22 +00:00
|
|
|
|
if (InvokeRequired)
|
|
|
|
|
{
|
|
|
|
|
Invoke(new Action(() => { CameraStreamOnStreamException(sender, args); }));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-24 15:35:41 +00:00
|
|
|
|
IssueLabel.Text = args.Exception.Message;
|
|
|
|
|
IssueLabel.Visible = true;
|
|
|
|
|
IssueLabel.BringToFront();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void NoDataTimer_Tick(object sender, EventArgs e)
|
2019-08-23 09:13:10 +00:00
|
|
|
|
{
|
|
|
|
|
var timeSinceLastFrame = DateTime.Now - lastFrameTime;
|
|
|
|
|
if (timeSinceLastFrame.TotalSeconds < 10)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-08-24 15:35:41 +00:00
|
|
|
|
IssueLabel.Text = $@"No data for {(int)timeSinceLastFrame.TotalSeconds} seconds";
|
|
|
|
|
IssueLabel.Visible = true;
|
|
|
|
|
IssueLabel.BringToFront();
|
2019-08-23 09:13:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|