mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-06-16 04:32:47 +02:00
avfilter: update deinterlace_d3d12 filter options name
This commit update deinterlace_d3d12 filter options name.
Currently it follows the options name with "deinterlace_vaapi",
In this commit, it will follow filters such as "yadif" and "w3fdif".
Sample command lines:
1. Software decode with hwupload:
ffmpeg -init_hw_device d3d12va=d3d12 -i interlaced.ts \
-vf "format=nv12,hwupload,deinterlace_d3d12=method=default,hwdownload,format=nv12" \
-c:v libx264 output.mp4
2. Full hardware pipeline:
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i interlaced.ts \
-vf "deinterlace_d3d12=method=custom:mode=field" \
-c:v h264_d3d12va output.mp4
Signed-off-by: younengxiao <steven.xiao@amd.com>
This commit is contained in:
@@ -34,22 +34,22 @@
|
||||
#define MAX_REFERENCES 8
|
||||
|
||||
/**
|
||||
* Deinterlace mode enumeration
|
||||
* Deinterlace method enumeration
|
||||
* Maps to D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG values
|
||||
*/
|
||||
enum DeinterlaceD3D12Mode {
|
||||
DEINT_D3D12_MODE_DEFAULT = 0, // Use best available mode
|
||||
DEINT_D3D12_MODE_BOB = 1, // Bob deinterlacing (simple field interpolation)
|
||||
DEINT_D3D12_MODE_CUSTOM = 2, // Driver-defined advanced deinterlacing
|
||||
enum DeinterlaceD3D12Method {
|
||||
DEINT_D3D12_METHOD_DEFAULT = 0, // Use best available method
|
||||
DEINT_D3D12_METHOD_BOB = 1, // Bob deinterlacing (simple field interpolation)
|
||||
DEINT_D3D12_METHOD_CUSTOM = 2, // Driver-defined advanced deinterlacing
|
||||
};
|
||||
|
||||
typedef struct DeinterlaceD3D12Context {
|
||||
const AVClass *classCtx;
|
||||
|
||||
/* Filter options */
|
||||
int mode; // Deinterlace mode (default, bob, custom)
|
||||
int field_rate; // Output field rate (1 = frame rate, 2 = field rate)
|
||||
int auto_enable; // Only deinterlace interlaced frames
|
||||
int method; // Deinterlace method (default, bob, custom)
|
||||
int mode; // Output mode (0 = frame rate, 1 = field rate)
|
||||
int deint; // Which frames to deinterlace (0 = all, 1 = interlaced only)
|
||||
|
||||
/* D3D12 objects */
|
||||
ID3D12Device *device;
|
||||
@@ -220,42 +220,42 @@ static AVRational get_input_framerate(AVFilterContext *ctx, AVFilterLink *inlink
|
||||
return framerate;
|
||||
}
|
||||
|
||||
static D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS get_deint_mode(DeinterlaceD3D12Context *s,
|
||||
static D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS get_deint_method(DeinterlaceD3D12Context *s,
|
||||
AVFilterContext *ctx)
|
||||
{
|
||||
D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS mode_flag;
|
||||
D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS method_flag;
|
||||
|
||||
switch (s->mode) {
|
||||
case DEINT_D3D12_MODE_BOB:
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
switch (s->method) {
|
||||
case DEINT_D3D12_METHOD_BOB:
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
break;
|
||||
case DEINT_D3D12_MODE_CUSTOM:
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM;
|
||||
case DEINT_D3D12_METHOD_CUSTOM:
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM;
|
||||
break;
|
||||
case DEINT_D3D12_MODE_DEFAULT:
|
||||
case DEINT_D3D12_METHOD_DEFAULT:
|
||||
default:
|
||||
/* Select best available mode */
|
||||
/* Select best available method */
|
||||
if (s->supported_deint_flags & D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM) {
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM;
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM;
|
||||
av_log(ctx, AV_LOG_VERBOSE, "Using custom (driver-defined) deinterlacing\n");
|
||||
} else if (s->supported_deint_flags & D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB) {
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
av_log(ctx, AV_LOG_VERBOSE, "Using bob deinterlacing\n");
|
||||
} else {
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
av_log(ctx, AV_LOG_WARNING, "No deinterlacing modes reported, trying bob\n");
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
av_log(ctx, AV_LOG_WARNING, "No deinterlacing methods reported, trying bob\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Verify requested mode is supported */
|
||||
if (mode_flag != D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB &&
|
||||
!(s->supported_deint_flags & mode_flag)) {
|
||||
av_log(ctx, AV_LOG_WARNING, "Requested deinterlace mode not supported, falling back to bob\n");
|
||||
mode_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
/* Verify requested method is supported */
|
||||
if (method_flag != D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB &&
|
||||
!(s->supported_deint_flags & method_flag)) {
|
||||
av_log(ctx, AV_LOG_WARNING, "Requested deinterlace method not supported, falling back to bob\n");
|
||||
method_flag = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB;
|
||||
}
|
||||
|
||||
return mode_flag;
|
||||
return method_flag;
|
||||
}
|
||||
|
||||
static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
@@ -265,7 +265,7 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
HRESULT hr;
|
||||
AVHWDeviceContext *hwctx = (AVHWDeviceContext *)s->hw_device_ctx->data;
|
||||
AVD3D12VADeviceContext *d3d12_hwctx = (AVD3D12VADeviceContext *)hwctx->hwctx;
|
||||
D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS deint_mode;
|
||||
D3D12_VIDEO_PROCESS_DEINTERLACE_FLAGS deint_method;
|
||||
D3D12_VIDEO_FIELD_TYPE field_type;
|
||||
|
||||
s->device = d3d12_hwctx->device;
|
||||
@@ -314,7 +314,7 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
|
||||
s->process_support.OutputFormat.Format = s->input_format;
|
||||
s->process_support.OutputFormat.ColorSpace = s->input_colorspace;
|
||||
s->process_support.OutputFrameRate.Numerator = s->input_framerate.num * s->field_rate;
|
||||
s->process_support.OutputFrameRate.Numerator = s->input_framerate.num * (s->mode + 1);
|
||||
s->process_support.OutputFrameRate.Denominator = s->input_framerate.den;
|
||||
s->process_support.OutputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
|
||||
|
||||
@@ -342,21 +342,21 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
|
||||
if (!(s->supported_deint_flags & (D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_BOB |
|
||||
D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM))) {
|
||||
av_log(ctx, AV_LOG_ERROR, "No deinterlacing modes supported by hardware\n");
|
||||
av_log(ctx, AV_LOG_ERROR, "No deinterlacing methods supported by hardware\n");
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
deint_mode = get_deint_mode(s, ctx);
|
||||
deint_method = get_deint_method(s, ctx);
|
||||
|
||||
/* Query reference frame requirements from hardware */
|
||||
#if CONFIG_D3D12_VIDEO_PROCESS_REFERENCE_INFO
|
||||
D3D12_FEATURE_DATA_VIDEO_PROCESS_REFERENCE_INFO ref_info = {
|
||||
.NodeIndex = 0,
|
||||
.DeinterlaceMode = deint_mode,
|
||||
.DeinterlaceMode = deint_method,
|
||||
.Filters = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE,
|
||||
.FeatureSupport = D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE,
|
||||
.InputFrameRate = { s->input_framerate.num, s->input_framerate.den },
|
||||
.OutputFrameRate = { s->input_framerate.num * s->field_rate, s->input_framerate.den },
|
||||
.OutputFrameRate = { s->input_framerate.num * (s->mode + 1), s->input_framerate.den },
|
||||
.EnableAutoProcessing = FALSE,
|
||||
};
|
||||
|
||||
@@ -376,18 +376,18 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
} else {
|
||||
av_log(ctx, AV_LOG_WARNING,
|
||||
"Failed to query reference info (HRESULT 0x%lX), using defaults\n", hr);
|
||||
s->num_past_frames = (deint_mode == D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM) ? 1 : 0;
|
||||
s->num_past_frames = (deint_method == D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM) ? 1 : 0;
|
||||
s->num_future_frames = 0;
|
||||
}
|
||||
#else
|
||||
av_log(ctx, AV_LOG_VERBOSE,
|
||||
"Reference info query not available in SDK, using defaults\n");
|
||||
s->num_past_frames = (deint_mode == D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM) ? 1 : 0;
|
||||
s->num_past_frames = (deint_method == D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_CUSTOM) ? 1 : 0;
|
||||
s->num_future_frames = 0;
|
||||
#endif
|
||||
|
||||
/* May need 1 extra slot for PTS calculation.*/
|
||||
s->extra_delay_for_timestamps = (s->field_rate == 2 && s->num_future_frames == 0) ? 1 : 0;
|
||||
s->extra_delay_for_timestamps = (s->mode && s->num_future_frames == 0) ? 1 : 0;
|
||||
|
||||
s->queue_depth = s->num_past_frames + s->num_future_frames + s->extra_delay_for_timestamps + 1;
|
||||
|
||||
@@ -409,7 +409,7 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
.AlphaFillMode = D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE,
|
||||
.AlphaFillModeSourceStreamIndex = 0,
|
||||
.BackgroundColor = { 0.0f, 0.0f, 0.0f, 1.0f },
|
||||
.FrameRate = { s->input_framerate.num * s->field_rate, s->input_framerate.den },
|
||||
.FrameRate = { s->input_framerate.num * (s->mode + 1), s->input_framerate.den },
|
||||
.EnableStereo = FALSE,
|
||||
};
|
||||
|
||||
@@ -421,7 +421,7 @@ static int deint_d3d12_configure_processor(DeinterlaceD3D12Context *s,
|
||||
.FrameRate = { s->input_framerate.num, s->input_framerate.den },
|
||||
.StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE,
|
||||
.FieldType = field_type,
|
||||
.DeinterlaceMode = deint_mode,
|
||||
.DeinterlaceMode = deint_method,
|
||||
.EnableOrientation = FALSE,
|
||||
.FilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE,
|
||||
.SourceSizeRange = {
|
||||
@@ -756,7 +756,7 @@ static int deint_d3d12_process_frame(AVFilterContext *ctx,
|
||||
out->flags &= ~AV_FRAME_FLAG_INTERLACED;
|
||||
|
||||
/* Calculate output PTS for field rate output */
|
||||
if (s->field_rate == 2 && queue_idx >= 0) {
|
||||
if (s->mode && queue_idx >= 0) {
|
||||
AVFrame *next_frame = (queue_idx + 1 < s->queue_count) ?
|
||||
s->frame_queue[queue_idx + 1] : NULL;
|
||||
|
||||
@@ -816,7 +816,7 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
while (flush_idx < s->queue_count) {
|
||||
input_frame = s->frame_queue[flush_idx];
|
||||
if (input_frame) {
|
||||
for (field = 0; field < s->field_rate; field++) {
|
||||
for (field = 0; field <= s->mode; field++) {
|
||||
ret = deint_d3d12_process_frame(ctx, outlink, input_frame, field, flush_idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -877,8 +877,8 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
}
|
||||
}
|
||||
|
||||
/* Auto mode: pass through progressive frames by processing them as-is */
|
||||
if (s->auto_enable && !(in->flags & AV_FRAME_FLAG_INTERLACED)) {
|
||||
/* interlaced : pass through progressive frames by processing them as-is */
|
||||
if (s->deint && !(in->flags & AV_FRAME_FLAG_INTERLACED)) {
|
||||
av_log(ctx, AV_LOG_DEBUG, "Progressive frame, processing as pass-through\n");
|
||||
ret = deint_d3d12_process_frame(ctx, outlink, in, 0, -1);
|
||||
av_frame_free(&in);
|
||||
@@ -887,11 +887,11 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
|
||||
/* Queue management and frame processing.
|
||||
*
|
||||
* For bob mode, the hardware typically needs no reference frames
|
||||
* For bob method, the hardware typically needs no reference frames
|
||||
* (past=0, future=0), so queue_depth=1 and every input frame is
|
||||
* processed immediately -- simple frame-in, frame-out.
|
||||
*
|
||||
* For custom (driver-defined) mode, the hardware uses temporal
|
||||
* For custom (driver-defined) method, the hardware uses temporal
|
||||
* reference frames for higher-quality motion-adaptive deinterlacing.
|
||||
* The queue possible holds past, current, and future reference frames:
|
||||
* The queue is managed in four phases:
|
||||
@@ -904,7 +904,7 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
* 4. EOF flush: process remaining frames after current_frame_index,
|
||||
* or all buffered frames if the queue never filled (short stream)
|
||||
*
|
||||
* When queue_depth=1 (bob mode), phases 1, 2, and 4 are effectively
|
||||
* When queue_depth=1 (bob method), phases 1, 2, and 4 are effectively
|
||||
* skipped, and only the steady-state path executes.
|
||||
*/
|
||||
|
||||
@@ -923,7 +923,7 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
input_frame = s->frame_queue[i];
|
||||
if (!input_frame)
|
||||
continue;
|
||||
for (field = 0; field < s->field_rate; field++) {
|
||||
for (field = 0; field <= s->mode; field++) {
|
||||
ret = deint_d3d12_process_frame(ctx, outlink, input_frame, field, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -946,7 +946,7 @@ static int deint_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
if (!input_frame)
|
||||
return 0;
|
||||
|
||||
for (field = 0; field < s->field_rate; field++) {
|
||||
for (field = 0; field <= s->mode; field++) {
|
||||
ret = deint_d3d12_process_frame(ctx, outlink, input_frame, field, s->current_frame_index);
|
||||
if (ret < 0)
|
||||
break;
|
||||
@@ -1000,8 +1000,8 @@ static int deint_d3d12_config_output(AVFilterLink *outlink)
|
||||
s->height = inlink->h;
|
||||
|
||||
/* Adjust time base and frame rate for field rate output */
|
||||
outlink->time_base = av_mul_q(inlink->time_base, (AVRational){ 1, s->field_rate });
|
||||
outl->frame_rate = av_mul_q(inl->frame_rate, (AVRational){ s->field_rate, 1 });
|
||||
outlink->time_base = av_mul_q(inlink->time_base, (AVRational){ 1, s->mode + 1 });
|
||||
outl->frame_rate = av_mul_q(inl->frame_rate, (AVRational){ s->mode + 1, 1 });
|
||||
|
||||
if (!inl->hw_frames_ctx) {
|
||||
av_log(ctx, AV_LOG_ERROR, "No hw_frames_ctx available on input link\n");
|
||||
@@ -1047,8 +1047,8 @@ static int deint_d3d12_config_output(AVFilterLink *outlink)
|
||||
if (!outl->hw_frames_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
av_log(ctx, AV_LOG_VERBOSE, "D3D12 deinterlace config: %dx%d, field_rate=%d\n",
|
||||
outlink->w, outlink->h, s->field_rate);
|
||||
av_log(ctx, AV_LOG_VERBOSE, "D3D12 deinterlace config: %dx%d, mode=%s\n",
|
||||
outlink->w, outlink->h, s->mode ? "field" : "frame");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1085,25 +1085,29 @@ static const AVFilterPad deint_d3d12_outputs[] = {
|
||||
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
|
||||
|
||||
static const AVOption deinterlace_d3d12_options[] = {
|
||||
{ "mode", "Deinterlacing mode",
|
||||
OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = DEINT_D3D12_MODE_DEFAULT },
|
||||
DEINT_D3D12_MODE_DEFAULT, DEINT_D3D12_MODE_CUSTOM, FLAGS, .unit = "mode" },
|
||||
{ "default", "Use best available deinterlacing mode",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_MODE_DEFAULT }, 0, 0, FLAGS, .unit = "mode" },
|
||||
{ "method", "Deinterlacing method",
|
||||
OFFSET(method), AV_OPT_TYPE_INT, { .i64 = DEINT_D3D12_METHOD_DEFAULT },
|
||||
DEINT_D3D12_METHOD_DEFAULT, DEINT_D3D12_METHOD_CUSTOM, FLAGS, .unit = "method" },
|
||||
{ "default", "Use best available deinterlacing method",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_METHOD_DEFAULT }, 0, 0, FLAGS, .unit = "method" },
|
||||
{ "bob", "Bob deinterlacing (simple field interpolation)",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_MODE_BOB }, 0, 0, FLAGS, .unit = "mode" },
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_METHOD_BOB }, 0, 0, FLAGS, .unit = "method" },
|
||||
{ "custom", "Driver-defined advanced deinterlacing",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_MODE_CUSTOM }, 0, 0, FLAGS, .unit = "mode" },
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = DEINT_D3D12_METHOD_CUSTOM }, 0, 0, FLAGS, .unit = "method" },
|
||||
|
||||
{ "rate", "Generate output at frame rate or field rate",
|
||||
OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 2, FLAGS, .unit = "rate" },
|
||||
{ "frame", "Output at frame rate (one frame for each field-pair)",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "rate" },
|
||||
{ "field", "Output at field rate (one frame for each field)",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, .unit = "rate" },
|
||||
{ "mode", "Specify the interlacing mode",
|
||||
OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "mode" },
|
||||
{ "frame", "Send one frame for each frame",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "mode" },
|
||||
{ "field", "Send one frame for each field",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "mode" },
|
||||
|
||||
{ "auto", "Only deinterlace interlaced frames, pass through progressive",
|
||||
OFFSET(auto_enable), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
|
||||
{ "deint", "Specify which frames to deinterlace",
|
||||
OFFSET(deint), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "deint" },
|
||||
{ "all", "Deinterlace all frames",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "deint" },
|
||||
{ "interlaced", "Only deinterlace frames marked as interlaced",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "deint" },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user