feat: 支持HDMI关闭传输
This commit is contained in:
		@@ -60,4 +60,38 @@ public class HdmiVideoStreamController : ControllerBase
 | 
			
		||||
        var endpoint = _videoStreamService.GetVideoEndpoint(boardId.ToString());
 | 
			
		||||
        return Ok(endpoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 禁用指定板子的 HDMI 传输
 | 
			
		||||
    [HttpPost("DisableHdmiTransmission")]
 | 
			
		||||
    [Authorize]
 | 
			
		||||
    public async Task<IActionResult> 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}");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ public class HttpHdmiVideoStreamService : BackgroundService
 | 
			
		||||
    private HttpListener? _httpListener;
 | 
			
		||||
    private readonly int _serverPort = 4322;
 | 
			
		||||
    private readonly ConcurrentDictionary<string, HdmiIn> _hdmiInDict = new();
 | 
			
		||||
    private bool _isEnabled = true;
 | 
			
		||||
    private readonly ConcurrentDictionary<string, CancellationTokenSource> _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<Task>();
 | 
			
		||||
        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();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user