docs(perception): record decoder parity and remaining full-graph bridge

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 13:14:11 +03:00
parent f102712f0b
commit a85aed2e03
3 changed files with 167 additions and 5 deletions
@@ -140,6 +140,55 @@ feed incremental decode and causal sensors into the same graph without using
the old concatenated camera file or precomputed geometry. Product source queues,
backend routes and the browser are not switched by this increment.
Stage-2 decoder increment, 2026-09-02 (`350366b`, `f102712`):
`media_fragments.py` now owns the existing bounded ISO-BMFF timing parser.
Archive inspection delegates to it and preserves `SessionIntegrityError` at its
boundary. `perception.streaming_decoder.FragmentDecoder` imports neither the
session store nor its materializer. It receives only bounded init/fragment bytes;
source filenames, recording length and EOF are not decoder inputs.
The measured subset is H.264, one 800×600 frame per fragment, one video track,
explicit moof-relative sample size/offset and no composition offset. The first
fragment must be random-access and the decoded frame must be keyframe; DTS must
remain contiguous. One persistent codec context, one slice thread, no flush or
future packet: each call must yield exactly one frame with the same PTS/raster.
Reordered/B-frame streams, unknown layouts, discontinuities and invalid output
fail closed. Other valid camera formats require explicit qualification, not a
hidden decoder fallback. These are current profile bounds, not a new K1 protocol.
PyAV 18.0.0 is pinned to wheel SHA-256
`ae56b40b6f8b067a8ad2dac664fbfbabac7f7a55b9a7bb031eb99289252bc017`.
It is installed only into a private experiment target and mounted read-only;
standalone packaging must include it. The public
[PyAV codec documentation](https://pyav.basswood.io/docs/stable/api/codec.html)
describes persistent packet decoding and thread modes; compatibility claims here
come from the actual 18.0.0 Worker probe, not from documentation version alone.
Sequential CPU-only 128-frame 1× comparisons produced exact BGR parity against
the previous pinned OpenCV decoder. Direct validated sample extraction replaces
opening/demuxing init+fragment on every frame; NumPy loads before readiness.
Measured new-decoder p95 improves 19.927→11.156 ms, p99 20.920→18.675 ms.
This is one bounded component comparison, not a full-profile speedup claim.
The reference full-MP4 path exists only in the separate pixel-comparison process;
neither new decoder path mounts/reads that MP4.
Combined IPC/decoder probe accepts 103 raw events and yields 32 exact BGR frames.
31 frames arrive before the source End marker; the final frame drains before
the receiver handles End. First decoded callback is 3.071 s before the marker.
Input reservations peak at 5,727,751 bytes including conservative decoder scratch
and init/extradata retention; normal and truncated-input cleanup return to zero.
Native codec/DPB allocations are bounded separately by the CPU-only container;
application payload counters alone do not constrain native allocation or execution
time. Before full-graph integration, native decoding must run in a supervised CPU
child with bounded RPC and explicit decoded-bundle ownership transfer.
Point/pose are preserved raw in this probe, not causally fused into a scene;
calibration identity is explicitly non-scene/synthetic. No full graph, GPU model,
network, physical live feed, vehicle control or product cutover is qualified.
Next: preserve the existing causal sensor cut at camera release, connect decoded
bundles to the same full graph, then repeat full-profile parity/timing. The last
full-profile p95/p99 remains 124.98/136.12 ms, not this decoder's timing.
Open → validate bounded metadata/claim → warm models → Ready → start the replay
clock → observations and incremental scenes → stop/drain bounded state → close
and asynchronously seal the immutable receipt. A live source already producing