From 8396b7aaea445032ee99d24a08231269603b235a Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Mon, 4 Aug 2025 17:00:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81HDMI=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E4=BC=A0=E8=BE=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/HdmiVideoStreamController.cs | 34 ++++++++++++++ .../Services/HttpHdmiVideoStreamService.cs | 44 ++++++++++++------- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/server/src/Controllers/HdmiVideoStreamController.cs b/server/src/Controllers/HdmiVideoStreamController.cs index 82025a2..396af2d 100644 --- a/server/src/Controllers/HdmiVideoStreamController.cs +++ b/server/src/Controllers/HdmiVideoStreamController.cs @@ -60,4 +60,38 @@ public class HdmiVideoStreamController : ControllerBase var endpoint = _videoStreamService.GetVideoEndpoint(boardId.ToString()); return Ok(endpoint); } + + // 禁用指定板子的 HDMI 传输 + [HttpPost("DisableHdmiTransmission")] + [Authorize] + public async Task DisableHdmiTransmission() + { + var userName = User.FindFirstValue(ClaimTypes.Name); + if (string.IsNullOrEmpty(userName)) + return Unauthorized("User name not found in claims."); + + var db = new AppDataConnection(); + if (db == null) + return NotFound("Database connection failed."); + + var userRet = db.GetUserByName(userName); + if (!userRet.IsSuccessful || !userRet.Value.HasValue) + return NotFound("User not found."); + + var user = userRet.Value.Value; + var boardId = user.BoardID; + if (boardId == Guid.Empty) + return NotFound("No board bound to this user."); + + try + { + await _videoStreamService.DisableHdmiTransmissionAsync(boardId.ToString()); + return Ok($"HDMI transmission for board {boardId} disabled."); + } + catch (Exception ex) + { + logger.Error(ex, $"Failed to disable HDMI transmission for board {boardId}"); + return StatusCode(500, $"Error disabling HDMI transmission: {ex.Message}"); + } + } } diff --git a/server/src/Services/HttpHdmiVideoStreamService.cs b/server/src/Services/HttpHdmiVideoStreamService.cs index 3e25d11..5682cc0 100644 --- a/server/src/Services/HttpHdmiVideoStreamService.cs +++ b/server/src/Services/HttpHdmiVideoStreamService.cs @@ -18,7 +18,7 @@ public class HttpHdmiVideoStreamService : BackgroundService private HttpListener? _httpListener; private readonly int _serverPort = 4322; private readonly ConcurrentDictionary _hdmiInDict = new(); - private bool _isEnabled = true; + private readonly ConcurrentDictionary _hdmiInCtsDict = new(); public override async Task StartAsync(CancellationToken cancellationToken) { @@ -72,29 +72,33 @@ public class HttpHdmiVideoStreamService : BackgroundService public override async Task StopAsync(CancellationToken cancellationToken) { logger.Info("Stopping HDMI Video Stream Service..."); - _isEnabled = false; - + // 禁用所有活跃的HDMI传输 var disableTasks = new List(); - foreach (var hdmiIn in _hdmiInDict.Values) + foreach (var hdmiKey in _hdmiInDict.Keys) { - disableTasks.Add(DisableHdmiTransmissionAsync(hdmiIn)); + disableTasks.Add(DisableHdmiTransmissionAsync(hdmiKey)); } - + // 等待所有禁用操作完成 await Task.WhenAll(disableTasks); - + // 清空字典 _hdmiInDict.Clear(); - + _hdmiInCtsDict.Clear(); + _httpListener?.Close(); // 立即关闭监听器,唤醒阻塞 await base.StopAsync(cancellationToken); } - - private async Task DisableHdmiTransmissionAsync(HdmiIn hdmiIn) + + public async Task DisableHdmiTransmissionAsync(string key) { try { + var cts = _hdmiInCtsDict[key]; + cts.Cancel(); + + var hdmiIn = _hdmiInDict[key]; var disableResult = await hdmiIn.EnableTrans(false); if (disableResult.IsSuccessful) { @@ -134,7 +138,7 @@ public class HttpHdmiVideoStreamService : BackgroundService var board = boardRet.Value.Value; hdmiIn = new HdmiIn(board.IpAddr, board.Port, 0); // taskID 可根据实际需求调整 - + // 启用HDMI传输 try { @@ -153,6 +157,7 @@ public class HttpHdmiVideoStreamService : BackgroundService } _hdmiInDict[boardId] = hdmiIn; + _hdmiInCtsDict[boardId] = new CancellationTokenSource(); return hdmiIn; } @@ -173,13 +178,20 @@ public class HttpHdmiVideoStreamService : BackgroundService return; } + var hdmiInToken = _hdmiInCtsDict[boardId].Token; + if (hdmiInToken == null) + { + await SendErrorAsync(context.Response, "HDMI input is not available"); + return; + } + if (path == "/snapshot") { - await HandleSnapshotRequestAsync(context.Response, hdmiIn, cancellationToken); + await HandleSnapshotRequestAsync(context.Response, hdmiIn, hdmiInToken); } else if (path == "/mjpeg") { - await HandleMjpegStreamAsync(context.Response, hdmiIn, cancellationToken); + await HandleMjpegStreamAsync(context.Response, hdmiIn, hdmiInToken); } else if (path == "/video") { @@ -218,7 +230,7 @@ public class HttpHdmiVideoStreamService : BackgroundService var expectedLength = frameWidth * frameHeight * 2; if (rgb565Data.Length != expectedLength) { - logger.Warn("HDMI快照数据长度不匹配,期望: {Expected}, 实际: {Actual}", + logger.Warn("HDMI快照数据长度不匹配,期望: {Expected}, 实际: {Actual}", expectedLength, rgb565Data.Length); } @@ -285,7 +297,7 @@ public class HttpHdmiVideoStreamService : BackgroundService const int frameWidth = 960; // HDMI输入分辨率 const int frameHeight = 540; - while (!cancellationToken.IsCancellationRequested && _isEnabled) + while (!cancellationToken.IsCancellationRequested) { try { @@ -381,7 +393,7 @@ public class HttpHdmiVideoStreamService : BackgroundService { logger.Error(ex, "禁用HDMI传输时出错"); } - + try { response.Close();