增加本地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

@@ -0,0 +1,63 @@
namespace SHH.CameraSdk;
/// <summary>
/// 动态窗口管理器
/// 职责:根据业务指令动态创建/销毁 OpenCV 播放窗口,并管理流订阅
/// </summary>
public class DisplayWindowManager
{
// 存储活跃的渲染器实例Key = AppId (如 "UI_Preview_Main")
private readonly ConcurrentDictionary<string, FrameConsumer> _activeWindows = new();
/// <summary>
/// 开启一个本地播放窗口
/// </summary>
/// <param name="appId">业务标识 (将作为窗口标题)</param>
/// <param name="deviceId">要观看的设备ID</param>
public void StartDisplay(string appId, int deviceId)
{
// 如果窗口已存在,直接返回(防止重复创建)
if (_activeWindows.ContainsKey(appId)) return;
Console.WriteLine($"[DisplayManager] 正在创建窗口: {appId} -> Device {deviceId}...");
// 1. 动态创建渲染器
var renderer = new FrameConsumer(appId);
// 2. 启动渲染循环 (由于我们之前加了懒加载逻辑,此时不会立即弹窗,直到有帧数据过来)
renderer.Start();
// 3. 存入字典管理
if (_activeWindows.TryAdd(appId, renderer))
{
// 4. 【关键】建立数据订阅:将设备流导向这个渲染器
GlobalStreamDispatcher.Subscribe(appId, deviceId, frame =>
{
// 引用计数 +1防止在渲染前被回收
frame.AddRef();
renderer.Enqueue(frame);
});
}
else
{
renderer.Dispose(); // 并发冲突处理
}
}
/// <summary>
/// 关闭并销毁窗口
/// </summary>
public void StopDisplay(string appId)
{
if (_activeWindows.TryRemove(appId, out var renderer))
{
Console.WriteLine($"[DisplayManager] 正在关闭窗口: {appId}");
// 1. 取消订阅 (停止接收数据)
GlobalStreamDispatcher.Unsubscribe(appId);
// 2. 销毁渲染器 (OpenCV DestroyWindow 会在 FrameConsumer 内部触发)
renderer.Dispose();
}
}
}