Commit e828ccee by liulongfei

1. 项目升级,接入通用框架

2. 添加中心轴视频插件
3. 添加云台杆值控制中心轴功能
parent 03d5bdff
......@@ -9,6 +9,10 @@
<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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
\ No newline at end of file
......@@ -5,7 +5,8 @@ using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Module;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Module;
namespace VIZ.GimbalAI.Client
......@@ -17,6 +18,16 @@ namespace VIZ.GimbalAI.Client
{
public App()
{
// 初始化 CSV
AppSetup.AppendSetup(new AppSetup_InitCSV());
// 初始化 LiteDB
AppSetup.AppendSetup(new AppSetup_InitLiteDB());
// 初始化 NDI
AppSetup.AppendSetup(new AppSetup_InitNDI());
// 初始化 UDP
AppSetup.AppendSetup(new AppSetup_InitUDP());
// 启动
AppSetupContext context = AppSetup.Setup();
if (context.Exception != null)
......
......@@ -19,6 +19,8 @@ using VIZ.GimbalAI.Storage;
using System.Diagnostics;
using VIZ.GimbalAI.Module;
using VIZ.GimbalAI.Connection;
using VIZ.Framework.Module;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Client
{
......
......@@ -164,7 +164,7 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="config\classes.xls">
<None Include="config\classes.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="config\config.ini">
......@@ -184,6 +184,34 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Common.Resource\VIZ.Framework.Common.Resource.csproj">
<Project>{76ef480a-e486-41b7-b7a5-2a849fc8d5bf}</Project>
<Name>VIZ.Framework.Common.Resource</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Common\VIZ.Framework.Common.csproj">
<Project>{92834c05-703e-4f05-9224-f36220939d8f}</Project>
<Name>VIZ.Framework.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Connection\VIZ.Framework.Connection.csproj">
<Project>{e07528dd-9dee-47c2-b79d-235ecfa6b003}</Project>
<Name>VIZ.Framework.Connection</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Core\VIZ.Framework.Core.csproj">
<Project>{75b39591-4bc3-4b09-bd7d-ec9f67efa96e}</Project>
<Name>VIZ.Framework.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Domain\VIZ.Framework.Domain.csproj">
<Project>{28661e82-c86a-4611-a028-c34f6ac85c97}</Project>
<Name>VIZ.Framework.Domain</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Module\VIZ.Framework.Module.csproj">
<Project>{47cf6fb0-e37d-4ef1-afc7-03db2bca8892}</Project>
<Name>VIZ.Framework.Module</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Storage\VIZ.Framework.Storage.csproj">
<Project>{06b80c09-343d-4bb2-aeb1-61cfbfbf5cad}</Project>
<Name>VIZ.Framework.Storage</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Common.Resource\VIZ.GimbalAI.Common.Resource.csproj">
<Project>{5d8021d1-a6b2-4784-b8fe-ff3b7f94e304}</Project>
<Name>VIZ.GimbalAI.Common.Resource</Name>
......@@ -196,10 +224,6 @@
<Project>{52ca7346-0bc0-4e03-8ca5-c00a8777f1ef}</Project>
<Name>VIZ.GimbalAI.Connection</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Core\VIZ.GimbalAI.Core.csproj">
<Project>{d4409326-3f36-4835-812a-bea8ed046e04}</Project>
<Name>VIZ.GimbalAI.Core</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Domain\VIZ.GimbalAI.Domain.csproj">
<Project>{bbf80159-d5de-4d82-a045-a96d67d80632}</Project>
<Name>VIZ.GimbalAI.Domain</Name>
......
name,display_name,ID,sign,is_checked
person,人,0,1,1
bicycle,自行车,1,1,0
car,汽车,2,1,0
motorbike,摩托车,3,1,0
aeroplane,飞机,4,1,0
bus,公共汽车,5,1,0
train,火车,6,1,0
truck,卡车,7,1,0
boat,船,8,1,0
traffic light,交通信号灯,9,0,0
fire hydrant,消防栓,10,0,0
stop sign,停车标志,11,0,0
parking meter,停车收费表,12,0,0
bench,长凳,13,0,0
bird,鸟,14,1,0
cat,猫,15,1,0
dog,狗,16,1,0
horse,马,17,1,0
sheep,羊,18,1,0
cow,牛,19,1,0
elephant,大象,20,1,0
bear,熊,21,1,0
zebra,斑马,22,1,0
giraffe,长颈鹿,23,1,0
backpack,背包,24,0,0
umbrella,雨伞,25,0,0
handbag,手提包,26,0,0
tie,领带,27,0,0
suitcase,手提箱,28,0,0
frisbee,飞盘,29,0,0
skis,滑雪板,30,1,0
snowboard,滑雪板,31,1,0
sports ball,球,32,1,0
kite,风筝,33,1,0
baseball bat,棒球棒,34,1,0
baseball glove,棒球手套,35,1,0
skateboard,滑板,36,1,0
surfboard,冲浪板,37,1,0
tennis racket,网球拍,38,1,0
bottle,瓶子,39,0,0
wine glass,酒杯,40,0,0
cup,杯子,41,0,0
fork,叉,42,0,0
knife,刀,43,0,0
spoon,勺子,44,0,0
bowl,碗,45,0,0
banana,香蕉,46,0,0
apple,苹果,47,0,0
sandwich,三明治,48,0,0
orange,橘子,49,0,0
broccoli,西蓝花,50,0,0
carrot,胡萝卜,51,0,0
hot dog,热狗,52,0,0
pizza,披萨,53,0,0
donut,甜甜圈,54,0,0
cake,糕饼,55,0,0
chair,椅子,56,0,0
sofa,沙发,57,0,0
pottedplant,盆栽植物,58,0,0
bed,床,59,0,0
diningtable,餐桌,60,0,0
toilet,马桶,61,0,0
tvmonitor,电视显示器,62,0,0
laptop,笔记本电脑,63,0,0
mouse,鼠标,64,0,0
remote,遥控器,65,0,0
keyboard,键盘,66,0,0
cell phone,手机,67,0,0
microwave,微波炉,68,0,0
oven,烤箱,69,0,0
toaster,烤面包机,70,0,0
sink,水池,71,0,0
refrigerator,冰箱,72,0,0
book,书,73,0,0
clock,时钟,74,0,0
vase,花瓶,75,0,0
scissors,剪刀,76,0,0
teddy bear,泰迪熊,77,0,0
hair drier,吹风机,78,0,0
toothbrush,牙刷,79,0,0
......@@ -2,20 +2,8 @@
; === Client ===
; ============================================================
[Client]
;视频是否显示FPS
CLIENT_IS_VIDEO_SHOW_FPS=true
;视频渲染等待(单位:毫秒)
CLIENT_VIDEO_RENDER_WAIT=5
;视频延时(单位:帧)
CLIENT_VIDEO_DELAY=0
;算法矩形框宽度(单位:像素)
CLIENT_ALGORITHM_RECTANGLE_STROKE_WIDTH=4
;算法矩形框颜色(#AARRGGBB)
CLIENT_ALGORITHM_RECTANGLE_COLOR=#FFFF0000
;框选矩形框宽度(单位:像素)
CLIENT_FRAME_SELECTION_STROKE_WIDTH=4
;框选矩形框颜色(#AARRGGBB)
CLIENT_FRAME_SELECTION_COLOR=#FFFF6D87
;日志输出最大行数,超过该数目会清理日志
CLIENT_CONSOLE_LOG_MAX_LINE=500
; ============================================================
......@@ -49,8 +37,8 @@ NDI_STREAM_NAME=LAPTOP-6ESNHBU6 (Test Pattern)
; ============================================================
[Algorithm]
;算法启动 绝对路径 或 相对路径(相对于智能云台跟踪系统EXE文件的路径)
ALGORITHM_SETUP_PATH=..\python\python.bat
;ALGORITHM_SETUP_PATH=E:\Project\VIZ.GimbalAI\VIZ.GimbalAI.Client\bin\x64\python\python.bat
;ALGORITHM_SETUP_PATH=..\python\python.bat
ALGORITHM_SETUP_PATH=C:\Users\admin\Desktop\object_tracker\start.bat
;算法命令行窗口显示样式
;Normal | Hidden | Minimized | Maximized
ALGORITHM_CMD_WINDOW_STYLE=Minimized
......@@ -62,4 +50,44 @@ ALGORITHM_CMD_WINDOW_STYLE=Minimized
GIMBAL_SETUP_PATH=..\python\python.bat
;云台命令行窗口显示样式
;Normal | Hidden | Minimized | Maximized
GIMBAL_CMD_WINDOW_STYLE=Minimized
\ No newline at end of file
GIMBAL_CMD_WINDOW_STYLE=Minimized
;云台中心轴移动速度
GIMBAL_CENTER_AXIS_SPEED=1
; ============================================================
; === Video ===
; ============================================================
[Video]
;视频是否显示FPS
VIDEO_IS_SHOW_FPS=true
;视频渲染等待(单位:毫秒)
VIDEO_RENDER_WAIT=10
;视频背景颜色
VIDEO_BACKGROUND_COLOR=#FF000000
;视频框边框宽度(单位:像素)
VIDEO_RECTANGLE_BORDER_WIDTH=4
;视频框边框颜色(格式:#AARRGGBB)
VIDEO_RECTANGLE_BORDER_COLOR=#FFFF0000
;视频跟踪框边框宽度(单位:像素)
VIDEO_TRACKING_BOX_BORDER_WIDTH=2
;视频跟踪框边框颜色
VIDEO_TRACKING_BOX_BORDER_COLOR=#FFFF0000
;视频框选边框宽度(单位:像素)
VIDEO_FRAME_SELECTION_BORDER_WIDTH=4
;视频框选边框颜色(格式:#AARRGGBB)
VIDEO_FRAME_SELECTION_BORDER_COLOR=#FFFF6D87
;视频剪切宽度(单位:像素)
VIDEO_CLIP_BOX_WIDTH=810
;视频剪切边框宽度(单位:像素)
VIDEO_CLIP_BOX_BORDER_WIDTH=4
;视频剪切边框颜色
VIDEO_CLIP_BOX_BORDER_COLOR=#FFFF0000
;视频剪切掩码颜色
VIDEO_CLIP_BOX_MASK_COLOR=#88000000
;视频边线检测多边形区域透明度
VIDEO_SIDE_CHECK_POLYGON_OPACITY=0.15
;视频人工校准区域透明度
VIDEO_MANUAL_CORRECTION_OPACITY=0.2
;中心轴宽度
VIDEO_CENTER_AXIS_WIDTH=2
;中心轴颜色
VIDEO_CENTER_AXIS_COLOR=#44000000
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VIZ.GimbalAI.Core;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 消息框
/// </summary>
[TemplatePart(Name = nameof(PART_YesButton), Type = typeof(Button))]
[TemplatePart(Name = nameof(PART_CancelButton), Type = typeof(Button))]
public class VMessageBox : ContentControl
{
static VMessageBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(VMessageBox), new FrameworkPropertyMetadata(typeof(VMessageBox)));
}
#region PART
/// <summary>
/// 确定按钮
/// </summary>
private Button PART_YesButton;
/// <summary>
/// 取消按钮
/// </summary>
private Button PART_CancelButton;
#endregion
#region Buttons -- 按钮组合
/// <summary>
/// 按钮组合
/// </summary>
public VMessageBoxButtons Buttons
{
get { return (VMessageBoxButtons)GetValue(ButtonsProperty); }
set { SetValue(ButtonsProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for Buttons. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty ButtonsProperty =
DependencyProperty.Register("Buttons", typeof(VMessageBoxButtons), typeof(VMessageBox), new PropertyMetadata(VMessageBoxButtons.YES));
#endregion
#region Title -- 标题
/// <summary>
/// 标题
/// </summary>
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(VMessageBox), new PropertyMetadata(null));
#endregion
#region Message -- 消息
/// <summary>
/// 消息
/// </summary>
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for Message. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(string), typeof(VMessageBox), new PropertyMetadata(null));
#endregion
#region Result -- 返回值
/// <summary>
/// 返回值
/// </summary>
public VMessageBoxResult Result
{
get { return (VMessageBoxResult)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for Result. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(VMessageBoxResult), typeof(VMessageBox), new PropertyMetadata(VMessageBoxResult.YES));
#endregion
/// <summary>
/// 创建模板时触发
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_YesButton = this.Template.FindName(nameof(PART_YesButton), this) as Button;
this.PART_CancelButton = this.Template.FindName(nameof(PART_CancelButton), this) as Button;
if (this.PART_YesButton != null)
{
this.PART_YesButton.Click -= PART_YesButton_Click;
this.PART_YesButton.Click += PART_YesButton_Click;
}
if (this.PART_CancelButton != null)
{
this.PART_CancelButton.Click -= PART_CancelButton_Click;
this.PART_CancelButton.Click += PART_CancelButton_Click;
}
}
/// <summary>
/// 点击取消按钮
/// </summary>
private void PART_CancelButton_Click(object sender, RoutedEventArgs e)
{
this.Result = VMessageBoxResult.CANCEL;
Window window = WPFHelper.GetAncestorByType<Window>(this);
window?.Close();
}
/// <summary>
/// 点击确定按钮
/// </summary>
private void PART_YesButton_Click(object sender, RoutedEventArgs e)
{
this.Result = VMessageBoxResult.YES;
Window window = WPFHelper.GetAncestorByType<Window>(this);
window?.Close();
}
/// <summary>
/// 显示提示框(线程安全)
/// </summary>
/// <param name="title">标题</param>
/// <param name="message">消息</param>
/// <param name="buttons">按钮组</param>
/// <param name="ownerWindow">所属窗口</param>
/// <returns>返回值</returns>
public static VMessageBoxResult ShowDialog(string title, string message, VMessageBoxButtons buttons, Window ownerWindow)
{
VMessageBoxResult result = VMessageBoxResult.YES;
WPFHelper.Invoke(() =>
{
VMessageBoxWindow window = new VMessageBoxWindow();
window.box.Title = title;
window.box.Message = message;
window.box.Buttons = buttons;
window.Owner = ownerWindow;
window.ShowDialog();
result = window.box.Result;
});
return result;
}
/// <summary>
/// 显示提示框(线程安全)
/// </summary>
/// <param name="title">标题</param>
/// <param name="message">消息</param>
/// <param name="buttons">按钮组</param>
/// <returns>返回值</returns>
public static VMessageBoxResult ShowDialog(string title, string message, VMessageBoxButtons buttons)
{
VMessageBoxResult result = VMessageBoxResult.YES;
WPFHelper.Invoke(() =>
{
VMessageBoxWindow window = new VMessageBoxWindow();
window.box.Title = title;
window.box.Message = message;
window.box.Buttons = buttons;
window.Owner = Application.Current?.MainWindow;
window.ShowDialog();
result = window.box.Result;
});
return result;
}
/// <summary>
/// 显示提示框(线程安全)
/// </summary>
/// <param name="title">标题</param>
/// <param name="message">消息</param>
/// <returns>返回值</returns>
public static VMessageBoxResult ShowDialog(string title, string message)
{
return ShowDialog(title, message, VMessageBoxButtons.YES);
}
/// <summary>
/// 显示提示框(线程安全)
/// </summary>
/// <param name="message">消息</param>
/// <returns>返回值</returns>
public static VMessageBoxResult ShowDialog(string message)
{
return ShowDialog("提示", message);
}
}
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:VIZ.GimbalAI.Common">
<Style x:Key="VMessageBox_Button_Yes" TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
<Setter Property="Width" Value="140"></Setter>
<Setter Property="Height" Value="45"></Setter>
<Setter Property="Margin" Value="10,0,10,0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="bd" CornerRadius="10" Background="#aa007cff">
<TextBlock Text="确定" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" Foreground="White"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bd" Property="Background" Value="#ff007cff"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="VMessageBox_Button_Cancel" TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
<Setter Property="Width" Value="140"></Setter>
<Setter Property="Height" Value="45"></Setter>
<Setter Property="Margin" Value="10,0,10,0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="bd" CornerRadius="10" Background="#aadcdcdc">
<TextBlock Text="取消" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="18" Foreground="Black"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bd" Property="Background" Value="#ffdcdcdc"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="common:VMessageBox">
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
<Setter Property="Width" Value="400"></Setter>
<Setter Property="Height" Value="300"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="common:VMessageBox">
<Border Background="White" CornerRadius="40">
<Border.Effect>
<DropShadowEffect Opacity="0.36"/>
</Border.Effect>
<Grid Margin="30,20,30,20">
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="80"></RowDefinition>
</Grid.RowDefinitions>
<common:DragWindowBar Grid.RowSpan="3" Background="Transparent"></common:DragWindowBar>
<TextBlock Text="{TemplateBinding Title}" Foreground="Black" FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Left"
FontWeight="Black"></TextBlock>
<TextBlock Grid.Row="1" Text="{TemplateBinding Message}" Foreground="Black" FontSize="24" TextWrapping="Wrap" TextTrimming="CharacterEllipsis"></TextBlock>
<StackPanel Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Right" Orientation="Horizontal">
<Button x:Name="PART_CancelButton" Grid.Row="2" Style="{StaticResource VMessageBox_Button_Cancel}" Content="取消" Visibility="Hidden"></Button>
<Button x:Name="PART_YesButton" Grid.Row="2" Style="{StaticResource VMessageBox_Button_Yes}" Content="确定"></Button>
</StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Buttons" Value="YES_CANCEL">
<Setter TargetName="PART_CancelButton" Property="Visibility" Value="Visible"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
\ No newline at end of file
<Window x:Class="VIZ.GimbalAI.Common.VMessageBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VIZ.GimbalAI.Common"
mc:Ignorable="d" WindowStartupLocation="CenterScreen" WindowState="Normal" WindowStyle="None" AllowsTransparency="True"
Title="VMessageBoxWindow" Height="400" Width="600" Background="Transparent">
<local:VMessageBox x:Name="box" Width="580" Height="380"></local:VMessageBox>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// VMessageBoxWindow.xaml 的交互逻辑
/// </summary>
public partial class VMessageBoxWindow : Window
{
public VMessageBoxWindow()
{
InitializeComponent();
}
}
}
using System;
namespace VIZ.GimbalAI.Common
{
public static class Disposer
{
public static void SafeDispose<T>(ref T resource) where T : class
{
if (resource == null)
{
return;
}
var disposer = resource as IDisposable;
if (disposer != null)
{
try
{
disposer.Dispose();
}
catch
{
}
}
resource = null;
}
}
}
using System;
using System.Runtime.InteropServices;
namespace VIZ.GimbalAI.Common
{
public static class NativeMethods
{
[DllImport("user32.dll", SetLastError = false)]
public static extern IntPtr GetDesktopWindow();
}
}
using SharpDX.Direct2D1;
using System;
using System.Collections.Generic;
namespace VIZ.GimbalAI.Common
{
public class ResourceCache
{
// - field -----------------------------------------------------------------------
private Dictionary<string, Func<RenderTarget, object>> generators = new Dictionary<string, Func<RenderTarget, object>>();
private Dictionary<string, object> resources = new Dictionary<string, object>();
private RenderTarget renderTarget = null;
// - property --------------------------------------------------------------------
public RenderTarget RenderTarget
{
get { return renderTarget; }
set { renderTarget = value; UpdateResources(); }
}
public int Count
{
get { return resources.Count; }
}
public object this[string key]
{
get { return resources[key]; }
}
public Dictionary<string, object>.KeyCollection Keys
{
get { return resources.Keys; }
}
public Dictionary<string, object>.ValueCollection Values
{
get { return resources.Values; }
}
// - public methods --------------------------------------------------------------
public void Add(string key, Func<RenderTarget, object> gen)
{
object resOld;
if (resources.TryGetValue(key, out resOld))
{
Disposer.SafeDispose(ref resOld);
generators.Remove(key);
resources.Remove(key);
}
if (renderTarget == null)
{
generators.Add(key, gen);
resources.Add(key, null);
}
else
{
var res = gen(renderTarget);
generators.Add(key, gen);
resources.Add(key, res);
}
}
public void Clear()
{
foreach (var key in resources.Keys)
{
var res = resources[key];
Disposer.SafeDispose(ref res);
}
generators.Clear();
resources.Clear();
}
public bool ContainsKey(string key)
{
return resources.ContainsKey(key);
}
public bool ContainsValue(object val)
{
return resources.ContainsValue(val);
}
public Dictionary<string, object>.Enumerator GetEnumerator()
{
return resources.GetEnumerator();
}
public bool Remove(string key)
{
object res;
if (resources.TryGetValue(key, out res))
{
Disposer.SafeDispose(ref res);
generators.Remove(key);
resources.Remove(key);
return true;
}
else
{
return false;
}
}
public bool TryGetValue(string key, out object res)
{
return resources.TryGetValue(key, out res);
}
// - private methods -------------------------------------------------------------
private void UpdateResources()
{
if (renderTarget == null) { return; }
foreach (var g in generators)
{
var key = g.Key;
var gen = g.Value;
var res = gen(renderTarget);
object resOld;
if (resources.TryGetValue(key, out resOld))
{
Disposer.SafeDispose(ref resOld);
resources.Remove(key);
}
resources.Add(key, res);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX.Mathematics.Interop;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// SharpDX颜色辅助类
/// </summary>
public static class SharpDxColorHelper
{
/// <summary>
/// 由RGBG值获取颜色
/// </summary>
/// <param name="r">红色值</param>
/// <param name="g">绿色值</param>
/// <param name="b">蓝色值</param>
/// <param name="a">透明度</param>
/// <returns>颜色</returns>
public static RawColor4 FromRGBA(float r, float g, float b, float a)
{
return new RawColor4(r, g, b, a);
}
/// <summary>
/// 由RGBG值获取颜色
/// </summary>
/// <param name="r">红色值</param>
/// <param name="g">绿色值</param>
/// <param name="b">蓝色值</param>
/// <param name="a">透明度</param>
/// <returns>颜色</returns>
public static RawColor4 FromRGBA(double r, double g, double b, double a)
{
return new RawColor4((float)r, (float)g, (float)b, (float)a);
}
/// <summary>
/// 由RGBG值获取颜色
/// </summary>
/// <param name="code">颜色码(#AARRGGBB),例如:#FFFF0000</param>
/// <returns>颜色</returns>
public static RawColor4 FromString(string code)
{
RawColor4 result = new RawColor4();
result.A = Convert.ToInt32(code.Substring(1, 2), 16) / 255f;
result.R = Convert.ToInt32(code.Substring(3, 2), 16) / 255f;
result.G = Convert.ToInt32(code.Substring(5, 2), 16) / 255f;
result.B = Convert.ToInt32(code.Substring(7, 2), 16) / 255f;
return result;
}
}
}
using SharpDX.Direct2D1;
using SharpDX.WIC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// WIC图片辅助类默认实现
/// </summary>
public class WicBitmapDefaultHelper : WicBitmapHelper
{
/// <summary>
/// WIC图片辅助类默认实现
/// </summary>
/// <param name="renderCallBack">渲染回调</param>
public WicBitmapDefaultHelper(Action<WicRenderTarget> renderCallBack)
{
this.RenderCallBack = renderCallBack;
}
/// <summary>
/// 渲染回调
/// </summary>
private Action<WicRenderTarget> RenderCallBack;
/// <summary>
/// 执行渲染
/// </summary>
/// <param name="renderTarget">渲染目标</param>
protected override void ExecuteeRender(WicRenderTarget renderTarget)
{
this.RenderCallBack?.Invoke(renderTarget);
}
/// <summary>
/// 获取保存图片格式
/// </summary>
/// <param name="factory">图片工厂</param>
protected override BitmapEncoder GetBitmapFrameEncoder(ImagingFactory factory)
{
return new JpegBitmapEncoder(factory);
}
}
}
using SharpDX.WIC;
using SharpDX.Direct2D1;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using System.IO;
using SharpDX.IO;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// WIC图片辅助类
/// </summary>
public abstract class WicBitmapHelper
{
/// <summary>
/// 渲染至文件
/// </summary>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="filename">文件名</param>
/// <param name="executeRender">执行渲染</param>
public void RenderToFile(int width, int height, string filename)
{
ImagingFactory wicFactory = new ImagingFactory();
SharpDX.Direct2D1.Factory d2dFactory = new SharpDX.Direct2D1.Factory();
SharpDX.WIC.Bitmap wicBitmap = new SharpDX.WIC.Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);
RenderTargetProperties renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new SharpDX.Direct2D1.PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);
WicRenderTarget d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);
d2dRenderTarget.BeginDraw();
this.ExecuteeRender(d2dRenderTarget);
d2dRenderTarget.EndDraw();
if (File.Exists(filename))
File.Delete(filename);
WICStream stream = new WICStream(wicFactory, filename, NativeFileAccess.Write);
// Initialize a Jpeg encoder with this stream
BitmapEncoder encoder = this.GetBitmapFrameEncoder(wicFactory);
encoder.Initialize(stream);
// Create a Frame encoder
BitmapFrameEncode bitmapFrameEncode = new BitmapFrameEncode(encoder);
bitmapFrameEncode.Initialize();
bitmapFrameEncode.SetSize(width, height);
var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare;
bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid);
bitmapFrameEncode.WriteSource(wicBitmap);
bitmapFrameEncode.Commit();
encoder.Commit();
bitmapFrameEncode.Dispose();
encoder.Dispose();
stream.Dispose();
d2dRenderTarget.Dispose();
wicBitmap.Dispose();
d2dFactory.Dispose();
wicFactory.Dispose();
}
/// <summary>
/// 执行渲染
/// </summary>
/// <param name="renderTarget">渲染目标</param>
protected abstract void ExecuteeRender(WicRenderTarget renderTarget);
/// <summary>
/// 获取保存图片格式
/// </summary>
/// <param name="factory">图片工厂</param>
/// <returns>图片格式</returns>
protected abstract BitmapEncoder GetBitmapFrameEncoder(ImagingFactory factory);
}
}
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
namespace VIZ.GimbalAI.Common
{
public abstract class D2dControl : System.Windows.Controls.Image
{
// - field -----------------------------------------------------------------------
private SharpDX.Direct3D11.Device device;
private Texture2D renderTarget;
private Dx11ImageSource d3DSurface;
private RenderTarget d2DRenderTarget;
private SharpDX.Direct2D1.Factory d2DFactory;
private readonly Stopwatch renderTimer = new Stopwatch();
protected ResourceCache resCache = new ResourceCache();
private long lastFrameTime = 0;
private long lastRenderTime = 0;
private int frameCount = 0;
private int frameCountHistTotal = 0;
private Queue<int> frameCountHist = new Queue<int>();
// - property --------------------------------------------------------------------
public static bool IsInDesignMode
{
get
{
var prop = DesignerProperties.IsInDesignModeProperty;
var isDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue;
return isDesignMode;
}
}
private static readonly DependencyPropertyKey FpsPropertyKey = DependencyProperty.RegisterReadOnly(
"Fps",
typeof(int),
typeof(D2dControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.None)
);
public static readonly DependencyProperty FpsProperty = FpsPropertyKey.DependencyProperty;
public int Fps
{
get { return (int)GetValue(FpsProperty); }
protected set { SetValue(FpsPropertyKey, value); }
}
public static DependencyProperty RenderWaitProperty = DependencyProperty.Register(
"RenderWait",
typeof(int),
typeof(D2dControl),
new FrameworkPropertyMetadata(2, OnRenderWaitChanged)
);
public int RenderWait
{
get { return (int)GetValue(RenderWaitProperty); }
set { SetValue(RenderWaitProperty, value); }
}
// - public methods --------------------------------------------------------------
public D2dControl()
{
base.Loaded += Window_Loaded;
base.Unloaded += Window_Closing;
base.Stretch = System.Windows.Media.Stretch.Fill;
}
public abstract void Render(RenderTarget target);
// - event handler ---------------------------------------------------------------
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (D2dControl.IsInDesignMode)
{
return;
}
StartD3D();
StartRendering();
}
private void Window_Closing(object sender, RoutedEventArgs e)
{
if (D2dControl.IsInDesignMode)
{
return;
}
StopRendering();
EndD3D();
}
private void OnRendering(object sender, EventArgs e)
{
if (!renderTimer.IsRunning)
{
return;
}
PrepareAndCallRender();
d3DSurface.InvalidateD3DImage();
lastRenderTime = renderTimer.ElapsedMilliseconds;
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
CreateAndBindTargets();
base.OnRenderSizeChanged(sizeInfo);
}
private void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (d3DSurface.IsFrontBufferAvailable)
{
StartRendering();
this.CreateAndBindTargets();
}
else
{
StopRendering();
}
}
private static void OnRenderWaitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (D2dControl)d;
control.d3DSurface.RenderWait = (int)e.NewValue;
}
// - private methods -------------------------------------------------------------
private void StartD3D()
{
device = new SharpDX.Direct3D11.Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport);
d3DSurface = new Dx11ImageSource();
d3DSurface.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged;
CreateAndBindTargets();
base.Source = d3DSurface;
}
private void EndD3D()
{
d3DSurface.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged;
base.Source = null;
Disposer.SafeDispose(ref d2DRenderTarget);
Disposer.SafeDispose(ref d2DFactory);
Disposer.SafeDispose(ref d3DSurface);
Disposer.SafeDispose(ref renderTarget);
Disposer.SafeDispose(ref device);
}
private void CreateAndBindTargets()
{
if (d3DSurface == null)
{
return;
}
d3DSurface.SetRenderTarget(null);
Disposer.SafeDispose(ref d2DRenderTarget);
Disposer.SafeDispose(ref d2DFactory);
Disposer.SafeDispose(ref renderTarget);
var width = Math.Max((int)ActualWidth, 100);
var height = Math.Max((int)ActualHeight, 100);
var renderDesc = new Texture2DDescription
{
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
Format = Format.B8G8R8A8_UNorm,
Width = width,
Height = height,
MipLevels = 1,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
OptionFlags = ResourceOptionFlags.Shared,
CpuAccessFlags = CpuAccessFlags.None,
ArraySize = 1
};
renderTarget = new Texture2D(device, renderDesc);
var surface = renderTarget.QueryInterface<Surface>();
d2DFactory = new SharpDX.Direct2D1.Factory();
var rtp = new RenderTargetProperties(new PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Premultiplied));
d2DRenderTarget = new RenderTarget(d2DFactory, surface, rtp);
resCache.RenderTarget = d2DRenderTarget;
d3DSurface.SetRenderTarget(renderTarget);
device.ImmediateContext.Rasterizer.SetViewport(0, 0, width, height, 0.0f, 1.0f);
}
private void StartRendering()
{
if (renderTimer.IsRunning)
{
return;
}
System.Windows.Media.CompositionTarget.Rendering -= OnRendering;
System.Windows.Media.CompositionTarget.Rendering += OnRendering;
renderTimer.Start();
}
private void StopRendering()
{
if (!renderTimer.IsRunning)
{
return;
}
System.Windows.Media.CompositionTarget.Rendering -= OnRendering;
renderTimer.Stop();
}
private void PrepareAndCallRender()
{
if (device == null)
{
return;
}
d2DRenderTarget.BeginDraw();
Render(d2DRenderTarget);
d2DRenderTarget.EndDraw();
CalcFps();
device.ImmediateContext.Flush();
}
private void CalcFps()
{
frameCount++;
if (renderTimer.ElapsedMilliseconds - lastFrameTime > 1000)
{
frameCountHist.Enqueue(frameCount);
frameCountHistTotal += frameCount;
if (frameCountHist.Count > 5)
{
frameCountHistTotal -= frameCountHist.Dequeue();
}
Fps = frameCountHistTotal / frameCountHist.Count;
frameCount = 0;
lastFrameTime = renderTimer.ElapsedMilliseconds;
}
}
}
}
using SharpDX.Direct3D9;
using System;
using System.Threading;
using System.Windows.Interop;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Storage;
namespace VIZ.GimbalAI.Common
{
public class Dx11ImageSource : D3DImage, IDisposable
{
// - field -----------------------------------------------------------------------
private static int ActiveClients;
private static Direct3DEx D3DContext;
private static DeviceEx D3DDevice;
private Texture renderTarget;
// - property --------------------------------------------------------------------
public int RenderWait { get; set; } = 20; // default: 2ms
// - public methods --------------------------------------------------------------
public Dx11ImageSource()
{
this.RenderWait = VDataDomain.IniStorage.GetValue<ClientConfig, int>(p => p.CLIENT_VIDEO_RENDER_WAIT);
StartD3D();
Dx11ImageSource.ActiveClients++;
}
public void Dispose()
{
SetRenderTarget(null);
Disposer.SafeDispose(ref renderTarget);
Dx11ImageSource.ActiveClients--;
EndD3D();
}
public void InvalidateD3DImage()
{
if (renderTarget != null)
{
base.Lock();
if (RenderWait != 0)
{
Thread.Sleep(RenderWait);
}
base.AddDirtyRect(new System.Windows.Int32Rect(0, 0, base.PixelWidth, base.PixelHeight));
base.Unlock();
}
}
public void SetRenderTarget(SharpDX.Direct3D11.Texture2D target)
{
if (renderTarget != null)
{
renderTarget = null;
base.Lock();
base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero);
base.Unlock();
}
if (target == null)
{
return;
}
var format = Dx11ImageSource.TranslateFormat(target);
var handle = GetSharedHandle(target);
if (!IsShareable(target))
{
throw new ArgumentException("Texture must be created with ResouceOptionFlags.Shared");
}
if (format == Format.Unknown)
{
throw new ArgumentException("Texture format is not compatible with OpenSharedResouce");
}
if (handle == IntPtr.Zero)
{
throw new ArgumentException("Invalid handle");
}
renderTarget = new Texture(Dx11ImageSource.D3DDevice, target.Description.Width, target.Description.Height, 1, Usage.RenderTarget, format, Pool.Default, ref handle);
using (var surface = renderTarget.GetSurfaceLevel(0))
{
base.Lock();
base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface.NativePointer);
base.Unlock();
}
}
// - private methods -------------------------------------------------------------
private void StartD3D()
{
if (Dx11ImageSource.ActiveClients != 0)
{
return;
}
var presentParams = GetPresentParameters();
var createFlags = CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve;
Dx11ImageSource.D3DContext = new Direct3DEx();
Dx11ImageSource.D3DDevice = new DeviceEx(D3DContext, 0, DeviceType.Hardware, IntPtr.Zero, createFlags, presentParams);
}
private void EndD3D()
{
if (Dx11ImageSource.ActiveClients != 0)
{
return;
}
Disposer.SafeDispose(ref renderTarget);
Disposer.SafeDispose(ref Dx11ImageSource.D3DDevice);
Disposer.SafeDispose(ref Dx11ImageSource.D3DContext);
}
private static void ResetD3D()
{
if (Dx11ImageSource.ActiveClients == 0)
{
return;
}
var presentParams = GetPresentParameters();
Dx11ImageSource.D3DDevice.ResetEx(ref presentParams);
}
private static PresentParameters GetPresentParameters()
{
var presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.DeviceWindowHandle = NativeMethods.GetDesktopWindow();
presentParams.PresentationInterval = PresentInterval.Default;
return presentParams;
}
private IntPtr GetSharedHandle(SharpDX.Direct3D11.Texture2D texture)
{
using (var resource = texture.QueryInterface<SharpDX.DXGI.Resource>())
{
return resource.SharedHandle;
}
}
private static Format TranslateFormat(SharpDX.Direct3D11.Texture2D texture)
{
switch (texture.Description.Format)
{
case SharpDX.DXGI.Format.R10G10B10A2_UNorm: return SharpDX.Direct3D9.Format.A2B10G10R10;
case SharpDX.DXGI.Format.R16G16B16A16_Float: return SharpDX.Direct3D9.Format.A16B16G16R16F;
case SharpDX.DXGI.Format.B8G8R8A8_UNorm: return SharpDX.Direct3D9.Format.A8R8G8B8;
default: return SharpDX.Direct3D9.Format.Unknown;
}
}
private static bool IsShareable(SharpDX.Direct3D11.Texture2D texture)
{
return (texture.Description.OptionFlags & SharpDX.Direct3D11.ResourceOptionFlags.Shared) != 0;
}
}
}
......@@ -4,7 +4,7 @@
xmlns:local="clr-namespace:VIZ.GimbalAI.Common">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/VIZ.GimbalAI.Common;component/MessageBox/VMessageBox.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
......@@ -132,30 +132,12 @@
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<Page Include="MessageBox\VMessageBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MessageBox\VMessageBoxWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Generic.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="VideoControl\Control\VideoControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="MessageBox\VMessageBox.cs" />
<Compile Include="MessageBox\VMessageBoxButtons.cs" />
<Compile Include="MessageBox\VMessageBoxResult.cs" />
<Compile Include="MessageBox\VMessageBoxWindow.xaml.cs">
<DependentUpon>VMessageBoxWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
......@@ -169,40 +151,6 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="SharpDx\Core\SharpDxColorHelper.cs" />
<Compile Include="SharpDx\WIC\WicBitmapHelper.cs" />
<Compile Include="SharpDx\WIC\WicBitmapDefaultHelper.cs" />
<Compile Include="SharpDx\WPF\D2dControl.cs" />
<Compile Include="SharpDx\Core\Disposer.cs" />
<Compile Include="SharpDx\WPF\Dx11ImageSource.cs" />
<Compile Include="SharpDx\Core\NativeMethods.cs" />
<Compile Include="SharpDx\Core\ResourceCache.cs" />
<Compile Include="VideoControl\Control\Drawing\VideoRectangle.cs" />
<Compile Include="VideoControl\Control\Drawing\VideoRectangleColor.cs" />
<Compile Include="VideoControl\Control\Drawing\VideoRectangleExpand.cs" />
<Compile Include="VideoControl\Control\EventArgs\VideoRectangleFrameSelectionEventArgs.cs" />
<Compile Include="VideoControl\Control\EventArgs\VideoRectangleClickEventArgs.cs" />
<Compile Include="VideoControl\Control\IVideoRender.cs" />
<Compile Include="VideoControl\Control\VideoControl.xaml.cs">
<DependentUpon>VideoControl.xaml</DependentUpon>
</Compile>
<Compile Include="VideoControl\Control\VideoCustomRender.cs" />
<Compile Include="VideoControl\Control\VideoRenderInfo.cs" />
<Compile Include="VideoControl\Stream\IVideoFrame.cs" />
<Compile Include="VideoControl\Stream\NDI\NDIToolOption.cs" />
<Compile Include="VideoControl\Stream\NDI\NDIToolStreamInfo.cs" />
<Compile Include="VideoControl\Stream\NDI\NDITool.cs" />
<Compile Include="VideoControl\Stream\NDI\NDITool.Static.cs" />
<Compile Include="VideoControl\Stream\NDI\NDIToolTaskBase.cs" />
<Compile Include="VideoControl\Stream\NDI\NDIToolTaskNames.cs" />
<Compile Include="VideoControl\Stream\NDI\NDIToolVideoFrame.cs" />
<Compile Include="VideoControl\Stream\VideoStreamManager.cs" />
<Compile Include="VideoControl\Stream\VideoFrameEventArgs.cs" />
<Compile Include="VideoControl\Stream\NDI\Task\NDIToolExecuteVideoTask.cs" />
<Compile Include="VideoControl\Stream\NDI\Task\NDIToolRecvVideoTask.cs" />
<Compile Include="VideoControl\Stream\NDI\Task\NDIToolFindStreamTask.cs" />
<Compile Include="Widgets\DragWindowBar\DragWindowBar.cs" />
<Compile Include="Widgets\NoneWindow\NoneWindow.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
......@@ -215,10 +163,6 @@
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VIZ.GimbalAI.Core\VIZ.GimbalAI.Core.csproj">
<Project>{d4409326-3f36-4835-812a-bea8ed046e04}</Project>
<Name>VIZ.GimbalAI.Core</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Domain\VIZ.GimbalAI.Domain.csproj">
<Project>{BBF80159-D5DE-4D82-A045-A96D67D80632}</Project>
<Name>VIZ.GimbalAI.Domain</Name>
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频矩形
/// </summary>
public class VideoRectangle
{
/// <summary>
/// 算法给出的矩形框ID
/// </summary>
public int AlgorithmID { get; set; }
/// <summary>
/// 算法给出的框定位信息
/// </summary>
public List<float> AlgorithmRoi { get; set; } = new List<float>();
/// <summary>
/// 颜色
/// </summary>
public VideoRectangleColor Color { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频框颜色
/// </summary>
public enum VideoRectangleColor
{
/// <summary>
/// 红色
/// </summary>
Red,
/// <summary>
/// 蓝色
/// </summary>
Blue,
/// <summary>
/// 绿色
/// </summary>
Green
}
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频矩形扩展
/// </summary>
public static class VideoRectangleExpand
{
/// <summary>
/// 将算法给定的坐标信息转化为Rectangle
/// </summary>
/// <param name="info">视频矩形信息</param>
/// <returns></returns>
public static RectangleF? ConvertAlgorithmRoiToRectangle(this VideoRectangle info)
{
if (info == null || info.AlgorithmRoi == null || info.AlgorithmRoi.Count != 4)
return null;
return new RectangleF(info.AlgorithmRoi[0], info.AlgorithmRoi[1], info.AlgorithmRoi[2], info.AlgorithmRoi[3]);
}
/// <summary>
/// 命中测试
/// </summary>
/// <param name="rectangles">矩形信息</param>
/// <param name="point">视频坐标</param>
/// <returns>命中的矩形</returns>
public static List<VideoRectangle> HitTest(List<VideoRectangle> rectangles, System.Windows.Point point)
{
List<VideoRectangle> result = new List<VideoRectangle>();
if (rectangles == null || rectangles.Count == 0)
return result;
foreach (VideoRectangle item in rectangles)
{
RectangleF? rect = item.ConvertAlgorithmRoiToRectangle();
if (rect == null)
continue;
if (point.X >= rect.Value.Left && point.X <= rect.Value.Right && point.Y >= rect.Value.Top && point.Y <= rect.Value.Bottom)
{
result.Add(item);
}
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频矩形信息点击事件参数s
/// </summary>
public class VideoRectangleClickEventArgs : EventArgs
{
/// <summary>
/// 鼠标点击位置
/// </summary>
public Point MousePosition { get; set; }
/// <summary>
/// 视频坐标
/// </summary>
public Point VideoPosition { get; set; }
/// <summary>
/// 当前渲染的视频矩形框
/// </summary>
public List<VideoRectangle> VideoRectangles { get; set; }
/// <summary>
/// 命中测试的视频矩形框
/// </summary>
public List<VideoRectangle> HitTestVideoRectangles { get; set; }
}
}
using ManageLiteAV;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频渲染
/// </summary>
public interface IVideoRender
{
/// <summary>
/// 是否启用绘制矩形框
/// </summary>
bool IsRenderRectangleEnabled { get; set; }
/// <summary>
/// 是否启用绘制框选区域
/// </summary>
bool IsRenderFrameSelectionEnabled { get; set; }
/// <summary>
/// 渲染
/// </summary>
void RenderVideo(IVideoFrame videoFrame);
/// <summary>
/// 渲染矩形框信息
/// </summary>
/// <param name="rectangles">矩形框</param>
void RenderRectangleInfo(List<VideoRectangle> rectangles);
/// <summary>
/// 渲染视频矩形区域框选
/// </summary>
/// <param name="uiRect">UI框选区域</param>
void RenderFrameSelection(RectangleF? uiRect);
/// <summary>
/// 将渲染内容保存为图片
/// ----------------------------------------------------
/// 1. 只保存视频帧 & 渲染框
/// 2. 图片保存为jpg数据
/// ----------------------------------------------------
/// </summary>
/// <param name="path">图片路径</param>
void SaveFrameImage(string path);
/// <summary>
/// 获取帧图片
/// </summary>
/// <returns>图片</returns>
Bitmap GetFrameImage();
}
}
<UserControl x:Class="VIZ.GimbalAI.Common.VideoControl"
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"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:common="clr-namespace:VIZ.GimbalAI.Common"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core"
mc:Ignorable="d" x:Name="uc"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<converter:Bool2VisibilityConverter x:Key="Bool2VisibilityConverter"></converter:Bool2VisibilityConverter>
</UserControl.Resources>
<Grid>
<common:VideoCustomRender x:Name="videoRender"></common:VideoCustomRender>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,0,0" IsHitTestVisible="False"
Visibility="{Binding Path=IsShowFPS,ElementName=uc,Converter={StaticResource Bool2VisibilityConverter}}">
<TextBlock Text="FPS:" Foreground="Red" FontSize="24"></TextBlock>
<TextBlock Text="{Binding ElementName=videoRender,Path=Fps}" Foreground="Red" FontSize="24" Margin="10,0,0,0"></TextBlock>
</StackPanel>
</Grid>
</UserControl>
using ManageLiteAV;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VIZ.GimbalAI.Core;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// VideoControl.xaml 的交互逻辑
/// </summary>
public partial class VideoControl : UserControl
{
public VideoControl()
{
InitializeComponent();
this.videoRender.OwnerVideoControl = this;
}
/// <summary>
/// 视频矩形框被选中时触发
/// </summary>
public event EventHandler<VideoRectangleClickEventArgs> VideoRectangleClick;
/// <summary>
/// 视频矩形框被框选时触发
/// </summary>
public event EventHandler<VideoRectangleFrameSelectionEventArgs> VideoRectangleFrameSelection;
// ===========================================================================================================
// === Property ===
// ===========================================================================================================
#region IsRenderRectangleEnabled -- 是否启用渲染矩形
/// <summary>
/// 是否启用渲染矩形
/// </summary>
public bool IsRenderRectangleEnabled
{
get { return (bool)GetValue(IsRenderRectangleEnabledProperty); }
set { SetValue(IsRenderRectangleEnabledProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for IsRenderRectangleEnabled. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty IsRenderRectangleEnabledProperty =
DependencyProperty.Register("IsRenderRectangleEnabled", typeof(bool), typeof(VideoControl), new PropertyMetadata(true, new PropertyChangedCallback((s, e) =>
{
IVideoRender render = (s as VideoControl).videoRender;
if (render == null)
return;
render.IsRenderRectangleEnabled = (bool)e.NewValue;
})));
#endregion
#region IsRenderFrameSelectionEnabled -- 是否渲染框选区域
/// <summary>
/// 是否渲染框选区域
/// </summary>
public bool IsRenderFrameSelectionEnabled
{
get { return (bool)GetValue(IsRenderFrameSelectionEnabledProperty); }
set { SetValue(IsRenderFrameSelectionEnabledProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for IsRenderFrameSelectionEnabled. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty IsRenderFrameSelectionEnabledProperty =
DependencyProperty.Register("IsRenderFrameSelectionEnabled", typeof(bool), typeof(VideoControl), new PropertyMetadata(false, new PropertyChangedCallback((s, e) =>
{
IVideoRender render = (s as VideoControl)?.videoRender;
if (render == null)
return;
render.IsRenderFrameSelectionEnabled = (bool)e.NewValue;
})));
#endregion
#region IsRectangleClickTrigger -- 是否触发鼠标点击事件
/// <summary>
/// 是否触发鼠标点击事件
/// </summary>
public bool IsRectangleClickTrigger
{
get { return (bool)GetValue(IsRectangleClickTriggerProperty); }
set { SetValue(IsRectangleClickTriggerProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for IsRectangleClickTrigger. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty IsRectangleClickTriggerProperty =
DependencyProperty.Register("IsRectangleClickTrigger", typeof(bool), typeof(VideoControl), new PropertyMetadata(true));
#endregion
#region IsRectangleFrameSelectionTrigger -- 是否触发框选
/// <summary>
/// 是否触发框选
/// </summary>
public bool IsRectangleFrameSelectionTrigger
{
get { return (bool)GetValue(IsRectangleFrameSelectionTriggerProperty); }
set { SetValue(IsRectangleFrameSelectionTriggerProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for IsRectangleFrameSelectionTrigger. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty IsRectangleFrameSelectionTriggerProperty =
DependencyProperty.Register("IsRectangleFrameSelectionTrigger", typeof(bool), typeof(VideoControl), new PropertyMetadata(false));
#endregion
#region IsShowFPS -- 是否显示FPS
/// <summary>
/// 是否显示FPS
/// </summary>
public bool IsShowFPS
{
get { return (bool)GetValue(IsShowFPSProperty); }
set { SetValue(IsShowFPSProperty, value); }
}
/// <summary>
/// Using a DependencyProperty as the backing store for IsShowFPS. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty IsShowFPSProperty =
DependencyProperty.Register("IsShowFPS", typeof(bool), typeof(VideoControl), new PropertyMetadata(false));
#endregion
// ===========================================================================================================
// === Public Function ===
// ===========================================================================================================
/// <summary>
/// 渲染
/// </summary>
public void RenderVideo(IVideoFrame videoFrame)
{
this.videoRender?.RenderVideo(videoFrame);
}
/// <summary>
/// 渲染矩形框信息
/// </summary>
/// <param name="rectangles">矩形框</param>
public void RenderRectangleInfo(List<VideoRectangle> rectangles)
{
this.videoRender?.RenderRectangleInfo(rectangles);
}
/// <summary>
/// 清理矩形框信息
/// </summary>
public void ClearRectangleInfo()
{
this.videoRender?.RenderRectangleInfo(null);
}
/// <summary>
/// 清理框选区域
/// </summary>
public void ClearFrameSelection()
{
this.videoRender.RenderFrameSelection(null);
}
/// <summary>
/// 保存图片
/// </summary>
/// <param name="path">图片路径</param>
public void SaveFrameImage(string path)
{
this.videoRender.SaveFrameImage(path);
}
/// <summary>
/// 获取帧图片
/// </summary>
/// <returns>图片</returns>
public Bitmap GetFrameImage()
{
return this.videoRender.GetFrameImage();
}
// ===========================================================================================================
/// <summary>
/// 执行视频矩形框点击事件
/// </summary>
/// <param name="args">视频矩形框被选中事件参数</param>
internal void ExecuteVideoRectangleClick(VideoRectangleClickEventArgs args)
{
if (!this.IsRectangleClickTrigger)
return;
this.VideoRectangleClick?.Invoke(this, args);
}
/// <summary>
/// 执行视频矩形框选事件
/// </summary>
/// <param name="args">视频矩形框框选事件参数</param>
internal void ExecuteVideoRectangleFrameSelection(VideoRectangleFrameSelectionEventArgs args)
{
if (!this.IsRectangleFrameSelectionTrigger)
return;
// 宽度或高度为0的矩形框为无效数据
if (args.VideoRectangle.Width == 0 || args.VideoRectangle.Height == 0)
{
this.ClearFrameSelection();
return;
}
this.VideoRectangleFrameSelection?.Invoke(this, args);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using SharpDX;
using SharpDX.Direct2D1;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频渲染信息
/// </summary>
public class VideoRenderInfo : IDisposable
{
/// <summary>
/// 图片数据
/// </summary>
public DataStream DataStream { get; set; }
/// <summary>
/// 视频帧信息
/// </summary>
public IVideoFrame Frame { get; set; }
/// <summary>
/// 渲染图片宽度
/// </summary>
public int BitmapWidth { get; set; }
/// <summary>
/// 渲染图片高度
/// </summary>
public int BitmapHeight { get; set; }
/// <summary>
/// 渲染区域
/// </summary>
public System.Drawing.RectangleF Rectangle { get; set; }
/// <summary>
/// 该对象是否已经被销毁
/// </summary>
private bool IsDisopsed { get; set; }
/// <summary>
/// 销毁
/// </summary>
public void Dispose()
{
if (this.IsDisopsed)
return;
this.IsDisopsed = true;
this.DataStream?.Dispose();
this.DataStream = null;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using SharpDX.Direct2D1;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频帧
/// </summary>
public interface IVideoFrame
{
/// <summary>
/// 宽度
/// </summary>
int Width { get; set; }
/// <summary>
/// 高度
/// </summary>
int Height { get; set; }
/// <summary>
/// 数据长度
/// </summary>
int Length { get; set; }
/// <summary>
/// 时间粗
/// </summary>
long TimeStamp { get; set; }
/// <summary>
/// 画面数据
/// </summary>
DataStream DataStream { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NewTek;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// NDI工具 静态部分
/// </summary>
public partial class NDITool
{
/// <summary>
/// 是否完成了初始化
/// </summary>
public static bool IsInited { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <returns>是否初始化成功</returns>
public static bool Init()
{
if (!NDIlib.initialize())
return false;
IsInited = true;
return true;
}
public static void Destroy()
{
if (!IsInited)
return;
NDIlib.destroy();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NewTek;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// NDI流信息
/// </summary>
public class NDIToolStreamInfo
{
/// <summary>
/// 机器
/// </summary>
public string Machine { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 完整名称
/// </summary>
public string FullName { get; set; }
/// <summary>
/// NDI流信息
/// </summary>
public NDIlib.source_t Source { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// NDI工具任务
/// </summary>
public abstract class NDIToolTaskBase : IDisposable
{
/// <summary>
/// 任务名称
/// </summary>
public abstract NDIToolTaskNames Name { get; }
/// <summary>
/// NDI工具
/// </summary>
public NDITool Tool { get; private set; }
/// <summary>
/// 是否开启
/// </summary>
public bool IsStarted { get; set; }
/// <summary>
/// 任务线程
/// </summary>
private Thread Thread;
/// <summary>
/// 开始
/// </summary>
public void Start(NDITool tool)
{
if (this.IsStarted)
throw new Exception("task is already started.");
this.Tool = tool;
this.IsStarted = true;
this.Thread = new Thread(this.Execute);
this.Thread.IsBackground = true;
this.Thread.Start();
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
this.IsStarted = false;
this.Thread = null;
}
/// <summary>
/// 销毁
/// </summary>
public void Dispose()
{
this.Stop();
}
/// <summary>
/// 执行
/// </summary>
protected abstract void Execute();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// NDI工具任务名称
/// </summary>
public enum NDIToolTaskNames
{
/// <summary>
/// 查找NDI流
/// </summary>
FIND_STREAM,
/// <summary>
/// 接收视频
/// </summary>
RECV_VIDEO,
/// <summary>
/// 处理视频帧
/// </summary>
EXECUTE_VIDEO
}
}
using NewTek;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using SharpDX.Direct2D1;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// NDI视频帧
/// </summary>
public class NDIToolVideoFrame : IVideoFrame
{
/// <summary>
/// 宽度
/// </summary>
public int Width { get; set; }
/// <summary>
/// 高度
/// </summary>
public int Height { get; set; }
/// <summary>
/// 数据长度
/// </summary>
public int Length { get; set; }
/// <summary>
/// 时间粗
/// </summary>
public long TimeStamp { get; set; }
/// <summary>
/// 画面数据
/// </summary>
public DataStream DataStream { get; set; }
}
}
using NewTek;
using NewTek.NDI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 查找NDI流任务
/// </summary>
public class NDIToolFindStreamTask : NDIToolTaskBase
{
/// <summary>
/// 任务名称
/// </summary>
public override NDIToolTaskNames Name => NDIToolTaskNames.FIND_STREAM;
/// <summary>
/// the size of an NDIlib.source_t, for pointer offsets
/// </summary>
private readonly int SOURCE_SIZE_IN_BYTES = Marshal.SizeOf(typeof(NDIlib.source_t));
/// <summary>
/// 执行
/// </summary>
protected override void Execute()
{
while (this.IsStarted)
{
this._Execute();
}
}
/// <summary>
/// 执行
/// </summary>
private void _Execute()
{
if (!NDIlib.find_wait_for_sources(this.Tool.FindInstancePtr, 500))
return;
lock (this.Tool.StreamInfos)
{
this.Tool.StreamInfos.Clear();
}
uint numSources = 0;
IntPtr sourcesPtr = NDIlib.find_get_current_sources(this.Tool.FindInstancePtr, ref numSources);
for (int i = 0; i < numSources; i++)
{
// 连续的数据结构
IntPtr p = IntPtr.Add(sourcesPtr, (i * SOURCE_SIZE_IN_BYTES));
// 指针转化为 NDIlib.source_t 数据结构
NDIlib.source_t src = (NDIlib.source_t)Marshal.PtrToStructure(p, typeof(NDIlib.source_t));
// NDI流名称
string ndiName = UTF.Utf8ToString(src.p_ndi_name);
// 添加NDI流信息
NDIToolStreamInfo info = new NDIToolStreamInfo();
info.FullName = ndiName;
info.Machine = ndiName.Split(new char[] { ' ' }, 2)[0];
info.Name = ndiName.Substring(ndiName.IndexOf(' ') + 1);
info.Source = src;
lock (this.Tool.StreamInfos)
{
this.Tool.StreamInfos.Add(info);
}
}
// 如果当前没有正在处理的流信息那么切换为当前RemoteSenderName指定的流信息
if (this.Tool.CurrentRemoteSenderSource == null)
{
this.Tool.ChangeRemoteSenderName(this.Tool.RemoteSenderName);
}
}
}
}
using NewTek;
using NewTek.NDI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 查找NDI流任务
/// </summary>
public class NDIToolRecvVideoTask : NDIToolTaskBase
{
/// <summary>
/// 任务名称
/// </summary>
public override NDIToolTaskNames Name => NDIToolTaskNames.RECV_VIDEO;
/// <summary>
/// 之前的视频帧时间戳
/// </summary>
private long old_video_timestamp = 0;
/// <summary>
/// 执行
/// </summary>
protected override void Execute()
{
while (this.IsStarted)
{
if (this.Tool.RecvInstancePtr == IntPtr.Zero || this.Tool.RecvSyncInstancePtr == IntPtr.Zero)
{
Thread.Sleep(1);
continue;
}
// 执行
this._Execute();
}
}
/// <summary>
/// 执行
/// </summary>
private void _Execute()
{
// 获取NDI视频帧
NDIlib.video_frame_v2_t frame = new NDIlib.video_frame_v2_t();
NDIlib.framesync_capture_video(this.Tool.RecvSyncInstancePtr, ref frame, NDIlib.frame_format_type_e.frame_format_type_progressive);
// 如果该帧的时间戳与之前的帧时间戳一致
// 那么认为没有获取到新的一帧画面
if (this.old_video_timestamp == frame.timestamp)
{
NDIlib.framesync_free_video(this.Tool.RecvSyncInstancePtr, ref frame);
Thread.Sleep(1);
return;
}
// 否则
// 获取到新的一帧画面
this.old_video_timestamp = frame.timestamp;
// 如果新的一帧画面的时间戳为0 || 帧没有数据
if (frame.timestamp == 0 || frame.p_data == IntPtr.Zero || frame.p_data == null)
{
NDIlib.framesync_free_video(this.Tool.RecvSyncInstancePtr, ref frame);
Thread.Sleep(1);
return;
}
// 视频帧队列最大容量
// 如果超过该容量,那么会抛弃对队列头部的处理
if (this.Tool.VideoFrameQueue.Count > NDITool.VIDEO_FRAME_QUEUE_MAX_COUNT + this.Tool.Option.DelayFrame)
{
this.Tool.VideoFrameQueue.TryDequeue(out IVideoFrame remove);
remove?.DataStream?.Dispose();
}
NDIToolVideoFrame videoFrame = new NDIToolVideoFrame();
videoFrame.Width = frame.xres;
videoFrame.Height = frame.yres;
videoFrame.Length = frame.xres * frame.yres * 4;
videoFrame.TimeStamp = frame.timestamp;
videoFrame.DataStream = new SharpDX.DataStream(videoFrame.Length, true, true);
unsafe
{
Buffer.MemoryCopy(frame.p_data.ToPointer(), videoFrame.DataStream.DataPointer.ToPointer(), videoFrame.Length, videoFrame.Length);
}
this.Tool.VideoFrameQueue.Enqueue(videoFrame);
// 尝试释放帧数据
NDIlib.framesync_free_video(this.Tool.RecvSyncInstancePtr, ref frame);
Thread.Sleep(5);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频帧事件参数
/// </summary>
public class VideoFrameEventArgs : EventArgs
{
/// <summary>
/// 视频帧数据
/// </summary>
public IVideoFrame Frame { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 视频流管理器
/// </summary>
public static class VideoStreamManager
{
/// <summary>
/// NDI工具
/// </summary>
public static NDITool NDITool { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using VIZ.GimbalAI.Core;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 拖拽窗口区域
/// </summary>
public class DragWindowBar : Border
{
/// <summary>
/// 鼠标按下的坐标
/// </summary>
private Point? mouseLeftButtonDownPoint;
/// <summary>
/// 所属窗口
/// </summary>
private Window ownerWindow;
/// <summary>
/// 获取所属窗口
/// </summary>
/// <returns>所属窗口</returns>
private Window GetOwnerWindow()
{
if (this.ownerWindow != null)
return this.ownerWindow;
this.ownerWindow = WPFHelper.GetAncestorByType<Window>(this);
return this.ownerWindow;
}
/// <summary>
/// 鼠标按下
/// </summary>
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
this.mouseLeftButtonDownPoint = e.GetPosition(this);
}
/// <summary>
/// 鼠标移动
/// </summary>
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
base.OnPreviewMouseMove(e);
if (e.LeftButton != MouseButtonState.Pressed || this.mouseLeftButtonDownPoint == null)
return;
Point point = e.GetPosition(this);
if (Math.Abs(point.X - this.mouseLeftButtonDownPoint.Value.X) >= 5 || Math.Abs(point.Y - this.mouseLeftButtonDownPoint.Value.Y) >= 5)
{
Window window = this.GetOwnerWindow();
window.DragMove();
}
}
/// <summary>
/// 鼠标释放
/// </summary>
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonUp(e);
this.mouseLeftButtonDownPoint = null;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
namespace VIZ.GimbalAI.Common
{
/// <summary>
/// 空窗口
/// </summary>
public class NoneWindow : Window
{
/// <summary>
/// 窗口
/// </summary>
/// <param name="width">窗口宽度</param>
/// <param name="height">窗口高度</param>
/// <param name="content">窗口内容</param>
public NoneWindow(double width, double height, Control content)
{
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
this.WindowState = WindowState.Normal;
this.WindowStyle = WindowStyle.None;
this.Background = new SolidColorBrush(Colors.Transparent);
this.AllowsTransparency = true;
this.Width = width;
this.Height = height;
this.Content = content;
content.Margin = new Thickness(10, 10, 10, 10);
}
}
}
......@@ -6,6 +6,10 @@
<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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
\ No newline at end of file
......@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -34,39 +35,20 @@ namespace VIZ.GimbalAI.Connection
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
/// <param name="info">信息</param>
public void Execute(ConnSingleJsonInfo info)
{
Task.Run(() =>
{
try
{
this._Execute(packageInfo);
}
catch (Exception ex)
{
log.Error(ex);
}
});
}
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
private void _Execute(UdpPackageInfo packageInfo)
{
AlgorithmPackageBase @base = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmPackageBase>(packageInfo.Message);
AlgorithmPackageBase @base = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmPackageBase>(info.Json);
foreach (IAlgorithmPackageProvider provider in this.providers)
{
if (string.Equals(provider.Signal, @base.signal))
{
provider.Execute(packageInfo);
provider.Execute(info);
break;
}
}
}
}
}
}
\ No newline at end of file
......@@ -45,5 +45,10 @@ namespace VIZ.GimbalAI.Connection
/// 算法初始化完成
/// </summary>
public const string tracking_init_complete = "tracking_init_complete";
/// <summary>
/// 设置中心轴位置
/// </summary>
public const string tx_ty = "tx_ty";
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -20,7 +21,7 @@ namespace VIZ.GimbalAI.Connection
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
void Execute(UdpPackageInfo packageInfo);
/// <param name="info">信息</param>
void Execute(ConnSingleJsonInfo info);
}
}
......@@ -4,7 +4,8 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
......@@ -25,15 +26,15 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
public void Execute(ConnSingleJsonInfo packageInfo)
{
AlgorithmDetectRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmDetectRecvPackage>(packageInfo.Message);
AlgorithmDetectRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmDetectRecvPackage>(packageInfo.Json);
VideoRenderRectangleMessage msg = new VideoRenderRectangleMessage();
msg.signal = package.signal;
msg.roi = package.roi;
VAppDomain.AlgorithmMessageManager.Send(msg);
ApplicationDomainEx.MessageManager.Send(msg);
}
}
}
......@@ -4,7 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
......@@ -25,16 +25,16 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
public void Execute(ConnSingleJsonInfo packageInfo)
{
// 更新界面
AlgorithmTargetLostRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmTargetLostRecvPackage>(packageInfo.Message);
AlgorithmTargetLostRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmTargetLostRecvPackage>(packageInfo.Json);
VideoRenderRectangleMessage msg = new VideoRenderRectangleMessage();
msg.signal = package.signal;
msg.roi = new Dictionary<int, List<float>>();
VAppDomain.AlgorithmMessageManager.Send(msg);
ApplicationDomainEx.MessageManager.Send(msg);
}
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
......@@ -23,11 +24,11 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
public void Execute(ConnSingleJsonInfo packageInfo)
{
AlgorithmInitCompleteMessage msg = new AlgorithmInitCompleteMessage();
VAppDomain.UiMessageManager.Send(msg);
ApplicationDomainEx.MessageManager.Send(msg);
}
}
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
......@@ -25,16 +25,16 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
public void Execute(ConnSingleJsonInfo packageInfo)
{
AlgorithmTrackingRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmTrackingRecvPackage>(packageInfo.Message);
AlgorithmTrackingRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmTrackingRecvPackage>(packageInfo.Json);
VideoRenderRectangleMessage msg = new VideoRenderRectangleMessage();
msg.signal = package.signal;
msg.roi = new Dictionary<int, List<float>>();
msg.roi.Add(0, package.roi);
VAppDomain.AlgorithmMessageManager.Send(msg);
ApplicationDomainEx.MessageManager.Send(msg);
}
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
namespace VIZ.GimbalAI.Connection
......@@ -21,10 +22,10 @@ namespace VIZ.GimbalAI.Connection
AlgorithmAutoDetectPackage package = new AlgorithmAutoDetectPackage();
package.signal = AlgorithmPackageSignal.detect;
package.mode = AlgorithmPackageMode.auto;
package.scene = VDataDomain.AlgorithmAutoSetting.Scene.Value;
package.classes = VDataDomain.AlgorithmAutoSetting.Classes.Where(p => p.IsChecked).Select(p => p.Value).ToList();
package.scene = ApplicationDomainEx.AlgorithmAutoSetting.Scene.Value;
package.classes = ApplicationDomainEx.AlgorithmAutoSetting.Classes.Where(p => p.IsChecked).Select(p => p.Value).ToList();
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -39,7 +40,7 @@ namespace VIZ.GimbalAI.Connection
package.mode = AlgorithmPackageMode.manual;
package.roi = roi;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -52,11 +53,11 @@ namespace VIZ.GimbalAI.Connection
AlgorithmAutoTrackingPackage package = new AlgorithmAutoTrackingPackage();
package.signal = AlgorithmPackageSignal.tracking;
package.mode = AlgorithmPackageMode.auto;
package.scene = VDataDomain.AlgorithmAutoSetting.Scene.Value;
package.classes = VDataDomain.AlgorithmAutoSetting.Classes.Where(p => p.IsChecked).Select(p => p.Value).ToList();
package.scene = ApplicationDomainEx.AlgorithmAutoSetting.Scene.Value;
package.classes = ApplicationDomainEx.AlgorithmAutoSetting.Classes.Where(p => p.IsChecked).Select(p => p.Value).ToList();
package.id = id;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -70,7 +71,7 @@ namespace VIZ.GimbalAI.Connection
package.signal = AlgorithmPackageSignal.mode_change;
package.mode = mode;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -84,7 +85,7 @@ namespace VIZ.GimbalAI.Connection
package.signal = AlgorithmPackageSignal.stop;
package.mode = mode;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -96,7 +97,21 @@ namespace VIZ.GimbalAI.Connection
AlgorithmExitPackage package = new AlgorithmExitPackage();
package.signal = AlgorithmPackageSignal.exit;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
/// 发送中心轴位置
/// </summary>
/// <param name="manager">UDP终结点管理器</param>
public static void CenterAxis(UdpEndpointManager manager)
{
AlgorithmCenterAxisPackage package = new AlgorithmCenterAxisPackage();
package.signal = AlgorithmPackageSignal.tx_ty;
package.tx = ApplicationDomainEx.GimbalControlModel.CenterAxisX;
package.ty = ApplicationDomainEx.GimbalControlModel.CenterAxisY;
manager.SendJson(package);
}
}
}
......@@ -7,13 +7,18 @@ using System.Threading.Tasks;
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// 链接管理器
/// 算法自动检测包
/// </summary>
public static class ConnectionManager
public class AlgorithmCenterAxisPackage : AlgorithmPackageBase
{
/// <summary>
/// Udp连接
/// 中心轴X坐标
/// </summary>
public static UdpConnection UdpConnection { get; set; }
public double tx { get; set; }
/// <summary>
/// 中心轴Y坐标
/// </summary>
public double ty { get; set; }
}
}
......@@ -27,5 +27,10 @@ namespace VIZ.GimbalAI.Connection
/// 云台预设指令
/// </summary>
public const string preset = "preset";
/// <summary>
/// 中心轴指令
/// </summary>
public const string center_axis = "center axis";
}
}
......@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -15,55 +16,36 @@ namespace VIZ.GimbalAI.Connection
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(AlgorithmPackageProvider));
private readonly static ILog log = LogManager.GetLogger(typeof(AlgorithmPackageProvider));
public GimbalPackageProvider()
{
this.providers.Add(new GimbalCenterAxisProvider());
this.providers.Add(new GimbalPtzSnapshotProvider());
}
/// <summary>
/// 算法数据包处理器
/// </summary>
private List<IGimbalPackageProvider> providers = new List<IGimbalPackageProvider>();
private readonly List<IGimbalPackageProvider> providers = new List<IGimbalPackageProvider>();
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
/// <param name="info">信息</param>
public void Execute(ConnSingleJsonInfo info)
{
Task.Run(() =>
{
try
{
this._Execute(packageInfo);
}
catch (Exception ex)
{
log.Error(ex);
}
});
}
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
private void _Execute(UdpPackageInfo packageInfo)
{
GimbalPackageBase @base = Newtonsoft.Json.JsonConvert.DeserializeObject<GimbalPackageBase>(packageInfo.Message);
AlgorithmPackageBase @base = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmPackageBase>(info.Json);
foreach (IGimbalPackageProvider provider in this.providers)
{
if (string.Equals(provider.Signal, @base.signal))
{
provider.Execute(packageInfo);
provider.Execute(info);
break;
}
}
}
}
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -21,6 +22,6 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
void Execute(UdpPackageInfo packageInfo);
void Execute(ConnSingleJsonInfo packageInfo);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Storage;
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// 设置中心轴指令
/// </summary>
public class GimbalCenterAxisProvider : IGimbalPackageProvider
{
/// <summary>
/// 信号
/// <see cref="GimbalPackageSignal"/>
/// </summary>
public string Signal { get; } = GimbalPackageSignal.center_axis;
/// <summary>
/// 云台中心轴移动速度
/// </summary>
private static readonly double GIMBAL_CENTER_AXIS_SPEED = ApplicationDomainEx.IniStorage.GetValue<GimbalConfig, double>(p => p.GIMBAL_CENTER_AXIS_SPEED);
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(ConnSingleJsonInfo packageInfo)
{
GimbalCenterAxisRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<GimbalCenterAxisRecvPackage>(packageInfo.Json);
if (package == null)
return;
// 更新坐标位置
double x = ApplicationDomainEx.GimbalControlModel.CenterAxisX + (package.h > 0 ? 1 : -1) * GIMBAL_CENTER_AXIS_SPEED;
double y = ApplicationDomainEx.GimbalControlModel.CenterAxisY + (package.v > 0 ? 1 : -1) * GIMBAL_CENTER_AXIS_SPEED;
x = MathHelper.Clip(0, 1920, x);
y = MathHelper.Clip(0, 1080, y);
ApplicationDomainEx.GimbalControlModel.CenterAxisX = x;
ApplicationDomainEx.GimbalControlModel.CenterAxisY = y;
// 向算法发送最新的中心轴位置
UdpEndpointManager manager = ConnectionManager.UdpConnection.GetEndpointManager(UdpEndpointKeys.algorithm);
AlgorithmSender.CenterAxis(manager);
// 向界面发送更新轴信息消息
GimbalCenterAxisMessage message = new GimbalCenterAxisMessage();
message.X = x;
message.Y = y;
ApplicationDomainEx.MessageManager.Send(message);
}
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
using VIZ.GimbalAI.Domain;
namespace VIZ.GimbalAI.Connection
......@@ -22,14 +23,14 @@ namespace VIZ.GimbalAI.Connection
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
public void Execute(UdpPackageInfo packageInfo)
public void Execute(ConnSingleJsonInfo packageInfo)
{
GimbalPtzSnapshotRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<GimbalPtzSnapshotRecvPackage>(packageInfo.Message);
GimbalPtzSnapshotRecvPackage package = Newtonsoft.Json.JsonConvert.DeserializeObject<GimbalPtzSnapshotRecvPackage>(packageInfo.Json);
GimbalPtzSnapshotMessage msg = new GimbalPtzSnapshotMessage();
msg.Data = package.Data;
VAppDomain.UiMessageManager.Send(msg);
ApplicationDomainEx.MessageManager.Send(msg);
}
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -22,7 +23,7 @@ namespace VIZ.GimbalAI.Connection
GimbalRresetSavePackage package = new GimbalRresetSavePackage();
package.signal = GimbalPackageSignal.preset_save;
manager.Send(package);
manager.SendJson(package);
}
/// <summary>
......@@ -36,7 +37,7 @@ namespace VIZ.GimbalAI.Connection
package.signal = GimbalPackageSignal.preset;
package.data = data;
manager.Send(package);
manager.SendJson(package);
}
}
}
......@@ -4,20 +4,21 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// 消息框按钮组
/// 云台预设返回包
/// </summary>
public enum VMessageBoxButtons
public class GimbalCenterAxisRecvPackage : GimbalPackageBase
{
/// <summary>
/// 确定
/// 俯仰值
/// </summary>
YES,
public double v { get; set; }
/// <summary>
/// 确定 & 取消
/// 旋转值
/// </summary>
YES_CANCEL
public double h { get; set; }
}
}
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Connection
{
......@@ -14,7 +15,7 @@ namespace VIZ.GimbalAI.Connection
/// <summary>
/// 执行
/// </summary>
/// <param name="packageInfo">包信息</param>
void Execute(UdpPackageInfo packageInfo);
/// <param name="info">信息</param>
void Execute(ConnSingleJsonInfo info);
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// UDP连接
/// </summary>
public class UdpConnection : IDisposable
{
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(UdpConnection));
/// <summary>
/// 最大数据长度
/// </summary>
public const int MAX_BUFFER_SIZE = 1024 * 10;
/// <summary>
/// UDP客户端
/// </summary>
public UdpClient UdpClient { get; private set; }
/// <summary>
/// IP地址
/// </summary>
public string IP { get; private set; }
/// <summary>
/// 端口
/// </summary>
public int Port { get; private set; }
/// <summary>
/// 终结点管理器集合
/// </summary>
private Dictionary<string, UdpEndpointManager> endpointManagers = new Dictionary<string, UdpEndpointManager>();
/// <summary>
/// 数据接收线程
/// </summary>
private Thread recvTrhead;
/// <summary>
/// 是否已经开始接收数据
/// </summary>
private bool IsRecvStart;
/// <summary>
/// 绑定IP和端口
/// </summary>
/// <param name="ip">IP</param>
/// <param name="port">端口</param>
public void Binding(string ip, int port)
{
this.IP = ip;
this.Port = port;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ip), port);
this.UdpClient = new UdpClient(ipep);
}
/// <summary>
/// 连接
/// </summary>
public void Start()
{
this.IsRecvStart = true;
this.recvTrhead = new Thread(this.ReceiveMessage);
this.recvTrhead.Start();
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
try
{
this.IsRecvStart = false;
this.UdpClient?.Close();
this.UdpClient?.Dispose();
this.recvTrhead = null;
}
catch (Exception ex)
{
log.Error(ex);
}
}
/// <summary>
/// 销毁
/// </summary>
public void Dispose()
{
this.Stop();
}
/// <summary>
/// 获取UDP终结点管理器
/// </summary>
/// <param name="key">终结点管理器键<see cref="UdpEndpointKeys"/></param>
/// <returns>终结点管理器</returns>
public UdpEndpointManager GetEndpointManager(string key)
{
this.endpointManagers.TryGetValue(key, out UdpEndpointManager manager);
return manager;
}
/// <summary>
/// 添加UDP终结点管理器
/// </summary>
/// <param name="manager">终结点管理器</param>
public void AddEndpointManager(UdpEndpointManager manager)
{
manager.UdpClient = this.UdpClient;
this.endpointManagers[manager.Key] = manager;
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="obj"></param>
private void ReceiveMessage(object obj)
{
while (this.IsRecvStart)
{
try
{
IPEndPoint endport = new IPEndPoint(IPAddress.Any, 0);
byte[] buffer = this.UdpClient.Receive(ref endport);
UdpPackageInfo info = new UdpPackageInfo();
info.IP = this.IP;
info.Port = this.Port;
info.Message = Encoding.UTF8.GetString(buffer);
foreach (var manager in this.endpointManagers.Values)
{
manager.Execute(info);
}
string consoleMsg = $"{DateTime.Now} 【接收】 {info.Message}";
#if DEBUG
Debug.WriteLine(consoleMsg);
#endif
UdpConsoleMessage msg = new UdpConsoleMessage();
msg.Message = info.Message;
msg.IsSender = false;
VAppDomain.UiMessageManager.Send(msg);
}
catch (Exception ex)
{
log.Error(ex);
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Diagnostics;
using log4net;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// UDP网络终结点管理器
/// </summary>
public class UdpEndpointManager
{
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(UdpEndpointManager));
/// <summary>
/// 网络终结点键<see cref="UdpEndpointKeys"/>
/// </summary>
public string Key { get; private set; }
/// <summary>
/// 监听IP
/// </summary>
public string IP { get; private set; }
/// <summary>
/// 监听端口
/// </summary>
public int Port { get; private set; }
/// <summary>
/// UDP客户端
/// </summary>
public UdpClient UdpClient { get; internal set; }
/// <summary>
/// 包处理器
/// </summary>
internal List<IUdpPackageProvider> PackageProviders = new List<IUdpPackageProvider>();
/// <summary>
/// UDP终结点管理器
/// </summary>
/// <param name="key">网络终结点键<see cref="UdpEndpointKeys"/></param>
/// <param name="ip">IP地址</param>
/// <param name="port">端口</param>
public UdpEndpointManager(string key, string ip, int port)
{
this.Key = key;
this.IP = ip;
this.Port = port;
}
/// <summary>
/// 添加包处理器
/// </summary>
/// <param name="provider">包处理器</param>
public void AddProvider(IUdpPackageProvider provider)
{
this.PackageProviders.Add(provider);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data">数据</param>
public void Send(string data)
{
byte[] buffer = Encoding.UTF8.GetBytes(data);
this.UdpClient.Send(buffer, buffer.Length, this.IP, this.Port);
string consoleMsg = $"{DateTime.Now} 【发送】 {data}";
#if DEBUG
Debug.WriteLine(consoleMsg);
#endif
UdpConsoleMessage msg = new UdpConsoleMessage();
msg.Message = data;
msg.IsSender = true;
VAppDomain.UiMessageManager.Send(msg);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data">数据</param>
public void Send(object data)
{
string str = Newtonsoft.Json.JsonConvert.SerializeObject(data);
this.Send(str);
}
/// <summary>
/// 處理UDP消息
/// </summary>
/// <param name="info">UDP消息信息</param>
public void Execute(UdpPackageInfo info)
{
foreach (IUdpPackageProvider provider in this.PackageProviders)
{
provider.Execute(info);
}
}
}
}
using System;
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using NewTek;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Common
namespace VIZ.GimbalAI.Connection
{
/// <summary>
/// 处理NDI视频帧任务
/// UDP包解析器
/// </summary>
public class NDIToolExecuteVideoTask : NDIToolTaskBase
public class UdpPackageProvider : ConnSingleJsonPackageProvider
{
/// <summary>
/// 任务名称
/// 日志
/// </summary>
public override NDIToolTaskNames Name => NDIToolTaskNames.EXECUTE_VIDEO;
private readonly static ILog log = LogManager.GetLogger(typeof(UdpPackageProvider));
public UdpPackageProvider()
{
this.providers.Add(new AlgorithmPackageProvider());
this.providers.Add(new GimbalPackageProvider());
}
private List<IUdpPackageProvider> providers = new List<IUdpPackageProvider>();
/// <summary>
/// 执行
/// </summary>
protected override void Execute()
/// <param name="info">信息</param>
protected override void Execute(ConnSingleJsonInfo info)
{
while (this.IsStarted)
Task.Run(() =>
{
if (this.Tool.VideoFrameQueue.Count <= this.Tool.Option.DelayFrame)
try
{
Thread.Sleep(2);
AlgorithmPackageBase @base = Newtonsoft.Json.JsonConvert.DeserializeObject<AlgorithmPackageBase>(info.Json);
continue;
foreach (IUdpPackageProvider provider in this.providers)
{
provider.Execute(info);
}
}
if (!this.Tool.VideoFrameQueue.TryDequeue(out IVideoFrame frame))
catch (Exception ex)
{
continue;
log.Error(ex);
}
// 触发视频帧处理事件
this.Tool.TriggerExecuteVideoFrame(frame);
Thread.Sleep(10);
}
});
}
}
}
......@@ -85,7 +85,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConnectionManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UDP\Algorithm\AlgorithmPackageBase.cs" />
<Compile Include="UDP\Algorithm\Enum\AlgorithmPackageSignal.cs" />
......@@ -100,6 +99,7 @@
<Compile Include="UDP\Algorithm\Signal\Recv\AlgorithmTargetLostRecvPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Recv\AlgorithmTrackingRecvPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Recv\AlgorithmDetectRecvPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Send\AlgorithmCenterAxisPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Send\AlgorithmAutoDetectPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Send\AlgorithmAutoTrackingPackage.cs" />
<Compile Include="UDP\Algorithm\Signal\Send\AlgorithmManualTrackingPackage.cs" />
......@@ -111,26 +111,43 @@
<Compile Include="UDP\Gimbal\GimbalPackageBase.cs" />
<Compile Include="UDP\Gimbal\GimbalPackageProvider.cs" />
<Compile Include="UDP\Gimbal\IGimbalPackageProvider.cs" />
<Compile Include="UDP\Gimbal\Provider\GimbalCenterAxisProvider.cs" />
<Compile Include="UDP\Gimbal\Provider\GimbalPtzSnapshotProvider.cs" />
<Compile Include="UDP\Gimbal\Sender\GimbalSender.cs" />
<Compile Include="UDP\Gimbal\Signal\Recv\GimbalCenterAxisRecvPackage.cs" />
<Compile Include="UDP\Gimbal\Signal\Recv\GimbalPtzSnapshotRecvPackage.cs" />
<Compile Include="UDP\Gimbal\Signal\Send\GimbalRresetPackage.cs" />
<Compile Include="UDP\Gimbal\Signal\Send\GimbalRresetSavePackage.cs" />
<Compile Include="UDP\IUdpPackageProvider.cs" />
<Compile Include="UDP\UdpEndpointKeys.cs" />
<Compile Include="UDP\UdpPackageInfo.cs" />
<Compile Include="UDP\UdpConnection.cs" />
<Compile Include="UDP\UdpEndpointManager.cs" />
<Compile Include="UDP\UdpPackageProvider.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VIZ.GimbalAI.Core\VIZ.GimbalAI.Core.csproj">
<Project>{d4409326-3f36-4835-812a-bea8ed046e04}</Project>
<Name>VIZ.GimbalAI.Core</Name>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Connection\VIZ.Framework.Connection.csproj">
<Project>{e07528dd-9dee-47c2-b79d-235ecfa6b003}</Project>
<Name>VIZ.Framework.Connection</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Core\VIZ.Framework.Core.csproj">
<Project>{75b39591-4bc3-4b09-bd7d-ec9f67efa96e}</Project>
<Name>VIZ.Framework.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Domain\VIZ.Framework.Domain.csproj">
<Project>{28661e82-c86a-4611-a028-c34f6ac85c97}</Project>
<Name>VIZ.Framework.Domain</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Storage\VIZ.Framework.Storage.csproj">
<Project>{06b80c09-343d-4bb2-aeb1-61cfbfbf5cad}</Project>
<Name>VIZ.Framework.Storage</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Domain\VIZ.GimbalAI.Domain.csproj">
<Project>{bbf80159-d5de-4d82-a045-a96d67d80632}</Project>
<Name>VIZ.GimbalAI.Domain</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Storage\VIZ.GimbalAI.Storage.csproj">
<Project>{fb44d2c0-5a08-4b87-b3c7-745471a0d868}</Project>
<Name>VIZ.GimbalAI.Storage</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
......
......@@ -4,7 +4,7 @@
<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>
</assemblyBinding>
</runtime>
......
......@@ -3,33 +3,35 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Core;
using VIZ.Framework.Domain;
using VIZ.GimbalAI.Storage;
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// 数据
/// 应用程序
/// </summary>
public static class VDataDomain
public class ApplicationDomainEx : ApplicationDomain
{
/// <summary>
/// 本地Config
/// CSV数据上下文
/// </summary>
public static DataManager dataManager { get; set; }
public static CsvContext CsvContext { get; set; }
/// <summary>
/// 算法自动设置
/// LiteDb数据
/// </summary>
public static AlgorithmAutoSetting AlgorithmAutoSetting { get; set; } = new AlgorithmAutoSetting();
public static LiteDbContext LiteDbContext { get; set; }
/// <summary>
/// LiteDb数据
/// 算法自动设置
/// </summary>
public static LiteDbContext LiteDbContext { get; set; }
public static AlgorithmAutoSetting AlgorithmAutoSetting { get; private set; } = new AlgorithmAutoSetting();
/// <summary>
/// Ini仓储
/// 云台控制模型
/// </summary>
public static IniStorage IniStorage { get; set; }
public static GimbalControlModel GimbalControlModel { get; private set; } = new GimbalControlModel();
}
}
......@@ -4,16 +4,16 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// NDI工具设置
/// NDI视图键
/// </summary>
public class NDIToolOption
public static class NDIViewKeys
{
/// <summary>
/// 延时帧(视频显示将在该延时帧之后处理)
/// 主视图
/// </summary>
public int DelayFrame { get; set; }
public const string Main = "Main";
}
}
......@@ -4,21 +4,21 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Domain.Message
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// UDP控制台消息
/// 服务键
/// </summary>
public class UdpConsoleMessage
public static class ServiceKeys
{
/// <summary>
/// 消息
/// 控制视图
/// </summary>
public string Message { get; set; }
public const string ControlView = "ControlView";
/// <summary>
/// 该消息是否是发送消息,否则为接收到的消息
/// 视频视图
/// </summary>
public bool IsSender { get; set; }
public const string VideoView = "VideoView";
}
}
......@@ -4,21 +4,21 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Common
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// 消息框返回
/// 云台中心轴消息
/// </summary>
public enum VMessageBoxResult
public class GimbalCenterAxisMessage
{
/// <summary>
/// 确定
/// 中心轴X坐标
/// </summary>
YES,
/// <summary>
public double X { get; set; }
/// <summary>
/// 取消
/// 中心轴Y坐标
/// </summary>
CANCEL
public double Y { get; set; }
}
}
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......@@ -63,7 +63,6 @@ namespace VIZ.GimbalAI.Domain
set { classes = value; this.RaisePropertyChanged(nameof(Classes)); }
}
#endregion
}
}
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......
......@@ -3,23 +3,23 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Common
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// 视频矩形框选事件参数
/// 云台控制模型
/// </summary>
public class VideoRectangleFrameSelectionEventArgs : EventArgs
public class GimbalControlModel : ModelBase
{
/// <summary>
/// 鼠标款选区域
/// 中心轴X坐标
/// </summary>
public RectangleF MouseRectangle { get; set; }
public double CenterAxisX { get; set; }
/// <summary>
/// 视频框选区域
/// 中心轴Y坐标
/// </summary>
public RectangleF VideoRectangle { get; set; }
public double CenterAxisY { get; set; }
}
}
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using System.Drawing;
using VIZ.GimbalAI.Storage;
......
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......
......@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Domain
{
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// 视音频帧数据参数
/// </summary>
public static class VAConstants
{
/// <summary>
/// 视频帧的最大长度
/// 1936*1088 1920*1088安卓与IOS端会因为H264硬件编码造成数据向16位补不起
/// 正常数据最大应为1920*1080 或 1080*1920
/// </summary>
public const int VideoFrameLengthMax = 3159552;
/// <summary>
/// 1920*1080帧大小
/// </summary>
public const int VideoFrameLength1080 = 3110400;
public const int Video1920 = 1920;
public const int Video1080 = 1080;
public const int Video1936 = 1936;
public const int Video1088 = 1088;
/// <summary>
/// 40ms
/// </summary>
public const int AudioFrameLengthMax = 7680;
/// <summary>
/// 20ms
/// </summary>
public const int AudioFrameLengthMin = 3840;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
namespace VIZ.GimbalAI.Domain
{
/// <summary>
/// 应用程序域
/// </summary>
public static class VAppDomain
{
/// <summary>
/// 算法消息管理
/// </summary>
public static IVMessageManager AlgorithmMessageManager { get; } = new VMessageManager();
/// <summary>
/// UI消息管理
/// </summary>
public static IVMessageManager UiMessageManager { get; } = new VMessageManager();
/// <summary>
/// 视图模型服务管理
/// </summary>
public static IViewModelServiceManager ViewModelServiceManager { get; } = new ViewModelServiceManager();
/// <summary>
/// 延时管理器
/// </summary>
public static IVDelayManager DelayManager { get; } = new VDelayManager();
}
}
......@@ -83,32 +83,41 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Enum\NDIViewKeys.cs" />
<Compile Include="Enum\ServiceKeys.cs" />
<Compile Include="Message\Gimbal\GimbalCenterAxisMessage.cs" />
<Compile Include="Message\Gimbal\GimbalInitCompleteMessage.cs" />
<Compile Include="Model\Gimbal\GimbalControlModel.cs" />
<Compile Include="Model\NDI\NdiStreamGroupModel.cs" />
<Compile Include="Model\NDI\NdiStreamModel.cs" />
<Compile Include="Model\NDI\NdiVideoFrameDelayModel.cs" />
<Compile Include="VDataDomain.cs" />
<Compile Include="Message\Algorithm\AlgorithmInitCompleteMessage.cs" />
<Compile Include="Message\Algorithm\VideoRenderRectangleMessage.cs" />
<Compile Include="Enum\Video\VideoViewStatus.cs" />
<Compile Include="Message\Gimbal\GimbalPtzSnapshotMessage.cs" />
<Compile Include="Message\UDP\UdpConsoleMessage.cs" />
<Compile Include="Model\Algorithm\AlgorithmClassModel.cs" />
<Compile Include="Model\Algorithm\AlgorithmSceneModel.cs" />
<Compile Include="Model\Algorithm\AlgorithmAutoSetting.cs" />
<Compile Include="Model\Gimbal\GimbalPresetModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VAConstants.cs" />
<Compile Include="VAppDomain.cs" />
<Compile Include="ApplicationDomainEx.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VIZ.GimbalAI.Core\VIZ.GimbalAI.Core.csproj">
<Project>{d4409326-3f36-4835-812a-bea8ed046e04}</Project>
<Name>VIZ.GimbalAI.Core</Name>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Common\VIZ.Framework.Common.csproj">
<Project>{92834c05-703e-4f05-9224-f36220939d8f}</Project>
<Name>VIZ.Framework.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Core\VIZ.Framework.Core.csproj">
<Project>{75b39591-4bc3-4b09-bd7d-ec9f67efa96e}</Project>
<Name>VIZ.Framework.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Domain\VIZ.Framework.Domain.csproj">
<Project>{28661e82-c86a-4611-a028-c34f6ac85c97}</Project>
<Name>VIZ.Framework.Domain</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Storage\VIZ.GimbalAI.Storage.csproj">
<Project>{FB44D2C0-5A08-4B87-B3C7-745471A0D868}</Project>
......
......@@ -4,7 +4,7 @@
<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>
</assemblyBinding>
</runtime>
......
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core">
xmlns:converter="clr-namespace:VIZ.Framework.Core;assembly=VIZ.Framework.Core">
<converter:Bitmap2ImageSourceConverter x:Key="Bitmap2ImageSourceConverter"></converter:Bitmap2ImageSourceConverter>
......
......@@ -133,14 +133,18 @@
<Resource Include="Icons\down_24x24.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Common\VIZ.Framework.Common.csproj">
<Project>{92834c05-703e-4f05-9224-f36220939d8f}</Project>
<Name>VIZ.Framework.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\VIZ.Framework\VIZ.Framework.Core\VIZ.Framework.Core.csproj">
<Project>{75b39591-4bc3-4b09-bd7d-ec9f67efa96e}</Project>
<Name>VIZ.Framework.Core</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Common.Resource\VIZ.GimbalAI.Common.Resource.csproj">
<Project>{5d8021d1-a6b2-4784-b8fe-ff3b7f94e304}</Project>
<Name>VIZ.GimbalAI.Common.Resource</Name>
</ProjectReference>
<ProjectReference Include="..\VIZ.GimbalAI.Core\VIZ.GimbalAI.Core.csproj">
<Project>{d4409326-3f36-4835-812a-bea8ed046e04}</Project>
<Name>VIZ.GimbalAI.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
\ No newline at end of file
......@@ -3,7 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Connection;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
using VIZ.GimbalAI.Storage;
......@@ -27,7 +28,7 @@ namespace VIZ.GimbalAI.Module
/// <summary>
/// 最大行数
/// </summary>
private readonly int MAX_LINE = VDataDomain.IniStorage.GetValue<ClientConfig, int>(p => p.CLIENT_CONSOLE_LOG_MAX_LINE);
private readonly int MAX_LINE = ApplicationDomainEx.IniStorage.GetValue<ClientConfig, int>(p => p.CLIENT_CONSOLE_LOG_MAX_LINE);
/// <summary>
/// 当前行数
......@@ -47,7 +48,8 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void InitMessage()
{
VAppDomain.UiMessageManager.Register<UdpConsoleMessage>(this, this.UdpConsole);
ApplicationDomainEx.MessageManager.Register<ConnSingleJsonMessage>(this, this.UdpConsole);
ApplicationDomainEx.MessageManager.Register<ConnSendMessage>(this, this.UdpConsole);
}
// ======================================================================================
......@@ -83,10 +85,10 @@ namespace VIZ.GimbalAI.Module
#region UdpConsoleMessage -- UDP控制台消息
/// <summary>
/// UDP控制台消息
/// UDP控制台消息 -- 接收的消息
/// </summary>
/// <param name="msg">消息</param>
public void UdpConsole(UdpConsoleMessage msg)
public void UdpConsole(ConnSingleJsonMessage msg)
{
WPFHelper.BeginInvoke(() =>
{
......@@ -100,7 +102,31 @@ namespace VIZ.GimbalAI.Module
this.Line = 1;
}
view.lb.AppendText("\r\n" + msg.Message);
view.lb.AppendText("\r\n接收: " + msg.Json);
view.lb.ScrollToEnd();
});
}
/// <summary>
/// UDP控制台消息 -- 发送的消息
/// </summary>
/// <param name="msg">消息</param>
private void UdpConsole(ConnSendMessage msg)
{
WPFHelper.BeginInvoke(() =>
{
ConsoleView view = this.GetView<ConsoleView>();
if (view == null)
return;
if (this.Line++ % MAX_LINE == 0)
{
view.lb.Clear();
this.Line = 1;
}
string text = Encoding.UTF8.GetString(msg.Buffer);
view.lb.AppendText("\r\n发送: " + text);
view.lb.ScrollToEnd();
});
}
......
......@@ -3,14 +3,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Module
{
/// <summary>
/// 控制器视图服务
/// </summary>
public interface IControlViewService : IViewModelService
public interface IControlViewService : IService
{
/// <summary>
/// 是否是手动模式
......
......@@ -5,8 +5,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:VIZ.GimbalAI.Module"
xmlns:common="clr-namespace:VIZ.GimbalAI.Common;assembly=VIZ.GimbalAI.Common"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core"
xmlns:common="clr-namespace:VIZ.Framework.Common;assembly=VIZ.Framework.Common"
xmlns:converter="clr-namespace:VIZ.Framework.Core;assembly=VIZ.Framework.Core"
d:DataContext="{d:DesignInstance Type=local:ChangeNdiStreamViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
......
......@@ -5,8 +5,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:VIZ.GimbalAI.Module"
xmlns:common="clr-namespace:VIZ.GimbalAI.Common;assembly=VIZ.GimbalAI.Common"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core"
xmlns:common="clr-namespace:VIZ.Framework.Common;assembly=VIZ.Framework.Common"
xmlns:converter="clr-namespace:VIZ.Framework.Core;assembly=VIZ.Framework.Core"
mc:Ignorable="d"
d:DesignHeight="520" d:DesignWidth="420">
<UserControl.Resources>
......
......@@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:VIZ.GimbalAI.Module"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core"
xmlns:converter="clr-namespace:VIZ.Framework.Core;assembly=VIZ.Framework.Core"
d:DataContext="{d:DesignInstance Type=local:ControlViewModel}"
mc:Ignorable="d" x:Name="uc"
d:DesignHeight="800" d:DesignWidth="300">
......@@ -61,7 +61,7 @@
<!-- 自动模式参数 -->
<Border Grid.Row="2" Margin="0,10,0,0" IsEnabled="{Binding Path=IsStarted,Mode=OneWay}">
<Grid IsEnabled="{Binding Path=IsAutoSettingEnabled}"
Visibility="{Binding ElementName=rbAuto,Path=IsChecked,Converter={StaticResource Bool2VisibilityConverter}}">
Visibility="{Binding ElementName=rbAuto,Path=IsChecked,Converter={StaticResource Bool2VisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
......
......@@ -12,7 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Connection;
namespace VIZ.GimbalAI.Module
......@@ -29,9 +29,7 @@ namespace VIZ.GimbalAI.Module
if (WPFHelper.IsInDesignMode(this))
return;
ControlViewModel vm = new ControlViewModel();
vm.SetView(this);
this.DataContext = vm;
WPFHelper.BindingViewModel(this, new ControlViewModel());
}
}
}
......@@ -3,12 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Common;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Storage;
using System.Windows;
using System.Windows.Controls;
using VIZ.Framework.Common;
namespace VIZ.GimbalAI.Module
{
......@@ -68,18 +69,20 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void Loaded()
{
if (VideoStreamManager.NDITool == null || VideoStreamManager.NDITool.StreamInfos == null || VideoStreamManager.NDITool.StreamInfos.Count == 0)
NDIStream ndiStream = VideoStreamManager.Get<NDIStream>(NDIViewKeys.Main);
if (ndiStream == null || ndiStream.StreamInfos == null || ndiStream.StreamInfos.Count == 0)
return;
string currentNdiStreamName = VDataDomain.IniStorage.GetValue<NdiConfig, string>(p => p.NDI_STREAM_NAME);
string currentNdiStreamName = ApplicationDomainEx.IniStorage.GetValue<NdiConfig, string>(p => p.NDI_STREAM_NAME);
string groupName = currentNdiStreamName.Split(new char[] { ' ' }, 2)[0];
string streamName = currentNdiStreamName.Substring(currentNdiStreamName.IndexOf(' ') + 1);
List<NdiStreamGroupModel> groupModels = new List<NdiStreamGroupModel>();
lock (VideoStreamManager.NDITool.StreamInfos)
lock (ndiStream.StreamInfos)
{
var groups = VideoStreamManager.NDITool.StreamInfos.GroupBy(p => p.Machine);
var groups = ndiStream.StreamInfos.GroupBy(p => p.Machine);
foreach (var group in groups)
{
......@@ -87,7 +90,7 @@ namespace VIZ.GimbalAI.Module
groupModel.Name = group.Key;
groupModel.DisplayName = group.Key;
foreach (NDIToolStreamInfo info in group)
foreach (NDIStreamInfo info in group)
{
NdiStreamModel model = new NdiStreamModel();
model.Name = info.Name;
......@@ -124,7 +127,7 @@ namespace VIZ.GimbalAI.Module
/// </summary>
public void Apply()
{
string currentNdiStreamName = VDataDomain.IniStorage.GetValue<NdiConfig, string>(p => p.NDI_STREAM_NAME);
string currentNdiStreamName = ApplicationDomainEx.IniStorage.GetValue<NdiConfig, string>(p => p.NDI_STREAM_NAME);
string groupName = currentNdiStreamName.Split(new char[] { ' ' }, 2)[0];
string streamName = currentNdiStreamName.Substring(currentNdiStreamName.IndexOf(' ') + 1);
......@@ -139,7 +142,7 @@ namespace VIZ.GimbalAI.Module
if (groupName == group.Name && streamName == item.Name)
return;
IVideoViewService service = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService service = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (service == null)
return;
......@@ -148,7 +151,7 @@ namespace VIZ.GimbalAI.Module
service.ChangeNdiStream($"{group.Name} {item.Name}");
// ------------------------------------------------------------------------------------------------
// 更新到配置文件
VDataDomain.IniStorage.SetValue<NdiConfig>(p => p.NDI_STREAM_NAME, $"{group.Name} {item.Name}");
ApplicationDomainEx.IniStorage.SetValue<NdiConfig>(p => p.NDI_STREAM_NAME, $"{group.Name} {item.Name}");
// ------------------------------------------------------------------------------------------------
// 刷新UI
NdiStreamGroupModel beforeGroup = this.NdiStreamGroups.FirstOrDefault(p => p.IsCurrentStream);
......@@ -196,6 +199,5 @@ namespace VIZ.GimbalAI.Module
#endregion
// ==============================================================================================
}
}
......@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Storage;
......@@ -47,7 +47,7 @@ namespace VIZ.GimbalAI.Module
this.ItemsSource.Add(new NdiVideoFrameDelayModel($"60 帧", 60));
this.ItemsSource.Add(new NdiVideoFrameDelayModel($"90 帧", 90));
int value = VDataDomain.IniStorage.GetValue<ClientConfig, int>(p => p.CLIENT_VIDEO_DELAY);
int value = ApplicationDomainEx.IniStorage.GetValue<ClientConfig, int>(p => p.CLIENT_VIDEO_DELAY);
NdiVideoFrameDelayModel current = this.ItemsSource.FirstOrDefault(p => p.Value == value);
if (current == null)
......@@ -107,13 +107,13 @@ namespace VIZ.GimbalAI.Module
if (this.SelectedValue == null)
return;
IVideoViewService service = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService service = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (service == null)
return;
service.ChangeNdiVideoFrameDelay(this.SelectedValue.Value);
VDataDomain.IniStorage.SetValue<ClientConfig>(p => p.CLIENT_VIDEO_DELAY, this.SelectedValue.Value);
ApplicationDomainEx.IniStorage.SetValue<ClientConfig>(p => p.CLIENT_VIDEO_DELAY, this.SelectedValue.Value);
foreach (NdiVideoFrameDelayModel model in this.ItemsSource)
{
......
......@@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Connection;
using VIZ.GimbalAI.Domain.Message;
using VIZ.GimbalAI.Domain;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Module
{
......@@ -18,7 +19,7 @@ namespace VIZ.GimbalAI.Module
public ControlViewModel()
{
// 注册视图模型服务
VAppDomain.ViewModelServiceManager.AddService(this);
ApplicationDomainEx.ServiceManager.AddService(ServiceKeys.ControlView, this);
// 初始化数据
this.InitData();
......@@ -48,9 +49,9 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void InitData()
{
this.AlgorithmSceneItems = VDataDomain.AlgorithmAutoSetting.Scenes;
this.AlgorithmScene = VDataDomain.AlgorithmAutoSetting.Scene;
this.AlgorithmClassItems = VDataDomain.AlgorithmAutoSetting.Classes;
this.AlgorithmSceneItems = ApplicationDomainEx.AlgorithmAutoSetting.Scenes;
this.AlgorithmScene = ApplicationDomainEx.AlgorithmAutoSetting.Scene;
this.AlgorithmClassItems = ApplicationDomainEx.AlgorithmAutoSetting.Classes;
}
/// <summary>
......@@ -58,8 +59,8 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void InitMessage()
{
VAppDomain.AlgorithmMessageManager.Register<VideoRenderRectangleMessage>(this, this.VideoRenderRectangle);
VAppDomain.UiMessageManager.Register<AlgorithmInitCompleteMessage>(this, this.AlgorithmInitComplete);
ApplicationDomainEx.MessageManager.Register<VideoRenderRectangleMessage>(this, this.VideoRenderRectangle);
ApplicationDomainEx.MessageManager.Register<AlgorithmInitCompleteMessage>(this, this.AlgorithmInitComplete);
}
// ==============================================================================================
......@@ -164,7 +165,7 @@ namespace VIZ.GimbalAI.Module
{
algorithmScene = value;
this.RaisePropertyChanged(nameof(AlgorithmScene));
VDataDomain.AlgorithmAutoSetting.Scene = value;
ApplicationDomainEx.AlgorithmAutoSetting.Scene = value;
}
}
......@@ -355,7 +356,7 @@ namespace VIZ.GimbalAI.Module
// -------------------------------------------------------------------------------------------------
// UI逻辑调整
IVideoViewService viewService = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService viewService = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (viewService == null)
return;
......@@ -391,7 +392,7 @@ namespace VIZ.GimbalAI.Module
// -------------------------------------------------------------------------------------------------
// UI逻辑调整
IVideoViewService viewService = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService viewService = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (viewService == null)
return;
......@@ -445,7 +446,7 @@ namespace VIZ.GimbalAI.Module
// -------------------------------------------------------------------------------------------------
// UI逻辑调整
IVideoViewService viewService = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService viewService = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (viewService == null)
return;
......
......@@ -54,9 +54,9 @@
</StackPanel>
<!-- 预设区域 -->
<module:PresetView Grid.Row="1"></module:PresetView>
<!--<module:PresetView Grid.Row="1"></module:PresetView>-->
<!-- 视频区域 -->
<module:VideoView Grid.Row="1" Grid.Column="1" Margin="0,0,30,0"></module:VideoView>
<module:VideoView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="15,0,30,0"></module:VideoView>
<!-- 控制区域 -->
<module:ControlView Grid.Row="1" Grid.Column="2"></module:ControlView>
<!-- 底栏 -->
......
......@@ -12,7 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Module
{
......@@ -28,9 +28,7 @@ namespace VIZ.GimbalAI.Module
if (WPFHelper.IsInDesignMode(this))
return;
MainViewModel vm = new MainViewModel();
vm.SetView(this);
this.DataContext = vm;
WPFHelper.BindingViewModel(this, new MainViewModel());
}
}
}
......@@ -6,10 +6,12 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using VIZ.GimbalAI.Connection;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Domain.Message;
using VIZ.GimbalAI.Common;
using VIZ.Framework.Module;
using VIZ.Framework.Common;
namespace VIZ.GimbalAI.Module
{
......@@ -44,7 +46,7 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void InitMessage()
{
VAppDomain.AlgorithmMessageManager.Register<VideoRenderRectangleMessage>(this, this.VideoRenderRectangle);
ApplicationDomainEx.MessageManager.Register<VideoRenderRectangleMessage>(this, this.VideoRenderRectangle);
}
// ======================================================================================
......@@ -96,14 +98,14 @@ namespace VIZ.GimbalAI.Module
private void Loaded()
{
// 加载完成后3秒执行加载流程
VAppDomain.DelayManager.Wait("VIZ.GimbalAI.Module.MainViewModel.Loaded", 3, () =>
ApplicationDomainEx.DelayManager.Wait("VIZ.GimbalAI.Module.MainViewModel.Loaded", 3, () =>
{
// 执行加载流程
AppSetupContext context = AppSetup.Load();
AppSetupContext context = AppSetup.Load(this.GetWindow());
if (!context.IsSuccess)
{
VMessageBox.ShowDialog($"执行 {context.ProviderDetail} 失败");
MessageBoxEx.ShowDialog($"执行 {context.ProviderDetail} 失败");
}
});
}
......@@ -126,8 +128,8 @@ namespace VIZ.GimbalAI.Module
if (view == null)
return;
VMessageBoxResult result = VMessageBox.ShowDialog("提示", "确定退出?", VMessageBoxButtons.YES_CANCEL);
if (result != VMessageBoxResult.YES)
MessageBoxExResult result = MessageBoxEx.ShowDialog("提示", "确定退出?", MessageBoxExButtons.YES_CANCEL);
if (result != MessageBoxExResult.YES)
return;
Window window = WPFHelper.GetAncestorByType<Window>(view);
......@@ -201,13 +203,9 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void ChangeNdiVideoDelay()
{
MainView mainView = this.GetView<MainView>();
if (mainView == null)
return;
ChangeVideoFrameDelayView view = new ChangeVideoFrameDelayView();
NoneWindow window = new NoneWindow(400, 650, view);
window.Owner = WPFHelper.GetAncestorByType<Window>(mainView);
window.Owner = this.GetWindow();
window.ShowDialog();
}
......
......@@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:VIZ.GimbalAI.Module"
xmlns:converter="clr-namespace:VIZ.GimbalAI.Core;assembly=VIZ.GimbalAI.Core"
xmlns:converter="clr-namespace:VIZ.Framework.Core;assembly=VIZ.Framework.Core"
d:DataContext="{d:DesignInstance Type=local:PresetViewModel}"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="400">
......
......@@ -12,7 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VIZ.GimbalAI.Core;
using VIZ.Framework.Core;
namespace VIZ.GimbalAI.Module
{
......@@ -28,9 +28,7 @@ namespace VIZ.GimbalAI.Module
if (WPFHelper.IsInDesignMode(this))
return;
PresetViewModel vm = new PresetViewModel();
vm.SetView(this);
this.DataContext = vm;
WPFHelper.BindingViewModel(this, new PresetViewModel());
}
}
}
......@@ -4,14 +4,16 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.GimbalAI.Core;
using VIZ.GimbalAI.Domain;
using VIZ.GimbalAI.Storage;
using VIZ.GimbalAI.Connection;
using System.Windows;
using log4net;
using System.Drawing.Imaging;
using VIZ.Framework.Core;
using VIZ.GimbalAI.Common;
using VIZ.Framework.Common;
using VIZ.Framework.Connection;
namespace VIZ.GimbalAI.Module
{
......@@ -23,7 +25,7 @@ namespace VIZ.GimbalAI.Module
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(PresetViewModel));
private readonly static ILog log = LogManager.GetLogger(typeof(PresetViewModel));
/// <summary>
/// 延时健
......@@ -49,7 +51,7 @@ namespace VIZ.GimbalAI.Module
{
ObservableCollection<GimbalPresetModel> items = new ObservableCollection<GimbalPresetModel>();
var query = VDataDomain.LiteDbContext.GimbalPresets.FindAll();
var query = ApplicationDomainEx.LiteDbContext.GimbalPresets.FindAll();
Dictionary<int, GimbalPreset> dic = query.ToDictionary(p => p.ID);
for (int i = 1; i <= 4; ++i)
......@@ -93,7 +95,7 @@ namespace VIZ.GimbalAI.Module
/// </summary>
private void InitMessage()
{
VAppDomain.UiMessageManager.Register<GimbalPtzSnapshotMessage>(this, this.GimbalPtzSnapshot);
ApplicationDomainEx.MessageManager.Register<GimbalPtzSnapshotMessage>(this, this.GimbalPtzSnapshot);
}
// ========================================================================================
......@@ -203,7 +205,7 @@ namespace VIZ.GimbalAI.Module
{
if (this.SelectedPreset == null)
{
VMessageBox.ShowDialog("请选择要保存的预设项!");
MessageBoxEx.ShowDialog("请选择要保存的预设项!");
return;
}
......@@ -217,7 +219,7 @@ namespace VIZ.GimbalAI.Module
// -------------------------------------------------------------------------------------------------
// UI调整
IVideoViewService service = VAppDomain.ViewModelServiceManager.GetService<IVideoViewService>();
IVideoViewService service = ApplicationDomainEx.ServiceManager.GetService<IVideoViewService>(ServiceKeys.VideoView);
if (service == null)
return;
......@@ -228,7 +230,7 @@ namespace VIZ.GimbalAI.Module
// 3. 如果在15秒内没有收到恢复那么认为超时
this.IsEnabled = false;
VAppDomain.DelayManager.Wait(DELAY_KEY_PRESET_SAVE, 15, () =>
ApplicationDomainEx.DelayManager.Wait(DELAY_KEY_PRESET_SAVE, 15, () =>
{
this.IsEnabled = true;
});
......@@ -252,22 +254,22 @@ namespace VIZ.GimbalAI.Module
if (model == null)
return;
VMessageBoxResult result = VMessageBox.ShowDialog("提示", $"确定重置云台 预设{model.ID}", VMessageBoxButtons.YES_CANCEL);
if (result != VMessageBoxResult.YES)
MessageBoxExResult result = MessageBoxEx.ShowDialog("提示", $"确定重置云台 预设{model.ID}", MessageBoxExButtons.YES_CANCEL);
if (result != MessageBoxExResult.YES)
return;
model.Bitmap = null;
model.Data = null;
// 更新缓存
GimbalPreset entity = VDataDomain.LiteDbContext.GimbalPresets.FindById(model.ID);
GimbalPreset entity = ApplicationDomainEx.LiteDbContext.GimbalPresets.FindById(model.ID);
if (entity == null)
return;
entity.Data = null;
entity.Bitmap = null;
VDataDomain.LiteDbContext.GimbalPresets.Update(entity);
ApplicationDomainEx.LiteDbContext.GimbalPresets.Update(entity);
}
#endregion
......@@ -304,7 +306,7 @@ namespace VIZ.GimbalAI.Module
/// <param name="msg">消息</param>
private void GimbalPtzSnapshot(GimbalPtzSnapshotMessage msg)
{
VAppDomain.DelayManager.Release(DELAY_KEY_PRESET_SAVE);
ApplicationDomainEx.DelayManager.Release(DELAY_KEY_PRESET_SAVE);
// 该判断处理如果收到恢复超时的情况
if (this.IsEnabled)
......@@ -330,9 +332,9 @@ namespace VIZ.GimbalAI.Module
model.Entity.ID = model.ID;
model.Entity.Data = model.Data;
model.Entity.Bitmap = BitmapHelper.GetBuffer(model.Bitmap, ImageFormat.Jpeg);
//model.Entity.Bitmap = BitmapHelper.GetBuffer(model.Bitmap, ImageFormat.Jpeg);
VDataDomain.LiteDbContext.GimbalPresets.Upsert(model.Entity);
ApplicationDomainEx.LiteDbContext.GimbalPresets.Upsert(model.Entity);
this.IsEnabled = true;
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using log4net;
namespace VIZ.GimbalAI.Module
{
/// <summary>
/// 应用程序启动
/// </summary>
public static class AppSetup
{
/// <summary>
/// 日志
/// </summary>
private static ILog log = LogManager.GetLogger(typeof(AppSetup));
/// <summary>
/// 应用程序启动
/// </summary>
private static List<IAppSetup> appSetups = new List<IAppSetup>();
/// <summary>
/// 应用程序加载
/// </summary>
private static List<IAppSetup> appLoads = new List<IAppSetup>();
/// <summary>
/// 是否已经启动
/// </summary>
public static bool IsSetup { get; private set; }
static AppSetup()
{
// 初始化应用程序启动
InitSetup();
// 初始化应用程序加载
InitLoad();
}
/// <summary>
/// 应用程序启动
/// </summary>
private static void InitSetup()
{
// Step 1. 单例启动
appSetups.Add(new AppSetup_Single());
// Step 2. 捕获未处理异常
appSetups.Add(new AppSetup_CatchUnhandledException());
// Step 3. 初始化日志
appSetups.Add(new AppSetup_LogInit());
// Step 4. 初始化数据域
appSetups.Add(new AppSetup_DtoDoainIInit());
// Step 5. 初始化延时
appSetups.Add(new AppSetup_DelayInit());
// Step 6. 读取算法Excel配置文件
appSetups.Add(new AppSetup_ExcelInit());
// Step 7. 初始化NDI
appSetups.Add(new AppSetup_NdiInit());
// Step 8. 初始化UDP链接
appSetups.Add(new AppSetup_UdpConnectionIInit());
}
/// <summary>
/// 应用程序加载
/// </summary>
private static void InitLoad()
{
// Step 1. 启动算法进程
appLoads.Add(new AppSetup_SetupAlgorithm());
// Step 2. 启动云台进程
//appLoads.Add(new AppSetup_SetupGimbal());
}
/// <summary>
/// 执行
/// </summary>
/// <returns>应用程序启动上下文</returns>
public static AppSetupContext Setup()
{
AppSetupContext context = new AppSetupContext();
if (IsSetup)
{
context.IsSuccess = false;
context.Remarks.Add("app is already setup.");
return context;
}
foreach (IAppSetup setup in appSetups)
{
try
{
if (setup.Setup(context))
continue;
context.IsSuccess = false;
context.ProviderDetail = setup.Detail;
return context;
}
catch (Exception ex)
{
log.Error(ex);
context.IsSuccess = false;
context.ProviderDetail = setup.Detail;
context.Exception = ex;
return context;
}
}
context.IsSuccess = true;
IsSetup = true;
return context;
}
/// <summary>
/// 关闭
/// </summary>
public static void ShutDown()
{
if (!IsSetup)
return;
AppSetupContext context = new AppSetupContext();
foreach (IAppSetup setup in appSetups)
{
try
{
setup.Shutdown(context);
}
catch (Exception ex)
{
log.Error(ex);
}
}
IsSetup = false;
}
/// <summary>
/// 加载
/// </summary>
/// <returns>启动上下文</returns>
public static AppSetupContext Load()
{
AppSetupContext context = new AppSetupContext();
foreach (IAppSetup setup in appLoads)
{
try
{
if (setup.Setup(context))
continue;
context.IsSuccess = false;
context.ProviderDetail = setup.Detail;
return context;
}
catch (Exception ex)
{
log.Error(ex);
context.IsSuccess = false;
context.ProviderDetail = setup.Detail;
context.Exception = ex;
return context;
}
}
context.IsSuccess = true;
return context;
}
/// <summary>
/// 卸载
/// </summary>
public static void UnLoad()
{
AppSetupContext context = new AppSetupContext();
foreach (IAppSetup setup in appLoads)
{
try
{
setup.Shutdown(context);
}
catch (Exception ex)
{
log.Error(ex);
}
}
}
}
}
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