Stage the next side-project: patch upstream Chromium to do HW video decode through VaapiVideoDecoder + our marfrit/libva-v4l2-request-fourier backend on a mainline Linux Wayland system, instead of going through the chromeos pipeline that fails on Brave today. STUDY.md captures: - The exact failure stack we're fixing (PickDecoderOutputFormat -> ImageProcessor init failure in media/gpu/chromeos/video_decoder_pipeline.cc) - Three candidate patches (chromeos pipeline bypass, V4L2VideoDecoder factory un-gate, libva backend default) - Reference forks (JeffyCN, igel-oss, 7Ji-PKGBUILDs/chromium-mpp, amazingfate/chromium-debian-build) — all use the older V4L2VDA path with vendor MPP, not VAAPI; useful for PKGBUILD shape and factory-un-gating patterns but not directly applicable - Build plan on fermi (depot_tools, ~30 GB fetch, 6-10 h initial build, distcc-avahi acceleration through CT108 + tesla) - Phase order — workspace done now, build env next session, patches after that, package after that, brave-fourier rebase last No PKGBUILD added yet; one will land when there's something to actually package. Build artifacts intentionally not in repo (chromium tree is ~100 GB). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.7 KiB
chromium-fourier — Chromium with V4L2-stateless / VAAPI HW decode on mainline-kernel ARM Linux
Goal
Patch upstream Chromium so it can do hardware video decode through
VaapiVideoDecoder on a plain Linux Wayland system on Rockchip
(RK3566 / RK3588), via our marfrit/libva-v4l2-request-fourier libva
backend. Target consumers: Brave (rebuilt from the same patched
Chromium), upstream Chromium itself for Arch Linux ARM, and any other
Blink-based browser that picks up the patches.
This fills a niche no shipping fork currently fills — every existing
ARM-Linux Chromium with HW decode (7Ji's chromium-mpp, Ubuntu's
liujianfeng1994/rockchip-multimedia PPA, JeffyCN's recipe, etc.) goes
through the vendor MPP path on **5.10 BSP kernel + X11 + Mali blob
- panfork**. We're going for mainline kernel + V4L2 stateless + Wayland + panfrost / panthor, the direction Fourier is heading anyway.
What's actually broken in stock Chromium 147+
-
media/gpu/chromeos/video_decoder_pipeline.ccis selected on Linux when it shouldn't be. It then tries to initialize a V4L2ImageProcessor(a ChromeOS-specific m2m chip block for color conversion / scaling) that doesn't exist on a plain Linux Wayland system. Failure surface:PickDecoderOutputFormat(): Initializing ImageProcessor; max buffers: 16 ERROR: failed Initialize()ing the frame pool -
VaapiVideoDecoderis compiled into stock Chromium / brave-bin (verified:strings /opt/brave-bin/brave | grep VaapiVideoDecoder), but the chromeos pipeline preempts it. Once the pipeline fails, the decoder selection bails — it never falls back to directVaapiVideoDecoder. -
V4L2VideoDecoderfactory isBUILDFLAG(IS_CHROMEOS)-gated. Feature flagsUseChromeOSDirectVideoDecoder/V4L2FlatStatelessVideoDecoderare no-ops on a non-ChromeOS build — their flag strings don't even appear in the binary.
The patch shape (sketch)
Patch 1 — bypass the chromeos pipeline on Linux
media/gpu/chromeos/video_decoder_pipeline.cc is reached from
media/gpu/vaapi/vaapi_video_decoder.cc somewhere in
ApplyResolutionChangeWithScreenSizes. Either:
- Skip the chromeos pipeline entirely on Linux non-ChromeOS, going
straight to
VaapiVideoDecoder::CreateContextAndScopedVASurfacesfor frame allocation, OR - Replace
PickDecoderOutputFormat's ImageProcessor probing with a no-op that just trusts the VAAPI surface format (since on real ChromeOS the IP does color conversion that we don't need in our dmabuf-passthrough path).
Reference: [crbug 40192819] "VaapiVideoDecoder on linux" (https://issues.chromium.org/issues/40192819).
Patch 2 — un-gate V4L2VideoDecoder factory for non-ChromeOS Linux
Optional but useful as a fallback. The class is compiled in; only the
factory registration is IS_CHROMEOS-gated. The igel-oss/meta-browser-hwdecode
patch https://github.com/igel-oss/meta-browser-hwdecode/blob/master/recipes-chromium/chromium/files/0001-Add-support-for-V4L2VDA-on-Linux.patch
shows the historical pattern for the V4L2VDA factory; the modern factory
is in media/gpu/v4l2/v4l2_video_decoder.{h,cc}.
This is plan B if Patch 1 turns out harder than expected — V4L2VDA
talks to /dev/videoN directly without going through libva, which means
we don't depend on the libva-v4l2-request-fourier decode-submission
path either. Shorter end-to-end critical path, but a more invasive
factory change.
Patch 3 — point libva at our backend (build-time)
Already configurable at runtime via LIBVA_DRIVER_NAME=v4l2_request,
but a Brave/Chromium binary that defaults to it would be cleaner. Could
patch the GPU process startup to set the env var if not already set.
Cosmetic, optional.
Reference forks (read these side-by-side with our patch)
- JeffyCN/meta-rockchip chromium recipe — the upstream of the V4L2VDA
factory un-gating and
libv4l-rkmppshim that every shipping fork uses. https://github.com/JeffyCN/meta-rockchip/tree/master/dynamic-layers/recipes-browser/chromium Caveat: targets the V4L2VDA path (Plan B), not the modernVaapiVideoDecoder(Plan A) we want. - igel-oss/meta-browser-hwdecode — Yocto layer with the original
0001-Add-support-for-V4L2VDA-on-Linux.patch. 2017-vintage but the pattern still applies. https://github.com/igel-oss/meta-browser-hwdecode - 7Ji-PKGBUILDs/chromium-mpp — the most recent ALARM-shipping variant, Chromium 132 with MPP. Useful for the PKGBUILD shape and the patch-set list, even though we're not using MPP. https://github.com/7Ji-PKGBUILDs/chromium-mpp
- amazingfate/chromium-debian-build — Debian flavour of the same approach, for reference. https://github.com/amazingfate/chromium-debian-build
Build environment
- Source tree:
gn/depot_tools, hosted on fermi (Arch ARM aarch64 LXC on hertz). Fetch is ~30 GB; full chromium tree is ~100 GB with build artifacts. Fermi's storage budget needs checking — may need to bind-mount a hertz path with more headroom. - Build acceleration:
distcc-avahiis already deployed. Wire the chromium build to use distcc through CT108 + tesla as compile workers. Pump mode can shave further; chromium's ninja will accept distcc'd cc/c++ via wrappers. - First build wall time estimate: 6–10 hours initial on fermi alone; 3–5 hours with distcc-avahi if the network throughput holds. After the first build, incrementals on small patches are ~10–15 min.
- Configure flags:
gn args— start from Arch'schromiumPKGBUILD, adduse_vaapi=true use_v4l2_codec=true is_official_build=false. - Output:
chromium-fourier-<chromium-ver>-1-aarch64.pkg.tar.zstshipping/usr/bin/chromium.provides=(chromium) conflicts=(chromium)shape, same asffmpeg-v4l2-request-git's replacement of stock ffmpeg.
Validation path
Once a patched binary builds:
- Launch with the same env we use for mpv-vaapi:
LIBVA_DRIVER_NAME=v4l2_request LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video0 - Open
chrome://gpu— should show "Video Decode: Hardware accelerated" (not "Disabled" or "Software only"). - Open a 1080p H.264 file:// URL, watch CPU on
/dev/video0openers, measure Brave's GPU process CPU% during playback. - Cross-reference with
mpv --hwdec=vaapinumbers once the libva-v4l2-request-fourier decode-submission path also lands.
Order of operations
Phase A (this session): workspace + STUDY.md (this file). Done.
Phase B: build environment — install depot_tools on fermi, run
fetch chromium, get a baseline (unpatched) build to confirm fermi can
build chromium at all. ~one full day.
Phase C: identify the exact line to flip for Patch 1 by reading
media/gpu/chromeos/video_decoder_pipeline.cc +
media/gpu/vaapi/vaapi_video_decoder.cc against current Chromium
master. Iterate the patch on a real build.
Phase D: package as chromium-fourier PKGBUILD, hook into
marfrit-packages CI on fermi (already has the pattern from
ffmpeg-v4l2-request-git).
Phase E: rebase Patch 1 (and Patch 2 if needed) onto Brave's source
tree, ship as brave-fourier next to chromium-fourier. Brave's tree
adds ~50 patches on top of upstream Chromium; the chromeos-pipeline
seam should be unchanged across that delta, so this should be a
mechanical rebase.
Out of scope
- HW video encode (cameras, webcam streams). RK3566 has a separate
encoder block on
/dev/video2; not a Fourier priority. - HEVC / VP9 / AV1 — RK3566 has no HW for these. RK3588 has VDPU381 but our libva backend doesn't speak HEVC yet.
- WebGL / WebGPU performance — separate concern, not part of video decode.
- Brave-specific features (Shields, Wallet, etc.) — they all live in Brave's source tree on top of Chromium and are unaffected by our decode patches.