using Serilog;
namespace SHH.CameraSdk;
///
/// [架构基类] 工业级视频源抽象核心 (V3.3.4 严格匹配版)
/// 核心职责:
/// 1. 提供线程安全的生命周期管理(启动/停止/销毁)
/// 2. 实现状态变更的可靠分发与异常隔离
/// 3. 支持配置热更新与动态参数应用
/// 4. 内置 FPS/码率统计、心跳保活、审计日志能力
/// 关键修复记录:
/// ✅ [Bug A] 死锁免疫:所有 await 均添加 ConfigureAwait(false),解除 UI 线程依赖
/// ✅ [Bug π] 管道安全:Dispose 采用优雅关闭策略,确保剩余状态消息被消费
/// ✅ [编译修复] 补全 CloneConfig 中 Transport/VendorArguments 的深拷贝逻辑
///
public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceConnectivity
{
// [新增] 物理在线状态(专门给 Ping 使用)
private volatile bool _isPhysicalOnline;
public bool IsPhysicalOnline => _isPhysicalOnline;
///
/// 图像预处理配置(缩放、增量等)
/// 放置在基类中,确保所有接入协议(HIK/DH/RTSP)均可共享处理逻辑
///
public PreprocessConfig PreprocessSettings { get; set; }
= new PreprocessConfig();
string IDeviceConnectivity.IpAddress => _config.IpAddress;
// 允许哨兵从外部更新 _isOnline 字段
void IDeviceConnectivity.SetNetworkStatus(bool isOnline)
{
if (_isPhysicalOnline != isOnline)
{
_isPhysicalOnline = isOnline;
// 触发状态变更是为了通知 UI 更新绿色小圆点,但不改变 Status
// 注意:这里传 _status 保持原样,只变消息
StatusChanged?.Invoke(this, new StatusChangedEventArgs(_status, isOnline ? "物理网络恢复" : "物理网络中断"));
}
}
protected abstract ILogger _sdkLog { get; }
#region --- 1. 核心配置与锁机制 (Core Config & Locks) ---
///
/// 核心配置对象(支持热更新,去除 readonly 修饰符)
/// 注意:外部修改需通过 UpdateConfig 方法,确保线程安全
///
protected VideoSourceConfig _config;
///
/// 状态同步锁
/// 作用:保护 _status 字段的读写原子性,防止多线程竞争导致状态不一致
///
private readonly object _stateSyncRoot = new();
///
/// 生命周期互斥锁(信号量)
/// 作用:确保 StartAsync/StopAsync/UpdateConfig 串行执行,防止重入导致状态机混乱
/// 配置:初始计数 1,最大计数 1 → 互斥锁
///
private readonly SemaphoreSlim _lifecycleLock = new(1, 1);
#endregion
#region --- 2. 内部状态与基础设施 (Internal States & Infrastructure) ---
/// 设备在线状态标志(volatile 确保多线程可见性)
private volatile bool _isOnline;
/// 视频源核心状态(受 _stateSyncRoot 保护)
private VideoSourceStatus _status = VideoSourceStatus.Disconnected;
///
/// 状态通知有界通道
/// 特性:DropOldest 策略,消费者过载时丢弃旧状态,防止内存溢出
/// 配置:容量 100 | 单读者多写者
///
private readonly Channel _statusQueue;
/// 状态分发器的取消令牌源
private CancellationTokenSource? _distributorCts;
/// 状态分发任务引用(用于 Dispose 时优雅等待)
private Task? _distributorTask;
/// 最后一帧接收的系统 Tick(单调时钟,不受系统时间修改影响)
private long _lastFrameTick = 0;
/// 视频帧回调事件(热路径,低延迟分发)
public event Action