Commit f6e69ae5 by liulongfei

1. 视频控件对齐队列

parent f3726dc1
......@@ -186,6 +186,9 @@
<Compile Include="SharpDx\WIC\WicBitmapHelper.cs" />
<Compile Include="SharpDx\WPF\D2dControl.cs" />
<Compile Include="SharpDx\WPF\Dx11ImageSource.cs" />
<Compile Include="VideoControl\Sync\IVideoControlSync.cs" />
<Compile Include="VideoControl\Sync\VideoControlSyncEventArgs.cs" />
<Compile Include="VideoControl\Sync\VideoControlSyncQueue.cs" />
<Compile Include="VideoControl\Control\IVideoPlugin.cs" />
<Compile Include="VideoControl\Control\Plugin\ClipBox\ClipBoxExpand.cs" />
<Compile Include="VideoControl\Control\Plugin\ClipBox\ClipBoxPlugin.cs" />
......
......@@ -20,7 +20,7 @@ namespace VIZ.Framework.Common
/// <summary>
/// 源点集合
/// </summary>
public List<RawVector2> SrcPoints { get; set; }
public List<RawVector2> SrcPoints { get; set; } = new List<RawVector2>();
/// <summary>
/// 填充颜色
......
......@@ -60,7 +60,7 @@ namespace VIZ.Framework.Common
foreach (TrackingBoxInfo item in trackingBoxInfos)
{
System.Windows.Point center = new System.Windows.Point((item.SrcRect.Right - item.SrcRect.Left) / 2d, (item.SrcRect.Bottom - item.SrcRect.Top) / 2d);
System.Windows.Point center = new System.Windows.Point((item.SrcRect.Right - item.SrcRect.Left) / 2d + item.SrcRect.Left, (item.SrcRect.Bottom - item.SrcRect.Top) / 2d + item.SrcRect.Top);
double dist = Math.Pow((point.Y - center.Y), 2) + Math.Pow((point.X - center.X), 2);
if (dist < min)
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Common
{
/// <summary>
/// 视频控件对齐
/// </summary>
public interface IVideoControlSync
{
/// <summary>
/// 时间戳
/// </summary>
long TimeStamp { get; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Common
{
/// <summary>
/// 视频控件同步事件参数
/// </summary>
public class VideoControlSyncEventArgs : EventArgs
{
/// <summary>
/// 视频帧
/// </summary>
public IVideoControlSync VideoFrame { get; set; }
/// <summary>
/// 数据帧
/// </summary>
public IVideoControlSync DataFrame { get; set; }
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using log4net;
namespace VIZ.Framework.Common
{
/// <summary>
/// 视频控件对齐队列
/// </summary>
/// <remarks>
/// 处理 VideoFrameQueue 与 DataFrameQueue 队列的帧对齐
/// </remarks>
public class VideoControlSyncQueue : IDisposable
{
/// <summary>
/// 日志
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(VideoControlSyncQueue));
/// <summary>
/// 最大队列长度
/// </summary>
public int MaxQueueCount { get; set; } = 100;
/// <summary>
/// 帧同步时触发
/// </summary>
public event EventHandler<VideoControlSyncEventArgs> OnFrameSync;
/// <summary>
/// 视频帧队列
/// </summary>
public ConcurrentQueue<IVideoControlSync> VideoFrameQueue { get; private set; } = new ConcurrentQueue<IVideoControlSync>();
/// <summary>
/// 数据帧队列
/// </summary>
public ConcurrentQueue<IVideoControlSync> DataFrameQueue { get; private set; } = new ConcurrentQueue<IVideoControlSync>();
/// <summary>
/// 视频帧待处理数据
/// </summary>
private volatile IVideoControlSync VideoFrame;
/// <summary>
/// 数据帧待处理数据
/// </summary>
private volatile IVideoControlSync DataFrame;
/// <summary>
/// 销毁
/// </summary>
public void Dispose()
{
this.VideoFrameQueue = null;
this.DataFrameQueue = null;
}
/// <summary>
/// 执行对齐
/// </summary>
public void Execute()
{
try
{
IVideoControlSync video = this.VideoFrame;
IVideoControlSync data = this.DataFrame;
if (this.VideoFrame == null)
{
this.VideoFrameQueue.TryDequeue(out video);
}
if (this.DataFrame == null)
{
this.DataFrameQueue.TryDequeue(out data);
}
int videoQueueCount = this.VideoFrameQueue.Count;
// 没有视频帧时不处理
if (video == null)
return;
// 有视频帧 没有数据帧
if (data == null)
{
// 如果视频帧队列在等待队列长度范围内,那么不处理
if (videoQueueCount < this.MaxQueueCount)
return;
// 处理数据
this.triggerEvent(video, null);
this.VideoFrame = null;
return;
}
// 如果视频帧的时间戳小于数据的时间戳
if (video.TimeStamp < data.TimeStamp)
{
this.triggerEvent(video, null);
this.VideoFrame = null;
return;
}
this.triggerEvent(video, data);
this.VideoFrame = null;
this.DataFrame = null;
}
catch (Exception ex)
{
log.Error(ex);
}
}
/// <summary>
/// 触发事件
/// </summary>
/// <param name="videoFrame">视频帧</param>
/// <param name="dataFrame">数据帧</param>
private void triggerEvent(IVideoControlSync videoFrame, IVideoControlSync dataFrame)
{
try
{
if (this.OnFrameSync == null)
return;
VideoControlSyncEventArgs args = new VideoControlSyncEventArgs();
args.VideoFrame = videoFrame;
args.DataFrame = dataFrame;
this.OnFrameSync.Invoke(this, args);
}
catch (Exception ex)
{
log.Error(ex);
}
}
}
}
......@@ -13,6 +13,14 @@ namespace VIZ.Framework.Connection
public static class TcpEndpointManagerExpand
{
/// <summary>
/// 序列化设置
/// </summary>
private readonly static JsonSerializerSettings JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="manager">TCP终结点管理器</param>
......@@ -42,7 +50,7 @@ namespace VIZ.Framework.Connection
/// <param name="encoding">字符编码方式</param>
public static void SendJson(this TcpEndpointManager manager, object obj, Encoding encoding)
{
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj);
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj, JSON_SERIALIZER_SETTINGS);
SendString(manager, msg, encoding);
}
......@@ -53,7 +61,7 @@ namespace VIZ.Framework.Connection
/// <param name="obj">对象</param>
public static void SendJson(this TcpEndpointManager manager, object obj)
{
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj);
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj, JSON_SERIALIZER_SETTINGS);
SendString(manager, msg, Encoding.UTF8);
}
}
......
......@@ -13,6 +13,14 @@ namespace VIZ.Framework.Connection
public static class UdpEndpointManagerExpand
{
/// <summary>
/// 序列化设置
/// </summary>
private readonly static JsonSerializerSettings JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="manager">UDP终结点管理器</param>
......@@ -42,7 +50,7 @@ namespace VIZ.Framework.Connection
/// <param name="encoding">字符编码方式</param>
public static void SendJson(this UdpEndpointManager manager, object obj, Encoding encoding)
{
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj);
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj, JSON_SERIALIZER_SETTINGS);
SendString(manager, msg, encoding);
}
......@@ -53,7 +61,7 @@ namespace VIZ.Framework.Connection
/// <param name="obj">对象</param>
public static void SendJson(this UdpEndpointManager manager, object obj)
{
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj);
string msg = obj == null ? string.Empty : JsonConvert.SerializeObject(obj, JSON_SERIALIZER_SETTINGS);
SendString(manager, msg, Encoding.UTF8);
}
}
......
......@@ -133,6 +133,7 @@ namespace VIZ.Framework.Core
catch (Exception ex)
{
log.Error(ex);
item.LastTriggerTime = now;
}
}
}
......
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Net;
......@@ -14,32 +16,41 @@ namespace VIZ.Framework.Core
/// </summary>
public static class NetHelper
{
/// summary
/// 获取网卡硬件地址
/// /summary
/// returns mac地址 /returns
public static string GetMacAddress()
/// <summary>
/// 获取当前使用的网卡或排序最后的有效网卡地址
/// </summary>
/// <returns>获取当前使用的或最后一个网卡地址</returns>
public static string GetUsedOrLastMacAddress()
{
try
{
//获取网卡硬件地址
string mac = string.Empty;
List<string> list = new List<string>();
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"])
{
mac = mo["MacAddress"].ToString();
break;
}
bool mac_ipEnabled = (bool)mo["IPEnabled"];
string mac_address = mo["MacAddress"]?.ToString()?.ToUpper();
string mac_description = mo["Description"]?.ToString()?.ToLower();
if (string.IsNullOrWhiteSpace(mac_address) || string.IsNullOrWhiteSpace(mac_description))
continue;
if (mac_description.Contains("debug") || mac_description.Contains("virtual") || mac_description.Contains("miniport"))
continue;
if (mac_ipEnabled)
return mac_address;
list.Add(mac_address);
}
moc.Dispose();
mc.Dispose();
moc = null;
mc = null;
return mac;
return list.LastOrDefault() ?? string.Empty;
}
catch
{
......@@ -48,6 +59,44 @@ namespace VIZ.Framework.Core
}
/// <summary>
/// 获取所有有效的Mac地址
/// </summary>
/// <returns>Mac地址</returns>
public static List<string> GetAllMacAddress()
{
List<string> result = new List<string>();
try
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
string mac_address = mo["MacAddress"]?.ToString()?.ToUpper();
string mac_description = mo["Description"]?.ToString()?.ToLower();
if (string.IsNullOrWhiteSpace(mac_address) || string.IsNullOrWhiteSpace(mac_description))
continue;
if (mac_description.Contains("debug") || mac_description.Contains("virtual") || mac_description.Contains("miniport"))
continue;
result.Add(mac_address);
}
moc.Dispose();
mc.Dispose();
moc = null;
mc = null;
return result;
}
catch
{
return result;
}
}
/// <summary>
/// 获取一个可用的UDP端口
/// </summary>
/// <param name="startPort">开始端口</param>
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Core
{
/// <summary>
/// 应用程序MAC地址检测
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
public class ApplicationMacCheckAttribute : Attribute
{
/// <summary>
/// 应用程序MAC地址检测
/// </summary>
/// <param name="macAddress">MAC地址</param>
public ApplicationMacCheckAttribute(string macAddress)
{
this.MacAddress = macAddress;
}
/// <summary>
/// 过期时间
/// </summary>
public string MacAddress { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Core
{
/// <summary>
/// 应用程序时间检测
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
public class ApplicationTimeCheckAttribute : Attribute
{
/// <summary>
/// 应用程序时间检测
/// </summary>
/// <param name="expirationTime">过期时间</param>
public ApplicationTimeCheckAttribute(string expirationTime)
{
this.ExpirationTime = DateTime.Parse(expirationTime);
}
/// <summary>
/// 过期时间
/// </summary>
public DateTime ExpirationTime { get; set; }
}
}
......@@ -94,6 +94,8 @@
<Compile Include="Core\Helper\ByteHelper.cs" />
<Compile Include="Core\Helper\ProcessHelper.cs" />
<Compile Include="Core\Helper\FPSHelper.cs" />
<Compile Include="Core\Safe\ApplicationMacCheckAttribute.cs" />
<Compile Include="Core\Safe\ApplicationTimeCheckAttribute.cs" />
<Compile Include="Expand\GPI\GPIManager.cs" />
<Compile Include="Expand\GPI\GPI_USB2GPI_DEVICE.cs" />
<Compile Include="Expand\GPI\GPI_USB_DEVICE.cs" />
......
......@@ -7,6 +7,7 @@
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBox x:Name="tb" Width="400" Height="60" IsReadOnly="True" FontSize="24" VerticalContentAlignment="Center" Loaded="tb_Loaded"></TextBox>
<TextBox x:Name="tb" Width="400" Height="300" IsReadOnly="True" FontSize="24" VerticalContentAlignment="Top" Loaded="tb_Loaded"
TextWrapping="Wrap"></TextBox>
</Grid>
</Window>
......@@ -28,7 +28,13 @@ namespace VIZ.Framework.MacTool
private void tb_Loaded(object sender, RoutedEventArgs e)
{
this.tb.Text = NetHelper.GetMacAddress();
StringBuilder sb = new StringBuilder();
foreach (string mac in NetHelper.GetAllMacAddress())
{
sb.AppendLine(mac);
}
this.tb.Text = sb.ToString();
}
}
}
......@@ -49,22 +49,25 @@ namespace VIZ.Framework.Module
/// </summary>
private static void InitSetup()
{
// Step 1. 单例启动
// Step 1. 应用程序安全
appSetups.Add(new AppSetup_ApplicationSafe());
// Step 2. 单例启动
appSetups.Add(new AppSetup_Single());
// Step 2. 捕获未处理异常
// Step 3. 捕获未处理异常
appSetups.Add(new AppSetup_CatchUnhandledException());
// Step 3. 初始化日志
// Step 4. 初始化日志
appSetups.Add(new AppSetup_LogInit());
// Step 4. 初始化延时
// Step 5. 初始化延时
appSetups.Add(new AppSetup_DelayInit());
// Step 5. 初始化循环
// Step 6. 初始化循环
appSetups.Add(new AppSetup_Loop());
// Step 6. 初始化辅助类
// Step 7. 初始化辅助类
appSetups.Add(new AppSetup_Helper());
}
......
using log4net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Management;
using VIZ.Framework.Core;
using VIZ.Framework.Connection;
using VIZ.Framework.Module;
using System.Reflection;
namespace VIZ.Framework.Module
{
/// <summary>
/// 应用程序启动 -- 应用程序安全
/// </summary>
public class AppSetup_ApplicationSafe : AppSetupBase
{
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(AppSetup_ApplicationSafe));
/// <summary>
/// 描述
/// </summary>
public override string Detail { get; } = "应用程序启动 -- 应用程序安全";
/// <summary>
/// 执行启动
/// </summary>
/// <param name="context">应用程序启动上下文</param>
/// <returns>是否成功执行</returns>
public override bool Setup(AppSetupContext context)
{
Assembly assembly = Assembly.GetEntryAssembly();
// Step 1. 应用程序过期时间校验
ApplicationTimeCheckAttribute time_check = assembly.GetCustomAttribute<ApplicationTimeCheckAttribute>();
if (time_check != null && time_check.ExpirationTime < DateTime.Now)
{
MessageBox.Show("系统校验失败,请联系管理员!");
return false;
}
// Step 2. 应用程序MAC地址校验
List<string> mac_address_list = NetHelper.GetAllMacAddress();
IEnumerable<ApplicationMacCheckAttribute> mac_check_list = assembly.GetCustomAttributes<ApplicationMacCheckAttribute>();
if (mac_check_list != null && mac_check_list.Count() > 0 && !mac_check_list.Any(p => mac_address_list.Contains(p.MacAddress)))
{
MessageBox.Show("系统校验失败,请联系管理员!");
return false;
}
return true;
}
/// <summary>
/// 执行关闭
/// </summary>
/// <param name="context">应用程序启动上下文</param>
public override void Shutdown(AppSetupContext context)
{
}
}
}
......@@ -98,6 +98,7 @@
<Compile Include="Setup\AppSetupContext.cs" />
<Compile Include="Setup\IAppSetup.cs" />
<Compile Include="Setup\Message\AppShutDownMessage.cs" />
<Compile Include="Setup\Provider\Setup\AppSetup_ApplicationSafe.cs" />
<Compile Include="Setup\Provider\Setup\AppSetup_Helper.cs" />
<Compile Include="Setup\Provider\Setup\AppSetup_CatchUnhandledException.cs" />
<Compile Include="Setup\Provider\Setup\AppSetup_Navigation3D.cs" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Storage
{
/// <summary>
/// CSV文件特性
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class CsvAttribute : Attribute
{
/// <summary>
/// 场景
/// </summary>
public CsvScene Scene { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.Storage
{
/// <summary>
/// CSV文件场景
/// </summary>
public enum CsvScene
{
/// <summary>
/// 写
/// </summary>
Write,
/// <summary>
/// 读
/// </summary>
Read,
/// <summary>
/// 读写
/// </summary>
ReadAndWrite
}
}
......@@ -77,5 +77,11 @@ namespace VIZ.Framework.Storage
/// </summary>
[Ini(Section = "Video", DefaultValue = "#44000000", Type = typeof(RawColor4))]
public string VIDEO_CLIP_BOX_MASK_COLOR { get; set; }
/// <summary>
/// 视频边线检测多边形区域透明度
/// </summary>
[Ini(Section = "Video", DefaultValue = "0.2", Type = typeof(double))]
public string VIDEO_SIDE_CHECK_POLYGON_OPACITY { get; set; }
}
}
......@@ -70,6 +70,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSV\CsvAttribute.cs" />
<Compile Include="CSV\CsvScene.cs" />
<Compile Include="Ini\Config\ApplicationConfig.cs" />
<Compile Include="Ini\Config\Navigation3DConfig.cs" />
<Compile Include="Ini\Config\VideoConfig.cs" />
......
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using VIZ.Framework.Core;
using Newtonsoft.Json;
namespace VIZ.Framework.UnitTest
{
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
/// <summary>
/// JSON测试
/// </summary>
[TestClass]
public class JsonTest
{
/// <summary>
/// Python Json 测试
/// </summary>
[TestMethod]
public void PythonJsonTest()
{
Student student = new Student();
student.Name = null;
student.Age = 17;
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
string str = JsonConvert.SerializeObject(student, settings);
}
/// <summary>
/// 时间测试
/// </summary>
[TestMethod]
public void TimeTest()
{
// 16612406883518854
long begin = new DateTime(1970, 1, 1, 8, 0, 0).Ticks;
DateTime time = new DateTime(16612406883518854 + begin);
}
}
}
......@@ -23,7 +23,7 @@ namespace VIZ.Framework.UnitTest
[TestMethod]
public void GetMacTest()
{
string str = NetHelper.GetMacAddress();
string str = NetHelper.GetUsedOrLastMacAddress();
Assert.IsTrue(!string.IsNullOrWhiteSpace(str));
}
......
......@@ -70,6 +70,7 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="JsonTest.cs" />
<Compile Include="MonitorTask.cs" />
<Compile Include="NetTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
......
......@@ -4,7 +4,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment