增加本地Cv2.ImShow播放的动态增加、移除的支持

This commit is contained in:
2025-12-26 17:28:07 +08:00
parent 83ad6221a4
commit e98059fd30
5 changed files with 305 additions and 185 deletions

View File

@@ -8,9 +8,11 @@ public class CamerasController : ControllerBase
{
private readonly CameraManager _manager;
public CamerasController(CameraManager manager)
// 构造函数注入管理器
public CamerasController(CameraManager manager, DisplayWindowManager displayManager)
{
_manager = manager;
_displayManager = displayManager;
}
// ==========================================================================
@@ -91,52 +93,6 @@ public class CamerasController : ControllerBase
// 区域 B: 多进程流控订阅 (Subscription Strategy)
// ==========================================================================
/// <summary>
/// 5. 注册/更新进程的流需求 (A/B/C/D 场景核心)
/// </summary>
/// <remarks>
/// 示例场景:
/// - 主进程配置(B): { "appId": "Main_Config", "displayFps": 25, "analysisFps": 0 }
/// - AI进程(C): { "appId": "AI_Core", "displayFps": 0, "analysisFps": 5 }
/// </remarks>
[HttpPost("{id}/subscriptions")]
public IActionResult UpdateSubscription(long id, [FromBody] SubscriptionDto sub)
{
var device = _manager.GetDevice(id);
if (device == null) return NotFound();
// 逻辑转换:将 "显示帧" 和 "分析帧" 映射到底层控制器的注册表
// 1. 处理显示需求
string displayKey = $"{sub.AppId}_Display";
if (sub.DisplayFps > 0)
{
// 告诉控制器:这个 App 需要 X 帧用于显示
device.Controller.Register(displayKey, sub.DisplayFps);
}
else
{
// 如果不需要,移除注册
device.Controller.Unregister(displayKey);
}
// 2. 处理分析需求
string analysisKey = $"{sub.AppId}_Analysis";
if (sub.AnalysisFps > 0)
{
// 告诉控制器:这个 App 需要 Y 帧用于分析
device.Controller.Register(analysisKey, sub.AnalysisFps);
}
else
{
device.Controller.Unregister(analysisKey);
}
// 运维审计
device.AddAuditLog($"更新订阅策略 [{sub.AppId}]: Display={sub.DisplayFps}, Analysis={sub.AnalysisFps}");
return Ok(new { Message = "订阅策略已更新", DeviceId = id });
}
// ==========================================================================
// 区域 C: 句柄动态绑定 (Handle Binding)
@@ -295,4 +251,93 @@ public class CamerasController : ControllerBase
return Ok(subs);
}
private readonly DisplayWindowManager _displayManager; // [新增]
[HttpPost("{id}/subscriptions")]
public IActionResult UpdateSubscription(int id, [FromBody] SubscriptionDto dto)
{
var device = _manager.GetDevice(id);
if (device == null) return NotFound("设备不存在");
if (device is HikVideoSource hikCam)
{
// 1. 更新流控策略 (FrameController)
// 告诉底层:这个 AppId 需要多少帧
int totalFps = dto.DisplayFps + dto.AnalysisFps;
if (totalFps > 0)
{
// 情况 A: 这是一个新增或更新订阅
hikCam.Controller.Register(dto.AppId, totalFps);
// 如果是预览模式,启动窗口
if (dto.DisplayFps > 0)
{
_displayManager.StartDisplay(dto.AppId, id);
}
}
else
{
// 情况 B: 这是一个停止订阅请求 (FPS 为 0)
// 1. 【核心修复】从调度中心物理删除,不再出现在列表中
hikCam.Controller.Unregister(dto.AppId);
// 2. 关闭可能存在的本地窗口
_displayManager.StopDisplay(dto.AppId);
}
return Ok(new { message = "Policy updated", currentConfig = hikCam.Controller.GetCurrentRequirements() });
}
return BadRequest("Device implies no controller");
}
///// <summary>
///// 5. 注册/更新进程的流需求 (A/B/C/D 场景核心)
///// </summary>
///// <remarks>
///// 示例场景:
///// - 主进程配置(B): { "appId": "Main_Config", "displayFps": 25, "analysisFps": 0 }
///// - AI进程(C): { "appId": "AI_Core", "displayFps": 0, "analysisFps": 5 }
///// </remarks>
//[HttpPost("{id}/subscriptions")]
//public IActionResult UpdateSubscription(long id, [FromBody] SubscriptionDto sub)
//{
// var device = _manager.GetDevice(id);
// if (device == null) return NotFound();
// // 逻辑转换:将 "显示帧" 和 "分析帧" 映射到底层控制器的注册表
// // 1. 处理显示需求
// string displayKey = $"{sub.AppId}_Display";
// if (sub.DisplayFps > 0)
// {
// // 告诉控制器:这个 App 需要 X 帧用于显示
// device.Controller.Register(displayKey, sub.DisplayFps);
// }
// else
// {
// // 如果不需要,移除注册
// device.Controller.Unregister(displayKey);
// }
// // 2. 处理分析需求
// string analysisKey = $"{sub.AppId}_Analysis";
// if (sub.AnalysisFps > 0)
// {
// // 告诉控制器:这个 App 需要 Y 帧用于分析
// device.Controller.Register(analysisKey, sub.AnalysisFps);
// }
// else
// {
// device.Controller.Unregister(analysisKey);
// }
// // 运维审计
// device.AddAuditLog($"更新订阅策略 [{sub.AppId}]: Display={sub.DisplayFps}, Analysis={sub.AnalysisFps}");
// return Ok(new { Message = "订阅策略已更新", DeviceId = id });
//}
}