Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

platform-integration.md

v0.1.0-build.85 Latest Commit ede38f5

Size
4.7 KB
Lines
68
Language
markdown
SHA-256
5170c3756cb2…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1# Integrating the CKey scanner into a camera platform
2
3This guide is for teams that own a camera pipeline: OS vendors, camera apps and scanning frameworks. It covers specification §6 and the benchmark plan that §12 leaves open. Adoption remains each platform's decision, and nothing here implies one has been made.
4
5## What to take
6
7| Component | Library | Header | Notes |
8|---|---|---|---|
9| Codeword framing, RS, CRC | `ckey_codec` | `ckey/ckey.h` | no dependencies |
10| Detection, refinement, decoding | `ckey_scan` | `ckey/ckey.h` | needs only `ckey_codec`; no renderer, no telemetry, no network, no file system, no threads |
11| Payload interpretation | your code | [`spec/CKey-Payload-Conventions.md`](../spec/CKey-Payload-Conventions.md) | allowlisted schemes only; never act without a tap |
12
13Do not link `ckey_render`, `ckey_certify` or `ckey_telemetry` in a scanner. Configure with `-DCKEY_BUILD_TELEMETRY=OFF` to leave telemetry out of the build entirely.
14
15## Pipeline for each frame
16
17The reference loop is `ios/CKeyReader/CameraScanner.swift`, and every SDK repeats it.
18
191. **Luma plane:** the Y plane of a 420 buffer is enough. No colour conversion is needed.
202. **Find borders:** call `ckey_find_borders_gray8(gray, w, h, stride, quads, max)` with up to 6 candidates. These are oriented quadrilaterals of the continuous frame stroke.
213. **Refine and decode Profile 0:** for each candidate, call `ckey_refine_quad_gray8(..., CKEY_FIELD_SCALABLE, quad)`. If it scores above 0, call `ckey_decode_scalable_gray8(...)` with an output buffer of 65,535 bytes. The decoder identifies the version and layout from the keys.
224. **Legacy profiles (optional):** repeat with `CKEY_FIELD_LOCATOR`, `CKEY_FIELD_TEXT` and `CKEY_FIELD_EXTENDED` and their decoders.
235. **Emit the first valid decode.** Every result has passed Reed–Solomon and CRC-32C. The candidate ranker only orders the work; it accepts nothing.
24
25**Threading:** every call is reentrant and keeps no global mutable state. Layout tables are built once, behind `std::call_once`. Run one frame per worker.
26
27**Memory:** the caller owns all buffers. The decoder allocates a few working vectors per call, proportional to the symbol's size.
28
29## Security review surface
30
31- **Bounded inputs:**
32 - Image calls validate dimensions, strides and quads before reading.
33 - The decoders never write past `out_capacity` and report the required size instead.
34 - The `.ckey` reader, which a scanner does not need, is bounded and checks its CRC. It is fuzzed in CI with 20,000 mutations under ASan/UBSan.
35- **No parsing of untrusted text in the scanner.** Payload bytes come back verbatim, and interpreting them is your code's job, under the conventions' safety rules.
36- **CI hardening:** a Debug ASan/UBSan matrix runs on every push (`.github/workflows/ci.yml`).
37- **Determinism:** fixed tables and seeded hashes. `tests/vectors/conformance-v1.json` pins codewords and geometry.
38
39## Conformance
40
41Run `ckey-conformance --check tests/vectors/conformance-v1.json` against your build, then decode the vectors' rasters through your own image path. Any mismatch in a codeword or the geometry hash is a conformance failure ([details](../tools/conformance/README.md)).
42
43## Benchmark test plan (proposed)
44
45This defines a latency target as specification §6 requires. Every target is stated per device, per image size, per profile/version and per percentile. Nothing has been measured on devices yet.
46
47| Dimension | Values |
48|---|---|
49| Devices | the vendor's current base model and its oldest supported model (on iOS, also the Neural Engine-free path) |
50| Frame | 1920×1080 and 3840×2160 luma, at the camera's native rate |
51| Symbols | P0 v1, v6, v16, v31 at level M, standard layout, plus P0.1 v6 |
52| Printed sizes | 0.5 in, 1 in and 2 in, on matte paper and on a phone screen |
53| Distances | as far as the camera can go with the symbol still covering 2–4 px per module |
54| Lighting | 50, 300 and 1,000 lux; backlit; with specular glare |
55| Motion | handheld, and on a 20°/s pan |
56| Clutter | the symbol among QR codes, text and patterned backgrounds |
57
58The plan collects 300 captures per cell, labelled with the payload. From each cell it reports:
59
60- frame latency at p50, p90 and p99;
61- time from first frame to first decode, at p50, p90 and p99;
62- the rate of decoding within 1 second;
63- false positives per 10,000 symbol-free frames;
64- results for QR at the same printed area, for comparison.
65
66The proposed acceptance target is first decode at p90 under 200 ms, on the base device at 1080p, for v1–v16 at 1 in and 30 cm. This target must be confirmed with measured data before anyone quotes it.
67
68`ckey-bench` (in [`docs/benchmarks`](benchmarks)) runs the same metrics on synthetic frames, so a regression can be caught before device runs.