using Serilog; using Ayay.SerilogLogs; namespace SHH.CameraSdk; /// /// [驱动支持层] 大华 SDK 全局资源管理器 /// 职责:统一管理大华 NetSDK 与 PlaySDK 的生命周期与预热 /// public static class DahuaSdkManager { #region --- 全局状态与锁 (Global States & Locks) --- /// /// 全局引用计数器。 /// 只有当计数从 0 变 1 时才进行物理初始化,从 1 变 0 时才物理卸载。 /// private static int _referenceCount = 0; /// /// 静态同步锁。 /// 用于保护 _referenceCount 的原子操作,防止多线程并发 Start/Stop 时导致的初始化冲突。 /// private static readonly object _lock = new(); /// /// 播放库预热状态标记。 /// 用于避免重复执行硬件探测(首次预热后后续直接返回)。 /// private static bool _isWarmedUp = false; #endregion // 静态回调引用,防止被 GC private static fDisConnectCallBack m_DisConnectCallBack = (lLoginID, pchDVRIP, nDVRPort, dwUser) => { }; #region --- SDK 初始化与卸载 (SDK Initialization & Uninstallation) --- /// /// 全局初始化大华 SDK 环境。 /// 此方法是幂等的,内部会自动增加引用计数,支持多线程并发调用。 /// /// 初始化成功返回 true;若 SDK 核心组件(HCNetSDK.dll)加载失败则返回 false。 public static bool Initialize() { lock (_lock) { // 引用计数为 0 时执行物理初始化(仅首次调用时触发) if (_referenceCount == 0) { // [物理初始化] 大华 NetSDK 初始化 // 注意:NETClient.Init 在某些版本下若重复调用会返回 false,需小心处理 try { NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null); // 设置一些全局超时参数,提升工业响应速度 // NETClient.SetConnectTime(3000, 1); } catch { return false; } } _referenceCount++; return true; } } /// /// 全局卸载大华 SDK 环境。 /// 当所有相机实例都停止并释放后(引用计数归 0),会真正释放非托管资源。 /// public static void Uninitialize() { lock (_lock) { if (_referenceCount > 0) { _referenceCount--; if (_referenceCount == 0) { // [物理卸载] 只有在没有实例使用时才彻底 Cleanup // NETClient.Cleanup(); } } } } #endregion #region --- 播放库预热 (PlayCtrl Warm-up) --- /// /// [核心策略] 大华播放库预热 /// 职责:诱发 play.dll 完成底层硬件环境探测,规避取流瞬间的卡顿 /// public static void ForceWarmUp() { if (_isWarmedUp) return; Log.ForContext("SourceContext", LogModules.Core) .Debug("[Dahua] 正在进行大华播放库硬件探测预热..."); Stopwatch sw = Stopwatch.StartNew(); int tempPort = -1; // 诱发点:PLAY_GetFreePort if (DahuaPlaySDK.PLAY_GetFreePort(ref tempPort)) { // 大华的端口释放也必须及时 DahuaPlaySDK.PLAY_ReleasePort(tempPort); } sw.Stop(); _isWarmedUp = true; Log.ForContext("SourceContext", LogModules.Core) .Debug($"[Dahua] 预热完成!耗时: {sw.ElapsedMilliseconds}ms."); } #endregion }