using OpenCvSharp;
namespace SHH.CameraSdk;
///
/// [零延迟核心] 智能帧对象池
/// 功能:预分配并复用 SmartFrame 实例,杜绝频繁 new Mat() 与 GC 回收,消除内存分配停顿
/// 核心策略:
/// 1. 预热分配:启动时创建初始数量帧,避免运行时内存申请
/// 2. 上限控制:最大池大小限制内存占用,防止内存溢出
/// 3. 背压丢帧:池空时返回 null,强制丢帧保证实时性,不阻塞生产端
///
public class FramePool : IDisposable
{
#region --- 私有资源与配置 (Private Resources & Configurations) ---
/// 可用帧队列(线程安全):存储待借出的空闲智能帧
private readonly ConcurrentQueue _availableFrames = new();
/// 所有已分配帧列表:用于统一销毁释放内存
private readonly List _allAllocatedFrames = new();
/// 创建新帧锁:确保多线程下创建新帧的线程安全
private readonly object _lock = new();
/// 帧宽度(与相机输出分辨率一致)
private readonly int _width;
/// 帧高度(与相机输出分辨率一致)
private readonly int _height;
/// 帧数据类型(如 CV_8UC3 对应 RGB 彩色图像)
private readonly MatType _type;
/// 池最大容量:限制最大分配帧数,防止内存占用过高
private readonly int _maxPoolSize;
#endregion
#region --- 构造与预热 (Constructor & Warm-Up) ---
///
/// 初始化智能帧对象池
///
/// 帧宽度
/// 帧高度
/// 帧数据类型
/// 初始预热帧数(默认5)
/// 池最大容量(默认10)
public FramePool(int width, int height, MatType type, int initialSize = 5, int maxSize = 10)
{
_width = width;
_height = height;
_type = type;
_maxPoolSize = maxSize;
// 预热:启动时预分配初始数量帧,避免运行时动态申请内存
for (int i = 0; i < initialSize; i++)
{
CreateNewFrame();
}
}
///
/// 创建新智能帧并加入池(内部调用,加锁保护)
///
private void CreateNewFrame()
{
var frame = new SmartFrame(this, _width, _height, _type);
_allAllocatedFrames.Add(frame);
_availableFrames.Enqueue(frame);
}
#endregion
#region --- 帧借出与归还 (Frame Borrow & Return) ---
///
/// 从池借出一个智能帧(O(1) 时间复杂度)
///
/// 可用智能帧 / 池空且达上限时返回 null(触发背压丢帧)
public SmartFrame Get()
{
// 1. 优先从可用队列取帧,无锁快速路径
if (_availableFrames.TryDequeue(out var frame))
{
frame.Activate();
return frame;
}
// 2. 可用队列为空,检查是否达最大容量
if (_allAllocatedFrames.Count < _maxPoolSize)
{
// 加锁创建新帧,避免多线程重复创建
lock (_lock)
{
// 双重检查:防止等待锁期间其他线程已创建新帧
if (_allAllocatedFrames.Count < _maxPoolSize)
{
CreateNewFrame();
}
}
// 递归重试取帧
return Get();
}
// 3. 背压策略:池空且达上限,返回 null 强制丢帧,保证生产端不阻塞
// 适用场景:消费端处理过慢导致帧堆积,丢帧保实时性
return null;
}
///
/// [系统内部调用] 将帧归还至池(由 SmartFrame.Dispose 自动触发)
///
/// 待归还的智能帧
public void Return(SmartFrame frame)
{
_availableFrames.Enqueue(frame);
}
#endregion
#region --- 资源释放 (Resource Disposal) ---
///
/// 释放帧池所有资源,销毁所有 Mat 内存
///
public void Dispose()
{
// 遍历所有已分配帧,释放 OpenCV Mat 底层内存
foreach (var frame in _allAllocatedFrames)
{
frame.InternalMat.Dispose();
}
_allAllocatedFrames.Clear();
_availableFrames.Clear();
}
#endregion
}