avfilter/d3d11: add output copy options to shader filters

This commit is contained in:
gnattu
2026-07-01 16:26:36 +08:00
parent e251df31b4
commit 1873d31a64
3 changed files with 57 additions and 18 deletions
+34 -4
View File
@@ -73,7 +73,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/vf_yadif_d3d11.c
@@ -0,0 +1,774 @@
@@ -0,0 +1,804 @@
+/*
+ * D3D11 YADIF/BWDIF deinterlacing filters
+ *
@@ -168,6 +168,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ int tex_w, tex_h;
+ int direct_input_srv;
+ int direct_output_uav;
+ int force_output_copy;
+} DeintD3D11Context;
+
+static void release_d3d11_resources(DeintD3D11Context *s)
@@ -712,7 +713,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ s->direct_input_srv = -1;
+ s->direct_output_uav = -1;
+
+ for (int direct = 1; direct >= 0; direct--) {
+ for (int direct = !s->force_output_copy; direct >= 0; direct--) {
+ l->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
+ if (!l->hw_frames_ctx)
+ return AVERROR(ENOMEM);
@@ -753,6 +754,8 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ }
+ if (ret < 0)
+ return ret;
+ if (s->force_output_copy)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: forced copy from internal UAV texture\n");
+
+ output_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
+
@@ -787,10 +790,37 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return 0;
+}
+
+#define DEINT_OFFSET(x) offsetof(DeintD3D11Context, x)
+#define YADIF_OFFSET(x) offsetof(DeintD3D11Context, yadif.x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
+#define CONST(name, help, val, u) { name, help, 0, AV_OPT_TYPE_CONST, { .i64 = val }, INT_MIN, INT_MAX, FLAGS, .unit = u }
+
+static const AVOption deint_d3d11_options[] = {
+ { "mode", "specify the interlacing mode", YADIF_OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = YADIF_MODE_SEND_FRAME }, 0, 3, FLAGS, .unit = "mode" },
+ CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"),
+ CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"),
+ CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"),
+ CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"),
+ { "parity", "specify the assumed picture field parity", YADIF_OFFSET(parity), AV_OPT_TYPE_INT, { .i64 = YADIF_PARITY_AUTO }, -1, 1, FLAGS, .unit = "parity" },
+ CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"),
+ CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"),
+ CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"),
+ { "deint", "specify which frames to deinterlace", YADIF_OFFSET(deint), AV_OPT_TYPE_INT, { .i64 = YADIF_DEINT_ALL }, 0, 1, FLAGS, .unit = "deint" },
+ CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"),
+ CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"),
+ { "force_output_copy", "Force output through an internal unordered-access texture", DEINT_OFFSET(force_output_copy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
+ { NULL }
+};
+
+#undef CONST
+#undef FLAGS
+#undef YADIF_OFFSET
+#undef DEINT_OFFSET
+
+static const AVClass yadif_d3d11_class = {
+ .class_name = "yadif_d3d11",
+ .item_name = av_default_item_name,
+ .option = ff_yadif_options,
+ .option = deint_d3d11_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_FILTER,
+};
@@ -798,7 +828,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+static const AVClass bwdif_d3d11_class = {
+ .class_name = "bwdif_d3d11",
+ .item_name = av_default_item_name,
+ .option = ff_yadif_options,
+ .option = deint_d3d11_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_FILTER,
+};
@@ -991,7 +991,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ { "w", "Overlay width", OFFSET(overlay_ow), AV_OPT_TYPE_STRING, { .str = "overlay_iw" }, 0, 255, FLAGS },
+ { "h", "Overlay height", OFFSET(overlay_oh), AV_OPT_TYPE_STRING, { .str = "overlay_ih*overlay_w/overlay_iw" }, 0, 255, FLAGS },
+ { "alpha", "Overlay global alpha", OFFSET(alpha), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 1.0, FLAGS },
+ { "force_output_copy", "Force output through an internal unordered-access texture", OFFSET(force_output_copy), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+ { "force_output_copy", "Force output through an internal unordered-access texture", OFFSET(force_output_copy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
+ { "eof_action", "Action to take when encountering EOF from secondary input",
+ OFFSET(opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
+ EOF_ACTION_REPEAT, EOF_ACTION_PASS, FLAGS, .unit = "eof_action" },
@@ -45,7 +45,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
typedef struct ScaleD3D11Context {
const AVClass *classCtx;
@@ -47,12 +75,26 @@ typedef struct ScaleD3D11Context {
@@ -47,12 +75,27 @@ typedef struct ScaleD3D11Context {
ID3D11VideoProcessorOutputView *outputView;
ID3D11VideoProcessorInputView *inputView;
@@ -61,6 +61,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ int shader_fallback;
+ int direct_input_srv;
+ int direct_output_uav;
+ int force_output_copy;
+
///< Buffer references
AVBufferRef *hw_device_ctx;
@@ -72,7 +73,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
int inputWidth, inputHeight;
DXGI_FORMAT input_format;
DXGI_FORMAT output_format;
@@ -83,6 +125,340 @@ static void release_d3d11_resources(Scal
@@ -83,6 +126,340 @@ static void release_d3d11_resources(Scal
s->videoDevice->lpVtbl->Release(s->videoDevice);
s->videoDevice = NULL;
}
@@ -413,7 +414,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
}
static int scale_d3d11_configure_processor(ScaleD3D11Context *s, AVFilterContext *ctx) {
@@ -144,6 +520,152 @@ static int scale_d3d11_configure_process
@@ -144,6 +521,152 @@ static int scale_d3d11_configure_process
return 0;
}
@@ -566,7 +567,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
static int scale_d3d11_filter_frame(AVFilterLink *inlink, AVFrame *in)
{
AVFilterContext *ctx = inlink->dst;
@@ -185,6 +707,9 @@ static int scale_d3d11_filter_frame(AVFi
@@ -185,6 +708,9 @@ static int scale_d3d11_filter_frame(AVFi
return AVERROR(EINVAL);
}
@@ -576,7 +577,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Allocate output frame
out = av_frame_alloc();
if (!out) {
@@ -353,13 +878,6 @@ static int scale_d3d11_config_props(AVFi
@@ -353,13 +879,6 @@ static int scale_d3d11_config_props(AVFi
return AVERROR(EINVAL);
}
@@ -590,7 +591,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Initialize filter's hardware device context
if (!s->hw_device_ctx) {
AVHWFramesContext *in_frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data;
@@ -382,6 +900,29 @@ static int scale_d3d11_config_props(AVFi
@@ -382,6 +901,29 @@ static int scale_d3d11_config_props(AVFi
return AVERROR(EINVAL);
}
@@ -620,7 +621,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Create new hardware frames context for output
s->hw_frames_ctx_out = av_hwframe_ctx_alloc(s->hw_device_ctx);
if (!s->hw_frames_ctx_out)
@@ -399,16 +940,38 @@ static int scale_d3d11_config_props(AVFi
@@ -399,16 +941,43 @@ static int scale_d3d11_config_props(AVFi
AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
frames_hwctx->MiscFlags = 0;
@@ -629,8 +630,9 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
- frames_hwctx->BindFlags |= D3D11_BIND_VIDEO_ENCODER;
+ if (s->shader_fallback) {
+ frames_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET |
+ D3D11_BIND_SHADER_RESOURCE |
+ D3D11_BIND_UNORDERED_ACCESS;
+ D3D11_BIND_SHADER_RESOURCE;
+ if (!s->force_output_copy)
+ frames_hwctx->BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+ } else {
+ frames_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ if (frames_ctx->sw_format == AV_PIX_FMT_NV12)
@@ -642,13 +644,15 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
av_buffer_unref(&s->hw_frames_ctx_out);
return ret;
}
+ if (s->shader_fallback) {
+ if (s->shader_fallback && !s->force_output_copy) {
+ ret = scale_d3d11_probe_output_uav_pool(ctx, s->hw_frames_ctx_out);
+ if (ret < 0) {
+ av_buffer_unref(&s->hw_frames_ctx_out);
+ return ret;
+ }
+ s->direct_output_uav = 1;
+ } else if (s->shader_fallback) {
+ s->direct_output_uav = 0;
+ }
+
+
@@ -656,13 +660,15 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ av_log(ctx, AV_LOG_VERBOSE, "D3D11 scale: using P010 output path\n");
+ if (s->direct_output_uav > 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: direct UAV\n");
+ else if (s->force_output_copy)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: forced copy from internal UAV texture\n");
+ }
+ av_buffer_unref(&outl->hw_frames_ctx);
outl->hw_frames_ctx = av_buffer_ref(s->hw_frames_ctx_out);
if (!outl->hw_frames_ctx)
return AVERROR(ENOMEM);
@@ -424,6 +987,11 @@ static av_cold void scale_d3d11_uninit(A
@@ -424,6 +993,11 @@ static av_cold void scale_d3d11_uninit(A
///< Release D3D11 resources
release_d3d11_resources(s);
@@ -674,7 +680,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Free the hardware device context reference
av_buffer_unref(&s->hw_frames_ctx_out);
av_buffer_unref(&s->hw_device_ctx);
@@ -453,7 +1021,9 @@ static const AVFilterPad scale_d3d11_out
@@ -453,9 +1027,12 @@ static const AVFilterPad scale_d3d11_out
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
static const AVOption scale_d3d11_options[] = {
@@ -683,8 +689,11 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
{ "height", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
{ "format", "Output video pixel format", OFFSET(format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = AV_PIX_FMT_NONE }, INT_MIN, INT_MAX, .flags=FLAGS },
+ { "force_output_copy", "Force P010 shader output through an internal unordered-access texture", OFFSET(force_output_copy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, .flags=FLAGS },
{ NULL }
@@ -463,7 +1033,7 @@ AVFILTER_DEFINE_CLASS(scale_d3d11);
};
@@ -463,7 +1040,7 @@ AVFILTER_DEFINE_CLASS(scale_d3d11);
const FFFilter ff_vf_scale_d3d11 = {
.p.name = "scale_d3d11",