video/filter: add field order support for built in deinterlacers

refqueue gets the field of the frame from mp_image which almost always(if not
always) assumes bottom field order first. By default this behavior should not
change but specifying the field order should bypass this.
This commit is contained in:
1nsane000 2024-02-21 01:55:36 +01:00 committed by Philip Langdale
parent 5b52d44972
commit 03bfd797f6
6 changed files with 49 additions and 6 deletions

View File

@ -88,12 +88,14 @@ static void deint_process(struct mp_filter *f)
bool has_filter = true;
if (img->imgfmt == IMGFMT_VDPAU) {
char *args[] = {"deint", "yes", NULL};
char *args[] = {"deint", "yes",
"parity", field_parity, NULL};
p->sub.filter =
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "vdpaupp", args);
} else if (img->imgfmt == IMGFMT_D3D11) {
char *args[] = {"parity", field_parity, NULL};
p->sub.filter =
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "d3d11vpp", NULL);
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "d3d11vpp", args);
} else if (img->imgfmt == IMGFMT_CUDA) {
char *args[] = {"mode", "send_field",
"parity", field_parity, NULL};
@ -106,7 +108,8 @@ static void deint_process(struct mp_filter *f)
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "bwdif_vulkan", args);
} else if (img->imgfmt == IMGFMT_VAAPI) {
char *args[] = {"deint", "motion-adaptive",
"interlaced-only", "yes", NULL};
"interlaced-only", "yes",
"parity", field_parity, NULL};
p->sub.filter =
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "vavpp", args);
} else {

View File

@ -39,6 +39,7 @@ struct mp_refqueue {
int needed_past_frames;
int needed_future_frames;
int flags;
int field_parity;
bool second_field; // current frame has to output a second field yet
bool eof;
@ -97,6 +98,11 @@ void mp_refqueue_set_mode(struct mp_refqueue *q, int flags)
q->flags = flags;
}
void mp_refqueue_set_parity(struct mp_refqueue *q, int parity)
{
q->field_parity = parity;
}
// Whether the current frame should be deinterlaced.
bool mp_refqueue_should_deint(struct mp_refqueue *q)
{
@ -113,8 +119,14 @@ bool mp_refqueue_is_top_field(struct mp_refqueue *q)
{
if (!mp_refqueue_has_output(q))
return false;
return !!(q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST) ^ q->second_field;
bool tff = q->field_parity == MP_FIELD_PARITY_TFF;
bool bff = q->field_parity == MP_FIELD_PARITY_BFF;
bool ret = (!!(q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST) ^ q->second_field
&& !tff && !bff); // Default parity
ret = ret || (tff && !q->second_field); // Check if top field is forced
ret = ret || (bff && q->second_field); // Check if bottom field is forced
return ret;
}
// Whether top-field-first mode is enabled.
@ -123,7 +135,9 @@ bool mp_refqueue_top_field_first(struct mp_refqueue *q)
if (!mp_refqueue_has_output(q))
return false;
return q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST;
bool tff = q->field_parity == MP_FIELD_PARITY_TFF;
bool bff = q->field_parity == MP_FIELD_PARITY_BFF;
return ((q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST) || tff) && !bff;
}
// Discard all state.

View File

@ -34,6 +34,7 @@ enum {
#define MP_FIELD_PARITY_BFF 1
void mp_refqueue_set_mode(struct mp_refqueue *q, int flags);
void mp_refqueue_set_parity(struct mp_refqueue *q, int parity);
bool mp_refqueue_should_deint(struct mp_refqueue *q);
bool mp_refqueue_is_top_field(struct mp_refqueue *q);
bool mp_refqueue_top_field_first(struct mp_refqueue *q);

View File

@ -46,6 +46,7 @@ struct opts {
bool deint_enabled;
bool interlaced_only;
int mode;
int field_parity;
};
struct priv {
@ -469,6 +470,7 @@ static struct mp_filter *vf_d3d11vpp_create(struct mp_filter *parent,
(p->opts->deint_enabled ? MP_MODE_DEINT : 0) |
MP_MODE_OUTPUT_FIELDS |
(p->opts->interlaced_only ? MP_MODE_INTERLACED_ONLY : 0));
mp_refqueue_set_parity(p->queue, p->opts->field_parity);
return f;
@ -488,6 +490,10 @@ static const m_option_t vf_opts_fields[] = {
{"mocomp", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_MOTION_COMPENSATION},
{"ivctc", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_INVERSE_TELECINE},
{"none", 0})},
{"parity", OPT_CHOICE(field_parity,
{"tff", MP_FIELD_PARITY_TFF},
{"bff", MP_FIELD_PARITY_BFF},
{"auto", MP_FIELD_PARITY_AUTO})},
{0}
};
@ -499,6 +505,7 @@ const struct mp_user_filter_entry vf_d3d11vpp = {
.priv_defaults = &(const OPT_BASE_STRUCT) {
.deint_enabled = true,
.mode = D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB,
.field_parity = MP_FIELD_PARITY_AUTO,
},
.options = vf_opts_fields,
},

View File

@ -51,6 +51,7 @@ struct pipeline {
struct opts {
int deint_type;
int field_parity;
bool interlaced_only;
bool reversal_bug;
};
@ -143,11 +144,13 @@ static void update_pipeline(struct mp_filter *vf)
(p->do_deint ? MP_MODE_DEINT : 0) |
(p->opts->deint_type >= 2 ? MP_MODE_OUTPUT_FIELDS : 0) |
(p->opts->interlaced_only ? MP_MODE_INTERLACED_ONLY : 0));
mp_refqueue_set_parity(p->queue, p->opts->field_parity);
return;
nodeint:
mp_refqueue_set_refs(p->queue, 0, 0);
mp_refqueue_set_mode(p->queue, 0);
mp_refqueue_set_parity(p->queue, p->opts->field_parity);
}
static struct mp_image *alloc_out(struct mp_filter *vf)
@ -485,6 +488,10 @@ static const m_option_t vf_opts_fields[] = {
{"motion-compensated", 5})},
{"interlaced-only", OPT_BOOL(interlaced_only)},
{"reversal-bug", OPT_BOOL(reversal_bug)},
{"parity", OPT_CHOICE(field_parity,
{"tff", MP_FIELD_PARITY_TFF},
{"bff", MP_FIELD_PARITY_BFF},
{"auto", MP_FIELD_PARITY_AUTO})},
{0}
};
@ -496,6 +503,7 @@ const struct mp_user_filter_entry vf_vavpp = {
.priv_defaults = &(const OPT_BASE_STRUCT){
.deint_type = -1,
.reversal_bug = true,
.field_parity = MP_FIELD_PARITY_AUTO,
},
.options = vf_opts_fields,
},

