firefox-fourier patch #3: accept AV_HWDEVICE_TYPE_V4L2REQUEST too #61
@@ -21,13 +21,15 @@ This patch adds a sibling init path, `InitV4L2RequestDecoder`, that:
|
|||||||
the legacy AVCodec-per-hwaccel registration. ALARM, Debian,
|
the legacy AVCodec-per-hwaccel registration. ALARM, Debian,
|
||||||
and most distros building with --enable-v4l2-request expose
|
and most distros building with --enable-v4l2-request expose
|
||||||
this (avcodec_find_decoder_by_name lookup).
|
this (avcodec_find_decoder_by_name lookup).
|
||||||
- **generic codec + AV_HWDEVICE_TYPE_DRM** in `hw_configs`:
|
- **generic codec + hw_configs walk**: the modern hwaccel
|
||||||
the modern hwaccel registration on some upstream-only ffmpeg
|
registration. Accepts EITHER AV_HWDEVICE_TYPE_DRM (legacy
|
||||||
builds.
|
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
|
Probes named-codec first (explicit, portable) and falls back to
|
||||||
walking the generic codec's `hw_configs` for the DRM device type;
|
walking the generic codec's `hw_configs` for either device type;
|
||||||
* creates an `AV_HWDEVICE_TYPE_DRM` hwdevice context bound to
|
* creates an hwdevice context of the matched type bound to
|
||||||
`/dev/dri/renderD128` via the new `av_hwdevice_ctx_create` wrapper
|
`/dev/dri/renderD128` via the `av_hwdevice_ctx_create` wrapper
|
||||||
(patch 2/4) and attaches it to the codec context;
|
(patch 2/4) and attaches it to the codec context;
|
||||||
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
|
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
|
||||||
(already returns `AV_PIX_FMT_DRM_PRIME`) and the existing
|
(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
|
codec, the function bails out, and the existing stateful
|
||||||
`InitV4L2Decoder` runs as before. No regression of stateful boards.
|
`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
|
`ProcessShutdown` (no-op when null). Gated behind
|
||||||
`media.ffmpeg.v4l2-request.enabled` from patch 4/4.
|
`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
|
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
|
--- 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
|
+++ 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;
|
bool IsLinuxHDR() const;
|
||||||
MediaResult InitVAAPIDecoder();
|
MediaResult InitVAAPIDecoder();
|
||||||
MediaResult InitV4L2Decoder();
|
MediaResult InitV4L2Decoder();
|
||||||
+ // firefox-fourier: V4L2 stateless (request API) decode path. Uses
|
+ // firefox-fourier: V4L2 stateless (request API) decode path. Uses
|
||||||
+ // libavcodec's v4l2_request hwaccel, which it surfaces via
|
+ // libavcodec's v4l2_request hwaccel, which it surfaces via either
|
||||||
+ // AV_HWDEVICE_TYPE_DRM rather than a dedicated _V4L2REQUEST type.
|
+ // AV_HWDEVICE_TYPE_DRM (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST
|
||||||
|
+ // (FFmpeg 7.1+ dedicated enum).
|
||||||
+ MediaResult InitV4L2RequestDecoder();
|
+ MediaResult InitV4L2RequestDecoder();
|
||||||
bool CreateVAAPIDeviceContext();
|
bool CreateVAAPIDeviceContext();
|
||||||
+ bool CreateV4L2RequestDeviceContext();
|
+ bool CreateV4L2RequestDeviceContext(int aDeviceType);
|
||||||
bool GetVAAPISurfaceDescriptor(VADRMPRIMESurfaceDescriptor* aVaDesc);
|
bool GetVAAPISurfaceDescriptor(VADRMPRIMESurfaceDescriptor* aVaDesc);
|
||||||
void AddAcceleratedFormats(nsTArray<AVCodecID>& aCodecList,
|
void AddAcceleratedFormats(nsTArray<AVCodecID>& aCodecList,
|
||||||
AVCodecID aCodecID, AVVAAPIHWConfig* hwconfig);
|
AVCodecID aCodecID, AVVAAPIHWConfig* hwconfig);
|
||||||
@@ -239,7 +244,10 @@
|
@@ -239,7 +245,10 @@
|
||||||
void AdjustHWDecodeLogging();
|
void AdjustHWDecodeLogging();
|
||||||
|
|
||||||
AVBufferRef* mVAAPIDeviceContext = nullptr;
|
AVBufferRef* mVAAPIDeviceContext = nullptr;
|
||||||
+ // firefox-fourier: DRM hwdevice ctx for the v4l2_request hwaccel.
|
+ // firefox-fourier: hwdevice ctx for the v4l2_request hwaccel.
|
||||||
+ AVBufferRef* mDRMDeviceContext = nullptr;
|
+ AVBufferRef* mV4L2RequestDeviceContext = nullptr;
|
||||||
bool mUsingV4L2 = false;
|
bool mUsingV4L2 = false;
|
||||||
+ bool mUsingV4L2Request = false;
|
+ bool mUsingV4L2Request = false;
|
||||||
// If video overlay is used we want to upload SW decoded frames to
|
// 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
|
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
|
--- 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
|
+++ 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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
+// firefox-fourier: V4L2 stateless (request API) DRM hwdevice context.
|
+// firefox-fourier: V4L2 stateless (request API) hwdevice context.
|
||||||
+// libavcodec's v4l2_request hwaccel binds via AV_HWDEVICE_TYPE_DRM —
|
+// libavcodec's v4l2_request hwaccel binds via either AV_HWDEVICE_TYPE_DRM
|
||||||
+// no dedicated _V4L2REQUEST type exists upstream.
|
+// (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST (FFmpeg 7.1+, enum value 13
|
||||||
+bool FFmpegVideoDecoder<LIBAV_VER>::CreateV4L2RequestDeviceContext() {
|
+// 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<LIBAV_VER>::CreateV4L2RequestDeviceContext(
|
||||||
|
+ int aDeviceType) {
|
||||||
+ if (!mLib->av_hwdevice_ctx_create) {
|
+ if (!mLib->av_hwdevice_ctx_create) {
|
||||||
+ FFMPEG_LOG(" av_hwdevice_ctx_create not available (libavutil too old)");
|
+ FFMPEG_LOG(" av_hwdevice_ctx_create not available (libavutil too old)");
|
||||||
+ return false;
|
+ return false;
|
||||||
+ }
|
+ }
|
||||||
+ const char* drmDevice = "/dev/dri/renderD128";
|
+ const char* drmDevice = "/dev/dri/renderD128";
|
||||||
+ if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
|
+ if (mLib->av_hwdevice_ctx_create(&mV4L2RequestDeviceContext,
|
||||||
+ AV_HWDEVICE_TYPE_DRM, drmDevice,
|
+ (enum AVHWDeviceType)aDeviceType,
|
||||||
+ nullptr, 0) < 0) {
|
+ drmDevice, nullptr, 0) < 0) {
|
||||||
+ FFMPEG_LOG(" av_hwdevice_ctx_create(DRM, %s) failed", drmDevice);
|
+ FFMPEG_LOG(" av_hwdevice_ctx_create(type=%d, %s) failed",
|
||||||
|
+ aDeviceType, drmDevice);
|
||||||
+ return false;
|
+ return false;
|
||||||
+ }
|
+ }
|
||||||
+ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext);
|
+ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mV4L2RequestDeviceContext);
|
||||||
+ FFMPEG_LOG(" DRM hwdevice ctx created on %s", drmDevice);
|
+ FFMPEG_LOG(" v4l2_request hwdevice ctx created (type=%d) on %s",
|
||||||
|
+ aDeviceType, drmDevice);
|
||||||
+ return true;
|
+ return true;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
@@ -113,13 +122,14 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+ // mechanisms depending on the build:
|
+ // mechanisms depending on the build:
|
||||||
+ // (a) Named AVCodec entry (h264_v4l2request, vp8_v4l2request,
|
+ // (a) Named AVCodec entry (h264_v4l2request, vp8_v4l2request,
|
||||||
+ // etc.) — the legacy mechanism. Each hwaccel is a standalone
|
+ // etc.) — the legacy mechanism. Each hwaccel is a standalone
|
||||||
+ // AVCodec, looked up by name. ALARM, Debian, and most distros
|
+ // AVCodec, looked up by name. Some forks expose this.
|
||||||
+ // building with --enable-v4l2-request expose this.
|
|
||||||
+ // (b) Modern hwaccel registration: the generic codec advertises
|
+ // (b) Modern hwaccel registration: the generic codec advertises
|
||||||
+ // AV_HWDEVICE_TYPE_DRM in its hw_configs array, and setting
|
+ // AV_HWDEVICE_TYPE_DRM (legacy) or AV_HWDEVICE_TYPE_V4L2REQUEST
|
||||||
+ // hw_device_ctx on the codec context binds v4l2_request
|
+ // (FFmpeg 7.1+ dedicated type, enum value 13 or 14 depending
|
||||||
+ // internally. Some upstream-only builds expose this.
|
+ // on whether AMF is in the enum) in its hw_configs array, and
|
||||||
+ // Probe (a) first — it is the explicit, distro-portable lookup.
|
+ // 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.
|
+ // Fall back to (b) when the named entry isn't registered.
|
||||||
+ const char* requestName = nullptr;
|
+ const char* requestName = nullptr;
|
||||||
+ switch (mCodecID) {
|
+ switch (mCodecID) {
|
||||||
@@ -134,8 +144,18 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+ return NS_ERROR_NOT_AVAILABLE;
|
+ return NS_ERROR_NOT_AVAILABLE;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ AVCodec* codec = mLib->avcodec_find_decoder_by_name(requestName);
|
+ // AV_HWDEVICE_TYPE_V4L2REQUEST integer values across known builds.
|
||||||
+ if (codec) {
|
+ // 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);
|
+ FFMPEG_LOG(" using named v4l2_request codec %s", requestName);
|
||||||
+ } else {
|
+ } else {
|
||||||
+ AVCodec* generic = mLib->avcodec_find_decoder(mCodecID);
|
+ 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++) {
|
+ for (int i = 0;; i++) {
|
||||||
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(generic, i);
|
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(generic, i);
|
||||||
+ if (!cfg) break;
|
+ 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;
|
+ 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;
|
+ break;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
@@ -153,9 +180,9 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (!codec) {
|
+ if (!codec) {
|
||||||
+ FFMPEG_LOG(" no v4l2_request path for codec ID %d \u2014 neither named "
|
+ FFMPEG_LOG(" no v4l2_request path for codec ID %d — neither named "
|
||||||
+ "codec %s nor generic codec with DRM hwaccel available "
|
+ "codec %s nor generic codec with DRM/V4L2REQUEST hwaccel "
|
||||||
+ "(libavcodec built without --enable-v4l2-request?)",
|
+ "available (libavcodec built without --enable-v4l2-request?)",
|
||||||
+ mCodecID, requestName);
|
+ mCodecID, requestName);
|
||||||
+ return NS_ERROR_NOT_AVAILABLE;
|
+ 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(
|
+ auto releaseDecoder = MakeScopeExit(
|
||||||
+ [&]() MOZ_NO_THREAD_SAFETY_ANALYSIS { ReleaseCodecContext(); });
|
+ [&]() MOZ_NO_THREAD_SAFETY_ANALYSIS { ReleaseCodecContext(); });
|
||||||
+
|
+
|
||||||
+ if (!CreateV4L2RequestDeviceContext()) {
|
+ if (!CreateV4L2RequestDeviceContext(matchedType)) {
|
||||||
+ return NS_ERROR_NOT_AVAILABLE;
|
+ return NS_ERROR_NOT_AVAILABLE;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@@ -205,10 +232,10 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+
|
+
|
||||||
MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2Decoder() {
|
MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2Decoder() {
|
||||||
FFMPEG_LOG("Initialising V4L2-DRM FFmpeg decoder");
|
FFMPEG_LOG("Initialising V4L2-DRM FFmpeg decoder");
|
||||||
|
|
||||||
@@ -656,6 +779,16 @@
|
@@ -656,6 +798,16 @@
|
||||||
# endif // MOZ_ENABLE_VAAPI
|
# endif // MOZ_ENABLE_VAAPI
|
||||||
|
|
||||||
# ifdef MOZ_ENABLE_V4L2
|
# ifdef MOZ_ENABLE_V4L2
|
||||||
+ // firefox-fourier: try V4L2 stateless (request API) first. On
|
+ // firefox-fourier: try V4L2 stateless (request API) first. On
|
||||||
+ // mainline-Linux Rockchip boards (RK3399 rkvdec, RK3566/RK3588
|
+ // 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
|
// VAAPI didn't work or is disabled, so try V4L2 with DRM
|
||||||
if (NS_SUCCEEDED(InitV4L2Decoder())) {
|
if (NS_SUCCEEDED(InitV4L2Decoder())) {
|
||||||
return;
|
return;
|
||||||
@@ -2046,6 +2179,11 @@
|
@@ -2046,6 +2198,11 @@
|
||||||
if (IsHardwareAccelerated()) {
|
if (IsHardwareAccelerated()) {
|
||||||
mLib->av_buffer_unref(&mVAAPIDeviceContext);
|
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.
|
+ // hwaccel. Always safe — av_buffer_unref no-ops on a null pointer.
|
||||||
+ if (mDRMDeviceContext) {
|
+ if (mV4L2RequestDeviceContext) {
|
||||||
+ mLib->av_buffer_unref(&mDRMDeviceContext);
|
+ mLib->av_buffer_unref(&mV4L2RequestDeviceContext);
|
||||||
+ }
|
+ }
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_ENABLE_D3D11VA
|
#ifdef MOZ_ENABLE_D3D11VA
|
||||||
|
|||||||
Reference in New Issue
Block a user