{"id":49769774,"url":"https://github.com/sysprog21/vpipe","last_synced_at":"2026-05-13T14:00:52.865Z","repository":{"id":356267842,"uuid":"1231656126","full_name":"sysprog21/vpipe","owner":"sysprog21","description":"A Linux-only V4L2 mem2mem prototype for measuring the cost of a camera-to-userspace frame path: copies, queueing, context switches, scheduler jitter, cache behavior, and a small deterministic kernel-side preprocessing step.","archived":false,"fork":false,"pushed_at":"2026-05-07T10:31:37.000Z","size":66,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-11T12:44:48.470Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sysprog21.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T06:57:39.000Z","updated_at":"2026-05-11T08:15:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sysprog21/vpipe","commit_stats":null,"previous_names":["sysprog21/vpipe"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sysprog21/vpipe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvpipe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvpipe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvpipe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvpipe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sysprog21","download_url":"https://codeload.github.com/sysprog21/vpipe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvpipe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32940110,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T09:19:52.626Z","status":"ssl_error","status_checked_at":"2026-05-12T09:17:33.438Z","response_time":102,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-11T12:11:52.138Z","updated_at":"2026-05-12T13:01:00.734Z","avatar_url":"https://github.com/sysprog21.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vpipe\n\n`vpipe` is a Linux-only V4L2 mem2mem prototype for measuring the cost of\na camera-to-userspace frame path: copies, queueing, context switches,\nscheduler jitter, cache behavior, and a small deterministic kernel-side\npreprocessing step. It is not a vision stack.\n\nThe driving question:\n\n\u003e Which costs in the frame path come from copies, context switches, buffer\n\u003e queueing, scheduler jitter, and cache behavior?\n\nTo keep that measurable, the baseline is constrained to single-plane\n`V4L2_PIX_FMT_GREY` at 640×480, one mem2mem node, one metadata sideband\nmiscdevice, one threshold algorithm over a clamped ROI, and deterministic\nfixture-driven validation before any live camera path.\n\n## Architecture\n\n```text\n┌──────────────────────────── userspace ────────────────────────────┐\n│                                                                   │\n│   vivid /dev/video0          vpipe /dev/videoN     /dev/vpipe-meta│\n│        │                         ▲      │              │          │\n│        │ VIDIOC_DQBUF            │      │ VIDIOC_DQBUF │ read(2)  │\n│        │      (CAPTURE)          │      │   (CAPTURE)  │          │\n│        ▼                         │      ▼              ▼          │\n│   correlate src_v4l2_sequence    │   write CSV / PGM artifacts    │\n│        │                         │                                │\n│        └──► VIDIOC_QBUF (OUTPUT, DMABUF or MMAP) ──┐              │\n│                                                    │              │\n└────────────────────────────────────────────────────┼──────────────┘\n                                                     ▼\n┌─────────────────────────── kmod/vpipe.ko ─────────────────────────┐\n│   OUTPUT queue ──► Tiny CV (threshold over ROI) ──► CAPTURE queue │\n│                              │                                    │\n│                              └──► /dev/vpipe-meta (ring buffer)   │\n│                                                                   │\n│   src_v4l2_sequence, timestamp_ns, algo_id, algo_status, ROI,     │\n│   algo_value0/1, flags  → one row per processed frame             │\n└───────────────────────────────────────────────────────────────────┘\n```\n\nUserspace owns orchestration, sequence correlation, and artifact capture.\nThe kernel owns transport mechanics and a deliberately small image\ntransform. Metadata is a separate device so transport timing and\nalgorithm output can be correlated without overloading the pixel\npayload. See `docs/design.md` for the ownership model.\n\n## Data Path Concretely\n\nThe mem2mem node accepts source frames on its OUTPUT queue (either\nimported via `V4L2_MEMORY_DMABUF` or staged through `V4L2_MEMORY_MMAP`)\nand produces processed frames on its CAPTURE queue. Per-buffer controls\n(`VPIPE_CID_SRC_SEQUENCE`, `VPIPE_CID_ALGO`, `VPIPE_CID_THRESHOLD`,\nROI controls) are snapshotted at QBUF time so concurrent control\nupdates cannot race a frame already in flight.\n\nThe fixture-driven path uses `dma-heap` (`/dev/dma_heap/system`) for\ndeterministic source allocation: one explicit userspace `memcpy()` from\nfixture bytes into the heap mapping, then DMABUF transport into vpipe.\nThis makes the copy count auditable and prevents accidental zero-copy\nclaims on virtual devices.\n\n## Components\n\nKernel side, in `kmod/`:\n\n- `vpipe-m2m.c` — V4L2 mem2mem node, queueing, format negotiation,\n  per-buffer control snapshotting, `device_run()` entry point\n- `vpipe-meta.c` — metadata miscdevice with per-open reader cursors\n  over a shared ring; overruns catch readers up to the current window\n- `vpipe-cv.c` — bounded Tiny CV; currently threshold over a clamped\n  GREY ROI, no floating point or hot-path allocation\n- `vpipe.h` — shared UAPI: ioctls, control IDs, metadata layout\n\nUserspace side, in `user/` (binaries are kebab-case):\n\n- `vpipe-capture-mmap`, `vpipe-capture-read` — Phase 1 baselines\n- `vpipe-capture-dmabuf` — DMABUF transport exerciser via vivid `EXPBUF`\n- `vpipe-capture-m2m` — full vivid → vpipe pipeline with selectable\n  DMABUF or MMAP OUTPUT transport\n- `vpipe-bench-fixture` — repeated heap-backed fixture transport bench\n- `vpipe-meta-drain` — `read(/dev/vpipe-meta)` to CSV recorder\n- `vpipe-fixture-feed` — deterministic single-shot fixture injection\n- `vpipe-cv-ref` — userspace threshold reference for byte-for-byte\n  comparison against the kernel output\n- `vpipe-pgm-diff` — absolute per-pixel PGM diff generator\n\n## Build And Validation\n\nLinux-only; the top-level `Makefile` does not enter a guest\nautomatically. The reference validation environment is an Ubuntu 25.10\n`aarch64` lima guest running kernel `6.17.0-22-generic`.\n\n```sh\nmake             # install hooks (first run), then build kmod/ and user/\nsudo make check  # validation suite (requires privileges)\n```\n\n`make check` runs userspace + kernel builds, the userspace unit tests\n(CRC32, PGM I/O, threshold reference), vivid enumeration, module load,\nfixture-driven metadata sanity (sequence contiguity and algo state),\na short Phase 1 mmap capture, the Phase 5 UAPI-state probe, and the\nfull Tiny CV fixture validation. Phase 5 is gated programmatically:\nthe suite fails loudly if the guest's V4L2 headers ever grow\n`V4L2_BUF_FLAG_IN_FENCE`, `V4L2_BUF_FLAG_OUT_FENCE`, or a `fence_fd`\nfield, forcing a Phase 5 reopen rather than silent acceptance.\n\nLonger-run measurement entrypoints:\n\n- `sudo scripts/bench_capture.sh 600 /dev/video0 bench`\n- `sudo scripts/bench_vpipe.sh /dev/video0 /dev/videoN bench/dmabuf-none 600 dmabuf`\n- `sudo scripts/bench_vpipe.sh /dev/video0 /dev/videoN bench/mmap-none 600 mmap`\n- `sudo scripts/bench_fixture.sh /dev/videoN /dev/dma_heap/system tests/fixtures/ramp.pgm bench/heap-threshold 600 threshold`\n\n## Validation Artifacts\n\nBench and `make check` runs write into a flat, gitignored `bench/`\ndirectory using suffix-based naming:\n\n- `bench/\u003crun\u003e.csv` — per-frame log (enqueue/dequeue ns, sequence,\n  bytesused)\n- `bench/\u003crun\u003e.meta.csv` — corresponding metadata sideband drain\n- `bench/\u003crun\u003e.perf.csv` — `perf stat` counters for the run\n- `bench/\u003cfixture\u003e.{input,reference,kernel,diff}.pgm` — Tiny CV review\n  set per fixture\n\nThe review loop is `fixture → userspace reference → kernel output →\ncmp → diff image`, so kernel-side image logic stays visually\ninspectable rather than asserted.\n\n## Measurement Model\n\nPhase-oriented; values below are illustrative medians from the\n2026-05-07 lima guest (full rows in `docs/benchmark.md`):\n\n- Phase 1: vivid baselines — `read()` p50 31.3 ms, `mmap` p50 133.2 ms\n  at 30 fps, both with zero `DQBUF` errors over 600-frame runs\n- Phase 2: vivid `EXPBUF` → vpipe DMABUF — added latency p50 0.107 ms,\n  exact `src_v4l2_sequence` correlation 0..599, no duplicates or gaps\n- Phase 3: DMA-BUF variants — copyful `mmap` p50 0.100 ms vs.\n  vivid-DMABUF p50 0.083 ms; heap-backed fixture path p50 3.4 µs with\n  one explicit userspace fixture copy\n- Phase 4: threshold over heap-DMABUF — p50 3.4 µs, p99 9.1 µs;\n  byte-identical against the userspace reference for the full fixture\n  set\n- Phase 5: explicit sync — currently `N/A`; gated by the UAPI-state\n  probe in `scripts/check.sh`\n\nEach phase captures, where the path permits: frame interval and drops,\np50/p95/p99 latency, cycles and instructions, cache references and\nmisses, context switches, and the timestamp source used.\n\n## Current Limits\n\n- transport is GREY-only and narrow by design\n- the ledger still has `TBD` rows where long-form measurement is missing\n- the lima guest does not expose PMU events for `cycles`, `instructions`,\n  or `cache-*`; `perf stat` reports them as `\u003cnot supported\u003e`\n- no V4L2 userspace out-fence claim: the validated guest exposes\n  `request_fd` but no fence flags or `fence_fd` field\n- `kmemleak` cannot be exercised here: the validated guest kernel\n  lacks `CONFIG_DEBUG_KMEMLEAK` and does not expose the debugfs node\n- some paths are validated for API shape and correlation before any\n  zero-copy claim is made\n\n## Licensing\n\nMIT License. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysprog21%2Fvpipe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsysprog21%2Fvpipe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysprog21%2Fvpipe/lists"}