summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author1nsane000 <33362569+1nsane000@users.noreply.github.com>2024-02-21 01:55:36 +0100
committerPhilip Langdale <github.philipl@overt.org>2024-03-04 17:41:40 -0800
commit03bfd797f6d8d703601aad1065194c760d8927dd (patch)
tree20e66ae0646dac493b4cbb3717316785d011ce1e
parent5b52d4497206f9d977f0f1bbf08c396e76dd619f (diff)
downloadmpv-03bfd797f6d8d703601aad1065194c760d8927dd.tar.bz2
mpv-03bfd797f6d8d703601aad1065194c760d8927dd.tar.xz
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.
-rw-r--r--filters/f_auto_filters.c9
-rw-r--r--video/filter/refqueue.c20
-rw-r--r--video/filter/refqueue.h1
-rw-r--r--video/filter/vf_d3d11vpp.c7
-rw-r--r--video/filter/vf_vavpp.c8
-rw-r--r--video/filter/vf_vdpaupp.c10
6 files changed, 49 insertions, 6 deletions
diff --git a/filters/f_auto_filters.c b/filters/f_auto_filters.c
index b37fd9d5f4..6fa38b96c2 100644
--- a/filters/f_auto_filters.c
+++ b/filters/f_auto_filters.c
@@ -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 {
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,