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]
