feat: 细化OV配置
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -60,8 +60,8 @@ public class UDPClientPool
 | 
			
		||||
        var sendLen = socket.SendTo(buf, endPoint);
 | 
			
		||||
        socket.Close();
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"UDP socket send bytes to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        logger.Debug($"  Original Data: {BitConverter.ToString(buf).Replace("-", " ")}");
 | 
			
		||||
        // logger.Debug($"UDP socket send bytes to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        // logger.Debug($"  Original Data: {BitConverter.ToString(buf).Replace("-", " ")}");
 | 
			
		||||
 | 
			
		||||
        if (sendLen == buf.Length) { return true; }
 | 
			
		||||
        else { return false; }
 | 
			
		||||
@@ -91,9 +91,9 @@ public class UDPClientPool
 | 
			
		||||
        var sendLen = socket.SendTo(sendBytes, endPoint);
 | 
			
		||||
        socket.Close();
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"UDP socket send address package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        logger.Debug($"  Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}");
 | 
			
		||||
        logger.Debug($"  Decoded  Data: {pkg.ToString()}");
 | 
			
		||||
        // logger.Debug($"UDP socket send address package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        // logger.Debug($"  Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}");
 | 
			
		||||
        // logger.Debug($"  Decoded  Data: {pkg.ToString()}");
 | 
			
		||||
 | 
			
		||||
        if (sendLen == sendBytes.Length) { return true; }
 | 
			
		||||
        else { return false; }
 | 
			
		||||
@@ -124,8 +124,8 @@ public class UDPClientPool
 | 
			
		||||
        var sendLen = socket.SendTo(sendBytes, endPoint);
 | 
			
		||||
        socket.Close();
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"UDP socket send data package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        logger.Debug($"  Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}");
 | 
			
		||||
        // logger.Debug($"UDP socket send data package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:");
 | 
			
		||||
        // logger.Debug($"  Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}");
 | 
			
		||||
 | 
			
		||||
        if (sendLen == sendBytes.Length) { return true; }
 | 
			
		||||
        else { return false; }
 | 
			
		||||
 
 | 
			
		||||
@@ -145,7 +145,7 @@ public class UDPServer
 | 
			
		||||
    {
 | 
			
		||||
        UDPData? data = null;
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr}-{taskID} UDP Data");
 | 
			
		||||
        // logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr}-{taskID} UDP Data");
 | 
			
		||||
 | 
			
		||||
        var startTime = DateTime.Now;
 | 
			
		||||
        var isTimeout = false;
 | 
			
		||||
@@ -164,7 +164,7 @@ public class UDPServer
 | 
			
		||||
                    dataQueue.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    data = dataQueue.Dequeue();
 | 
			
		||||
                    logger.Debug($"Find UDP Data: {data.ToString()}");
 | 
			
		||||
                    // logger.Debug($"Find UDP Data: {data.ToString()}");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -212,7 +212,7 @@ public class UDPServer
 | 
			
		||||
                    dataQueue.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    data = dataQueue.ToList();
 | 
			
		||||
                    logger.Debug($"Find UDP Data Array: {JsonConvert.SerializeObject(data)}");
 | 
			
		||||
                    // logger.Debug($"Find UDP Data Array: {JsonConvert.SerializeObject(data)}");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -290,8 +290,8 @@ public class UDPServer
 | 
			
		||||
        // Handle RemoteEP
 | 
			
		||||
        if (remoteEP is null)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Debug($"Receive Data from Unknown at {DateTime.Now.ToString()}:");
 | 
			
		||||
            logger.Debug($"  Original Data : {BitConverter.ToString(bytes).Replace("-", " ")}");
 | 
			
		||||
            // logger.Debug($"Receive Data from Unknown at {DateTime.Now.ToString()}:");
 | 
			
		||||
            // logger.Debug($"  Original Data : {BitConverter.ToString(bytes).Replace("-", " ")}");
 | 
			
		||||
            goto BEGIN_RECEIVE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -395,9 +395,9 @@ public class UDPServer
 | 
			
		||||
            recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"Receive Data from {data.Address}:{data.Port} at {data.DateTime.ToString()}:");
 | 
			
		||||
        logger.Debug($"  Original Data : {BitConverter.ToString(bytes).Replace("-", " ")}");
 | 
			
		||||
        if (recvData.Length != 0) logger.Debug($"  Decoded Data  : {recvData}");
 | 
			
		||||
        // logger.Debug($"Receive Data from {data.Address}:{data.Port} at {data.DateTime.ToString()}:");
 | 
			
		||||
        // logger.Debug($"  Original Data : {BitConverter.ToString(bytes).Replace("-", " ")}");
 | 
			
		||||
        // if (recvData.Length != 0) logger.Debug($"  Decoded Data  : {recvData}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -408,13 +408,13 @@ public class UDPServer
 | 
			
		||||
    {
 | 
			
		||||
        using (udpData.AcquireReadLock())
 | 
			
		||||
        {
 | 
			
		||||
            logger.Debug("Ready Data:");
 | 
			
		||||
            // logger.Debug("Ready Data:");
 | 
			
		||||
 | 
			
		||||
            foreach (var ip in udpData)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var data in ip.Value)
 | 
			
		||||
                {
 | 
			
		||||
                    logger.Debug(data.ToString());
 | 
			
		||||
                    // logger.Debug(data.ToString());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user