using NetMQ; using SHH.Contracts; namespace SHH.CameraService { /// /// 负责将业务契约转换为 ZeroMQ 传输协议 /// public static class NetMQProtocolExtensions { private const string PROTOCOL_HEADER = "SHH_V1"; /// /// 扩展方法:将 Payload 转为 NetMQMessage /// 使用方法:var msg = payload.ToNetMqMessage(); /// public static NetMQMessage ToNetMqMessage(this VideoPayload payload) { var msg = new NetMQMessage(); // Frame 0: 协议魔数 msg.Append(PROTOCOL_HEADER); // Frame 1: 元数据 JSON msg.Append(payload.GetMetadataJson()); // Frame 2: 原始图 (保持帧位对齐,无数据则发空帧) if (payload.HasOriginalImage && payload.OriginalImageBytes != null) msg.Append(payload.OriginalImageBytes); else msg.Append(Array.Empty()); // Frame 3: 处理图 if (payload.HasTargetImage && payload.TargetImageBytes != null) msg.Append(payload.TargetImageBytes); else msg.Append(Array.Empty()); return msg; } /// /// 扩展方法:从 NetMQMessage 还原 Payload /// public static VideoPayload ToVideoPayload(this NetMQMessage msg) { if (msg == null || msg.FrameCount < 4) return null; // Frame 0 Check if (msg[0].ConvertToString() != PROTOCOL_HEADER) return null; // Frame 1: Metadata string json = msg[1].ConvertToString(); var payload = VideoPayload.FromMetadataJson(json); if (payload == null) return null; // Frame 2: Raw Image // 利用 BufferSize 避免不必要的内存拷贝,如果长度为0则跳过 if (payload.HasOriginalImage && msg[2].BufferSize > 0) { payload.OriginalImageBytes = msg[2].ToByteArray(); } // Frame 3: Processed Image if (payload.HasTargetImage && msg[3].BufferSize > 0) { payload.TargetImageBytes = msg[3].ToByteArray(); } return payload; } } }