This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 35660a244de7b9a26bbaaf2cd2bd2ab95d3169c7
Author:     Julius Bairaktaris <[email protected]>
AuthorDate: Mon Aug 31 16:08:25 2026 +0200
Commit:     ArazIusubov <[email protected]>
CommitDate: Wed Sep 16 22:05:28 2026 +0000

    avfilter/amf: advertise only AMF surfaces on the output link
    
    amf_init_filter_config() always creates an AV_PIX_FMT_AMF_SURFACE frames
    context and amf_amfsurface_to_avframe() allocates every output frame from
    it, so an AMF filter returns an AMF surface no matter what the output link
    negotiated. The output format lists offered software formats and, for a
    D3D11VA or DXVA2 device, the foreign hardware format, so a downstream
    filter that takes one of them made the link agree on a format the filter
    never produces:
    
      ffmpeg -f lavfi -i testsrc2,format=nv12 \
             -vf vpp_amf=w=320:h=180:format=nv12,signalstats -f null -
    
    crashes, because signalstats reads an AMFSurface pointer as an NV12 plane.
    The frame carries the right format, so it is only the link that lies, but
    nothing downstream looks at that.
    
    Offer AV_PIX_FMT_AMF_SURFACE alone, which is what the hardware filters in
    the tree do. A software consumer now needs an explicit hwdownload, which
    was already the only way to get a correct software frame out of these
    filters, and negotiation fails at configuration time instead of handing
    out a mislabelled surface. The device type still selects the input format,
    where D3D11 and DXVA2 surfaces really are what the filter is handed.
    
    The documentation examples and the sr_amf note on the zeroed alpha channel
    followed the filter with a software format directly, which no longer forms
    a valid chain; they now name the download and the frames context format
    first.
    
    Tested on Windows 11, RX 9070 XT, driver 32.0.31041.1004: the case above
    now fails to configure instead of crashing, and vpp_amf, vqe_amf, frc_amf
    and sr_amf keep working with software, AMF, D3D11VA and DXVA2 input, into
    hwdownload and into h264_amf and hevc_amf.
    
    Assisted-by: Claude Opus 5
    Assisted-by: Claude Fable 5.1
    Signed-off-by: Julius Bairaktaris <[email protected]>
---
 doc/filters.texi            | 15 ++++++++++-----
 libavfilter/vf_amf_common.c |  9 +++++----
 libavfilter/vf_amf_common.h |  2 +-
 libavfilter/vf_frc_amf.c    | 14 +-------------
 libavfilter/vf_sr_amf.c     | 29 +++++++----------------------
 libavfilter/vf_vpp_amf.c    | 13 +------------
 libavfilter/vf_vqe_amf.c    | 10 +---------
 7 files changed, 26 insertions(+), 66 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 070df58779..0407c46917 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -23286,8 +23286,9 @@ DirectX 12 device, so it is available on Windows only. 
Inputs in other formats
 such as @code{nv12} or @code{p010} are converted to a packed RGB format
 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.
+preserve the alpha channel (it is left zeroed); drop it after the download,
+e.g. with @code{hwdownload,format=rgba,format=rgb24}, if an opaque result is
+required.
 
 @end table
 
@@ -23322,9 +23323,11 @@ which does not fill the entire output surface should 
be filled with a solid colo
 
 @itemize
 @item
-Scale input to 720p, keeping aspect ratio and ensuring the output is yuv420p.
+Upscale to 720p, keeping aspect ratio, and read the result back into system
+memory. The filter always outputs AMF surfaces, so a @ref{hwdownload} is needed
+to feed a software encoder.
 @example
-sr_amf=-2:720:format=yuv420p
+sr_amf=-2:720,hwdownload,format=nv12
 @end example
 
 @item
@@ -26228,8 +26231,10 @@ JEDEC P22 phosphors
 @itemize
 @item
 Scale input to 720p, keeping aspect ratio and ensuring the output is yuv420p.
+The filter always outputs AMF surfaces, so a @ref{hwdownload} is needed to 
feed a
+software encoder.
 @example
-vpp_amf=-2:720:format=yuv420p
+vpp_amf=-2:720:format=yuv420p,hwdownload,format=yuv420p
 @end example
 
 @item
diff --git a/libavfilter/vf_amf_common.c b/libavfilter/vf_amf_common.c
index 2d70d6d954..b3a18ed9b1 100644
--- a/libavfilter/vf_amf_common.c
+++ b/libavfilter/vf_amf_common.c
@@ -221,12 +221,15 @@ fail:
 
 
 int amf_setup_input_output_formats(AVFilterContext *avctx,
-                                    const enum AVPixelFormat *input_pix_fmts,
-                                    const enum AVPixelFormat *output_pix_fmts)
+                                    const enum AVPixelFormat *input_pix_fmts)
 {
     int err;
     AVFilterFormats *input_formats;
     AVFilterFormats *output_formats;
+    static const enum AVPixelFormat output_pix_fmts[] = {
+        AV_PIX_FMT_AMF_SURFACE,
+        AV_PIX_FMT_NONE,
+    };
 
     //in case if hw_device_ctx is set to DXVA2 we change order of pixel 
formats to set DXVA2 be chosen by default
     //The order is ignored if hw_frames_ctx is not NULL on the config_output 
stage
@@ -242,7 +245,6 @@ int amf_setup_input_output_formats(AVFilterContext *avctx,
                     AV_PIX_FMT_NONE,
                 };
                 input_pix_fmts  = pix_fmts_d3d11;
-                output_pix_fmts = pix_fmts_d3d11;
             }
             break;
     #endif
