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: - 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.
209 lines
8.5 KiB
Diff
209 lines
8.5 KiB
Diff
From: Markus Fritsche <mfritsche@reauktion.de>
|
|
Subject: [PATCH 3/4] dom/media/platforms/ffmpeg: route through libavcodec
|
|
v4l2_request hwaccel for V4L2 stateless boards
|
|
Date: 2026-04-27
|
|
|
|
Background
|
|
----------
|
|
Firefox's existing V4L2 init (`InitV4L2Decoder`) finds the codec by
|
|
suffix lookup (`FindVideoHardwareAVCodec(mLib, mCodecID)`), which on
|
|
Linux resolves to the **stateful** V4L2-M2M wrapper codec
|
|
(`h264_v4l2m2m` etc). Mainline-Linux Rockchip boards (RK3399 rkvdec,
|
|
RK3566/RK3588 hantro, RK3588 rkvdec2) only expose **stateless**
|
|
V4L2 fourccs (`S264`, `S265`, `VP9F`); the stateful wrapper codec
|
|
fails to open, Firefox falls all the way through to software.
|
|
|
|
This patch adds a sibling init path, `InitV4L2RequestDecoder`, that:
|
|
|
|
* uses the **generic** codec (e.g. plain `h264`, returned by
|
|
`avcodec_find_decoder(AV_CODEC_ID_H264)`) rather than the stateful
|
|
wrapper;
|
|
* sanity-checks the codec's `hw_configs` for an `AV_HWDEVICE_TYPE_DRM`
|
|
entry — that's how libavcodec surfaces the v4l2_request hwaccel
|
|
upstream (no dedicated `_V4L2REQUEST` device type exists);
|
|
* creates an `AV_HWDEVICE_TYPE_DRM` hwdevice context bound to
|
|
`/dev/dri/renderD128` via the new `av_hwdevice_ctx_create` wrapper
|
|
(patch 2/4) and attaches it to the codec context;
|
|
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
|
|
(already returns `AV_PIX_FMT_DRM_PRIME`) and the existing
|
|
`apply_cropping = 0` constraint.
|
|
|
|
`InitV4L2RequestDecoder` is invoked **before** `InitV4L2Decoder` in
|
|
`InitHWDecoderIfAllowed`. On Rockchip mainline it succeeds. On Pi4 /
|
|
Mediatek / vendor-MPP-stateful boards the codec's `hw_configs` lacks
|
|
a DRM entry (the V4L2-M2M codecs don't register one), the sanity
|
|
check fails, and the existing stateful `InitV4L2Decoder` runs as
|
|
before. No regression of stateful boards.
|
|
|
|
`mDRMDeviceContext` is unconditionally `av_buffer_unref`'d in
|
|
`ProcessShutdown` (no-op when null). Gated behind
|
|
`media.ffmpeg.v4l2-request.enabled` from patch 4/4.
|
|
|
|
Bug 1969297.
|
|
|
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
|
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-03-18 19:22:14.000000000 +0000
|
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-04-27 20:43:39.347992674 +0000
|
|
@@ -225,7 +225,12 @@
|
|
bool IsLinuxHDR() const;
|
|
MediaResult InitVAAPIDecoder();
|
|
MediaResult InitV4L2Decoder();
|
|
+ // firefox-fourier: V4L2 stateless (request API) decode path. Uses
|
|
+ // libavcodec's v4l2_request hwaccel, which it surfaces via
|
|
+ // AV_HWDEVICE_TYPE_DRM rather than a dedicated _V4L2REQUEST type.
|
|
+ MediaResult InitV4L2RequestDecoder();
|
|
bool CreateVAAPIDeviceContext();
|
|
+ bool CreateV4L2RequestDeviceContext();
|
|
bool GetVAAPISurfaceDescriptor(VADRMPRIMESurfaceDescriptor* aVaDesc);
|
|
void AddAcceleratedFormats(nsTArray<AVCodecID>& aCodecList,
|
|
AVCodecID aCodecID, AVVAAPIHWConfig* hwconfig);
|
|
@@ -239,7 +244,10 @@
|
|
void AdjustHWDecodeLogging();
|
|
|
|
AVBufferRef* mVAAPIDeviceContext = nullptr;
|
|
+ // firefox-fourier: DRM hwdevice ctx for the v4l2_request hwaccel.
|
|
+ AVBufferRef* mDRMDeviceContext = nullptr;
|
|
bool mUsingV4L2 = false;
|
|
+ bool mUsingV4L2Request = false;
|
|
// If video overlay is used we want to upload SW decoded frames to
|
|
// DMABuf and present it as a external texture to rendering pipeline.
|
|
bool mUploadSWDecodeToDMABuf = false;
|
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
|
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-03-18 19:22:14.000000000 +0000
|
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-27 20:44:33.280766228 +0000
|
|
@@ -406,6 +406,105 @@
|
|
return NS_OK;
|
|
}
|
|
|
|
+// firefox-fourier: V4L2 stateless (request API) DRM hwdevice context.
|
|
+// libavcodec's v4l2_request hwaccel binds via AV_HWDEVICE_TYPE_DRM —
|
|
+// no dedicated _V4L2REQUEST type exists upstream.
|
|
+bool FFmpegVideoDecoder<LIBAV_VER>::CreateV4L2RequestDeviceContext() {
|
|
+ if (!mLib->av_hwdevice_ctx_create) {
|
|
+ FFMPEG_LOG(" av_hwdevice_ctx_create not available (libavutil too old)");
|
|
+ return false;
|
|
+ }
|
|
+ const char* drmDevice = "/dev/dri/renderD128";
|
|
+ if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
|
|
+ AV_HWDEVICE_TYPE_DRM, drmDevice,
|
|
+ nullptr, 0) < 0) {
|
|
+ FFMPEG_LOG(" av_hwdevice_ctx_create(DRM, %s) failed", drmDevice);
|
|
+ return false;
|
|
+ }
|
|
+ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext);
|
|
+ FFMPEG_LOG(" DRM hwdevice ctx created on %s", drmDevice);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+// firefox-fourier: try V4L2 stateless decode via libavcodec's
|
|
+// v4l2_request hwaccel. Distinct from InitV4L2Decoder which uses the
|
|
+// stateful h264_v4l2m2m wrapper codec. On Rockchip mainline boards
|
|
+// (rkvdec / hantro / rkvdec2) only the stateless path exists.
|
|
+MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2RequestDecoder() {
|
|
+ FFMPEG_LOG("Initialising V4L2 stateless (request API) FFmpeg decoder");
|
|
+
|
|
+ StaticMutexAutoLock mon(sMutex);
|
|
+
|
|
+ // Use the GENERIC codec (not the _v4l2m2m wrapper). libavcodec picks
|
|
+ // the v4l2_request hwaccel internally by walking the codec's
|
|
+ // hw_configs once an AV_HWDEVICE_TYPE_DRM ctx is attached.
|
|
+ AVCodec* codec = mLib->avcodec_find_decoder(mCodecID);
|
|
+ if (!codec) {
|
|
+ FFMPEG_LOG(" generic codec for ID %d not found", mCodecID);
|
|
+ return NS_ERROR_NOT_AVAILABLE;
|
|
+ }
|
|
+
|
|
+ // Sanity-check: refuse when libavcodec was built without the
|
|
+ // v4l2_request hwaccel (no DRM hwaccel registered against this
|
|
+ // codec). Distro packagers occasionally drop --enable-v4l2-request.
|
|
+ bool hasDrmHwaccel = false;
|
|
+ for (int i = 0;; i++) {
|
|
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(codec, i);
|
|
+ if (!cfg) break;
|
|
+ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM) {
|
|
+ hasDrmHwaccel = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (!hasDrmHwaccel) {
|
|
+ FFMPEG_LOG(" codec %s has no DRM hwaccel — libavcodec built "
|
|
+ "without --enable-v4l2-request?", codec->name);
|
|
+ return NS_ERROR_NOT_AVAILABLE;
|
|
+ }
|
|
+ FFMPEG_LOG(" V4L2 stateless: codec %s : %s", codec->name, codec->long_name);
|
|
+
|
|
+ if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
|
|
+ FFMPEG_LOG(" couldn't init HW ffmpeg context");
|
|
+ return NS_ERROR_OUT_OF_MEMORY;
|
|
+ }
|
|
+ mCodecContext->opaque = this;
|
|
+
|
|
+ // Reuse the existing V4L2 init helpers: pixel-format selector returns
|
|
+ // AV_PIX_FMT_DRM_PRIME, cropping disabled (FFmpeg can't crop opaque
|
|
+ // DRM buffers). Same constraints as the stateful V4L2 path.
|
|
+ InitHWCodecContext(ContextType::V4L2);
|
|
+ mCodecContext->apply_cropping = 0;
|
|
+
|
|
+ auto releaseDecoder = MakeScopeExit(
|
|
+ [&]() MOZ_NO_THREAD_SAFETY_ANALYSIS { ReleaseCodecContext(); });
|
|
+
|
|
+ if (!CreateV4L2RequestDeviceContext()) {
|
|
+ return NS_ERROR_NOT_AVAILABLE;
|
|
+ }
|
|
+
|
|
+ MediaResult ret = AllocateExtraData();
|
|
+ if (NS_FAILED(ret)) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
|
|
+ FFMPEG_LOG(" Couldn't open V4L2 stateless decoder");
|
|
+ return NS_ERROR_DOM_MEDIA_FATAL_ERR;
|
|
+ }
|
|
+
|
|
+ if (mAcceleratedFormats.IsEmpty()) {
|
|
+ mAcceleratedFormats.AppendElement(mCodecID);
|
|
+ }
|
|
+
|
|
+ AdjustHWDecodeLogging();
|
|
+
|
|
+ FFMPEG_LOG(" V4L2 stateless FFmpeg init successful");
|
|
+ mUsingV4L2 = true;
|
|
+ mUsingV4L2Request = true;
|
|
+ releaseDecoder.release();
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2Decoder() {
|
|
FFMPEG_LOG("Initialising V4L2-DRM FFmpeg decoder");
|
|
|
|
@@ -659,6 +758,16 @@
|
|
# endif // MOZ_ENABLE_VAAPI
|
|
|
|
# ifdef MOZ_ENABLE_V4L2
|
|
+ // firefox-fourier: try V4L2 stateless (request API) first. On
|
|
+ // mainline-Linux Rockchip boards (RK3399 rkvdec, RK3566/RK3588
|
|
+ // hantro, RK3588 rkvdec2) the kernel exposes only stateless
|
|
+ // fourccs, so the stateful path below would fail anyway. On
|
|
+ // stateful boards (Pi4 / vendor MPP) this gracefully falls
|
|
+ // through (no DRM hwaccel registered for the codec).
|
|
+ if (StaticPrefs::media_ffmpeg_v4l2_request_enabled() &&
|
|
+ NS_SUCCEEDED(InitV4L2RequestDecoder())) {
|
|
+ return;
|
|
+ }
|
|
// VAAPI didn't work or is disabled, so try V4L2 with DRM
|
|
if (NS_SUCCEEDED(InitV4L2Decoder())) {
|
|
return;
|
|
@@ -2046,6 +2155,11 @@
|
|
if (IsHardwareAccelerated()) {
|
|
mLib->av_buffer_unref(&mVAAPIDeviceContext);
|
|
}
|
|
+ // firefox-fourier: release the DRM hwdevice ctx for the v4l2_request
|
|
+ // hwaccel. Always safe — av_buffer_unref no-ops on a null pointer.
|
|
+ if (mDRMDeviceContext) {
|
|
+ mLib->av_buffer_unref(&mDRMDeviceContext);
|
|
+ }
|
|
#endif
|
|
#ifdef MOZ_ENABLE_D3D11VA
|
|
if (IsHardwareAccelerated()) {
|