View File

@ -43,6 +43,7 @@
struct opts {
bool deint_enabled;
bool interlaced_only;
int field_parity;
struct mp_vdpau_mixer_opts opts;
};
@ -156,6 +157,8 @@ static struct mp_filter *vf_vdpaupp_create(struct mp_filter *parent, void *optio
(p->opts->interlaced_only ? MP_MODE_INTERLACED_ONLY : 0) |
(p->opts->opts.deint >= 2 ? MP_MODE_OUTPUT_FIELDS : 0));
mp_refqueue_set_parity(p->queue, p->opts->field_parity);
mp_refqueue_add_in_format(p->queue, IMGFMT_VDPAU, 0);
return f;
@ -180,6 +183,10 @@ static const m_option_t vf_opts_fields[] = {
{"sharpen", OPT_FLOAT(opts.sharpen), M_RANGE(-1, 1)},
{"hqscaling", OPT_INT(opts.hqscaling), M_RANGE(0, 9)},
{"interlaced-only", OPT_BOOL(interlaced_only)},
{"parity", OPT_CHOICE(field_parity,
{"tff", MP_FIELD_PARITY_TFF},
{"bff", MP_FIELD_PARITY_BFF},
{"auto", MP_FIELD_PARITY_AUTO})},
{0}
};
@ -188,6 +195,9 @@ const struct mp_user_filter_entry vf_vdpaupp = {
.description = "vdpau postprocessing",
.name = "vdpaupp",
.priv_size = sizeof(OPT_BASE_STRUCT),
.priv_defaults = &(const OPT_BASE_STRUCT){
.field_parity = MP_FIELD_PARITY_AUTO,
},
.options = vf_opts_fields,
},
.create = vf_vdpaupp_create,