Files
marfrit 8756ce38be
build and publish packages / distcc-avahi-aarch64 (push) Successful in 46s
build and publish packages / lmcp-any (push) Successful in 9s
build and publish packages / lmcp-debian (push) Successful in 4s
build and publish packages / claude-his-any (push) Successful in 7s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Successful in 12m8s
build and publish packages / claude-his-debian (push) Successful in 5s
chromium-fourier r2 + firefox-fourier 150.0.1 + KWIN_PIVOT.md
chromium-fourier:
- patch 3/3 nv12-external-oes-on-modifier-external-only.patch — adds
  NativePixmapEGLBinding::ModifierRequiresExternalOES helper, extends
  OzoneImageGLTexturesHolder::GetBinding to honor EGL external_only
  flag for NV12 dmabufs on panfrost / panthor. Validated on ohm
  (RK3566 hantro mainline 6.19.10): bbb_1080p30_h264.mp4 plays at
  34.7 % combined CPU vs ~131 % pre-patch baseline (~3.8x).
- PKGBUILD pkgrel 1->2, source array + sha256sums + prepare() hook for
  patch 4, patch numbering 1/2,2/2 -> 1/3,2/3,3/3.
- NEXT.md appended with 2026-04-28 section: patch 4 design, validation
  log, KWin GL_ALPHA bug pinpoint (preexisting since 2026-03-06,
  affects every wayland video client; unrelated to chromium-fourier),
  device-renumbering note (/dev/video1 = encoder post-reboot).
- KWIN_PIVOT.md: 4-phase plan to identify and patch KWin's
  glTexImage2D(internalFormat=GL_ALPHA) site, ohm-only test plan,
  scope discipline.
- patches/ now tracked (compiler-rt-adjust-paths, enable-v4l2,
  wayland-allow-direct-egl-gles2, nv12-external-oes); the dead-end
  chromeos-pipeline-bypass.patch removed.

firefox-fourier:
- 4 patches (gfxinfo v4l2 stateless fourccs, libwrapper hwdevice ctx,
  ffmpegvideo v4l2-request route, prefs v4l2-request default).
- PKGBUILD bumped to firefox 150.0.1, Arch toolchain glue patches
  layered in, mozconfig with --without-wasm-sandboxed-libraries for
  ALARM, package() launcher fix (rm -f symlink before cat > to avoid
  ENOENT through the dangling /usr/local symlink mach install drops).
- 150.0.1-1-aarch64.pkg.tar.zst built on boltzmann (95 MB), pending
  fresnel power-on for V4L2 stateless validation on RK3399.
2026-04-28 12:02:18 +00:00

10 KiB
Raw Permalink Blame History

firefox-fourier — V4L2 Stateless Decoder Patch Plan

Plan to extend Firefox 149's V4L2 hardware decode path to cover Rockchip mainline kernel boards (RK3399 rkvdec, RK3566/RK3588 hantro, RK3588 rkvdec2) by routing stateless S264/S265/VP9F fourccs through libavcodec's v4l2_request hwaccel, which mainline FFmpeg surfaces via AV_HWDEVICE_TYPE_DRM (no dedicated _V4L2REQUEST enum exists upstream — confirmed against libavutil/hwcontext.h).

1. Files touched (in order)

# Path Change Lines
1 widget/gtk/GfxInfo.cpp V4L2ProbeDevice (~L10301110): add S264/S265/VP9F matches alongside existing H264/HEVC/VP90. Set mIsV4L2Supported = Some(true) and OR the same CODEC_HW_DEC_* bits. Tag a new bool mV4L2IsStateless so downstream can branch. +35 / -2
2 dom/media/platforms/ffmpeg/FFmpegLibWrapper.h Add wrappers for av_hwdevice_ctx_create (currently only _alloc/_init per L173174) and av_hwdevice_find_type_by_name. Needed because stateless wants the device-path-aware _create form to bind /dev/dri/renderD128. +4 / 0
3 dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp dlsym the two new pointers; gate behind LIBAVUTIL_VERSION_MAJOR >= 56. +6 / 0
4 dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h Add AVBufferRef* mDRMDeviceContext = nullptr; and bool mUsingV4L2Request = false; next to existing mUsingV4L2. +3 / 0
5 dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp New CreateV4L2RequestDeviceContext() modelled on CreateVAAPIDeviceContext (current uses av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI)). Wire it in alongside the existing V4L2 init branch (the one feeding ChooseV4L2PixelFormat at L~258). FindVideoHardwareAVCodec call at L708 stays unchanged for stateless — we want the generic h264/hevc/vp9 decoder + a DRM hw_device_ctx, not a _v4l2m2m codec. +90 / -5
6 modules/libpref/init/StaticPrefList.yaml New pref media.ffmpeg.v4l2-request.enabled mirroring media.ffmpeg.vaapi.enabled (default @IS_LINUX@). +6 / 0
7 dom/media/ipc/RDDProcessHost.cpp + sandbox policy file Whitelist /dev/media*, /dev/dri/renderD*, /dev/video* for the RDD process (already partly done for VAAPI — verify policy/linux/SandboxBrokerPolicyFactory.cpp). +6 / 0

