Files
cvmmap-streamer/include/cvmmap_streamer/ipc/contracts.hpp
T

201 lines
5.4 KiB
C++

#pragma once
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <functional>
#include <span>
#include <string_view>
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<std::uint8_t, 8> 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 DepthUnit : std::uint8_t {
Unknown = 0,
Millimeter = 1,
Meter = 2,
};
enum class ModuleStatus : std::int32_t {
Online = 0xa1,
Offline = 0xa0,
StreamReset = 0xb0,
};
enum class ParseError {
BufferTooSmall,
InvalidSize,
InvalidMagic,
UnsupportedVersion,
InvalidDepth,
InvalidDepthUnit,
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<std::uint8_t, kFrameMetadataMagic.size()> 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<std::uint8_t, kLabelLenMax> label_bytes;
[[nodiscard]]
std::string_view label() const {
const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast<std::uint8_t>(0));
return std::string_view{
reinterpret_cast<const char *>(label_bytes.data()),
static_cast<std::size_t>(std::distance(label_bytes.begin(), end))};
}
};
struct ModuleStatusMessage {
std::uint8_t versions_major;
std::uint8_t versions_minor;
ModuleStatus module_status;
std::array<std::uint8_t, kLabelLenMax> label_bytes;
[[nodiscard]]
std::string_view label() const {
const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast<std::uint8_t>(0));
return std::string_view{
reinterpret_cast<const char *>(label_bytes.data()),
static_cast<std::size_t>(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<std::uint8_t, kLabelLenMax> label_bytes;
std::span<const std::uint8_t> request_payload;
[[nodiscard]]
std::string_view label() const {
const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast<std::uint8_t>(0));
return std::string_view{
reinterpret_cast<const char *>(label_bytes.data()),
static_cast<std::size_t>(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<std::uint8_t, kLabelLenMax> label_bytes;
std::span<const std::uint8_t> response_payload;
[[nodiscard]]
std::string_view label() const {
const auto end = std::find(label_bytes.begin(), label_bytes.end(), static_cast<std::uint8_t>(0));
return std::string_view{
reinterpret_cast<const char *>(label_bytes.data()),
static_cast<std::size_t>(std::distance(label_bytes.begin(), end))};
}
};
struct ValidatedShmView {
FrameMetadata metadata;
DepthUnit depth_unit{DepthUnit::Unknown};
std::span<const std::uint8_t> payload;
std::span<const std::uint8_t> left;
std::optional<FrameInfo> depth_info{};
std::span<const std::uint8_t> depth{};
std::optional<FrameInfo> confidence_info{};
std::span<const std::uint8_t> confidence{};
};
struct CoherentSnapshot {
FrameMetadata metadata;
DepthUnit depth_unit{DepthUnit::Unknown};
std::span<const std::uint8_t> left;
std::optional<FrameInfo> depth_info{};
std::span<const std::uint8_t> depth{};
std::optional<FrameInfo> confidence_info{};
std::span<const std::uint8_t> confidence{};
std::size_t bytes_copied;
};
using SnapshotReadHook = std::function<void()>;
std::expected<FrameMetadata, ParseError> parse_frame_metadata(std::span<const std::uint8_t> bytes);
std::expected<SyncMessage, ParseError> parse_sync_message(std::span<const std::uint8_t> bytes);
std::expected<ModuleStatusMessage, ParseError> parse_module_status_message(std::span<const std::uint8_t> bytes);
std::expected<ControlRequestMessage, ParseError> parse_control_request_message(std::span<const std::uint8_t> bytes);
std::expected<ControlResponseMessage, ParseError> parse_control_response_message(std::span<const std::uint8_t> bytes);
std::expected<ValidatedShmView, ParseError> validate_shm_region(std::span<const std::uint8_t> shm_region);
std::expected<CoherentSnapshot, SnapshotError> read_coherent_snapshot(
std::span<const std::uint8_t> shm_region,
std::span<std::uint8_t> destination,
const SnapshotReadHook &before_second_metadata_read = {});
}