From 5f21a71770f53e2d6f76929be6d94068230c3914 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Thu, 21 May 2026 00:09:54 +0200 Subject: [PATCH] firefox-fourier patch #3: accept AV_HWDEVICE_TYPE_V4L2REQUEST too Closes part of #60 (firefox-side patch update for fourier2 ffmpeg). Background: libavcodec61-fourier2 (Kwiboo v4l2-request-n7.1.3 backed) registers its hwaccels with AV_HWDEVICE_TYPE_V4L2REQUEST (the dedicated enum added in FFmpeg 7.1+), not AV_HWDEVICE_TYPE_DRM as fourier1 did. The firefox-fourier patch #3 walked hw_configs looking only for DRM and fell through to software for every codec. Patch updates: - CreateV4L2RequestDeviceContext now takes an int aDeviceType (Mozillas bundled libavutil headers may lack the V4L2REQUEST enumerator), passed through to av_hwdevice_ctx_create. - hw_configs walk accepts DRM (legacy) OR V4L2REQUEST integer value (13 on Kwibooss no-AMF tree, 14 on upstream-AMF tree). - Renamed mDRMDeviceContext to mV4L2RequestDeviceContext for accuracy. Build pkgrel will be bumped at debian-package level to +fourier2. --- .../0003-ffmpegvideo-v4l2-request-route.patch | 123 +++++++++++------- 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/arch/firefox-fourier/0003-ffmpegvideo-v4l2-request-route.patch b/arch/firefox-fourier/0003-ffmpegvideo-v4l2-request-route.patch index c02f97bdf..9ef6905c8 100644 --- a/arch/firefox-fourier/0003-ffmpegvideo-v4l2-request-route.patch +++ b/arch/firefox-fourier/0003-ffmpegvideo-v4l2-request-route.patch @@ -21,13 +21,15 @@ This patch adds a sibling init path, `InitV4L2RequestDecoder`, that: the legacy AVCodec-per-hwaccel registration. ALARM, Debian, and most distros building with --enable-v4l2-request expose this (avcodec_find_decoder_by_name lookup). - - **generic codec + AV_HWDEVICE_TYPE_DRM** in `hw_configs`: - the modern hwaccel registration on some upstream-only ffmpeg - builds. + - **generic codec + hw_configs walk**: the modern hwaccel + registration. Accepts EITHER AV_HWDEVICE_TYPE_DRM (legacy + ffmpeg-v4l2-request-fork output prior to FFmpeg 7.1) OR + AV_HWDEVICE_TYPE_V4L2REQUEST (FFmpeg 7.1+ dedicated enum, + value 13 on Kwiboo's no-AMF tree, 14 on upstream-AMF tree). Probes named-codec first (explicit, portable) and falls back to - walking the generic codec's `hw_configs` for the DRM device type; - * creates an `AV_HWDEVICE_TYPE_DRM` hwdevice context bound to - `/dev/dri/renderD128` via the new `av_hwdevice_ctx_create` wrapper + walking the generic codec's `hw_configs` for either device type; + * creates an hwdevice context of the matched type bound to + `/dev/dri/renderD128` via the `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 @@ -40,7 +42,7 @@ vendor-MPP-stateful boards neither mechanism is registered for the codec, the function bails out, and the existing stateful `InitV4L2Decoder` runs as before. No regression of stateful boards. -`mDRMDeviceContext` is unconditionally `av_buffer_unref`'d in +`mV4L2RequestDeviceContext` is unconditionally `av_buffer_unref`'d in `ProcessShutdown` (no-op when null). Gated behind `media.ffmpeg.v4l2-request.enabled` from patch 4/4. @@ -49,25 +51,26 @@ 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 @@ +@@ -225,7 +225,13 @@ 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. ++ // libavcodec's v4l2_request hwaccel, which it surfaces via either ++ // AV_HWDEVICE_TYPE_DRM (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST ++ // (FFmpeg 7.1+ dedicated enum). + MediaResult InitV4L2RequestDecoder(); bool CreateVAAPIDeviceContext(); -+ bool CreateV4L2RequestDeviceContext(); ++ bool CreateV4L2RequestDeviceContext(int aDeviceType); bool GetVAAPISurfaceDescriptor(VADRMPRIMESurfaceDescriptor* aVaDesc); void AddAcceleratedFormats(nsTArray& aCodecList, AVCodecID aCodecID, AVVAAPIHWConfig* hwconfig); -@@ -239,7 +244,10 @@ +@@ -239,7 +245,10 @@ void AdjustHWDecodeLogging(); - + AVBufferRef* mVAAPIDeviceContext = nullptr; -+ // firefox-fourier: DRM hwdevice ctx for the v4l2_request hwaccel. -+ AVBufferRef* mDRMDeviceContext = nullptr; ++ // firefox-fourier: hwdevice ctx for the v4l2_request hwaccel. ++ AVBufferRef* mV4L2RequestDeviceContext = nullptr; bool mUsingV4L2 = false; + bool mUsingV4L2Request = false; // If video overlay is used we want to upload SW decoded frames to @@ -76,27 +79,33 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platfor diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-27 16:09:10.000000000 +0200 +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-29 00:10:00.098884335 +0200 -@@ -403,6 +403,129 @@ +@@ -403,6 +403,148 @@ 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::CreateV4L2RequestDeviceContext() { + ++// firefox-fourier: V4L2 stateless (request API) hwdevice context. ++// libavcodec's v4l2_request hwaccel binds via either AV_HWDEVICE_TYPE_DRM ++// (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST (FFmpeg 7.1+, enum value 13 ++// on Kwiboo's no-AMF tree, 14 on upstream-AMF tree). Caller passes the ++// matched type as an int (Mozilla's bundled libavutil headers may not ++// have the V4L2REQUEST enumerator). ++bool FFmpegVideoDecoder::CreateV4L2RequestDeviceContext( ++ int aDeviceType) { + 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); ++ if (mLib->av_hwdevice_ctx_create(&mV4L2RequestDeviceContext, ++ (enum AVHWDeviceType)aDeviceType, ++ drmDevice, nullptr, 0) < 0) { ++ FFMPEG_LOG(" av_hwdevice_ctx_create(type=%d, %s) failed", ++ aDeviceType, drmDevice); + return false; + } -+ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext); -+ FFMPEG_LOG(" DRM hwdevice ctx created on %s", drmDevice); ++ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mV4L2RequestDeviceContext); ++ FFMPEG_LOG(" v4l2_request hwdevice ctx created (type=%d) on %s", ++ aDeviceType, drmDevice); + return true; +} + @@ -113,13 +122,14 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + // mechanisms depending on the build: + // (a) Named AVCodec entry (h264_v4l2request, vp8_v4l2request, + // etc.) — the legacy mechanism. Each hwaccel is a standalone -+ // AVCodec, looked up by name. ALARM, Debian, and most distros -+ // building with --enable-v4l2-request expose this. ++ // AVCodec, looked up by name. Some forks expose this. + // (b) Modern hwaccel registration: the generic codec advertises -+ // AV_HWDEVICE_TYPE_DRM in its hw_configs array, and setting -+ // hw_device_ctx on the codec context binds v4l2_request -+ // internally. Some upstream-only builds expose this. -+ // Probe (a) first — it is the explicit, distro-portable lookup. ++ // AV_HWDEVICE_TYPE_DRM (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST ++ // (FFmpeg 7.1+ dedicated type, enum value 13 or 14 depending ++ // on whether AMF is in the enum) in its hw_configs array, and ++ // setting hw_device_ctx on the codec context binds v4l2_request ++ // internally. ++ // Probe (a) first — explicit, distro-portable lookup. + // Fall back to (b) when the named entry isn't registered. + const char* requestName = nullptr; + switch (mCodecID) { @@ -134,8 +144,18 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + return NS_ERROR_NOT_AVAILABLE; + } + -+ AVCodec* codec = mLib->avcodec_find_decoder_by_name(requestName); -+ if (codec) { ++ // AV_HWDEVICE_TYPE_V4L2REQUEST integer values across known builds. ++ // Kwiboo's v4l2-request-n7.1.3 tree (no AMF) puts it at 13; ++ // upstream FFmpeg 8.x with AMF puts it at 14. ++ const int V4L2REQUEST_KWIBOO = 13; ++ const int V4L2REQUEST_UPSTREAM = 14; ++ ++ AVCodec* codec = nullptr; ++ int matchedType = AV_HWDEVICE_TYPE_DRM; ++ ++ AVCodec* named = mLib->avcodec_find_decoder_by_name(requestName); ++ if (named) { ++ codec = named; + FFMPEG_LOG(" using named v4l2_request codec %s", requestName); + } else { + AVCodec* generic = mLib->avcodec_find_decoder(mCodecID); @@ -143,9 +163,16 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + for (int i = 0;; i++) { + const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(generic, i); + if (!cfg) break; -+ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM) { ++ if (!(cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) { ++ continue; ++ } ++ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM || ++ (int)cfg->device_type == V4L2REQUEST_KWIBOO || ++ (int)cfg->device_type == V4L2REQUEST_UPSTREAM) { + codec = generic; -+ FFMPEG_LOG(" using generic codec %s with DRM hwaccel", codec->name); ++ matchedType = (int)cfg->device_type; ++ FFMPEG_LOG(" using generic codec %s with v4l2_request hwaccel " ++ "(device_type=%d)", codec->name, matchedType); + break; + } + } @@ -153,9 +180,9 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + } + + if (!codec) { -+ FFMPEG_LOG(" no v4l2_request path for codec ID %d \u2014 neither named " -+ "codec %s nor generic codec with DRM hwaccel available " -+ "(libavcodec built without --enable-v4l2-request?)", ++ FFMPEG_LOG(" no v4l2_request path for codec ID %d — neither named " ++ "codec %s nor generic codec with DRM/V4L2REQUEST hwaccel " ++ "available (libavcodec built without --enable-v4l2-request?)", + mCodecID, requestName); + return NS_ERROR_NOT_AVAILABLE; + } @@ -176,7 +203,7 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + auto releaseDecoder = MakeScopeExit( + [&]() MOZ_NO_THREAD_SAFETY_ANALYSIS { ReleaseCodecContext(); }); + -+ if (!CreateV4L2RequestDeviceContext()) { ++ if (!CreateV4L2RequestDeviceContext(matchedType)) { + return NS_ERROR_NOT_AVAILABLE; + } + @@ -205,10 +232,10 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + MediaResult FFmpegVideoDecoder::InitV4L2Decoder() { FFMPEG_LOG("Initialising V4L2-DRM FFmpeg decoder"); - -@@ -656,6 +779,16 @@ + +@@ -656,6 +798,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 @@ -223,14 +250,14 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf // VAAPI didn't work or is disabled, so try V4L2 with DRM if (NS_SUCCEEDED(InitV4L2Decoder())) { return; -@@ -2046,6 +2179,11 @@ +@@ -2046,6 +2198,11 @@ if (IsHardwareAccelerated()) { mLib->av_buffer_unref(&mVAAPIDeviceContext); } -+ // firefox-fourier: release the DRM hwdevice ctx for the v4l2_request ++ // firefox-fourier: release the 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); ++ if (mV4L2RequestDeviceContext) { ++ mLib->av_buffer_unref(&mV4L2RequestDeviceContext); + } #endif #ifdef MOZ_ENABLE_D3D11VA -- 2.47.3