46 Commits

Author SHA1 Message Date
test0r b851861931 debian/mpv-fourier: new package
Mirror of arch/mpv-fourier into the Debian tree.  Same source
pin (mpv 0.41.0), same 3 patches:
  - 0001-meson-add-detection-logic-for-v4l2request-support.patch
  - 0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch
    (Kwiboo + Langdale wiring for AV_HWDEVICE_TYPE_V4L2REQUEST
     through drmprime VO hwdec — '--hwdec=v4l2request' actually
     engages on dmabuf-wayland)
  - 0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch
    (iter1 of dmabuf-modifier-triage — explicit DMA_BUF_IOCTL_SYNC
     on import fds; KWin-on-RK3566 dark-green chroma readback
     regression fix on ohm.  Root cause is the vb2_dma_resv RFC
     upstream still pending.)

Depends on ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier) —
AV_HWDEVICE_TYPE_V4L2REQUEST only exists in Kwiboo's FFmpeg
fork; stock Debian ffmpeg doesn't have it.

Conflicts/Replaces stock mpv + libmpv2/libmpv1 — drop-in
replacement.  Takes epoch 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:01:29 +00:00
test0r 45f4b5e56f debian/ffmpeg-v4l2-request-fourier: new package
Mirror of arch/ffmpeg-v4l2-request-fourier into the Debian tree.
Same source pin (Kwiboo v4l2-request-n8.1 @ b57fbbe), same 2
patches (libudev-bypass-fallback + nv15-to-p010-unpack), same
configure flag policy (drop X11/AMF/CUDA/Bluray/Vulkan/SDL2/etc.
per Fourier fleet focus).

Output: single .deb at /usr/bin/ffmpeg + /usr/bin/ffprobe +
/usr/lib/aarch64-linux-gnu/libav*.so.61.  Conflicts/Replaces
the stock Debian ffmpeg + per-lib packages; takes epoch 2
(matches Debian's existing ffmpeg epoch).

Provides 'ffmpeg -hwaccel v4l2request' + '-hwaccel drm' routes
that drive rkvdec / hantro / cedrus / rpi-hevc-dec /
daedalus_v4l2 stateless decoders through libavcodec's hwdevice
DRM path, bypassing libva.  Required by mpv-fourier and
firefox-fourier as their backing FFmpeg; also the kdirect
bit-exact reference for libva-v4l2-request-fourier validation.

NOT strictly required for the VAAPI-only path on
daedalus-v4l2 hosts (stock Debian ffmpeg + libva-v4l2-request-
fourier covers that).  Install only when going firefox-fourier
or kdirect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:01:18 +00:00
test0r 1bd11eaf27 daedalus-v4l2{,-dkms}: f04d700 -> f55b2cd (UAF lifetime fix)
Bumps all 4 daedalus packages (arch + debian × userspace + dkms)
to pick up daedalus-v4l2 f55b2cd: "kernel: media_request_get/put
around inf->req (UAF safety)".

Closes the SHIP-WITH-EYES-OPEN concern Sonnet flagged in the
pre-deployment review — without explicit media_request_get on
capture + media_request_put on completion, a concurrent
MEDIA_IOC_REQUEST_REINIT or process-kill triggering
buf_request_complete from the cancel path could drop vb2's
reference before our completion handler ran, leaving inf->req
dangling through v4l2_ctrl_request_complete + buf_done.

Matches the cedrus / rkvdec refcount pattern.  No protocol
change, no API change, no consumer-side adjustment required.
Same byte-exact output verified on hertz post-fix (libva path:
match; standalone test_m2m_stream: 30/30 frames).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:39:40 +00:00
test0r 4776dc01d2 daedalus-v4l2-dkms: loud warning when DKMS build doesn't land
Sonnet pre-deployment review caught a BLOCKER: on a fresh higgs
(Debian 13 / Pi CM5) install without the RPi kernel headers
pre-installed, the postinst's `dkms autoinstall || true` silently
swallowed the build failure. Package appeared installed but the
.ko was absent; `modprobe daedalus_v4l2` then failed and the
entire stack was dead with no clear pointer to the cause.

Fix in both ecosystems:

debian/daedalus-v4l2-dkms/build-deb.sh:
- After `dkms autoinstall`, verify the post-condition with
  `dkms status -m daedalus_v4l2 -v VER -k $(uname -r)`.
- If the module isn't 'installed' / 'loaded' for the running
  kernel, emit a yellow-bolded ANSI warning naming the most
  likely cause (kernel headers package missing) and the exact
  recovery steps (linux-headers-rpi-2712 for RPi or
  linux-headers-$KERNELVER for Debian generic, then
  `dkms autoinstall` + `modprobe`).
- Colour only on TTY; the warning is unconditional regardless.

arch/daedalus-v4l2-dkms/:
- New daedalus-v4l2-dkms.install with post_install +
  post_upgrade hooks that run the same `dkms status` check.
- post_upgrade catches the case where a kernel-headers package
  was uninstalled / pruned between upgrades, silently
  regressing the build.
- Wired into the PKGBUILD via install="${pkgname}.install".

Both versions point at the actual repair commands rather than
just saying "build failed", so the user is one apt/pacman away
from a working stack instead of debugging dkms internals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:38:52 +00:00
test0r f3dd1c1886 debian/daedalus-v4l2-dkms: new package — kernel module via DKMS
Mirror of arch/daedalus-v4l2-dkms into the Debian tree.
Architecture: all (source package — DKMS rebuilds per-kernel
at install time).  Same pin (f04d700, Phase 8.13 close).

Installs kernel/ source to /usr/src/daedalus_v4l2-<ver>/ with
generated dkms.conf.  postinst runs `dkms add` + `dkms
autoinstall` so the module builds against the running kernel's
headers automatically.  prerm runs `dkms remove --all`.

Same Makefile-include-path flattening as the Arch sibling:
copies daedalus_v4l2_proto.h into kernel/include/ and patches
the Makefile's -I path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:46 +00:00
test0r add049f0bd debian/daedalus-v4l2: new package — userspace daemon + tools
Mirror of arch/daedalus-v4l2 into the Debian tree.  Same pin
(f04d700, Phase 8.13 close), same install layout.  Output as
arm64 .deb.

Build path: CMake for daemon (build via ninja); in-tree Makefile
for tools.  No debhelper; standalone dpkg-deb so it builds on
the non-Debian runner.

Depends on ffmpeg (libavformat/libavcodec/libavutil 7.1+) at
runtime, libdrm2.  Recommends daedalus-v4l2-dkms (the kernel
module).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:39 +00:00
test0r 249e8461bb debian/libva-v4l2-request-fourier: new package
Mirror of arch/libva-v4l2-request-fourier into the Debian tree.
Same pin (de27e95), same build (meson + ninja), output as
arm64 .deb installing the VA-API ICD as
/usr/lib/aarch64-linux-gnu/dri/v4l2_request_drv_video.so.

Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv
--hwdec=vaapi, Firefox VAAPI accel) when
LIBVA_DRIVER_NAME=v4l2_request is set.

build-deb.sh follows the lmcp pattern: reproducible build with
SOURCE_DATE_EPOCH pin; standalone dpkg-deb so it runs on a
non-Debian builder without dh/debhelper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:33 +00:00
test0r 3293cd6542 arch/daedalus-v4l2-dkms: new package — kernel module via DKMS
PKGBUILD pinning the same daedalus-v4l2 @ f04d700 as the
userspace sibling.  Installs kernel/ source to
/usr/src/daedalus_v4l2-<ver>/ with a generated dkms.conf;
AUTOINSTALL=yes builds the module against the running kernel.

The kernel/ Makefile uses -I$(src)/../include for the shared
protocol header.  In the userspace tree that's daedalus-v4l2/include/;
for DKMS we flatten by copying the header into kernel/include/
and patching the Makefile in package() to point there.

Sibling Debian package: debian/daedalus-v4l2-dkms/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:21 +00:00
test0r 6de7268b49 arch/daedalus-v4l2: new package — userspace daemon + tools
PKGBUILD pinning daedalus-v4l2 @ f04d700 (Phase 8.13 close).

Installs:
- /usr/bin/daedalus_v4l2_daemon — the FFmpeg-backed decode daemon
- /usr/libexec/daedalus-v4l2/{test_chardev_pingpong,test_m2m_decode,
  test_m2m_stream} — verification harnesses
- /usr/include/daedalus_v4l2_proto.h — shared kernel↔daemon wire
  protocol (for third-party chardev clients)
- /usr/share/doc/daedalus-v4l2/ — README + Phase 8.x closure docs

Runtime deps: ffmpeg (libavformat/libavcodec/libavutil dlopen'd
at runtime per Option γ — daemon binary is link-clean from
FFmpeg), libdrm.

optdepends:
- daedalus-v4l2-dkms: companion kernel module
- libva-v4l2-request-fourier: VAAPI consumer routing through us

Sibling Debian package: debian/daedalus-v4l2/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:14 +00:00
test0r dbae9832b6 libva-v4l2-request-fourier: 1.0.0.r348.7ac934e -> 1.0.0.r376.de27e95
Bump pin to de27e95 — "v4l2: log error_idx + failing ctrl id on
S_EXT_CTRLS failure" (Phase 8.13 diagnostic).

Includes:
- b5b3acf: daedalus_v4l2 entry in known_decoder_drivers[]
- 2146341: meson option gate (default true) for the daedalus
  probe slot
- de27e95: diagnostic logging on S_EXT_CTRLS failure (logs
  error_idx + failing control id, ioctl-level vs per-control)