@@ -254,7 +256,6 @@ int amf_setup_input_output_formats(AVFilterContext *avctx,
                     AV_PIX_FMT_NONE,
                 };
                 input_pix_fmts  = pix_fmts_dxva2;
-                output_pix_fmts = pix_fmts_dxva2;
             }
             break;
     #endif
diff --git a/libavfilter/vf_amf_common.h b/libavfilter/vf_amf_common.h
index eedaef7ba6..4910b23e9b 100644
--- a/libavfilter/vf_amf_common.h
+++ b/libavfilter/vf_amf_common.h
@@ -79,7 +79,7 @@ int amf_copy_surface(AVFilterContext *avctx, const AVFrame 
*frame, AMFSurface* s
 void amf_free_amfsurface(void *opaque, uint8_t *data);
 AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, AMFSurface* 
pSurface);
 int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, 
AMFSurface** ppSurface);
-int amf_setup_input_output_formats(AVFilterContext *avctx, const enum 
AVPixelFormat *input_pix_fmts, const enum AVPixelFormat *output_pix_fmts);
+int amf_setup_input_output_formats(AVFilterContext *avctx, const enum 
AVPixelFormat *input_pix_fmts);
 int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in);
 
 #endif /* AVFILTER_AMF_COMMON_H */
diff --git a/libavfilter/vf_frc_amf.c b/libavfilter/vf_frc_amf.c
index 1a84a2ee4f..c05ab818e8 100644
--- a/libavfilter/vf_frc_amf.c
+++ b/libavfilter/vf_frc_amf.c
@@ -67,7 +67,6 @@ static int amf_frc_init(AVFilterContext *avctx) {
 
 static int amf_filter_query_formats(AVFilterContext *avctx)
 {
-    const enum AVPixelFormat *output_pix_fmts;
     static const enum AVPixelFormat input_pix_fmts[] = {
         AV_PIX_FMT_AMF_SURFACE,
         AV_PIX_FMT_D3D11,
@@ -80,19 +79,8 @@ static int amf_filter_query_formats(AVFilterContext *avctx)
         AV_PIX_FMT_X2BGR10,
         AV_PIX_FMT_NONE,
     };
-    static const enum AVPixelFormat output_pix_fmts_default[] = {
-        AV_PIX_FMT_AMF_SURFACE,
-        AV_PIX_FMT_NV12,
-        AV_PIX_FMT_P010,
-        AV_PIX_FMT_BGRA,
-        AV_PIX_FMT_RGBA,
-        AV_PIX_FMT_RGBAF16,
-        AV_PIX_FMT_X2BGR10,
-        AV_PIX_FMT_NONE,
-    };
-    output_pix_fmts = output_pix_fmts_default;
 
-    return amf_setup_input_output_formats(avctx, input_pix_fmts, 
output_pix_fmts);
+    return amf_setup_input_output_formats(avctx, input_pix_fmts);
 }
 
 static int amf_frc_filter_config_output(AVFilterLink *outlink)
diff --git a/libavfilter/vf_sr_amf.c b/libavfilter/vf_sr_amf.c
index 8ecfcbb1fe..0d8ba40b31 100644
--- a/libavfilter/vf_sr_amf.c
+++ b/libavfilter/vf_sr_amf.c
@@ -68,7 +68,7 @@ static int amf_is_packed_rgb(enum AVPixelFormat format)
 static int amf_filter_query_formats(AVFilterContext *avctx)
 {
     AMFFilterContext *ctx = avctx->priv;
-    const enum AVPixelFormat *input_pix_fmts, *output_pix_fmts;
+    const enum AVPixelFormat *input_pix_fmts;
     static const enum AVPixelFormat input_pix_fmts_default[] = {
         AV_PIX_FMT_NV12,
         AV_PIX_FMT_P010,
@@ -80,17 +80,6 @@ static int amf_filter_query_formats(AVFilterContext *avctx)
         AV_PIX_FMT_RGBAF16,
         AV_PIX_FMT_NONE,
     };
-    static const enum AVPixelFormat output_pix_fmts_default[] = {
-        AV_PIX_FMT_NV12,
-        AV_PIX_FMT_P010,
-        AV_PIX_FMT_BGRA,
-        AV_PIX_FMT_RGBA,
-        AV_PIX_FMT_AMF_SURFACE,
-        AV_PIX_FMT_D3D11,
-        AV_PIX_FMT_DXVA2_VLD,
-        AV_PIX_FMT_RGBAF16,
-        AV_PIX_FMT_NONE,
-    };
     // sr1-1 and point need packed RGB; YUV is converted on the GPU
     static const enum AVPixelFormat pix_fmts_packed_rgb[] = {
         AV_PIX_FMT_RGBA,
@@ -111,26 +100,22 @@ static int amf_filter_query_formats(AVFilterContext 
*avctx)
     };
     int i;
 
-    if (amf_hq_scaler_needs_packed_rgb(ctx->algorithm)) {
-        input_pix_fmts  = pix_fmts_packed_rgb;
-        output_pix_fmts = pix_fmts_packed_rgb;
-    } else {
-        input_pix_fmts  = input_pix_fmts_default;
-        output_pix_fmts = output_pix_fmts_default;
-    }
+    if (amf_hq_scaler_needs_packed_rgb(ctx->algorithm))
+        input_pix_fmts = pix_fmts_packed_rgb;
+    else
+        input_pix_fmts = input_pix_fmts_default;
 
     if (ctx->format_opt != AV_PIX_FMT_NONE) {
         for (i = 0; input_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
             if (input_pix_fmts[i] == ctx->format_opt) {
                 pix_fmts_requested[0] = ctx->format_opt;
-                input_pix_fmts  = pix_fmts_requested;
-                output_pix_fmts = pix_fmts_requested;
+                input_pix_fmts = pix_fmts_requested;
                 break;
             }
         }
     }
 
-    return amf_setup_input_output_formats(avctx, input_pix_fmts, 
output_pix_fmts);
+    return amf_setup_input_output_formats(avctx, input_pix_fmts);
 }
 
 static int amf_filter_config_output(AVFilterLink *outlink)
diff --git a/libavfilter/vf_vpp_amf.c b/libavfilter/vf_vpp_amf.c
index f9ed2dc635..970bb770a1 100644
--- a/libavfilter/vf_vpp_amf.c
+++ b/libavfilter/vf_vpp_amf.c
@@ -46,7 +46,6 @@
 
 static int amf_filter_query_formats(AVFilterContext *avctx)
 {
-    const enum AVPixelFormat *output_pix_fmts;
     static const enum AVPixelFormat input_pix_fmts[] = {
         AV_PIX_FMT_AMF_SURFACE,
         AV_PIX_FMT_D3D11,
@@ -58,18 +57,8 @@ static int amf_filter_query_formats(AVFilterContext *avctx)
         AV_PIX_FMT_YUV420P,
         AV_PIX_FMT_NONE,
     };
-    static const enum AVPixelFormat output_pix_fmts_default[] = {
-        AV_PIX_FMT_AMF_SURFACE,
-        AV_PIX_FMT_D3D11,
-        AV_PIX_FMT_DXVA2_VLD,
-        AV_PIX_FMT_NV12,
-        AV_PIX_FMT_BGRA,
-        AV_PIX_FMT_YUV420P,
-        AV_PIX_FMT_NONE,
-    };
-    output_pix_fmts = output_pix_fmts_default;
 
-    return amf_setup_input_output_formats(avctx, input_pix_fmts, 
output_pix_fmts);
+    return amf_setup_input_output_formats(avctx, input_pix_fmts);
 }
 
 static int amf_filter_config_output(AVFilterLink *outlink)
diff --git a/libavfilter/vf_vqe_amf.c b/libavfilter/vf_vqe_amf.c
index 63febf5c15..e36492645d 100644
--- a/libavfilter/vf_vqe_amf.c
+++ b/libavfilter/vf_vqe_amf.c
@@ -62,7 +62,6 @@ static int amf_vqe_init(AVFilterContext *avctx) {
 
 static int amf_filter_query_formats(AVFilterContext *avctx)
 {
-    const enum AVPixelFormat *output_pix_fmts;
     static const enum AVPixelFormat input_pix_fmts[] = {
         AV_PIX_FMT_AMF_SURFACE,
         AV_PIX_FMT_D3D11,
@@ -71,15 +70,8 @@ static int amf_filter_query_formats(AVFilterContext *avctx)
         AV_PIX_FMT_P010,
         AV_PIX_FMT_NONE,
     };
-    static const enum AVPixelFormat output_pix_fmts_default[] = {
-        AV_PIX_FMT_AMF_SURFACE,
-        AV_PIX_FMT_NV12,
-        AV_PIX_FMT_P010,
-        AV_PIX_FMT_NONE,
-    };
-    output_pix_fmts = output_pix_fmts_default;
 
-    return amf_setup_input_output_formats(avctx, input_pix_fmts, 
output_pix_fmts);
+    return amf_setup_input_output_formats(avctx, input_pix_fmts);
 }
 
 static int amf_vqe_filter_config_output(AVFilterLink *outlink)

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to