add: 添加了HDMI视频流Client
This commit is contained in:
parent
0bd1ad8a0e
commit
51b39cee07
|
@ -1,6 +1,7 @@
|
|||
using System.Net;
|
||||
using DotNext;
|
||||
using Peripherals.PowerClient;
|
||||
using WebProtocol;
|
||||
|
||||
namespace Peripherals.CameraClient;
|
||||
|
||||
|
@ -225,6 +226,7 @@ class Camera
|
|||
this.taskID, // taskID
|
||||
FrameAddr,
|
||||
(int)_currentFrameLength, // 使用当前分辨率的动态大小
|
||||
BurstType.ExtendBurst,
|
||||
this.timeout);
|
||||
|
||||
if (!result.IsSuccessful)
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
using System.Net;
|
||||
using DotNext;
|
||||
using Peripherals.PowerClient;
|
||||
using WebProtocol;
|
||||
|
||||
namespace Peripherals.HdmiInClient;
|
||||
|
||||
static class HdmiInAddr
|
||||
{
|
||||
public const UInt32 BASE = 0xA000_0000;
|
||||
public const UInt32 HdmiIn_CTRL = BASE + 0x0; //[0]: rstn, 0 is reset.
|
||||
public const UInt32 HdmiIn_READFIFO = BASE + 0x1;
|
||||
}
|
||||
|
||||
class HdmiIn
|
||||
{
|
||||
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
readonly int timeout = 500;
|
||||
readonly int taskID;
|
||||
readonly int port;
|
||||
readonly string address;
|
||||
private IPEndPoint ep;
|
||||
|
||||
// 动态分辨率参数
|
||||
private UInt16 _currentWidth = 960;
|
||||
private UInt16 _currentHeight = 540;
|
||||
private UInt32 _currentFrameLength = 960 * 540 * 2 / 4; // RGB565格式,2字节/像素,按4字节对齐
|
||||
|
||||
/// <summary>
|
||||
/// 初始化HDMI输入客户端
|
||||
/// </summary>
|
||||
/// <param name="address">HDMI输入设备IP地址</param>
|
||||
/// <param name="port">HDMI输入设备端口</param>
|
||||
/// <param name="timeout">超时时间(毫秒)</param>
|
||||
public HdmiIn(string address, int port, int timeout = 500)
|
||||
{
|
||||
if (timeout < 0)
|
||||
throw new ArgumentException("Timeout couldn't be negative", nameof(timeout));
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.ep = new IPEndPoint(IPAddress.Parse(address), port);
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> EnableTrans(bool isEnable)
|
||||
{
|
||||
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, HdmiInAddr.HdmiIn_CTRL, (isEnable ? 0x00000001u : 0x00000000u));
|
||||
if (!ret.IsSuccessful)
|
||||
{
|
||||
logger.Error($"Failed to write HdmiIn_CTRL to HdmiIn at {this.address}:{this.port}, error: {ret.Error}");
|
||||
return new(ret.Error);
|
||||
}
|
||||
if (!ret.Value)
|
||||
{
|
||||
logger.Error($"HdmiIn_CTRL write returned false for HdmiIn at {this.address}:{this.port}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取一帧图像数据
|
||||
/// </summary>
|
||||
/// <returns>包含图像数据的字节数组</returns>
|
||||
public async ValueTask<Result<byte[]>> ReadFrame()
|
||||
{
|
||||
// 只在第一次或出错时清除UDP缓冲区,避免每帧都清除造成延迟
|
||||
// MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
|
||||
|
||||
logger.Trace($"Reading frame from HdmiIn {this.address}");
|
||||
|
||||
// 使用UDPClientPool读取图像帧数据
|
||||
var result = await UDPClientPool.ReadAddr4BytesAsync(
|
||||
this.ep,
|
||||
this.taskID, // taskID
|
||||
HdmiInAddr.HdmiIn_READFIFO,
|
||||
(int)_currentFrameLength, // 使用当前分辨率的动态大小
|
||||
BurstType.FixedBurst,
|
||||
this.timeout);
|
||||
|
||||
if (!result.IsSuccessful)
|
||||
{
|
||||
logger.Error($"Failed to read frame from HdmiIn {this.address}:{this.port}, error: {result.Error}");
|
||||
// 读取失败时清除缓冲区,为下次读取做准备
|
||||
try
|
||||
{
|
||||
MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Warn($"Failed to clear UDP data after read error: {ex.Message}");
|
||||
}
|
||||
return new(result.Error);
|
||||
}
|
||||
|
||||
logger.Trace($"Successfully read frame from HdmiIn {this.address}:{this.port}, data length: {result.Value.Length} bytes");
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前分辨率
|
||||
/// </summary>
|
||||
/// <returns>当前分辨率(宽度, 高度)</returns>
|
||||
public (int Width, int Height) GetCurrentResolution()
|
||||
{
|
||||
return (_currentWidth, _currentHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前帧长度
|
||||
/// </summary>
|
||||
/// <returns>当前帧长度</returns>
|
||||
public UInt32 GetCurrentFrameLength()
|
||||
{
|
||||
return _currentFrameLength;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ using System.Collections;
|
|||
using System.Net;
|
||||
using Common;
|
||||
using DotNext;
|
||||
using WebProtocol;
|
||||
|
||||
namespace Peripherals.LogicAnalyzerClient;
|
||||
|
||||
|
@ -475,6 +476,7 @@ public class Analyzer
|
|||
this.taskID,
|
||||
AnalyzerAddr.STORE_OFFSET_ADDR,
|
||||
capture_length,
|
||||
BurstType.ExtendBurst, // 使用扩展突发读取
|
||||
this.timeout
|
||||
);
|
||||
if (!ret.IsSuccessful)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Net;
|
||||
using Common;
|
||||
using DotNext;
|
||||
using WebProtocol;
|
||||
|
||||
namespace Peripherals.OscilloscopeClient;
|
||||
|
||||
|
@ -319,6 +320,7 @@ class Oscilloscope
|
|||
this.taskID,
|
||||
OscilloscopeAddr.RD_DATA_ADDR,
|
||||
(int)OscilloscopeAddr.RD_DATA_LENGTH / 32,
|
||||
BurstType.ExtendBurst, // 使用扩展突发读取
|
||||
this.timeout
|
||||
);
|
||||
if (!ret.IsSuccessful)
|
||||
|
|
|
@ -433,11 +433,12 @@ public class UDPClientPool
|
|||
/// <param name="endPoint">IP端点(IP地址与端口)</param>
|
||||
/// <param name="taskID">任务ID</param>
|
||||
/// <param name="devAddr">设备地址</param>
|
||||
/// <param name="burstType">突发类型</param>
|
||||
/// <param name="dataLength">要读取的数据长度(4字节)</param>
|
||||
/// <param name="timeout">超时时间(毫秒)</param>
|
||||
/// <returns>读取结果,包含接收到的字节数组</returns>
|
||||
public static async ValueTask<Result<byte[]>> ReadAddr4BytesAsync(
|
||||
IPEndPoint endPoint, int taskID, UInt32 devAddr, int dataLength, int timeout = 1000)
|
||||
IPEndPoint endPoint, int taskID, UInt32 devAddr, int dataLength, BurstType burstType, int timeout = 1000)
|
||||
{
|
||||
var pkgList = new List<SendAddrPackage>();
|
||||
var resultData = new List<byte>();
|
||||
|
@ -460,7 +461,7 @@ public class UDPClientPool
|
|||
|
||||
var opts = new SendAddrPackOptions
|
||||
{
|
||||
BurstType = BurstType.FixedBurst,
|
||||
BurstType = burstType,
|
||||
CommandID = Convert.ToByte(taskID),
|
||||
IsWrite = false,
|
||||
BurstLength = (byte)(currentSegmentSize - 1),
|
||||
|
|
Loading…
Reference in New Issue