[PR] avfilter/vf_vqe_amf: Add AMF Video Quality Enhancer filter (PR #23536)

ArazIusubov via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178188508603.59.3122472239498838609@29965ddac10e>
PR #23536 opened by ArazIusubov
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23536
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23536.patch

Introduce a new vqe_amf filter implementing AMD AMF Video Quality Enhancer.

The filter exposes VQ enhancement functionality through the attenuation option.

At present, the filter is available on Windows systems only.

Examples:
_ffmpeg -hwaccel amf -hwaccel_output_format amf -i input.mp4 -vf vqe_amf=attenuation=0.4 -c:v hevc_amf output.mp4_

_ffmpeg -init_hw_device d3d11va=dx11 -init_hw_device amf=hw@dx11 -filter_hw_device hw -i input.mp4 -vf vqe_amf=attenuation=0.4 -c:v hevc_amf output.mp4_


>From 70e560eb05e76a4338b008789e26cd5440c4eb07 Mon Sep 17 00:00:00 2001
From: Araz Iusubov <[email protected]>
Date: Fri, 19 Jun 2026 17:19:37 +0200
Subject: [PATCH] avfilter/vf_vqe_amf: Add AMF Video Quality Enhancer filter

---
 Changelog                |   2 +-
 configure                |   1 +
 doc/filters.texi         |  37 +++++++++
 libavfilter/Makefile     |   1 +
 libavfilter/allfilters.c |   1 +
 libavfilter/vf_vqe_amf.c | 169 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 libavfilter/vf_vqe_amf.c

diff --git a/Changelog b/Changelog
index 2ad3ee255f..6f54ca07d7 100644
--- a/Changelog
+++ b/Changelog
@@ -18,7 +18,7 @@ version <next>:
 - Remove ogg/celt parsing
 - Bitstream filter to split Dolby Vision multi-layer HEVC
 - Add AMF hardware memory mapping support.
-
+- Add AMF Video Quality Enhancer (vf_vqe_amf) filter
 
 version 8.1:
 - ffprobe -codec option
diff --git a/configure b/configure
index 5149f3c217..e4de18171d 100755
--- a/configure
+++ b/configure
@@ -4272,6 +4272,7 @@ scale_filter_deps="swscale"
 sr_amf_filter_deps="amf"
 vpp_amf_filter_deps="amf"
 frc_amf_filter_deps="amf windows_h"
+vqe_amf_filter_deps="amf windows_h"
 scale_qsv_filter_deps="libmfx"
 scale_qsv_filter_select="qsvvpp"
 scdet_filter_select="scene_sad"
diff --git a/doc/filters.texi b/doc/filters.texi
index 2cae41c7c5..63b4fcf1ab 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -14816,6 +14816,43 @@ Boolean value: enable dependency on future frame, improves quality for the cost
 of latency (Default value: enabled).
 @end table
 
+@section vqe_amf
+
+AMD AMF VQ Enhancer filter.
+This filter applies AMD AMF VQ Enhancement to the input video.
+
+This filter accepts the following option:
+
+@table @option
+
+@item attenuation
+Set VQ Enhancer strength. Allowed range is from @code{0.02} to @code{0.4}.
+Default is @code{0.1}.
+
+@item engine_type
+Set AMF memory type used by the filter.
+
+Possible values:
+
+@table @samp
+@item dx11
+DirectX 11
+@item dx12
+DirectX 12
+@item vulkan
+Vulkan
+@item opencl
+OpenCL
+@end table
+
+@end table
+
+Example:
+
+@example
+ffmpeg -i input.mp4 -vf vqe_amf=attenuation=0.4 -c:v hevc_amf output.mp4
+@end example
+
 @section framestep
 
 Select one frame every N-th frame.
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 5f0760a2ff..ae7da8b068 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -576,6 +576,7 @@ OBJS-$(CONFIG_VIGNETTE_FILTER)               += vf_vignette.o
 OBJS-$(CONFIG_VMAFMOTION_FILTER)             += vf_vmafmotion.o framesync.o
 OBJS-$(CONFIG_VPP_AMF_FILTER)                += vf_vpp_amf.o scale_eval.o vf_amf_common.o
 OBJS-$(CONFIG_FRC_AMF_FILTER)                += vf_frc_amf.o vf_amf_common.o
+OBJS-$(CONFIG_VQE_AMF_FILTER)                += vf_vqe_amf.o vf_amf_common.o
 OBJS-$(CONFIG_VPP_QSV_FILTER)                += vf_vpp_qsv.o
 OBJS-$(CONFIG_VSTACK_FILTER)                 += vf_stack.o framesync.o
 OBJS-$(CONFIG_W3FDIF_FILTER)                 += vf_w3fdif.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 66c49d453b..a56ca79f8f 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -444,6 +444,7 @@ extern const FFFilter ff_vf_scale;
 extern const FFFilter ff_vf_vpp_amf;
 extern const FFFilter ff_vf_sr_amf;
 extern const FFFilter ff_vf_frc_amf;
+extern const FFFilter ff_vf_vqe_amf;
 extern const FFFilter ff_vf_scale_cuda;
 extern const FFFilter ff_vf_scale_d3d11;
 extern const FFFilter ff_vf_scale_d3d12;
diff --git a/libavfilter/vf_vqe_amf.c b/libavfilter/vf_vqe_amf.c
new file mode 100644
index 0000000000..d7249d999b
--- /dev/null
+++ b/libavfilter/vf_vqe_amf.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Quality Enhancer video filter with AMF hardware acceleration
+ */
+
+#include "libavutil/opt.h"
+
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_amf.h"
+#include "libavutil/hwcontext_amf_internal.h"
+
+#include "AMF/components/VQEnhancer.h"
+#include "vf_amf_common.h"
+
+#include "avfilter.h"
+#include "avfilter_internal.h"
+#include "formats.h"
+#include "video.h"
+
+#if CONFIG_D3D11VA
+#include <d3d11.h>
+#endif
+
+#if CONFIG_D3D12VA
+#include <d3d12.h>
+#endif
+
+typedef struct AMFVQEFilterContext {
+    AMFFilterContext common;
+
+    int engine_type;
+    double attenuation;
+} AMFVQEFilterContext;
+
+static int amf_vqe_init(AVFilterContext *avctx) {
+    AMFVQEFilterContext *ctx = avctx->priv;
+
+    ctx->common.format = AV_PIX_FMT_NONE;
+
+    return 0;
+}
+
+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_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,
+    };
+    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);
+}
+
+static int amf_vqe_filter_config_output(AVFilterLink *outlink)
+{
+    AVFilterContext     *avctx = outlink->src;
+    AMFComponent        *amf_filter = NULL;
+    AVFilterLink        *inlink = avctx->inputs[0];
+    AMFVQEFilterContext *vqe_ctx = avctx->priv;
+    AMFFilterContext    *amf_ctx = &vqe_ctx->common;
+    AVAMFDeviceContext  *device_ctx = NULL;
+
+    int err;
+    AMF_RESULT res;
+    enum AVPixelFormat in_format;
+
+    err = amf_init_filter_config(outlink, &in_format);
+    if (err < 0)
+        return err;
+
+    device_ctx = amf_ctx->amf_device_ctx;
+
+    res = AMF_IFACE_CALL(device_ctx->factory, CreateComponent, device_ctx->context, AMFVQEnhancer, &amf_ctx->component);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_FILTER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", AMFVQEnhancer, res);
+
+    amf_filter = amf_ctx->component;
+
+    if (vqe_ctx->engine_type != -1)
+        AMF_ASSIGN_PROPERTY_INT64(res, amf_filter, AMF_VIDEO_ENHANCER_ENGINE_TYPE, vqe_ctx->engine_type);
+
+    AMF_ASSIGN_PROPERTY_DOUBLE(res, amf_filter, AMF_VE_FCR_ATTENUATION, vqe_ctx->attenuation);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Failed to set VQ enhancer attenuation: %d\n", res);
+
+    res = AMF_IFACE_CALL(amf_filter, Init, av_av_to_amf_format(in_format), inlink->w, inlink->h);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "AMFVQEnhancer-Init() failed with error %d\n", res);
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(AMFVQEFilterContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+static const AVOption vqe_amf_options[] = {
+    { "engine_type",    "Engine type",   OFFSET(engine_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AMF_MEMORY_OPENCL, .flags = FLAGS, "engine_type" },
+    { "dx11",           "DirectX 11",    0,  AV_OPT_TYPE_CONST,   { .i64 = AMF_MEMORY_DX11 }, 0, 0, FLAGS, "engine_type" },
+    { "dx12",           "DirectX 12",    0,  AV_OPT_TYPE_CONST,   { .i64 = AMF_MEMORY_DX12 }, 0, 0, FLAGS, "engine_type" },
+    { "vulkan",         "Vulkan",        0,  AV_OPT_TYPE_CONST,   { .i64 = AMF_MEMORY_VULKAN }, 0, 0, FLAGS, "engine_type" },
+    { "opencl",         "OpenCL",        0,  AV_OPT_TYPE_CONST,   { .i64 = AMF_MEMORY_OPENCL }, 0, 0, FLAGS, "engine_type" },
+
+    { "attenuation",    "Control VQEnhancer strength", OFFSET(attenuation), AV_OPT_TYPE_DOUBLE,  { .dbl = 0.1  },  0.02, 0.4, FLAGS, "attenuation" },
+
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(vqe_amf);
+
+static const AVFilterPad amf_filter_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = amf_filter_filter_frame,
+    }
+};
+
+static const AVFilterPad amf_filter_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = amf_vqe_filter_config_output,
+    }
+};
+
+FFFilter ff_vf_vqe_amf = {
+    .p.name         = "vqe_amf",
+    .p.description  = NULL_IF_CONFIG_SMALL("AMD AMF VQ Enhancer"),
+    .p.priv_class   = &vqe_amf_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(AMFVQEFilterContext),
+    .init           = amf_vqe_init,
+    .uninit         = amf_filter_uninit,
+    FILTER_INPUTS(amf_filter_inputs),
+    FILTER_OUTPUTS(amf_filter_outputs),
+    FILTER_QUERY_FUNC(&amf_filter_query_formats),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.