核心代码格式化

This commit is contained in:
2026-01-17 14:03:33 +08:00
parent 8482996a94
commit e06c60968d
2 changed files with 409 additions and 315 deletions

View File

@@ -8,85 +8,69 @@ using System.Security;
namespace SHH.CameraSdk;
/// <summary>
/// [海康驱动] 工业级视频源实现 V3.4.0 (运维增强版)
/// 修复记录:
/// 1. [Fix Bug Z] 控制器遮蔽:移除子类 Controller 定义,复用基类实例,修复 FPS 控制失效问题。
/// 2. [Feat A] 热更新支持:实现 OnApplyOptions支持码流/句柄不亦断线热切换。
/// 3. [Feat B] 审计集成:全面接入 AddAuditLog对接 Web 运维仪表盘。
/// [海康驱动] 工业级视频源实现 V3.5.0 (运维增强版)
/// <para>技术支撑:基于 Hikvision CH-NetSDK V6.1.x 开发</para>
/// <para>核心职责:深度封装海康私有协议,实现从原始私有码流到 BGR 零拷贝帧池的高性能转换与分发</para>
/// 关键修复与增强记录:
/// <para>✅ 1. [Fix Bug Z] 架构修正:移除子类冗余的 Controller 定义,强制复用基类 <see cref="BaseVideoSource.Controller"/>,彻底修复多路并发下的 FPS 流控失效问题</para>
/// <para>✅ 2. [Feat A] 热更新支持:重写 <see cref="OnApplyOptions"/>,实现码流类型(Main/Sub)与渲染句柄的动态热切换,无需重启设备链路即可生效</para>
/// <para>✅ 3. [Feat B] 运维集成:全链路接入 <see cref="BaseVideoSource.AddAuditLog"/>,将登录、取流、重连及 SDK 报警实时推送至 Web 运维仪表盘</para>
/// <para>✅ 4. [Feat C] 性能优化:在解码回调中使用 <see cref="Monitor.TryEnter"/> 竞争锁,有效规避在设备断开瞬间可能产生的驱动层死锁</para>
/// </summary>
public class HikVideoSource : BaseVideoSource,
IHikContext, ITimeSyncFeature, IRebootFeature, IPtzFeature
{
#region --- (Global Resources) ---
#region --- 1. (Static Resources) ---
// 日志实例
/// <summary> 海康 SDK 专用日志实例 </summary>
protected override ILogger _sdkLog => Log.ForContext("SourceContext", LogModules.HikVisionSdk);
// 静态路由表
/// <summary> 全局句柄映射表:用于静态异常回调分发至具体实例 </summary>
private static readonly ConcurrentDictionary<int, HikVideoSource> _instances = new();
// 全局异常回调
/// <summary> 静态异常回调委托引用 </summary>
private static readonly HikNativeMethods.EXCEPTION_CALLBACK _globalExceptionCallback = StaticOnSdkException;
// 端口抢占锁
/// <summary> 全局播放端口抢占锁 </summary>
private static readonly object _globalPortLock = new();
#endregion
// 声明组件
#region --- 2. (Instance Members) ---
// 协议功能组件
private readonly HikTimeSyncProvider _timeProvider;
private readonly HikRebootProvider _rebootProvider;
private readonly HikPtzProvider _ptzProvider;
// ==========================================
// 实现 IHikContext (核心数据暴露)
// ==========================================
public int GetUserId() => _userId; // 暴露父类或私有的 _userId
public string GetDeviceIp() => Config.IpAddress;
// ==========================================
// 实现 ITimeSyncFeature (路由转发)
// ==========================================
// 核心逻辑:全部委托给 _timeProvider 处理,自己不写一行逻辑
public Task<DateTime> GetTimeAsync() => _timeProvider.GetTimeAsync();
public Task SetTimeAsync(DateTime time) => _timeProvider.SetTimeAsync(time);
public Task RebootAsync() => _rebootProvider.RebootAsync();
public Task PtzControlAsync(PtzAction action, bool stop, int speed = 4)
=> _ptzProvider.PtzControlAsync(action, stop, speed);
public Task PtzStepAsync(PtzAction action, int durationMs, int speed = 4)
=> _ptzProvider.PtzStepAsync(action, durationMs, speed);
#region --- (Instance Members) ---
// SDK 句柄与资源
private int _userId = -1; // SDK 登录句柄
private int _realPlayHandle = -1; // 预览句柄
private int _playPort = -1; // 播放端口
private readonly object _initLock = new();
private readonly object _bufferLock = new();
// 同步控制
private readonly object _initLock = new(); // 登录句柄初始化锁
private readonly object _bufferLock = new(); // 帧缓冲锁
private volatile int _connectionEpoch = 0; // 连接轮询版本号
private volatile int _connectionEpoch = 0;
// 回调委托引用 (防止GC)
// 回调委托强引用防止GC回收
private HikNativeMethods.REALDATACALLBACK? _realDataCallBack;
private HikPlayMethods.DECCBFUN? _decCallBack;
// 内存复用对象
// 图像处理资源, 内存复用对象
private Mat? _sharedYuvMat;
private Mat? _sharedBgrMat; // (如有需要可复用当前逻辑直接用FramePool)
private Mat? _sharedBgrMat;
private FramePool? _framePool;
private bool _isPoolReady = false;
// 【关键修复 Bug Z】: 删除了这里原本的 "public FrameController Controller..."
// 直接使用 BaseVideoSource.Controller
#endregion
#region --- (Constructor) ---
#region --- 3. (Constructor) ---
/// <summary>
/// 海康视频源实现
/// </summary>
/// <param name="config"></param>
public HikVideoSource(VideoSourceConfig config) : base(config)
{
// 初始化组件,将 "this" 作为上下文传进去
@@ -97,8 +81,70 @@ public class HikVideoSource : BaseVideoSource,
#endregion
#region --- (Core Lifecycle) ---
#region --- 4. IHikContext & Features (Interface Impls) ---
/// <summary>
/// 获取登录句柄
/// </summary>
/// <returns></returns>
public int GetUserId() => _userId; // 暴露父类或私有的 _userId
/// <summary>
/// 获取设备IP
/// </summary>
/// <returns></returns>
public string GetDeviceIp() => Config.IpAddress;
/// <summary>
/// 核心逻辑:全部委托给 _timeProvider 处理,自己不写一行逻辑
/// </summary>
/// <returns></returns>
public Task<DateTime> GetTimeAsync() => _timeProvider.GetTimeAsync();
/// <summary>
/// 设置设备时间
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public Task SetTimeAsync(DateTime time) => _timeProvider.SetTimeAsync(time);
/// <summary>
/// 重启设备
/// </summary>
/// <returns></returns>
public Task RebootAsync() => _rebootProvider.RebootAsync();
/// <summary>
/// PTZ 控制
/// </summary>
/// <param name="action"></param>
/// <param name="stop"></param>
/// <param name="speed"></param>
/// <returns></returns>
public Task PtzControlAsync(PtzAction action, bool stop, int speed = 4)
=> _ptzProvider.PtzControlAsync(action, stop, speed);
/// <summary>
/// PTZ 步长
/// </summary>
/// <param name="action"></param>
/// <param name="durationMs"></param>
/// <param name="speed"></param>
/// <returns></returns>
public Task PtzStepAsync(PtzAction action, int durationMs, int speed = 4)
=> _ptzProvider.PtzStepAsync(action, durationMs, speed);
#endregion
#region --- 5. (Lifecycle Overrides) ---
/// <summary>
/// 启动逻辑
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="CameraException"></exception>
/// <exception cref="OperationCanceledException"></exception>
protected override async Task OnStartAsync(CancellationToken token)
{
int currentEpoch = Interlocked.Increment(ref _connectionEpoch);
@@ -171,6 +217,10 @@ public class HikVideoSource : BaseVideoSource,
}, token);
}
/// <summary>
/// 停止逻辑
/// </summary>
/// <returns></returns>
protected override async Task OnStopAsync()
{
Interlocked.Increment(ref _connectionEpoch);
@@ -184,6 +234,9 @@ public class HikVideoSource : BaseVideoSource,
AddAuditLog($"[SDK] Hik 设备已停止. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
}
/// <summary>
/// 同步清理所有 SDK 资源
/// </summary>
private void CleanupSync()
{
lock (_initLock)
@@ -268,11 +321,20 @@ public class HikVideoSource : BaseVideoSource,
}
}
/// <summary>
/// 获取设备元数据
/// </summary>
/// <returns></returns>
protected override Task<DeviceMetadata> OnFetchMetadataAsync() => Task.FromResult(new DeviceMetadata());
#endregion
#region --- [] (Hot Swap) ---
#region --- 6. (OnApplyOptions) ---
// 【关键修复 Feat A】实现基类的抽象方法处理码流切换
/// <summary>
/// 配置更新
/// </summary>
/// <param name="options"></param>
protected override void OnApplyOptions(DynamicStreamOptions options)
{
// 1. 码流热切换逻辑
@@ -343,8 +405,12 @@ public class HikVideoSource : BaseVideoSource,
#endregion
#region --- (Network Streaming) ---
#region --- 7. (Streaming & Decoding) ---
/// <summary>
/// 开始预览
/// </summary>
/// <returns></returns>
private bool StartRealPlay()
{
var previewInfo = new HikNativeMethods.NET_DVR_PREVIEWINFO
@@ -361,6 +427,14 @@ public class HikVideoSource : BaseVideoSource,
return _realPlayHandle >= 0;
}
/// <summary>
/// 预览数据回调
/// </summary>
/// <param name="lRealHandle"></param>
/// <param name="dwDataType"></param>
/// <param name="pBuffer"></param>
/// <param name="dwBufSize"></param>
/// <param name="pUser"></param>
private void SafeOnRealDataReceived(int lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser)
{
try
@@ -414,11 +488,15 @@ public class HikVideoSource : BaseVideoSource,
}
}
#endregion
#region --- (Decoding) ---
// 必须同时加上 SecurityCritical
/// <summary>
/// 必须同时加上 SecurityCritical
/// </summary>
/// <param name="nPort"></param>
/// <param name="pBuf"></param>
/// <param name="nSize"></param>
/// <param name="pFrameInfo"></param>
/// <param name="nReserved1"></param>
/// <param name="nReserved2"></param>
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private void SafeOnDecodingCallBack(int nPort, IntPtr pBuf, int nSize, ref HikPlayMethods.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2)
@@ -536,8 +614,15 @@ public class HikVideoSource : BaseVideoSource,
#endregion
#region --- ---
#region --- 8. ---
/// <summary>
/// SDK 报警回调
/// </summary>
/// <param name="dwType"></param>
/// <param name="lUserID"></param>
/// <param name="lHandle"></param>
/// <param name="pUser"></param>
private static void StaticOnSdkException(uint dwType, int lUserID, int lHandle, IntPtr pUser)
{
try
@@ -558,6 +643,4 @@ public class HikVideoSource : BaseVideoSource,
}
#endregion
protected override Task<DeviceMetadata> OnFetchMetadataAsync() => Task.FromResult(new DeviceMetadata());
}