feat(sim): replay a directory of real images as captures (playlist pattern) - #14
Merged
Conversation
added 2 commits
August 22, 2026 16:33
Adds a `playlist` pattern to the simulator backend so a downstream vision
component receives genuine imagery through the real camera path instead of
synthetic colour bars (D-CAM-31, for image-processor D-IP-18).
`frame.pattern` now accepts `{ "playlist": { directory, include, order, loop,
advance } }` beside the four synthetic tokens. The directory is walked once at
connect - deterministic, symbolic links refused, bounded at 10,000 files and 32
levels, and a directory matching no file fails the connect - and ordered
`sorted` by relative path or `seeded` by a SplitMix64 Fisher-Yates shuffle keyed
by the simulator seed. Each capture yields the next file with that file's own
dimensions and format and runs the unchanged finalize path: temp write, fsync,
sidecar first, atomic visibility, catalog row, `ImageCaptured`.
A JPEG member captured under `passthrough` or `raw` is delivered as the bytes on
disk, so the announced and sidecar `image.sha256` is the source file's own
digest; every other combination decodes to RGB8/Mono8 and re-encodes through the
ordinary encoding stage. Byte-preserving replay stays JPEG-only because
`OutputEncoding::Passthrough` already requires a complete JPEG source.
The terminal body carries `backendMetadata.playlist` (`sourcePath`, `index`), and
the backend session-status surface carries `playlist{count,index,directory}`.
`CaptureRequest` gains an opaque `trigger_key`, derived adapter-side from the
durable `CaptureTrigger`, which `advance: perTrigger` compares for equality, so
no EdgeCommons message shape crosses the backend seam.
`config.schema.json`, `docs/reference/configuration.md`, `docs/how-to-guides.md`,
and `DESIGN.md` (section 6.2.1 plus decision D-CAM-31) are updated in the same
change.
The playlist cursor now advances one file per capture, full stop. `advance` (`perCapture` / `perTrigger`) is removed from the configuration, the schema, the reference and how-to docs, and D-CAM-31; the register keeps the reasoning for dropping it. `perTrigger` was the only reason a capture had to know which operator action or schedule occurrence produced it, so `CaptureRequest.trigger_key` and the `CaptureTrigger`-derived key that fed it are removed as well. That restores the backend seam and the twelve `CaptureRequest` construction sites in the GenICam, ONVIF, and RTSP backends to what they were, and leaves the playlist feature touching only the simulator, its configuration, and its own tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
frame.pattern.playlistto thesimbackend (decision D-CAM-31; requested byimage-processorD-IP-18): the simulator replays a directory of real image files as captures through the real finalize path — temp write, fsync, sidecar first, atomic visibility, catalog record,ImageCapturedannouncement with the file's trueimage.bytes/image.sha256— so downstream vision components receive genuine imagery from the real camera contract.loop: falsefails cleanly when spent.passthrough; other combinations decode and re-encode (PNG passthrough would need a newPixelFormatvariant across all backends — recorded in the D-CAM-31 rationale).backendMetadata.playlist{sourcePath, index}on the terminal body / sidecar / catalog;playlist{count, index, directory}on session status.Docs:
config.schema.json(oneOfverified against the parser),docs/reference/configuration.md,docs/how-to-guides.md("Replay real images with the simulator"),DESIGN.md§6.2.1 + register.Validation
cargo test: 655 passed, 0 failed, 1 ignored (+ integration binaries ok);cargo clippy --all-targets -- -D warnings: clean.cargo llvm-cov --fail-under-lines 90: 92.17 % bundle;diff-cover --fail-under=95: 95 % on the diff (the#[cfg(unix)]symlink/containment tests run on the Linux runner).image.sha256equals the replayed file's digest and thatbackendMetadata.playlistis present.