增加大华驱动
This commit is contained in:
118
SHH.CameraSdk/Drivers/DaHua/DahuaSdkManager.cs
Normal file
118
SHH.CameraSdk/Drivers/DaHua/DahuaSdkManager.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user