Total: roughly +150 / -10 across 7 files.

2. Probe extension — GfxInfo.cpp::V4L2ProbeDevice

Existing pattern (~L1075):

if (outFormats.Contains("H264")) { mIsV4L2Supported = Some(true);
  mV4L2SupportedCodecs |= CODEC_HW_DEC_H264; ... }

Add three siblings, each setting an additional mV4L2IsStateless = true:

if (outFormats.Contains("S264")) { /* CODEC_HW_DEC_H264 | stateless */ }
if (outFormats.Contains("S265")) { /* CODEC_HW_DEC_HEVC | stateless */ }
if (outFormats.Contains("VP9F")) { /* CODEC_HW_DEC_VP9  | stateless */ }

Decision: do not introduce a separate mIsV4L2StatelessSupported. Collapse under mIsV4L2Supported so the existing feature-gate plumbing (MediaCodecsSupport, gfxFeature::HW_DECODE_VIDEO) flips identically — only mV4L2IsStateless distinguishes the routing in step 3. Stateful

  • stateless on the same SoC (rare, but RK3588 has both rkvdec2 + hantro VEPU) gracefully degrades to whichever codec wins enumeration order.

The capture-format gate (YV12/NV12) needs widening: stateless decoders frequently expose only NV12 or NV15 (10-bit, RK3588 HEVC). Add NV15 and NM12 (multiplanar NV12, hantro). Without this the prober rejects an otherwise-good device.

3. Decoder routing — FFmpegVideoDecoder.cpp

Codec selection happens at L651 (AV_HWDEVICE_TYPE_VAAPIh264_vaapi) and L708 (the V4L2 fallback path → h264_v4l2m2m via FindVideoHardwareAVCodec(mLib, mCodecID) resolving by suffix). The stateless route diverges from both: the codec must remain the generic h264/hevc/vp9 decoder (libavcodec auto-binds v4l2_request from its hw_configs when a DRM hw_device_ctx is attached). Pseudo-patch:

if (gfxInfo.mUsingV4L2 && gfxInfo.mV4L2IsStateless) {
  AVCodec* codec = mLib->avcodec_find_decoder(mCodecID);  // generic
  mCodecContext = mLib->avcodec_alloc_context3(codec);
  if (!CreateV4L2RequestDeviceContext()) return false;
  mCodecContext->get_format = ChooseV4L2PixelFormat;        // already returns DRM_PRIME
  mUsingV4L2Request = true;
}

CreateV4L2RequestDeviceContext() body:

const char* drm = "/dev/dri/renderD128";
if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
        AV_HWDEVICE_TYPE_DRM, drm, nullptr, 0) < 0) return false;
mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext);

av_hwdevice_ctx_create — not currently wrapped — is the entry point. The codec's internal hwaccel selector then walks avcodec_get_hw_config() and picks the entry whose device_type == AV_HWDEVICE_TYPE_DRM and pix_fmt == AV_PIX_FMT_DRM_PRIME, which is the v4l2_request hwaccel registered in libavcodec/v4l2_request_*.c. No av_hwdevice_find_type_by_name("v4l2_request") needed — stays an internal libavcodec name.

4. Dmabuf / DRM_PRIME reuse

ChooseV4L2PixelFormat at L~258270 already returns AV_PIX_FMT_DRM_PRIME and is the only format the v4l2_request hwaccel produces. The downstream consumer (DMABufSurfaceYUV import in FFmpegVideoFramePool.cpp) is already DRM_PRIME-aware for the stateful path — same code reads AVDRMFrameDescriptor from frame->data[0]. No new output handling required for NV12/YV12.

10-bit caveat: RK3588 HEVC outputs DRM_FORMAT_NV15 / NV20 (Mali-tile). Existing WaylandDMABufSurface::CreateYUVSurface modifier list does not include DRM_FORMAT_MOD_ARM_AFBC or NV15 fourcc. Either reject 10-bit at probe (capture format gate above) or extend gfx/layers/DMABUFSurfaceImage.cpp — out of scope for v1; gate to NV12 only.

SAND format pollution Turner mentioned in bug 1969297 c#3 is Pi5-specific; rkvdec/hantro do not produce SAND. Safe to ignore for the Rockchip target.

5. Configuration

New pref:

- name: media.ffmpeg.v4l2-request.enabled
  type: RelaxedAtomicBool
  value: @IS_LINUX@
  mirror: always