Backward-compatible on rkvdec / hantro / cedrus / rpi-hevc-dec
hosts — daedalus probe is off-path unless daedalus_v4l2.ko
is loaded and /dev/video0 advertises driver "daedalus_v4l2".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:06 +00:00
marfrit b248aa2ac8 Merge pull request 'linux-ampere-fourier: bump to kafr2 (v7.0-rc3 + kernel-agent manifest, VP9 + AV1)' (#27) from claude-noether/marfrit-packages:noether/linux-ampere-fourier-kafr2 into main
Reviewed-on: marfrit/marfrit-packages#27
2026-05-18 14:34:57 +00:00
test0r 06023bcf9d linux-ampere-fourier: bump to kafr2 (v7.0-rc3 + fleet/ampere.yaml manifest)
Drops the f8f3ad9 baseline ("18 commits ahead, BLACK-SCREENS ampere"
per fleet/ampere.yaml bisect note) in favor of the kernel-agent-
managed 10-patch set produced by ka-promote from fleet/ampere.yaml.

Baseline: mainline v7.0-rc3 (3daa4f5dc6cc), plus the 10 scope-tagged
patches under marfrit/kernel-agent/patches/{soc,module,board,driver}/:
  - 1 soc/rk3588 pwm15 pinctrl
  - 6 board/coolpi-cm5-genbook DTS patches
  - 3 driver/media Sarma VP9-on-VDPU381 patches (PR #24 closure)

New _commit 48a8c78 reflects this tree state in ~/src/linux-rockchip
(branch vp9-build on ampere, exactly v7.0-rc3 + 10 manifest patches).

End-to-end verified before this iteration was cut (hand-build of the
same tip on 2026-05-18 booted ampere via arch_vp9_test extlinux
label):
  - VP9 decode bit-exact HW==SW==libva (sha c8624d7c42db66525f53a02a515bc38d0a17ef39f692660cc7bebb1e2d2e1b48)
  - AV1 decode bit-exact HW==SW via kdirect (sha 30d2091158d92f3c5e0a807217c3e7307f873267673d92632e7fb147383e7dd1, av1-vpu-dec is mainline 7.0)

prebuild.sh canonical sha256 cleared — gzip-version-dependent, the
script warns-not-fails on mismatch. First successful kafr2 build can
pin a canonical sha here if a reproducibility audit ever needs it.

Cross-references:
  - marfrit/kernel-agent#12 (VP9 enablement closure)
  - marfrit/kernel-agent PR #24 (Sarma patch import + ampere.yaml bump)
2026-05-18 14:03:56 +00:00
marfrit 7542989f2b Merge PR #26: ffmpeg-v4l2-request-fourier NV15 to P010 unpack for Hi10P / Main10 2026-05-18 08:52:50 +00:00
test0r 9e9447502e ffmpeg-v4l2-request-fourier: patch NV15→P010 unpack for Hi10P / Main10
The n8.1 pin's hwcontext_v4l2request.c deliberately blanks the
transfer-formats list for AV_PIX_FMT_YUV420P10 sw_format (the mapping
target for V4L2_PIX_FMT_NV15), so `ffmpeg -hwaccel v4l2request
-vf hwdownload,format=p010le` on a Hi10P / Main10 input failed at
filter-init with -22 EINVAL — even though kernel-side decode succeeded.

0002-nv15-to-p010-unpack.patch adds an inline NV15→P010 unpack
(5 bytes per 4 samples, little-endian → high-10-of-16) inside
v4l2request_transfer_data_from, exposes AV_PIX_FMT_P010 in
transfer_get_formats for that sw_format, and rejects non-P010
destinations explicitly with ENOSYS instead of silently corrupting
output via av_frame_copy on NV15-packed bytes.

Verified on fresnel (RK3399, linux-fresnel-fourier 7.0-14):
- 5-frame smoke test from issue #21 → exit 0, 13.8MB output
- 20-frame mid-fixture decode → bit-exact HW==SW
  sha256 7d9b66d48d8f17b2281da1881c663ecc31722bb218aba1ae23bf28d07aa66b08
- 8-bit baseline (bbb_60s_720p.h264.mp4) still bit-exact HW==SW (no
  regression in the existing NV12 path)
- Cross-device repro of original EINVAL on unpatched ampere (RK3588)
  pkgrel=4, confirming the bug is upstream-FFmpeg-side, not RK3399-specific

Patch is upstream-able to Kwiboo's v4l2-request-n8.1 branch.

Closes #21.
2026-05-18 08:35:19 +00:00
marfrit eb1782e86f Merge pull request 'lmcp: 1.1.1 -> 1.2.1 (tools.d plugin scan + LMCP_HOST/LMCP_CONF env)' (#25) from claude-noether/marfrit-packages:noether/lmcp-1.2.1 into main
Reviewed-on: marfrit/marfrit-packages#25
2026-05-17 23:37:19 +00:00
test0r a168342fa8 lmcp: 1.1.1 -> 1.2.1 (tools.d plugin scan + LMCP_HOST/LMCP_CONF env)
Tracks upstream lmcp v1.2.1 (commits e05438f + c5375b8). Combined
release that lets hosts like hertz/ampere stop maintaining forked
/opt/lmcp/server.lua overrides — packaged server.lua becomes the
canonical entrypoint, host-local tools live in /opt/lmcp/tools.d/
as plugin files, single-interface binding + conf-file auth come via
LMCP_HOST + LMCP_CONF systemd env. Closes lmcp#22 structurally.

New tarball sha256:
  bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 23:34:07 +00:00
marfrit 4820e53b18 Merge pull request 'lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)' (#24) from claude-noether/marfrit-packages:noether/lmcp-1.1.1 into main
Reviewed-on: marfrit/marfrit-packages#24
2026-05-17 22:47:59 +00:00
test0r 248bef5503 lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)
Tracks upstream lmcp v1.1.1 (commit 9707f7a). Single-bug-fix
release: lmcp:tool() now normalises empty inputSchema.properties
by dropping the key, so Zod-strict MCP clients don't reject
tools/list with "expected: record, received: array".

Discovered live on a hertz-tools deployment where two custom
no-arg tools tripped the check and caused Claude Code to mark
the endpoint as disconnected.

New tarball sha256:
  80c2e815aa61a2d3baab051c51cd247bdefa9dd03d72c4867b99c49b6eae9cb9

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:47:21 +00:00
marfrit 8a49ac6061 Merge pull request 'lmcp: 1.0.0~rc1 -> 1.1.0 (concurrent dispatch + cancellation + windows sync)' (#23) from claude-noether/marfrit-packages:noether/lmcp-1.1.0 into main
Reviewed-on: marfrit/marfrit-packages#23
2026-05-17 20:22:30 +00:00
test0r 4764f5f37f lmcp: 1.0.0~rc1 -> 1.1.0
Tracks upstream lmcp v1.1.0 (commit 7e62f71). Closes 3 upstream
issues: #11 (progress + cancellation), #18 (windows MSI sync), #20
(concurrent handler dispatch).

Arch:
  pkgver=1.1.0 (no pre-release suffix this time).
  _tag back-translation kept so future rc bumps just need pkgver=X.Y.Z_rcN.

Debian:
  PKGVER=1.1.0 (no ~ suffix).
  Changelog entry summarises the three closed issues + the zero-
  handler-source-changes invariant.

New tarball sha256:
  d758a9504389528cb8940ea81bc8cf47afad8c01166aef3484ac4f5752445532

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 19:44:26 +00:00
marfrit dcb1da2f59 Merge pull request 'lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)' (#22) from claude-noether/marfrit-packages:noether/lmcp-1.0.0-rc1 into main 2026-05-17 17:42:16 +00:00
test0r 238c5cee7e lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)
Bumps both arch and debian packaging to track upstream v1.0.0-rc1
(commit deb73d1).

Arch (arch/lmcp/PKGBUILD):
  pkgver=1.0.0_rc1 (Arch convention: '_' substitutes for '-' in pre-
  release tags). _tag back-translates for the source URL.

Debian (debian/lmcp/build-deb.sh + changelog):
  PKGVER=1.0.0~rc1 (Debian convention: '~' sorts before the release).
  UPSTREAM_TAG=v1.0.0-rc1 drives the archive URL.

New tarball sha256: 81f9222264371735c196664382460261ef60a259348766bbd6fd2f49ea9d1e7e

What's in 1.0.0-rc1 (full release notes in upstream commit):
  - 14 issues closed
  - new MCP primitives: Resources, Prompts, Completion, Logging,
    Sampling, Roots, fetch, web_search
  - protocol: cursor pagination, structuredContent, _meta, tool
    annotations, protocolVersion bump to 2025-06-18
  - transports: stdio (LMCP_TRANSPORT=stdio), full Streamable HTTP
    rewrite with sessions, persistent SSE, server-initiated requests
  - json.lua: UTF-16 surrogate pairs + empty_object sentinel
  - backwards-compatible with every existing sessionless-POST client

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 17:18:18 +00:00
marfrit 70c943e948 Merge pull request 'ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier (dir rename)' (#20) from claude-noether/marfrit-packages:noether/rename-ffmpeg-dir into main
Reviewed-on: marfrit/marfrit-packages#20
2026-05-16 23:08:10 +00:00
claude-noether d6c4260eb8 ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier: rename directory
PKGBUILD already renamed itself (pkgname=ffmpeg-v4l2-request-fourier,
replaces=(ffmpeg ffmpeg-v4l2-request-git)) but the containing
directory was never moved. This commit completes the rename to align
the path with the package identity and the rest of the -fourier
umbrella (libva, mpv, kwin, qt6-base, chromium, linux-*).

CI workflow path-trigger is wildcard (arch/**), unaffected. Step
names + cp source path updated to the new directory.
2026-05-17 01:04:37 +02:00
marfrit 1fed626900 Merge pull request 'libva-v4l2-request-ohm-gl-fix: mark deprecated' (#19) from claude-noether/marfrit-packages:noether/deprecate-ohm-gl-fix into main
Reviewed-on: marfrit/marfrit-packages#19
2026-05-16 23:01:00 +00:00
claude-noether 0b2393cecc libva-v4l2-request-ohm-gl-fix: mark deprecated, point at -fourier
Predecessor experimental package (tarball + 18 stacked patches) is
superseded by libva-v4l2-request-fourier (git-tracked fork tip,
iter38 multi-device probe). The successor already declares
replaces=('libva-v4l2-request-ohm-gl-fix') so installs migrate
automatically; this commit just makes the deprecation visible in
README + pkgdesc.

Kept in-tree as historical reference for the ohm_gl_fix Phase 6
audit trail.
2026-05-17 01:00:25 +02:00
marfrit 697413103d Merge pull request 'libva-v4l2-request-fourier: -Db_lto=false (closes #17)' (#18) from claude-noether/marfrit-packages:noether/libva-disable-lto into main 2026-05-16 16:39:57 +00:00
claude-noether b648276122 libva-v4l2-request-fourier: -Db_lto=false (closes #17)
CI binary segfaulted on HEVC vaEndPicture even though
/etc/makepkg.conf has OPTIONS=(... !lto ...). Root cause: arch-meson's
wrapper hard-codes `-D b_lto=true` regardless of makepkg.conf, so
the binary still gets cross-function ICF (Identical Code Folding)
under -O2 + LTO.

HEVC is the only codec in the campaign that submits a per-frame chain
of 4 control structs (SPS + PPS + DECODE_PARAMS + SLICE_PARAMS); ICF
finds a near-duplicate per-codec helper across the codec dispatch and
merges them, then the wrong instance's local stack layout is invoked
on the HEVC path → SEGV. The other 4 codecs (H.264, VP8, VP9, MPEG-2)
submit fewer/simpler control structs and tolerate the folding by
accident.

Empirical confirmation from the issue body's binary bisection:

  meson build (default debugoptimized)     485 KB   HEVC ✓
  arch-meson + --buildtype=release          145 KB   HEVC ✓
  arch-meson + release + -flto              76 KB   HEVC SEGV
  CI build (this package, 7ac934e-1)        133 KB   HEVC SEGV

Fix: append `-Db_lto=false` to the arch-meson invocation.
pkgrel 1 -> 2.
2026-05-15 19:03:46 +00:00
marfrit 2e2c9b6361 linux-ampere-fourier: chmod +x prebuild.sh (#16) 2026-05-15 17:20:10 +00:00
claude-noether 0d311d61b4 linux-ampere-fourier: chmod +x prebuild.sh
The exec bit was missing on prebuild.sh as committed in PR #15
(it landed mode 0644). Running './prebuild.sh' fails with
'Permission denied'; bash ./prebuild.sh works as a workaround but
the shebang is intended to do its job.

Caught while running the first linux-ampere-fourier build on
boltzmann today. README.md examples show './prebuild.sh' so users
will hit the same error.

Single-bit fix via git update-index --chmod=+x. No content change.
2026-05-15 16:54:29 +00:00
marfrit efc1bfd66a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588) (#15) 2026-05-15 16:49:45 +00:00
claude-noether 154fa2f14a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588)
Sibling to kernel-agent PR #8 which lands the scope-tagged board
patches + fleet/ampere.yaml manifest. This PR carries the
makepkg-side recipe.

## Baseline

marfrit/linux-rk3588-marfrit @ f8f3ad9 (mainline v7.0-rc3 + 18 commits):
  10 by Markus Fritsche  (board DTS + Kconfig + suspend/wakeup + bt)
   4 by Shawn Lin        (phy: rockchip-snps-pcie3 stability)
   2 by Cristian Ciocaltea (clk + dw-dp bridge — Collabora)
   1 by Sebastian Reichel (Rock 5 ITX hdmirx — unused by ampere)
   1 by Pedro Alves      (CLK_SET_RATE_PARENT VOP2 fix)

The 6 board-relevant patches (pwm15 pinctrl + RK806 power-off +
genbook pwm-fan/speaker/USB-C/lid) are scope-tagged in
kernel-agent. The 12 others are 'cherry-picks-in-baseline'
currently — splitting them into scope-tagged patches is a
follow-up.

## Source distribution

The kernel tree isn't pushable to Gitea (boltzmann's working clone
is shallow). Tarball (260MB) doesn't belong in marfrit-packages
either. Pragmatic shortcut: ship prebuild.sh that produces the
tarball locally from $LINUX_RK3588_MARFRIT_TREE (default
~/src/linux-rockchip) just before makepkg runs. PKGBUILD source
array references the tarball by name; makepkg picks it up from
the PKGBUILD dir.

Build flow:
  cd arch/linux-ampere-fourier
  ./prebuild.sh           # produces 260MB tarball; idempotent w/ sha check
  makepkg -s --noconfirm

Future iteration: host the tarball on Gitea release assets or
packages.reauktion.de/sources/ and switch source to URL.

## What the PR ships

  PKGBUILD                          — the recipe (linux-rk3588-marfrit @ f8f3ad9)
  config                            — snapshot of ampere's /proc/config.gz
  linux-ampere-fourier.preset       — mkinitcpio preset, /boot/firmware/ paths
  extlinux-add.hook                 — alpm hook, fires on /boot/firmware/Image* changes
  extlinux-add.sh                   — idempotent managed-label injector for
                                     /boot/firmware/extlinux/extlinux.conf
                                     (vfat on mmcblk0p1, ampere-specific path)
  prebuild.sh                       — source-staging helper (see above)
  README.md                         — build + install runbook

## ampere-specific boot path differences vs fresnel

ampere boots from /boot/firmware/ (vfat partition), not /boot/ (root
partition) like fresnel. The PKGBUILD installs Image + initramfs + DTB
under /boot/firmware/ directly. The extlinux-add hook fires on
/boot/firmware/<X> path changes and edits
/boot/firmware/extlinux/extlinux.conf. The mkinitcpio preset writes
initramfs to /boot/firmware/.

Only one PRESET ('default') — no fallback image — because
/boot/firmware is ~1G total and two ~20MB initramfs files plus the
DTB and a couple of kernel-image backups would squeeze it tight.

## Out of scope this PR

- Ask 2 (VP9 enablement) and Ask 3 (AV1 dec) from kernel-agent issue #6
- Build + publish + install (sequenced after this PR + kernel-agent PR #8 merge)
- Splitting the 12 non-board commits into scope-tagged kernel-agent patches
2026-05-15 16:19:24 +00:00
marfrit 2af63ce988 Merge pull request 'linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)' (#14) from claude-noether/marfrit-packages:noether/linux-fresnel-fourier-pkgrel14 into main
Reviewed-on: marfrit/marfrit-packages#14
2026-05-15 15:37:23 +00:00
claude-noether e9bc6ebd27 linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)
Sibling to kernel-agent PR #7 (which lands the vb2_dma_resv RFC v2
series under patches/subsystem/media/videobuf2/ and updates
fleet/fresnel.yaml to include them). This PR carries the same three
patches in the build-tree-ready form for the linux-fresnel-fourier
PKGBUILD.

Background: Markus iterated v2 locally on boltzmann reaching pkgrel=14
since the 2026-05-09 bootstrap published 7.0-1. v2 attaches the V4L2
producer fence at device_run in slept-OK context per Dufresne's v1
review on linux-media. Drivers opted in here: hantro + rockchip-rga.

Changes:
- pkgrel 1 -> 14
- pkgdesc adds '+ vb2_dma_resv RFC v2'
- source array gains 3 new local patch files (scope-tagged comments
  point to where they live in marfrit/kernel-agent)
- sha256sums extended to 11 SKIP entries

No prepare() edit needed — the existing for-loop applies every *.patch
in $srcdir, so the 4/5/6 patches get picked up automatically. config
unchanged (verified diff vs boltzmann's local pkgrel=14 tree).

Pre-built artifacts: linux-fresnel-fourier-7.0-14-aarch64.pkg.tar.zst
and linux-fresnel-fourier-headers-7.0-14-aarch64.pkg.tar.zst already
exist on boltzmann at /home/mfritsche/src/kernel-agent-bootstrap/
build/marfrit-packages/arch/linux-fresnel-fourier/ — will be signed
and published via marfrit-publish-arch after this PR merges (no fresh
compile needed; the artifacts were built locally during the iteration
loop that reached pkgrel=14).
2026-05-15 15:33:55 +00:00
marfrit 201e671d61 Merge pull request 'firefox-fourier: vendor-prefs install path correction (browser/defaults -> defaults)' (#13) from claude-noether/marfrit-packages:noether/firefox-fourier-vendor-prefs-correct-path into main
Reviewed-on: marfrit/marfrit-packages#13
2026-05-15 14:23:32 +00:00
claude-noether d63d1cef72 firefox-fourier: move vendor-prefs to defaults/preferences/ (the path Firefox actually scans)
Empirical follow-up to #9. After packaging 150.0.1-4 and installing on
fresnel, MOZ_LOG showed the failure pattern was still present:

  D/FFmpegVideo FFMPEG: Using preferred software codec h264

No VAAPI_VLD engagement, no dmabuf surface locking — Gecko bailed
before reaching the patched VAAPI path. Same symptom as issue #8
pre-fix, despite the prefs file being on disk at the expected path.

Root cause: /usr/lib/firefox-fourier/browser/defaults/preferences/ is
NOT a vendor-prefs scan location in Firefox 150. Mozilla's canonical
scan dir is /usr/lib/<app>/defaults/preferences/ — without the
'browser/' prefix.

Verified by hand-copying the same file to /usr/lib/firefox-fourier/
defaults/preferences/ and re-running the H.264 playback test:

  D/FFmpegVideo FFMPEG: Requesting pixel format VAAPI_VLD
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26267
    FFMPEG ID 0x4000000 mAVHWFrameContext ...
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26268
    FFMPEG ID 0x4000001 ...
  (15+ surface locks)

End-to-end zero-copy DMABUF path engaged, hantro/rkvdec dekodes the
H.264 stream via libva-v4l2-request-fourier iter38b.

pkgrel 4 -> 5. No other PKGBUILD changes.
2026-05-15 14:18:09 +00:00
marfrit 108c725c58 Merge pull request 'kwin-fourier 6.6.4->6.6.5 + qt6-base-fourier 6.11.0->6.11.1 (track upstream extra)' (#12) from claude-noether/marfrit-packages:noether/kwin-qt6-baseline-bump into main
Reviewed-on: marfrit/marfrit-packages#12
2026-05-15 11:45:27 +00:00
claude-noether 75dadb2925 qt6-base-fourier: rebase 6.11.0 -> 6.11.1 to track upstream extra
Triggered by 'pacman -Syu' on fresnel showing local 1:6.11.0-2 newer
than (then-)extra 6.11.0-4. By the time of this commit Arch has moved
on to 6.11.1-1; rebase straight to that.

Diff against Arch's qt6-base 6.11.1 PKGBUILD reduced:
- _pkgver 6.11.0 -> 6.11.1
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256 of git tag updated to 2eafe504... (matches Arch's 6.11.1 PKGBUILD)
- Drop cherry-pick of 8b54513cdcf6 (qdbus crash fix landed upstream
  in 6.11.1; Arch dropped it from theirs as well)
- depends: gcc-libs replaced by libgcc + libstdc++ (Arch split these
  into separate packages between 6.11.0 and 6.11.1)
- Build flag: -DFEATURE_sql_ibase=OFF removed, -DFEATURE_mimetype_database=OFF
  added (Arch toggled in 6.11.1)

Kept (the reason this fork exists):
- 0001/0002/0003 GL_R8-on-ES3 patches (Mali GLES3 KWin compositor stall fix)
- qt6-base-cflags.patch + qt6-base-nostrip.patch (system CFLAGS + skip strip)
- qt6-xcb-private-headers-fourier sub-package (depended on by other fork pkgs)
- epoch=1 (precedence guarantee until upstream lands GL_R8/ES3 fix)

Patches NOT dry-run-verified against 6.11.1 source (qt clone is multi-GB
and impractical to fetch for a quick check). They touch glyph cache and
RHI gles2 paths that have been stable since Qt 6.10; expected to apply
cleanly. Will revert pkgrel and re-pin if first build hits hunk failures.
2026-05-15 10:57:02 +00:00
claude-noether fedcc4a357 kwin-fourier: 6.6.4 -> 6.6.5 (track upstream extra)
Triggered by 'pacman -Syu' on fresnel showing local 1:6.6.4-1 newer
than extra 6.6.5-1 (epoch wins, but our base lags upstream).

- pkgver 6.6.4 -> 6.6.5
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256sum updated for new tarball
- 0001-transaction-bypass-watchDmaBuf-fence-wait.patch dry-run verified
  clean against 6.6.5/src/wayland/transaction.cpp

Epoch=1 retained until upstream lands a proper V4L2 implicit-sync
fence-wait bypass (the patch-header hypothesis is still being tested
through ohm/fresnel HW-decode validation; not upstreamable yet).
2026-05-15 10:53:59 +00:00
marfrit 860ebf2df5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support) (#11) 2026-05-15 08:04:12 +00:00
claude-noether 109858eae5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support)
Follow-up to #10. The subdir layout I assumed worked turned out to not
work — per 'man PKGBUILD':

  The filename in the array must NOT include any path components like ./

makepkg's source-staging only honors basenames; the patches/ subdir
references staged the files but the basename-lookup at apply time
failed with the same 'not found in build directory' error that #9 hit.

I copied the chromium-fourier convention thinking it was proven, but
chromium-fourier has no CI either and likely has the same latent
breakage (separate issue, not in this PR's scope).

The actually-working pattern is the mpv-fourier one: patches at the
top level next to the PKGBUILD. mpv-fourier iter2 just built green
on CI (#92) with that layout.

This commit:
- Moves all 8 patches (5 fourier + 3 arch upstream) from patches/
  to arch/firefox-fourier/ via git mv (preserves blame).
- Removes the now-empty patches/ subdir.
- Strips 'patches/' prefix from source array entries.
- Strips '/patches' from prepare() patch -i paths.

No semantic change to the patch content or apply order.

pkgrel 3 -> 4.
2026-05-15 08:00:27 +00:00
marfrit 9041c1bf51 firefox-fourier: fix patches layout + ship missing arch upstream patches (#10) 2026-05-15 07:56:58 +00:00
claude-noether f41e9a117b firefox-fourier: fix patches layout — ship arch-*.patch + reference patches/
The PKGBUILD has been structurally broken since at least the 150.0.1
import: source array referenced patches at top level ('0001-...patch')
but the actual files live in patches/ — makepkg searched for them in
the package root and failed before doing any work. The arch-0002/3/4
upstream toolchain patches (clang 22, glibc 2.43, Rust 1.95) weren't
shipped in the repo at all.

Caught when boltzmann tried to build 150.0.1-2 (PR #9 follow-up); fails
at the source-staging phase with:

  ==> ERROR: arch-0002-Bug-2033279-Make-enable-rust-simd-work-with-Rust-1.9.patch
              was not found in the build directory and is not a URL.

Why nobody noticed: firefox-fourier has no Gitea Actions job (too heavy
for the runner pool). The shipped 150.0.1-1 .pkg.tar.zst was produced
by hand-staging files; the PKGBUILD itself never reproduced from a
clean checkout.

This commit:
- Moves all source-array patch references under patches/ to match the
  on-disk layout (same convention as chromium-fourier).
- Updates prepare() paths accordingly.
- Adds arch-0002/3/4 patches fetched verbatim from
  https://gitlab.archlinux.org/archlinux/packaging/packages/firefox
  (raw/main/{0002,0003,0004}-...patch). Renamed with arch- prefix in
  the repo to avoid namespace collision with the local 0001..0005.
- Adds the previously-omitted 0005-rdd-sandbox-v4l2-media-ctl.patch
  to the source array + prepare(); this is the patch that broadens
  the RDD sandbox so /dev/media* and /dev/video* ioctls reach the
  decoder child (README §1 enumerates it as load-bearing for the HW
  path). It was present in patches/ but not wired up.

Dry-run verified all 8 patches apply cleanly against firefox-150.0.1
source (some hunks offset by ≤3 lines, no conflicts).

pkgrel 2 -> 3.
2026-05-15 07:24:30 +00:00
marfrit 2f78136479 Merge pull request 'fresnel-fourier stack: bump libva to iter38b + fix firefox HW-decode defaults (#8)' (#9) from claude-noether/marfrit-packages:noether/libva-iter38b-and-firefox-prefs into main
Reviewed-on: marfrit/marfrit-packages#9
2026-05-15 06:13:19 +00:00
claude-noether 62a594ab59 firefox-fourier: ship RK3399 HW-decode default prefs (closes #8)
Three prefs that gate the patched VAAPI / V4L2-request code path are
'false' upstream and need to be 'true' for the libva-v4l2-request
backend to actually engage on RK3399 / panfrost EGL:

  widget.dmabuf.force-enabled
  media.hardware-video-decoding.force-enabled
  media.ffvpx-hw.enabled

Without them, Gecko's DMA-BUF probe silently fails (panfrost EGL
doesn't trip the right detection), the (Intel-tuned) HW-vs-SW cost
heuristic picks SW, and the FFvpx PDM never selects its HW-capable
variant for VP8/VP9. Net result: fresh profiles SW-decode despite the
0001..0004 unlock patches being applied.

Shipped as a vendor-default file at:
  /usr/lib/firefox-fourier/browser/defaults/preferences/rockchip-fourier-defaults.js

Lower precedence than user.js / about:config — power users debugging
HW decode can still flip them off without touching the package.

pkgrel 1 -> 2.

Closes: #8
2026-05-15 06:10:01 +00:00
claude-noether 81cc050bf3 libva-v4l2-request-fourier: bump pin iter8 -> iter38b (7ac934e)
Carries the fork from libva-multiplanar iter8 close (2026-05-06) to
fresnel-fourier iter38b (2026-05-14): multi-device probe so a single
libva session serves rkvdec (H.264 + HEVC + VP9) + hantro (MPEG-2 +
VP8) without LIBVA_V4L2_REQUEST_VIDEO_PATH overrides, plus the
MAX_PROFILES bounds-check fix from iter38b.

Required by the fresnel-fourier README's HW-decode stack (vainfo
exposes all 10 profiles in one session, byte-exact bench verified
across 5 codecs).

68 commits between the old pin (65969da3) and the new (7ac934e0).
pkgver() recomputes the rev count at build time; the static placeholder
is bumped from r280 to r348 to reflect the new pin.
2026-05-15 06:08:21 +00:00
62 changed files with 19675 additions and 43 deletions
+4 -4
View File
@@ -375,7 +375,7 @@ jobs:
run: rm -f /root/repo_pass /root/.ssh/id_ed25519
# -------------------------------------------------------------------------
# ffmpeg-v4l2-request-git (aarch64 only) — FFmpeg with V4L2 Request API
# ffmpeg-v4l2-request-fourier (aarch64 only) — FFmpeg with V4L2 Request API
# hwaccel for Rockchip / Allwinner stateless decoders. Used by the Fourier
# umbrella (ohm, fresnel, ampere). Long-running build, so failures don't
# block downstream debian jobs.
@@ -416,11 +416,11 @@ jobs:
chmod 600 /root/.ssh/id_ed25519
ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null
- name: makepkg ffmpeg-v4l2-request-git
- name: makepkg ffmpeg-v4l2-request-fourier
run: |
set -e
rm -rf /tmp/build-ffmpeg-v4l2
cp -r arch/ffmpeg-v4l2-request-git /tmp/build-ffmpeg-v4l2
cp -r arch/ffmpeg-v4l2-request-fourier /tmp/build-ffmpeg-v4l2
chown -R builder:builder /tmp/build-ffmpeg-v4l2
cd /tmp/build-ffmpeg-v4l2
# Parallelise wide; distcc-avahi distributes compiles across the
@@ -429,7 +429,7 @@ jobs:
makepkg --nocheck --noconfirm --syncdeps --cleanbuild
ls -la *.pkg.tar.* | grep -v "\.sig$"
- name: sign ffmpeg-v4l2-request-git
- name: sign ffmpeg-v4l2-request-fourier
run: |
set -e
cd /tmp/build-ffmpeg-v4l2
+71
View File
@@ -0,0 +1,71 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
#
# daedalus-v4l2-dkms — DKMS package for the daedalus_v4l2 out-of-tree
# kernel module (V4L2 stateless decoder shim for Pi 5 / CM5).
#
# Pair to daedalus-v4l2 (userspace daemon). When loaded, the module
# registers /dev/videoNN (V4L2 m2m) + /dev/mediaNN (media controller) +
# /dev/daedalus-v4l2 (chardev to the userspace daemon). Userspace
# clients drive the V4L2 m2m + request API path; the daemon does the
# actual FFmpeg-backed decode on /dev/daedalus-v4l2.
#
# Project: https://git.reauktion.de/reauktion/daedalus-v4l2
# Sibling userspace package: daedalus-v4l2
# Sibling consumer: libva-v4l2-request-fourier
pkgname=daedalus-v4l2-dkms
_module=daedalus_v4l2
# Same pin as arch/daedalus-v4l2 — keep kernel module + daemon
# bit-versioned together so the chardev wire protocol stays in sync.
_commit=f55b2cdab8a8c0bc04e8c1bb1d0b6ca85e7d96d2
pkgver=0.1.0.r16.f55b2cd
pkgrel=1
pkgdesc="V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5"
arch=('any')
url="https://git.reauktion.de/reauktion/daedalus-v4l2"
license=('GPL-2.0-or-later')
depends=('dkms')
makedepends=('git')
install="${pkgname}.install"
source=("git+https://git.reauktion.de/reauktion/daedalus-v4l2.git#commit=${_commit}"
"dkms.conf"
"${pkgname}.install")
sha256sums=('SKIP'
'SKIP'
'SKIP')
pkgver() {
cd "${srcdir}/daedalus-v4l2"
printf '0.1.0.r%s.%s' \
"$(git rev-list --count HEAD)" \
"$(git rev-parse --short=7 HEAD)"
}
package() {
local _src="${pkgdir}/usr/src/${_module}-${pkgver}"
install -dm755 "${_src}"
# Install the kernel/ subdir and embed the shared proto header in
# the same tree. The in-tree Makefile uses
# `ccflags-y += -I$(src)/../include` (assuming the parent
# daedalus-v4l2 layout); for DKMS we flatten by copying the header
# into kernel/include/ and patching the Makefile to point there.
cp -r "${srcdir}/daedalus-v4l2/kernel/." "${_src}/"
install -Dm644 "${srcdir}/daedalus-v4l2/include/daedalus_v4l2_proto.h" \
"${_src}/include/daedalus_v4l2_proto.h"
sed -i 's|-I\$(src)/\.\./include|-I$(src)/include|' "${_src}/Makefile"
# dkms.conf at the root of the source tree (DKMS convention).
# Substitute #MODULE_VERSION# placeholder with the actual pkgver
# so dkms install/uninstall match what's on disk.
install -Dm644 "${srcdir}/dkms.conf" "${_src}/dkms.conf"
sed -i "s/#MODULE_VERSION#/${pkgver}/" "${_src}/dkms.conf"
# License
install -Dm644 "${srcdir}/daedalus-v4l2/kernel/daedalus_v4l2_main.c" \
"${pkgdir}/usr/share/licenses/${pkgname}/SPDX-HEADER"
}
@@ -0,0 +1,61 @@
# post-install / post-upgrade hook for daedalus-v4l2-dkms.
#
# pacman + the dkms-helpers alpm hook will already attempt
# `dkms install` on its own. This script's job is to emit a
# loud, actionable warning when the module didn't actually
# build for the running kernel — most commonly because the
# kernel headers package isn't installed yet.
#
# Without this you get a silent failure: the package looks
# installed but `modprobe daedalus_v4l2` returns ENOENT.
_check_dkms_built() {
local name=daedalus_v4l2
local ver=$1
local kernelver=$(uname -r)
if ! command -v dkms >/dev/null 2>&1; then
return 1 # the hard-dep should have caught this
fi
local status
status=$(dkms status -m "$name" -v "$ver" -k "$kernelver" 2>/dev/null || true)
if printf '%s\n' "$status" | grep -q -E 'installed|loaded'; then
return 0 # all good
fi
cat >&2 <<EOF
==> daedalus-v4l2-dkms: DKMS build did NOT land for kernel $kernelver.
==> dkms status -m $name -v $ver -k $kernelver:
==> $(printf '%s' "$status" | head -1)
==>
==> Most likely cause: kernel headers package is missing.
==> Arch / ALARM: pacman -S linux-rpi-headers (or linux-rpi5-headers)
==> Raspberry Pi OS: apt install linux-headers-rpi-2712
==>
==> After installing headers, finish the install with:
==> sudo dkms autoinstall $name/$ver
==> sudo modprobe daedalus_v4l2
==>
==> Until then daedalus_v4l2 will NOT be loadable and the
==> userspace daedalus-v4l2 daemon will have nothing to talk to.
EOF
return 1
}
post_install() {
_check_dkms_built "$1" || true
}
post_upgrade() {
# New version pinned by the bump may have built fine, but if
# a kernel-headers package was uninstalled / pruned since the
# last upgrade we'd silently regress. Re-check.
_check_dkms_built "$1" || true
}
pre_remove() {
# The dkms alpm hook handles dkms remove on its own; nothing
# we need to add here.
:
}
+19
View File
@@ -0,0 +1,19 @@
# DKMS configuration for daedalus_v4l2 — V4L2 stateless decoder shim.
#
# Built against /lib/modules/$kernelver/build with the in-tree Makefile.
# The Makefile uses `obj-m := daedalus_v4l2.o` and links
# daedalus_v4l2_main.o + daedalus_v4l2_chardev.o into the final .ko.
PACKAGE_NAME="daedalus_v4l2"
PACKAGE_VERSION="#MODULE_VERSION#"
# Single module produced by the Makefile.
BUILT_MODULE_NAME[0]="daedalus_v4l2"
DEST_MODULE_LOCATION[0]="/updates"
# Use the package's own Makefile — it already does
# `$(MAKE) -C $(KERNELDIR) M=$(PWD) modules`.
MAKE[0]="make KERNELDIR=/lib/modules/${kernelver}/build all"
CLEAN="make KERNELDIR=/lib/modules/${kernelver}/build clean"
AUTOINSTALL="yes"
+105
View File
@@ -0,0 +1,105 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
#
# daedalus-v4l2 — userspace daemon + V4L2 m2m test tools.
#
# Pair to daedalus-v4l2-dkms (kernel module). Together they expose
# /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder shim on Pi 5 /
# CM5, decoding VP9 / AV1 / H.264 via dlopen'd FFmpeg in a single-
# threaded daemon and shipping decoded NV12 / P010 back through dmabuf.
# Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0.r376) so
# `ffmpeg -hwaccel vaapi` against vp9_small.ivf produces byte-exact NV12.
#
# Project: https://git.reauktion.de/reauktion/daedalus-v4l2
# Sibling kernel package: daedalus-v4l2-dkms
# Sibling consumer: libva-v4l2-request-fourier
pkgname=daedalus-v4l2
_upstreampkg=daedalus-v4l2
# Pin the daedalus-v4l2 tip. f55b2cd = "Phase 8.13: byte-exact end-to-
# end via libva (consumer target hit)" — first commit where the full
# ffmpeg -hwaccel vaapi → libva → /dev/video0 → daemon path lands a
# pixel-correct decoded frame back in ffmpeg. Promote to a later pin
# only after a future phase closes cleanly.
_commit=f55b2cdab8a8c0bc04e8c1bb1d0b6ca85e7d96d2
# 0.1.0 (pre-1.0) + commit count + short sha. Bump the .Y on each
# Phase 8.x close. pkgver() recomputes at build time.
pkgver=0.1.0.r16.f55b2cd
pkgrel=1
pkgdesc="Userspace daemon for the daedalus-v4l2 V4L2 stateless decoder shim (VP9/AV1/H.264 on Pi 5 / CM5)"
arch=('aarch64')
url="https://git.reauktion.de/reauktion/daedalus-v4l2"
license=('BSD-2-Clause' 'GPL-2.0-or-later')
# Daemon dlopens libavformat.so.61 / libavcodec.so.61 / libavutil.so.59
# at runtime (Option γ — see daemon/src/ffmpeg_loader.h). ffmpeg
# provides those; we don't link them.
depends=('ffmpeg' 'libdrm')
# Headers from libav*-dev needed at compile time for type-safe function
# pointer signatures; pkg-config locates them.
makedepends=('cmake' 'ninja' 'pkgconf' 'git' 'ffmpeg')
optdepends=('daedalus-v4l2-dkms: kernel module providing /dev/video0 + /dev/daedalus-v4l2'
'libva-v4l2-request-fourier: VA-API consumer routing through this daemon')
source=("git+https://git.reauktion.de/reauktion/daedalus-v4l2.git#commit=${_commit}")
sha256sums=('SKIP')
pkgver() {
cd "${srcdir}/${_upstreampkg}"
printf '0.1.0.r%s.%s' \
"$(git rev-list --count HEAD)" \
"$(git rev-parse --short=7 HEAD)"
}
build() {
cd "${srcdir}/${_upstreampkg}/daemon"
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build
cd "${srcdir}/${_upstreampkg}/tools"
make
}
package() {
cd "${srcdir}/${_upstreampkg}"
# Daemon binary
install -Dm755 daemon/build/daedalus_v4l2_daemon \
"${pkgdir}/usr/bin/daedalus_v4l2_daemon"
# Test tools (under /usr/libexec to keep them out of the default PATH
# — they're for verification, not daily use).
install -Dm755 tools/test_chardev_pingpong \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_chardev_pingpong"
install -Dm755 tools/test_m2m_decode \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_m2m_decode"
install -Dm755 tools/test_m2m_stream \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_m2m_stream"
# Shared wire-protocol header (kernel ↔ daemon); useful for
# third-party clients of the chardev.
install -Dm644 include/daedalus_v4l2_proto.h \
"${pkgdir}/usr/include/daedalus_v4l2_proto.h"
# Documentation
install -Dm644 README.md \
"${pkgdir}/usr/share/doc/${pkgname}/README.md"
for d in docs/*.md; do
install -Dm644 "$d" "${pkgdir}/usr/share/doc/${pkgname}/$(basename "$d")"
done
# Licenses: BSD-2-Clause for daemon/tools, GPL for the kernel proto
# header; the SPDX headers in src/ are the canonical declaration but
# ship a short note here for package-manager-driven license queries.
install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}"
cat > "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" <<'EOF'
daedalus-v4l2 userspace components are BSD-2-Clause licensed.
The shared kernel↔daemon wire protocol header
(/usr/include/daedalus_v4l2_proto.h) is GPL-2.0-or-later WITH
Linux-syscall-note for kernel-side compatibility. See SPDX
headers on individual source files for the canonical
per-file declaration.
EOF
}
@@ -0,0 +1,178 @@
From 0cd6e669735e453ec8772f111065bbb2f70a5bc6 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Mon, 18 May 2026 07:27:10 +0000
Subject: [PATCH] avutil/hwcontext_v4l2request: unpack NV15 to P010 in
transfer_data_from
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2_PIX_FMT_NV15 (RK3399/RK3588 rkvdec 10-bit 4:2:0 capture) is mapped to
sw_format = AV_PIX_FMT_YUV420P10 in v4l2request_capture_pixelformats[]. The
existing transfer_get_formats explicitly blanked the format list for that
sw_format, so 'ffmpeg -hwaccel v4l2request -vf hwdownload,format=p010le' on
a Hi10P / Main10 input failed at filter init with EINVAL before reaching
the actual decode (which itself succeeds — 2 frames decoded cleanly).
Expose AV_PIX_FMT_P010 as the transfer target for NV15-backed surfaces and
unpack the packed 10-bit samples into the standard high-bits-of-16 layout
inside transfer_data_from. Luma and chroma share the same packing format
(5 bytes per 4 samples, little endian); chroma plane is W × H/2 samples
for 4:2:0.
The other 'needs custom unpack' sw_formats (YUV420P / Allwinner NV12_32L32
tiled and YUV422P10 / rkvdec NV20) keep the original ENOSYS path because
they need different unpack code that isn't covered by this patch.
Closes marfrit/marfrit-packages#21.
---
libavutil/hwcontext_v4l2request.c | 111 +++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/libavutil/hwcontext_v4l2request.c b/libavutil/hwcontext_v4l2request.c
index b6633d9081..3842160dfb 100644
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -1073,6 +1073,56 @@ fail:
return ret;
}
+/*
+ * Unpack one NV15-packed 10-bit plane (5 bytes per 4 samples, little endian)
+ * into a P010-style plane (10 bits in the high bits of a 16-bit container).
+ * `dst_stride` is in bytes; `src_stride` is bytes per row of NV15 data.
+ */
+static void v4l2request_nv15_unpack_plane_to_p010(const uint8_t *src,
+ uint16_t *dst,
+ unsigned width,
+ unsigned height,
+ unsigned src_stride,
+ unsigned dst_stride)
+{
+ for (unsigned y = 0; y < height; y++) {
+ const uint8_t *s = src + y * src_stride;
+ uint16_t *d = (uint16_t *)((uint8_t *)dst + y * dst_stride);
+ unsigned x;
+
+ for (x = 0; x + 4 <= width; x += 4) {
+ uint16_t a = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ uint16_t b = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ uint16_t c = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ uint16_t e = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ d[0] = (uint16_t)(a << 6);
+ d[1] = (uint16_t)(b << 6);
+ d[2] = (uint16_t)(c << 6);
+ d[3] = (uint16_t)(e << 6);
+
+ d += 4;
+ s += 5;
+ }
+
+ if (x < width) {
+ unsigned rem = width - x;
+ uint16_t pix[4] = { 0, 0, 0, 0 };
+
+ pix[0] = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ if (rem >= 2)
+ pix[1] = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ if (rem >= 3)
+ pix[2] = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ if (rem >= 4)
+ pix[3] = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ for (unsigned j = 0; j < rem; j++)
+ d[j] = (uint16_t)(pix[j] << 6);
+ }
+ }
+}
+
static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
@@ -1082,6 +1132,22 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
if (dir == AV_HWFRAME_TRANSFER_DIRECTION_TO)
return AVERROR(ENOSYS);
+ /*
+ * NV15-backed surfaces (sw_format = YUV420P10) are exposed as P010 to
+ * downstream filters: the unpack below converts the packed 10-bit
+ * samples into the standard high-bits-of-16 layout. Hi10P / Main10
+ * VAAPI/v4l2-request decode reaches userspace through this path.
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ fmts = av_malloc_array(2, sizeof(*fmts));
+ if (!fmts)
+ return AVERROR(ENOMEM);
+ fmts[0] = AV_PIX_FMT_P010;
+ fmts[1] = AV_PIX_FMT_NONE;
+ *formats = fmts;
+ return 0;
+ }
+
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
@@ -1089,8 +1155,13 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
fmts[0] = hwfc->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
+ /*
+ * Tiled-NV12-32L32 (Allwinner) and NV20 (rkvdec 4:2:2 10-bit) still need
+ * dedicated unpacks before hwdownload can consume them; leave them as
+ * "no transfer formats" so the filter graph reports the limitation
+ * rather than silently producing garbage.
+ */
if (hwfc->sw_format == AV_PIX_FMT_YUV420P ||
- hwfc->sw_format == AV_PIX_FMT_YUV420P10 ||
hwfc->sw_format == AV_PIX_FMT_YUV422P10)
fmts[0] = AV_PIX_FMT_NONE;
@@ -1110,6 +1181,44 @@ static int v4l2request_transfer_data_from(AVHWFramesContext *hwfc,
map = av_frame_alloc();
if (!map)
return AVERROR(ENOMEM);
+
+ /*
+ * For NV15→P010, map the raw NV15 bytes (sw_format) and unpack into
+ * dst's P010 storage. Otherwise fall through to the original byte-copy
+ * path used for 1:1 sw_format matches (NV12, NV16, AFBC handled by DRM).
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ /*
+ * Only P010 is advertised by transfer_get_formats for this sw_format;
+ * a caller that bypasses get_formats and asks for anything else would
+ * silently corrupt output via av_frame_copy on NV15-packed bytes.
+ * Reject explicitly.
+ */
+ if (dst->format != AV_PIX_FMT_P010) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ map->format = hwfc->sw_format;
+ ret = v4l2request_map_frame(hwfc, map, src);
+ if (ret)
+ goto fail;
+
+ v4l2request_nv15_unpack_plane_to_p010(map->data[0],
+ (uint16_t *)dst->data[0],
+ dst->width, dst->height,
+ map->linesize[0],
+ dst->linesize[0]);
+ /* NV15 chroma plane is W × H/2 samples (4:2:0, UV interleaved). */
+ v4l2request_nv15_unpack_plane_to_p010(map->data[1],
+ (uint16_t *)dst->data[1],
+ dst->width, dst->height / 2,
+ map->linesize[1],
+ dst->linesize[1]);
+ ret = 0;
+ goto fail;
+ }
+
map->format = dst->format;
ret = v4l2request_map_frame(hwfc, map, src);
--
2.47.3
@@ -24,7 +24,7 @@ _srcname=FFmpeg
_version='8.1'
_commit='b57fbbe50c9b2656fad86a1a7eeabfd2b2a50935' # v4l2-request-n8.1 tip 2026-04-24
pkgver=8.1.r123329.b57fbbe
pkgrel=4
pkgrel=5
epoch=2
pkgdesc='FFmpeg with V4L2 Request API hwaccel (Rockchip / Allwinner stateless decode)'
arch=('aarch64')
@@ -78,8 +78,9 @@ provides=(
conflicts=(ffmpeg)
replaces=(ffmpeg ffmpeg-v4l2-request-git)
source=("git+https://github.com/Kwiboo/FFmpeg.git#commit=${_commit}"
'0001-libudev-bypass-fallback.patch')
sha256sums=('SKIP' 'SKIP')
'0001-libudev-bypass-fallback.patch'
'0002-nv15-to-p010-unpack.patch')
sha256sums=('SKIP' 'SKIP' 'SKIP')
pkgver() {
cd "${_srcname}"
@@ -91,6 +92,7 @@ pkgver() {
prepare() {
cd "${_srcname}"
patch -Np1 -i "${srcdir}/0001-libudev-bypass-fallback.patch"
patch -Np1 -i "${srcdir}/0002-nv15-to-p010-unpack.patch"
}
build() {
+22 -2
View File
@@ -13,7 +13,7 @@
pkgname=firefox-fourier
pkgver=150.0.1
pkgrel=1
pkgrel=5
pkgdesc='Firefox with V4L2 stateless HW video decode unlocked for mainline Linux Rockchip'
arch=('aarch64' 'x86_64')
url='https://www.mozilla.org/firefox'
@@ -87,8 +87,12 @@ source=(
'0002-libwrapper-hwdevice-ctx-create.patch'
'0003-ffmpegvideo-v4l2-request-route.patch'
'0004-prefs-v4l2-request.patch'
'0005-rdd-sandbox-v4l2-media-ctl.patch'
# Vendor-default prefs that gate the patched VAAPI path on RK3399 —
# widget.dmabuf.force-enabled etc. See marfrit-packages#8 for evidence.
'rockchip-fourier-defaults.js'
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
prepare() {
cd "${srcdir}/firefox-${pkgver}"
@@ -103,6 +107,7 @@ prepare() {
patch -Np1 -i "${srcdir}/0002-libwrapper-hwdevice-ctx-create.patch"
patch -Np1 -i "${srcdir}/0003-ffmpegvideo-v4l2-request-route.patch"
patch -Np1 -i "${srcdir}/0004-prefs-v4l2-request.patch"
patch -Np1 -i "${srcdir}/0005-rdd-sandbox-v4l2-media-ctl.patch"
cp "${srcdir}/mozconfig" .mozconfig
}
@@ -160,4 +165,19 @@ export MOZ_X11_EGL="${MOZ_X11_EGL:-1}"
exec /usr/lib/firefox-fourier/firefox-fourier "$@"
LAUNCHER
chmod 0755 "${pkgdir}/usr/bin/firefox-fourier"
# Vendor-default prefs (RK3399 HW-decode unlock) — closes #8.
# Lower precedence than user prefs / about:config; loaded by Firefox
# at startup from the package install dir. The 0004 patch covers
# media.ffmpeg.v4l2-request.enabled; this file covers the three
# additional prefs that gate the path to the patched code.
# Vendor-prefs install path: /usr/lib/firefox-fourier/defaults/preferences/
# (Mozilla's canonical scan dir for third-party default-pref drops.) The
# browser/defaults/preferences/ alternative looked promising but is NOT a
# vendor-prefs scan location in Firefox 150 — empirically confirmed on
# fresnel: file shipped there, VAAPI never engaged. Same file under
# defaults/preferences/ → MOZ_LOG showed `Requesting pixel format
# VAAPI_VLD` + dmabuf surfaces locking end-to-end.
install -Dm644 "${srcdir}/rockchip-fourier-defaults.js" \
"${pkgdir}/usr/lib/firefox-fourier/defaults/preferences/rockchip-fourier-defaults.js"
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Hochheiden <ahochheiden@mozilla.com>
Date: Wed, 1 Apr 2026 18:11:37 +0000
Subject: [PATCH] Bug 2023597 - Use `wasm32-wasip1` target for clang >= 22.1
r=firefox-build-system-reviewers,sergesanspaille
https://github.com/llvm/llvm-project/pull/165345
https://releases.llvm.org/22.1.0/tools/clang/docs/ReleaseNotes.html
Differential Revision: https://phabricator.services.mozilla.com/D291023
---
build/moz.configure/toolchain.configure | 3 +++
1 file changed, 3 insertions(+)
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
index a37ed610cc43..c7d0c8bdf75c 100644
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -695,6 +695,9 @@ def check_compiler(configure_cache, compiler, language, target, android_version)
# This makes clang define __ANDROID_API__ and use versioned library
# directories from the NDK.
toolchain = "%s%d" % (target.toolchain, android_version)
+ elif target.kernel == "WASI" and info.type == "clang" and info.version >= Version("22.1"):
+ # The wasm32-wasi target was renamed to wasm32-wasip1 in LLVM 22.1.
+ toolchain = "wasm32-wasip1"
else:
toolchain = target.toolchain
@@ -0,0 +1,19 @@
// firefox-fourier — RK3399 V4L2-stateless HW-decode default prefs.
//
// The patch series (0001..0004) builds the VAAPI / V4L2-request routing
// path through libavcodec, but the resulting code path is gated by three
// other prefs that are 'false' upstream because the relevant probes don't
// fire on panfrost EGL or trip the Intel-tuned cost heuristic. Without
// these, firefox-fourier silently SW-decodes on a fresh profile despite
// having all the unlock patches applied.
//
// Filed via marfrit/marfrit-packages#8 — see that issue for MOZ_LOG
// evidence on fresnel (Pinebook Pro / RK3399).
//
// These are *vendor* defaults: lower precedence than user.js and
// about:config user prefs. Power users who want to disable HW decode for
// debugging can flip them in user prefs without touching this file.
pref("widget.dmabuf.force-enabled", true);
pref("media.hardware-video-decoding.force-enabled", true);
pref("media.ffvpx-hw.enabled", true);
+4 -4
View File
@@ -2,7 +2,7 @@
# Upstream maintainers: Felix Yan, Antonio Rojas
# Contributor: Andrea Scarpino <andrea@archlinux.org>
#
# kwin-fourier — KWin 6.6.4 with the V4L2-stateless implicit-sync
# kwin-fourier — KWin 6.6.5 with the V4L2-stateless implicit-sync
# transaction wait bypass. Hypothesis: KWin's
# `Transaction::watchDmaBuf` calls DMA_BUF_IOCTL_EXPORT_SYNC_FILE on
# every plane of every imported dmabuf and parks the transaction on a
@@ -21,9 +21,9 @@
# ../chromium-fourier/KWIN_PIVOT.md for the full diagnosis thread.
pkgname=kwin-fourier
pkgver=6.6.4
pkgver=6.6.5
_dirver=$(echo $pkgver | cut -d. -f1-3)
pkgrel=3
pkgrel=1
_upname=kwin
epoch=1
arch=(aarch64 x86_64)
@@ -103,7 +103,7 @@ conflicts=(kwin)
replaces=(kwin)
source=(https://download.kde.org/stable/plasma/$_dirver/$_upname-$pkgver.tar.xz{,.sig}
0001-transaction-bypass-watchDmaBuf-fence-wait.patch)
sha256sums=('3f9439760580a977d018daf4b35b62e5a1700def7b21c8dfbfc789d21378d7ad'
sha256sums=('6c187ce7a5506090b438ef900103836fa0537674dde8b31e5b497ef321643cb4'
'SKIP'
'SKIP')
validpgpkeys=('E0A3EB202F8E57528E13E72FD7574483BB57B18D' # Jonathan Esk-Riddell <jr@jriddell.org>
+31 -11
View File
@@ -6,8 +6,11 @@
# tracks the campaign fork's git history directly, so iteration sweeps
# (DEBUG removal, follow-up bugfixes) land in a clean linear log.
#
# Campaign: ~/src/libva-multiplanar/ (eight closed iterations as of
# 2026-05-06; iter8 close is the production tip pinned below).
# Campaign: ~/src/libva-multiplanar/ (iter8 close 2026-05-06) plus
# ~/src/fresnel-fourier/ which carried the fork to iter38b — multi-device
# probe so a single libva session serves all 5 codecs (rkvdec H.264 +
# HEVC + VP9, hantro MPEG-2 + VP8) plus a bounds-check fix for
# MAX_PROFILES. Pinned below.
# Fork repo: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
# Bootlin upstream: https://github.com/bootlin/libva-v4l2-request
#
@@ -20,16 +23,25 @@
pkgname=libva-v4l2-request-fourier
_upstreampkg=libva-v4l2-request
# Pin the fork tip. 65969da = "iter8 Phase 4: tests/run_perf_binding_cell.sh"
# — last commit on master before fresnel-fourier work started layering
# MPEG-2 rewrites on top of it (2026-05-08). The libva-multiplanar campaign
# closed iter8 at this commit; promote to a later pin only after a future
# iteration closes cleanly.
_commit=65969da3ee901442a8ca4e1f7f9697d5461d368a
# Pin the fork tip. de27e95 = "v4l2: log error_idx + failing ctrl id
# on S_EXT_CTRLS failure" — Phase 8.13 diagnostic that surfaced the
# real root cause of the libva→daedalus_v4l2 request-completion
# timeout (turned out the EINVAL libva was logging was a harmless
# H264/HEVC probe; actual VP9 stateless control SET worked all along).
#
# Prior pin (7ac934e) was iter38b — fresnel-fourier multi-device probe
# + MAX_PROFILES bounds-check fix. de27e95 adds the daedalus_v4l2
# probe slot (b5b3acf), the meson option gate (2146341), and the
# S_EXT_CTRLS diagnostic (de27e95 itself). Backward-compatible on
# rkvdec / hantro / cedrus / rpi-hevc-dec hosts — daedalus probe is
# off by default unless the kernel module is present.
_commit=de27e95571b67ef34619c23a12db4698f9b3454e
# Project version from meson.build (1.0.0) + commit count + short sha,
# matching the ffmpeg-v4l2-request-fourier convention.
pkgver=1.0.0.r280.65969da
# matching the ffmpeg-v4l2-request-fourier convention. Recomputed at
# build time by pkgver() below; the static value here is a placeholder
# so AUR-style consumers see something coherent before src/ exists.
pkgver=1.0.0.r376.de27e95
pkgrel=1
pkgdesc="VA-API backend for V4L2 stateless decoders (multiplanar fork — fourier umbrella)"
arch=('aarch64')
@@ -55,7 +67,15 @@ build() {
cd "${srcdir}/${_upstreampkg}-fourier"
# meson_options.txt only exposes 'kernel_headers' — leave it empty to
# use system /usr/include kernel UAPI headers. No per-codec toggles.
arch-meson build --buildtype=release
#
# b_lto=false: override arch-meson's wrapper default of `-D b_lto=true`,
# which the makepkg.conf OPTIONS=(..., !lto, ...) line does NOT actually
# override (arch-meson hard-codes b_lto=true). The hand-built reproducer
# from issue #17 shows: LTO/ICF kernel-folds per-codec helpers and HEVC's
# multi-control-struct chain (SPS+PPS+DECODE_PARAMS+SLICE_PARAMS) gets a
# wrong helper-instance pulled in at vaEndPicture → segfault. The 4 other
# codecs (single-control-struct) tolerate the folding by accident.
arch-meson build --buildtype=release -Db_lto=false
meson compile -C build
}
+8 -1
View File
@@ -1,6 +1,13 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
# Campaign: ohm_gl_fix Phase 6 Step 1
#
# DEPRECATED (2026-05-16): superseded by ../libva-v4l2-request-fourier/
# which tracks the campaign fork's git history directly and adds the
# iter38 multi-device probe (single libva session for rkvdec H.264/HEVC/VP9
# + hantro MPEG-2/VP8). The successor declares
# replaces=('libva-v4l2-request-ohm-gl-fix'), so installing it removes
# this package automatically. See README.md for the full deprecation note.
#
# Forks libva-v4l2-request to add hantro-vpu multiplanar + modern
# stateless UAPI support. Conflicts/replaces stock libva-v4l2-request.
#
@@ -11,7 +18,7 @@ pkgname=libva-v4l2-request-ohm-gl-fix
_upstreampkg=libva-v4l2-request
pkgver=1.0.0.r0.ga3c2476
pkgrel=2
pkgdesc="VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork"
pkgdesc="DEPRECATED — use libva-v4l2-request-fourier. VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork"
arch=('aarch64')
url="https://github.com/bootlin/libva-v4l2-request"
license=('LGPL2.1' 'MIT')
@@ -1,5 +1,24 @@
# libva-v4l2-request-ohm-gl-fix
> ## ⚠ DEPRECATED — use [`libva-v4l2-request-fourier`](../libva-v4l2-request-fourier/) instead
>
> This package is the **predecessor experimental** build (tarball pin
> + 18 stacked patches) and is no longer maintained as of 2026-05-16.
> Its successor `libva-v4l2-request-fourier` tracks the campaign fork's
> git history directly
> ([git.reauktion.de/marfrit/libva-v4l2-request-fourier](https://git.reauktion.de/marfrit/libva-v4l2-request-fourier))
> so iteration sweeps (DEBUG removal, follow-up bugfixes) land in a clean
> linear log, and adds the iter38 multi-device probe that lets a single
> libva session serve rkvdec H.264/HEVC/VP9 + hantro MPEG-2/VP8 without
> needing `LIBVA_V4L2_REQUEST_VIDEO_PATH` overrides.
>
> `libva-v4l2-request-fourier` declares
> `replaces=('libva-v4l2-request-ohm-gl-fix')`, so installing it will
> remove this package automatically. Kept in-tree as historical reference
> for the ohm_gl_fix Phase 6 audit trail.
---
Bootlin's libva-v4l2-request VA-API backend, with hantro-vpu
multi-planar + chromium-149-era stateless H.264 patches developed
in the [ohm_gl_fix campaign](../../../ohm_gl_fix/) Phase 6 Step 1
+168
View File
@@ -0,0 +1,168 @@
# Maintainer: Markus Fritsche <mfritsche@reauktion.de>
#
# linux-ampere-fourier — CoolPi GenBook (RK3588) kernel built from the
# kernel-agent fleet/ampere.yaml manifest applied to mainline v7.0-rc3.
#
# kafr2 baseline (2026-05-18): mainline v7.0-rc3 + the 10 scope-tagged
# kernel-agent patches under patches/{soc,module,board,driver}/:
# - 1 soc/rk3588 pwm15 pinctrl
# - 6 board/coolpi-cm5-genbook DTS patches (pwm-fan, RK806 power-off,
# speaker, USB-C PD, lid switch + USB3 PHY, microphone)
# - 3 driver/media VP9-on-VDPU381 patches (Sarma's v8 series, imported
# via marfrit/kernel-agent#12 closure and PR #24)
#
# Drops the prior f8f3ad9 baseline ("18 commits ahead") because that tip
# black-screens ampere — kernel-agent's ka-promote produces this 10-patch
# minimal set from fleet/ampere.yaml. End-to-end VP9 + AV1 (av1-vpu-dec
# is mainline-7.0) decode verified bit-exact via kdirect on the
# hand-built tip 48a8c78 before this package iteration was cut.
#
# Coexists with the user's other extlinux labels in
# /boot/firmware/extlinux/extlinux.conf; never edits them. Adds a
# managed `linux-ampere-fourier` label (the user sets `default` manually
# after verifying boot).
#
# Bootloader path: /boot/firmware/ (vfat on mmcblk0p1). Kernel +
# initramfs + DTB land there directly. Reverting = boot a different
# extlinux label (e.g. arch_mainline, ubuntu_mainline).
pkgbase=linux-ampere-fourier
pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0rc3.kafr2
pkgrel=1
pkgdesc='CoolPi GenBook kernel (v7.0-rc3 + kernel-agent fleet/ampere.yaml — 6 board patches + 3 VP9-VDPU381 + 1 pwm15)'
arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only)
makedepends=(
bc cpio gettext kmod libelf pahole perl python tar xz
ccache
uboot-tools dtc
)
options=('!strip')
# Pinned tip of the kernel-agent-managed source tree for ampere.
# 10 commits ahead of v7.0-rc3, exactly mirroring fleet/ampere.yaml's
# manifest under apply order:
# - c57d069 soc/rk3588: pwm15 pinctrl entries
# - 05a915c board/genbook: pwm-fan with thermal cooling
# - d007b90 module/coolpi-cm5: RK806 system-power-controller
# - 3722eab board/genbook: speaker via audio-graph-card
# - 3e42ab6 board/genbook: USB-C PD via FUSB302
# - 7c241f2 board/genbook: lid switch + USB3 PHY lane
# - dd545fa board/genbook: wire internal microphone
# - 9ddcae5 driver/media: rkvdec-vp9 helper rename (Sarma)
# - c5063d9 driver/media: rkvdec move vp9 to common (Sarma)
# - 48a8c78 driver/media: rkvdec VP9 for VDPU381 (Sarma)
#
# This is the same tree state ka-promote ampere produces as cumulative.patch
# (see marfrit/kernel-agent build/ampere/v7.0-rc3/manifest.lock for the
# b2sum + per-patch sha256s).
_commit=48a8c785de7f5320513052a64e544c6310d7b273
source=(
# Local tarball produced by ./prebuild.sh from a local clone of the
# linux-rk3588-marfrit branch. Not fetched from a URL because the
# boltzmann working clone is shallow (gitea push rejects) and the
# 260MB tarball isn't committed to marfrit-packages. Run prebuild.sh
# before makepkg; see README in this dir.
"linux-rk3588-marfrit-${_commit:0:7}.tar.gz"
'config' # snapshot of running ampere kernel's /proc/config.gz (7.0.0-rc3-ARCH+)
'linux-ampere-fourier.preset'
'extlinux-add.hook'
'extlinux-add.sh'
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
# kernelrelease becomes <Makefile-VERSION>.<PATCH>.<SUBLEVEL><EXTRAVERSION><LOCALVERSION>
# i.e. 7.0.0-rc3-ampere-fourier. Module dir + EXTRAVERSION suffix keep
# this disjoint from the hand-managed /boot/firmware/Image-7.0.0-rc3-ARCH+
# that's currently on the host.
_kernver=7.0.0-rc3-ampere-fourier
_srcdir=linux-rk3588-marfrit
prepare() {
cd "${_srcdir}"
echo ":: writing config"
cp "${srcdir}/config" .config
# LOCALVERSION suffix to differentiate from upstream-stock builds.
scripts/config --set-str LOCALVERSION "-ampere-fourier"
scripts/config -d LOCALVERSION_AUTO
echo ":: olddefconfig (accept new symbols sensibly)"
make olddefconfig
make -s kernelrelease > version
echo ":: kernel release: $(<version)"
}
build() {
cd "${_srcdir}"
unset LDFLAGS
# Native build only — no distcc per kernel-agent policy
# (feedback_kernel_agent_no_distcc.md). ccache stays.
export CC="ccache gcc"
export HOSTCC="ccache gcc"
make ${MAKEFLAGS:--j$(nproc)} Image modules dtbs
}
_package() {
pkgdesc='CoolPi GenBook overclocked kernel (ampere-fourier baseline)'
depends=(coreutils kmod mkinitcpio uboot-tools)
optdepends=('linux-firmware: firmware images needed for some devices')
backup=("etc/mkinitcpio.d/${pkgbase}.preset")
cd "${_srcdir}"
local _kver
_kver=$(<version)
# Kernel image into the vfat firmware partition (where extlinux looks).
install -Dm644 arch/arm64/boot/Image \
"${pkgdir}/boot/firmware/Image-ampere-fourier"
# Single DTB for the GenBook target — install directly under
# /boot/firmware/ (no subdir, matches existing host convention).
install -Dm644 arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dtb \
"${pkgdir}/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier"
ZSTD_CLEVEL=19 make INSTALL_MOD_PATH="${pkgdir}/usr" \
INSTALL_MOD_STRIP=1 modules_install
rm -f "${pkgdir}/usr/lib/modules/${_kver}/"{source,build}
install -Dm644 "${srcdir}/${pkgbase}.preset" \
"${pkgdir}/etc/mkinitcpio.d/${pkgbase}.preset"
install -Dm755 "${srcdir}/extlinux-add.hook" \
"${pkgdir}/usr/share/libalpm/hooks/95-${pkgbase}-extlinux.hook"
install -Dm755 "${srcdir}/extlinux-add.sh" \
"${pkgdir}/usr/share/libalpm/scripts/${pkgbase}-extlinux"
}
_package-headers() {
pkgdesc='Headers and scripts for the linux-ampere-fourier kernel'
depends=(pahole)
cd "${_srcdir}"
local _kver _builddir
_kver=$(<version)
_builddir="${pkgdir}/usr/lib/modules/${_kver}/build"
install -Dt "${_builddir}" -m644 .config Makefile Module.symvers System.map vmlinux version
install -Dt "${_builddir}/kernel" -m644 kernel/Makefile
cp -a scripts "${_builddir}"
install -Dt "${_builddir}/arch/arm64" -m644 arch/arm64/Makefile
cp -a arch/arm64/include "${_builddir}/arch/arm64/"
cp -a include "${_builddir}/"
find . -name 'Kbuild' -exec install -Dm644 {} "${_builddir}/{}" \;
find . -name 'Kconfig*' -exec install -Dm644 {} "${_builddir}/{}" \;
install -d "${pkgdir}/usr/src"
ln -sr "${_builddir}" "${pkgdir}/usr/src/${pkgbase}"
}
eval "package_${pkgbase}() { _package; }"
eval "package_${pkgbase}-headers() { _package-headers; }"
+70
View File
@@ -0,0 +1,70 @@
# linux-ampere-fourier
Kernel package for ampere (CoolPi GenBook RK3588). Baselined on
`marfrit/linux-rk3588-marfrit @ f8f3ad9` (mainline v7.0-rc3 + 18
RK3588-fleet-relevant commits — 10 Markus, 8 upstream cherry-picks).
See `marfrit/kernel-agent/fleet/ampere.yaml` for the manifest +
`marfrit/kernel-agent/patches/{soc,module,board}/...` for the
scope-tagged board patches in the baseline.
## Build
The kernel source isn't on Gitea — boltzmann's working clone is
shallow (Gitea refuses shallow pushes) and a 260MB tarball doesn't
belong in `marfrit-packages`. Stage the source locally from a
clone of the `linux-rk3588-marfrit` branch:
```sh
cd arch/linux-ampere-fourier
./prebuild.sh # produces linux-rk3588-marfrit-f8f3ad9.tar.gz
makepkg -s --noconfirm # native aarch64 build; no distcc
```
`prebuild.sh` looks at `$LINUX_RK3588_MARFRIT_TREE` (default
`~/src/linux-rockchip`) for the kernel working tree. The tip commit
must be reachable in that clone — fetch the `linux-rk3588-marfrit`
branch first if you cloned from elsewhere.
## Build hosts
Native aarch64 only (per kernel-agent `feedback_kernel_agent_no_distcc.md`).
Either ampere itself (8C/2.4GHz, 32GB, native arch) or boltzmann
(Rock 5 ITX+, same uarch). fermi as fallback.
## Install
Adds a managed label to `/boot/firmware/extlinux/extlinux.conf`:
```
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append <inherited from arch_mainline>
```
Default label is NOT changed. After verifying boot of the managed
label at the u-boot menu, you flip `default` manually. Reverting =
boot a different label (e.g. `arch_mainline`, `ubuntu_mainline`).
## Boot path
ampere uses `/boot/firmware/` (vfat on mmcblk0p1, ~1G), distinct
from fresnel's `/boot/` on root partition. The PKGBUILD installs
Image, initramfs, and DTB directly under `/boot/firmware/`. No
DTB subdir — single board target.
## Open follow-ups (per kernel-agent issue #6)
- **Ask 2** (VP9 enablement on RK3588 rkvdec) — not addressed in this
iteration. Separate session.
- **Ask 3** (AV1 decoder integration) — backend libva work, not kernel.
- Hosting the source tarball publicly so `prebuild.sh` isn't needed —
candidate: Gitea release asset, or `packages.reauktion.de/sources/`.
- Splitting the 12 non-board cherry-pick commits in the baseline
(4 Shawn Lin phy, 2 Cristian Ciocaltea, etc.) into scope-tagged
patches in kernel-agent — currently they ride along inside the
pinned baseline rather than being explicit `includes:` in the
manifest.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = boot/firmware/Image-ampere-fourier
Target = boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
Target = boot/firmware/initramfs-ampere-fourier.img
[Action]
Description = Updating extlinux entry for linux-ampere-fourier
When = PostTransaction
Exec = /usr/share/libalpm/scripts/linux-ampere-fourier-extlinux
+62
View File
@@ -0,0 +1,62 @@
#!/bin/sh
# Add / update / remove the linux-ampere-fourier entry in
# /boot/firmware/extlinux/extlinux.conf. Idempotent. Coexists with
# the hand-managed labels in that file; never edits them. Default
# label is NOT touched — user picks at u-boot menu.
#
# ampere boots from a vfat partition (mmcblk0p1) mounted at
# /boot/firmware/, distinct from fresnel's /boot/ on root.
set -eu
CONF="/boot/firmware/extlinux/extlinux.conf"
TAG_BEGIN="# >>> linux-ampere-fourier (managed) >>>"
TAG_END="# <<< linux-ampere-fourier (managed) <<<"
# Copy APPEND from the user's `arch_mainline` label so the managed
# entry inherits the same root= and console= settings the host's
# bootloader already trusts. Falls back to a CoolPi GenBook default
# if no arch_mainline label exists (first-time install on a fresh
# bootloader config).
EXISTING_APPEND=$(awk '
/^[[:space:]]*label[[:space:]]+arch_mainline[[:space:]]*$/ { found=1; next }
found && /^[[:space:]]*append[[:space:]]/ {
sub(/^[[:space:]]*append[[:space:]]+/, "")
print
exit
}
/^[[:space:]]*label[[:space:]]/ { found=0 }
' "$CONF" 2>/dev/null || true)
APPEND="${EXISTING_APPEND:-root=LABEL=arch rw rootwait rootfstype=btrfs rootflags=subvol=@,ssd,discard=async console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=7 cma=256M coherent_pool=2M}"
ENTRY=$(cat <<EOF
${TAG_BEGIN}
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append ${APPEND}
${TAG_END}
EOF
)
# Strip any prior managed block, then append fresh
TMP=$(mktemp)
awk -v b="$TAG_BEGIN" -v e="$TAG_END" '
$0==b{skip=1; next}
$0==e{skip=0; next}
!skip{print}
' "$CONF" > "$TMP"
# Post-Remove: kernel files absent → don't re-add the entry
if [ -f "/boot/firmware/Image-ampere-fourier" ] \
&& [ -f "/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier" ]; then
printf '%s\n' "$ENTRY" >> "$TMP"
echo "linux-ampere-fourier: extlinux entry updated"
else
echo "linux-ampere-fourier: kernel files absent, entry removed"
fi
mv "$TMP" "$CONF"
@@ -0,0 +1,13 @@
# mkinitcpio preset for linux-ampere-fourier
#
# ampere boots from /boot/firmware/ (vfat partition on mmcblk0p1). The
# initramfs lands there too so extlinux can pick it up. Only one PRESET
# because /boot/firmware is ~1G total — no room for a fallback image
# alongside the primary.
ALL_kver="/boot/firmware/Image-ampere-fourier"
ALL_microcode=()
PRESETS=('default')
default_image="/boot/firmware/initramfs-ampere-fourier.img"
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
# prebuild — stage the kernel source tarball this PKGBUILD expects.
#
# linux-ampere-fourier's source is a snapshot of marfrit/linux-rk3588-marfrit
# @ f8f3ad9 (260MB), too big to commit to marfrit-packages and currently
# unpushable to Gitea (boltzmann's working clone is shallow; gitea push
# refuses shallow updates). Hosting the tarball outside Gitea would need
# infrastructure setup that's not in scope for the first iteration.
#
# So: produce the tarball locally from the kernel working tree just
# before makepkg runs. Idempotent — if an existing tarball matches the
# expected sha256 we skip the archive step.
#
# Run from this directory: cd arch/linux-ampere-fourier && ./prebuild.sh
# Override the kernel-tree location: LINUX_RK3588_MARFRIT_TREE=/path ./prebuild.sh
#
# Default tree location matches the boltzmann/ampere convention from
# kernel-agent issue #6: $HOME/src/linux-rockchip.
set -euo pipefail
TREE="${LINUX_RK3588_MARFRIT_TREE:-${HOME}/src/linux-rockchip}"
COMMIT=48a8c785de7f5320513052a64e544c6310d7b273
# Generated tarball sha varies with gzip version — script warns-not-fails.
# Leave EXPECTED empty for fresh kafr2 builds; first successful build can
# pin a canonical sha here if a reproducibility audit needs it.
SHA256_EXPECTED=
HERE="$(cd "$(dirname "$0")" && pwd)"
OUTPUT="${HERE}/linux-rk3588-marfrit-${COMMIT:0:7}.tar.gz"
if [ -f "$OUTPUT" ]; then
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" = "$SHA256_EXPECTED" ]; then
echo "prebuild: $OUTPUT already exists with correct sha256"
exit 0
else
echo "prebuild: existing $OUTPUT sha mismatch (have=$have, want=$SHA256_EXPECTED) — regenerating" >&2
rm -f "$OUTPUT"
fi
fi
if [ ! -d "$TREE/.git" ]; then
echo "prebuild: kernel tree not at $TREE" >&2
echo " set LINUX_RK3588_MARFRIT_TREE=/path/to/linux-rockchip and retry" >&2
exit 2
fi
cd "$TREE"
if ! git cat-file -e "$COMMIT" 2>/dev/null; then
echo "prebuild: commit $COMMIT not found in $TREE" >&2
echo " fetch the linux-rk3588-marfrit branch first:" >&2
echo " git fetch <remote> linux-rk3588-marfrit" >&2
exit 3
fi
echo "prebuild: generating archive from $TREE @ $COMMIT..."
git archive --format=tar.gz --prefix=linux-rk3588-marfrit/ "$COMMIT" -o "$OUTPUT"
# git archive emits a deterministic tar stream but gzip compression may
# vary by version. The sha256 check is informational; warn-don't-fail.
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" != "$SHA256_EXPECTED" ]; then
echo "prebuild: WARNING $OUTPUT sha=$have (canonical=$SHA256_EXPECTED)" >&2
echo " probably a gzip-version difference; tar payload should be identical" >&2
fi
echo "prebuild: wrote $OUTPUT ($(du -h "$OUTPUT" | cut -f1), sha=$have)"
@@ -0,0 +1,356 @@
From a202de1646d4c8f8ee2ebc2e4c100b621975754a Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:16:07 +0200
Subject: [PATCH RFC v2] media: videobuf2: add opt-in dma_resv producer fence
helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2 producers historically don't propagate buffer-state-done into
the dmabuf's dma_resv exclusive fence. Userspace consumers that
import V4L2-produced dmabufs and wait on the dmabuf's implicit-sync
fence (poll(POLLIN), DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
EGL_LINUX_DMA_BUF_EXT) currently see either zero fences or a stub
fence from dma_fence_get_stub(). This is correct by accident for the
common DQBUF-then-import case but represents a contract gap that
breaks Wayland compositors importing CAPTURE buffers from a stateless
H.264 decoder under continuous playback on implicit-sync GPU stacks
(observed on RK3566 + hantro VPU + Mali-G52 panfrost; manifests as
green frames -- BT.709 limited-range YUV(0,0,0) -> RGB(0,77,0) -- when
the GPU samples the dmabuf before the producer's decode completes).
Add an opt-in API gated by both a per-driver runtime flag
(vb2_queue::supports_release_fences) and a Kconfig
(CONFIG_VIDEOBUF2_RELEASE_FENCES, default n) that lets producers
populate a real dma_resv exclusive write fence on the dmabufs they
export. Drivers call vb2_buffer_attach_release_fence(vb) at a
finite-time-fenced point in their pipeline (typically m2m
device_run, just before the HW kick); vb2_buffer_done() signals and
puts the fence as part of its state transition.
The publish and signal paths are wrapped in
dma_fence_begin_signalling() / dma_fence_end_signalling() so
PROVE_LOCKING can validate that nothing taken in those critical
sections deadlocks against the signal path. dma_resv_lock is
sleepable but not taken on the signal path, so taking it inside the
publish critical section is safe under lockdep.
Skips planes whose vb2_plane.dbuf is NULL -- buffers never exported
via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF) have no
dmabuf for userspace to wait on.
Drivers that don't opt in pay nothing: the helper is a no-op stub
when CONFIG_VIDEOBUF2_RELEASE_FENCES=n, and an early-return check
of supports_release_fences when =y but the flag is unset.
Validated on RK3566 PineTab2 with PROVE_LOCKING enabled: 30s of
bbb_1080p30 H.264 stateless decode + zero-copy panfrost EGL import
via dmabuf-wayland (mpv 0.41 + KWin 6.6.4 + Mesa panfrost 26.0.5)
produces 31,816 dma_fence init/signal pairs across 5,724 vb2 buffer
cycles with zero lockdep splats from videobuf2 / dma_resv code paths.
Subsequent patches in this series opt the hantro and rockchip-rga
drivers in.
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Christian König <christian.koenig@amd.com>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Tomasz Figa <tfiga@chromium.org>
Cc: linux-media@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linaro-mm-sig@lists.linaro.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/common/videobuf2/Kconfig | 29 ++++
.../media/common/videobuf2/videobuf2-core.c | 135 ++++++++++++++++++
include/media/videobuf2-core.h | 51 +++++++
3 files changed, 215 insertions(+)
diff --git a/drivers/media/common/videobuf2/Kconfig b/drivers/media/common/videobuf2/Kconfig
index d2223a12c..bbfa26984 100644
--- a/drivers/media/common/videobuf2/Kconfig
+++ b/drivers/media/common/videobuf2/Kconfig
@@ -30,3 +30,32 @@ config VIDEOBUF2_DMA_SG
config VIDEOBUF2_DVB
tristate
select VIDEOBUF2_CORE
+
+config VIDEOBUF2_RELEASE_FENCES
+ bool "videobuf2: opt-in dma_resv producer fences for V4L2 dmabuf exports"
+ depends on VIDEOBUF2_CORE
+ depends on DMA_SHARED_BUFFER
+ default n
+ help
+ Enables an opt-in API that lets vb2 producers populate a dma_resv
+ exclusive write fence on the dmabufs they export to userspace.
+ The fence is signalled when the buffer transitions to
+ VB2_BUF_STATE_DONE.
+
+ This gives userspace consumers that import V4L2-produced dmabufs
+ and wait on the dmabuf's implicit-sync fence (poll(POLLIN),
+ DMA_BUF_IOCTL_EXPORT_SYNC_FILE, EGL_LINUX_DMA_BUF_EXT) a real
+ producer fence to wait on, instead of a stub fence from
+ dma_fence_get_stub() that the dma_buf core substitutes when
+ dma_resv is empty.
+
+ Drivers individually opt in by setting
+ vb2_queue::supports_release_fences = true and calling
+ vb2_buffer_attach_release_fence() at the right point in their
+ pipeline (typically m2m device_run, just before HW kick).
+
+ Distributors leave this off unless targeting Wayland/EGL
+ consumers of V4L2 stateless decoder output on
+ implicit-sync-only GPU stacks (e.g. mainline panfrost).
+
+ If unsure, say N.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index adf668b21..85d7fddbd 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -26,6 +26,12 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+#include <linux/dma-fence.h>
+#include <linux/dma-resv.h>
+#include <linux/dma-buf.h>
+#endif
+
#include <media/videobuf2-core.h>
#include <media/v4l2-mc.h>
@@ -1173,6 +1179,120 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
}
EXPORT_SYMBOL_GPL(vb2_plane_cookie);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+/*
+ * dma_resv release-fence integration.
+ *
+ * Optional, opt-in path that lets producers publish a real
+ * dma_fence on their CAPTURE-side dmabufs so userspace consumers
+ * (compositors, EGL importers) get spec-clean implicit-sync
+ * semantics instead of the dma_buf core's stub fence. Drivers
+ * call vb2_buffer_attach_release_fence() at a finite-time-fenced
+ * point (typically m2m device_run) and the fence is signalled by
+ * vb2_buffer_done(). Gated at runtime by
+ * vb2_queue::supports_release_fences and at compile time by
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+
+static const char *vb2_dma_resv_get_driver_name(struct dma_fence *fence)
+{
+ return "videobuf2";
+}
+
+static const char *vb2_dma_resv_get_timeline_name(struct dma_fence *fence)
+{
+ return "vb2-release-fence";
+}
+
+static const struct dma_fence_ops vb2_dma_resv_fence_ops = {
+ .get_driver_name = vb2_dma_resv_get_driver_name,
+ .get_timeline_name = vb2_dma_resv_get_timeline_name,
+};
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ struct dma_fence *fence;
+ unsigned int plane;
+ bool cookie;
+
+ if (!q->supports_release_fences)
+ return 0;
+
+ if (WARN_ON(vb->release_fence))
+ return -EINVAL;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence)
+ return -ENOMEM;
+
+ dma_fence_init(fence, &vb2_dma_resv_fence_ops, &q->dma_resv_fence_lock,
+ q->dma_resv_fence_context,
+ atomic64_inc_return(&q->dma_resv_fence_seqno));
+
+ /*
+ * Annotate the publish-side critical section. Per
+ * Documentation/driver-api/dma-buf.rst, lockdep validates
+ * that nothing taken in this region can deadlock against
+ * the signal path in vb2_buffer_signal_release_fence().
+ * dma_resv_lock is sleepable but is not taken on the signal
+ * path, so taking it inside the critical section is safe.
+ */
+ cookie = dma_fence_begin_signalling();
+ for (plane = 0; plane < vb->num_planes; plane++) {
+ struct dma_buf *dbuf = vb->planes[plane].dbuf;
+
+ if (!dbuf)
+ continue;
+
+ dma_resv_lock(dbuf->resv, NULL);
+ dma_resv_add_fence(dbuf->resv, fence, DMA_RESV_USAGE_WRITE);
+ dma_resv_unlock(dbuf->resv);
+ }
+ dma_fence_end_signalling(cookie);
+
+ /* One reference for the eventual signal in vb2_buffer_done. */
+ vb->release_fence = dma_fence_get(fence);
+
+ /* The dma_resv held its own reference per plane. Drop ours. */
+ dma_fence_put(fence);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+ struct dma_fence *fence = vb->release_fence;
+ bool cookie;
+
+ if (!fence)
+ return;
+
+ cookie = dma_fence_begin_signalling();
+ if (state == VB2_BUF_STATE_ERROR)
+ dma_fence_set_error(fence, -EIO);
+ dma_fence_signal(fence);
+ dma_fence_end_signalling(cookie);
+
+ dma_fence_put(fence);
+ vb->release_fence = NULL;
+}
+#else /* !CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static inline void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+}
+#endif /* CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
struct vb2_queue *q = vb->vb2_queue;
@@ -1199,6 +1319,9 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
if (state != VB2_BUF_STATE_QUEUED)
__vb2_buf_mem_finish(vb);
+ if (state != VB2_BUF_STATE_QUEUED)
+ vb2_buffer_signal_release_fence(vb, state);
+
spin_lock_irqsave(&q->done_lock, flags);
if (state == VB2_BUF_STATE_QUEUED) {
vb->state = VB2_BUF_STATE_QUEUED;
@@ -2651,6 +2774,18 @@ int vb2_core_queue_init(struct vb2_queue *q)
mutex_init(&q->mmap_lock);
init_waitqueue_head(&q->done_wq);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Per-queue dma_resv release-fence context. Drivers that
+ * opt in via supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a single per-queue timeline.
+ */
+ q->dma_resv_fence_context = dma_fence_context_alloc(1);
+ atomic64_set(&q->dma_resv_fence_seqno, 0);
+ spin_lock_init(&q->dma_resv_fence_lock);
+#endif
+
q->memory = VB2_MEMORY_UNKNOWN;
if (q->buf_struct_size == 0)
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4424d481d..766ff2194 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -288,6 +288,16 @@ struct vb2_buffer {
unsigned int skip_cache_sync_on_finish:1;
struct vb2_plane planes[VB2_MAX_PLANES];
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Producer release fence published on each plane's
+ * dmabuf->resv when the driver opts in via
+ * vb2_buffer_attach_release_fence(). Signalled and put by
+ * vb2_buffer_done() on transition to DONE/ERROR. NULL when
+ * the driver did not opt in for this buffer.
+ */
+ struct dma_fence *release_fence;
+#endif
struct list_head queued_entry;
struct list_head done_entry;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -648,6 +658,19 @@ struct vb2_queue {
spinlock_t done_lock;
wait_queue_head_t done_wq;
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * dma_resv release-fence context. Drivers that set
+ * supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a per-queue timeline.
+ */
+ u64 dma_resv_fence_context;
+ atomic64_t dma_resv_fence_seqno;
+ spinlock_t dma_resv_fence_lock;
+#endif
+
+ unsigned int supports_release_fences:1;
unsigned int streaming:1;
unsigned int start_streaming_called:1;
unsigned int error:1;
@@ -735,6 +758,34 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
*/
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
+/**
+ * vb2_buffer_attach_release_fence() - opt-in dma_resv release fence.
+ * @vb: the buffer being committed to the producer.
+ *
+ * Drivers that have set vb2_queue::supports_release_fences may call
+ * this from any sleepable context where they have committed to
+ * running the operation in finite time -- typically m2m
+ * device_run(), just before the HW kick. The helper allocates a
+ * dma_fence on the queue's per-queue timeline, attaches it as
+ * DMA_RESV_USAGE_WRITE on each plane's dmabuf->resv, and stashes
+ * it in vb->release_fence. vb2_buffer_done() signals and puts the
+ * fence as part of the buffer's state transition.
+ *
+ * Skips planes whose vb2_plane.dbuf is NULL -- buffers never
+ * exported via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF)
+ * have no dmabuf for userspace to wait on.
+ *
+ * No-op when vb2_queue::supports_release_fences is not set
+ * (regardless of CONFIG_VIDEOBUF2_RELEASE_FENCES). When
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES=n, this is a stub that returns 0.
+ *
+ * Returns 0 on success or when the no-op stub is in effect,
+ * negative errno on allocation failure when fence publishing was
+ * attempted. Best-effort: drivers should ignore the return value
+ * unless they want diagnostics.
+ */
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb);
+
/**
* vb2_discard_done() - discard all buffers marked as DONE.
* @q: pointer to &struct vb2_queue with videobuf2 queue.
--
2.53.0
@@ -0,0 +1,95 @@
From 1844c263bde8dd244d7db46f8c508e7c70da459c Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:24:01 +0200
Subject: [PATCH RFC v2] media: hantro: attach dma_resv release fence at
device_run
Opt the hantro driver into the new vb2 release-fence helper so its
CAPTURE-side dmabufs carry a real producer fence that wayland
compositors and other implicit-sync consumers can wait on, instead
of the dma_buf core's stub fence.
Attach point is m2m device_run, immediately after
v4l2_m2m_buf_copy_metadata() and before ctx->codec_ops->run().
Per Nicolas Dufresne's v1 review (lore.kernel.org/linux-media/
3d8deeb15581b754e4c061d4c4a13657aa08bc3c.camel@ndufresne.ca/),
this satisfies the dma_fence finite-time contract: the m2m core
has committed to running the job by this point, codec_ops->run
either kicks the HW (decode-complete signals the fence via
vb2_buffer_done) or fails immediately (job_finish with
VB2_BUF_STATE_ERROR signals with -EIO). PM and clocks are already
up by this point, so no allocation context restrictions.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers that import hantro CAPTURE dmabufs and wait on
their implicit-sync fence (Wayland zwp_linux_dmabuf_v1 +
panfrost EGL_LINUX_DMA_BUF_EXT) now wait on a real fence
representing the producer's actual completion, fixing green-frame
corruption observed on RK3566 PineTab2 + Mali-G52 panfrost (the
GPU was sampling zero pages because the dmabuf's implicit fence
was the dma_buf core's pre-signalled stub).
Validated end-to-end on PineTab2 (RK3566 / hantro G1 / Mali-G52
mainline panfrost): 30s of bbb_1080p30 H.264 stateless decode +
zero-copy panfrost EGL import via dmabuf-wayland (mpv 0.41 +
KWin 6.6.4 + Mesa panfrost 26.0.5) renders correctly with no
green-frame corruption and no PROVE_LOCKING splats.
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
.../media/platform/verisilicon/hantro_drv.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 2e81877f6..6a66c47ed 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -186,6 +186,22 @@ static void device_run(void *priv)
v4l2_m2m_buf_copy_metadata(src, dst);
+ /*
+ * Attach a producer fence on the CAPTURE-side dmabuf so userspace
+ * importers (e.g. Wayland compositors) get spec-clean implicit-sync
+ * semantics. Called from device_run rather than buf_queue: the
+ * dma_fence finite-time contract requires that once a fence is
+ * published, the producer must signal it in finite time. By the
+ * time we reach device_run, the m2m core has committed to running
+ * this job, and the next hop (codec_ops->run) either kicks the HW
+ * (decode-complete signals the fence via vb2_buffer_done) or
+ * fails immediately (job_finish with VB2_BUF_STATE_ERROR signals
+ * the fence with -EIO). Either path resolves the fence in finite
+ * time. Best-effort: a NOMEM here means we lose implicit-sync
+ * precision for this frame, no functional regression.
+ */
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
if (ctx->codec_ops->run(ctx))
goto err_cancel_job;
@@ -249,6 +265,13 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->dev->vpu_mutex;
dst_vq->dev = ctx->dev->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * No-op unless CONFIG_VIDEOBUF2_RELEASE_FENCES=y; runtime cost
+ * is one extra fence allocation + dma_resv update per device_run.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
@@ -0,0 +1,117 @@
From 2c63a63bf65739763051dc4ce7ce2ffaf2d514c4 Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:50:51 +0200
Subject: [PATCH RFC v2] media: rockchip-rga: attach dma_resv release fence at
device_run
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Opt the rockchip-rga driver into the new vb2 release-fence helper.
Same shape as the hantro patch: attach a producer fence on the
CAPTURE-side dmabuf at m2m device_run, signalled by
vb2_buffer_done() when RGA completes the m2m operation.
Differs from hantro in one mechanical detail: rga's device_run
wraps the entire body in spin_lock_irqsave(&rga->ctrl_lock). Our
helper calls dma_resv_lock(), which is sleepable, so the
buffer-fetch + fence-attach sequence has to run above the spinlock.
Restructure device_run so:
- v4l2_m2m_next_src_buf / next_dst_buf,
- src->sequence increment,
- vb2_buffer_attach_release_fence(&dst->vb2_buf)
run before spin_lock_irqsave; only the rga->curr assignment and
rga_hw_start() (the actual HW kick) remain inside the spinlock.
This is safe under the m2m-job ownership model: by the time
device_run is called, the m2m core has selected this context and
serializes one device_run per context, so v4l2_m2m_next_*_buf
returns stable pointers until the corresponding *_buf_remove in
rga_isr. ctrl_lock was previously protecting per-device state
(rga->curr) and the HW register access, neither of which depends on
the buffer-fetch happening inside the lock.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers of RGA-produced dmabufs (image-processing
pipelines, screen-rotation servers, gstreamer flows on Rockchip
boards) get spec-clean implicit-sync semantics, matching what
hantro does in the previous patch in this series.
Sven Püschel's ongoing "media: platform: rga: Add RGA3 support"
v5 series (linux-rockchip 2026-04-28) restructures rga.c
substantially. If that lands first, the device_run restructure
here will need a rebase against the new shape; the locking story
itself is invariant.
Cc: Jacob Chen <jacob-chen@iotwrt.com>
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Sven Püschel <s.pueschel@pengutronix.de>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/platform/rockchip/rga/rga.c | 27 +++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index fea63b94c..03030c7ea 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -38,15 +38,28 @@ static void device_run(void *prv)
struct vb2_v4l2_buffer *src, *dst;
unsigned long flags;
- spin_lock_irqsave(&rga->ctrl_lock, flags);
-
- rga->curr = ctx;
-
+ /*
+ * Fetch the next-job buffers and (best-effort) attach a producer
+ * fence on CAPTURE before taking ctrl_lock below.
+ * vb2_buffer_attach_release_fence() takes dma_resv_lock, which is
+ * sleepable; ctrl_lock is taken with spin_lock_irqsave so any
+ * sleepable call must happen above it. Buffer ownership is
+ * already committed at this point: the m2m core has selected
+ * this context for device_run and serializes one device_run per
+ * context, so v4l2_m2m_next_*_buf returns stable pointers until
+ * the corresponding *_buf_remove in rga_isr.
+ */
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
src->sequence = ctx->osequence++;
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
+ spin_lock_irqsave(&rga->ctrl_lock, flags);
+
+ rga->curr = ctx;
+
rga_hw_start(rga, vb_to_rga(src), vb_to_rga(dst));
spin_unlock_irqrestore(&rga->ctrl_lock, flags);
@@ -123,6 +136,12 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->rga->mutex;
dst_vq->dev = ctx->rga->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * Compile-time gated by CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
+8 -3
View File
@@ -10,8 +10,8 @@
pkgbase=linux-fresnel-fourier
pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0
pkgrel=1
pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks)'
pkgrel=14
pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks + vb2_dma_resv RFC v2)'
arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only)
@@ -23,15 +23,20 @@ makedepends=(
options=('!strip')
source=(
"https://git.kernel.org/torvalds/t/linux-${pkgver}.tar.gz"
# board/pinebook-pro
'0001-arm64-dts-rk3399-pinebook-pro-add-OC-OPP-tables-1704-2184.patch'
'0002-arm64-dts-rk3399-pinebook-pro-enable-hdmi-sound.patch'
'0003-arm64-dts-rk3399-pinebook-pro-spi1-max-freq-10MHz.patch'
# subsystem/media/videobuf2/dma-resv-release-fence (RFC v2, in kernel-agent)
'0004-media-videobuf2-add-opt-in-dma_resv-producer-fence-h.patch'
'0005-media-hantro-attach-dma_resv-release-fence-at-device.patch'
'0006-media-rockchip-rga-attach-dma_resv-release-fence-at-.patch'
'config' # snapshot of fresnel /usr/lib/modules/6.19.10-1-eos-arm/build/.config
'linux-fresnel-fourier.preset'
'extlinux-add.hook'
'extlinux-add.sh'
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
_kernver=${pkgver}.0-fresnel-fourier
_srcdir=linux-${pkgver}
+6 -3
View File
@@ -3,15 +3,18 @@
# Source of truth: git.reauktion.de/marfrit/lmcp
pkgname=lmcp
pkgver=0.5.4
pkgver=1.2.1
pkgrel=1
pkgdesc="Lightweight MCP (Model Context Protocol) server in pure Lua"
arch=('any')
url="https://git.reauktion.de/marfrit/lmcp"
license=('MIT')
depends=('lua' 'lua-socket')
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/v${pkgver}.tar.gz")
sha256sums=('af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf')
# The _tag back-translation handles both clean releases (no '_') and
# pre-release pkgvers (e.g. 1.2.0_rc1 → v1.2.0-rc1).
_tag="v${pkgver//_/-}"
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/${_tag}.tar.gz")
sha256sums=('bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609')
package() {
cd "${pkgname}"
+9 -9
View File
@@ -21,14 +21,14 @@
# pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase")
# resolves correctly. The "-fourier" suffix lives only in the
# directory name and the commit history; epoch=1 gives our local
# build strict precedence over upstream pkgrel=2 until upstream lands
# build strict precedence over upstream pkgrel=N until upstream lands
# the GL_R8/ES3 fix and we can drop the epoch.
pkgbase=qt6-base
pkgname=(qt6-base-fourier
qt6-xcb-private-headers-fourier)
_pkgver=6.11.0
_pkgver=6.11.1
pkgver=${_pkgver/-/}
pkgrel=3
pkgrel=1
epoch=1
arch=(aarch64 x86_64)
url='https://www.qt.io'
@@ -42,7 +42,6 @@ depends=(brotli
double-conversion
fontconfig
freetype2
gcc-libs
glib2
glibc
harfbuzz
@@ -51,6 +50,7 @@ depends=(brotli
libb2
libcups
libdrm
libgcc
libgl
libice
libinput
@@ -58,6 +58,7 @@ depends=(brotli
libpng
libproxy
libsm
libstdc++
liburing
libx11
libxcb
@@ -115,7 +116,7 @@ source=(git+https://code.qt.io/qt/$_pkgfn#tag=v$_pkgver
0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch
0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch
0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch)
sha256sums=('2223c075e95d86f8dbf6395b025a74d996c418f094453c903290e3c2663fbed2'
sha256sums=('2eafe504fae873d20f206b5661e2e10506879455cb2d370f42c5bb72ccf7a8a1'
'5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78'
'4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094'
'SKIP'
@@ -126,9 +127,8 @@ prepare() {
patch -d $_pkgfn -p1 < qt6-base-cflags.patch # Use system CFLAGS
patch -d $_pkgfn -p1 < qt6-base-nostrip.patch # Don't strip binaries with qmake
# cherry-pick needs git author identity; git-cli refuses without it.
git -C $_pkgfn -c user.email=fourier@build -c user.name='qt6-base-fourier build' \
cherry-pick -n 8b54513cdcf62047376a5d27d784ad68a8f235bf # Fix qdbus crashes
# 8b54513cdcf6 (qdbus crash fix) cherry-pick removed: landed upstream
# in 6.11.1. Re-add if qdbus regressions re-surface.
# qt6-base-fourier — three small runtime-checks that pick GL_R8 over
# GL_ALPHA when the live GL context is ES 3 or newer. See the
@@ -165,7 +165,7 @@ build() {
-DFEATURE_system_sqlite=ON \
-DFEATURE_system_xcb_xinput=ON \
-DFEATURE_no_direct_extern_access=$_no_direct_extern_access \
-DFEATURE_sql_ibase=OFF \
-DFEATURE_mimetype_database=OFF \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_MESSAGE_LOG_LEVEL=STATUS
cmake --build build
+174
View File
@@ -0,0 +1,174 @@
#!/bin/bash
# Build daedalus-v4l2-dkms_<ver>_all.deb (kernel module via DKMS).
#
# Installs kernel/ source tree to /usr/src/daedalus_v4l2-${PKGVER}/
# plus a dkms.conf. Postinst registers with DKMS (dkms add + build +
# install). Prerm deregisters. Result: the daedalus_v4l2 module
# auto-rebuilds against any installed kernel headers without users
# needing to remember to dkms-add it.
#
# Architecture: all. The kernel module itself is per-kernel-version,
# but the SOURCE package is arch-independent.
#
# Sibling Arch package: ../../arch/daedalus-v4l2-dkms/PKGBUILD
# Sibling userspace package: ../daedalus-v4l2/build-deb.sh
set -euo pipefail
UPSTREAM_COMMIT=f55b2cdab8a8c0bc04e8c1bb1d0b6ca85e7d96d2
PKGVER=0.1.0+r16+gf55b2cd
PKGREL=1
MODULE_NAME=daedalus_v4l2
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo daedalus-v4l2.tar.gz \
"https://git.reauktion.de/reauktion/daedalus-v4l2/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf daedalus-v4l2.tar.gz
SRCDIR=daedalus-v4l2
ROOT="$work/pkgroot"
SRCROOT="$ROOT/usr/src/${MODULE_NAME}-${PKGVER}"
mkdir -p "$SRCROOT/include" \
"$ROOT/DEBIAN" \
"$ROOT/usr/share/doc/daedalus-v4l2-dkms"
# Copy kernel/ source files to the DKMS source dir.
cp -r "$work/$SRCDIR/kernel/." "$SRCROOT/"
# Embed the shared protocol header inline (rather than referencing
# ../include/ which doesn't exist after DKMS extracts the tree).
# Patch the Makefile to find it at $SRCROOT/include/ instead.
install -m 644 "$work/$SRCDIR/include/daedalus_v4l2_proto.h" \
"$SRCROOT/include/daedalus_v4l2_proto.h"
sed -i 's|-I\$(src)/\.\./include|-I$(src)/include|' "$SRCROOT/Makefile"
# Generate dkms.conf with the actual version substituted.
cat > "$SRCROOT/dkms.conf" <<EOF
PACKAGE_NAME="${MODULE_NAME}"
PACKAGE_VERSION="${PKGVER}"
BUILT_MODULE_NAME[0]="${MODULE_NAME}"
DEST_MODULE_LOCATION[0]="/updates"
MAKE[0]="make KERNELDIR=/lib/modules/\${kernelver}/build all"
CLEAN="make KERNELDIR=/lib/modules/\${kernelver}/build clean"
AUTOINSTALL="yes"
EOF
# Doc
install -m 644 "$work/$SRCDIR/README.md" \
"$ROOT/usr/share/doc/daedalus-v4l2-dkms/README.md"
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/daedalus-v4l2-dkms/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/daedalus-v4l2-dkms/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/daedalus-v4l2-dkms/changelog.Debian"
# DKMS post-install / pre-remove hooks.
cat > "$ROOT/DEBIAN/postinst" <<EOF
#!/bin/sh
set -e
NAME=${MODULE_NAME}
VERSION=${PKGVER}
KERNELVER=\$(uname -r)
# Yellow + bold ANSI for the warning so it stands out in apt's
# stream of "Setting up" lines. Disable colour on non-TTY.
if [ -t 1 ]; then
Y=\$(printf '\\033[1;33m'); R=\$(printf '\\033[0m')
else
Y=''; R=''
fi
warn() {
printf '%s==> daedalus-v4l2-dkms: %s%s\\n' "\$Y" "\$1" "\$R" >&2
}
if [ "\$1" = "configure" ]; then
if ! command -v dkms >/dev/null 2>&1; then
warn "dkms not installed; module \$NAME/\$VERSION not registered."
warn "Install 'dkms' then run: dkms add \$NAME/\$VERSION && dkms autoinstall"
exit 0
fi
dkms add "\$NAME/\$VERSION" 2>/dev/null || true
# Don't let autoinstall failure mask the actual problem behind '|| true'.
# Run it, capture the result, then verify post-condition.
autoinstall_rc=0
dkms autoinstall "\$NAME/\$VERSION" || autoinstall_rc=\$?
# Verify the module actually built + installed for the running kernel.
status=\$(dkms status -m "\$NAME" -v "\$VERSION" -k "\$KERNELVER" 2>/dev/null || true)
if ! printf '%s\\n' "\$status" | grep -q -E 'installed|loaded'; then
warn ""
warn "DKMS build did NOT land for kernel \$KERNELVER."
warn " dkms status -m \$NAME -v \$VERSION -k \$KERNELVER:"
warn " \$(printf '%s' "\$status" | head -1)"
warn ""
warn "Most likely cause: kernel headers package is missing."
warn " Raspberry Pi OS / Pi 5: apt install linux-headers-rpi-2712"
warn " Debian generic: apt install linux-headers-\$KERNELVER"
warn ""
warn "After installing headers, finish the install with:"
warn " sudo dkms autoinstall \$NAME/\$VERSION"
warn " sudo modprobe daedalus_v4l2"
warn ""
warn "Until then daedalus_v4l2 will NOT be loadable and the"
warn "userspace daedalus-v4l2 daemon will have nothing to talk to."
fi
fi
#DEBHELPER#
EOF
chmod 755 "$ROOT/DEBIAN/postinst"
cat > "$ROOT/DEBIAN/prerm" <<EOF
#!/bin/sh
set -e
NAME=${MODULE_NAME}
VERSION=${PKGVER}
if [ "\$1" = "remove" ] && command -v dkms >/dev/null 2>&1; then
dkms remove "\$NAME/\$VERSION" --all || true
fi
#DEBHELPER#
EOF
chmod 755 "$ROOT/DEBIAN/prerm"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: daedalus-v4l2-dkms
Version: ${PKGVER}-${PKGREL}
Section: kernel
Priority: optional
Architecture: all
Depends: dkms (>= 2.1.0.0)
Recommends: daedalus-v4l2, linux-headers-generic | linux-headers
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Description: V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5
Out-of-tree V4L2 m2m kernel module for the daedalus-v4l2 stack on
Raspberry Pi 5 / CM5. Registers /dev/videoNN (V4L2 stateless m2m
decoder), /dev/mediaNN (media controller with request API), and
/dev/daedalus-v4l2 (chardev bridge to the userspace daemon).
.
The actual decode happens in the userspace daemon shipped by the
daedalus-v4l2 package — this module is just the kernel-side V4L2
plumbing. Install both to actually serve VAAPI / V4L2 clients.
.
Built via DKMS against the running kernel's headers.
EOF
DEB_OUT="daedalus-v4l2-dkms_${PKGVER}-${PKGREL}_all.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+11
View File
@@ -0,0 +1,11 @@
daedalus-v4l2-dkms (0.1.0+r16+gf55b2cd-1) bookworm trixie; urgency=medium
* Initial Debian DKMS packaging for the daedalus_v4l2 kernel module.
* Pinned to f55b2cd (Phase 8.13 close): kernel-side framework
integration (V4L2 m2m, dmabuf-export, media controller, request
API, NV12 single-plane + NV12M + P010 CAPTURE) that closes the
libva→/dev/video0→daemon round-trip with byte-exact pixels.
* Auto-builds via DKMS against the running kernel's headers.
* Companion userspace package: daedalus-v4l2 (daemon + tools).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+24
View File
@@ -0,0 +1,24 @@
Source: daedalus-v4l2-dkms
Section: kernel
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Package: daedalus-v4l2-dkms
Architecture: all
Depends: ${misc:Depends}, dkms (>= 2.1.0.0)
Recommends: daedalus-v4l2,
linux-headers-generic | linux-headers
Description: V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5
Out-of-tree V4L2 m2m kernel module for the daedalus-v4l2 stack on
Raspberry Pi 5 / CM5. Registers /dev/videoNN (V4L2 stateless m2m
decoder), /dev/mediaNN (media controller with request API), and
/dev/daedalus-v4l2 (chardev bridge to the userspace daemon).
.
The actual decode happens in the userspace daemon shipped by the
daedalus-v4l2 package — this module is just the kernel-side V4L2
plumbing. Install both to actually serve VAAPI / V4L2 clients.
.
Built via DKMS against the running kernel's headers.
+21
View File
@@ -0,0 +1,21 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: daedalus-v4l2
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/reauktion/daedalus-v4l2
Files: *
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-2.0-or-later
Comment:
Kernel module (loadable into the Linux kernel) — GPL-2.0-or-later.
The shared protocol header carries an additional Linux-syscall-note
exception so userspace inclusion is BSD-clean.
License: GPL-2.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
+106
View File
@@ -0,0 +1,106 @@
#!/bin/bash
# Build daedalus-v4l2_<ver>_arm64.deb (userspace daemon + test tools).
#
# Mirrors arch/daedalus-v4l2 (Arch Linux build). The companion DKMS
# package (debian/daedalus-v4l2-dkms) carries the kernel module
# separately so apt/dpkg can split kernel-version-tied and userspace
# upgrade cadence.
#
# Sibling Arch package: ../../arch/daedalus-v4l2/PKGBUILD
# Sibling DKMS package: ../daedalus-v4l2-dkms/build-deb.sh
# Upstream repo: https://git.reauktion.de/reauktion/daedalus-v4l2
set -euo pipefail
# Same pin as the Arch PKGBUILD. f55b2cd = "Phase 8.13: byte-exact
# end-to-end via libva (consumer target hit)" — first commit where the
# full ffmpeg -hwaccel vaapi → libva → /dev/video0 → daemon path lands
# a pixel-correct decoded frame back in ffmpeg.
UPSTREAM_COMMIT=f55b2cdab8a8c0bc04e8c1bb1d0b6ca85e7d96d2
PKGVER=0.1.0+r16+gf55b2cd
PKGREL=1
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo daedalus-v4l2.tar.gz \
"https://git.reauktion.de/reauktion/daedalus-v4l2/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf daedalus-v4l2.tar.gz
SRCDIR=daedalus-v4l2
# Build daemon (CMake)
cd "$SRCDIR/daemon"
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build
# Build test tools (in-tree Makefile)
cd "$work/$SRCDIR/tools"
make
# Stage
ROOT="$work/pkgroot"
mkdir -p "$ROOT/DEBIAN" \
"$ROOT/usr/bin" \
"$ROOT/usr/libexec/daedalus-v4l2" \
"$ROOT/usr/include" \
"$ROOT/usr/share/doc/daedalus-v4l2"
install -m 755 "$work/$SRCDIR/daemon/build/daedalus_v4l2_daemon" \
"$ROOT/usr/bin/daedalus_v4l2_daemon"
install -m 755 "$work/$SRCDIR/tools/test_chardev_pingpong" \
"$ROOT/usr/libexec/daedalus-v4l2/test_chardev_pingpong"
install -m 755 "$work/$SRCDIR/tools/test_m2m_decode" \
"$ROOT/usr/libexec/daedalus-v4l2/test_m2m_decode"
install -m 755 "$work/$SRCDIR/tools/test_m2m_stream" \
"$ROOT/usr/libexec/daedalus-v4l2/test_m2m_stream"
install -m 644 "$work/$SRCDIR/include/daedalus_v4l2_proto.h" \
"$ROOT/usr/include/daedalus_v4l2_proto.h"
install -m 644 "$work/$SRCDIR/README.md" \
"$ROOT/usr/share/doc/daedalus-v4l2/README.md"
for d in "$work/$SRCDIR/docs/"*.md; do
install -m 644 "$d" "$ROOT/usr/share/doc/daedalus-v4l2/$(basename "$d")"
done
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/daedalus-v4l2/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/daedalus-v4l2/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/daedalus-v4l2/changelog.Debian"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: daedalus-v4l2
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: ffmpeg (>= 7.1), libdrm2
Recommends: daedalus-v4l2-dkms
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Description: Userspace daemon for the daedalus_v4l2 stateless decoder shim
daedalus-v4l2 ships the userspace daemon that backs the daedalus_v4l2
out-of-tree V4L2 kernel module on Raspberry Pi 5 / CM5. Together they
expose /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder for
VP9, AV1, and H.264 — actual decoding happens in this single-threaded
daemon via dlopen'd FFmpeg, with decoded NV12 / P010 frames shipped
back through dmabuf.
.
Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0+r376) so
that 'ffmpeg -hwaccel vaapi' against vp9_small.ivf produces a
byte-exact NV12 frame.
.
The kernel module ships separately in daedalus-v4l2-dkms; install
both to actually serve V4L2 clients.
EOF
DEB_OUT="daedalus-v4l2_${PKGVER}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+13
View File
@@ -0,0 +1,13 @@
daedalus-v4l2 (0.1.0+r16+gf55b2cd-1) bookworm trixie; urgency=medium
* Initial Debian packaging for the daedalus-v4l2 userspace daemon.
* Pinned to f55b2cd (Phase 8.13 close): first commit where the full
ffmpeg -hwaccel vaapi → libva-v4l2-request-fourier → /dev/video0
→ daemon path lands a pixel-correct decoded NV12 frame back in
ffmpeg.
* Codecs: VP9, AV1, H.264 (all via dlopen'd FFmpeg 7.1.3).
* Capture formats: NV12M (2 plane), NV12 (1 plane, for libva),
P010 (10-bit single plane).
* Companion package: daedalus-v4l2-dkms (kernel module).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+34
View File
@@ -0,0 +1,34 @@
Source: daedalus-v4l2
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
cmake,
ninja-build,
pkg-config,
libavformat-dev (>= 7.1),
libavcodec-dev (>= 7.1),
libavutil-dev (>= 7.1)
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Package: daedalus-v4l2
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends},
ffmpeg (>= 7.1),
libdrm2
Recommends: daedalus-v4l2-dkms
Description: Userspace daemon for the daedalus_v4l2 stateless decoder shim
daedalus-v4l2 ships the userspace daemon that backs the daedalus_v4l2
out-of-tree V4L2 kernel module on Raspberry Pi 5 / CM5. Together they
expose /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder for
VP9, AV1, and H.264 — actual decoding happens in this single-threaded
daemon via dlopen'd FFmpeg, with decoded NV12 / P010 frames shipped
back through dmabuf.
.
Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0+r376) so
that 'ffmpeg -hwaccel vaapi' against vp9_small.ivf produces a
byte-exact NV12 frame.
.
The kernel module ships separately in daedalus-v4l2-dkms; install
both to actually serve V4L2 clients.
+40
View File
@@ -0,0 +1,40 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: daedalus-v4l2
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/reauktion/daedalus-v4l2
Files: *
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: BSD-2-Clause
Files: include/daedalus_v4l2_proto.h
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-2.0-or-later WITH Linux-syscall-note
Comment:
Shared kernel↔daemon wire-protocol header. GPL-2.0-or-later (matches
the kernel module that includes it) with the standard
Linux-syscall-note exception so userspace inclusion is BSD-clean.
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED.
License: GPL-2.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
@@ -0,0 +1,166 @@
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -19,12 +19,13 @@
#include "config.h"
#include <fcntl.h>
#include <linux/dma-buf.h>
#include <linux/media.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <drm_fourcc.h>
#include <libudev.h>
@@ -690,12 +691,125 @@
}
udev_enumerate_unref(enumerate);
return ret;
}
+/*
+ * Brute-force fallback used when libudev's scan fails (e.g. inside firefox's
+ * RDD sandbox where Mozilla's broker rejects fd-relative openat used by
+ * systemd's chase() symlink resolver). Iterates /dev/video[0..63], picks the
+ * one whose major/minor matches the requested devnum.
+ */
+static char *v4l2request_devnum_to_video_path_brute(dev_t devnum)
+{
+ char path[32];
+ struct stat st;
+ for (int i = 0; i < 64; i++) {
+ snprintf(path, sizeof(path), "/dev/video%d", i);
+ if (stat(path, &st) < 0)
+ continue;
+ if (st.st_rdev == devnum)
+ return av_strdup(path);
+ }
+ return NULL;
+}
+
+/* Brute-force version of v4l2request_probe_video_devices: replaces the
+ * udev_device_new_from_devnum + udev_device_get_devnode flow with
+ * stat()-based major/minor matching against /dev/video[0..63]. */
+static int v4l2request_probe_video_devices_brute(AVHWFramesContext *hwfc,
+ uint32_t pixelformat,
+ uint32_t buffersize)
+{
+ AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
+ AVV4L2RequestFramesContextInternal *fctxi = fctx->internal;
+ struct media_device_info device_info;
+ struct media_v2_topology topology = {0};
+ struct media_v2_interface *interfaces;
+ char *path;
+ dev_t devnum;
+ int ret;
+
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info) < 0)
+ return AVERROR(errno);
+
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0)
+ return AVERROR(errno);
+
+ if (!topology.num_interfaces)
+ return AVERROR(ENOENT);
+
+ interfaces = av_calloc(topology.num_interfaces,
+ sizeof(struct media_v2_interface));
+ if (!interfaces)
+ return AVERROR(ENOMEM);
+
+ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces;
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0) {
+ ret = AVERROR(errno);
+ goto fail;
+ }
+
+ ret = AVERROR(ENOENT);
+ for (unsigned i = 0; i < topology.num_interfaces; i++) {
+ if (interfaces[i].intf_type != MEDIA_INTF_T_V4L_VIDEO)
+ continue;
+
+ devnum = makedev(interfaces[i].devnode.major,
+ interfaces[i].devnode.minor);
+ path = v4l2request_devnum_to_video_path_brute(devnum);
+ if (!path)
+ continue;
+
+ ret = v4l2request_probe_video_device(hwfc, path, pixelformat, buffersize);
+ if (!ret) {
+ av_log(hwfc, AV_LOG_INFO,
+ "Using V4L2 media driver %s (brute-force) for %s\n",
+ device_info.driver, av_fourcc2str(pixelformat));
+ av_free(path);
+ break;
+ }
+ av_free(path);
+ }
+
+fail:
+ av_free(interfaces);
+ return ret;
+}
+
+/* Brute-force fallback for v4l2request_probe_media_devices(). Iterates
+ * /dev/media[0..15], opens each, probes via topology+stat. */
+static int v4l2request_probe_media_devices_brute(AVHWFramesContext *hwfc,
+ uint32_t pixelformat,
+ uint32_t buffersize)
+{
+ AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
+ AVV4L2RequestFramesContextInternal *fctxi = fctx->internal;
+ char path[32];
+ int ret = AVERROR(ENOENT);
+
+ for (int i = 0; i < 16; i++) {
+ snprintf(path, sizeof(path), "/dev/media%d", i);
+
+ fctxi->media_fd = open(path, O_RDWR);
+ if (fctxi->media_fd < 0)
+ continue;
+
+ ret = v4l2request_probe_video_devices_brute(hwfc, pixelformat,
+ buffersize);
+ if (!ret)
+ return 0;
+
+ close(fctxi->media_fd);
+ fctxi->media_fd = -1;
+ }
+
+ return ret;
+}
+
static int v4l2request_open_decoder(AVHWFramesContext *hwfc)
{
AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
uint32_t buffersize;
struct udev *udev;
int ret;
@@ -712,12 +826,23 @@
buffersize = FFMAX(hwfc->width * hwfc->height * 3 / 2, 256 * 1024);
// Probe all media devices (auto-detection)
ret = v4l2request_probe_media_devices(hwfc, udev, fctx->pixelformat, buffersize);
+ // Brute-force fallback when libudev fails. Firefox-fourier hits this
+ // because Mozilla's RDD sandbox blocks fd-relative openat used by
+ // systemd's chase() symlink resolver inside udev_enumerate_scan_devices.
+ if (ret < 0) {
+ av_log(hwfc, AV_LOG_INFO,
+ "libudev probe failed (%d), falling back to brute-force /dev/media*\n",
+ ret);
+ ret = v4l2request_probe_media_devices_brute(hwfc, fctx->pixelformat,
+ buffersize);
+ }
+
udev_unref(udev);
return ret;
}
static AVBufferRef *v4l2request_v4l2_buffer_alloc(AVHWFramesContext *hwfc,
struct v4l2_format *format)
@@ -0,0 +1,178 @@
From 0cd6e669735e453ec8772f111065bbb2f70a5bc6 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Mon, 18 May 2026 07:27:10 +0000
Subject: [PATCH] avutil/hwcontext_v4l2request: unpack NV15 to P010 in
transfer_data_from
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2_PIX_FMT_NV15 (RK3399/RK3588 rkvdec 10-bit 4:2:0 capture) is mapped to
sw_format = AV_PIX_FMT_YUV420P10 in v4l2request_capture_pixelformats[]. The
existing transfer_get_formats explicitly blanked the format list for that
sw_format, so 'ffmpeg -hwaccel v4l2request -vf hwdownload,format=p010le' on
a Hi10P / Main10 input failed at filter init with EINVAL before reaching
the actual decode (which itself succeeds — 2 frames decoded cleanly).
Expose AV_PIX_FMT_P010 as the transfer target for NV15-backed surfaces and
unpack the packed 10-bit samples into the standard high-bits-of-16 layout
inside transfer_data_from. Luma and chroma share the same packing format
(5 bytes per 4 samples, little endian); chroma plane is W × H/2 samples
for 4:2:0.
The other 'needs custom unpack' sw_formats (YUV420P / Allwinner NV12_32L32
tiled and YUV422P10 / rkvdec NV20) keep the original ENOSYS path because
they need different unpack code that isn't covered by this patch.
Closes marfrit/marfrit-packages#21.
---
libavutil/hwcontext_v4l2request.c | 111 +++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/libavutil/hwcontext_v4l2request.c b/libavutil/hwcontext_v4l2request.c
index b6633d9081..3842160dfb 100644
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -1073,6 +1073,56 @@ fail:
return ret;
}
+/*
+ * Unpack one NV15-packed 10-bit plane (5 bytes per 4 samples, little endian)
+ * into a P010-style plane (10 bits in the high bits of a 16-bit container).
+ * `dst_stride` is in bytes; `src_stride` is bytes per row of NV15 data.
+ */
+static void v4l2request_nv15_unpack_plane_to_p010(const uint8_t *src,
+ uint16_t *dst,
+ unsigned width,
+ unsigned height,
+ unsigned src_stride,
+ unsigned dst_stride)
+{
+ for (unsigned y = 0; y < height; y++) {
+ const uint8_t *s = src + y * src_stride;
+ uint16_t *d = (uint16_t *)((uint8_t *)dst + y * dst_stride);
+ unsigned x;
+
+ for (x = 0; x + 4 <= width; x += 4) {
+ uint16_t a = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ uint16_t b = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ uint16_t c = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ uint16_t e = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ d[0] = (uint16_t)(a << 6);
+ d[1] = (uint16_t)(b << 6);
+ d[2] = (uint16_t)(c << 6);
+ d[3] = (uint16_t)(e << 6);
+
+ d += 4;
+ s += 5;
+ }
+
+ if (x < width) {
+ unsigned rem = width - x;
+ uint16_t pix[4] = { 0, 0, 0, 0 };
+
+ pix[0] = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ if (rem >= 2)
+ pix[1] = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ if (rem >= 3)
+ pix[2] = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ if (rem >= 4)
+ pix[3] = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ for (unsigned j = 0; j < rem; j++)
+ d[j] = (uint16_t)(pix[j] << 6);
+ }
+ }
+}
+
static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
@@ -1082,6 +1132,22 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
if (dir == AV_HWFRAME_TRANSFER_DIRECTION_TO)
return AVERROR(ENOSYS);
+ /*
+ * NV15-backed surfaces (sw_format = YUV420P10) are exposed as P010 to
+ * downstream filters: the unpack below converts the packed 10-bit
+ * samples into the standard high-bits-of-16 layout. Hi10P / Main10
+ * VAAPI/v4l2-request decode reaches userspace through this path.
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ fmts = av_malloc_array(2, sizeof(*fmts));
+ if (!fmts)
+ return AVERROR(ENOMEM);
+ fmts[0] = AV_PIX_FMT_P010;
+ fmts[1] = AV_PIX_FMT_NONE;
+ *formats = fmts;
+ return 0;
+ }
+
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
@@ -1089,8 +1155,13 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
fmts[0] = hwfc->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
+ /*
+ * Tiled-NV12-32L32 (Allwinner) and NV20 (rkvdec 4:2:2 10-bit) still need
+ * dedicated unpacks before hwdownload can consume them; leave them as
+ * "no transfer formats" so the filter graph reports the limitation
+ * rather than silently producing garbage.
+ */
if (hwfc->sw_format == AV_PIX_FMT_YUV420P ||
- hwfc->sw_format == AV_PIX_FMT_YUV420P10 ||
hwfc->sw_format == AV_PIX_FMT_YUV422P10)
fmts[0] = AV_PIX_FMT_NONE;
@@ -1110,6 +1181,44 @@ static int v4l2request_transfer_data_from(AVHWFramesContext *hwfc,
map = av_frame_alloc();
if (!map)
return AVERROR(ENOMEM);
+
+ /*
+ * For NV15→P010, map the raw NV15 bytes (sw_format) and unpack into
+ * dst's P010 storage. Otherwise fall through to the original byte-copy
+ * path used for 1:1 sw_format matches (NV12, NV16, AFBC handled by DRM).
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ /*
+ * Only P010 is advertised by transfer_get_formats for this sw_format;
+ * a caller that bypasses get_formats and asks for anything else would
+ * silently corrupt output via av_frame_copy on NV15-packed bytes.
+ * Reject explicitly.
+ */
+ if (dst->format != AV_PIX_FMT_P010) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ map->format = hwfc->sw_format;
+ ret = v4l2request_map_frame(hwfc, map, src);
+ if (ret)
+ goto fail;
+
+ v4l2request_nv15_unpack_plane_to_p010(map->data[0],
+ (uint16_t *)dst->data[0],
+ dst->width, dst->height,
+ map->linesize[0],
+ dst->linesize[0]);
+ /* NV15 chroma plane is W × H/2 samples (4:2:0, UV interleaved). */
+ v4l2request_nv15_unpack_plane_to_p010(map->data[1],
+ (uint16_t *)dst->data[1],
+ dst->width, dst->height / 2,
+ map->linesize[1],
+ dst->linesize[1]);
+ ret = 0;
+ goto fail;
+ }
+
map->format = dst->format;
ret = v4l2request_map_frame(hwfc, map, src);
--
2.47.3
+177
View File
@@ -0,0 +1,177 @@
#!/bin/bash
# Build ffmpeg-v4l2-request-fourier_<ver>_arm64.deb (the Kwiboo FFmpeg
# fork with the V4L2-Request API hwaccel patches).
#
# Mirror of arch/ffmpeg-v4l2-request-fourier into the Debian tree.
# Provides the patched `ffmpeg` + `ffprobe` binaries plus the shared
# libav* libraries with v4l2-request support, so consumers like
# mpv-fourier (and the kdirect bit-exact reference test rig) work
# end-to-end without a stock-Debian FFmpeg fallback.
#
# Conflicts: ffmpeg, libav* — this is a drop-in replacement. Pi 5 /
# CM5 (BCM2712) hosts using daedalus_v4l2 + libva-v4l2-request-fourier
# DON'T strictly need this package (stock Debian ffmpeg + libva path
# is sufficient for the VAAPI route), but the kdirect bit-exact
# reference + firefox-fourier / mpv-fourier consumers do.
#
# Big build: 25-40 min on a runner. Output is a single .deb that
# bundles ffmpeg/ffprobe + libavcodec.so.61 + libavformat.so.61 etc.
# all together — no split per-library subpackages. Easier to consume,
# trades off finer-grained downgrades.
#
# Sibling Arch package: ../../arch/ffmpeg-v4l2-request-fourier/PKGBUILD
# Upstream: https://github.com/Kwiboo/FFmpeg (branch v4l2-request-n8.1)
set -euo pipefail
# Same pin as arch/ — v4l2-request-n8.1 tip 2026-04-24.
UPSTREAM_COMMIT=b57fbbe50c9b2656fad86a1a7eeabfd2b2a50935
FFMPEG_VERSION=8.1
# epoch 2 matches Debian's stock ffmpeg (currently 7:7.1.x in trixie);
# +rfourier suffix to avoid colliding with upstream/Debian rebuilds.
PKGVER=2:${FFMPEG_VERSION}+rfourier+gb57fbbe
PKGREL=1
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
git clone --depth 1 \
--branch v4l2-request-n8.1 \
https://github.com/Kwiboo/FFmpeg.git FFmpeg
cd FFmpeg
# git fetch the specific commit (depth=1 of branch tip might not be it)
if [ "$(git rev-parse HEAD)" != "$UPSTREAM_COMMIT" ]; then
git fetch origin "$UPSTREAM_COMMIT"
git checkout "$UPSTREAM_COMMIT"
fi
# Apply patches (same as Arch).
patch -Np1 -i "$HERE/0001-libudev-bypass-fallback.patch"
patch -Np1 -i "$HERE/0002-nv15-to-p010-unpack.patch"
# Configure with Arch-parity flags. Drops the same set of features
# (X11, AMF, CUDA, FireWire, AviSynth, Bluray, OpenMPT, JPEG-XL,
# Theora, XVid, rsvg, soxr, ssh, vidstab, modplug, SDL2, Vulkan,
# JACK, GSM, Speex) — not needed on the Fourier fleet, keeps the .deb
# smaller and the dependency graph tighter.
./configure \
--prefix=/usr \
--libdir=/usr/lib/aarch64-linux-gnu \
--shlibdir=/usr/lib/aarch64-linux-gnu \
--incdir=/usr/include/aarch64-linux-gnu \
--disable-debug \
--disable-static \
--disable-doc \
--disable-stripping \
--enable-shared \
--enable-gpl \
--enable-version3 \
--enable-pic \
--enable-neon \
--arch=aarch64 \
--enable-libdrm \
--enable-libv4l2 \
--enable-libudev \
--enable-v4l2-request \
--enable-v4l2_m2m \
--enable-vaapi \
--enable-opengl \
--enable-gnutls \
--enable-fontconfig \
--enable-libass \
--enable-libfreetype \
--enable-libfribidi \
--enable-libxml2 \
--enable-libpulse \
--enable-libdav1d \
--enable-libopus \
--enable-libvorbis \
--enable-libmp3lame \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-libwebp \
--host-cflags='-fPIC'
make -j"$(nproc)"
make tools/qt-faststart
# Stage
ROOT="$work/pkgroot"
make DESTDIR="$ROOT" install
install -Dm755 tools/qt-faststart "$ROOT/usr/bin/qt-faststart"
# Doc
mkdir -p "$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier" "$ROOT/DEBIAN"
install -Dm644 "$HERE/debian/copyright" \
"$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" \
"$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/changelog.Debian"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: ffmpeg-v4l2-request-fourier
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: libc6,
libdrm2,
libfontconfig1,
libfreetype6,
libfribidi0,
libxml2,
libpulse0,
libdav1d7 | libdav1d6,
libopus0,
libvorbis0a,
libvorbisenc2,
libmp3lame0,
libvpx9 | libvpx8 | libvpx7,
libx264-164 | libx264-163,
libx265-215 | libx265-209 | libx265-199,
libwebp7 | libwebp6,
libwebpmux3,
libass9,
libgnutls30,
libudev1,
libv4l-0,
libva2,
libva-drm2
Conflicts: ffmpeg, libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Replaces: ffmpeg, libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Provides: ffmpeg (= ${PKGVER}-${PKGREL}),
libavcodec.so.61,
libavformat.so.61,
libavutil.so.59
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://github.com/Kwiboo/FFmpeg
Description: FFmpeg with V4L2 Request API hwaccel (Kwiboo fork)
FFmpeg ${FFMPEG_VERSION} patched with the V4L2 Request API stateless
video decoder hwaccel — Kwiboo's long-running rebase of Jernej
Škrabec's v4l2-request patchset onto FFmpeg release tags.
.
Provides 'ffmpeg -hwaccel v4l2request' / '-hwaccel drm' routes that
drive rkvdec / hantro / cedrus / rpi-hevc-dec / daedalus_v4l2
stateless decoders directly through libavcodec's hwdevice DRM path,
bypassing libva. Used by mpv-fourier and firefox-fourier as their
backing FFmpeg, and as the kdirect bit-exact reference in libva-v4l2-
request-fourier validation.
.
Drops X11/AMF/CUDA/Bluray/JACK/Vulkan/SDL2/Theora/XVid/Speex/JPEG-XL
per Fourier fleet policy (Wayland + ARM + video-decode focus).
No 'ffplay' binary; mpv-fourier covers interactive playback.
EOF
DEB_OUT="ffmpeg-v4l2-request-fourier_${PKGVER//:/%3a}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+14
View File
@@ -0,0 +1,14 @@
ffmpeg-v4l2-request-fourier (2:8.1+rfourier+gb57fbbe-1) bookworm trixie; urgency=medium
* Initial Debian packaging for the Kwiboo FFmpeg fork with V4L2
Request API hwaccel patches.
* Mirror of arch/ffmpeg-v4l2-request-fourier (same pin b57fbbe,
same configure flags, same 2 patches: libudev-bypass-fallback +
nv15-to-p010-unpack).
* Drop-in replacement for Debian's stock ffmpeg + libav*; takes
epoch 2 to win the apt version comparison.
* Required by mpv-fourier and firefox-fourier; not strictly
required for the VAAPI-only path on daedalus-v4l2 hosts (stock
libva + Debian ffmpeg works there).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+61
View File
@@ -0,0 +1,61 @@
Source: ffmpeg-v4l2-request-fourier
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
git,
nasm,
pkg-config,
libass-dev,
libdrm-dev,
libfontconfig1-dev,
libfreetype6-dev,
libfribidi-dev,
libgnutls28-dev,
libmp3lame-dev,
libopus-dev,
libpulse-dev,
libudev-dev,
libv4l-dev,
libva-dev,
libvorbis-dev,
libvpx-dev,
libwebp-dev,
libx264-dev,
libx265-dev,
libxml2-dev,
libdav1d-dev,
linux-libc-dev
Standards-Version: 4.6.2
Homepage: https://github.com/Kwiboo/FFmpeg
Package: ffmpeg-v4l2-request-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends}
Conflicts: ffmpeg,
libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Replaces: ffmpeg,
libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Provides: ffmpeg (= ${binary:Version}),
libavcodec.so.61,
libavformat.so.61,
libavutil.so.59
Description: FFmpeg with V4L2 Request API hwaccel (Kwiboo fork)
FFmpeg 8.1 patched with the V4L2 Request API stateless video decoder
hwaccel — Kwiboo's long-running rebase of Jernej Škrabec's
v4l2-request patchset onto FFmpeg release tags.
.
Provides 'ffmpeg -hwaccel v4l2request' / '-hwaccel drm' routes that
drive rkvdec / hantro / cedrus / rpi-hevc-dec / daedalus_v4l2
stateless decoders directly through libavcodec's hwdevice DRM path,
bypassing libva. Used by mpv-fourier and firefox-fourier as their
backing FFmpeg, and as the kdirect bit-exact reference in
libva-v4l2-request-fourier validation.
.
Drops X11/AMF/CUDA/Bluray/JACK/Vulkan/SDL2/Theora/XVid/Speex/JPEG-XL
per Fourier fleet policy (Wayland + ARM + video-decode focus). No
'ffplay' binary; mpv-fourier covers interactive playback.
+21
View File
@@ -0,0 +1,21 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: FFmpeg (Kwiboo v4l2-request fork)
Upstream-Contact: Niklas Haas <niklas@haasn.dev>, Jernej Škrabec, Kwiboo
Source: https://github.com/Kwiboo/FFmpeg
Files: *
Copyright: 2000-2026 The FFmpeg developers
License: GPL-3.0-or-later
Files: 0001-libudev-bypass-fallback.patch 0002-nv15-to-p010-unpack.patch
Copyright: 2024-2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-3.0-or-later
License: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v3 can be found in `/usr/share/common-licenses/GPL-3'.
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# Build libva-v4l2-request-fourier_<ver>_arm64.deb.
#
# Compiles the libva ICD from the marfrit/libva-v4l2-request-fourier
# tip pinned in PKGVER below. Mirrors arch/libva-v4l2-request-fourier
# (Arch Linux build). Output is a single arm64 .deb that ships the
# VA-API driver as /usr/lib/aarch64-linux-gnu/dri/v4l2_request_drv_video.so.
#
# Sibling Arch package: ../../arch/libva-v4l2-request-fourier/PKGBUILD
# Upstream fork: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
set -euo pipefail
# Same pin as the Arch PKGBUILD. de27e95 = "v4l2: log error_idx +
# failing ctrl id on S_EXT_CTRLS failure" (Phase 8.13 diagnostic).
UPSTREAM_COMMIT=de27e95571b67ef34619c23a12db4698f9b3454e
PKGVER=1.0.0+r376+gde27e95
PKGREL=1
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo libva-fourier.tar.gz \
"https://git.reauktion.de/marfrit/libva-v4l2-request-fourier/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf libva-fourier.tar.gz
SRCDIR=$(echo libva-v4l2-request-fourier)
cd "$SRCDIR"
meson setup build \
--buildtype=release \
--prefix=/usr \
--libdir=lib/aarch64-linux-gnu \
-Db_lto=false
meson compile -C build
ROOT="$work/pkgroot"
DESTDIR="$ROOT" meson install -C build
# Strip any non-package debug, then drop dependencies + control.
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/libva-v4l2-request-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/libva-v4l2-request-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/libva-v4l2-request-fourier/changelog.Debian"
mkdir -p "$ROOT/DEBIAN"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: libva-v4l2-request-fourier
Version: ${PKGVER}-${PKGREL}
Section: libs
Priority: optional
Architecture: arm64
Depends: libva2, libdrm2
Conflicts: libva-v4l2-request
Replaces: libva-v4l2-request
Provides: libva-driver, libva-v4l2-request (= ${PKGVER}-${PKGREL})
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Description: VA-API backend for V4L2 stateless decoders (fourier fork)
LibVA implementation for the Linux Video4Linux2 Request API, multiplanar
fork of bootlin/libva-v4l2-request. Drives rkvdec / hantro / cedrus /
rpi-hevc-dec / daedalus_v4l2 stateless decoders for H.264, HEVC, VP8,
VP9, AV1, and MPEG-2.
.
Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv --hwdec=vaapi,
Firefox VAAPI accel) when LIBVA_DRIVER_NAME=v4l2_request is set.
EOF
DEB_OUT="libva-v4l2-request-fourier_${PKGVER}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+15
View File
@@ -0,0 +1,15 @@
libva-v4l2-request-fourier (1.0.0+r376+gde27e95-1) bookworm trixie; urgency=medium
* Initial Debian packaging (sibling to existing
arch/libva-v4l2-request-fourier).
* Pinned to fork tip de27e95: "v4l2: log error_idx + failing ctrl id
on S_EXT_CTRLS failure" — Phase 8.13 diagnostic that surfaced the
real root cause of the libva→daedalus_v4l2 request-completion
timeout.
* Includes daedalus_v4l2 probe slot (b5b3acf) and meson option gate
(2146341) for the Pi 5 daemon-backed decoder shim.
* Backward-compatible on rkvdec / hantro / cedrus / rpi-hevc-dec
hosts — daedalus probe is off by default unless the kernel module
is present.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+27
View File
@@ -0,0 +1,27 @@
Source: libva-v4l2-request-fourier
Section: libs
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
libva-dev,
libdrm-dev,
meson (>= 0.43),
ninja-build,
pkg-config
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Package: libva-v4l2-request-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends}, libva2, libdrm2
Conflicts: libva-v4l2-request
Replaces: libva-v4l2-request
Provides: libva-driver, libva-v4l2-request (= ${binary:Version})
Description: VA-API backend for V4L2 stateless decoders (fourier fork)
LibVA implementation for the Linux Video4Linux2 Request API, multiplanar
fork of bootlin/libva-v4l2-request. Drives rkvdec / hantro / cedrus /
rpi-hevc-dec / daedalus_v4l2 stateless decoders for H.264, HEVC, VP8,
VP9, AV1, and MPEG-2.
.
Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv --hwdec=vaapi,
Firefox VAAPI accel) when LIBVA_DRIVER_NAME=v4l2_request is set.
+38
View File
@@ -0,0 +1,38 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: libva-v4l2-request-fourier
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Comment:
Fork of bootlin/libva-v4l2-request with multi-codec / multi-device
enhancements for the fourier campaign (RK3399 / RK3588 / RK3566 / BCM2712).
Per-file SPDX headers are the canonical declaration; this summary
covers the aggregate.
Files: *
Copyright: 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
2018-2026 The libva-v4l2-request authors
2024-2026 Markus Fritsche <fritsche.markus@gmail.com>
License: LGPL-2.1+ or MIT
License: LGPL-2.1+
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
.
On Debian systems, the complete text of the GNU Lesser General
Public License v2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
+4 -3
View File
@@ -7,9 +7,10 @@
# package (Architecture: all, depends on lua + lua-socket).
set -euo pipefail
PKGVER=0.5.4
PKGVER=1.2.1
UPSTREAM_TAG=v1.2.1
PKGREL=1
LMCP_TARBALL_SHA256=af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf
LMCP_TARBALL_SHA256=bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build: pin all file mtimes + ar member timestamps to a fixed
@@ -22,7 +23,7 @@ work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/v${PKGVER}.tar.gz"
curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/${UPSTREAM_TAG}.tar.gz"
echo "$LMCP_TARBALL_SHA256 lmcp.tar.gz" | sha256sum -c
tar xzf lmcp.tar.gz
+80
View File
@@ -1,3 +1,83 @@
lmcp (1.2.1-1) bookworm trixie; urgency=medium
* tools.d/ plugin scan (closes lmcp#22): server.lua now scans
LMCP_TOOLS_DIR (default /opt/lmcp/tools.d on POSIX) for *.lua
files and invokes each as a function receiving (server, run).
Lets hosts ship local tool extensions alongside the packaged
generics without forking server.lua. Existing single-file
deployments without a tools.d/ directory: no behaviour change.
* LMCP_HOST + LMCP_CONF env vars: packaged server.lua now threads
these into lmcp.new(opts.host, opts.conf). Hosts that need
single-interface binding (e.g. hertz on 192.168.88.18) or a
conf-file-based bearer token (e.g. /opt/herding/etc/hertz-tools.conf)
can drive the packaged entrypoint directly via systemd env
instead of carrying a forked server.lua.
* Together with the above, hertz, ampere, and any future host with
custom tools can migrate from /opt/lmcp/server.lua forks to a
plain plugin file + standard systemd env. apt upgrade then
delivers all packaged improvements automatically.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 01:30:00 +0000
lmcp (1.1.1-1) bookworm trixie; urgency=medium
* Bug fix: omit empty inputSchema.properties at tool registration.
The json.lua empty-table-as-array gotcha (same one that bit
`ping` in v1.0.0-rc1) was re-surfacing on tool inputSchemas
declared with `properties = {}` — spec-strict MCP clients (Zod)
rejected the tools/list with "expected: record, received: array".
lmcp:tool() now normalises empty properties tables by dropping
the key entirely (JSON Schema permits omitting `properties` on
`type:object`, meaning "any object — no constraints").
Discovered live on a hertz-tools deployment where two custom
no-arg tools (lxc_list, network_status) tripped the Zod check
and caused Claude Code to mark the entire MCP endpoint as
disconnected.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 00:55:00 +0000
lmcp (1.1.0-1) bookworm trixie; urgency=medium
* Concurrent handler dispatch (closes #20): tool handlers run in
cooperative coroutines. server.lua:run()'s sleep_ms yields to
the event loop instead of blocking. Slow shell commands no
longer serialise other requests — fast ping during a slow
`sleep N` returns in ~10ms (was ~N seconds).
* Progress + cancellation notifications (closes #11): tool
handler ctx gains progress(p, total?, message?) and cancelled().
Client→server notifications/cancelled flips a flag the running
handler sees within ~420ms (poll interval capped when ctx
present). Cancelled requests get a JSON-RPC -32800 error
response (spec wording is "SHOULD NOT respond" but the practical
UX wins; see upstream issue for the FD-inheritance trade-off).
* Windows MSI build sync (closes #18): windows/sync.sh script
refreshes windows/pkg/{lmcp,server,json}.lua from root before
WiX is invoked. Closes the drift trap that left the MSI ~6
months behind master in April 2026.
* Zero handler source-code changes; all existing tools (shell,
fetch, web_search, hub remote_*) benefit from concurrency and
auto-cancellation transparently via the run() helper.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 19:45:00 +0000
lmcp (1.0.0~rc1-1) bookworm trixie; urgency=medium
* Full MCP 2025-06-18 surface (release candidate). Closes 14
upstream issues. New primitives: Resources, Prompts, Completion,
Logging, Sampling, Roots, fetch, web_search. Protocol: cursor
pagination, structuredContent, _meta passthrough, tool annotations
(readOnlyHint/destructiveHint/idempotentHint/openWorldHint).
Transports: stdio (LMCP_TRANSPORT=stdio) for Claude Desktop / IDE
clients; full Streamable HTTP rewrite with select()-based event
loop, sessions (Mcp-Session-Id), persistent SSE, server-initiated
requests, heartbeat, DELETE.
* json.lua: UTF-16 surrogate-pair combination + json.empty_object
sentinel for spec-correct {} emission (fixes ping's result:[]
bug).
* Backwards compatible with all existing sessionless-POST clients.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 17:25:00 +0000
lmcp (0.5.4-1) bookworm trixie; urgency=medium
* Ship examples/lmcp.service systemd unit template alongside the
@@ -0,0 +1,56 @@
From 9d3bbd3651eb8405b8609e4f5e8c4978056483d0 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 18 Aug 2024 17:42:14 -0700
Subject: [PATCH 1/2] meson: add detection logic for v4l2request support
We will probably adjust this to look for a specific libavutil version after
v4l2request support is merged upstream, but this check is fine for now.
---
meson.build | 11 +++++++++++
meson.options | 1 +
2 files changed, 12 insertions(+)
diff --git a/meson.build b/meson.build
index d4c75a907f..540f279dc7 100644
--- a/meson.build
+++ b/meson.build
@@ -1444,6 +1444,16 @@ if features['ios-gl']
sources += files('video/out/hwdec/hwdec_ios_gl.m')
endif
+v4l2request = get_option('v4l2request').require(
+ cc.has_header_symbol('libavutil/hwcontext.h',
+ 'AV_HWDEVICE_TYPE_V4L2REQUEST',
+ dependencies: libavutil)
+)
+features += {'v4l2request': v4l2request.allowed()}
+if features['v4l2request']
+ sources += files('video/v4l2request.c')
+endif
+
libva = dependency('libva', version: '>= 1.1.0', required: get_option('vaapi'))
vaapi_drm = dependency('libva-drm', version: '>= 1.1.0', required:
@@ -1911,6 +1921,7 @@ summary({'cocoa': features['cocoa'] and features['swift'],
'libmpv': get_option('libmpv'),
'lua': features['lua'],
'opengl': features['gl'],
+ 'v4l2request': features['v4l2request'],
'vulkan': features['vulkan'],
'wayland': features['wayland'],
'x11': features['x11']},
diff --git a/meson.options b/meson.options
index 836d16d03f..54ec2dccfc 100644
--- a/meson.options
+++ b/meson.options
@@ -103,6 +103,7 @@ option('d3d-hwaccel', type: 'feature', value: 'auto', description: 'D3D11VA hwac
option('d3d9-hwaccel', type: 'feature', value: 'auto', description: 'DXVA2 hwaccel')
option('gl-dxinterop-d3d9', type: 'feature', value: 'auto', description: 'OpenGL/DirectX DXVA2 hwaccel')
option('ios-gl', type: 'feature', value: 'auto', description: 'iOS OpenGL ES interop support')
+option('v4l2request', type: 'feature', value: 'auto', description: 'V4L2 Request API hwaccel')
option('videotoolbox-gl', type: 'feature', value: 'auto', description: 'Videotoolbox with OpenGL')
option('videotoolbox-pl', type: 'feature', value: 'auto', description: 'Videotoolbox with libplacebo')
--
2.52.0
@@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Fri, 8 May 2026 23:30:00 +0000
Subject: [PATCH] vo_dmabuf_wayland: explicit DMA_BUF_IOCTL_SYNC on import fds
V4L2 does not attach implicit fences (dma_resv) to CAPTURE buffers
on VIDIOC_DQBUF. When the buffer is forwarded to a Wayland compositor
that imports it via wl_dmabuf and samples in the GPU, the GPU may
read from physical memory before the producer's writes have flushed,
producing all-zero output (manifests as solid green for BT.601
limited-range YUV(0,0,0) -> RGB(0, 135, 0) on the consumer side).
Issue an explicit DMA_BUF_IOCTL_SYNC(SYNC_START|SYNC_RW) +
SYNC_END(SYNC_RW) round-trip on each unique dma_buf fd before
zwp_linux_buffer_params_v1_add(). This invokes the producer driver's
dma_buf_ops->begin_cpu_access / end_cpu_access, which on most ARM
SoCs flushes write buffers and synchronizes coherent memory before
the compositor's GPU import.
This is a userspace workaround. Root cause is the missing implicit
fence on V4L2 CAPTURE DQBUF and is being addressed upstream via
the vb2_dma_resv RFC.
Without this patch, on RK3566 (hantro VPU + Mali-G52 panfrost +
KDE Plasma 6 / KWin 6.6.4), `mpv --hwdec=vaapi --vo=dmabuf-wayland`
shows solid green frames for all hardware-decoded content. With
this patch, decoded frames are presented correctly.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c
index 6b7c511..16e3d18 100644
--- a/video/out/vo_dmabuf_wayland.c
+++ b/video/out/vo_dmabuf_wayland.c
@@ -27,6 +27,12 @@
#include <va/va_drmcommon.h>
#endif
+/* fourier patch: explicit dma_buf cache sync workaround for missing
+ * implicit-fence on V4L2 stateless CAPTURE buffers. Applies to both
+ * VAAPI and DRMPrime import paths. */
+#include <linux/dma-buf.h>
+#include <sys/ioctl.h>
+
#include "gpu/hwdec.h"
#include "gpu/video.h"
#include "mpv_talloc.h"
@@ -205,6 +211,14 @@ static void vaapi_dmabuf_importer(struct buffer *buf, struct mp_image *src,
buf->drm_format = 0;
goto done;
}
+ /* fourier patch: explicit cache coherency sync on each dma_buf fd
+ * before submitting to the compositor. See top-of-file comment. */
+ for (int obj_no = 0; obj_no < desc.num_objects; obj_no++) {
+ struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW };
+ (void)ioctl(desc.objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ (void)ioctl(desc.objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ }
for (int plane_no = 0; plane_no < desc.layers[layer_no].num_planes; ++plane_no) {
int object = desc.layers[layer_no].object_index[plane_no];
uint64_t modifier = desc.objects[object].drm_format_modifier;
@@ -258,6 +272,16 @@ static void drmprime_dmabuf_importer(struct buffer *buf, struct mp_image *src,
return;
buf->id = drmprime_surface_id(src);
+
+ /* fourier patch: explicit cache coherency sync on each dma_buf fd
+ * before submitting to the compositor. See top-of-file comment. */
+ for (int obj_no = 0; obj_no < desc->nb_objects; obj_no++) {
+ struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW };
+ (void)ioctl(desc->objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ (void)ioctl(desc->objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ }
+
for (layer_no = 0; layer_no < desc->nb_layers; layer_no++) {
AVDRMLayerDescriptor layer = desc->layers[layer_no];
--
2.51.0
@@ -0,0 +1,435 @@
From dd1e1fd6fe884d66c49dc26af715e1423c7471a3 Mon Sep 17 00:00:00 2001
From: Philip Langdale <philipl@overt.org>
Date: Sun, 18 Aug 2024 17:43:41 -0700
Subject: [PATCH 2/2] vo: hwdec: drmprime: add separate hwdecs for v4l2request
With all the machinery in place, we can now add the v4l2request hwdecs with a
different hw device type, and a different initialisation path. This applies to
both the drmprime and drmprime_overlay hwdecs.
At the moment, the device initialisation is done in the bare minimum way, but
it can be extended to take a device path (for example) if that makes sense as
we better understand what meaningful configuration will be.
Co-authored-by: Jonas Karlman <jonas@kwiboo.se>
---
video/hwdec.c | 3 +
video/hwdec.h | 1 +
video/out/gpu/hwdec.c | 6 ++
video/out/hwdec/hwdec_drmprime.c | 125 +++++++++++++++++------
video/out/hwdec/hwdec_drmprime_overlay.c | 81 +++++++++++++--
video/out/vo_dmabuf_wayland.c | 1 +
video/v4l2request.c | 34 ++++++
7 files changed, 210 insertions(+), 41 deletions(-)
create mode 100644 video/v4l2request.c
diff --git a/video/hwdec.c b/video/hwdec.c
index deba518e82..de2ffecc40 100644
--- a/video/hwdec.c
+++ b/video/hwdec.c
@@ -125,6 +125,9 @@ static const struct hwcontext_fns *const hwcontext_fns[] = {
#if HAVE_DRM
&hwcontext_fns_drmprime,
#endif
+#if HAVE_V4L2REQUEST
+ &hwcontext_fns_v4l2request,
+#endif
#if HAVE_VAAPI
&hwcontext_fns_vaapi,
#endif
diff --git a/video/hwdec.h b/video/hwdec.h
index e7734e5d7e..bf337389cb 100644
--- a/video/hwdec.h
+++ b/video/hwdec.h
@@ -119,6 +119,7 @@ extern const struct hwcontext_fns hwcontext_fns_cuda;
extern const struct hwcontext_fns hwcontext_fns_d3d11;
extern const struct hwcontext_fns hwcontext_fns_drmprime;
extern const struct hwcontext_fns hwcontext_fns_dxva2;
+extern const struct hwcontext_fns hwcontext_fns_v4l2request;
extern const struct hwcontext_fns hwcontext_fns_vaapi;
extern const struct hwcontext_fns hwcontext_fns_vdpau;
diff --git a/video/out/gpu/hwdec.c b/video/out/gpu/hwdec.c
index be39c507d0..f50b927851 100644
--- a/video/out/gpu/hwdec.c
+++ b/video/out/gpu/hwdec.c
@@ -38,6 +38,8 @@ extern const struct ra_hwdec_driver ra_hwdec_drmprime;
extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;
extern const struct ra_hwdec_driver ra_hwdec_aimagereader;
extern const struct ra_hwdec_driver ra_hwdec_vulkan;
+extern const struct ra_hwdec_driver ra_hwdec_v4l2request;
+extern const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay;
const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
#if HAVE_D3D_HWACCEL
@@ -73,6 +75,10 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
&ra_hwdec_drmprime,
&ra_hwdec_drmprime_overlay,
#endif
+#if HAVE_V4L2REQUEST
+ &ra_hwdec_v4l2request,
+ &ra_hwdec_v4l2request_overlay,
+#endif
#if HAVE_ANDROID_MEDIA_NDK
&ra_hwdec_aimagereader,
#endif
diff --git a/video/out/hwdec/hwdec_drmprime.c b/video/out/hwdec/hwdec_drmprime.c
index 7869eb124a..446f63de44 100644
--- a/video/out/hwdec/hwdec_drmprime.c
+++ b/video/out/hwdec/hwdec_drmprime.c
@@ -77,7 +77,7 @@ static const char *forked_pix_fmt_names[] = {
"rpi4_10",
};
-static int init(struct ra_hwdec *hw)
+static int pre_init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
@@ -92,36 +92,12 @@ static int init(struct ra_hwdec *hw)
return -1;
}
- /*
- * The drm_params resource is not provided when using X11 or Wayland, but
- * there are extensions that supposedly provide this information from the
- * drivers. Not properly documented. Of course.
- */
- mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
- "drm_params_v2");
-
- /*
- * Respect drm_device option, so there is a way to control this when not
- * using a DRM gpu context. If drm_params_v2 are present, they will already
- * respect this option.
- */
- void *tmp = talloc_new(NULL);
- struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
- const char *opt_path = drm_opts->device_path;
-
- const char *device_path = params && params->render_fd > -1 ?
- drmGetRenderDeviceNameFromFd(params->render_fd) :
- opt_path ? opt_path : "/dev/dri/renderD128";
- MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
+ return 0;
+}
- int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
- AV_HWDEVICE_TYPE_DRM,
- device_path, NULL, 0);
- talloc_free(tmp);
- if (ret != 0) {
- MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
- return -1;
- }
+static int post_init(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
/*
* At the moment, there is no way to discover compatible formats
@@ -154,6 +130,75 @@ static int init(struct ra_hwdec *hw)
return 0;
}
+static int init_drmprime(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The drm_params resource is not provided when using X11 or Wayland, but
+ * there are extensions that supposedly provide this information from the
+ * drivers. Not properly documented. Of course.
+ */
+ mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
+ "drm_params_v2");
+
+ /*
+ * Respect drm_device option, so there is a way to control this when not
+ * using a DRM gpu context. If drm_params_v2 are present, they will already
+ * respect this option.
+ */
+ void *tmp = talloc_new(NULL);
+ struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
+ const char *opt_path = drm_opts->device_path;
+
+ const char *device_path = params && params->render_fd > -1 ?
+ drmGetRenderDeviceNameFromFd(params->render_fd) :
+ opt_path ? opt_path : "/dev/dri/renderD128";
+ MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
+
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_DRM,
+ device_path, NULL, 0);
+ talloc_free(tmp);
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ return ret;
+ }
+
+ return post_init(hw);
+}
+
+#if HAVE_V4L2REQUEST
+static int init_v4l2request(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
+ * correct type must be created here or hwaccel will fail.
+ *
+ * FIXME: Create hwdevice based on type in AVCodecHWConfig
+ */
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_V4L2REQUEST,
+ NULL, NULL, 0);
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ return ret;
+ }
+
+ return post_init(hw);
+}
+#endif
+
static void mapper_unmap(struct ra_hwdec_mapper *mapper)
{
struct priv_owner *p_owner = mapper->owner->priv;
@@ -308,7 +353,7 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = {
.priv_size = sizeof(struct priv_owner),
.imgfmts = {IMGFMT_DRMPRIME, 0},
.device_type = AV_HWDEVICE_TYPE_DRM,
- .init = init,
+ .init = init_drmprime,
.uninit = uninit,
.mapper = &(const struct ra_hwdec_mapper_driver){
.priv_size = sizeof(struct dmabuf_interop_priv),
@@ -318,3 +363,21 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = {
.unmap = mapper_unmap,
},
};
+
+#if HAVE_V4L2REQUEST
+const struct ra_hwdec_driver ra_hwdec_v4l2request = {
+ .name = "v4l2request",
+ .priv_size = sizeof(struct priv_owner),
+ .imgfmts = {IMGFMT_DRMPRIME, 0},
+ .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .init = init_v4l2request,
+ .uninit = uninit,
+ .mapper = &(const struct ra_hwdec_mapper_driver){
+ .priv_size = sizeof(struct dmabuf_interop_priv),
+ .init = mapper_init,
+ .uninit = mapper_uninit,
+ .map = mapper_map,
+ .unmap = mapper_unmap,
+ },
+};
+#endif
diff --git a/video/out/hwdec/hwdec_drmprime_overlay.c b/video/out/hwdec/hwdec_drmprime_overlay.c
index 61514f8e89..689e9b04e5 100644
--- a/video/out/hwdec/hwdec_drmprime_overlay.c
+++ b/video/out/hwdec/hwdec_drmprime_overlay.c
@@ -246,7 +246,7 @@ static void uninit(struct ra_hwdec *hw)
}
}
-static int init(struct ra_hwdec *hw)
+static int pre_init(struct ra_hwdec *hw)
{
struct priv *p = hw->priv;
int draw_plane, drmprime_video_plane;
@@ -267,15 +267,15 @@ static int init(struct ra_hwdec *hw)
drm_params->connector_id, draw_plane, drmprime_video_plane);
if (!p->ctx) {
mp_err(p->log, "Failed to retrieve DRM atomic context.\n");
- goto err;
+ return -1;
}
if (!p->ctx->drmprime_video_plane) {
mp_warn(p->log, "No drmprime video plane. You might need to specify it manually using --drm-drmprime-video-plane\n");
- goto err;
+ return -1;
}
} else {
mp_verbose(p->log, "Failed to retrieve DRM fd from native display.\n");
- goto err;
+ return -1;
}
drmModeCrtcPtr crtc;
@@ -289,7 +289,7 @@ static int init(struct ra_hwdec *hw)
uint64_t has_prime;
if (drmGetCap(p->ctx->fd, DRM_CAP_PRIME, &has_prime) < 0) {
MP_ERR(hw, "Card does not support prime handles.\n");
- goto err;
+ return -1;
}
if (has_prime) {
@@ -298,19 +298,67 @@ static int init(struct ra_hwdec *hw)
disable_video_plane(hw);
+ return 0;
+}
+
+static int init_drmprime(struct ra_hwdec *hw)
+{
+ struct priv *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ goto err;
+
p->hwctx = (struct mp_hwdec_ctx) {
.driver_name = hw->driver->name,
.hw_imgfmt = IMGFMT_DRMPRIME,
};
char *device = drmGetDeviceNameFromFd2(p->ctx->fd);
- int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
- AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
if (device)
free(device);
- if (ret != 0) {
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ goto err;
+ }
+
+ hwdec_devices_add(hw->devs, &p->hwctx);
+
+ return 0;
+
+err:
+ uninit(hw);
+ return ret;
+}
+
+#if HAVE_V4L2REQUEST
+static int init_v4l2request(struct ra_hwdec *hw)
+{
+ struct priv *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ goto err;
+
+ p->hwctx = (struct mp_hwdec_ctx) {
+ .driver_name = hw->driver->name,
+ .hw_imgfmt = IMGFMT_DRMPRIME,
+ };
+
+ /*
+ * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
+ * correct type must be created here or hwaccel will fail.
+ *
+ * FIXME: Create hwdevice based on type in AVCodecHWConfig
+ */
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_V4L2REQUEST,
+ NULL, NULL, 0);
+ if (ret < 0) {
MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
goto err;
}
@@ -321,15 +369,28 @@ static int init(struct ra_hwdec *hw)
err:
uninit(hw);
- return -1;
+ return ret;
}
+#endif
const struct ra_hwdec_driver ra_hwdec_drmprime_overlay = {
.name = "drmprime-overlay",
.priv_size = sizeof(struct priv),
.imgfmts = {IMGFMT_DRMPRIME, 0},
.device_type = AV_HWDEVICE_TYPE_DRM,
- .init = init,
+ .init = init_drmprime,
+ .overlay_frame = overlay_frame,
+ .uninit = uninit,
+};
+
+#if HAVE_V4L2REQUEST
+const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay = {
+ .name = "v4l2request-overlay",
+ .priv_size = sizeof(struct priv),
+ .imgfmts = {IMGFMT_DRMPRIME, 0},
+ .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .init = init_v4l2request,
.overlay_frame = overlay_frame,
.uninit = uninit,
};
+#endif
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c
index 9b06643544..6d62849568 100644
--- a/video/out/vo_dmabuf_wayland.c
+++ b/video/out/vo_dmabuf_wayland.c
@@ -860,6 +860,7 @@ static int preinit(struct vo *vo)
// Initialize all possible hwdec drivers.
ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "vaapi", false);
ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "drmprime", false);
+ ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "v4l2request", false);
p->src = (struct mp_rect){0, 0, 0, 0};
return 0;
diff --git a/video/v4l2request.c b/video/v4l2request.c
new file mode 100644
index 0000000000..2aa4d14fea
--- /dev/null
+++ b/video/v4l2request.c
@@ -0,0 +1,34 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libavutil/hwcontext.h>
+
+#include "hwdec.h"
+
+static struct AVBufferRef *v4l2request_create_standalone(struct mpv_global *global,
+ struct mp_log *log, struct hwcontext_create_dev_params *params)
+{
+ AVBufferRef* ref = NULL;
+ av_hwdevice_ctx_create(&ref, AV_HWDEVICE_TYPE_V4L2REQUEST, NULL, NULL, 0);
+
+ return ref;
+}
+
+const struct hwcontext_fns hwcontext_fns_v4l2request = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .create_dev = v4l2request_create_standalone,
+};
--
2.52.0
+134
View File
@@ -0,0 +1,134 @@
#!/bin/bash
# Build mpv-fourier_<ver>_arm64.deb (mpv with v4l2request hwdec wiring +
# vo_dmabuf_wayland cache-sync fix).
#
# Mirror of arch/mpv-fourier into the Debian tree. Same source pin
# (mpv 0.41.0), same 3 patches, same meson options.
#
# Depends on ffmpeg-v4l2-request-fourier for the libavcodec backing
# library — the v4l2request hwdec mpv now offers requires
# AV_HWDEVICE_TYPE_V4L2REQUEST which only exists in Kwiboo's FFmpeg
# fork, not in Debian stock ffmpeg.
#
# Conflicts: mpv — drop-in replacement. Pi 5 / CM5 hosts using stock
# Firefox + VAAPI don't need this; the firefox-fourier / kdirect
# bench-test paths do.
#
# Sibling Arch package: ../../arch/mpv-fourier/PKGBUILD
# Sibling FFmpeg package: ../ffmpeg-v4l2-request-fourier/build-deb.sh
# Upstream: https://github.com/mpv-player/mpv
set -euo pipefail
MPV_VERSION=0.41.0
PKGVER=1:${MPV_VERSION}+rfourier
PKGREL=1
MPV_TARBALL_SHA256=ee21092a5ee427353392360929dc64645c54479aefdb5babc5cfbb5fad626209
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo mpv.tar.gz \
"https://github.com/mpv-player/mpv/archive/v${MPV_VERSION}/mpv-${MPV_VERSION}.tar.gz"
echo "$MPV_TARBALL_SHA256 mpv.tar.gz" | sha256sum -c
tar xzf mpv.tar.gz
cd "mpv-${MPV_VERSION}"
# Apply the 3 fourier patches.
patch -p1 < "$HERE/0001-meson-add-detection-logic-for-v4l2request-support.patch"
patch -p1 < "$HERE/0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch"
patch -p1 < "$HERE/0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch"
# Configure. Same shape as arch/mpv-fourier's meson options.
meson setup build \
--prefix=/usr \
--libdir=lib/aarch64-linux-gnu \
--buildtype=release \
--auto-features=auto \
-Dv4l2request=enabled \
-Dlibmpv=true \
-Dgl-x11=enabled \
-Dcaca=disabled \
-Dcdda=enabled \
-Ddrm=enabled \
-Ddvbin=enabled \
-Ddvdnav=enabled \
-Dlibarchive=enabled \
-Dopenal=enabled \
-Dsdl2-audio=enabled \
-Dsdl2-video=enabled \
-Dsdl2-gamepad=enabled
meson compile -C build -j"$(nproc)"
# Stage
ROOT="$work/pkgroot"
DESTDIR="$ROOT" meson install -C build
# Drop private linkage entries from the .pc (only matter for static linking).
sed -i -e '/Requires.private/d' -e '/Libs.private/d' \
"$ROOT/usr/lib/aarch64-linux-gnu/pkgconfig/mpv.pc"
# Docs
mkdir -p "$ROOT/usr/share/doc/mpv-fourier" "$ROOT/DEBIAN"
install -m 644 DOCS/encoding.rst "$ROOT/usr/share/doc/mpv-fourier/"
install -m 644 DOCS/tech-overview.txt "$ROOT/usr/share/doc/mpv-fourier/"
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/mpv-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/mpv-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/mpv-fourier/changelog.Debian"
# TOOLS scripts
mkdir -p "$ROOT/usr/share/mpv/scripts"
install -m 644 TOOLS/umpv TOOLS/mpv_identify.sh TOOLS/stats-conv.py TOOLS/idet.sh \
"$ROOT/usr/share/mpv/scripts/" 2>/dev/null || true
[ -d TOOLS/lua ] && cp TOOLS/lua/* "$ROOT/usr/share/mpv/scripts/" 2>/dev/null || true
cat > "$ROOT/DEBIAN/control" <<EOF
Package: mpv-fourier
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier),
libc6, libdrm2,
libass9, libbluray2, libcdio19, libcdio-paranoia2,
libdvdnav4, libdvdread8,
libegl1, libgl1, libjpeg62-turbo | libjpeg62,
libplacebo338 | libplacebo208,
libpulse0, libsixel1, libluajit-5.1-2,
libmujs3 | libmujs2 | libmujs1,
libpipewire-0.3-0, librubberband2, libsdl2-2.0-0,
libopenal1, libuchardet0, libvulkan1,
libwayland-client0, libwayland-egl1, libwayland-cursor0,
libxkbcommon0, libxext6, libxpresent1,
libxrandr2, libxss1, libxv1, libx11-6,
zlib1g
Conflicts: mpv, libmpv2 | libmpv1
Replaces: mpv, libmpv2, libmpv1
Provides: mpv (= ${PKGVER}-${PKGREL}), libmpv.so.2
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://mpv.io/
Description: mpv media player with V4L2-Request hwdec (fourier fork)
mpv ${MPV_VERSION} patched with:
- Kwiboo + Langdale v4l2request hwdec wiring (meson detection +
vo_hwdec_drmprime separate hwdec instance for AV_HWDEVICE_TYPE_
V4L2REQUEST) so '--hwdec=v4l2request' actually engages on
dmabuf-wayland.
- vo_dmabuf_wayland explicit DMA_BUF_IOCTL_SYNC on import fds
(iter1 of dmabuf-modifier-triage) — workaround for missing
implicit-fence on V4L2 stateless CAPTURE buffers. Fixes the
KWin-on-RK3566 dark-green chroma readback regression on ohm.
.
Requires ffmpeg-v4l2-request-fourier as the backing libavcodec.
Stock Debian ffmpeg does not provide AV_HWDEVICE_TYPE_V4L2REQUEST.
EOF
DEB_OUT="mpv-fourier_${PKGVER//:/%3a}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+12
View File
@@ -0,0 +1,12 @@
mpv-fourier (1:0.41.0+rfourier-1) bookworm trixie; urgency=medium
* Initial Debian packaging for mpv with the fourier-umbrella patches.
* Mirror of arch/mpv-fourier (same source tarball pin 0.41.0,
same 3 patches: v4l2request meson detection, drmprime hwdec
wiring, vo_dmabuf_wayland explicit cache-sync).
* Depends on ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier) — the
v4l2request hwdec requires AV_HWDEVICE_TYPE_V4L2REQUEST which
only exists in Kwiboo's FFmpeg fork.
* Drop-in replacement for Debian's stock mpv; takes epoch 1.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+70
View File
@@ -0,0 +1,70 @@
Source: mpv-fourier
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
meson (>= 1.0),
ninja-build,
pkg-config,
python3-docutils,
ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier),
libdrm-dev,
libass-dev,
libbluray-dev,
libcdio-dev,
libcdio-paranoia-dev,
libdvdnav-dev,
libdvdread-dev,
libegl-dev,
libgl-dev,
libjpeg-dev,
libplacebo-dev,
libpulse-dev,
libsixel-dev,
libluajit-5.1-dev,
libmujs-dev,
libpipewire-0.3-dev,
librubberband-dev,
libsdl2-dev,
libopenal-dev,
libuchardet-dev,
libvulkan-dev,
libwayland-dev,
wayland-protocols,
libxkbcommon-dev,
libxext-dev,
libxpresent-dev,
libxrandr-dev,
libxss-dev,
libxv-dev,
libx11-dev,
libv4l-dev,
libudev-dev,
libsystemd-dev,
libarchive-dev,
libxml2-dev,
libdvbpsi-dev,
zlib1g-dev
Standards-Version: 4.6.2
Homepage: https://mpv.io/
Package: mpv-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends},
ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier)
Conflicts: mpv, libmpv2, libmpv1
Replaces: mpv, libmpv2, libmpv1
Provides: mpv (= ${binary:Version}), libmpv.so.2
Description: mpv media player with V4L2-Request hwdec (fourier fork)
mpv 0.41.0 patched with:
- Kwiboo + Langdale v4l2request hwdec wiring (meson detection +
vo_hwdec_drmprime separate hwdec instance for AV_HWDEVICE_TYPE_
V4L2REQUEST) so '--hwdec=v4l2request' actually engages on
dmabuf-wayland.
- vo_dmabuf_wayland explicit DMA_BUF_IOCTL_SYNC on import fds
(iter1 of dmabuf-modifier-triage) — workaround for missing
implicit-fence on V4L2 stateless CAPTURE buffers. Fixes the
KWin-on-RK3566 dark-green chroma readback regression on ohm.
.
Requires ffmpeg-v4l2-request-fourier as the backing libavcodec.
Stock Debian ffmpeg does not provide AV_HWDEVICE_TYPE_V4L2REQUEST.
+25
View File
@@ -0,0 +1,25 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: mpv
Upstream-Contact: https://github.com/mpv-player/mpv/issues
Source: https://github.com/mpv-player/mpv
Files: *
Copyright: 2000-2026 The mpv developers
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Files: 0001-meson-add-detection-logic-for-v4l2request-support.patch
0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch
Copyright: 2024 Kwiboo, Niklas Haas, contributors
License: LGPL-2.1-or-later
Files: 0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: LGPL-2.1-or-later
License: GPL-2.0-or-later
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
License: LGPL-2.1-or-later
On Debian systems, the complete text of the GNU Lesser General
Public License v2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.