namespace SHH.CameraSdk; /// /// 动态窗口管理器 /// 职责:根据业务指令动态创建/销毁 OpenCV 播放窗口,并管理流订阅 /// public class DisplayWindowManager { // 存储活跃的渲染器实例:Key = AppId (如 "UI_Preview_Main") private readonly ConcurrentDictionary _activeWindows = new(); /// /// 开启一个本地播放窗口 /// /// 业务标识 (将作为窗口标题) /// 要观看的设备ID 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(); // 并发冲突处理 } } /// /// 关闭并销毁窗口 /// 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(); } } }