支持通过网页增加、删除、修改摄像头配置信息
支持摄像头配置信息中句柄的设置,并实测有效
This commit is contained in:
@@ -267,9 +267,13 @@ public class CameraManager : IDisposable, IAsyncDisposable
|
||||
if (dto.ChannelIndex != null) newConfig.ChannelIndex = dto.ChannelIndex.Value;
|
||||
if (dto.StreamType != null) newConfig.StreamType = dto.StreamType.Value;
|
||||
if (dto.Name != null) newConfig.Name = dto.Name;
|
||||
if (dto.RenderHandle != null) newConfig.RenderHandle = (IntPtr)dto.RenderHandle.Value;
|
||||
if (dto.Brand != null) newConfig.Brand = (DeviceBrand)dto.Brand;
|
||||
|
||||
newConfig.RtspPath = dto.RtspPath;
|
||||
newConfig.MainboardIp = dto.MainboardIp;
|
||||
newConfig.MainboardPort = dto.MainboardPort;
|
||||
newConfig.RenderHandle = dto.RenderHandle;
|
||||
|
||||
// 4. 判定冷热更新
|
||||
bool needColdRestart =
|
||||
newConfig.IpAddress != oldConfig.IpAddress ||
|
||||
@@ -306,7 +310,7 @@ public class CameraManager : IDisposable, IAsyncDisposable
|
||||
var options = new DynamicStreamOptions
|
||||
{
|
||||
StreamType = dto.StreamType,
|
||||
RenderHandle = dto.RenderHandle.HasValue ? (IntPtr)dto.RenderHandle : null
|
||||
RenderHandle = (IntPtr)dto.RenderHandle
|
||||
};
|
||||
device.ApplyOptions(options);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,30 @@ public class FrameController
|
||||
_accumulators.TryRemove(appId, out _);
|
||||
}
|
||||
|
||||
// 修改 Register 方法,接收整个 Requirement 对象或多个参数
|
||||
public void Register(FrameRequirement req)
|
||||
{
|
||||
_requirements.AddOrUpdate(req.AppId,
|
||||
_ => req, // 如果不存在,直接添加整个对象
|
||||
(_, old) =>
|
||||
{
|
||||
// 如果已存在,更新关键业务字段,同时保留统计状态
|
||||
old.TargetFps = req.TargetFps;
|
||||
old.Memo = req.Memo;
|
||||
old.Handle = req.Handle;
|
||||
old.Type = req.Type;
|
||||
old.SavePath = req.SavePath;
|
||||
// 注意:不要覆盖 old.RealFps,保留之前的统计值
|
||||
return old;
|
||||
});
|
||||
|
||||
// 如果是降频(<=20),确保积分器存在
|
||||
if (req.TargetFps <= 20)
|
||||
{
|
||||
_accumulators.GetOrAdd(req.AppId, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister(string appId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(appId)) return;
|
||||
@@ -100,6 +124,9 @@ public class FrameController
|
||||
// 扣除成本,保留余数 (余数是精度的关键)
|
||||
acc -= LOGICAL_BASE_FPS;
|
||||
|
||||
// 【核心修复】在此处触发统计,RealFps 才会开始跳动
|
||||
req.UpdateRealFps();
|
||||
|
||||
req.LastCaptureTick = currentTick;
|
||||
}
|
||||
|
||||
@@ -120,6 +147,6 @@ public class FrameController
|
||||
// ---------------------------------------------------------
|
||||
public List<dynamic> GetCurrentRequirements()
|
||||
{
|
||||
return _requirements.Values.Select(r => new { r.AppId, r.TargetFps, LastActive = r.LastCaptureTick }).ToList<dynamic>();
|
||||
return _requirements.Values.Select(r => new { r.AppId, r.TargetFps, r.RealFps, LastActive = r.LastCaptureTick, r.Memo, r.SavePath, r.Handle, r.TargetIp, r.TargetPort, r.Protocol, r.Type }).ToList<dynamic>();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,36 @@
|
||||
/// </summary>
|
||||
public class FrameRequirement
|
||||
{
|
||||
public FrameRequirement()
|
||||
{
|
||||
}
|
||||
|
||||
public FrameRequirement(SubscriptionDto dto)
|
||||
{
|
||||
// 1. 核心标识
|
||||
this.AppId = dto.AppId;
|
||||
this.Type = dto.Type;
|
||||
|
||||
// 2. 流控参数
|
||||
this.TargetFps = dto.DisplayFps;
|
||||
|
||||
// 3. 业务动态参数
|
||||
this.Memo = dto.Memo;
|
||||
this.Handle = dto.Handle;
|
||||
this.RecordDuration = dto.RecordDuration;
|
||||
this.SavePath = dto.SavePath;
|
||||
|
||||
// 4. 网络转发相关参数 (补全)
|
||||
this.Protocol = dto.Protocol;
|
||||
this.TargetIp = dto.TargetIp;
|
||||
this.TargetPort = dto.TargetPort;
|
||||
|
||||
// 5. 初始化内部统计状态
|
||||
this.LastCaptureTick = Environment.TickCount64;
|
||||
this._lastFpsCalcTick = Environment.TickCount64;
|
||||
this.IsActive = true;
|
||||
}
|
||||
|
||||
#region --- 订阅者核心标识 (Subscriber Core Identification) ---
|
||||
|
||||
/// <summary> 订阅者唯一ID(如 "Client_A"、"AI_Service"、"WPF_Display_Main") </summary>
|
||||
@@ -81,16 +111,20 @@ public class FrameRequirement
|
||||
/// <remarks> 每当成功分发一帧后调用,内部自动按秒计算 RealFps </remarks>
|
||||
public void UpdateRealFps()
|
||||
{
|
||||
_frameCount++;
|
||||
long currentTick = Environment.TickCount64;
|
||||
long elapsed = currentTick - _lastFpsCalcTick;
|
||||
|
||||
if (elapsed >= 1000) // 达到 1 秒周期
|
||||
try
|
||||
{
|
||||
RealFps = Math.Round(_frameCount / (elapsed / 1000.0), 1);
|
||||
_frameCount = 0;
|
||||
_lastFpsCalcTick = currentTick;
|
||||
_frameCount++;
|
||||
long currentTick = Environment.TickCount64;
|
||||
long elapsed = currentTick - _lastFpsCalcTick;
|
||||
|
||||
if (elapsed >= 1000) // 达到 1 秒周期
|
||||
{
|
||||
RealFps = Math.Round(_frameCount / (elapsed / 1000.0), 1);
|
||||
_frameCount = 0;
|
||||
_lastFpsCalcTick = currentTick;
|
||||
}
|
||||
}
|
||||
catch{ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -28,7 +28,7 @@ public class EnhanceWorker : BaseWorker
|
||||
var options = _configManager.GetOptions(deviceId);
|
||||
|
||||
// 2. 检查开关:如果没开启增强,直接跳过
|
||||
if (!options.EnableEnhance) return;
|
||||
if (!options.EnableBrightness) return;
|
||||
|
||||
// 3. 确定操作对象
|
||||
// 策略:如果上一站生成了 TargetMat (缩放图),我们处理缩放图;
|
||||
@@ -36,22 +36,16 @@ public class EnhanceWorker : BaseWorker
|
||||
// 通常 UI 预览场景下,如果不缩放,直接处理 4K 原图会非常卡。
|
||||
// 建议:仅当 TargetMat 存在时处理,或者强制 clone 一份原图作为 TargetMat
|
||||
|
||||
Mat srcMat = frame.TargetMat;
|
||||
bool createdNew = false;
|
||||
|
||||
// 如果没有 TargetMat (上一站透传了),但开启了增亮
|
||||
// 我们必须基于原图生成一个 TargetMat,否则下游 UI 拿不到处理结果
|
||||
if (srcMat == null || srcMat.IsDisposed)
|
||||
{
|
||||
// 注意:处理 4K 原图非常耗时,生产环境建议这里做个限制
|
||||
Mat srcMat;
|
||||
if (frame.TargetMat != null)
|
||||
srcMat = frame.TargetMat;
|
||||
else
|
||||
srcMat = frame.InternalMat;
|
||||
createdNew = true; // 标记我们需要 Attach 新的
|
||||
}
|
||||
|
||||
// 4. 执行增亮
|
||||
Mat brightMat = new Mat();
|
||||
// Alpha=1.0, Beta=配置值
|
||||
srcMat.ConvertTo(brightMat, -1, 1.0, options.BrightnessLevel);
|
||||
srcMat.ConvertTo(brightMat, -1, 1.0, options.Brightness);
|
||||
|
||||
// 5. 挂载结果
|
||||
// 这会自动释放上一站生成的旧 TargetMat (如果存在)
|
||||
|
||||
@@ -31,9 +31,12 @@ namespace SHH.CameraSdk
|
||||
// 1. 获取实时配置 (极快,内存读取)
|
||||
var options = _configManager.GetOptions(deviceId);
|
||||
|
||||
Mat sourceMat = frame.InternalMat;
|
||||
if (sourceMat.Empty()) return;
|
||||
|
||||
// 2. 原始尺寸
|
||||
int srcW = frame.InternalMat.Width;
|
||||
int srcH = frame.InternalMat.Height;
|
||||
int srcW = sourceMat.Width;
|
||||
int srcH = sourceMat.Height;
|
||||
|
||||
// 3. 目标尺寸
|
||||
int targetW = options.TargetWidth;
|
||||
|
||||
@@ -32,6 +32,6 @@ public class ProcessingConfigManager
|
||||
|
||||
Console.WriteLine($"[ConfigManager] 设备 {deviceId} 预处理参数已更新: " +
|
||||
$"Expand={newOptions.EnableExpand} Shrink:{newOptions.EnableShrink} 分辨率:({newOptions.TargetWidth}x{newOptions.TargetHeight}), " +
|
||||
$"Enhance={newOptions.EnableEnhance}");
|
||||
$"EnableBrightness}}={newOptions.EnableBrightness}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user