Files
Ayay/SHH.CameraSdk/Drivers/DaHua/DahuaSdkManager.cs
2026-01-17 19:17:49 +08:00

118 lines
3.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Serilog;
using Ayay.SerilogLogs;
namespace SHH.CameraSdk;
/// <summary>
/// [驱动支持层] 大华 SDK 全局资源管理器
/// 职责:统一管理大华 NetSDK 与 PlaySDK 的生命周期与预热
/// </summary>
public static class DahuaSdkManager
{
#region --- (Global States & Locks) ---
/// <summary>
/// 全局引用计数器。
/// 只有当计数从 0 变 1 时才进行物理初始化,从 1 变 0 时才物理卸载。
/// </summary>
private static int _referenceCount = 0;
/// <summary>
/// 静态同步锁。
/// 用于保护 _referenceCount 的原子操作,防止多线程并发 Start/Stop 时导致的初始化冲突。
/// </summary>
private static readonly object _lock = new();
/// <summary>
/// 播放库预热状态标记。
/// 用于避免重复执行硬件探测(首次预热后后续直接返回)。
/// </summary>
private static bool _isWarmedUp = false;
#endregion
// 静态回调引用,防止被 GC
private static fDisConnectCallBack m_DisConnectCallBack = (lLoginID, pchDVRIP, nDVRPort, dwUser) => { };
#region --- SDK (SDK Initialization & Uninstallation) ---
/// <summary>
/// 全局初始化大华 SDK 环境。
/// <para>此方法是幂等的,内部会自动增加引用计数,支持多线程并发调用。</para>
/// </summary>
/// <returns>初始化成功返回 true若 SDK 核心组件HCNetSDK.dll加载失败则返回 false。</returns>
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;
}
}
/// <summary>
/// 全局卸载大华 SDK 环境。
/// <para>当所有相机实例都停止并释放后(引用计数归 0会真正释放非托管资源。</para>
/// </summary>
public static void Uninitialize()
{
lock (_lock)
{
if (_referenceCount > 0)
{
_referenceCount--;
if (_referenceCount == 0)
{
// [物理卸载] 只有在没有实例使用时才彻底 Cleanup
// NETClient.Cleanup();
}
}
}
}
#endregion
#region --- (PlayCtrl Warm-up) ---
/// <summary>
/// [核心策略] 大华播放库预热
/// 职责:诱发 play.dll 完成底层硬件环境探测,规避取流瞬间的卡顿
/// </summary>
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
}