firefox-fourier: v4l2-request hwaccel inert on Pi 5 — no libavcodec with --enable-v4l2-request at the soname Firefox loads #59

Open
opened 2026-05-20 20:31:11 +00:00 by claude-noether · 2 comments
Contributor

Summary

The firefox-fourier package on a Pi 5 / CM5 (Debian trixie aarch64) silently falls back to software decode for every codec. The patched InitV4L2RequestDecoder runs, calls into the libavcodec Firefox dlopened, and the libavcodec reports it has no v4l2_request hwaccel registered for that codec. Firefox unwinds through InitV4L2Decoder (stateful h264_v4l2m2m — also missing), then through stock VAAPI lookup (no *_vaapi codecs in modern FFmpeg), and finally lands on Using preferred software codec h264. The daedalus_v4l2 daemon stays dark — daemon journal shows 0 REQ_DECODE despite Firefox running at 25-30% CPU on the video tab.

Observed on higgs (Pi CM5, kernel 6.18.29, firefox-fourier 1:150.0.3-1+rpt1+fourier1):

MOZ_LOG=PlatformDecoderModule:5,FFmpegVideo:5 firefox
  ...
  D/FFmpegVideo FFMPEG: Initialising V4L2 stateless (request API) FFmpeg decoder
  D/FFmpegVideo FFMPEG:   no v4l2_request path for codec ID 27 — neither named codec
                          h264_v4l2request nor generic codec with DRM hwaccel available
                          (libavcodec built without --enable-v4l2-request?)
  D/FFmpegVideo FFMPEG: Initialising V4L2-DRM FFmpeg decoder
  D/FFmpegVideo FFMPEG:   V4L2 codec h264_v4l2m2m : V4L2 mem2mem H.264 decoder wrapper
  D/FFmpegVideo FFMPEG:   Couldn't initialise V4L2 decoder
  D/FFmpegVideo FFMPEG: Using preferred software codec h264

Daedalus daemon journal during 30s of YouTube playback: zero REQ_DECODE.

Root cause — three libavcodecs on the box, none usable

