feat: 细化OV配置
This commit is contained in:
@@ -82,8 +82,8 @@ public class HttpVideoStreamService : BackgroundService
|
||||
private HttpListener? _httpListener;
|
||||
private readonly int _serverPort = 8080;
|
||||
private readonly int _frameRate = 30; // 30 FPS
|
||||
private readonly int _frameWidth = 640;
|
||||
private readonly int _frameHeight = 480;
|
||||
private readonly int _frameWidth = 1280;
|
||||
private readonly int _frameHeight = 720;
|
||||
|
||||
// 摄像头客户端
|
||||
private Camera? _camera;
|
||||
@@ -559,21 +559,59 @@ public class HttpVideoStreamService : BackgroundService
|
||||
private async Task GenerateVideoFrames(CancellationToken cancellationToken)
|
||||
{
|
||||
var frameInterval = TimeSpan.FromMilliseconds(1000.0 / _frameRate);
|
||||
var lastFrameTime = DateTime.UtcNow;
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested && _cameraEnable)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从 FPGA 获取图像数据(模拟)
|
||||
var frameStartTime = DateTime.UtcNow;
|
||||
|
||||
// 从 FPGA 获取图像数据
|
||||
var imageData = await GetFPGAImageData();
|
||||
|
||||
// 向所有连接的客户端发送帧
|
||||
await BroadcastFrameAsync(imageData, cancellationToken);
|
||||
var imageAcquireTime = DateTime.UtcNow;
|
||||
|
||||
_frameCounter++;
|
||||
// 如果有图像数据,立即开始广播(不等待)
|
||||
if (imageData != null && imageData.Length > 0)
|
||||
{
|
||||
// 异步广播帧,不阻塞下一帧的获取
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await BroadcastFrameAsync(imageData, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "异步广播帧时发生错误");
|
||||
}
|
||||
}, cancellationToken);
|
||||
|
||||
// 等待下一帧
|
||||
await Task.Delay(frameInterval, cancellationToken);
|
||||
_frameCounter++;
|
||||
|
||||
var frameEndTime = DateTime.UtcNow;
|
||||
var frameProcessingTime = (frameEndTime - frameStartTime).TotalMilliseconds;
|
||||
var imageAcquireElapsed = (imageAcquireTime - frameStartTime).TotalMilliseconds;
|
||||
|
||||
if (_frameCounter % 30 == 0) // 每秒记录一次性能信息
|
||||
{
|
||||
logger.Debug("帧 {FrameNumber} 性能统计 - 图像获取: {AcquireTime:F1}ms, 总处理: {ProcessTime:F1}ms",
|
||||
_frameCounter, imageAcquireElapsed, frameProcessingTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 动态调整延迟 - 基于实际处理时间
|
||||
var elapsed = (DateTime.UtcNow - lastFrameTime).TotalMilliseconds;
|
||||
var targetInterval = frameInterval.TotalMilliseconds;
|
||||
var remainingDelay = Math.Max(0, targetInterval - elapsed);
|
||||
|
||||
if (remainingDelay > 0)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(remainingDelay), cancellationToken);
|
||||
}
|
||||
|
||||
lastFrameTime = DateTime.UtcNow;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -582,7 +620,7 @@ public class HttpVideoStreamService : BackgroundService
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "生成视频帧时发生错误");
|
||||
await Task.Delay(1000, cancellationToken); // 错误恢复延迟
|
||||
await Task.Delay(100, cancellationToken); // 减少错误恢复延迟
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -593,6 +631,7 @@ public class HttpVideoStreamService : BackgroundService
|
||||
/// </summary>
|
||||
private async Task<byte[]> GetFPGAImageData()
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
Camera? currentCamera = null;
|
||||
|
||||
lock (_cameraLock)
|
||||
@@ -609,7 +648,10 @@ public class HttpVideoStreamService : BackgroundService
|
||||
try
|
||||
{
|
||||
// 从摄像头读取帧数据
|
||||
var readStartTime = DateTime.UtcNow;
|
||||
var result = await currentCamera.ReadFrame();
|
||||
var readEndTime = DateTime.UtcNow;
|
||||
var readTime = (readEndTime - readStartTime).TotalMilliseconds;
|
||||
|
||||
if (!result.IsSuccessful)
|
||||
{
|
||||
@@ -627,17 +669,23 @@ public class HttpVideoStreamService : BackgroundService
|
||||
}
|
||||
|
||||
// 将 RGB565 转换为 RGB24
|
||||
var convertStartTime = DateTime.UtcNow;
|
||||
var rgb24Result = Common.Image.ConvertRGB565ToRGB24(rgb565Data, _frameWidth, _frameHeight, isLittleEndian: false);
|
||||
var convertEndTime = DateTime.UtcNow;
|
||||
var convertTime = (convertEndTime - convertStartTime).TotalMilliseconds;
|
||||
|
||||
if (!rgb24Result.IsSuccessful)
|
||||
{
|
||||
logger.Error("RGB565转RGB24失败: {Error}", rgb24Result.Error);
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
var totalTime = (DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
if (_frameCounter % 30 == 0) // 每秒更新一次日志
|
||||
{
|
||||
logger.Debug("成功获取第 {FrameNumber} 帧,RGB565大小: {RGB565Size} 字节, RGB24大小: {RGB24Size} 字节",
|
||||
_frameCounter, rgb565Data.Length, rgb24Result.Value.Length);
|
||||
logger.Debug("帧 {FrameNumber} 数据获取性能 - 读取: {ReadTime:F1}ms, 转换: {ConvertTime:F1}ms, 总计: {TotalTime:F1}ms, RGB565: {RGB565Size} 字节, RGB24: {RGB24Size} 字节",
|
||||
_frameCounter, readTime, convertTime, totalTime, rgb565Data.Length, rgb24Result.Value.Length);
|
||||
}
|
||||
|
||||
return rgb24Result.Value;
|
||||
@@ -688,8 +736,8 @@ public class HttpVideoStreamService : BackgroundService
|
||||
return; // 没有活跃客户端
|
||||
}
|
||||
|
||||
// 向每个活跃的客户端发送帧
|
||||
foreach (var client in clientsToProcess)
|
||||
// 向每个活跃的客户端并行发送帧
|
||||
var sendTasks = clientsToProcess.Select(async client =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -705,19 +753,33 @@ public class HttpVideoStreamService : BackgroundService
|
||||
// 确保数据立即发送
|
||||
await client.OutputStream.FlushAsync(cancellationToken);
|
||||
|
||||
if (_frameCounter % 30 == 0) // 每秒记录一次日志
|
||||
{
|
||||
logger.Debug("已向客户端 {ClientId} 发送第 {FrameNumber} 帧,大小:{Size} 字节",
|
||||
client.OutputStream.GetHashCode(), _frameCounter, jpegData.Length);
|
||||
}
|
||||
return (client, success: true, error: (Exception?)null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Debug("发送帧数据时出错: {Error}", ex.Message);
|
||||
return (client, success: false, error: ex);
|
||||
}
|
||||
});
|
||||
|
||||
// 等待所有发送任务完成
|
||||
var results = await Task.WhenAll(sendTasks);
|
||||
|
||||
// 处理发送结果
|
||||
foreach (var (client, success, error) in results)
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
logger.Debug("发送帧数据时出错: {Error}", error?.Message ?? "未知错误");
|
||||
clientsToRemove.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (_frameCounter % 30 == 0 && clientsToProcess.Count > 0) // 每秒记录一次日志
|
||||
{
|
||||
logger.Debug("已向 {ClientCount} 个客户端发送第 {FrameNumber} 帧,大小:{Size} 字节",
|
||||
clientsToProcess.Count, _frameCounter, jpegData.Length);
|
||||
}
|
||||
|
||||
// 移除断开连接的客户端
|
||||
if (clientsToRemove.Count > 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user