|
| 1 | +<!-- markdownlint-disable MD013 --> |
| 2 | +# Agent guide — Pelorus |
| 3 | + |
| 4 | +> Cross-tool context for Claude Code, Cursor, Aider, Codex, Continue, and other |
| 5 | +> coding assistants. **Read this before suggesting changes.** Then read the |
| 6 | +> per-subdirectory `AGENTS.md` for the area you're touching. Claude Code users: |
| 7 | +> [CLAUDE.md](CLAUDE.md) extends this file. |
| 8 | +
|
| 9 | +## What this repo is |
| 10 | + |
| 11 | +`Pelorus` is a GPU **pre-encode** pipeline: Vulkan compute filters + FFmpeg |
| 12 | +filters that fix the psychovisual flaws of a hardware video encoder *before* it |
| 13 | +sees the pixels, entirely in VRAM (zero-copy). The goal is to close the BD-rate |
| 14 | +gap between fixed-function GPU encoders (NVENC/AMF/QSV) and slow CPU encoders |
| 15 | +(x265/SVT-AV1) — debanding, temporal denoise, film-grain synthesis, and |
| 16 | +optical-flow motion hints. These are **codec-agnostic**: deband/denoise/motion |
| 17 | +help HEVC (`hevc_nvenc`/`hevc_qsv`/`hevc_vaapi`/`hevc_amf`, rivaling x265) and |
| 18 | +AV1 equally; only film-grain is codec-specific (AV1 = AOM, HEVC/VVC = H.274). |
| 19 | + |
| 20 | +Pelorus is the sibling of **vmafx** (the VMAF fork), hosted under the same |
| 21 | +`vmafx` GitHub org. vmafx dropped its own Vulkan backend (its ADR-0726), so |
| 22 | +Pelorus is the Vulkan home; vmafx stays the **quality oracle**. The two are |
| 23 | +bidirectionally wired: Pelorus filters write a shared side-data blob that vmafx |
| 24 | +reads for perceptually-weighted scoring, and Pelorus tunes its filter strength |
| 25 | +against VMAF using vmafx's autotune loop. See |
| 26 | +[docs/architecture/overview.md](docs/architecture/overview.md) and |
| 27 | +[docs/principles.md](docs/principles.md). |
| 28 | + |
| 29 | +## Hard rules |
| 30 | + |
| 31 | +1. **Never break the `libpelorus` public ABI without a `Migration:` footer.** |
| 32 | + The `PelorusSideData` interop blob is append-only (interop.h R1/R2): add a |
| 33 | + field or section bit and bump `PELORUS_ABI_MINOR` — never reorder, resize, or |
| 34 | + remove. A breaking change is forbidden; mint a new section bit instead. |
| 35 | +2. **All errors flow through `pel_result`.** No bare `return -1;` across a |
| 36 | + `libpelorus` API boundary. Every non-void return is checked or `(void)`-cast. |
| 37 | +3. **No global mutable state / no static-init side effects.** Lifecycle is |
| 38 | + explicit. Banned C functions: `gets`, `strcpy`, `strcat`, `sprintf`, |
| 39 | + `strtok`, `atoi`, `atof`, `rand`, `system` (see docs/principles.md §1.2). |
| 40 | +4. **Keep the two deband implementations in lockstep.** The standalone |
| 41 | + reference shader (`libpelorus/shaders/pelorus_deband.comp`) and the FFmpeg |
| 42 | + filter's inline GLSL (`ffmpeg-patches/files/vf_pelorus_deband_vulkan.c`) |
| 43 | + implement the same algorithm; edit both together. |
| 44 | +5. **Patch-stack sync.** A change to any `libpelorus` surface the FFmpeg patches |
| 45 | + consume updates `ffmpeg-patches/files/` + the regenerated patch in the same |
| 46 | + PR. Verify with a full series replay (`ffmpeg-patches/test/build-and-run.sh`), |
| 47 | + not per-patch `git apply --check`. |
| 48 | +6. **Every PR leaves touched files lint-clean** to `-Wall -Wextra -Werror` + |
| 49 | + clang-tidy. A `// NOLINT` carries an inline citation. |
| 50 | +7. **Every merged commit: 0 warnings · clang-tidy clean · `meson test |
| 51 | + --suite=fast` green · the deband shader compiles (glslang).** |
| 52 | + |
| 53 | +See [docs/principles.md](docs/principles.md) for the full Power-of-10, |
| 54 | +SEI-CERT-C, style, and Vulkan-usage contract, and [CONTRIBUTING.md](CONTRIBUTING.md) |
| 55 | +for the per-PR deliverables (ADRs, per-surface docs, changelog fragments). |
| 56 | + |
| 57 | +## Repository layout |
| 58 | + |
| 59 | +```text |
| 60 | +Pelorus/ |
| 61 | +├── meson.build meson_options.txt # build root (libpelorus + tests + shaders) |
| 62 | +│ |
| 63 | +├── libpelorus/ # the shared core (vendored by vmafx too) |
| 64 | +│ ├── include/pelorus/ |
| 65 | +│ │ ├── pelorus.h # umbrella: version, pel_result |
| 66 | +│ │ ├── interop.h # the Pelorus<->vmafx side-data ABI |
| 67 | +│ │ └── deband.h # smart-deband parameter contract |
| 68 | +│ ├── src/ # interop.c (pack/parse), deband_params.c |
| 69 | +│ ├── shaders/ # standalone reference .comp shaders |
| 70 | +│ └── test/ # interop ABI conformance fixture |
| 71 | +│ |
| 72 | +├── ffmpeg-patches/ # vf_pelorus_* filters, stacked vs n8.1.1 |
| 73 | +│ ├── files/ # canonical filter sources (edit here) |
| 74 | +│ ├── 0001-*.patch series.txt # generated artifacts + apply order |
| 75 | +│ ├── generate.sh # regenerate patches from files/ |
| 76 | +│ └── test/build-and-run.sh # apply + build + smoke-test gate |
| 77 | +│ |
| 78 | +├── docs/ |
| 79 | +│ ├── principles.md # the coding + Vulkan-usage contract |
| 80 | +│ ├── adr/ # Architecture Decision Records (Nygard) |
| 81 | +│ ├── architecture/ api/ metrics/ # per-surface docs (C4, interop, filters) |
| 82 | +│ ├── usage/ backends/ development/ # pipeline, Vulkan path, build/release |
| 83 | +│ └── research/ # deep-dive digests |
| 84 | +│ |
| 85 | +├── changelog.d/ # Keep-a-Changelog fragments (rendered) |
| 86 | +└── AGENTS.md CLAUDE.md CONTRIBUTING.md README.md |
| 87 | +``` |
| 88 | + |
| 89 | +Per-subdirectory `AGENTS.md` files give unit-level conventions + the |
| 90 | +rebase-sensitive invariants. |
| 91 | + |
| 92 | +## Common tasks |
| 93 | + |
| 94 | +| Task | Command | |
| 95 | +|---|---| |
| 96 | +| Configure + build | `meson setup build && ninja -C build` | |
| 97 | +| Fast test gate | `meson test -C build --suite=fast` | |
| 98 | +| Install (for the FFmpeg patches) | `ninja -C build install` | |
| 99 | +| Regenerate FFmpeg patches | `cd ffmpeg-patches && ./generate.sh` | |
| 100 | +| Apply + build + smoke FFmpeg | `ffmpeg-patches/test/build-and-run.sh` | |
| 101 | +| Lint | `clang-format --dry-run -Werror` + `clang-tidy` on touched files | |
| 102 | +| Reserve an ADR number | `scripts/adr/next-free.sh --claim <slug>` | |
| 103 | + |
| 104 | +## Pinned upstream references |
| 105 | + |
| 106 | +| Component | Version | |
| 107 | +|---|---| |
| 108 | +| FFmpeg base for the patch stack | `n8.1.1` | |
| 109 | +| FFmpeg Vulkan filter model | `libavfilter/vf_gblur_vulkan.c`, `vf_nlmeans_vulkan.c` | |
| 110 | +| AV1 film-grain struct mirrored by interop §(d) | `libavutil/film_grain_params.h` | |
| 111 | +| vmafx control plane (autotune) | `libvmaf_tune` filter, `vmafx-server` `/v1/score`, `vmaf-mcp` | |
| 112 | + |
| 113 | +## When in doubt |
| 114 | + |
| 115 | +Read [docs/principles.md](docs/principles.md), then the per-subdirectory |
| 116 | +`AGENTS.md` for the area you're touching. Decisions live in |
| 117 | +[docs/adr/](docs/adr/); the project plan + current status live in |
| 118 | +`.workingdir/PLAN.md` + `.workingdir/STATE.md` (local, gitignored). |
0 commit comments