path soname --enable-v4l2-request? dlopen'd by RDD?
/usr/lib/firefox/libmozavcodec.so (FFVPX bundle) unversioned (libmozavcodec.so) NO YES (FFVPX PDM is #0, accepts every video codec via Supports())
/usr/lib/aarch64-linux-gnu/libavcodec.so.61 (Debian libavcodec61) .61 NO (Debian build doesn't set it) possibly (OSLibrary PDM, #1)
/opt/fourier/lib/libavcodec.so.62 (ffmpeg-v4l2-request-fourier) .62 YES NO — soname mismatch, ld.so refuses to satisfy a .so.61 DT_NEEDED with a .so.62 file

Verification: dpkg -S /usr/lib/aarch64-linux-gnu/libavcodec.so.61libavcodec61:arm64 (Debian stock). ffmpeg -hide_banner -buildconf | grep v4l2 on the Debian-stock binary returns empty. /opt/fourier/bin/ffmpeg -hide_banner -hwaccels (the fourier-prefix binary) returns vdpau / vaapi / drm / vulkan / v4l2request — has the feature, wrong soname. RDD's /proc/$pid/maps shows /usr/lib/firefox/libmozavcodec.so + libmozavutil.so loaded; no libavcodec.so.61 or libavcodec.so.62 mapped at all.

The mozconfig comment claims the design intent is "the v4l2_request hwaccel routing happens via the system libavcodec loaded at startup" — but on Debian trixie the system libavcodec (.61) is stock without the feature, and LD_LIBRARY_PATH=/opt/fourier/lib doesn't help because of the soname split.

What's blocked

Full Pi 5 Fourier campaign on the consumer end. The other layers all work:

  • libva-v4l2-request-fourier per-codec dispatch (libva PRs #6, #7, #9, #10) lands on /dev/video0+daedalus.
  • daedalus-v4l2 kernel module (PR #2 v4l2_ctrl_request_setup + PR #3 per-ctx vb_mutex) honors V4L2 stateless H.264 correctly.
  • daedalus-v4l2 daemon (PR #1 DAEMON-PPS) synthesises SPS+PPS NAL units, libavcodec dlopens FFmpeg 7.1.3 cleanly.
  • ffmpeg-v4l2-request-fourier at /opt/fourier/ has --enable-v4l2-request + --enable-vaapi.

When the daemon was reached directly (test_m2m_decode harness, ffmpeg via vaapi command-line) the stack decoded H.264 at 30 fps clean (60/60 frames, zero errors, unique fnv1a hashes). YouTube via Firefox: zero REQ_DECODE. The only missing piece is making Firefox actually call into a libavcodec that has v4l2_request registered.

Proposed fix paths

A. libavcodec61-fourier compat package (recommended)

New package in marfrit-packages that ships libavcodec.so.61 (matching Debian's soname) built with --enable-v4l2-request + --enable-vaapi, with:

Package: libavcodec61-fourier
Replaces: libavcodec61
Conflicts: libavcodec61
Provides: libavcodec61

When installed, replaces Debian's stock libavcodec61 with a feature-on variant at the same soname. Firefox's OSLibrary PDM dlopens it at startup, v4l2_request hwaccel is now registered on the generic h264 codec, the patched InitV4L2RequestDecoder finds the DRM hwaccel in hw_configs, succeeds, decode flows through libavcodec → V4L2 stateless → daedalus_v4l2 → daemon. Touches no other consumers (ffmpeg CLI, mpv, anything-else-linked-against-libavcodec61).

Main risk: ABI compat with downstream packages. Since --enable-v4l2-request is an ADDITIVE configure flag (doesn't remove or rename anything in the public API) the ABI surface should be identical to Debian's; only added codepaths. Verifiable via abidiff against Debian's .so.61.

Minor risk: Debian package updates of libavcodec61 will fight with the Replaces/Conflicts on apt upgrades. Pin the marfrit-packages variant via apt preferences.

B. Enable v4l2-request in FFVPX inside the firefox-fourier build

Add to arch/firefox-fourier/mozconfig:

ac_add_options --enable-ffmpeg-extra-config='--enable-v4l2-request'

(exact Mozilla configure key may vary — needs verification against the FFVPX build subtree). This makes the bundled libmozavcodec.so register the v4l2_request hwaccel. Then both FFVPX and OSLibrary PDM paths support it.

Main risk: Mozilla's FFVPX is a stripped-down build optimised for sandbox safety; adding hwaccel may pull in libraries Mozilla deliberately excluded (libdrm, libv4l2). May require also adding --enable-libdrm --enable-libv4l2 to the FFVPX configure, which inflates libmozavcodec.so size and changes its dlopen surface.

C. Both A and B (defense in depth)

If both land, every PDM path supports v4l2_request — no profile-pref churn needed.

Recommendation

Ship A first (smaller blast radius, no Mozilla-internal build changes, fixes the path the mozconfig already documents as the design intent). B as follow-up if any consumer ends up wanting bundled-only operation (e.g. a Firefox-portable scenario where system libavcodec might be a stock Debian one).

Happy to draft the libavcodec61-fourier package skeleton — would reuse the existing ffmpeg-v4l2-request-fourier build script with a different install prefix + Debian control fields.

Related

  • daedalus-v4l2 PRs #1, #2, #3 — the kernel + daemon stack already routes H.264 correctly when fed.
  • libva-v4l2-request-fourier PRs #6, #7, #10 — VAAPI consumer path works (verified via ffmpeg CLI), separate from this firefox-direct path.
  • marfrit-packages issues #55, #11 — adjacent CI / AV1 work.
  • firefox-fourier PLAN.md explicitly mentions the v4l2_request hwaccel path requires libavcodec with --enable-v4l2-request — the gap is in which libavcodec ends up dlopened on a fresh Debian trixie install.
## Summary The firefox-fourier package on a Pi 5 / CM5 (Debian trixie aarch64) silently falls back to software decode for every codec. The patched `InitV4L2RequestDecoder` runs, calls into the libavcodec Firefox dlopened, and the libavcodec reports it has no v4l2_request hwaccel registered for that codec. Firefox unwinds through `InitV4L2Decoder` (stateful `h264_v4l2m2m` — also missing), then through stock VAAPI lookup (no `*_vaapi` codecs in modern FFmpeg), and finally lands on `Using preferred software codec h264`. The daedalus_v4l2 daemon stays dark — daemon journal shows 0 REQ_DECODE despite Firefox running at 25-30% CPU on the video tab. Observed on higgs (Pi CM5, kernel 6.18.29, firefox-fourier `1:150.0.3-1+rpt1+fourier1`): ``` MOZ_LOG=PlatformDecoderModule:5,FFmpegVideo:5 firefox ... D/FFmpegVideo FFMPEG: Initialising V4L2 stateless (request API) FFmpeg decoder D/FFmpegVideo FFMPEG: no v4l2_request path for codec ID 27 — neither named codec h264_v4l2request nor generic codec with DRM hwaccel available (libavcodec built without --enable-v4l2-request?) D/FFmpegVideo FFMPEG: Initialising V4L2-DRM FFmpeg decoder D/FFmpegVideo FFMPEG: V4L2 codec h264_v4l2m2m : V4L2 mem2mem H.264 decoder wrapper D/FFmpegVideo FFMPEG: Couldn't initialise V4L2 decoder D/FFmpegVideo FFMPEG: Using preferred software codec h264 ``` Daedalus daemon journal during 30s of YouTube playback: zero REQ_DECODE. ## Root cause — three libavcodecs on the box, none usable | path | soname | `--enable-v4l2-request`? | dlopen'd by RDD? | |---|---|---|---| | `/usr/lib/firefox/libmozavcodec.so` (FFVPX bundle) | unversioned (`libmozavcodec.so`) | **NO** | YES (FFVPX PDM is #0, accepts every video codec via `Supports()`) | | `/usr/lib/aarch64-linux-gnu/libavcodec.so.61` (Debian `libavcodec61`) | `.61` | **NO** (Debian build doesn't set it) | possibly (OSLibrary PDM, #1) | | `/opt/fourier/lib/libavcodec.so.62` (`ffmpeg-v4l2-request-fourier`) | `.62` | **YES** | NO — soname mismatch, `ld.so` refuses to satisfy a `.so.61` DT_NEEDED with a `.so.62` file | Verification: `dpkg -S /usr/lib/aarch64-linux-gnu/libavcodec.so.61` → `libavcodec61:arm64` (Debian stock). `ffmpeg -hide_banner -buildconf | grep v4l2` on the Debian-stock binary returns empty. `/opt/fourier/bin/ffmpeg -hide_banner -hwaccels` (the fourier-prefix binary) returns `vdpau / vaapi / drm / vulkan / v4l2request` — has the feature, wrong soname. RDD's `/proc/$pid/maps` shows `/usr/lib/firefox/libmozavcodec.so` + `libmozavutil.so` loaded; **no `libavcodec.so.61` or `libavcodec.so.62` mapped at all**. The mozconfig comment claims the design intent is *"the v4l2_request hwaccel routing happens via the system libavcodec loaded at startup"* — but on Debian trixie the system libavcodec (`.61`) is stock without the feature, and `LD_LIBRARY_PATH=/opt/fourier/lib` doesn't help because of the soname split. ## What's blocked Full Pi 5 Fourier campaign on the consumer end. The other layers all work: - libva-v4l2-request-fourier per-codec dispatch (libva PRs #6, #7, #9, #10) lands on /dev/video0+daedalus. - daedalus-v4l2 kernel module (PR #2 v4l2_ctrl_request_setup + PR #3 per-ctx vb_mutex) honors V4L2 stateless H.264 correctly. - daedalus-v4l2 daemon (PR #1 DAEMON-PPS) synthesises SPS+PPS NAL units, libavcodec dlopens FFmpeg 7.1.3 cleanly. - ffmpeg-v4l2-request-fourier at `/opt/fourier/` has `--enable-v4l2-request` + `--enable-vaapi`. When the daemon was reached directly (test_m2m_decode harness, ffmpeg via vaapi command-line) the stack decoded H.264 at 30 fps clean (60/60 frames, zero errors, unique fnv1a hashes). YouTube via Firefox: zero REQ_DECODE. The only missing piece is making Firefox actually call into a libavcodec that has v4l2_request registered. ## Proposed fix paths ### A. `libavcodec61-fourier` compat package (recommended) New package in marfrit-packages that ships `libavcodec.so.61` (matching Debian's soname) built with `--enable-v4l2-request` + `--enable-vaapi`, with: ``` Package: libavcodec61-fourier Replaces: libavcodec61 Conflicts: libavcodec61 Provides: libavcodec61 ``` When installed, replaces Debian's stock libavcodec61 with a feature-on variant at the same soname. Firefox's OSLibrary PDM dlopens it at startup, v4l2_request hwaccel is now registered on the generic h264 codec, the patched `InitV4L2RequestDecoder` finds the DRM hwaccel in `hw_configs`, succeeds, decode flows through libavcodec → V4L2 stateless → daedalus_v4l2 → daemon. Touches no other consumers (ffmpeg CLI, mpv, anything-else-linked-against-libavcodec61). Main risk: ABI compat with downstream packages. Since `--enable-v4l2-request` is an ADDITIVE configure flag (doesn't remove or rename anything in the public API) the ABI surface should be identical to Debian's; only added codepaths. Verifiable via `abidiff` against Debian's `.so.61`. Minor risk: Debian package updates of `libavcodec61` will fight with the Replaces/Conflicts on apt upgrades. Pin the marfrit-packages variant via apt preferences. ### B. Enable v4l2-request in FFVPX inside the firefox-fourier build Add to `arch/firefox-fourier/mozconfig`: ``` ac_add_options --enable-ffmpeg-extra-config='--enable-v4l2-request' ``` (exact Mozilla configure key may vary — needs verification against the FFVPX build subtree). This makes the bundled `libmozavcodec.so` register the v4l2_request hwaccel. Then both FFVPX and OSLibrary PDM paths support it. Main risk: Mozilla's FFVPX is a stripped-down build optimised for sandbox safety; adding hwaccel may pull in libraries Mozilla deliberately excluded (libdrm, libv4l2). May require also adding `--enable-libdrm --enable-libv4l2` to the FFVPX configure, which inflates `libmozavcodec.so` size and changes its dlopen surface. ### C. Both A and B (defense in depth) If both land, every PDM path supports v4l2_request — no profile-pref churn needed. ## Recommendation Ship **A** first (smaller blast radius, no Mozilla-internal build changes, fixes the path the mozconfig already documents as the design intent). **B** as follow-up if any consumer ends up wanting bundled-only operation (e.g. a Firefox-portable scenario where system libavcodec might be a stock Debian one). Happy to draft the libavcodec61-fourier package skeleton — would reuse the existing ffmpeg-v4l2-request-fourier build script with a different install prefix + Debian control fields. ## Related - daedalus-v4l2 PRs #1, #2, #3 — the kernel + daemon stack already routes H.264 correctly when fed. - libva-v4l2-request-fourier PRs #6, #7, #10 — VAAPI consumer path works (verified via ffmpeg CLI), separate from this firefox-direct path. - marfrit-packages issues #55, #11 — adjacent CI / AV1 work. - firefox-fourier `PLAN.md` explicitly mentions the v4l2_request hwaccel path requires libavcodec with `--enable-v4l2-request` — the gap is in *which* libavcodec ends up dlopened on a fresh Debian trixie install.
Owner

Status 2026-05-21 — original symptom resolved, AV1 still in flight

What landed

Both halves of the title's OR landed in practice, via the compat-package route:

  • libavcodec61 on Pi CM5 is now 8:7.1.3-0+deb13u1+rpt1+fourier2 — soname-compatible Debian-stock rebuild with --enable-v4l2-request. dpkg confirmed on higgs.
  • ffmpeg-v4l2-request-fourier 2:8.1+rfourier+gb57fbbe-4 is installed.
  • libva-v4l2-request-fourier routes Pi CM5 traffic through the daedalus_v4l2 kmod into the userspace daemon (/opt/fourier libavcodec), bypassing Firefox's bundled libmozavcodec (FFVPX) entirely.

Verified end-to-end on Pi CM5

Firefox YouTube playback now engages the daedalus daemon — journalctl -u daedalus-v4l2 shows the live REQ_DECODE stream, libva opens daedalus_v4l2 at video_fd=34 media_fd=35, cap_pool_init: 24 slots ready, h264_set_controls VAProfile=6 ... per request, decode succeeds. The original issue-body symptom ("silently falls back to software decode for every codec") no longer reproduces.

VP9 same path.

Design note for future-self

The firefox-fourier ↔ FFVPX --enable-v4l2-request option mentioned first in the title was never pursued. The compat-package route turned out to be the cleaner deliverable: we get the v4l2-request hwaccel surfaced at the soname Firefox loads without touching FFVPX's vendored mozilla build. Decision was driven by the observation that on a Pi CM5 the actual hot path skips Firefox's libavcodec entirely (libva → kernel → daemon) — so the FFVPX patch would have shipped code that real workloads don't exercise.

Still in flight

  • AV1: needs the daemon-side OBU sequence-header synthesiser. Tracked on reauktion/daedalus-v4l2 as the daemon-half of issue #11 (and task #144 in our local list). When that lands the same end-to-end path will cover AV1.
  • Possible packaging cleanup: this issue can either stay open as the AV1 umbrella, or be closed once daedalus-v4l2#11 is resolved. Either works.
## Status 2026-05-21 — original symptom resolved, AV1 still in flight ### What landed Both halves of the title's `OR` landed in practice, via the compat-package route: - `libavcodec61` on Pi CM5 is now `8:7.1.3-0+deb13u1+rpt1+fourier2` — soname-compatible Debian-stock rebuild with `--enable-v4l2-request`. dpkg confirmed on higgs. - `ffmpeg-v4l2-request-fourier` `2:8.1+rfourier+gb57fbbe-4` is installed. - `libva-v4l2-request-fourier` routes Pi CM5 traffic through the `daedalus_v4l2` kmod into the userspace daemon (`/opt/fourier` libavcodec), bypassing Firefox's bundled `libmozavcodec` (FFVPX) entirely. ### Verified end-to-end on Pi CM5 Firefox YouTube playback now engages the daedalus daemon — `journalctl -u daedalus-v4l2` shows the live `REQ_DECODE` stream, libva opens `daedalus_v4l2 at video_fd=34 media_fd=35`, `cap_pool_init: 24 slots ready`, `h264_set_controls VAProfile=6 ...` per request, decode succeeds. The original issue-body symptom ("silently falls back to software decode for every codec") no longer reproduces. VP9 same path. ### Design note for future-self The `firefox-fourier ↔ FFVPX --enable-v4l2-request` option mentioned first in the title was never pursued. The compat-package route turned out to be the cleaner deliverable: we get the v4l2-request hwaccel surfaced at the soname Firefox loads without touching FFVPX's vendored mozilla build. Decision was driven by the observation that on a Pi CM5 the actual hot path skips Firefox's libavcodec entirely (libva → kernel → daemon) — so the FFVPX patch would have shipped code that real workloads don't exercise. ### Still in flight - AV1: needs the daemon-side OBU sequence-header synthesiser. Tracked on `reauktion/daedalus-v4l2` as the daemon-half of issue #11 (and task #144 in our local list). When that lands the same end-to-end path will cover AV1. - Possible packaging cleanup: this issue can either stay open as the AV1 umbrella, or be closed once `daedalus-v4l2#11` is resolved. Either works.
Author
Contributor

Close-out

Original symptom (firefox-fourier silently falling back to software for H.264/VP9 on Pi 5 / CM5) resolved via the libavcodec61-fourier compat-package route per marfrit's 2026-05-21 status comment. Verified end-to-end on higgs with live REQ_DECODE stream in journalctl -u daedalus-v4l2 for both codecs.

AV1 is not covered by this fix — it needs daemon-side OBU sequence-header synthesis (the AV1 analogue of the H.264 DAEMON-PPS path). The earlier comment referenced daedalus-v4l2#11 for this, but #11 is actually a different scope (H.264 B-frame display-order re-architecture). Created a fresh AV1-specific tracking issue with the correct scope:

reauktion/daedalus-v4l2#14 — daemon: AV1 OBU sequence-header synthesis
reauktion/daedalus-v4l2#14

Closing this one as resolved. AV1 work lives in daedalus-v4l2#14 from here on.

Closes #59.

## Close-out Original symptom (firefox-fourier silently falling back to software for H.264/VP9 on Pi 5 / CM5) resolved via the `libavcodec61-fourier` compat-package route per marfrit's 2026-05-21 status comment. Verified end-to-end on higgs with live `REQ_DECODE` stream in `journalctl -u daedalus-v4l2` for both codecs. AV1 is **not** covered by this fix — it needs daemon-side OBU sequence-header synthesis (the AV1 analogue of the H.264 DAEMON-PPS path). The earlier comment referenced `daedalus-v4l2#11` for this, but #11 is actually a different scope (H.264 B-frame display-order re-architecture). Created a fresh AV1-specific tracking issue with the correct scope: → **reauktion/daedalus-v4l2#14 — daemon: AV1 OBU sequence-header synthesis** https://git.reauktion.de/reauktion/daedalus-v4l2/issues/14 Closing this one as resolved. AV1 work lives in daedalus-v4l2#14 from here on. Closes #59.
Sign in to join this conversation.
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marfrit/marfrit-packages#59