No new env var. No MOZ_X11_EGL-style kludge. The existing MOZ_LOG=PlatformDecoderModule:5 covers diagnostics. Default-on matches media.ffmpeg.vaapi.enabled shape; users get fallback to software via existing failure paths if av_hwdevice_ctx_create fails (e.g., missing /dev/media0).

6. Test plan (fresnel — RK3399, KDE Wayland)

  1. ls /dev/video* /dev/media* — confirm /dev/video0 (rkvdec output) and /dev/media0 exist.
  2. v4l2-ctl -d /dev/video0 --list-formats-out — expect S264/S265/VP9F.
  3. Start: MOZ_LOG="PlatformDecoderModule:5,FFmpegVideo:5" firefox-fourier 2>&1 | tee fx.log.
  4. Open https://test-videos.co.uk/bigbuckbunny/mp4-h264 1080p clip.
  5. Success markers in fx.log:
    • V4L2ProbeDevice: /dev/video0 supports S264 (stateless)
    • Choosing FFmpeg pixel format for V4L2 video decoding.
    • Requesting pixel format DRM PRIME
    • av_hwdevice_ctx_create(DRM, /dev/dri/renderD128) ok
    • No Using preferred software codec h264.
  6. cat /sys/kernel/debug/clk/clk_summary | grep vdec — clock should be active during playback.
  7. top — CPU < 40% on a single A72 core for 1080p H.264 (stock = 100% on all 6 cores).

7. Build + ship — firefox-fourier PKGBUILD

Mirror chromium-fourier shape exactly (sibling).

pkgname=firefox-fourier
pkgver=149.0
arch=('aarch64' 'x86_64')
makedepends=(rust clang lld nodejs python cbindgen nasm yasm wasi-libc-bin
             gtk3 mesa libva ffmpeg)   # ffmpeg only for headers via system libs
source=(
  "https://archive.mozilla.org/pub/firefox/releases/${pkgver}/source/firefox-${pkgver}.source.tar.xz"
  patches/0001-gfxinfo-v4l2-stateless-fourccs.patch
  patches/0002-libwrapper-hwdevice-ctx-create.patch
  patches/0003-ffmpegvideo-v4l2-request-route.patch
  patches/0004-prefs-v4l2-request.patch
  mozconfig
)

prepare(): cd firefox-${pkgver} → apply patches with patch -Np1. build(): MOZ_NOSPAM=1 ./mach build. package(): ./mach install DESTDIR=${pkgdir}. mozconfig enables --enable-default-toolkit=cairo-gtk3-wayland, --with-system-ffmpeg, ac_add_options --disable-tests. No --enable-media-gpu-process — let it default. Tarball is the official Mozilla source release (not gecko-dev).

Extra makedepends vs. stock firefox PKGBUILD: none — this only modifies existing C++.

8. Risk register (ranked)

  1. libavcodec ABI mismatch. ALARM ships ffmpeg 7.x; Firefox dlopens whatever's at libavcodec.so.61. If the v4l2_request hwaccel was compiled out (Arch's ffmpeg has it; ALARM rebuild may not), av_hwdevice_ctx_create(DRM, ...) succeeds but no codec binds — silent fallback. Mitigation: ffmpeg -hwaccels should list drm.
  2. Renderer-process sandbox blocks /dev/dri/renderD128 open. VAAPI already brokered this for RDD process; verify SandboxBrokerPolicyFactory.cpp covers /dev/media* too — likely doesn't.
  3. glxtest probe runs in stripped env. v4l2test (the FireTestProcess child) needs cap_sys_admin for VIDIOC_S_EXT_CTRLS request API ioctls? No — request API just needs O_RDWR on /dev/media*. Should be fine.
  4. Regression of stateful path. Adding new fourccs is additive; the routing branch is gated on mV4L2IsStateless. Stateful boards (Pi4) untouched.
  5. NV15/10-bit on RK3588 — explicitly out-of-scope v1; gate-rejected.
  6. rkvdec2 driver maturity. Linux 6.12 mainline rkvdec2 H.264 works; HEVC/VP9 still upstream-pending on some boards. Probe will skip what kernel doesn't expose.
  7. DMA-BUF modifier negotiation with panfrost/panthor on Wayland — already shaken out by chromium-fourier on RK3566; same code path.

9. Upstream path (bug 1969297)

Split into 4 reviewable commits matching files 1, 2+3, 5, 6 from the table. Add a gtest exercising V4L2ProbeDevice against a synthetic v4l2test stdout containing S264 (no kernel needed). Reach out to skyevg (D252119 author) for review continuity. r? jya for the FFmpegVideoDecoder change. The av_hwdevice_ctx_create wrapper addition is a self-contained 6-liner that should land independently. The 10-bit/SAND concerns Turner raised remain valid for Pi5 — explicitly scope this series to stateless DRM_PRIME NV12 only, leaving SAND for a follow-up bug.