201 lines
5.4 KiB
C++
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 = {});
|
|
|
|
}
|