Read Events
Task goal
Get the "event stream" into your program. Events come from two sources: a real-time camera and a recording file. This page covers how to read from both and what the fields mean.
Classes and concepts
Shimeta::hv::Camera::GetFrame/SetEventCallback: get events in real time (synchronous / asynchronous).Shimeta::codec::Evt2Decoder/Evt3Decoder(plusMipiRaw8Decoderfor MIPI): decode raw event bytes intoEventCD.Shimeta::io::EventReader: read and decode from a RAW file.Shimeta::EventCD: a single event with fields(x, y, t, polarity)— coordinates, timestamp (microseconds), polarity.
Key change in v2.0
The v2.0 camera hands you raw event bytes (Frame.evs / EventPacket.data, in the format chosen by DeviceConfig.event_fmt) and does not directly hand you decoded events. You decode the bytes into EventCD with the corresponding codec. This replaces the old startEventCapture flow that directly delivered a vector<EventCD> callback.
Live camera: getting events + decoding
Synchronous: GetFrame + decoding Frame.evs
#include <shimetapi/hv/camera.h>
#include <shimetapi/hv/device_config.h>
#include <shimetapi/codec/evt2_codec.h>
#include <vector>
Shimeta::hv::Camera cam;
Shimeta::hv::DeviceConfig cfg;
cfg.backend = Shimeta::hv::Backend::Usb;
cfg.vendor_id = 0x1d6b;
cfg.product_id = 0x0105;
cfg.event_fmt = Shimeta::hv::EventFormat::Evt2; // Determines the Frame.evs format → which Decoder to pick
cam.Init(cfg);
cam.StartStream();
Shimeta::codec::Evt2Decoder dec; // Stateful: maintains the time base across packets; construct outside the loop and reuse
Shimeta::Frame f;
while (cam.GetFrame(f, 1000)) {
std::vector<Shimeta::EventCD> events;
dec.Decode(f.evs.data, f.evs.size, events); // Raw bytes → EventCD
for (const auto& e : events) {
// e.x, e.y: pixel coordinates; e.polarity: polarity (true = brighten / false = darken); e.t: timestamp (us)
}
}
cam.StopStream();
cam.Destroy();event_fmt to decoder mapping: Evt2 → Evt2Decoder; Evt3 → Evt3Decoder. Both are stateful — reuse the same instance across packets of a stream, and call Reset() before starting a new stream.
Asynchronous: SetEventCallback
The callback receives an EventPacket whose data is a packet of raw event bytes; decode it with the codec the same way:
Shimeta::codec::Evt2Decoder dec; // Reuse across callbacks; do not construct per call
cam.SetEventCallback([&dec](const Shimeta::hv::EventPacket& pkt) {
std::vector<Shimeta::EventCD> events;
dec.Decode(pkt.data.data, pkt.data.size, events);
// Process events
});Callback-thread notes
Callbacks fire serially on the dispatch thread (the capture thread does not invoke callbacks). Do not do blocking work inside the callback or call the camera's synchronous interfaces back; offload heavy computation to a worker thread.
MIPI HVS: using MipiRaw8Decoder
Frame.evs from Backend::MipiHvs is not an EVT2/EVT3 byte stream but an apx003 RAW8 sub-frame stream — it must be decoded with MipiRaw8Decoder (not Evt2/Evt3Decoder). It is stateless: no cross-packet reuse, no Reset() needed:
#include <shimetapi/codec/mipi_raw8_codec.h>
Shimeta::codec::MipiRaw8Decoder dec;
Shimeta::Frame f;
while (cam.GetFrame(f, 1000)) {
std::vector<Shimeta::EventCD> events;
dec.Decode(f.evs.data, f.evs.size, events); // RAW8 sub-frame stream → EventCD
}The old MIPI split into "record callback / display callback / RAW8 callback" is merged in the v2.0 unified API: you get the raw bytes and decode them yourself, and the display frame rate is controlled at the application layer (e.g. by lowering the frame-pickup rate or processing only some sub-frames).
S100 and X5 share the same event byte layout and decoder; the differences are mainly the platform libraries, sensor index, and APS format. Event-reading code does not need two versions.
Recording file: EventReader
After Shimeta::io::EventReader opens a RAW file, it automatically picks EVT2/EVT3 decoding from the header's ev_version; readAllEvents returns all decoded events in one call:
#include <shimetapi/io/event_reader.h>
#include <iostream>
Shimeta::io::EventReader reader;
reader.open("events.raw");
std::vector<Shimeta::EventCD> events;
size_t n = reader.readAllEvents(events); // Internally picks EVT2/EVT3 decoding automatically
std::cout << "共 " << n << " 个事件" << std::endl;Current limitation
The v2.0 EventReader currently only provides readAllEvents (reads everything into memory); batched / streaming reads are not yet available. Watch memory usage with very large files; to process in chunks, you can split the file by byte offsets yourself and feed the chunks to the corresponding Decoder.
File formats (EVT2 / RAW8 / CSV) and conversion at Data Formats.
EventCD fields
struct EventCD {
uint16_t x; // Pixel X coordinate
uint16_t y; // Pixel Y coordinate
int64_t t; // Timestamp (microseconds)
bool polarity; // true = CD_ON (brighten), false = CD_OFF (darken)
};Field names differ slightly from the old
Metavision::EventCD: the polarity field ispolarity(bool), not the oldp(int).
Further reading
- Full API: Toolkit C++ API
- Save the events you read: Guide 03 — Record & Replay
- Denoise events before using them: Guide 04 — Event Processing (Denoise)
