#pragma once #include #include #include #include #include #include #include #include namespace cvmmap_streamer::ipc { constexpr std::size_t kLabelLenMax = 24; constexpr std::size_t kShmPayloadOffset = 256; constexpr std::uint8_t kFrameTopicMagic = 0x7d; constexpr std::uint8_t kModuleStatusMagic = 0x5a; constexpr std::uint8_t kControlRequestMagic = 0x3c; constexpr std::uint8_t kControlResponseMagic = 0x3d; constexpr std::uint8_t kVersionMajor = 1; constexpr std::uint8_t kVersionMinor = 0; constexpr std::array kFrameMetadataMagic{ 'C', 'V', '-', 'M', 'M', 'A', 'P', '\0'}; enum class Depth : std::uint8_t { U8 = 0, S8 = 1, U16 = 2, S16 = 3, S32 = 4, F32 = 5, F64 = 6, F16 = 7, }; enum class PixelFormat : std::uint8_t { RGB = 0, BGR, RGBA, BGRA, GRAY, YUV, YUYV, }; enum class ModuleStatus : std::int32_t { Online = 0xa1, Offline = 0xa0, StreamReset = 0xb0, }; enum class ParseError { BufferTooSmall, InvalidSize, InvalidMagic, UnsupportedVersion, InvalidDepth, InvalidPixelFormat, InvalidModuleStatus, PayloadLengthMismatch, }; enum class SnapshotError { InvalidShmLayout, DestinationTooSmall, TornRead, }; std::string_view to_string(ParseError error); std::string_view to_string(SnapshotError error); struct FrameInfo { std::uint16_t width; std::uint16_t height; std::uint8_t channels; Depth depth; PixelFormat pixel_format; std::uint32_t buffer_size; }; struct FrameMetadata { std::array magic; std::uint8_t versions_major; std::uint8_t versions_minor; std::uint32_t frame_count; std::uint64_t timestamp_ns; FrameInfo info; }; struct SyncMessage { std::uint8_t versions_major; std::uint8_t versions_minor; std::uint32_t frame_count; std::uint64_t timestamp_ns; std::array label_bytes; [[nodiscard]] std::string_view label() const { const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast(0)); return std::string_view{ reinterpret_cast(label_bytes.data()), static_cast(std::distance(label_bytes.begin(), end))}; } }; struct ModuleStatusMessage { std::uint8_t versions_major; std::uint8_t versions_minor; ModuleStatus module_status; std::array label_bytes; [[nodiscard]] std::string_view label() const { const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast(0)); return std::string_view{ reinterpret_cast(label_bytes.data()), static_cast(std::distance(label_bytes.begin(), end))}; } }; struct ControlRequestMessage { std::uint8_t versions_major; std::uint8_t versions_minor; std::int32_t command_id; std::array label_bytes; std::span request_payload; [[nodiscard]] std::string_view label() const { const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast(0)); return std::string_view{ reinterpret_cast(label_bytes.data()), static_cast(std::distance(label_bytes.begin(), end))}; } }; struct ControlResponseMessage { std::uint8_t versions_major; std::uint8_t versions_minor; std::int32_t command_id; std::int32_t response_code; std::array label_bytes; std::span response_payload; [[nodiscard]] std::string_view label() const { const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast(0)); return std::string_view{ reinterpret_cast(label_bytes.data()), static_cast(std::distance(label_bytes.begin(), end))}; } }; struct ValidatedShmView { FrameMetadata metadata; std::span payload; }; struct CoherentSnapshot { FrameMetadata metadata; std::size_t bytes_copied; }; using SnapshotReadHook = std::function; std::expected parse_frame_metadata(std::span bytes); std::expected parse_sync_message(std::span bytes); std::expected parse_module_status_message(std::span bytes); std::expected parse_control_request_message(std::span bytes); std::expected parse_control_response_message(std::span bytes); std::expected validate_shm_region(std::span shm_region); std::expected read_coherent_snapshot( std::span shm_region, std::span destination, const SnapshotReadHook &before_second_metadata_read = {}); }