Timestamp Output
This sample shows how to export TimestampFrame output from DELTA raw data. It
uses a two-phase workflow: first save live sensor data as a .dvs file, then
reopen the saved file with playback and export per-pixel ON/OFF timestamps.
Back to Code Samples.
Example Overview
| Step | SDK API | Purpose |
|---|---|---|
| 1 | scanDevices() / openDevice() |
Find and open a connected DELTA Series camera. |
| 2 | applySensorSetting() |
Apply the recommended sensor setting file. |
| 3 | startStream() |
Start live USB streaming. |
| 4 | startRawSaving() / saveRawBy*() |
Save raw sensor data as a .dvs file. |
| 5 | openFile() / startPlayback() |
Reopen the saved .dvs file for offline conversion. |
| 6 | setFrameGeneration() |
Choose how events are grouped into generated frames. |
| 7 | setOutputType(OutputType::TimestampFrame) |
Generate timestamp frame output. |
| 8 | getTimestampFrameBufferSize() |
Get the required timestamp buffer size. |
| 9 | getTimestampFrame() |
Read per-pixel ON/OFF timestamp arrays. |
| 10 | setReadOverCallback() |
Detect when playback reaches the end of the file. |
Expected Result
When the sample runs successfully, a timestamp_frame folder is created under
the save directory. The folder contains the raw data captured during Phase 1
and the timestamp frame export files generated during Phase 2.
timestamp_frame/
├─ raw_data/
| └─ year-month-day-hour-minute-second-DELTA.dvs
├─ timestamp_frame_data.bin
├─ timestamp_frame_frame_timestamps.csv
└─ timestamp_frame_metadata.txt
The raw_data folder stores the .dvs raw data file recorded from the camera.
timestamp_frame_data.bin is a binary tensor-style dump of all exported
TimestampFrame data. For each generated frame, the file stores the full ON
timestamp image first, followed by the full OFF timestamp image.
Frame 0: ON[H*W] OFF[H*W]
Frame 1: ON[H*W] OFF[H*W]
Frame 2: ON[H*W] OFF[H*W]
...
Each value is stored as uint32 in row-major order and uses microseconds as
the unit. A value of 0 means that no timestamp was recorded for that pixel in
that channel.
timestamp_frame_frame_timestamps.csv stores one timestamp per generated
frame. This is the lastTimestamp value for each frame and can be used later
for time-surface or decay-based processing.
timestamp_frame_metadata.txt stores the information needed to read the binary
file correctly.
width=960
height=720
frame_count=959
dtype=uint32
channels=on,off
units=microseconds
layout=row-major (H,W) per channel; ON channel then OFF channel per frame
Note
timestamp_frame_data.bin is not an image file. It is a compact binary
export of per-pixel timestamp values. Use the metadata file to interpret the
width, height, frame count, data type, channel order, and layout.
Code Walkthrough
Edit the User Control Panel
The USER CONTROL PANEL section controls camera selection, frame generation,
raw saving mode, and output directories.
Select a Camera
const std::int32_t selectDeviceIndex = 0;
Select a Frame Generation Mode
Only one selected_framemode line should be active at a time.
const std::string selected_framemode = "FrameEndBased";
const std::int32_t frameEndCount = 1;
// const std::string selected_framemode = "TimeBased";
const std::int32_t framePeriodMs = 16;
// const std::string selected_framemode = "EventCountBased";
const std::int32_t eventsPerFrame = 50000;
Frame generation determines when a new TimestampFrame is produced during
offline conversion.
Select a Raw Saving Mode
const std::string selected_savemode = "Continuous";
// const std::string selected_savemode = "Time";
const std::int32_t durationMs = 5000;
// const std::string selected_savemode = "FrameCount";
const std::uint64_t targetFrames = 100;
// const std::string selected_savemode = "EventCount";
const std::uint64_t targetEvents = 1000000;
Continuous starts saving when you press s and stops when you press q.
Other modes call saveRawByTime(), saveRawByFrameCount(), or
saveRawByEventCount().
Select Output Directories
const std::filesystem::path rawSaveDirectory =
std::filesystem::path(DELTA_SAMPLE_ROOT) / "saved_data" / "timestamp_frame" / "raw_data";
const std::filesystem::path outputSaveDirectory =
std::filesystem::path(DELTA_SAMPLE_ROOT) / "saved_data" / "timestamp_frame";
Phase 1: Capture Raw Data
The example saves a .dvs file first so timestamp export speed does not affect
live sensor capture.
status = delta::startStream(cameraHandle);
status = delta::startRawSaving(cameraHandle, rawSaveDirectoryString.c_str());
After saving finishes, the example locates the newly saved .dvs file.
Phase 2: Select TimestampFrame Output
The saved file is reopened with playback, and TimestampFrame is selected as
the only processing output.
status = delta::openFile(rawFileString.c_str(), &fileHandle);
status = delta::setPlaybackMode(fileHandle, delta::PlaybackMode::Once);
status = delta::setFrameGeneration(fileHandle, frameGeneration);
status = delta::setOutputType(fileHandle, delta::OutputType::TimestampFrame);
Prepare Timestamp Buffers
TimestampFrame requires two equally sized uint32_t arrays.
const std::uint32_t tsBufferSize =
delta::getTimestampFrameBufferSize(fileHandle);
const std::uint32_t tsPixelCount =
tsBufferSize / sizeof(std::uint32_t);
std::vector<std::uint32_t> tsOnBuffer(tsPixelCount);
std::vector<std::uint32_t> tsOffBuffer(tsPixelCount);
delta::TimestampFrame tsFrame{};
tsFrame.onEvent = tsOnBuffer.data();
tsFrame.offEvent = tsOffBuffer.data();
tsFrame.bufferSize = tsBufferSize;
| Buffer | Meaning |
|---|---|
onEvent |
Latest ON event timestamp per pixel. |
offEvent |
Latest OFF event timestamp per pixel. |
lastTimestamp |
Latest timestamp observed for the generated frame. |
Timestamp values are in microseconds. A value of 0 means no timestamp is
stored for that pixel.
Detect End of Playback
PlaybackMode::Once fires this callback once the file has been fully read. A
few more frames can still be in flight in the processing pipeline at that
point, so the sample keeps polling for a short grace period afterward instead
of stopping immediately.
std::atomic<bool> playbackDone{false};
status = delta::setReadOverCallback(
fileHandle,
[](void* userData) { static_cast<std::atomic<bool>*>(userData)->store(true); },
&playbackDone
);
Once playbackDone is set, the polling loop allows up to 100 consecutive
empty polls to drain any remaining frames before it stops.
constexpr int kDrainRetriesAfterEnd = 100;
int drainRetries = 0;
while (true) {
status = delta::getTimestampFrame(fileHandle, &tsFrame, 0);
if (status != delta::Status::Success) {
if (playbackDone.load() && ++drainRetries >= kDrainRetriesAfterEnd) { break; }
continue;
}
drainRetries = 0;
// ... write frame to output files ...
}
Export Timestamp Data
The sample writes three output files.
| File | Contents |
|---|---|
timestamp_frame_data.bin |
Concatenated frames. Each frame stores ON timestamps followed by OFF timestamps. |
timestamp_frame_frame_timestamps.csv |
Per-frame lastTimestamp values. |
timestamp_frame_metadata.txt |
Width, height, frame count, dtype, units, and layout information. |
status = delta::getTimestampFrame(fileHandle, &tsFrame, 0);
binFile.write(
reinterpret_cast<const char*>(tsOnBuffer.data()),
tsOnBuffer.size() * sizeof(std::uint32_t)
);
binFile.write(
reinterpret_cast<const char*>(tsOffBuffer.data()),
tsOffBuffer.size() * sizeof(std::uint32_t)
);
timestampsFile << frameIndex << ',' << tsFrame.lastTimestamp << '\n';
Stop Playback
delta::stopPlayback(fileHandle);
delta::closeFile(fileHandle);