diff options
Diffstat (limited to 'filters/f_auto_filters.c')
-rw-r--r-- | filters/f_auto_filters.c | 120 |
1 files changed, 94 insertions, 26 deletions
diff --git a/filters/f_auto_filters.c b/filters/f_auto_filters.c index 944fe89eab..e151e2dc19 100644 --- a/filters/f_auto_filters.c +++ b/filters/f_auto_filters.c @@ -1,9 +1,12 @@ #include <math.h> +#include "audio/aframe.h" +#include "audio/format.h" #include "common/common.h" #include "common/msg.h" #include "options/m_config.h" #include "options/options.h" +#include "video/filter/refqueue.h" #include "video/mp_image.h" #include "video/mp_image_pool.h" @@ -19,7 +22,7 @@ struct deint_priv { struct mp_subfilter sub; int prev_imgfmt; - int prev_setting; + bool deinterlace_active; struct m_config_cache *opts; }; @@ -43,15 +46,18 @@ static void deint_process(struct mp_filter *f) return; } + struct mp_image *img = frame.data; + bool interlaced = img->fields & MP_IMGFIELD_INTERLACED; + m_config_cache_update(p->opts); struct filter_opts *opts = p->opts->opts; + bool should_deinterlace = (opts->deinterlace == -1 && interlaced) || + opts->deinterlace == 1; - if (!opts->deinterlace) + if (!should_deinterlace) mp_subfilter_destroy(&p->sub); - struct mp_image *img = frame.data; - - if (img->imgfmt == p->prev_imgfmt && p->prev_setting == opts->deinterlace) { + if (img->imgfmt == p->prev_imgfmt && p->deinterlace_active == should_deinterlace) { mp_subfilter_continue(&p->sub); return; } @@ -62,24 +68,50 @@ static void deint_process(struct mp_filter *f) assert(!p->sub.filter); p->prev_imgfmt = img->imgfmt; - p->prev_setting = opts->deinterlace; - if (!p->prev_setting) { + p->deinterlace_active = should_deinterlace; + if (!p->deinterlace_active) { mp_subfilter_continue(&p->sub); return; } + char *field_parity; + switch (opts->field_parity) { + case MP_FIELD_PARITY_TFF: + field_parity = "tff"; + break; + case MP_FIELD_PARITY_BFF: + field_parity = "bff"; + break; + default: + field_parity = "auto"; + } + 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", NULL}; + char *args[] = {"mode", "send_field", + "parity", field_parity, NULL}; + p->sub.filter = + mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "bwdif_cuda", args); + } else if (img->imgfmt == IMGFMT_VULKAN) { + char *args[] = {"mode", "send_field", + "parity", field_parity, NULL}; p->sub.filter = - mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "yadif_cuda", args); + 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", + "parity", field_parity, NULL}; + p->sub.filter = + mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "vavpp", args); } else { has_filter = false; } @@ -94,7 +126,7 @@ static void deint_process(struct mp_filter *f) struct mp_autoconvert *ac = mp_autoconvert_create(subf); if (ac) { filters[0] = ac->f; - // We know vf_yadif does not support hw inputs. + // We know vf_bwdif does not support hw inputs. mp_autoconvert_add_all_sw_imgfmts(ac); if (!mp_autoconvert_probe_input_video(ac, img)) { @@ -106,9 +138,10 @@ static void deint_process(struct mp_filter *f) } } - char *args[] = {"mode", "send_field", NULL}; + char *args[] = {"mode", "send_field", + "parity", field_parity, NULL}; filters[1] = - mp_create_user_filter(subf, MP_OUTPUT_CHAIN_VIDEO, "yadif", args); + mp_create_user_filter(subf, MP_OUTPUT_CHAIN_VIDEO, "bwdif", args); mp_chain_filters(subf->ppins[0], subf->ppins[1], filters, 2); p->sub.filter = subf; @@ -152,6 +185,12 @@ static const struct mp_filter_info deint_filter = { .destroy = deint_destroy, }; +bool mp_deint_active(struct mp_filter *f) +{ + struct deint_priv *p = f->priv; + return p->deinterlace_active; +} + struct mp_filter *mp_deint_create(struct mp_filter *parent) { struct mp_filter *f = mp_filter_create(parent, &deint_filter); @@ -295,7 +334,8 @@ struct mp_filter *mp_autorotate_create(struct mp_filter *parent) struct aspeed_priv { struct mp_subfilter sub; - double cur_speed; + double cur_speed, cur_speed_drop; + int current_filter; }; static void aspeed_process(struct mp_filter *f) @@ -305,26 +345,48 @@ static void aspeed_process(struct mp_filter *f) if (!mp_subfilter_read(&p->sub)) return; - if (fabs(p->cur_speed - 1.0) < 1e-8) { + if (!p->sub.filter) + p->current_filter = 0; + + double speed = p->cur_speed * p->cur_speed_drop; + + int req_filter = 0; + if (fabs(speed - 1.0) >= 1e-8) { + req_filter = p->cur_speed_drop == 1.0 ? 1 : 2; + if (p->sub.frame.type == MP_FRAME_AUDIO && + !af_fmt_is_pcm(mp_aframe_get_format(p->sub.frame.data))) + req_filter = 2; + } + + if (req_filter != p->current_filter) { if (p->sub.filter) - MP_VERBOSE(f, "removing scaletempo\n"); + MP_VERBOSE(f, "removing audio speed filter\n"); if (!mp_subfilter_drain_destroy(&p->sub)) return; - } else if (!p->sub.filter) { - MP_VERBOSE(f, "adding scaletempo\n"); - p->sub.filter = - mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, "scaletempo", NULL); - if (!p->sub.filter) { - MP_ERR(f, "could not create scaletempo filter\n"); - mp_subfilter_continue(&p->sub); - return; + + if (req_filter) { + if (req_filter == 1) { + MP_VERBOSE(f, "adding scaletempo2\n"); + p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, + "scaletempo2", NULL); + } else if (req_filter == 2) { + MP_VERBOSE(f, "adding drop\n"); + p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, + "drop", NULL); + } + if (!p->sub.filter) { + MP_ERR(f, "could not create filter\n"); + mp_subfilter_continue(&p->sub); + return; + } + p->current_filter = req_filter; } } if (p->sub.filter) { struct mp_filter_command cmd = { .type = MP_FILTER_COMMAND_SET_SPEED, - .speed = p->cur_speed, + .speed = speed, }; mp_filter_command(p->sub.filter, &cmd); } @@ -341,6 +403,11 @@ static bool aspeed_command(struct mp_filter *f, struct mp_filter_command *cmd) return true; } + if (cmd->type == MP_FILTER_COMMAND_SET_SPEED_DROP) { + p->cur_speed_drop = cmd->speed; + return true; + } + if (cmd->type == MP_FILTER_COMMAND_IS_ACTIVE) { cmd->is_active = !!p->sub.filter; return true; @@ -381,6 +448,7 @@ struct mp_filter *mp_autoaspeed_create(struct mp_filter *parent) struct aspeed_priv *p = f->priv; p->cur_speed = 1.0; + p->cur_speed_drop = 1.0; p->sub.in = mp_filter_add_pin(f, MP_PIN_IN, "in"); p->sub.out = mp_filter_add_pin(f, MP_PIN_OUT, "out"); |