1
mirror of https://github.com/mpv-player/mpv synced 2024-09-09 01:16:56 +02:00

video: fix deinterlace filter handling for VFCTRL_SET_DEINTERLACE filters

Some filters support VFCTRL_SET_DEINTERLACE. This affects most hardware
deinterlace filters. They can be inserted by the user manually, or auto-
inserted by vf.c itself as conversion filter (vf_d3d11vpp). In these
cases, we shouldn't insert or remove filters outselves, and instead
VFCTRL_SET_DEINTERLACE should be invoked to switch the mode.

This wasn't done correctly in the recently refactored code and could
have broken with --deinterlace. (The refactor only considered switching
via property in this case.) Fix it by making it a proper part of the
filter_reconfig() function, and making set_deinterlacing() (which is
called by the property handler) merely call filter_reconfig() in all
cases to do the real work.

We can even avoid rebuilding the filter chain - though only if no other
auto-filters are inserted. It probably also provides a slightly cleaner
way to implement functionality in the VO while still inserting video
filter fallbacks correctly if required.
This commit is contained in:
wm4 2016-07-06 14:08:47 +02:00
parent 08cd50b84b
commit 771a8bf5c6

View File

@ -162,6 +162,14 @@ static bool check_output_format(struct vo_chain *vo_c, int imgfmt)
static int probe_deint_filters(struct vo_chain *vo_c)
{
// Usually, we prefer inserting/removing deint filters. But If there's VO
// support, or the user inserted a filter that supports swichting deint and
// that has no VF_DEINTERLACE_LABEL, or if the filter was auto-inserted
// for other reasons and supports switching deint (like vf_d3d11vpp), then
// use the runtime switching method.
if (video_vf_vo_control(vo_c, VFCTRL_SET_DEINTERLACE, &(int){1}) == CONTROL_OK)
return 0;
if (check_output_format(vo_c, IMGFMT_VDPAU)) {
char *args[5] = {"deint", "yes"};
int pref = 0;
@ -200,8 +208,13 @@ static void filter_reconfig(struct MPContext *mpctx, struct vo_chain *vo_c)
vf_remove_filter(vo_c->vf, vf);
}
if (vf_reconfig(vo_c->vf, &params) < 0)
return;
if (vo_c->vf->initialized < 1) {
if (vf_reconfig(vo_c->vf, &params) < 0)
return;
}
// Make sure to reset this even if runtime deint switching is used.
video_vf_vo_control(vo_c, VFCTRL_SET_DEINTERLACE, &(int){0});
if (params.rotate && (params.rotate % 90 == 0)) {
if (!(vo_c->vo->driver->caps & VO_CAP_ROTATE90)) {
@ -252,22 +265,11 @@ int get_deinterlacing(struct MPContext *mpctx)
void set_deinterlacing(struct MPContext *mpctx, bool enable)
{
struct vo_chain *vo_c = mpctx->vo_chain;
if (vf_find_by_label(vo_c->vf, VF_DEINTERLACE_LABEL)) {
if (!enable) {
mpctx->opts->deinterlace = 0;
recreate_auto_filters(mpctx);
}
} else {
if ((get_deinterlacing(mpctx) > 0) != enable) {
int arg = enable;
if (video_vf_vo_control(vo_c, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK)
{
mpctx->opts->deinterlace = 1;
recreate_auto_filters(mpctx);
}
}
}
if (enable == (get_deinterlacing(mpctx) > 0))
return;
mpctx->opts->deinterlace = enable;
recreate_auto_filters(mpctx);
mpctx->opts->deinterlace = get_deinterlacing(mpctx) > 0;
}