From 03bfd797f6d8d703601aad1065194c760d8927dd Mon Sep 17 00:00:00 2001 From: 1nsane000 <33362569+1nsane000@users.noreply.github.com> Date: Wed, 21 Feb 2024 01:55:36 +0100 Subject: 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. --- video/filter/refqueue.c | 20 +++++++++++++++++--- video/filter/refqueue.h | 1 + video/filter/vf_d3d11vpp.c | 7 +++++++ video/filter/vf_vavpp.c | 8 ++++++++ video/filter/vf_vdpaupp.c | 10 ++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) (limited to 'video/filter') diff --git a/video/filter/refqueue.c b/video/filter/refqueue.c index d018e38c00..3cfe3c61ff 100644 --- a/video/filter/refqueue.c +++ b/video/filter/refqueue.c @@ -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. diff --git a/video/filter/refqueue.h b/video/filter/refqueue.h index 9d47ee87fb..d14058d609 100644 --- a/video/filter/refqueue.h +++ b/video/filter/refqueue.h @@ -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); diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c index d63acd11ce..cedb91d857 100644 --- a/video/filter/vf_d3d11vpp.c +++ b/video/filter/vf_d3d11vpp.c @@ -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, }, diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index f70fe1f4a6..960c74587e 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -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, }, diff --git a/video/filter/vf_vdpaupp.c b/video/filter/vf_vdpaupp.c index b8a5d4194f..b5434cdfbc 100644 --- a/video/filter/vf_vdpaupp.c +++ b/video/filter/vf_vdpaupp.c @@ -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, -- cgit v1.2.3