# bugzilla.mozilla.org bug 1969297 — comment draft **Bug**: https://bugzilla.mozilla.org/show_bug.cgi?id=1969297 **Title**: Implement hardware decoding of h.265/HEVC with v4l2-stateless **Owner**: david.turner@raspberrypi.com **Status**: ASSIGNED, Linux/ARM64, Core :: Audio/Video: Playback This bug tracks H.265/HEVC stateless. Our work targeted H.264 stateless on Rockchip RK3399 (Pinebook Pro, mainline kernel, rkvdec driver) but the plumbing — gfxinfo fourcc detection, libavcodec hwaccel routing, RDD sandbox carve-out — is identical in shape to what David outlined in comment #3 ("work that needs doing"). Posting findings here in case it saves duplicate effort and to flag a sandbox interaction that any V4L2 stateless implementation will hit. --- ## Comment to post (markdown — Bugzilla renders ` ``` ` blocks) Posting independent findings from a parallel firefox-fourier campaign on Rockchip RK3399 / Pinebook Pro / mainline rkvdec (H.264 stateless). The plumbing is identical to what David described in comment #3 for HEVC, so this should fold into bug 1969297 cleanly once H.265-specific bits are layered on. **Patch series** (validated end-to-end, RDD CPU 78% software → 5% hardware on bbb 1080p30 H.264, default RDD sandbox enabled, no env overrides): 1. `widget/gtk/GfxInfo.cpp` — recognize V4L2 stateless fourccs `S264`, `S265`, `VP9F` alongside the existing stateful set 2. `dom/media/platforms/ffmpeg/FFmpegLibWrapper` — silent `av_hwdevice_ctx_create` wrapper (suppresses libavutil's stderr spam when the autodetect tries unsupported devices) 3. `dom/media/platforms/ffmpeg/FFmpegVideoDecoder` — split V4L2 stateless init (`InitV4L2RequestDecoder`) from stateful (`InitV4L2Decoder`), with a two-pass codec-name-first / `hw_configs`-fallback probe so it works against both legacy (`AV_HWDEVICE_TYPE_DRM`) and modern (`AV_HWDEVICE_TYPE_V4L2REQUEST`, value 15 in Kwiboo's fork) FFmpeg vintages 4. `modules/libpref/init/StaticPrefList.yaml` — gate behind `media.ffmpeg.v4l2-request.enabled` (default true) 5. `security/sandbox/linux/{broker/SandboxBrokerPolicyFactory,SandboxFilter}.cpp` — RDD sandbox extension: `/dev/media*` (driver-matched against the existing `/dev/video*` walk), MEDIA_IOC_* ioctl family `'|'`, plus AddTree on `/sys/class`, `/sys/bus`, `/sys/dev/char`, `/sys/devices/platform`, `/run/udev`, `/etc/udev/udev.conf`, `/proc/self`, `/dev/dma_heap` The series is published on git.reauktion.de/marfrit/marfrit-packages under `arch/firefox-fourier/patches/`. **The non-obvious finding worth surfacing here:** `udev_enumerate_scan_devices()` returns `-EUNATCH` (-49) inside RDD's sandbox even with all the broker carve-outs above in place. Mozilla's `OpenAtTrap` in `security/sandbox/linux/SandboxFilter.cpp` explicitly rejects fd-relative `openat()`: ```c if (fd != AT_FDCWD && path[0] != '/') { SANDBOX_LOG("unsupported fd-relative openat(%d, \"%s\", 0%o)", fd, path, flags); return BlockedSyscallTrap(aArgs, nullptr); // returns -ENOSYS } ``` systemd v255+ uses fd-relative `openat()` extensively inside its `chase()` symlink-resolver for TOCTOU safety, and `chase()` is the spine of `udev_enumerate_scan_devices`. So libudev fails inside the sandbox no matter how permissive the broker policy is — the calls never reach the broker. Confirmed by bpftrace comparison (sandbox-on vs sandbox-off): full `openat("/")`, `openat("sys")`, `openat("bus")`, `openat("..")` chase flurry under sandbox-off, zero `openat()` events under sandbox-on. **Workaround we shipped** (in our ffmpeg-v4l2-request fork): a brute-force fallback inside `libavutil/hwcontext_v4l2request.c`'s `v4l2request_open_decoder` that enumerates `/dev/media[0..15]` directly via absolute paths plus `MEDIA_IOC_DEVICE_INFO` and `MEDIA_IOC_G_TOPOLOGY`, with stat()-based major/minor matching to resolve `/dev/videoN` paths. The fallback only activates when libudev's scan returns negative. Same approach Chromium uses in `media/gpu/v4l2/stateless/` for ChromeOS where the sandbox has the same constraint. This is a libavcodec-side fix, not a Firefox-side one — so it'd be appropriate either to upstream to FFmpeg (the v4l2_request hwaccel predates wider sandboxed-Linux deployment, so the libudev assumption was reasonable at the time) or carry it as a Firefox-bundled libavcodec patch. The alternative — teaching Mozilla's broker to handle fd-relative `openat()` via `/proc/self/fd//` resolution — would close the gap for any future libudev consumer in the sandbox, but has TOCTOU implications I haven't audited; the libavcodec-side bypass felt cheaper to ship. Validation log on RK3399 / Pinebook Pro / mainline rkvdec, default RDD sandbox, `MOZ_LOG=FFmpegLib:5`: ``` V4L2 stateless FFmpeg init successful Format drm_prime chosen by get_format(). Format drm_prime requires hwaccel h264_v4l2request initialisation. libudev probe failed (-2), falling back to brute-force /dev/media* Using V4L2 media driver rkvdec (brute-force) for S264 Reinit context to 1920x1088, pix_fmt: drm_prime ``` Happy to coordinate / split work / share patches if that helps the HEVC track. None of patches 1-4 above are H.264-specific; 5 is codec-agnostic. The libavcodec libudev-bypass has zero codec coupling. --- ## Notes for upload - This is just the comment text. Don't attach the patches — Mozilla prefers Phabricator (D-numbers) for code review. If the H.264 work is upstreamed it should go through Phabricator with David tagged. - Suggest emailing David first (david.turner@raspberrypi.com) before pasting in the bug, in case he's already half-implemented something similar — saves a thrash if there's overlap. - The /proc/self/fd/ trick mentioned at the end is real (and is how Chromium handles its own broker for some paths). If pursued upstream in Mozilla, see security/sandbox/linux/broker/SandboxBroker.cpp RealPath() + SymlinkPermissions() for the existing precedent.