修复 Bug
This commit is contained in:
@@ -9,7 +9,7 @@ namespace SHH.CameraSdk;
|
||||
/// </summary>
|
||||
public class SmartFrame : IDisposable
|
||||
{
|
||||
public List<string> SubscriberIds { get; } = new List<string>(16);
|
||||
public ConcurrentQueue<string> SubscriberIds { get; } = new ConcurrentQueue<string>();
|
||||
|
||||
#region --- 私有资源与状态 (Private Resources & States) ---
|
||||
|
||||
@@ -114,6 +114,8 @@ public class SmartFrame : IDisposable
|
||||
ScaleType = scaleType;
|
||||
}
|
||||
|
||||
private readonly object _subscriberLock = new(); // 建议在类头部定义此锁
|
||||
|
||||
/// <summary>
|
||||
/// 内部清理:释放衍生数据
|
||||
/// </summary>
|
||||
@@ -126,9 +128,14 @@ public class SmartFrame : IDisposable
|
||||
}
|
||||
ScaleType = FrameScaleType.None;
|
||||
|
||||
// 2. [核心逻辑] 清空订阅者列表
|
||||
// 注意:Clear() 只是把 Count 设为 0,底层数组容量不变,不会触发 GC
|
||||
SubscriberIds.Clear();
|
||||
// 2. [核心逻辑] 线程安全地清空订阅者列表
|
||||
// 使用 lock 确保在 Clear 的瞬间,没有其他分发线程正在执行 Add 操作
|
||||
lock (_subscriberLock)
|
||||
{
|
||||
// 注意:Clear() 只是把 Count 设为 0,底层数组容量 (Capacity) 不变
|
||||
// 这样下次复用时,SubscriberIds 不需要重新分配内存,完美符合零拷贝初衷
|
||||
SubscriberIds.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -158,7 +158,7 @@ public class HikVideoSource : BaseVideoSource,
|
||||
throw new CameraException(HikErrorMapper.Map(err), $"预览失败: {err}", DeviceBrand.HikVision, (int)err);
|
||||
}
|
||||
|
||||
_sdkLog.Debug($"[SDK] Hik 网络取流成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
|
||||
_sdkLog.Information($"[SDK] Hik 网络取流成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
|
||||
AddAuditLog($"[SDK] Hik 网络取流成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -506,7 +506,8 @@ public class HikVideoSource : BaseVideoSource,
|
||||
Cv2.CvtColor(rawYuvWrapper, smartFrame.InternalMat, ColorConversionCodes.YUV2BGR_YV12);
|
||||
}
|
||||
|
||||
smartFrame.SubscriberIds.AddRange(decision.TargetAppIds);
|
||||
foreach(var targetAppId in decision.TargetAppIds)
|
||||
smartFrame.SubscriberIds.Enqueue(targetAppId);
|
||||
|
||||
// =========================================================================
|
||||
// 【修正】删除这里的 GlobalStreamDispatcher.Dispatch!
|
||||
@@ -530,13 +531,10 @@ public class HikVideoSource : BaseVideoSource,
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 【核心修复】
|
||||
// 只有当分发失败(异常)时,驱动层才负责回收。
|
||||
// 一旦分发成功,所有权属于 GlobalProcessingCenter,驱动层严禁 Dispose。
|
||||
if (!handoverSuccess && smartFrame != null)
|
||||
{
|
||||
smartFrame.Dispose();
|
||||
}
|
||||
// Optimized: [原因] 驱动层必须释放它持有的初始引用。
|
||||
// 如果 Dispatch 内部已经 AddRef,此处 Dispose 只会让计数从 2 降到 1,帧不会回池。
|
||||
// 如果没有其他人持有,此处 Dispose 会让计数从 1 降到 0,帧安全回池。
|
||||
smartFrame?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user