Extended vpp_amf filter with D3D11-based deinterlace and crop for ffmpeg
(github pages)
vpp_amf filtervf_amf_common.cvf_amf_common.hvf_vpp_amf.cdeint or crop(cx,cy,cw,ch) is specified together with the original w / h options of vpp_amf,w × h as the canvas-hwaccel amf) supports the codecffmpeg -hwaccel amf -i "input.m2ts" \
-c:v hevc_amf \
-vf "vpp_amf=w=1920:h=720:deint=fast:deint_frame_format=tff:format=nv12:cx=0:cy=139:cw=1920:ch=802" \
-c:a copy -f mp4 "output.mp4"
ffmpeg -i "input.m2ts" \
-c:v hevc_amf \
-vf "format=nv12, vpp_amf=w=1920:h=720:deint=fast:deint_frame_format=tff:format=nv12:cx=0:cy=139:cw=1920:ch=802" \
-c:a copy -f mp4 "output.mp4"
format, deint, and deint_frame_format in the filter (see 2-2)deint=adaptive may produce jagged framesdeint=fast + deint_frame_format for stable resultsnv12 or p010, so it failsformat=nv12 explicitly (see 2-2)AMF decoder support as of 2026.1:
DEFINE_AMF_DECODER(h264, H264, ...)
DEFINE_AMF_DECODER(hevc, HEVC, ...)
DEFINE_AMF_DECODER(vp9, VP9, ...)
DEFINE_AMF_DECODER(av1, AV1, ...)
deint and deint_frame_format togetherffmpeg -i test.vob -filter:v idet -frames:v 300 -an -f null -
ffprobe -select_streams v:0 -show_entries stream=codec_name test.vob
ffmpeg -i "test.mp4" -vf cropdetect -f null -
ffmpeg_vpp_amf_d3d11_ext
+- patches
| +- original
| | +- vf_amf_common.c
| | +- vf_amf_common.h
| | +- vf_vpp_amf.c
| +- patched
| | +- vf_amf_common.c
| | +- vf_amf_common.h
| | +- vf_vpp_amf.c
| +- vf_amf_common_c.patch
| +- vf_amf_common_h.patch
| +- vf_vpp_amf_c.patch
+- Makefile
Edit the following line:
ROOT := /d/Data/ffmpeg_vpp_amf_d3d11_ext
INSTALL_TO := /d/utils/ffmpeg-self
cd ffmpeg_vpp_amf_d3d11_ext
make
configurereset_sar optionThe following code inside amf_init_filter_config() does not appear to behave as originally intended:
if (ctx->reset_sar && inlink->sample_aspect_ratio.num)
w_adj = (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den;
ff_scale_adjust_dimensions(inlink, &ctx->width, &ctx->height,
ctx->force_original_aspect_ratio, ctx->force_divisible_by, w_adj);
Regarding inlink->sample_aspect_ratio.num:
w=-1 or w=-2 is specified, inlink->sample_aspect_ratio.num is non‑zero.w is omitted (implicitly w=iw), explicitly set to a fixed value (e.g., w=1280:h=720), or given as an expression (e.g., w=ih*sar), inlink->sample_aspect_ratio.num becomes zero.As a result, ff_scale_adjust_dimensions() is executed with w_adj left at 1.0.
This behavior appears to be unintended and is problematic for my extension. Since inlink->sample_aspect_ratio.num is rarely zero in actual frames passed to the filter, this may be due to a change in FFmpeg’s filter framework or a bug in the current version.
If this is indeed a bug, it may be fixed in a future stable release. For now, I will work around it by selecting command‑line parameters according to the specific objective.
reset_sar optionWorkaround notes for observed FFmpeg expression‑evaluation behavior (as of 2026‑04‑15):
The following patterns have been confirmed regarding w (width) and reset_sar. Command‑line parameters should be chosen according to these rules:
w unspecified & reset_sar=false
w is evaluated as iw; output SAR matches input SAR.
w unspecified & reset_sar=true
w is evaluated as iw; output SAR is forced to 1.
Note: This causes distortion if the input SAR is not 1:1.
w=-2 & reset_sar=false
w is evaluated as h * dar / sar; output SAR matches input SAR.
w=-2 & reset_sar=true
w is evaluated as h * dar / sar, then scaled again by w * sar inside vpp_amf; output SAR is forced to 1.
w=value/expr & reset_sar=false
Output SAR matches input SAR. The input value should represent Display Width / SAR.
w=value/expr & reset_sar=true
Output SAR is forced to 1. The input value should be the actual Display Width.
This patch follows the ffmpeg project’s license (GPL/LGPL).
Refer to the ffmpeg source tree for full license details.