PR #23351 opened by JuliusBairaktaris
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23351
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23351.patch
Fixes the `sr_amf` filter emitting a **solid green frame** when
`algorithm=sr1-1` (AMF VideoSR1.1).
### Root cause
Per AMD's `AMF_HQ_Scaler_API.md`, VideoSR1.1 only runs on a DX11/DX12 engine
and does **not** accept NV12/P010 (it needs packed RGB:
BGRA/RGBA/R10G10B10A2/RGBA_F16). The filter advertised NV12/P010 and passed the
input format straight to `AMFHQScaler::Init()`, which returns `AMF_OK` even for
the unsupported format — so the existing result check never fired and the
output was green.
### Changes
- `vf_sr_amf.c`: when `algorithm=sr1-1`, restrict the negotiated pixel formats
to RGBA so libavfilter auto-inserts a converter for YUV input.
- `vf_sr_amf.c`: reject an NV12/P010-backed hardware surface explicitly in
`config_output` instead of silently producing green.
- `doc/filters.texi`: document the `sr1-1` format/device requirement and the
alpha caveat.
### Testing
Built with `--enable-amf` and runtime-tested on Windows (Radeon 840M, DX11):
ffmpeg -init_hw_device amf -f lavfi -i testsrc2=size=1280x720 \
-vf "sr_amf=w=2560:h=1440:algorithm=sr1-1,hwdownload,format=rgba"
-frames:v 1 out.png
| `algorithm=sr1-1` | RGB mean (R/G/B) | std | distinct colors |
|---|---|---|---|
| before (unpatched) | 0 / 136 / 0 (solid green) | 0 | 1 |
| after (patched) | 123 / 130 / 124 | ~124 | 2200+ |
After the fix the output matches the known-good algorithms (bilinear / bicubic
/ point / sr1-0).
### Note on alpha
AMF's VideoSR algorithms (`sr1-0` and `sr1-1`) leave the alpha channel zeroed
and expose no property to control it (the basic algorithms preserve it). Append
e.g. `format=rgb24` downstream for an opaque result.
No new FATE samples required.
Refs: AMD `AMF_HQ_Scaler_API.md`, mpv-player/mpv#18068
From 8bf18bf0401dc57803f7fe34d07a847ab7810228 Mon Sep 17 00:00:00 2001
From: Julius Bairaktaris <[email protected]>
Date: Thu, 4 Jun 2026 23:53:01 +0200
Subject: [PATCH] avfilter/vf_sr_amf: fix solid green frame with
algorithm=sr1-1
Per AMD's AMF_HQ_Scaler_API.md, the HQ Scaler's VideoSR1.1 algorithm is
only supported on a DX11/DX12 engine and with input/output formats other
than NV12 or P010 (it accepts packed RGB: BGRA, RGBA, R10G10B10A2 or
RGBA_F16). The filter however advertised NV12/P010 as valid input and
passed the input format straight to AMFHQScaler::Init(), which returns
AMF_OK even for the unsupported format. The existing result check
therefore never fired and the filter silently emitted a solid green
frame.
When algorithm=sr1-1, restrict the negotiated formats to RGBA, the packed
RGB format that round-trips cleanly through the AMF hwcontext (both upload
and hwdownload), so a converter is auto-inserted for YUV input, and reject
an unsupported hardware surface explicitly in config_output instead of
producing green.
Note that AMF's VideoSR algorithms (sr1-0 and sr1-1) leave the alpha
channel zeroed and expose no property to control it; drop alpha
downstream, e.g. with format=rgb24, for an opaque result.
Refs AMD AMF_HQ_Scaler_API.md and mpv-player/mpv#18068.
Signed-off-by: Julius Bairaktaris <[email protected]>
---
doc/filters.texi | 6 ++++++
libavfilter/vf_sr_amf.c | 38 +++++++++++++++++++++++++++++++++++---
2 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 2cae41c7c5..1a4314e5f9 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -22947,6 +22947,12 @@ Point
@item sr1-1
Video SR1.1
+This algorithm only supports packed RGB formats and requires a DirectX 11 or
+DirectX 12 device, so it is available on Windows only. Inputs in other formats
+such as @code{nv12} or @code{p010} are converted to @code{rgba} automatically.
+Note that the VideoSR algorithms (@code{sr1-0} and @code{sr1-1}) do not
+preserve the alpha channel (it is left zeroed); append e.g. @code{format=rgb24}
+downstream if an opaque result is required.
@end table
diff --git a/libavfilter/vf_sr_amf.c b/libavfilter/vf_sr_amf.c
index 8f3ae7ed80..a0be23d114 100644
--- a/libavfilter/vf_sr_amf.c
+++ b/libavfilter/vf_sr_amf.c
@@ -54,8 +54,9 @@
static int amf_filter_query_formats(AVFilterContext *avctx)
{
- const enum AVPixelFormat *output_pix_fmts;
- static const enum AVPixelFormat input_pix_fmts[] = {
+ AMFFilterContext *ctx = avctx->priv;
+ const enum AVPixelFormat *input_pix_fmts, *output_pix_fmts;
+ static const enum AVPixelFormat input_pix_fmts_default[] = {
AV_PIX_FMT_NV12,
AV_PIX_FMT_P010,
AV_PIX_FMT_BGRA,
@@ -75,7 +76,24 @@ static int amf_filter_query_formats(AVFilterContext *avctx)
AV_PIX_FMT_RGBAF16,
AV_PIX_FMT_NONE,
};
- output_pix_fmts = output_pix_fmts_default;
+ // VideoSR1.1 supports only RGB (BGRA, RGBA, R10G10B10A2, RGBA_F16) on
+ // DX11/DX12, not NV12/P010 (AMF_HQ_Scaler_API.md). Negotiate RGBA, the
+ // packed RGB format that round-trips cleanly through the AMF hwcontext
+ // (both upload and hwdownload), so a converter is inserted for YUV input.
+ // AMF_SURFACE keeps the hardware path; config_output rejects NV12/P010.
+ static const enum AVPixelFormat pix_fmts_sr1_1[] = {
+ AV_PIX_FMT_RGBA,
+ AV_PIX_FMT_AMF_SURFACE,
+ AV_PIX_FMT_NONE,
+ };
+
+ if (ctx->algorithm == AMF_HQ_SCALER_ALGORITHM_VIDEOSR1_1) {
+ input_pix_fmts = pix_fmts_sr1_1;
+ output_pix_fmts = pix_fmts_sr1_1;
+ } else {
+ input_pix_fmts = input_pix_fmts_default;
+ output_pix_fmts = output_pix_fmts_default;
+ }
return amf_setup_input_output_formats(avctx, input_pix_fmts,
output_pix_fmts);
}
@@ -94,6 +112,20 @@ static int amf_filter_config_output(AVFilterLink *outlink)
if (err < 0)
return err;
+ // VideoSR1.1 requires a packed RGB surface and does not support NV12/P010.
+ // The format restriction in query_formats inserts a converter for software
+ // input, but a hardware AMF surface backed by NV12/P010 can still reach
here,
+ // so reject it explicitly instead of silently producing a green frame.
+ if (ctx->algorithm == AMF_HQ_SCALER_ALGORITHM_VIDEOSR1_1 &&
+ (in_format == AV_PIX_FMT_NV12 || in_format == AV_PIX_FMT_P010)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "sr1-1 (VideoSR1.1) requires a packed RGB format (rgba); "
+ "%s is not supported. Convert the input first (e.g.
format=rgba) or "
+ "select another algorithm.\n",
+ av_get_pix_fmt_name(in_format));
+ return AVERROR(EINVAL);
+ }
+
// HQ scaler should be used for upscaling only
if (inlink->w > outlink->w || inlink->h > outlink->h) {
av_log(avctx, AV_LOG_ERROR, "AMF HQ scaler should be used for
upscaling only.\n");
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]