lcameraDev: add resolve-only deviceSelector API and deduplicate resolve paths.

Export lcameraDev_resolveDeviceSelectorCReq for attach-identity consumers,
factor live-camera snapshot helpers, and share resolveDeviceSelectorAgainstRecords
with get-or-create session acquisition.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-14 11:02:11 -04:00
parent 7a47f2bd49
commit 7af684039d
9 changed files with 229 additions and 34 deletions
+51 -12
View File
@@ -117,15 +117,33 @@ Possible future params (not implemented in v1):
### `lcameraBuff()` stim-buff-api params
Reserved for per-producer options (frame rate caps, pixel format preference).
Channel selection is driven by the qualeIface name, not by stim-buff-api params.
Channel selection is driven by the qualeIface name (`colour-yuv-y/u/v`), not by
stim-buff-api params. Params configure the shared camera mode for all three
attachments on the same device.
Possible future params:
**Resolution (mutually exclusive — use one group only):**
* `fps-hz=30`
* `width=640|height=480`
* `pixfmt=NV12` — negotiation hint for `lcameraBuff` stream setup (not
`lcameraDev`)
| Group | Synonyms | Meaning |
|---|---|---|
| Explicit dimensions | `frame-width`, `frame-w`, `dimension-width`, `dimension-w`, `dim-width`, `dim-w` | Capture width in pixels |
| Explicit dimensions | `frame-height`, `frame-h`, `dimension-height`, `dimension-h`, `dim-height`, `dim-h` | Capture height in pixels |
| Vertical shorthand | `vertical-resolution`, `v-resolution`, `v-res`, `vres` | Preset token: `360`, `360p`, `480`, `480p`, `720`, `720p`, `1080`, `1080p` |
**Other params:**
| Synonyms | Meaning |
|---|---|
| `colorspace`, `color-space`, `colourspace`, `colour-space` | Semantic colour model (`yuv` in v1) |
| `full-planar-is-optional`, `opt-planar` | Allow semi-planar or packed YUV when fully planar is unavailable (presence or empty value means enabled; use `=false` to disable) |
Example:
```text
lcameraBuff(v-res=480p|colour-space=yuv|opt-planar)
```
Stage 2 (`lcameraBuff`) attach/configure/classify is implemented; capture daemon
and frame publication remain future work.
## Device selector format
@@ -256,13 +274,13 @@ Rules:
(conflicting mode requests on the same physical camera).
* `fullPlanarIsOptional == false` (default): must select a fully planar YUV
format or throw with candidate-format diagnostics.
* `fullPlanarIsOptional == true`: rejected at the configure API until
`lcameraBuff` implements non-planar producer deinterleaving (Stage 2). The
policy helper still accepts optional planar selection for future use.
* `fullPlanarIsOptional == true`: may select semi-planar or packed YUV (e.g.
`YUYV` on UVC webcams). `lcameraBuff` classifies the layout and sizes channel
placeholder buffers; OpenCL deinterleave and capture start are later stages.
Streaming, frame delivery, and per-frame colourspace work remain **out of scope**
for `lcameraDev`; `lcameraBuff` uses the configured session to allocate buffers
and start capture on attach.
for `lcameraDev`; `lcameraBuff` uses the configured session for attach-time
setup and will allocate capture buffers / start streaming in later stages.
## dlopen API
@@ -298,6 +316,9 @@ struct LcameraDevGetOrCreateResult
typedef sscl::co::ViralNonPostingInvoker<LcameraDevGetOrCreateResult>
lcameraDev_getOrCreateDeviceCReqFn(const std::string& deviceSelector);
typedef sscl::co::ViralNonPostingInvoker<CameraIdentityRecord>
lcameraDev_resolveDeviceSelectorCReqFn(const std::string& deviceSelector);
typedef sscl::co::ViralNonPostingInvoker<void>
lcameraDev_releaseDeviceCReqFn(
const std::shared_ptr<CameraSession>& deviceSession);
@@ -308,6 +329,24 @@ Failures throw `std::exception`. `lcameraBuff` holds the returned
session wraps the acquired `libcamera::Camera`; higher layers configure the mode
then stream from that handle.
### Selector resolution (resolve-only)
```cpp
typedef sscl::co::ViralNonPostingInvoker<CameraIdentityRecord>
lcameraDev_resolveDeviceSelectorCReqFn(const std::string& deviceSelector);
```
Parses and resolves a `deviceSelector` against the live libcamera camera list
using the same narrowing rules as `getOrCreateDeviceCReq`, but does **not**
create a session, acquire a camera, or change session refcounts. Use this when
a consumer already holds session-scoped state keyed by `CameraIdentityRecord::id`
(for example `lcameraBuff` detach) and only needs the canonical resolved camera
identity from an input DAP line.
Internally both resolve-only and get-or-create paths share
`resolveDeviceSelectorAgainstRecords()` in `selectorResolve.cpp` and the live
camera snapshot helpers in `cameraManagerState.cpp`.
### Session mode configuration
```cpp