Hybrid Vision Toolkit C++ API
v2.0 三后端(USB / MIPI / Ethernet)共用同一套 Shimeta::hv::Camera 统一 API。本页给出完整 C++ 公有 API 参考;MIPI 专属的差异(RAW8 解码、APS 格式因板卡而异、ARM 构建)在各对应小节内标注。
符号、签名以
include/shimetapi/头文件为准(源码仓与发布仓一致,零差异)。所有符号位于Shimeta::命名空间下,零第三方事件 SDK 依赖。
core
头文件:<shimetapi/core/*.h>
Shimeta::EventCD
#include <shimetapi/core/event_cd.h>
作用:自有事件类型(POD),字段语义与业界常见事件结构一一对应。
struct EventCD {
uint16_t x; // 像素 X 坐标
uint16_t y; // 像素 Y 坐标
int64_t t; // 时间戳(微秒)
bool polarity; // 1 = CD_ON, 0 = CD_OFF
};Shimeta::Status
#include <shimetapi/core/status.h>
作用:库统一错误码枚举;statusToString() 把错误码转为人读字符串,便于日志与诊断。
enum class Status : int32_t {
Ok = 0, ErrDeviceNotFound = -1, ErrPermissionDenied = -2,
ErrUsbTransfer = -3, ErrV4l2Ioctl = -4, ErrNetworkTimeout = -5,
ErrInvalidParam = -6, ErrBufferFull = -7, ErrDecodeFailure = -8,
ErrUnsupportedFormat = -9,
};
const char* statusToString(Status s);Shimeta::BufferView / BufferPool
#include <shimetapi/core/buffer_pool.h>
作用:BufferView 是对池 slab 的非拥有只读视图;BufferPool 是固定大小 slab 池,用于零拷贝帧生命周期管理。
struct BufferView {
const uint8_t* data = nullptr;
size_t size = 0;
};
class BufferPool {
public:
BufferPool(size_t slab_size, size_t slab_count);
std::shared_ptr<uint8_t[]> acquire();
size_t slab_size() const;
size_t capacity() const;
size_t available() const;
};BufferPool 构造函数
【语法】BufferPool(size_t slab_size, size_t slab_count);
【描述】构造池并预分配 slab_count 个 slab,每个 slab_size 字节。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| slab_size | size_t (in) | 单个 slab 的字节数(如 NV12 帧 = w×h×3/2) |
| slab_count | size_t (in) | slab 总数(决定并发帧数上限) |
【返回值】无(构造函数)。
【注意】slab 耗尽时 acquire() 返回 nullptr,slab_count 应 ≥ 并发帧数。
【举例】
Shimeta::BufferPool pool(768 * 608 * 3 / 2, 8); // NV12 帧 × 8acquire
【语法】std::shared_ptr<uint8_t[]> acquire();
【描述】从池中获取一个 slab,返回引用计数 handle。最后一个引用释放时 slab 自动归还池。
【参数】无。
【返回值】
| 返回值 | 描述 |
|---|---|
非空 shared_ptr<uint8_t[]> | 成功获取 slab |
nullptr | 池已耗尽(所有 slab 均在使用中) |
【注意】返回的 shared_ptr 可安全传递给 Frame.*_owner,保证视图在 Frame 存活期间有效。
【举例】
auto slab = pool.acquire();
if (!slab) { /* 池耗尽,丢帧或等待 */ }slab_size / capacity / available
【语法】
size_t slab_size() const; // 单 slab 字节数
size_t capacity() const; // slab 总数
size_t available() const; // 当前空闲 slab 数【描述】查询池的容量与空闲状态。
【参数】无。
【返回值】size_t(对应值)。
【注意】available() 可用于监控池压力;趋近 0 表示丢帧风险。
【举例】无。
Shimeta::PixelFormat
#include <shimetapi/core/pixel_format.h>
作用:APS 图像像素格式枚举。
enum class PixelFormat : uint8_t { BayerRG8 = 0, RGB888 = 1, Gray8 = 2, RAW8 = 3, RAW10 = 4, NV12 = 5 };
NV12为 MIPI HVS 后端 APS 帧经 ISP→PYM 后的 packed YUV 格式;USB 后端 APS 默认 NV12(768×608)。X5 载板上 APS 走 VIN 直读,输出Gray8(预期行为,见 MIPI 注意事项)。
Shimeta::TimestampInfo
#include <shimetapi/core/timestamp.h>
作用:帧时间戳信息。
struct TimestampInfo {
int64_t evs_ts_ns = 0; // EVS 事件参考时间戳(纳秒)
int64_t aps_ts_ns = 0; // APS 曝光时刻(纳秒)
bool ptp_locked = false; // Ethernet 后端 PTP 是否锁定
};Shimeta::EvsTimestamp
#include <shimetapi/core/evs_timestamp.h>
作用:EVS 传感器内部时间戳(从 MIPI RAW8 子帧头提取),用于 HybridWriter / HybridReader 的 tsmp chunk。由 Shimeta::codec::extractEvsTimestamp() 提取。
struct EvsTimestamp {
uint64_t raw_timestamp = 0; // 传感器 45-bit 原始时间戳
uint64_t processed_timestamp = 0; // raw_timestamp / 200(微秒)
bool valid = false;
};Shimeta::Frame
#include <shimetapi/core/frame.h>
作用:统一帧。aps / evs 为池内存的只读视图,*_owner 持有 slab 引用以保证视图在 Frame 存活期间有效(零拷贝、池托管生命周期)。
struct Frame {
BufferView aps{};
BufferView evs{};
TimestampInfo ts{};
int width{0};
int height{0};
int frame_id{0};
PixelFormat format{};
std::shared_ptr<uint8_t[]> aps_owner{};
std::shared_ptr<uint8_t[]> evs_owner{};
};
Frame.evs是 HAL 未解码的原始事件字节(USB 后端通常为 EVT2);需用对应 codec 解码。
hv
头文件:<shimetapi/hv/camera.h>、<shimetapi/hv/device_config.h>、<shimetapi/hv/event_format.h>、<shimetapi/hv/event_packet.h>、<shimetapi/hv/image_data.h>。
Shimeta::hv::Backend / EventFormat
#include <shimetapi/hv/device_config.h>#include <shimetapi/hv/event_format.h>
作用:Backend 选择采集后端;EventFormat 选择事件字节编码格式(决定 Frame.evs 如何解码)。
enum class Backend { Auto, Usb, Mipi, MipiHvs, Ethernet };
enum class EventFormat { Evt2, Evt3 };| Backend | 说明 |
|---|---|
Auto | 自动选择(按 DeviceConfig 字段推断)。 |
Usb | libusb 后端(USB 相机)。 |
Mipi | MIPI 后端(EVS-only)。 |
MipiHvs | MIPI HVS 双 VC 后端:VC0 传 EVS 事件,VC1 传 APS 帧。 |
Ethernet | 以太网后端(POSIX sockets,DVS1 协议)。 |
Shimeta::hv::DeviceConfig
#include <shimetapi/hv/device_config.h>
作用:采集配置 —— 选择后端 + 各后端参数。传给 Camera::Init()。
struct DeviceConfig {
Backend backend = Backend::Auto;
std::string device_node; // MIPI: "/dev/video0"
std::string ip; // Ethernet
uint16_t data_port = 8000;
uint16_t ctrl_port = 8001;
EventFormat event_fmt = EventFormat::Evt3;
int buffer_count = 8;
uint16_t vendor_id = 0, product_id = 0; // USB VID/PID
enum class QueuePolicy { DropOldest, Block };
QueuePolicy queue_policy = QueuePolicy::DropOldest;
int event_urbs = 4; // USB 事件端点在途 URB 数
uint16_t evs_fps = 0; // 0=不设置;非 0=Init 时自动下发
int sensor_index = 0; // MIPI 传感器索引;平台样例通常由构建配置覆盖
uint8_t i2c_bus = 1; // MIPI 安全芯片认证 I2C 总线
uint16_t listen_port = 8888; // Ethernet: TCP 监听端口
std::string bind_ip; // Ethernet: 本地绑定 IP(空=INADDR_ANY)
};| 字段 | 适用后端 | 描述 |
|---|---|---|
backend | 全部 | 选择后端类型 |
vendor_id / product_id | USB | USB 设备 VID/PID(如 0x1d6b / 0x0105) |
event_urbs | USB | 事件端点在途 URB 数,默认 4;增大可提高吞吐但占内存 |
queue_policy | 全部 | 池满策略:DropOldest(丢旧帧,默认)/ Block(阻塞等待) |
event_fmt | 全部 | 事件字节格式:Evt2(USB 默认)/ Evt3 |
evs_fps | 全部 | MIPI 帧率档;USB/Ethernet 运行时改帧率用 Camera::SetFrameRate¹ |
device_node | MIPI | 设备节点路径,如 "/dev/video0" |
sensor_index | MIPI | RDK 传感器索引;API 默认 0,S100/X5 样例当前分别使用 9/49 |
i2c_bus | MIPI | 安全芯片认证 I2C 总线号,默认 1 |
ip / data_port / ctrl_port | Ethernet | 相机 IP + 数据/控制端口 |
listen_port / bind_ip | Ethernet | 相机作服务端时的监听端口与本地绑定 IP |
¹ MIPI:0 = 默认 240;可选 120 / 240 / 300 / 500 / 750 / 1000;Init 时下发,非档位值报错。
Shimeta::hv::Camera
#include <shimetapi/hv/camera.h>
作用:统一采集 API;同一套接口覆盖 USB / MIPI / Ethernet 三后端。支持同步拉取(GetFrame)与异步回调(Frame / Event / Image 三选一或多)。
namespace Shimeta::hv {
class Camera {
public:
Camera();
~Camera();
Camera(const Camera&) = delete;
Camera& operator=(const Camera&) = delete;
bool Init(const DeviceConfig& cfg);
bool StartStream();
void StopStream();
void Destroy();
bool GetFrame(Frame& frame, int timeout_ms = 1000);
using FrameCallback = std::function<void(const Frame&)>;
using EventCallback = std::function<void(const EventPacket&)>;
using ImageCallback = std::function<void(const ImageData&)>;
void SetFrameCallback(FrameCallback cb);
void SetEventCallback(EventCallback cb);
void SetImageCallback(ImageCallback cb);
bool SetExposure(int value);
bool SetFrameRate(unsigned fps);
bool GetFrameRate(unsigned& fps);
bool SyncClock();
};
} // namespace Shimeta::hvInit
【语法】bool Init(const DeviceConfig& cfg);
【描述】按 DeviceConfig 初始化后端(不阻塞打开硬件;部分后端在 StartStream 才实际连接设备)。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| cfg | const DeviceConfig& (in) | 采集配置:后端类型 + VID/PID / IP / sensor_index 等 |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 配置已接受,后端初始化成功 |
| false | 配置无效(未知后端 / 必填字段缺失 / 参数越界) |
【注意】
Init不打开硬件,实际连接发生在StartStream。- 可多次调用(内部先
Destroy再重新初始化)。
【举例】
Shimeta::hv::DeviceConfig cfg;
cfg.backend = Shimeta::hv::Backend::Usb;
cfg.vendor_id = 0x1d6b;
cfg.product_id = 0x0105;
cam.Init(cfg);StartStream
【语法】bool StartStream();
【描述】启动采集线程并连接设备。这是实际打开硬件、开始数据传输的入口。
【参数】无。
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 成功连接设备并启动采集 |
| false | 设备未找到 / 权限不足 / 已被占用 |
【注意】
- 必须先调用
Init。 - 返回
false时不产生异常,可检查Status或重试。
【举例】
if (!cam.StartStream()) {
std::cerr << "无法连接设备,请检查 USB 连接与权限" << std::endl;
return 1;
}GetFrame
【语法】bool GetFrame(Frame& frame, int timeout_ms = 1000);
【描述】同步拉取一帧组合数据(EVS 事件 + APS 图像),阻塞直到取到帧或超时。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| frame | Frame& (out) | 输出帧;aps/evs 为池内存只读视图,*_owner 持有 slab 引用 |
| timeout_ms | int (in) | 超时毫秒数,默认 1000 |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 在超时内取到帧 |
| false | 超时未取到(设备未连接 / 采集已停止 / 数据耗尽) |
【注意】
frame.evs是 HAL 未解码的原始事件字节(USB 通常为 EVT2),需用Evt2Decoder/Evt3Decoder解码。frame.aps为原始 APS 字节,格式由frame.format决定;S100/USB 通常为 NV12,X5 为 Gray8。应用层按格式转换。- 同一
Frame实例可重复传入;每次调用覆盖其内容。
【举例】
Shimeta::codec::Evt2Decoder dec;
Shimeta::Frame f;
while (cam.GetFrame(f, 1000)) {
std::vector<Shimeta::EventCD> events;
dec.Decode(f.evs.data, f.evs.size, events); // 解码事件
// f.aps.data / f.aps.size → NV12,应用层 cvtColor
}SetFrameCallback / SetEventCallback / SetImageCallback
【语法】
void SetFrameCallback(FrameCallback cb); // 组合帧(事件 + APS)
void SetEventCallback(EventCallback cb); // 原始事件包
void SetImageCallback(ImageCallback cb); // APS 图像【描述】注册异步回调。回调仅在派发线程串行触发,采集线程不回调。三个回调可同时注册、互不干扰。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| cb | FrameCallback / EventCallback / ImageCallback (in) | 回调函数对象;传 nullptr 取消该回调 |
【返回值】无。
【注意】
- 回调在内部派发线程执行,不要在回调中阻塞或反向调用相机的同步接口(如
GetFrame、StopStream)。 - 重计算应转存到工作线程处理。
EventCallback收到的是EventPacket(原始字节),同样需 codec 解码。
【举例】
cam.SetEventCallback([&dec](const Shimeta::hv::EventPacket& pkt) {
std::vector<Shimeta::EventCD> events;
dec.Decode(pkt.data.data, pkt.data.size, events);
// 处理 events(在工作线程,勿阻塞回调)
});SetExposure
【语法】bool SetExposure(int value);
【描述】设置 APS 曝光值。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| value | int (in) | 曝光值(设备定义的单位,一般越大越亮) |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 设置成功 |
| false | 设备不支持 / 未连接 |
【注意】仅对支持 APS 的后端生效(USB / MipiHvs)。
【举例】无。
SetFrameRate / GetFrameRate
【语法】
bool SetFrameRate(unsigned fps);
bool GetFrameRate(unsigned& fps);【描述】设置 / 读取 EVS 事件帧率。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| fps | unsigned (in/out) | 帧率(fps);GetFrameRate 为输出参数 |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 成功 |
| false | 后端不支持 / 未连接 |
【注意】当前支持 USB / Ethernet 后端;MIPI 后端用 DeviceConfig.evs_fps 在 Init 时设置。
【举例】
cam.SetFrameRate(120); // 设为 120 fps
unsigned current;
cam.GetFrameRate(current); // 读当前帧率StopStream / Destroy / SyncClock
【语法】
void StopStream();
void Destroy();
bool SyncClock();【描述】
| 方法 | 描述 |
|---|---|
StopStream() | 停止采集并 join 采集线程(阻塞直到线程退出)。 |
Destroy() | 释放后端资源(可在 StopStream 后或代替它调用)。 |
SyncClock() | 时钟同步(Ethernet PTP mode 0 等)。 |
【参数】无。
【返回值】
| 方法 | 返回值 | 描述 |
|---|---|---|
StopStream / Destroy | void | — |
SyncClock | bool | true=同步成功;false=后端不支持或未连接 |
【注意】推荐的关闭顺序:StopStream() → Destroy()。
【举例】
cam.StopStream();
cam.Destroy();Shimeta::hv::EventPacket / ImageData
#include <shimetapi/hv/event_packet.h>#include <shimetapi/hv/image_data.h>
作用:EventPacket 是一包事件原始字节(HAL 未解码),用于 EventCallback;ImageData 是一帧 APS 图像 + 元信息,用于 ImageCallback。
namespace Shimeta::hv {
struct EventPacket {
BufferView data{}; // 一包事件原始字节
int64_t t_begin_ns = 0;
int64_t t_end_ns = 0;
};
struct ImageData {
BufferView pixels{};
int width = 0, height = 0;
PixelFormat format{};
TimestampInfo ts{};
};
}codec
头文件:<shimetapi/codec/evt2_codec.h>、<shimetapi/codec/evt3_codec.h>、<shimetapi/codec/mipi_raw8_codec.h>。命名空间 Shimeta::codec。
EVT2
32-bit word 流,USB 默认。
class Evt2Encoder {
public:
Evt2Encoder();
void Encode(const EventCD* events, size_t count, std::vector<uint8_t>& out);
void Reset();
};
class Evt2Decoder {
public:
Evt2Decoder();
size_t Decode(const uint8_t* buffer, size_t buffer_size, std::vector<EventCD>& out);
void Reset();
};Evt2Encoder::Encode
【语法】void Encode(const EventCD* events, size_t count, std::vector<uint8_t>& out);
【描述】把 count 个事件编码为 EVT2 32-bit word 字节流(含必要的 TimeHigh 冗余字),追加到 out。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| events | const EventCD* (in) | 事件数组指针 |
| count | size_t (in) | 事件数量 |
| out | std::vector<uint8_t>& (out) | 输出字节(追加,不清空) |
【返回值】无。
【注意】编码器有状态(维护 time-base),多包流请复用同一实例;新流前调用 Reset()。
【举例】
Shimeta::codec::Evt2Encoder enc;
std::vector<Shimeta::EventCD> events = { /* ... */ };
std::vector<uint8_t> raw;
enc.Encode(events.data(), events.size(), raw);Evt2Decoder::Decode
【语法】size_t Decode(const uint8_t* buffer, size_t buffer_size, std::vector<EventCD>& out);
【描述】解码 EVT2 32-bit word 字节流,将 CD 事件追加到 out。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| buffer | const uint8_t* (in) | 输入字节 |
| buffer_size | size_t (in) | 输入字节数 |
| out | std::vector<EventCD>& (out) | 输出事件(追加,不清空) |
【返回值】
| 返回值 | 描述 |
|---|---|
size_t | 本次调用解码出的 CD 事件数 |
【注意】
- 解码器有状态(跨包维护 time-base / 翻转计数),多包流请复用同一实例。
- 新流前调用
Reset()。
【举例】
Shimeta::codec::Evt2Decoder dec;
std::vector<Shimeta::EventCD> events;
size_t n = dec.Decode(frame.evs.data, frame.evs.size, events);Evt2Encoder::Reset / Evt2Decoder::Reset
【语法】
void Evt2Encoder::Reset(); // 重置编码器(下次从 time-base 0 起)
void Evt2Decoder::Reset(); // 清除解码状态(新流前调用)【参数】无。【返回值】无。【注意】切换到新的事件流(如新文件、新录制段)时必须调用。【举例】无。
EVT3
16-bit word 流。
class Evt3Encoder {
public:
Evt3Encoder();
void Encode(const EventCD* events, size_t count, std::vector<uint8_t>& out);
void Reset();
};
class Evt3Decoder {
public:
Evt3Decoder();
size_t Decode(const uint8_t* buf, size_t len, std::vector<EventCD>& out);
void Reset();
};Evt3Encoder::Encode
【语法】void Encode(const EventCD* events, size_t count, std::vector<uint8_t>& out);
【描述】把 count 个事件编码为 EVT3 16-bit word 字节流,追加到 out。
【参数】同 Evt2Encoder::Encode。
【返回值】无。
【注意】有状态,同 EVT2 规则。【举例】无。
Evt3Decoder::Decode
【语法】size_t Decode(const uint8_t* buf, size_t len, std::vector<EventCD>& out);
【描述】解码 EVT3 16-bit word 字节流为 CD 事件。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| buf | const uint8_t* (in) | 输入字节 |
| len | size_t (in) | 必须为 2 的倍数(16-bit 对齐) |
| out | std::vector<EventCD>& (out) | 输出事件(追加) |
【返回值】
| 返回值 | 描述 |
|---|---|
size_t | 本次调用解码出的 CD 事件数 |
【注意】len 必须为偶数;否则行为未定义。其余同 Evt2Decoder::Decode(有状态、新流前 Reset)。
【举例】
Shimeta::codec::Evt3Decoder dec;
std::vector<Shimeta::EventCD> events;
dec.Decode(frame.evs.data, frame.evs.size, events);Evt3Encoder::Reset / Evt3Decoder::Reset
同 EVT2,新流前调用。
MIPI RAW8
apx003 子帧流
作用:MipiRaw8Decoder 解码 apx003 RAW8 子帧流为 EventCD,无状态。USB 后端不产生 RAW8,通常无需此类。详见 C++ API。
class MipiRaw8Decoder {
public:
MipiRaw8Decoder() = default;
// subframe_count<=0 为自动档:按 len/kSubframeBytes 解全部子帧
// (各帧率档整包子帧数不同:120fps=16 … 1000fps=128)
size_t Decode(const uint8_t* data, size_t len, std::vector<EventCD>& out,
int subframe_count = 0);
void Reset(); // 无状态,no-op
};MipiRaw8Decoder::Decode
【语法】size_t Decode(const uint8_t* data, size_t len, std::vector<EventCD>& out, int subframe_count = 0);
【描述】解码 apx003 RAW8 子帧流为 CD 事件。无状态(无跨包时间戳维护)。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| data | const uint8_t* (in) | RAW8 字节 |
| len | size_t (in) | 字节数 |
| out | std::vector<EventCD>& (out) | 输出事件(追加) |
| subframe_count | int (in) | 子帧数;≤0 = 自动档按 len 全部解,>0 = 仅前 N 个 |
【返回值】
| 返回值 | 描述 |
|---|---|
size_t | 本次解码出的 CD 事件数 |
【注意】仅用于 MIPI HVS 后端的 Frame.evs(RAW8 子帧流),不能用于 EVT2/EVT3 字节流。
【举例】
Shimeta::codec::MipiRaw8Decoder dec;
std::vector<Shimeta::EventCD> events;
dec.Decode(frame.evs.data, frame.evs.size, events);extractEvsTimestamp
【语法】Shimeta::EvsTimestamp extractEvsTimestamp(const uint8_t* data, size_t len);
【描述】从 apx003 RAW8 子帧头提取传感器时间戳(45-bit / 200 → 微秒)。顺序遍历子帧,取第一个头掩码匹配的。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| data | const uint8_t* (in) | RAW8 字节(至少含一个完整子帧 32768B) |
| len | size_t (in) | 字节数 |
【返回值】
| 返回值 | 描述 |
|---|---|
EvsTimestamp | valid=true → processed_timestamp 为微秒;valid=false → 未找到匹配子帧 |
【注意】与 MipiRaw8Decoder 配合使用:先提取时间戳、再解码事件。
【举例】
auto ts = Shimeta::codec::extractEvsTimestamp(frame.evs.data, frame.evs.size);
if (ts.valid) { /* ts.processed_timestamp = 微秒 */ }io
头文件:<shimetapi/io/event_reader.h>、<shimetapi/io/event_writer.h>、<shimetapi/io/hybrid_writer.h>、<shimetapi/io/hybrid_reader.h>。命名空间 Shimeta::io。
Shimeta::io::RawFormat
#include <shimetapi/io/event_reader.h>
enum class RawFormat { Evt2, Evt3, Unknown };Shimeta::io::EventReader
#include <shimetapi/io/event_reader.h>
作用:读取 RAW 事件文件(.raw),按文件头 ev_version 自动选 EVT2/EVT3 解码为 EventCD。
class EventReader {
public:
bool open(const std::string& filename);
void close();
bool isOpen() const;
RawFormat format() const;
std::pair<uint32_t, uint32_t> imageSize() const;
size_t readAllEvents(std::vector<EventCD>& events);
void reset();
};open
【语法】bool open(const std::string& filename);
【描述】打开 RAW 文件并解析文件头(自动识别 EVT2/EVT3)。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| filename | const std::string& (in) | RAW 文件路径 |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 打开成功 |
| false | 文件不存在 / 格式无效 |
【注意】打开后可用 format() / imageSize() 查询元信息。【举例】
Shimeta::io::EventReader reader;
reader.open("events.raw");readAllEvents
【语法】size_t readAllEvents(std::vector<EventCD>& events);
【描述】读取并解码文件中全部事件到 events。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| events | std::vector<EventCD>& (out) | 输出事件向量 |
【返回值】
| 返回值 | 描述 |
|---|---|
size_t | 读取的事件总数 |
【注意】大文件会占用大量内存(一次性读入);v2.0 暂无流式分批读取。
【举例】
std::vector<Shimeta::EventCD> events;
size_t n = reader.readAllEvents(events);format / imageSize / isOpen / close / reset
【语法】
RawFormat format() const; // 文件实际事件格式
std::pair<uint32_t, uint32_t> imageSize() const; // 传感器 {width, height}
bool isOpen() const; // 文件是否已打开
void close(); // 关闭文件
void reset(); // 读位置回到数据区起点【描述】查询与控制。
【参数】无。【返回值】见签名。【注意】reset() 可重复读取同一文件。【举例】无。
Shimeta::io::EventWriter
#include <shimetapi/io/event_writer.h>
作用:把事件写入 RAW 文件;支持原始字节透传(Frame.evs 直写)和事件编码写入两种路径。
class EventWriter {
public:
bool open(const std::string& filename, uint32_t width, uint32_t height,
RawFormat fmt = RawFormat::Evt3, uint64_t start_timestamp = 0);
void close();
bool isOpen() const;
size_t writeRaw(const uint8_t* data, size_t len);
size_t writeEvents(const std::vector<EventCD>& events);
void flush();
uint64_t writtenEventCount() const;
};open
【语法】bool open(const std::string& filename, uint32_t width, uint32_t height, RawFormat fmt = RawFormat::Evt3, uint64_t start_timestamp = 0);
【描述】创建新文件并写入文件头。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| filename | const std::string& (in) | 输出文件路径 |
| width | uint32_t (in) | 传感器宽度 |
| height | uint32_t (in) | 传感器高度 |
| fmt | RawFormat (in) | 决定头 ev_version,默认 Evt3 |
| start_timestamp | uint64_t (in) | 起始时间戳(微秒),默认 0 |
【返回值】bool(是否成功创建)。【注意】若文件已存在将被覆盖。【举例】无。
writeRaw
【语法】size_t writeRaw(const uint8_t* data, size_t len);
【描述】原始字节透传写入(Frame.evs 直写,不再编码)—— 最快。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| data | const uint8_t* (in) | 原始事件字节 |
| len | size_t (in) | 字节数 |
【返回值】size_t(写入字节数)。
【注意】要求写入的字节本身已是目标格式(EVT2/EVT3);不更新 writtenEventCount()。
【举例】
writer.writeRaw(frame.evs.data, frame.evs.size); // Frame.evs 直写writeEvents
【语法】size_t writeEvents(const std::vector<EventCD>& events);
【描述】用 Evt2Encoder 编码事件后写入。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| events | const std::vector<EventCD>& (in) | 待写入的事件向量 |
【返回值】size_t(写入事件数)。【注意】更新 writtenEventCount()。【举例】无。
flush / writtenEventCount / isOpen / close
【语法】
void flush(); // 强制刷新缓冲到磁盘
uint64_t writtenEventCount() const; // 已写入事件累计数
bool isOpen() const;
void close(); // 关闭(自动 flush)【参数】无。【返回值】见签名。【注意】采集结束务必 flush() 或 close(),确保数据落盘。【举例】无。
Shimeta::io::HybridWriter
#include <shimetapi/io/hybrid_writer.h>
作用:混合录制门面 —— EVS 存为 RAW 事件文件(复用 EventWriter),APS 原始帧存为 AVI(含 tsmp 时间戳 chunk)。APS 格式按输入 Frame.format 处理。
class HybridWriter {
public:
~HybridWriter();
bool open(const std::string& evs_path, const std::string& aps_path,
uint32_t width, uint32_t height, RawFormat evs_format = RawFormat::Evt3,
double aps_fps = 30.0);
bool writeFrame(const Shimeta::Frame& frame, const Shimeta::EvsTimestamp* evs_ts = nullptr);
void close();
uint32_t apsFrameCount() const;
};open
【语法】bool open(const std::string& evs_path, const std::string& aps_path, uint32_t width, uint32_t height, RawFormat evs_format = RawFormat::Evt3, double aps_fps = 30.0);
【描述】打开 EVS / APS 两路输出文件。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| evs_path | const std::string& (in) | EVS raw 文件路径 |
| aps_path | const std::string& (in) | APS AVI 文件路径 |
| width / height | uint32_t (in) | 传感器宽 / 高 |
| evs_format | RawFormat (in) | EVS 文件格式,默认 Evt3 |
| aps_fps | double (in) | 仅写入 AVI 头,不控制采集,默认 30.0 |
【返回值】bool。【注意】文件已存在会被覆盖。【举例】
Shimeta::io::HybridWriter hw;
hw.open("events.raw", "aps.avi", 768, 608);writeFrame
【语法】bool writeFrame(const Shimeta::Frame& frame, const Shimeta::EvsTimestamp* evs_ts = nullptr);
【描述】写一帧:EVS 走 writeRaw,APS 按 Frame.format 写入 AVI。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| frame | const Shimeta::Frame& (in) | 待写入的帧(frame.evs + frame.aps) |
| evs_ts | const Shimeta::EvsTimestamp* (in, 可选) | EVS 传感器时间戳;注入 AVI tsmp chunk,默认 nullptr |
【返回值】bool。【注意】evs_ts 可用 extractEvsTimestamp(frame.evs.data, frame.evs.size) 提取。【举例】
auto ts = Shimeta::codec::extractEvsTimestamp(frame.evs.data, frame.evs.size);
hw.writeFrame(frame, &ts);close / apsFrameCount
【语法】
void close(); // 关闭两路输出并收尾 AVI 索引
uint32_t apsFrameCount() const; // 已写入的 APS 帧数【参数】无。【返回值】见签名。【注意】close() 自动 flush。【举例】无。
Shimeta::io::HybridReader
#include <shimetapi/io/hybrid_reader.h>
作用:HybridWriter 的读取对偶 —— 读取其产出的混合录像(EVS raw + APS AVI,含 tsmp chunk)。与 Camera 一样返回原始字节,应用自行按格式解码。
class HybridReader {
public:
HybridReader(); ~HybridReader();
bool open(const std::string& evs_path, const std::string& aps_path);
void close();
bool isOpen() const;
uint32_t width() const;
uint32_t height() const;
double apsFps() const;
uint32_t apsFrameCount() const;
bool readApsFrame(Shimeta::Frame& out, Shimeta::EvsTimestamp* evs_ts = nullptr);
bool readEvsPacket(Shimeta::Frame& out, size_t packet_bytes = 0);
};open
【语法】bool open(const std::string& evs_path, const std::string& aps_path);
【描述】打开 EVS / APS 两路文件;任一路径为空则跳过该侧。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| evs_path | const std::string& (in) | EVS raw 文件路径(空 = 不读 EVS) |
| aps_path | const std::string& (in) | APS AVI 文件路径(空 = 不读 APS) |
【返回值】bool(两路均需成功打开对应文件)。
【注意】APS 侧解析 RIFF/AVI 头;输入/输出格式由录制时的 APS 帧格式决定(S100/USB 通常为 NV12,X5 为 Gray8);EVS 侧自动跳过 EVT3 文本头。
【举例】
Shimeta::io::HybridReader hr;
hr.open("events.raw", "aps.avi");readApsFrame
【语法】bool readApsFrame(Shimeta::Frame& out, Shimeta::EvsTimestamp* evs_ts = nullptr);
【描述】顺序读下一帧 APS 原始字节,格式由 .format 标记。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| out | Shimeta::Frame& (out) | 填充 .aps + .format/.width/.height/.ts.aps_ts_ns |
| evs_ts | Shimeta::EvsTimestamp* (out, 可选) | 该帧的传感器时间戳(从 AVI tsmp chunk 提取) |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 成功读取一帧 |
| false | 到达文件末尾 / APS 未打开 |
【注意】
out.aps.data为 APS 原始字节;应用层需根据out.format解码(NV12 转 BGR,Gray8 直接作为灰度图)。out.aps_owner持有 slab,Frame 离开 reader 后仍有效(自包含)。
【举例】
Shimeta::Frame f;
Shimeta::EvsTimestamp ts;
while (hr.readApsFrame(f, &ts)) {
// f.aps.data:按 f.format 解码(NV12 或 Gray8)
// ts.processed_timestamp = 微秒
}readEvsPacket
【语法】bool readEvsPacket(Shimeta::Frame& out, size_t packet_bytes = 0);
【描述】顺序读下一包 EVS 原始字节(已跳过 EVT3 文本头)。
【参数】
| 参数 | 类型 | 描述 |
|---|---|---|
| out | Shimeta::Frame& (out) | 填充 .evs(owner 自包含) |
| packet_bytes | size_t (in) | 每次读取字节数;0 = 默认 1 MiB(apx003 RAW8 单包 32768×32) |
【返回值】
| 返回值 | 描述 |
|---|---|
| true | 成功读取(out.evs.size 为实际读到的字节数,末包可能 < packet_bytes) |
| false | 到达文件末尾 / EVS 未打开 |
【注意】读到的原始字节需用 MipiRaw8Decoder(MIPI RAW8)或 Evt2Decoder/Evt3Decoder(EVT2/3)解码。
【举例】
Shimeta::codec::MipiRaw8Decoder dec;
Shimeta::Frame f;
while (hr.readEvsPacket(f)) {
std::vector<Shimeta::EventCD> events;
dec.Decode(f.evs.data, f.evs.size, events);
}width / height / apsFps / apsFrameCount / isOpen / close
【语法】
uint32_t width() const; // APS 宽
uint32_t height() const; // APS 高
double apsFps() const; // AVI 头帧率(无效回退 30.0)
uint32_t apsFrameCount() const; // AVI 头声明的总帧数
bool isOpen() const;
void close();【参数】无。【返回值】见签名。【注意】无。【举例】无。
MIPI 注意事项
APS 图像
Backend::MipiHvs 的 Frame.aps 由 VC1 通道提供,格式依板卡而异:
| 板卡 | Frame.format | 路径 | 应用处理 |
|---|---|---|---|
| S100 | NV12(彩色) | ISP→PYM 处理后 | cv::cvtColorTwoPlane 转 BGR |
| X5 | Gray8(灰度) | VIN 直读 RAW10(ISP 2A ioctl 受限,bypass 属预期行为) | 直接作为灰度图使用 |
Backend::Mipi(EVS-only)不提供 APS。
许可证
Apache License 2.0。EVT2/EVT3 编解码为基于公开规范的独立实现(clean-room),不含第三方闭源源码。
